selftests/bpf: Add few tests for alu32 shift value tracking and zext

Add few more alu32 shift tests using div-by-zero on provably dead paths
to check both verifier and JIT xlation resp. runtime correctness.

If the verifier mistracks the result, it rejects due to the div by 0;
if the JIT computes a wrong value, then runtime hits the dead path and
retval changes.

  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_subreg
  [...]
  #644/76  verifier_subreg/arsh32_imm1_value:OK
  #644/77  verifier_subreg/lsh32_reg0_zero_extend_check:OK
  #644/78  verifier_subreg/rsh32_reg0_zero_extend_check:OK
  #644/79  verifier_subreg/arsh32_reg0_zero_extend_check:OK
  #644/80  verifier_subreg/lsh32_imm31_value:OK
  #644/81  verifier_subreg/rsh32_imm31_value:OK
  #644/82  verifier_subreg/arsh32_imm31_value:OK
  #644/83  verifier_subreg/lsh32_unknown_precise_bounds:OK
  #644/84  verifier_subreg/rsh32_unknown_bounds:OK
  #644     verifier_subreg:OK
  Summary: 1/84 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20260327220629.343327-1-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Daniel Borkmann 2026-03-27 23:06:29 +01:00 committed by Alexei Starovoitov
parent 101a9d9df8
commit 398ad123e8

View File

@ -823,4 +823,169 @@ __naked void arsh_63_or(void)
: __clobber_all);
}
SEC("socket")
__success __retval(42)
__naked void arsh32_imm1_value(void)
{
asm volatile (" \
r0 = 42; \
r1 = -2147483648; \
w1 s>>= 1; /* r1 = 0xC0000000 */ \
r2 = 0xC0000000 ll; \
if r1 == r2 goto l0_%=; \
r0 /= 0; /* unreachable */ \
l0_%=: exit; \
" :
:
: __clobber_all);
}
SEC("socket")
__success __retval(1)
__naked void lsh32_reg0_zero_extend_check(void)
{
asm volatile (" \
r6 = 1; \
call %[bpf_get_prandom_u32]; \
r1 = 0x1000000000 ll; \
r0 |= r1; \
w1 = 0; \
w0 <<= w1; /* reg shift by 0 */ \
r0 >>= 32; /* must be 0 */ \
if r0 == 0 goto l0_%=; \
r6 /= 0; /* unreachable */ \
l0_%=: r0 = r6; \
exit; \
" :
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__success __retval(1)
__naked void rsh32_reg0_zero_extend_check(void)
{
asm volatile (" \
r6 = 1; \
call %[bpf_get_prandom_u32]; \
r1 = 0x1000000000 ll; \
r0 |= r1; \
w1 = 0; \
w0 >>= w1; /* reg rsh by 0 */ \
r0 >>= 32; /* must be 0 */ \
if r0 == 0 goto l0_%=; \
r6 /= 0; /* unreachable */ \
l0_%=: r0 = r6; \
exit; \
" :
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__success __retval(1)
__naked void arsh32_reg0_zero_extend_check(void)
{
asm volatile (" \
r6 = 1; \
call %[bpf_get_prandom_u32]; \
r1 = 0x1000000000 ll; \
r0 |= r1; \
w1 = 0; \
w0 s>>= w1; /* reg arsh by 0 */ \
r0 >>= 32; /* must be 0 */ \
if r0 == 0 goto l0_%=; \
r6 /= 0; /* unreachable */ \
l0_%=: r0 = r6; \
exit; \
" :
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__success __retval(42)
__naked void lsh32_imm31_value(void)
{
asm volatile (" \
r0 = 42; \
r1 = 1; \
w1 <<= 31; /* r1 = 0x80000000 */ \
r2 = 0x80000000 ll; \
if r1 == r2 goto l0_%=; \
r0 /= 0; /* unreachable */ \
l0_%=: exit; \
" :
:
: __clobber_all);
}
SEC("socket")
__success __retval(42)
__naked void rsh32_imm31_value(void)
{
asm volatile (" \
r0 = 42; \
r1 = -2147483648; /* 0x80000000 */ \
w1 >>= 31; /* r1 = 1 */ \
if r1 == 1 goto l0_%=; \
r0 /= 0; /* unreachable */ \
l0_%=: exit; \
" :
:
: __clobber_all);
}
SEC("socket")
__success __retval(42)
__naked void arsh32_imm31_value(void)
{
asm volatile (" \
r0 = 42; \
r1 = -2147483648; /* 0x80000000 */ \
w1 s>>= 31; /* r1 = 0xFFFFFFFF */ \
r2 = 0xFFFFFFFF ll; \
if r1 == r2 goto l0_%=; \
r0 /= 0; /* unreachable */ \
l0_%=: exit; \
" :
:
: __clobber_all);
}
SEC("socket")
__success __retval(1)
__naked void lsh32_unknown_precise_bounds(void)
{
asm volatile (" \
r6 = 1; \
call %[bpf_get_prandom_u32]; \
w0 &= 3; /* u32: [0, 3] */ \
w0 <<= 1; /* u32: [0, 6] */ \
if w0 < 7 goto l0_%=; \
r6 /= 0; /* unreachable */ \
l0_%=: r0 = r6; \
exit; \
" :
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
SEC("socket")
__success __retval(1)
__naked void rsh32_unknown_bounds(void)
{
asm volatile (" \
r6 = 1; \
call %[bpf_get_prandom_u32]; \
w0 >>= 28; /* u32: [0, 15] */ \
if w0 < 16 goto l0_%=; \
r6 /= 0; /* unreachable */ \
l0_%=: r0 = r6; \
exit; \
" :
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
char _license[] SEC("license") = "GPL";