mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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	[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	[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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®