]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Reject registration of duplicated kfunc
authorSong Chen <chensong_2000@126.com>
Wed, 3 Jun 2026 09:19:10 +0000 (17:19 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 5 Jun 2026 15:05:14 +0000 (08:05 -0700)
Search for duplicated kfunc in btf_vmlinux and btf_modules
before a kernel module attempts to register a kfunc.
If kfunc would shadow existing kfunc then pr_err() and
reject module loading.

Reviewed-by: Yonghong Song <yonghong.song@linux.dev>
Signed-off-by: Song Chen <chensong_2000@126.com>
Link: https://lore.kernel.org/r/20260603091910.7212-1-chensong_2000@126.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/btf.c

index 55aa3ba1b1e054a3947ac91b9193ffe68fb45dd3..ef440227478645522f7ae142813cecfe3b0f3d4c 100644 (file)
@@ -8771,6 +8771,39 @@ static int btf_check_iter_kfuncs(struct btf *btf, const char *func_name,
        return 0;
 }
 
+static int btf_check_kfunc_name(struct btf *btf, const char *func_name, u32 kind)
+{
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+       struct btf_module *btf_mod, *tmp;
+#endif
+       s32 id;
+
+       if (!btf_is_module(btf))
+               return 0;
+
+       id = btf_find_by_name_kind(bpf_get_btf_vmlinux(), func_name, kind);
+       if (id >= 0) {
+               pr_err("kfunc %s (id: %d) is already present in vmlinux.\n",
+                      func_name, id);
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+       guard(mutex)(&btf_module_mutex);
+       list_for_each_entry_safe(btf_mod, tmp, &btf_modules, list) {
+               if (btf_mod->btf == btf)
+                       continue;
+               id = btf_find_by_name_kind(btf_mod->btf, func_name, kind);
+               if (id >= 0) {
+                       pr_err("kfunc %s (id: %d) is already present in module %s.\n",
+                              func_name, id, btf_mod->module->name);
+                       return -EINVAL;
+               }
+       }
+#endif
+       return 0;
+}
+
 static int btf_check_kfunc_protos(struct btf *btf, u32 func_id, u32 func_flags)
 {
        const struct btf_type *func;
@@ -8784,7 +8817,8 @@ static int btf_check_kfunc_protos(struct btf *btf, u32 func_id, u32 func_flags)
 
        /* sanity check kfunc name */
        func_name = btf_name_by_offset(btf, func->name_off);
-       if (!func_name || !func_name[0])
+       if (!func_name || !func_name[0] ||
+           btf_check_kfunc_name(btf, func_name, BTF_INFO_KIND(func->info)))
                return -EINVAL;
 
        func = btf_type_by_id(btf, func->type);