bpf: don't infer PTR_TO_CTX for programs with unnamed context type

For program types that don't have named context type name (e.g., BPF
iterator programs or tracepoint programs), ctx_tname will be a non-NULL
empty string. For such programs it shouldn't be possible to have
PTR_TO_CTX argument for global subprogs based on type name alone.
arg:ctx tag is the only way to have PTR_TO_CTX passed into global
subprog for such program types.

Fix this loophole, which currently would assume PTR_TO_CTX whenever
user uses a pointer to anonymous struct as an argument to their global
subprogs. This happens in practice with the following (quite common, in
practice) approach:

typedef struct { /* anonymous */
    int x;
} my_type_t;

int my_subprog(my_type_t *arg) { ... }

User's intent is to have PTR_TO_MEM argument for `arg`, but verifier
will complain about expecting PTR_TO_CTX.

This fix also closes unintended s390x-specific KPROBE handling of
PTR_TO_CTX case. Selftest change is necessary to accommodate this.

Fixes: 91cc1a9974 ("bpf: Annotate context types")
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20240212233221.2575350-4-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Andrii Nakryiko 2024-02-12 15:32:20 -08:00 committed by Alexei Starovoitov
parent 824c58fb10
commit 879bbe7aa4
2 changed files with 22 additions and 0 deletions

View File

@ -5746,6 +5746,9 @@ again:
bpf_log(log, "Please fix kernel include/linux/bpf_types.h\n");
return false;
}
/* program types without named context types work only with arg:ctx tag */
if (ctx_tname[0] == '\0')
return false;
/* only compare that prog's ctx type name is the same as
* kernel expects. No need to compare field by field.
* It's ok for bpf prog to do:

View File

@ -26,6 +26,23 @@ int kprobe_typedef_ctx(void *ctx)
return kprobe_typedef_ctx_subprog(ctx);
}
/* s390x defines:
*
* typedef user_pt_regs bpf_user_pt_regs_t;
* typedef struct { ... } user_pt_regs;
*
* And so "canonical" underlying struct type is anonymous.
* So on s390x only valid ways to have PTR_TO_CTX argument in global subprogs
* are:
* - bpf_user_pt_regs_t *ctx (typedef);
* - struct bpf_user_pt_regs_t *ctx (backwards compatible struct hack);
* - void *ctx __arg_ctx (arg:ctx tag)
*
* Other architectures also allow using underlying struct types (e.g.,
* `struct pt_regs *ctx` for x86-64)
*/
#ifndef bpf_target_s390
#define pt_regs_struct_t typeof(*(__PT_REGS_CAST((struct pt_regs *)NULL)))
__weak int kprobe_struct_ctx_subprog(pt_regs_struct_t *ctx)
@ -40,6 +57,8 @@ int kprobe_resolved_ctx(void *ctx)
return kprobe_struct_ctx_subprog(ctx);
}
#endif
/* this is current hack to make this work on old kernels */
struct bpf_user_pt_regs_t {};