Skip to content

Commit bb1cc7f

Browse files
anakryikogregkh
authored andcommitted
bpf: Fix global subprog context argument resolution logic
[ Upstream commit d384dce ] 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: 91cc1a9 ("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 Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 30651cf commit bb1cc7f

1 file changed

Lines changed: 11 additions & 2 deletions

File tree

kernel/bpf/btf.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5131,6 +5131,7 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
51315131
if (!ctx_struct)
51325132
/* should not happen */
51335133
return NULL;
5134+
again:
51345135
ctx_tname = btf_name_by_offset(btf_vmlinux, ctx_struct->name_off);
51355136
if (!ctx_tname) {
51365137
/* should not happen */
@@ -5144,8 +5145,16 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, const struct btf *btf,
51445145
* int socket_filter_bpf_prog(struct __sk_buff *skb)
51455146
* { // no fields of skb are ever used }
51465147
*/
5147-
if (strcmp(ctx_tname, tname))
5148-
return NULL;
5148+
if (strcmp(ctx_tname, tname)) {
5149+
/* bpf_user_pt_regs_t is a typedef, so resolve it to
5150+
* underlying struct and check name again
5151+
*/
5152+
if (!btf_type_is_modifier(ctx_struct))
5153+
return NULL;
5154+
while (btf_type_is_modifier(ctx_struct))
5155+
ctx_struct = btf_type_by_id(btf_vmlinux, ctx_struct->type);
5156+
goto again;
5157+
}
51495158
return ctx_type;
51505159
}
51515160

0 commit comments

Comments
 (0)