diff options
| author | Kumar Kartikeya Dwivedi <memxor@gmail.com> | 2026-06-09 18:39:46 +0300 |
|---|---|---|
| committer | Kumar Kartikeya Dwivedi <memxor@gmail.com> | 2026-06-09 18:39:47 +0300 |
| commit | f1a660bbd12dd855fce6cf13f144008c4e45e7c7 (patch) | |
| tree | 2a62aaa899e85eae3f0d567e73ed73ceee025105 | |
| parent | dd0f9684d2f7d3f99aee63f5fa80562f2207b964 (diff) | |
| parent | af8c3f170f7314d316023efc0ae670384e220b09 (diff) | |
| download | linux-f1a660bbd12dd855fce6cf13f144008c4e45e7c7.tar.xz | |
Merge branch 'bpf-enforce-btf-pointer-write-checks-for-global-args'
Nuoqi Gui says:
====================
bpf: Enforce BTF pointer write checks for global args
check_mem_reg() verifies both read and write access when a caller passes
memory into a global subprogram. For PTR_TO_BTF_ID callers,
check_helper_mem_access() currently always checks the access as BPF_READ.
That lets a tracing program pass a task_struct field pointer to a global
subprogram argument typed as writable memory. The direct field store is rejected
with "only read is supported", but the callee is validated with a generic
writable PTR_TO_MEM argument and can store through it.
Forward the requested access type into the PTR_TO_BTF_ID helper-access path and
add verifier coverage for the global-subprogram argument case.
Validation (tested on bpf-next 8496d9020ff3):
Without this series:
direct BTF field store rejected with "only read is supported";
global-subprogram candidate loaded, attached, and runtime-confirmed.
With this series applied:
direct BTF field store rejected with "only read is supported";
global-subprogram candidate rejected with "only read is supported".
Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
---
====================
Link: https://patch.msgid.link/20260609-f01-04-btf-writable-arg-v1-0-f449cd970669@mails.tsinghua.edu.cn
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
| -rw-r--r-- | kernel/bpf/verifier.c | 2 | ||||
| -rw-r--r-- | tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c | 19 |
2 files changed, 20 insertions, 1 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index ed7ba0e6a9ce..cdff3e6eb96e 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -6777,7 +6777,7 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, struct bpf_reg_ zero_size_allowed, access_type, meta); case PTR_TO_BTF_ID: return check_ptr_to_btf_access(env, regs, reg, argno, 0, - access_size, BPF_READ, -1); + access_size, access_type, -1); case PTR_TO_CTX: /* Only permit reading or writing syscall context using helper calls. */ if (is_var_ctx_off_allowed(env->prog)) { diff --git a/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c b/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c index ea273e152209..0bdeb7bc4687 100644 --- a/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c +++ b/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c @@ -287,6 +287,25 @@ int trusted_to_untrusted_mem(void *ctx) return subprog_void_untrusted(bpf_get_current_task_btf()); } +__weak int subprog_write_mem_arg(int *p) +{ + if (!p) + return 0; + + *p = 42; + return 0; +} + +SEC("?tp_btf/task_newtask") +__failure +__msg("only read is supported") +int trusted_btf_field_to_writable_mem(void *ctx) +{ + struct task_struct *task = bpf_get_current_task_btf(); + + return subprog_write_mem_arg(&task->prio); +} + SEC("tp_btf/sys_enter") __success int anything_to_untrusted_mem(void *ctx) |
