]> Git Repo - linux.git/commitdiff
libbpf: Find correct module BTFs for struct_ops maps and progs.
authorKui-Feng Lee <[email protected]>
Fri, 19 Jan 2024 22:50:03 +0000 (14:50 -0800)
committerMartin KaFai Lau <[email protected]>
Wed, 24 Jan 2024 01:12:52 +0000 (17:12 -0800)
Locate the module BTFs for struct_ops maps and progs and pass them to the
kernel. This ensures that the kernel correctly resolves type IDs from the
appropriate module BTFs.

For the map of a struct_ops object, the FD of the module BTF is set to
bpf_map to keep a reference to the module BTF. The FD is passed to the
kernel as value_type_btf_obj_fd when the struct_ops object is loaded.

For a bpf_struct_ops prog, attach_btf_obj_fd of bpf_prog is the FD of a
module BTF in the kernel.

Signed-off-by: Kui-Feng Lee <[email protected]>
Acked-by: Andrii Nakryiko <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Martin KaFai Lau <[email protected]>
tools/lib/bpf/bpf.c
tools/lib/bpf/bpf.h
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf_probes.c

index 9dc9625651dcff13699d1961b7a7c31fffd3bbd2..3a35472a17c5ea3941e114179edf613be39649ed 100644 (file)
@@ -169,7 +169,8 @@ int bpf_map_create(enum bpf_map_type map_type,
                   __u32 max_entries,
                   const struct bpf_map_create_opts *opts)
 {
-       const size_t attr_sz = offsetofend(union bpf_attr, map_extra);
+       const size_t attr_sz = offsetofend(union bpf_attr,
+                                          value_type_btf_obj_fd);
        union bpf_attr attr;
        int fd;
 
@@ -191,6 +192,7 @@ int bpf_map_create(enum bpf_map_type map_type,
        attr.btf_key_type_id = OPTS_GET(opts, btf_key_type_id, 0);
        attr.btf_value_type_id = OPTS_GET(opts, btf_value_type_id, 0);
        attr.btf_vmlinux_value_type_id = OPTS_GET(opts, btf_vmlinux_value_type_id, 0);
+       attr.value_type_btf_obj_fd = OPTS_GET(opts, value_type_btf_obj_fd, -1);
 
        attr.inner_map_fd = OPTS_GET(opts, inner_map_fd, 0);
        attr.map_flags = OPTS_GET(opts, map_flags, 0);
index d0f53772bdc02ace4e062aadb8907e73665f543d..53b0bee053ad21e58e16b3e5c5cc0ab4140b3daa 100644 (file)
@@ -51,8 +51,10 @@ struct bpf_map_create_opts {
 
        __u32 numa_node;
        __u32 map_ifindex;
+       __s32 value_type_btf_obj_fd;
+       size_t:0;
 };
-#define bpf_map_create_opts__last_field map_ifindex
+#define bpf_map_create_opts__last_field value_type_btf_obj_fd
 
 LIBBPF_API int bpf_map_create(enum bpf_map_type map_type,
                              const char *map_name,
index b8b00da6290714e51a5ebaa35bde8fe6580a5849..0569b4973a4f471f6e6e3d63371812a7f3a447c5 100644 (file)
@@ -528,6 +528,7 @@ struct bpf_map {
        struct bpf_map_def def;
        __u32 numa_node;
        __u32 btf_var_idx;
+       int mod_btf_fd;
        __u32 btf_key_type_id;
        __u32 btf_value_type_id;
        __u32 btf_vmlinux_value_type_id;
@@ -931,22 +932,29 @@ find_member_by_name(const struct btf *btf, const struct btf_type *t,
        return NULL;
 }
 
+static int find_ksym_btf_id(struct bpf_object *obj, const char *ksym_name,
+                           __u16 kind, struct btf **res_btf,
+                           struct module_btf **res_mod_btf);
+
 #define STRUCT_OPS_VALUE_PREFIX "bpf_struct_ops_"
 static int find_btf_by_prefix_kind(const struct btf *btf, const char *prefix,
                                   const char *name, __u32 kind);
 
 static int
-find_struct_ops_kern_types(const struct btf *btf, const char *tname,
+find_struct_ops_kern_types(struct bpf_object *obj, const char *tname,
+                          struct module_btf **mod_btf,
                           const struct btf_type **type, __u32 *type_id,
                           const struct btf_type **vtype, __u32 *vtype_id,
                           const struct btf_member **data_member)
 {
        const struct btf_type *kern_type, *kern_vtype;
        const struct btf_member *kern_data_member;
+       struct btf *btf;
        __s32 kern_vtype_id, kern_type_id;
        __u32 i;
 
-       kern_type_id = btf__find_by_name_kind(btf, tname, BTF_KIND_STRUCT);
+       kern_type_id = find_ksym_btf_id(obj, tname, BTF_KIND_STRUCT,
+                                       &btf, mod_btf);
        if (kern_type_id < 0) {
                pr_warn("struct_ops init_kern: struct %s is not found in kernel BTF\n",
                        tname);
@@ -1000,14 +1008,16 @@ static bool bpf_map__is_struct_ops(const struct bpf_map *map)
 }
 
 /* Init the map's fields that depend on kern_btf */
-static int bpf_map__init_kern_struct_ops(struct bpf_map *map,
-                                        const struct btf *btf,
-                                        const struct btf *kern_btf)
+static int bpf_map__init_kern_struct_ops(struct bpf_map *map)
 {
        const struct btf_member *member, *kern_member, *kern_data_member;
        const struct btf_type *type, *kern_type, *kern_vtype;
        __u32 i, kern_type_id, kern_vtype_id, kern_data_off;
+       struct bpf_object *obj = map->obj;
+       const struct btf *btf = obj->btf;
        struct bpf_struct_ops *st_ops;
+       const struct btf *kern_btf;
+       struct module_btf *mod_btf;
        void *data, *kern_data;
        const char *tname;
        int err;
@@ -1015,16 +1025,19 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map,
        st_ops = map->st_ops;
        type = st_ops->type;
        tname = st_ops->tname;
-       err = find_struct_ops_kern_types(kern_btf, tname,
+       err = find_struct_ops_kern_types(obj, tname, &mod_btf,
                                         &kern_type, &kern_type_id,
                                         &kern_vtype, &kern_vtype_id,
                                         &kern_data_member);
        if (err)
                return err;
 
+       kern_btf = mod_btf ? mod_btf->btf : obj->btf_vmlinux;
+
        pr_debug("struct_ops init_kern %s: type_id:%u kern_type_id:%u kern_vtype_id:%u\n",
                 map->name, st_ops->type_id, kern_type_id, kern_vtype_id);
 
+       map->mod_btf_fd = mod_btf ? mod_btf->fd : -1;
        map->def.value_size = kern_vtype->size;
        map->btf_vmlinux_value_type_id = kern_vtype_id;
 
@@ -1100,6 +1113,8 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map,
                                return -ENOTSUP;
                        }
 
+                       if (mod_btf)
+                               prog->attach_btf_obj_fd = mod_btf->fd;
                        prog->attach_btf_id = kern_type_id;
                        prog->expected_attach_type = kern_member_idx;
 
@@ -1142,8 +1157,7 @@ static int bpf_object__init_kern_struct_ops_maps(struct bpf_object *obj)
                if (!bpf_map__is_struct_ops(map))
                        continue;
 
-               err = bpf_map__init_kern_struct_ops(map, obj->btf,
-                                                   obj->btf_vmlinux);
+               err = bpf_map__init_kern_struct_ops(map);
                if (err)
                        return err;
        }
@@ -5162,8 +5176,13 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b
        create_attr.numa_node = map->numa_node;
        create_attr.map_extra = map->map_extra;
 
-       if (bpf_map__is_struct_ops(map))
+       if (bpf_map__is_struct_ops(map)) {
                create_attr.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id;
+               if (map->mod_btf_fd >= 0) {
+                       create_attr.value_type_btf_obj_fd = map->mod_btf_fd;
+                       create_attr.map_flags |= BPF_F_VTYPE_BTF_OBJ_FD;
+               }
+       }
 
        if (obj->btf && btf__fd(obj->btf) >= 0) {
                create_attr.btf_fd = btf__fd(obj->btf);
@@ -9970,7 +9989,9 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog, const char *attac
                *btf_obj_fd = 0;
                *btf_type_id = 1;
        } else {
-               err = find_kernel_btf_id(prog->obj, attach_name, attach_type, btf_obj_fd, btf_type_id);
+               err = find_kernel_btf_id(prog->obj, attach_name,
+                                        attach_type, btf_obj_fd,
+                                        btf_type_id);
        }
        if (err) {
                pr_warn("prog '%s': failed to find kernel BTF type ID of '%s': %d\n",
index 9c4db90b92b6b55bb143d80c308085003becc20b..98373d126d9d77a7313c452c20f1a95974248b9d 100644 (file)
@@ -326,6 +326,7 @@ static int probe_map_create(enum bpf_map_type map_type)
        case BPF_MAP_TYPE_STRUCT_OPS:
                /* we'll get -ENOTSUPP for invalid BTF type ID for struct_ops */
                opts.btf_vmlinux_value_type_id = 1;
+               opts.value_type_btf_obj_fd = -1;
                exp_err = -524; /* -ENOTSUPP */
                break;
        case BPF_MAP_TYPE_BLOOM_FILTER:
This page took 0.082817 seconds and 4 git commands to generate.