selftests/bpf: Add tests for delta tracking when src_reg == dst_reg

Extend the verifier_linked_scalars BPF selftest with a rX += rX test
such that the div-by-zero path is rejected in the fixed case.

  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_linked_scalars
  [...]
  ./test_progs -t verifier_linked_scalars
  #612/1   verifier_linked_scalars/scalars: find linked scalars:OK
  #612/2   verifier_linked_scalars/sync_linked_regs_preserves_id:OK
  #612/3   verifier_linked_scalars/scalars_neg:OK
  #612/4   verifier_linked_scalars/scalars_neg_sub:OK
  #612/5   verifier_linked_scalars/scalars_neg_alu32_add:OK
  #612/6   verifier_linked_scalars/scalars_neg_alu32_sub:OK
  #612/7   verifier_linked_scalars/scalars_pos:OK
  #612/8   verifier_linked_scalars/scalars_sub_neg_imm:OK
  #612/9   verifier_linked_scalars/scalars_double_add:OK
  #612/10  verifier_linked_scalars/scalars_sync_delta_overflow:OK
  #612/11  verifier_linked_scalars/scalars_sync_delta_overflow_large_range:OK
  #612/12  verifier_linked_scalars/scalars_alu32_big_offset:OK
  #612/13  verifier_linked_scalars/scalars_alu32_basic:OK
  #612/14  verifier_linked_scalars/scalars_alu32_wrap:OK
  #612/15  verifier_linked_scalars/scalars_alu32_zext_linked_reg:OK
  #612/16  verifier_linked_scalars/scalars_alu32_alu64_cross_type:OK
  #612/17  verifier_linked_scalars/scalars_alu32_alu64_regsafe_pruning:OK
  #612/18  verifier_linked_scalars/alu32_negative_offset:OK
  #612/19  verifier_linked_scalars/spurious_precision_marks:OK
  #612/20  verifier_linked_scalars/scalars_self_add_clears_id:OK
  #612/21  verifier_linked_scalars/scalars_self_add_alu32_clears_id:OK
  #612     verifier_linked_scalars:OK
  Summary: 1/21 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20260407192421.508817-3-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Daniel Borkmann
2026-04-07 21:24:20 +02:00
committed by Alexei Starovoitov
parent 1b327732c8
commit ed2eecdc0c

View File

@@ -535,4 +535,61 @@ int spurious_precision_marks(void *ctx)
return 0;
}
/*
* Test that r += r (self-add, src_reg == dst_reg) clears the scalar ID
* so that sync_linked_regs() does not propagate an incorrect delta.
*/
SEC("socket")
__failure
__msg("div by zero")
__naked void scalars_self_add_clears_id(void)
{
asm volatile (" \
call %[bpf_get_prandom_u32]; \
r6 = r0; /* r6 unknown, id A */ \
r7 = r6; /* r7 linked to r6, id A */ \
call %[bpf_get_prandom_u32]; \
r8 = r0; /* r8 unknown, id B */ \
r9 = r8; /* r9 linked to r8, id B */ \
if r7 != 1 goto l_exit_%=; \
/* r7 == 1; sync propagates: r6 = 1 (known, id A) */ \
r6 += r6; /* r6 = 2; should clear id */ \
if r7 == r9 goto l_exit_%=; \
/* Bug: r6 synced to r7(1)+delta(2)=3; Fix: r6 = 2 */ \
if r6 == 3 goto l_exit_%=; \
r0 /= 0; \
l_exit_%=: \
r0 = 0; \
exit; \
" :
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
/* Same as above but with alu32 such that w6 += w6 also clears id. */
SEC("socket")
__failure
__msg("div by zero")
__naked void scalars_self_add_alu32_clears_id(void)
{
asm volatile (" \
call %[bpf_get_prandom_u32]; \
w6 = w0; \
w7 = w6; \
call %[bpf_get_prandom_u32]; \
w8 = w0; \
w9 = w8; \
if w7 != 1 goto l_exit_%=; \
w6 += w6; \
if w7 == w9 goto l_exit_%=; \
if w6 == 3 goto l_exit_%=; \
r0 /= 0; \
l_exit_%=: \
r0 = 0; \
exit; \
" :
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
char _license[] SEC("license") = "GPL";