public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
* [PATH bpf-next] selftests/bpf: Add few tests for alu32 shift value tracking and zext
@ 2026-03-27 22:06 Daniel Borkmann
  2026-03-29 17:00 ` patchwork-bot+netdevbpf
  0 siblings, 1 reply; 2+ messages in thread
From: Daniel Borkmann @ 2026-03-27 22:06 UTC (permalink / raw)
  To: bpf; +Cc: ast, rivastava0

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>
---
 .../selftests/bpf/progs/verifier_subreg.c     | 165 ++++++++++++++++++
 1 file changed, 165 insertions(+)

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";
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-03-29 17:00 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-27 22:06 [PATH bpf-next] selftests/bpf: Add few tests for alu32 shift value tracking and zext Daniel Borkmann
2026-03-29 17:00 ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox