Split __register_btf_kfunc_id_set(), register_btf_id_dtor_kfuncs() and
__register_bpf_struct_ops() into the part that looks up the BTF for the
owner and the part that adds the registration to a given BTF:
btf_kfunc_id_set_add(), btf_dtor_kfuncs_add() and btf_struct_ops_add().

In is_valid_value_type(), look up bpf_struct_ops_common_value in the btf
the function was given rather than in the btf_vmlinux global.  The id is
a vmlinux id and a module BTF resolves it through its base, so the result
is the same; the function already uses the passed btf for every other
lookup.

No functional change.  With CONFIG_DEBUG_INFO_BTF=m, registrations made
from initcalls before the vmlinux BTF is available are queued and applied
later by the BTF parsing code, which needs the add-to-this-btf half on
its own; the struct_ops ones are applied before the parsed vmlinux BTF is
published, i.e. while btf_vmlinux is still NULL.

Signed-off-by: Jay Wang <[email protected]>
---
 kernel/bpf/bpf_struct_ops.c |  3 +-
 kernel/bpf/btf.c            | 91 ++++++++++++++++++++++---------------
 2 files changed, 57 insertions(+), 37 deletions(-)

diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c
index 1178acd72296..bf3004908d15 100644
--- a/kernel/bpf/bpf_struct_ops.c
+++ b/kernel/bpf/bpf_struct_ops.c
@@ -103,7 +103,8 @@ static bool is_valid_value_type(struct btf *btf, s32 
value_id,
        }
        member = btf_type_member(vt);
        mt = btf_type_by_id(btf, member->type);
-       common_value_type = btf_type_by_id(btf_vmlinux,
+       /* a vmlinux id resolves through the base BTF of a module BTF too */
+       common_value_type = btf_type_by_id(btf,
                                           
st_ops_ids[IDX_ST_OPS_COMMON_VALUE_ID]);
        if (mt != common_value_type) {
                pr_warn("The first member of %s should be 
bpf_struct_ops_common_value\n",
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index a6634237dc89..c3c1421208b4 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -9313,11 +9313,26 @@ u32 *btf_kfunc_is_modify_return(const struct btf *btf, 
u32 kfunc_btf_id,
        return btf_kfunc_id_set_contains(btf, BTF_KFUNC_HOOK_FMODRET, 
kfunc_btf_id);
 }
 
+static int btf_kfunc_id_set_add(struct btf *btf, enum btf_kfunc_hook hook,
+                               const struct btf_kfunc_id_set *kset)
+{
+       int ret, i;
+
+       for (i = 0; i < kset->set->cnt; i++) {
+               ret = btf_check_kfunc_protos(btf, btf_relocate_id(btf, 
kset->set->pairs[i].id),
+                                            kset->set->pairs[i].flags);
+               if (ret)
+                       return ret;
+       }
+
+       return btf_populate_kfunc_set(btf, hook, kset);
+}
+
 static int __register_btf_kfunc_id_set(enum btf_kfunc_hook hook,
                                       const struct btf_kfunc_id_set *kset)
 {
        struct btf *btf;
-       int ret, i;
+       int ret;
 
        btf = btf_get_module_btf(kset->owner);
        if (!btf)
@@ -9325,16 +9340,7 @@ static int __register_btf_kfunc_id_set(enum 
btf_kfunc_hook hook,
        if (IS_ERR(btf))
                return PTR_ERR(btf);
 
-       for (i = 0; i < kset->set->cnt; i++) {
-               ret = btf_check_kfunc_protos(btf, btf_relocate_id(btf, 
kset->set->pairs[i].id),
-                                            kset->set->pairs[i].flags);
-               if (ret)
-                       goto err_out;
-       }
-
-       ret = btf_populate_kfunc_set(btf, hook, kset);
-
-err_out:
+       ret = btf_kfunc_id_set_add(btf, hook, kset);
        btf_put(btf);
        return ret;
 }
@@ -9426,21 +9432,13 @@ static int btf_check_dtor_kfuncs(struct btf *btf, const 
struct btf_id_dtor_kfunc
        return 0;
 }
 
-/* This function must be invoked only from initcalls/module init functions */
-int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors, u32 
add_cnt,
-                               struct module *owner)
+static int btf_dtor_kfuncs_add(struct btf *btf, const struct btf_id_dtor_kfunc 
*dtors,
+                              u32 add_cnt)
 {
        struct btf_id_dtor_kfunc_tab *tab;
-       struct btf *btf;
        u32 tab_cnt, i;
        int ret;
 
-       btf = btf_get_module_btf(owner);
-       if (!btf)
-               return check_btf_kconfigs(owner, "dtor kfuncs");
-       if (IS_ERR(btf))
-               return PTR_ERR(btf);
-
        if (add_cnt >= BTF_DTOR_KFUNC_MAX_CNT) {
                pr_err("cannot register more than %d kfunc destructors\n", 
BTF_DTOR_KFUNC_MAX_CNT);
                ret = -E2BIG;
@@ -9497,6 +9495,23 @@ int register_btf_id_dtor_kfuncs(const struct 
btf_id_dtor_kfunc *dtors, u32 add_c
 end:
        if (ret)
                btf_free_dtor_kfunc_tab(btf);
+       return ret;
+}
+
+/* This function must be invoked only from initcalls/module init functions */
+int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors, u32 
add_cnt,
+                               struct module *owner)
+{
+       struct btf *btf;
+       int ret;
+
+       btf = btf_get_module_btf(owner);
+       if (!btf)
+               return check_btf_kconfigs(owner, "dtor kfuncs");
+       if (IS_ERR(btf))
+               return PTR_ERR(btf);
+
+       ret = btf_dtor_kfuncs_add(btf, dtors, add_cnt);
        btf_put(btf);
        return ret;
 }
@@ -10135,32 +10150,36 @@ bpf_struct_ops_find(struct btf *btf, u32 type_id)
        return NULL;
 }
 
-int __register_bpf_struct_ops(struct bpf_struct_ops *st_ops)
+static int btf_struct_ops_add(struct btf *btf, struct bpf_struct_ops *st_ops)
 {
        struct bpf_verifier_log *log;
-       struct btf *btf;
-       int err = 0;
-
-       btf = btf_get_module_btf(st_ops->owner);
-       if (!btf)
-               return check_btf_kconfigs(st_ops->owner, "struct_ops");
-       if (IS_ERR(btf))
-               return PTR_ERR(btf);
+       int err;
 
        log = kzalloc_obj(*log, GFP_KERNEL | __GFP_NOWARN);
-       if (!log) {
-               err = -ENOMEM;
-               goto errout;
-       }
+       if (!log)
+               return -ENOMEM;
 
        log->level = BPF_LOG_KERNEL;
 
        err = btf_add_struct_ops(btf, st_ops, log);
 
-errout:
        kfree(log);
-       btf_put(btf);
+       return err;
+}
 
+int __register_bpf_struct_ops(struct bpf_struct_ops *st_ops)
+{
+       struct btf *btf;
+       int err;
+
+       btf = btf_get_module_btf(st_ops->owner);
+       if (!btf)
+               return check_btf_kconfigs(st_ops->owner, "struct_ops");
+       if (IS_ERR(btf))
+               return PTR_ERR(btf);
+
+       err = btf_struct_ops_add(btf, st_ops);
+       btf_put(btf);
        return err;
 }
 EXPORT_SYMBOL_GPL(__register_bpf_struct_ops);
-- 
2.47.3


Reply via email to