Netdev List
 help / color / mirror / Atom feed
* [PATCH bpf-next] selftests/bpf: add helper retval linked scalar pruning selftest
@ 2026-06-11 16:07 Zhenzhong Wu
  2026-06-11 16:55 ` Alexei Starovoitov
  2026-06-11 16:58 ` bot+bpf-ci
  0 siblings, 2 replies; 5+ messages in thread
From: Zhenzhong Wu @ 2026-06-11 16:07 UTC (permalink / raw)
  To: bpf
  Cc: netdev, linux-kernel, ast, daniel, john.fastabend, andrii,
	martin.lau, song, yonghong.song, kpsingh, haoluo, jolsa,
	menglong8.dong, eddyz87, shung-hsi.yu, stable, mykolal, tamird

Add a verifier runtime test for a branch pattern where a helper return
value and a related scalar stay live across the same control-flow
sequence. Rust/Aya-generated eBPF can naturally produce this shape when
a match on a helper status keeps data derived before the helper call
live across the same branches. Such code commonly uses the helper return
value in r0, where 0 means success, producing an r0 == 0 / r0 != 0
branch shape.

The test preserves that branch shape but shifts the success value to 1
before branching. Using r0 == 1 / r0 != 1 avoids depending on the
verifier's not-equal-zero refinement, so the test exercises linked
scalar precision and pruning behavior directly instead of being masked
by zero-specific range refinement.

On affected kernels the verifier can explore an impossible path where
r0 and r7 are linked by scalar ID, keep the wrong branch, and make the
test return 1. With linked scalar precision tracked per instruction,
state pruning keeps the real success path, and the test returns 0.

Suggested-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
Signed-off-by: Zhenzhong Wu <jt26wzz@gmail.com>
---
 .../selftests/bpf/progs/verifier_scalar_ids.c | 35 +++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c b/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
index 70ae14d60..de71d547f 100644
--- a/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
+++ b/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
@@ -448,6 +448,41 @@ __naked void linked_regs_broken_link_2(void)
 	: __clobber_all);
 }
 
+SEC("tc")
+__description("helper retval linked scalar pruning")
+__success __retval(0)
+__naked void helper_retval_linked_scalar_pruning(void)
+{
+	asm volatile (
+	"r7 = *(u32 *)(r1 + %[__sk_buff_data_end]);"
+	"r5 = *(u32 *)(r1 + %[__sk_buff_data]);"
+	"r7 -= r5;"
+	"r2 = 0;"
+	"r3 = r10;"
+	"r3 += -8;"
+	"r4 = 1;"
+	"call %[bpf_skb_load_bytes];"
+	"r0 += 1;"
+	"r6 = 1;"
+	/* success path keeps r7 independent; failure path links r7 to r0. */
+	"if r0 == 1 goto l0_%=;"
+	"r7 = r0;"
+"l0_%=: if r0 != 1 goto l1_%=;"
+	"r7 <<= 32;"
+	"r7 >>= 32;"
+	"if r7 != %[test_data_len] goto l1_%=;"
+	"r0 = 0;"
+	"exit;"
+"l1_%=: r0 = r6;"
+	"exit;"
+	:
+	: __imm(bpf_skb_load_bytes),
+	  __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
+	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),
+	  __imm_const(test_data_len, TEST_DATA_LEN)
+	: __clobber_all);
+}
+
 /* Check that mark_chain_precision() for one of the conditional jump
  * operands does not trigger equal scalars precision propagation.
  */

base-commit: 30dee2c176e7954f63d1fa3e52d172f30beb9bfb
-- 
2.43.0


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

* Re: [PATCH bpf-next] selftests/bpf: add helper retval linked scalar pruning selftest
  2026-06-11 16:07 [PATCH bpf-next] selftests/bpf: add helper retval linked scalar pruning selftest Zhenzhong Wu
@ 2026-06-11 16:55 ` Alexei Starovoitov
  2026-06-12 10:18   ` Shung-Hsi Yu
  2026-06-11 16:58 ` bot+bpf-ci
  1 sibling, 1 reply; 5+ messages in thread
From: Alexei Starovoitov @ 2026-06-11 16:55 UTC (permalink / raw)
  To: Zhenzhong Wu, bpf
  Cc: netdev, linux-kernel, ast, daniel, john.fastabend, andrii,
	martin.lau, song, yonghong.song, kpsingh, haoluo, jolsa,
	menglong8.dong, eddyz87, shung-hsi.yu, stable, mykolal, tamird

On Thu Jun 11, 2026 at 9:07 AM PDT, Zhenzhong Wu wrote:
> Add a verifier runtime test for a branch pattern where a helper return
> value and a related scalar stay live across the same control-flow
> sequence. Rust/Aya-generated eBPF can naturally produce this shape when
> a match on a helper status keeps data derived before the helper call
> live across the same branches. Such code commonly uses the helper return
> value in r0, where 0 means success, producing an r0 == 0 / r0 != 0
> branch shape.
>
> The test preserves that branch shape but shifts the success value to 1
> before branching. Using r0 == 1 / r0 != 1 avoids depending on the
> verifier's not-equal-zero refinement, so the test exercises linked
> scalar precision and pruning behavior directly instead of being masked
> by zero-specific range refinement.
>
> On affected kernels the verifier can explore an impossible path where
> r0 and r7 are linked by scalar ID, keep the wrong branch, and make the
> test return 1. With linked scalar precision tracked per instruction,
> state pruning keeps the real success path, and the test returns 0.
>
> Suggested-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
> Signed-off-by: Zhenzhong Wu <jt26wzz@gmail.com>
> ---
>  .../selftests/bpf/progs/verifier_scalar_ids.c | 35 +++++++++++++++++++
>  1 file changed, 35 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c b/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
> index 70ae14d60..de71d547f 100644
> --- a/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
> +++ b/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c
> @@ -448,6 +448,41 @@ __naked void linked_regs_broken_link_2(void)
>  	: __clobber_all);
>  }
>  
> +SEC("tc")
> +__description("helper retval linked scalar pruning")
> +__success __retval(0)
> +__naked void helper_retval_linked_scalar_pruning(void)
> +{
> +	asm volatile (
> +	"r7 = *(u32 *)(r1 + %[__sk_buff_data_end]);"
> +	"r5 = *(u32 *)(r1 + %[__sk_buff_data]);"
> +	"r7 -= r5;"
> +	"r2 = 0;"
> +	"r3 = r10;"
> +	"r3 += -8;"
> +	"r4 = 1;"
> +	"call %[bpf_skb_load_bytes];"
> +	"r0 += 1;"
> +	"r6 = 1;"
> +	/* success path keeps r7 independent; failure path links r7 to r0. */
> +	"if r0 == 1 goto l0_%=;"

this exercises linked registers with BPF_ADD_CONST logic.
We already have such tests. Why do we need this one?
How is it different?

pw-bot: cr

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

* Re: [PATCH bpf-next] selftests/bpf: add helper retval linked scalar pruning selftest
  2026-06-11 16:07 [PATCH bpf-next] selftests/bpf: add helper retval linked scalar pruning selftest Zhenzhong Wu
  2026-06-11 16:55 ` Alexei Starovoitov
@ 2026-06-11 16:58 ` bot+bpf-ci
  2026-06-12  6:32   ` Zhenzhong Wu
  1 sibling, 1 reply; 5+ messages in thread
From: bot+bpf-ci @ 2026-06-11 16:58 UTC (permalink / raw)
  To: jt26wzz, bpf
  Cc: netdev, linux-kernel, ast, daniel, john.fastabend, andrii,
	martin.lau, song, yonghong.song, kpsingh, haoluo, jolsa,
	menglong8.dong, eddyz87, shung-hsi.yu, stable, mykolal, tamird,
	ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
	ihor.solodrai

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

> selftests/bpf: add helper retval linked scalar pruning selftest
>
>     Add a verifier runtime test for a branch pattern where a helper return
>     value and a related scalar stay live across the same control-flow
>     sequence. Rust/Aya-generated eBPF can naturally produce this shape when
>     a match on a helper status keeps data derived before the helper call
>     live across the same branches. Such code commonly uses the helper return
>     value in r0, where 0 means success, producing an r0 == 0 / r0 != 0
>     branch shape.
>
>     The test preserves that branch shape but shifts the success value to 1
>     before branching. Using r0 == 1 / r0 != 1 avoids depending on the
>     verifier's not-equal-zero refinement, so the test exercises linked
>     scalar precision and pruning behavior directly instead of being masked
>     by zero-specific range refinement.
>
>     On affected kernels the verifier can explore an impossible path where
>     r0 and r7 are linked by scalar ID, keep the wrong branch, and make the
>     test return 1. With linked scalar precision tracked per instruction,
>     state pruning keeps the real success path, and the test returns 0.
>
>     Suggested-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
>     Signed-off-by: Zhenzhong Wu <jt26wzz@gmail.com>

This adds a regression test for a verifier state-pruning issue with
scalars linked by scalar ID, but there is no Fixes: tag.

The test structure (success path keeps r7 independent with id=0, failure
path links r7 to r0) matches the "registers with id=0 in cached state vs
linked in current state" pruning scenario that was addressed by changing
check_scalar_ids() and regsafe() to treat rold->id == 0 as independent.

Should this carry:

  Fixes: b0388bafa494 ("bpf: Relax scalar id equivalence for state pruning")


---
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/27361218656

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

* Re: [PATCH bpf-next] selftests/bpf: add helper retval linked scalar pruning selftest
  2026-06-11 16:58 ` bot+bpf-ci
@ 2026-06-12  6:32   ` Zhenzhong Wu
  0 siblings, 0 replies; 5+ messages in thread
From: Zhenzhong Wu @ 2026-06-12  6:32 UTC (permalink / raw)
  To: bot+bpf-ci
  Cc: bpf, netdev, linux-kernel, ast, daniel, john.fastabend, andrii,
	martin.lau, song, yonghong.song, kpsingh, haoluo, jolsa,
	menglong8.dong, eddyz87, shung-hsi.yu, stable, mykolal, tamird,
	martin.lau, clm, ihor.solodrai

Thanks for taking a look.

I used `r0 += 1` only to shift the helper success value from 0 to
1, so this test is not masked by the verifier's not-equal-zero
refinement. In this reproducer, `r0 += 1` does not enter the internal
BPF_ADD_CONST linked-scalar path.

The helper returns an integer with `R0 id=0`, `r0 += 1` keeps
`R0 id=0`, and the `r0`/`r7` scalar-id relation is established later
by the `r7 = r0` move on the failure path.

The success path skips that move and keeps `r7` independent. The test
is intended to cover pruning between those two different state shapes,
not ADD_CONST delta propagation.

Separately, I don't think the Fixes tag suggested by the bot is
appropriate. I do not have evidence that b0388bafa494 introduced this
issue. I can reproduce the issue on v5.10.258, v5.15.209, v6.1.91 and
v6.6.142. The upstream change that fixes this state shape is the later
linked-scalar precision tracking change:

  4bf79f9be434
  ("bpf: Track equal scalars history on per-instruction level")

More background is in the v2 thread:

  https://lore.kernel.org/r/20260607170959.823755-1-jt26wzz@gmail.com/

BR,
Zhenzhong

On Fri, Jun 12, 2026 at 12:58 AM <bot+bpf-ci@kernel.org> wrote:
>
> > selftests/bpf: add helper retval linked scalar pruning selftest
> >
> >     Add a verifier runtime test for a branch pattern where a helper return
> >     value and a related scalar stay live across the same control-flow
> >     sequence. Rust/Aya-generated eBPF can naturally produce this shape when
> >     a match on a helper status keeps data derived before the helper call
> >     live across the same branches. Such code commonly uses the helper return
> >     value in r0, where 0 means success, producing an r0 == 0 / r0 != 0
> >     branch shape.
> >
> >     The test preserves that branch shape but shifts the success value to 1
> >     before branching. Using r0 == 1 / r0 != 1 avoids depending on the
> >     verifier's not-equal-zero refinement, so the test exercises linked
> >     scalar precision and pruning behavior directly instead of being masked
> >     by zero-specific range refinement.
> >
> >     On affected kernels the verifier can explore an impossible path where
> >     r0 and r7 are linked by scalar ID, keep the wrong branch, and make the
> >     test return 1. With linked scalar precision tracked per instruction,
> >     state pruning keeps the real success path, and the test returns 0.
> >
> >     Suggested-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
> >     Signed-off-by: Zhenzhong Wu <jt26wzz@gmail.com>
>
> This adds a regression test for a verifier state-pruning issue with
> scalars linked by scalar ID, but there is no Fixes: tag.
>
> The test structure (success path keeps r7 independent with id=0, failure
> path links r7 to r0) matches the "registers with id=0 in cached state vs
> linked in current state" pruning scenario that was addressed by changing
> check_scalar_ids() and regsafe() to treat rold->id == 0 as independent.
>
> Should this carry:
>
>   Fixes: b0388bafa494 ("bpf: Relax scalar id equivalence for state pruning")
>
>
> ---
> 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/27361218656

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

* Re: [PATCH bpf-next] selftests/bpf: add helper retval linked scalar pruning selftest
  2026-06-11 16:55 ` Alexei Starovoitov
@ 2026-06-12 10:18   ` Shung-Hsi Yu
  0 siblings, 0 replies; 5+ messages in thread
From: Shung-Hsi Yu @ 2026-06-12 10:18 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Zhenzhong Wu, bpf, netdev, linux-kernel, ast, daniel,
	john.fastabend, andrii, martin.lau, song, yonghong.song, kpsingh,
	haoluo, jolsa, menglong8.dong, eddyz87, stable, mykolal, tamird

On Thu, Jun 11, 2026 at 09:55:55AM -0700, Alexei Starovoitov wrote:
> On Thu Jun 11, 2026 at 9:07 AM PDT, Zhenzhong Wu wrote:
> > Add a verifier runtime test for a branch pattern where a helper return
> > value and a related scalar stay live across the same control-flow
> > sequence. Rust/Aya-generated eBPF can naturally produce this shape when
> > a match on a helper status keeps data derived before the helper call
> > live across the same branches. Such code commonly uses the helper return
> > value in r0, where 0 means success, producing an r0 == 0 / r0 != 0
> > branch shape.
[...]
> > +SEC("tc")
> > +__description("helper retval linked scalar pruning")
> > +__success __retval(0)
> > +__naked void helper_retval_linked_scalar_pruning(void)
> > +{
> > +	asm volatile (
> > +	"r7 = *(u32 *)(r1 + %[__sk_buff_data_end]);"
> > +	"r5 = *(u32 *)(r1 + %[__sk_buff_data]);"
> > +	"r7 -= r5;"
> > +	"r2 = 0;"
> > +	"r3 = r10;"
> > +	"r3 += -8;"
> > +	"r4 = 1;"
> > +	"call %[bpf_skb_load_bytes];"
> > +	"r0 += 1;"
> > +	"r6 = 1;"
> > +	/* success path keeps r7 independent; failure path links r7 to r0. */
> > +	"if r0 == 1 goto l0_%=;"
> 
> this exercises linked registers with BPF_ADD_CONST logic.
> We already have such tests. Why do we need this one?
> How is it different?

BPF_ADD_CONST wasn't what was meant to be tested.

The main logic is r7.id == r0.id only happens on "if r0 == 1 goto l0_%="
fall through, and does not have such link otherwise. I only check tests
added in commit c0087d59e504 ("selftests/bpf: tests for per-insn
sync_linked_regs() precision tracking"), but it doesn't seem like such
conditional linking was tested. 

The other rational is that this seem like a common pattern that is
genereated from Rust-based BPF program.

> > +	/* success path keeps r7 independent; failure path links r7 to r0. */
> > +	"if r0 == 1 goto l0_%=;"
> > +	"r7 = r0;"
         ^^^^^^^ conditional scalar linking

> > +"l0_%=: if r0 != 1 goto l1_%=;"
> > +	"r7 <<= 32;"
> > +	"r7 >>= 32;"
> > +	"if r7 != %[test_data_len] goto l1_%=;"
> > +	"r0 = 0;"
> > +	"exit;"
> > +"l1_%=: r0 = r6;"
> > +	"exit;"
> > +	:
> > +	: __imm(bpf_skb_load_bytes),
> > +	  __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
> > +	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)),
> > +	  __imm_const(test_data_len, TEST_DATA_LEN)
> > +	: __clobber_all);
> > +}
[...]

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

end of thread, other threads:[~2026-06-12 10:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-11 16:07 [PATCH bpf-next] selftests/bpf: add helper retval linked scalar pruning selftest Zhenzhong Wu
2026-06-11 16:55 ` Alexei Starovoitov
2026-06-12 10:18   ` Shung-Hsi Yu
2026-06-11 16:58 ` bot+bpf-ci
2026-06-12  6:32   ` Zhenzhong Wu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox