* [PATCH bpf v3 0/2] bpf: Reject bare pointer for __arg_trusted arg
@ 2026-10-06 16:06 Yiyang Chen
2026-10-06 16:06 ` [PATCH bpf v3 1/2] " Yiyang Chen
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Yiyang Chen @ 2026-10-06 16:06 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest, Amery Hung, Yiyang Chen
A global subprogram parameter tagged __arg_trusted is verified as holding a
PTR_TRUSTED pointer, but its call-site type check also accepts bare
PTR_TO_BTF_ID. This lets a caller pass a pointer without lifetime protection
to code verified for raw trusted-pointer accesses.
Reject the bare pointer while preserving referenced, trusted, and
RCU-protected arguments. The latter is used by sched-ext programs that pass
the result of an RCU-protected kfunc through trusted-and-nullable global
subprogram arguments.
Add a rejection test for the bare pointer and a positive regression test for
the RCU-protected case.
This series targets bpf, which uses separate global-subprogram and kfunc
argument checkers.
Changes in v3:
- Preserve RCU-protected arguments accepted by existing sched-ext programs.
- Make the MEM_RCU case a positive regression test.
- Use the preferred multi-line comment style.
- Link to v2: https://lore.kernel.org/r/20261005-a3-arg-trusted-v4-v2-0-319ce2936949@mails.tsinghua.edu.cn
Changes in v2:
- Retarget the fix to btf_check_func_arg_match(), where the subprogram
argument check lives in this tree, instead of check_func_arg().
- Run the check after check_reg_type() and check_func_arg_reg_off() so type
and offset diagnostics keep their wording.
v1: https://lore.kernel.org/bpf/20261005-a3-arg-trusted-v4-v1-0-50ee0268fd39@mails.tsinghua.edu.cn/
---
Yiyang Chen (2):
bpf: Reject bare pointer for __arg_trusted arg
selftests/bpf: Cover bare and RCU __arg_trusted arguments
kernel/bpf/verifier.c | 24 +++++++++++++++
.../selftests/bpf/progs/verifier_global_ptr_args.c | 34 ++++++++++++++++++++++
2 files changed, 58 insertions(+)
base-commit: ff47652a4b66c067c765a7ad464d930b5a9367cc
change-id: 20261005-a3-arg-trusted-v4-9d5d9485e5ba
--
Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH bpf v3 1/2] bpf: Reject bare pointer for __arg_trusted arg
2026-10-06 16:06 [PATCH bpf v3 0/2] bpf: Reject bare pointer for __arg_trusted arg Yiyang Chen
@ 2026-10-06 16:06 ` Yiyang Chen
2026-10-06 16:06 ` [PATCH bpf v3 2/2] selftests/bpf: Cover bare and RCU __arg_trusted arguments Yiyang Chen
2026-10-06 16:57 ` [PATCH bpf v3 0/2] bpf: Reject bare pointer for __arg_trusted arg Alexei Starovoitov
2 siblings, 0 replies; 4+ messages in thread
From: Yiyang Chen @ 2026-10-06 16:06 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest, Amery Hung, Yiyang Chen
A global subprogram parameter tagged __arg_trusted is specified to accept
only lifetime-protected PTR_TO_BTF_ID registers, but the call-site check in
btf_check_func_arg_match() also accepts a bare PTR_TO_BTF_ID.
check_reg_type() resolves the accepted set from the base argument type
alone and compares only MEM_RDONLY and PTR_MAYBE_NULL, so the PTR_TRUSTED
bit of arg_type is never consulted. btf_ptr_types includes bare
PTR_TO_BTF_ID, and nothing else on the subprogram call path rejects it.
The callee is then validated with PTR_TRUSTED set on the register while
the caller passed a pointer without lifetime protection.
bpf_may_fault_on_deref() is false for PTR_TRUSTED, so the dereference
becomes a raw load instead of a BPF_PROBE_MEM probe and the callee can
pass the pointer on as trusted.
Reject a bare PTR_TO_BTF_ID when the argument is marked PTR_TRUSTED. Keep
accepting referenced, trusted, and RCU-protected registers.
PTR_MAYBE_NULL is allowed when __arg_nullable declares it.
The check runs after check_reg_type() and check_func_arg_reg_off()
succeed so that type and offset diagnostics keep their current wording.
The kfunc path is unchanged.
Fixes: e2b3c4ff5d183da6d1863c2321413406a2752e7a ("bpf: add __arg_trusted global func arg tag")
Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
---
kernel/bpf/verifier.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 5f874979b8d75..7ea181f3e8c15 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -9806,6 +9806,30 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
err = err ?: check_func_arg_reg_off(env, reg, argno, arg->arg_type);
if (err)
return err;
+
+ /*
+ * A __arg_trusted argument requires a referenced, trusted, or
+ * RCU-protected pointer. btf_ptr_types also matches a bare
+ * PTR_TO_BTF_ID, but that has no lifetime protection even
+ * though the callee is verified with PTR_TRUSTED.
+ * PTR_MAYBE_NULL is allowed when __arg_nullable declares it.
+ *
+ * Checked after the type/offset match so that type and offset
+ * diagnostics keep their current wording.
+ */
+ if (arg->arg_type & PTR_TRUSTED) {
+ u32 flags = type_flag(reg->type);
+
+ if (!reg_is_referenced(env, reg) &&
+ (!(flags & (BPF_REG_TRUSTED_MODIFIERS | MEM_RCU)) ||
+ (flags & ~(BPF_REG_TRUSTED_MODIFIERS | MEM_RCU |
+ (arg->arg_type & PTR_MAYBE_NULL))))) {
+ bpf_log(log,
+ "%s must be referenced, trusted, or RCU protected\n",
+ reg_arg_name(env, argno));
+ return -EINVAL;
+ }
+ }
} else {
verifier_bug(env, "unrecognized %s type %d",
reg_arg_name(env, argno), arg->arg_type);
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH bpf v3 2/2] selftests/bpf: Cover bare and RCU __arg_trusted arguments
2026-10-06 16:06 [PATCH bpf v3 0/2] bpf: Reject bare pointer for __arg_trusted arg Yiyang Chen
2026-10-06 16:06 ` [PATCH bpf v3 1/2] " Yiyang Chen
@ 2026-10-06 16:06 ` Yiyang Chen
2026-10-06 16:57 ` [PATCH bpf v3 0/2] bpf: Reject bare pointer for __arg_trusted arg Alexei Starovoitov
2 siblings, 0 replies; 4+ messages in thread
From: Yiyang Chen @ 2026-10-06 16:06 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest, Amery Hung, Yiyang Chen
verifier_global_ptr_args.c already covers passing an untrusted pointer to
a __arg_trusted argument, which is rejected by the register type match.
It does not cover the bare PTR_TO_BTF_ID flavor that the type match also
accepts.
Add a rejection case that walks task_struct->last_wakee out of a trusted
current task and passes the result to a __arg_trusted subprogram parameter.
The field has no __rcu tag and is not in
BTF_TYPE_SAFE_RCU(task_struct), so the load yields a bare PTR_TO_BTF_ID.
Also pass task_struct->real_parent to a trusted-and-nullable subprogram
as a positive test. The field is __rcu and on
BTF_TYPE_SAFE_RCU(task_struct), so it yields PTR_TO_BTF_ID | MEM_RCU and
must remain accepted.
Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
---
.../selftests/bpf/progs/verifier_global_ptr_args.c | 34 ++++++++++++++++++++++
1 file changed, 34 insertions(+)
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 dcc2dd46751a4..6176b2223a0fb 100644
--- a/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c
+++ b/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c
@@ -289,6 +289,40 @@ __weak int subprog_void_untrusted(void *p __arg_untrusted)
return *(int *)p;
}
+__weak int subprog_trusted_bare(struct task_struct *task __arg_trusted)
+{
+ return task->pid;
+}
+
+SEC("tp_btf/task_newtask")
+__failure
+__msg("R1 must be referenced, trusted, or RCU protected")
+__msg("Caller passes invalid args into func#{{.*}} ('subprog_trusted_bare')")
+int bare_to_trusted(void *ctx)
+{
+ struct task_struct *cur = bpf_get_current_task_btf();
+ struct task_struct *wakee;
+
+ if (!cur)
+ return 0;
+ wakee = cur->last_wakee;
+ if (!wakee)
+ return 0;
+ return subprog_trusted_bare(wakee);
+}
+
+/* real_parent yields an RCU-protected pointer, which is a valid argument. */
+SEC("tp_btf/task_newtask")
+__success
+int memrcu_to_trusted(void *ctx)
+{
+ struct task_struct *cur = bpf_get_current_task_btf();
+
+ if (!cur)
+ return 0;
+ return subprog_trusted_task_nullable(cur->real_parent);
+}
+
__weak int subprog_char_untrusted(char *p __arg_untrusted)
{
return *(int *)p;
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH bpf v3 0/2] bpf: Reject bare pointer for __arg_trusted arg
2026-10-06 16:06 [PATCH bpf v3 0/2] bpf: Reject bare pointer for __arg_trusted arg Yiyang Chen
2026-10-06 16:06 ` [PATCH bpf v3 1/2] " Yiyang Chen
2026-10-06 16:06 ` [PATCH bpf v3 2/2] selftests/bpf: Cover bare and RCU __arg_trusted arguments Yiyang Chen
@ 2026-10-06 16:57 ` Alexei Starovoitov
2 siblings, 0 replies; 4+ messages in thread
From: Alexei Starovoitov @ 2026-10-06 16:57 UTC (permalink / raw)
To: Yiyang Chen, Daniel Borkmann, John Fastabend, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Ihor Solodrai, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest, Amery Hung
On Tue, Oct 06, 2026 at 04:06 PM Yiyang Chen <chenyy23@mails.tsinghua.edu.cn> wrote:
> Reject the bare pointer while preserving referenced, trusted, and
> RCU-protected arguments. The latter is used by sched-ext programs that pass
> the result of an RCU-protected kfunc through trusted-and-nullable global
> subprogram arguments.
Which programs?
veristat-scx failed on v2. The only one I see in scx repo is
cake_wake_place() in scx_cake. It takes the result of scx_bpf_cpu_curr()
as __arg_trusted __arg_nullable.
That arg was added two weeks ago. The last scx release doesn't have it.
On kernels without the kfunc cake_wake_place() already reads curr
by itself. Pls send a fix to scx instead.
rcu_ptr_ is not trusted. The refcount can be zero.
The callee sees trusted_ptr_ and can pass it to a kfunc that is not KF_RCU.
bpf_cpumask_acquire() does plain refcount_inc().
With rcu_ptr_bpf_cpumask loaded from a map it increments from zero
and the prog holds a reference to a cpumask that is freed after GP.
Commit e2b3c4ff5d18 says
"only PTR_TRUSTED flavor of PTR_TO_BTF_ID is supported".
v2 was right to reject it. Add the above to the commit log.
> This series targets bpf, which uses separate global-subprogram and kfunc
> argument checkers.
That's not an answer to Amery:
https://lore.kernel.org/bpf/CAMB2axNnY5wxkTrd3_tHyXBzXYyjJUkqRb1uNbUquwTJ_FLVMg@mail.gmail.com/
The loop in btf_check_func_arg_match() is gone in bpf-next. See
commit 668a51c4ed4b ("bpf: Build argument prototypes for subprog calls").
This patch will conflict when bpf is merged into bpf-next and the fix
has to be written again in check_func_arg().
The bug is there since 6.9 and the fix rejects progs that load today.
Pls target bpf-next and do what Amery suggested.
Also 12 chars of sha in the Fixes tag.
pw-bot: cr
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-06 16:57 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-06 16:06 [PATCH bpf v3 0/2] bpf: Reject bare pointer for __arg_trusted arg Yiyang Chen
2026-10-06 16:06 ` [PATCH bpf v3 1/2] " Yiyang Chen
2026-10-06 16:06 ` [PATCH bpf v3 2/2] selftests/bpf: Cover bare and RCU __arg_trusted arguments Yiyang Chen
2026-10-06 16:57 ` [PATCH bpf v3 0/2] bpf: Reject bare pointer for __arg_trusted arg Alexei Starovoitov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.