]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
selftests/bpf: Add few tests for alu32 shift value tracking and zext
authorDaniel Borkmann <daniel@iogearbox.net>
Fri, 27 Mar 2026 22:06:29 +0000 (23:06 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Sun, 29 Mar 2026 16:57:39 +0000 (09:57 -0700)
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>
tools/testing/selftests/bpf/progs/verifier_subreg.c

index be328100ba531b6a0cb9294b0f043e2650131b1e..31832a306f91b1be373df37290f2967634fea824 100644 (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";