Skip to content

Commit d9ab2f7

Browse files
eddyz87anakryiko
authored andcommitted
libbpf: Tie struct_ops programs to kernel BTF ids, not to local ids
Enforce the following existing limitation on struct_ops programs based on kernel BTF id instead of program-local BTF id: struct_ops BPF prog can be re-used between multiple .struct_ops & .struct_ops.link as long as it's the same struct_ops struct definition and the same function pointer field This allows reusing same BPF program for versioned struct_ops map definitions, e.g.: SEC("struct_ops/test") int BPF_PROG(foo) { ... } struct some_ops___v1 { int (*test)(void); }; struct some_ops___v2 { int (*test)(void); }; SEC(".struct_ops.link") struct some_ops___v1 a = { .test = foo } SEC(".struct_ops.link") struct some_ops___v2 b = { .test = foo } Signed-off-by: Eduard Zingerman <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent a2a5172 commit d9ab2f7

File tree

1 file changed

+26
-23
lines changed

1 file changed

+26
-23
lines changed

tools/lib/bpf/libbpf.c

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,8 +1146,32 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map)
11461146

11471147
if (mod_btf)
11481148
prog->attach_btf_obj_fd = mod_btf->fd;
1149-
prog->attach_btf_id = kern_type_id;
1150-
prog->expected_attach_type = kern_member_idx;
1149+
1150+
/* if we haven't yet processed this BPF program, record proper
1151+
* attach_btf_id and member_idx
1152+
*/
1153+
if (!prog->attach_btf_id) {
1154+
prog->attach_btf_id = kern_type_id;
1155+
prog->expected_attach_type = kern_member_idx;
1156+
}
1157+
1158+
/* struct_ops BPF prog can be re-used between multiple
1159+
* .struct_ops & .struct_ops.link as long as it's the
1160+
* same struct_ops struct definition and the same
1161+
* function pointer field
1162+
*/
1163+
if (prog->attach_btf_id != kern_type_id) {
1164+
pr_warn("struct_ops init_kern %s func ptr %s: invalid reuse of prog %s in sec %s with type %u: attach_btf_id %u != kern_type_id %u\n",
1165+
map->name, mname, prog->name, prog->sec_name, prog->type,
1166+
prog->attach_btf_id, kern_type_id);
1167+
return -EINVAL;
1168+
}
1169+
if (prog->expected_attach_type != kern_member_idx) {
1170+
pr_warn("struct_ops init_kern %s func ptr %s: invalid reuse of prog %s in sec %s with type %u: expected_attach_type %u != kern_member_idx %u\n",
1171+
map->name, mname, prog->name, prog->sec_name, prog->type,
1172+
prog->expected_attach_type, kern_member_idx);
1173+
return -EINVAL;
1174+
}
11511175

11521176
st_ops->kern_func_off[i] = kern_data_off + kern_moff;
11531177

@@ -9428,27 +9452,6 @@ static int bpf_object__collect_st_ops_relos(struct bpf_object *obj,
94289452
return -EINVAL;
94299453
}
94309454

9431-
/* if we haven't yet processed this BPF program, record proper
9432-
* attach_btf_id and member_idx
9433-
*/
9434-
if (!prog->attach_btf_id) {
9435-
prog->attach_btf_id = st_ops->type_id;
9436-
prog->expected_attach_type = member_idx;
9437-
}
9438-
9439-
/* struct_ops BPF prog can be re-used between multiple
9440-
* .struct_ops & .struct_ops.link as long as it's the
9441-
* same struct_ops struct definition and the same
9442-
* function pointer field
9443-
*/
9444-
if (prog->attach_btf_id != st_ops->type_id ||
9445-
prog->expected_attach_type != member_idx) {
9446-
pr_warn("struct_ops reloc %s: cannot use prog %s in sec %s with type %u attach_btf_id %u expected_attach_type %u for func ptr %s\n",
9447-
map->name, prog->name, prog->sec_name, prog->type,
9448-
prog->attach_btf_id, prog->expected_attach_type, name);
9449-
return -EINVAL;
9450-
}
9451-
94529455
st_ops->progs[member_idx] = prog;
94539456

94549457
/* st_ops->data will be exposed to users, being returned by

0 commit comments

Comments
 (0)