Skip to content

Commit 66967a3

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
bpf: extract bpf_ctx_convert_map logic and make it more reusable
Refactor btf_get_prog_ctx_type() a bit to allow reuse of bpf_ctx_convert_map logic in more than one places. Simplify interface by returning btf_type instead of btf_member (field reference in BTF). To do the above we need to touch and start untangling btf_translate_to_vmlinux() implementation. We do the bare minimum to not regress anything for btf_translate_to_vmlinux(), but its implementation is very questionable for what it claims to be doing. Mapping kfunc argument types to kernel corresponding types conceptually is quite different from recognizing program context types. Fixing this is out of scope for this change though. Signed-off-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 01b55f4 commit 66967a3

File tree

2 files changed

+46
-27
lines changed

2 files changed

+46
-27
lines changed

include/linux/btf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ s32 btf_find_dtor_kfunc(struct btf *btf, u32 btf_id);
512512
int register_btf_id_dtor_kfuncs(const struct btf_id_dtor_kfunc *dtors, u32 add_cnt,
513513
struct module *owner);
514514
struct btf_struct_meta *btf_find_struct_meta(const struct btf *btf, u32 btf_id);
515-
const struct btf_member *
515+
const struct btf_type *
516516
btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
517517
const struct btf_type *t, enum bpf_prog_type prog_type,
518518
int arg);

kernel/bpf/btf.c

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5615,21 +5615,46 @@ static u8 bpf_ctx_convert_map[] = {
56155615
#undef BPF_MAP_TYPE
56165616
#undef BPF_LINK_TYPE
56175617

5618-
const struct btf_member *
5619-
btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
5620-
const struct btf_type *t, enum bpf_prog_type prog_type,
5621-
int arg)
5618+
static const struct btf_type *find_canonical_prog_ctx_type(enum bpf_prog_type prog_type)
56225619
{
56235620
const struct btf_type *conv_struct;
5624-
const struct btf_type *ctx_struct;
56255621
const struct btf_member *ctx_type;
5626-
const char *tname, *ctx_tname;
56275622

56285623
conv_struct = bpf_ctx_convert.t;
5629-
if (!conv_struct) {
5630-
bpf_log(log, "btf_vmlinux is malformed\n");
5624+
if (!conv_struct)
56315625
return NULL;
5632-
}
5626+
/* prog_type is valid bpf program type. No need for bounds check. */
5627+
ctx_type = btf_type_member(conv_struct) + bpf_ctx_convert_map[prog_type] * 2;
5628+
/* ctx_type is a pointer to prog_ctx_type in vmlinux.
5629+
* Like 'struct __sk_buff'
5630+
*/
5631+
return btf_type_by_id(btf_vmlinux, ctx_type->type);
5632+
}
5633+
5634+
static int find_kern_ctx_type_id(enum bpf_prog_type prog_type)
5635+
{
5636+
const struct btf_type *conv_struct;
5637+
const struct btf_member *ctx_type;
5638+
5639+
conv_struct = bpf_ctx_convert.t;
5640+
if (!conv_struct)
5641+
return -EFAULT;
5642+
/* prog_type is valid bpf program type. No need for bounds check. */
5643+
ctx_type = btf_type_member(conv_struct) + bpf_ctx_convert_map[prog_type] * 2 + 1;
5644+
/* ctx_type is a pointer to prog_ctx_type in vmlinux.
5645+
* Like 'struct sk_buff'
5646+
*/
5647+
return ctx_type->type;
5648+
}
5649+
5650+
const struct btf_type *
5651+
btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
5652+
const struct btf_type *t, enum bpf_prog_type prog_type,
5653+
int arg)
5654+
{
5655+
const struct btf_type *ctx_type;
5656+
const char *tname, *ctx_tname;
5657+
56335658
t = btf_type_by_id(btf, t->type);
56345659
while (btf_type_is_modifier(t))
56355660
t = btf_type_by_id(btf, t->type);
@@ -5646,17 +5671,15 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
56465671
bpf_log(log, "arg#%d struct doesn't have a name\n", arg);
56475672
return NULL;
56485673
}
5649-
/* prog_type is valid bpf program type. No need for bounds check. */
5650-
ctx_type = btf_type_member(conv_struct) + bpf_ctx_convert_map[prog_type] * 2;
5651-
/* ctx_struct is a pointer to prog_ctx_type in vmlinux.
5652-
* Like 'struct __sk_buff'
5653-
*/
5654-
ctx_struct = btf_type_by_id(btf_vmlinux, ctx_type->type);
5655-
if (!ctx_struct)
5674+
5675+
ctx_type = find_canonical_prog_ctx_type(prog_type);
5676+
if (!ctx_type) {
5677+
bpf_log(log, "btf_vmlinux is malformed\n");
56565678
/* should not happen */
56575679
return NULL;
5680+
}
56585681
again:
5659-
ctx_tname = btf_name_by_offset(btf_vmlinux, ctx_struct->name_off);
5682+
ctx_tname = btf_name_by_offset(btf_vmlinux, ctx_type->name_off);
56605683
if (!ctx_tname) {
56615684
/* should not happen */
56625685
bpf_log(log, "Please fix kernel include/linux/bpf_types.h\n");
@@ -5677,10 +5700,10 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
56775700
/* bpf_user_pt_regs_t is a typedef, so resolve it to
56785701
* underlying struct and check name again
56795702
*/
5680-
if (!btf_type_is_modifier(ctx_struct))
5703+
if (!btf_type_is_modifier(ctx_type))
56815704
return NULL;
5682-
while (btf_type_is_modifier(ctx_struct))
5683-
ctx_struct = btf_type_by_id(btf_vmlinux, ctx_struct->type);
5705+
while (btf_type_is_modifier(ctx_type))
5706+
ctx_type = btf_type_by_id(btf_vmlinux, ctx_type->type);
56845707
goto again;
56855708
}
56865709
return ctx_type;
@@ -5692,13 +5715,9 @@ static int btf_translate_to_vmlinux(struct bpf_verifier_log *log,
56925715
enum bpf_prog_type prog_type,
56935716
int arg)
56945717
{
5695-
const struct btf_member *prog_ctx_type, *kern_ctx_type;
5696-
5697-
prog_ctx_type = btf_get_prog_ctx_type(log, btf, t, prog_type, arg);
5698-
if (!prog_ctx_type)
5718+
if (!btf_get_prog_ctx_type(log, btf, t, prog_type, arg))
56995719
return -ENOENT;
5700-
kern_ctx_type = prog_ctx_type + 1;
5701-
return kern_ctx_type->type;
5720+
return find_kern_ctx_type_id(prog_type);
57025721
}
57035722

57045723
int get_kern_ctx_btf_id(struct bpf_verifier_log *log, enum bpf_prog_type prog_type)

0 commit comments

Comments
 (0)