Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Fix global subprog context argument resolution logic

KPROBE program's user-facing context type is defined as typedef
bpf_user_pt_regs_t. This leads to a problem when trying to passing
kprobe/uprobe/usdt context argument into global subprog, as kernel
always strip away mods and typedefs of user-supplied type, but takes
expected type from bpf_ctx_convert as is, which causes mismatch.

Current way to work around this is to define a fake struct with the same
name as expected typedef:

struct bpf_user_pt_regs_t {};

__noinline my_global_subprog(struct bpf_user_pt_regs_t *ctx) { ... }

This patch fixes the issue by resolving expected type, if it's not
a struct. It still leaves the above work-around working for backwards
compatibility.

Fixes: 91cc1a99740e ("bpf: Annotate context types")
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Stanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/bpf/20230216045954.3002473-2-andrii@kernel.org

authored by

Andrii Nakryiko and committed by
Daniel Borkmann
d384dce2 64f50f65

+11 -2
+11 -2
kernel/bpf/btf.c
··· 5669 5669 if (!ctx_struct) 5670 5670 /* should not happen */ 5671 5671 return NULL; 5672 + again: 5672 5673 ctx_tname = btf_name_by_offset(btf_vmlinux, ctx_struct->name_off); 5673 5674 if (!ctx_tname) { 5674 5675 /* should not happen */ ··· 5683 5682 * int socket_filter_bpf_prog(struct __sk_buff *skb) 5684 5683 * { // no fields of skb are ever used } 5685 5684 */ 5686 - if (strcmp(ctx_tname, tname)) 5687 - return NULL; 5685 + if (strcmp(ctx_tname, tname)) { 5686 + /* bpf_user_pt_regs_t is a typedef, so resolve it to 5687 + * underlying struct and check name again 5688 + */ 5689 + if (!btf_type_is_modifier(ctx_struct)) 5690 + return NULL; 5691 + while (btf_type_is_modifier(ctx_struct)) 5692 + ctx_struct = btf_type_by_id(btf_vmlinux, ctx_struct->type); 5693 + goto again; 5694 + } 5688 5695 return ctx_type; 5689 5696 } 5690 5697