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

From: Song Chen

Date: Sun May 17 2026 - 02:35:42 EST


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.

/Song


If this is not intended, then we may need a mechanism to reject
overriding an already-overridden kfunc unless the caller explicitly
requests a forced replacement.

All that only for bpf progs that are loaded after override.
Already loaded progs don't need to be live patched.
Thoughts?