summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKumar Kartikeya Dwivedi <memxor@gmail.com>2026-06-09 18:39:46 +0300
committerKumar Kartikeya Dwivedi <memxor@gmail.com>2026-06-09 18:39:47 +0300
commitf1a660bbd12dd855fce6cf13f144008c4e45e7c7 (patch)
tree2a62aaa899e85eae3f0d567e73ed73ceee025105
parentdd0f9684d2f7d3f99aee63f5fa80562f2207b964 (diff)
parentaf8c3f170f7314d316023efc0ae670384e220b09 (diff)
downloadlinux-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.c2
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c19
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)