All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next v2 0/2] bpf: Compare iterator types during state pruning
@ 2026-08-11  3:59 Ning Ding
  2026-08-11  3:59 ` [PATCH bpf-next v2 1/2] " Ning Ding
  2026-08-11  3:59 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test RCU iterator " Ning Ding
  0 siblings, 2 replies; 4+ messages in thread
From: Ning Ding @ 2026-08-11  3:59 UTC (permalink / raw)
  To: bpf
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
	Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
	Ihor Solodrai, Shuah Khan, Ning Ding, Chuyi Zhou, linux-kernel,
	linux-kselftest

Iterator stack slots can be marked MEM_RCU or PTR_UNTRUSTED. The
STACK_ITER check in stacksafe() does not compare this type, so state
pruning can treat these states as equal and prune an unsafe path.

Compare the type and add a test where RCU protection has a gap.

---
Changes in v2:
- Convert the regression test to inline assembly so its verifier-sensitive
  control-flow layout is stable.
- Add Eduard Zingerman's Acked-by tag to patch 1.

v1: https://lore.kernel.org/bpf/20260807004320.134069-1-dingning04@gmail.com/

Ning Ding (2):
  bpf: Compare iterator types during state pruning
  selftests/bpf: Test RCU iterator state pruning

 kernel/bpf/states.c                           |  3 +-
 .../selftests/bpf/progs/iters_task_failure.c  | 46 +++++++++++++++++++
 2 files changed, 48 insertions(+), 1 deletion(-)

-- 
2.43.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH bpf-next v2 1/2] bpf: Compare iterator types during state pruning
  2026-08-11  3:59 [PATCH bpf-next v2 0/2] bpf: Compare iterator types during state pruning Ning Ding
@ 2026-08-11  3:59 ` Ning Ding
  2026-08-11  3:59 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test RCU iterator " Ning Ding
  1 sibling, 0 replies; 4+ messages in thread
From: Ning Ding @ 2026-08-11  3:59 UTC (permalink / raw)
  To: bpf
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
	Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
	Ihor Solodrai, Shuah Khan, Ning Ding, Chuyi Zhou, linux-kernel,
	linux-kselftest

An iterator stack slot can be MEM_RCU or PTR_UNTRUSTED. These states
must not be equal, or the verifier can prune an unsafe path.

Compare the pointer type for STACK_ITER slots.

Fixes: dfab99df147b ("bpf: teach the verifier to enforce css_iter and task_iter in RCU CS")
Signed-off-by: Ning Ding <dingning04@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
---
 kernel/bpf/states.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/bpf/states.c b/kernel/bpf/states.c
index ea2153cf28d0a..4e6aafad33bd2 100644
--- a/kernel/bpf/states.c
+++ b/kernel/bpf/states.c
@@ -812,7 +812,8 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old,
 			 * infinite loop check triggering, see
 			 * iter_active_depths_differ()
 			 */
-			if (old_reg->iter.btf != cur_reg->iter.btf ||
+			if (old_reg->type != cur_reg->type ||
+			    old_reg->iter.btf != cur_reg->iter.btf ||
 			    old_reg->iter.btf_id != cur_reg->iter.btf_id ||
 			    old_reg->iter.state != cur_reg->iter.state ||
 			    /* ignore {old_reg,cur_reg}->iter.depth, see above */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH bpf-next v2 2/2] selftests/bpf: Test RCU iterator state pruning
  2026-08-11  3:59 [PATCH bpf-next v2 0/2] bpf: Compare iterator types during state pruning Ning Ding
  2026-08-11  3:59 ` [PATCH bpf-next v2 1/2] " Ning Ding
@ 2026-08-11  3:59 ` Ning Ding
  2026-08-11  4:41   ` bot+bpf-ci
  1 sibling, 1 reply; 4+ messages in thread
From: Ning Ding @ 2026-08-11  3:59 UTC (permalink / raw)
  To: bpf
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
	Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
	Ihor Solodrai, Shuah Khan, Ning Ding, Chuyi Zhou, linux-kernel,
	linux-kselftest

Add a path where RCU protection reaches zero and then starts again.
The iterator is untrusted after this gap and must be rejected.

Signed-off-by: Ning Ding <dingning04@gmail.com>
---
 .../selftests/bpf/progs/iters_task_failure.c  | 46 +++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/iters_task_failure.c b/tools/testing/selftests/bpf/progs/iters_task_failure.c
index fe3663dedbe14..566a1d3dffeab 100644
--- a/tools/testing/selftests/bpf/progs/iters_task_failure.c
+++ b/tools/testing/selftests/bpf/progs/iters_task_failure.c
@@ -61,6 +61,52 @@ int BPF_PROG(iter_tasks_lock_and_unlock)
 	return 0;
 }
 
+SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
+__failure __msg("expected an RCU CS when using bpf_iter_task_next")
+__flag(BPF_F_TEST_STATE_FREQ)
+int BPF_PROG(iter_tasks_rcu_state_pruning)
+{
+	struct bpf_iter_task it;
+
+	asm volatile (
+		"call %[bpf_rcu_read_lock];"
+		"r1 = %[it];"
+		"r2 = 0;"
+		"r3 = 0;" /* BPF_TASK_ITER_ALL_PROCS */
+		"call %[bpf_iter_task_new];"
+
+		"call %[bpf_get_prandom_u32];"
+		"if w0 == 0 goto unprotected_%=;"
+
+		/* Keep the outer RCU lock active on the straight-line path. */
+		"call %[bpf_rcu_read_lock];"
+		"call %[bpf_rcu_read_unlock];"
+		"goto merge_%=;"
+
+	"unprotected_%=:"
+		/* Create an unprotected gap on the taken path. */
+		"call %[bpf_rcu_read_unlock];"
+		"call %[bpf_rcu_read_lock];"
+
+	"merge_%=: r1 = %[it];"
+		"call %[bpf_iter_task_next];"
+		"r1 = %[it];"
+		"call %[bpf_iter_task_destroy];"
+		"call %[bpf_rcu_read_unlock];"
+		:
+		: __imm_ptr(it),
+		  __imm(bpf_get_prandom_u32),
+		  __imm(bpf_iter_task_new),
+		  __imm(bpf_iter_task_next),
+		  __imm(bpf_iter_task_destroy),
+		  __imm(bpf_rcu_read_lock),
+		  __imm(bpf_rcu_read_unlock)
+		: __clobber_common
+	);
+
+	return 0;
+}
+
 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
 __failure __msg("expected an RCU CS when using bpf_iter_css_next")
 int BPF_PROG(iter_css_lock_and_unlock)
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH bpf-next v2 2/2] selftests/bpf: Test RCU iterator state pruning
  2026-08-11  3:59 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test RCU iterator " Ning Ding
@ 2026-08-11  4:41   ` bot+bpf-ci
  0 siblings, 0 replies; 4+ messages in thread
From: bot+bpf-ci @ 2026-08-11  4:41 UTC (permalink / raw)
  To: dingning04, bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, ihor.solodrai, shuah, dingning04,
	zhouchuyi, linux-kernel, linux-kselftest, ast, andrii, daniel,
	martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 2553 bytes --]

> selftests/bpf: Test RCU iterator state pruning
>
> Add a path where RCU protection reaches zero and then starts again.
> The iterator is untrusted after this gap and must be rejected.
>
> Signed-off-by: Ning Ding <dingning04@gmail.com>

This isn't a bug, but could the changelog mention why BPF_F_TEST_STATE_FREQ
is needed and that both arms deliberately converge with the same RCU lock
depth, so a future reader knows what keeps this test meaningful?

> diff --git a/tools/testing/selftests/bpf/progs/iters_task_failure.c b/tools/testing/selftests/bpf/progs/iters_task_failure.c
> index fe3663dedbe1..566a1d3dffea 100644
> --- a/tools/testing/selftests/bpf/progs/iters_task_failure.c
> +++ b/tools/testing/selftests/bpf/progs/iters_task_failure.c
> @@ -61,6 +61,52 @@ int BPF_PROG(iter_tasks_lock_and_unlock)
>  	return 0;
>  }
>
> +SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
> +__failure __msg("expected an RCU CS when using bpf_iter_task_next")
> +__flag(BPF_F_TEST_STATE_FREQ)
> +int BPF_PROG(iter_tasks_rcu_state_pruning)
> +{
> +	struct bpf_iter_task it;
> +
> +	asm volatile (
> +		"call %[bpf_rcu_read_lock];"
> +		"r1 = %[it];"
> +		"r2 = 0;"
> +		"r3 = 0;" /* BPF_TASK_ITER_ALL_PROCS */
> +		"call %[bpf_iter_task_new];"
> +
> +		"call %[bpf_get_prandom_u32];"
> +		"if w0 == 0 goto unprotected_%=;"
> +
> +		/* Keep the outer RCU lock active on the straight-line path. */
> +		"call %[bpf_rcu_read_lock];"
> +		"call %[bpf_rcu_read_unlock];"

This isn't a bug, but would it help to say what the nested lock/unlock
pair is for here - e.g. that it scratches the caller-saved registers so
the only state difference at merge_ is the iterator's MEM_RCU vs
PTR_UNTRUSTED type?

> +		"goto merge_%=;"
> +
> +	"unprotected_%=:"
> +		/* Create an unprotected gap on the taken path. */
> +		"call %[bpf_rcu_read_unlock];"
> +		"call %[bpf_rcu_read_lock];"
> +
> +	"merge_%=: r1 = %[it];"
> +		"call %[bpf_iter_task_next];"
> +		"r1 = %[it];"
> +		"call %[bpf_iter_task_destroy];"
> +		"call %[bpf_rcu_read_unlock];"
> +		:
> +		: __imm_ptr(it),
> +		  __imm(bpf_get_prandom_u32),
> +		  __imm(bpf_iter_task_new),
> +		  __imm(bpf_iter_task_next),
> +		  __imm(bpf_iter_task_destroy),
> +		  __imm(bpf_rcu_read_lock),
> +		  __imm(bpf_rcu_read_unlock)
> +		: __clobber_common
> +	);
> +
> +	return 0;
> +}
> +


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/31457825387

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-08-11  4:41 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-11  3:59 [PATCH bpf-next v2 0/2] bpf: Compare iterator types during state pruning Ning Ding
2026-08-11  3:59 ` [PATCH bpf-next v2 1/2] " Ning Ding
2026-08-11  3:59 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test RCU iterator " Ning Ding
2026-08-11  4:41   ` bot+bpf-ci

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.