Re: [PATCH bpf-next] selftests/bpf: add helper retval linked scalar pruning selftest
From: Shung-Hsi Yu <hidden>
Date: 2026-06-12 10:18:52
Also in:
bpf, lkml, stable
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:quoted
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.
[...]
quoted
+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.
quoted
+ /* success path keeps r7 independent; failure path links r7 to r0. */ + "if r0 == 1 goto l0_%=;" + "r7 = r0;"
^^^^^^^ conditional scalar linking
quoted
+"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); +}
[...]