summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2026-03-28 01:06:29 +0300
committerAlexei Starovoitov <ast@kernel.org>2026-03-29 19:57:39 +0300
commit398ad123e83045cd187c74689cd46851b0a0459f (patch)
treebf7174820391597f4307bd0f2fde4b62652ca4c7
parent101a9d9df8e794af8bf06e1e09c176e2dab2abf6 (diff)
downloadlinux-398ad123e83045cd187c74689cd46851b0a0459f.tar.xz
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>
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_subreg.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/progs/verifier_subreg.c b/tools/testing/selftests/bpf/progs/verifier_subreg.c
index be328100ba53..31832a306f91 100644
--- a/tools/testing/selftests/bpf/progs/verifier_subreg.c
+++ b/tools/testing/selftests/bpf/progs/verifier_subreg.c
@@ -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";