Re: [PATCH V2 1/2] tools/lib/bpf/libbpf: Prioritize module kfuncs over vmlinux kfuncs

From: Alexei Starovoitov

Date: Sun May 17 2026 - 10:59:32 EST


On Sat, May 16, 2026 at 11:32 PM Song Chen <chensong_2000@xxxxxxx> wrote:
>
> Hi,
>
> On 5/14/26 21:29, Kaitao Cheng wrote:
> >
> >
> > 在 2026/5/13 05:41, Alexei Starovoitov 写道:
> >> On Mon, May 11, 2026 at 8:19 PM Kaitao Cheng <kaitao.cheng@xxxxxxxxx> wrote:
> >>>
> >>> It seems that there are two problems to solve here:
> >>>
> >>> 1. Allowing kernel modules to override vmlinux kfuncs with the same
> >>> name.
> >>>
> >>> This should be relatively straightforward to implement by matching
> >>> names in kernel modules first, and then falling back to vmlinux.
> >>>
> >>> 2. Handling the case where different kernel modules have kfuncs with
> >>> the same name.
> >>>
> >>> Could we use a new libbpf API to establish the mapping manually?
> >>> for example:
> >>> bpf_object__set_ksym_btf(obj, "kfunc_name", "module_name")
> >>>
> >>> Or define a new attribute, for example:
> >>> extern void kfunc_name(void) __ksym __module("module_name");
> >>>
> >>> We probably need to hear suggestions from other developers on this.
> >>
> >> I'm not excited about 2.
> >> Two different modules are not allowed to have two different functions
> >> with the same name.
> >> The kernel has only one global namespace.
> >> Hence I don't think we should be introducing such namespacing concept
> >> into kfuncs.
> >>
> >> But 1, I feel, is useful for experiments and mitigations,
> >> but it probably should be done transparently to libbpf.
> >>
> >> register_btf_kfunc_id_set() should be changed to return an error
> >> when a module attempts to register a kfunc with a name that already
> >> exists in the kernel.
> >> We also introduce override_btf_kfunc_set() that would register
> >> a replacement kfunc.
> >> override_btf_kfunc_set() would check that all overriding kfuncs
> >> have the exact same kfunc already in vmlinux BTF: proto and name should match.
> >> Then the kernel will just remember that the address of that kfunc
> >> is in the module.
> >> libbpf doesn't need to be aware of this substitution.
> >> It will find kfunc in the vmlinux BTF, but the verifier will supply
> >> implementation from the module to bpf prog.
> >> 2nd module should be able to override_btf_kfunc_set() from vmlinux
> >> and from 1st module that replaced some kfuncs.
> >
> > If multiple modules are allowed to call override_btf_kfunc_id_set()
> > for the same vmlinux kfunc, the effective implementation becomes
> > dependent on module load order.
> >
> > For example, module A overrides a vmlinux kfunc and an A BPF program
> > is written with the expectation that this kfunc resolves to module A's
> > implementation. Later, developer B loads module B, which overrides the
> > same kfunc so that B's BPF program can work. If developer A then reloads
> > or reruns the A BPF program without knowing about module B's override,
> > the same kfunc may now resolve to module B's implementation. This can
> > make the behavior hard to debug and increase the maintenance cost of the
> > system.
> >
> > If this is the intended semantics, I think override_btf_kfunc_id_set()
> > should have clear comments documenting that later overrides replace
> > earlier ones for future BPF program loads. It may also be useful to
> > expose some debugging visibility, e.g. through verifier logs, debugfs,
> > or bpftool, so users can tell whether a given kfunc currently resolves
> > to vmlinux or to a specific module.
>
> I agree with you. I have already had a solution for this proposal:
> define a new attribute, for example:
> extern void kfunc_name(void) __ksym __module("module_name");
>
> 1) introduce a tag in bpf_helpers.h
> #define __kmod(name) __attribute__((btf_decl_tag("kmod:" name)))
>
> 2) add module_name in struct extern_desc
> struct extern_desc {
> enum extern_type type;
> ....
> const char *module_name;
> } ksym;
> 3) read tag in bpf_object__collect_externs:
> tag = btf__name_by_offset(btf, t->name_off);
> ext->ksym.module_name = tag + strlen("kmod:");
> 4) search kfunc in modules in find_ksym_btf_id if ext->ksym.module_name
> is valid, otherwise, search it in vmlinux.
>
> This proposal solves the kfunc priority gracefully, if ebpf program
> declares the kfunc module explicitly like this:
>
> extern int foo(const char *str, const char *substr) __ksym __kmod("hello");
>
> then use foo in module hello, if no __kmod after declaration,
> ext->ksym.module_name is NULL, the behavior of find_ksym_btf_id remains
> same, no impact to its original logic.

I don't like it for the same reasons as before.
This is a half measure of namespaces.
If override is not clear win, let's do error during kmod load
on conflicting kfunc name for now.