selftests/bpf: Add a test case for 32-bit spill tracking
authorMaxim Mikityanskiy <maxim@isovalent.com>
Mon, 8 Jan 2024 20:51:59 +0000 (22:51 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 23 Jan 2024 22:40:22 +0000 (14:40 -0800)
When a range check is performed on a register that was 32-bit spilled to
the stack, the IDs of the two instances of the register are the same, so
the range should also be the same.

Signed-off-by: Maxim Mikityanskiy <maxim@isovalent.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20240108205209.838365-6-maxtram95@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/progs/verifier_spill_fill.c

index 848f2930f599d29c4fec4ab0793bfd4a3af19f99..f303ac19cf410065bde3c6ffee3c12555c87ce27 100644 (file)
@@ -735,4 +735,35 @@ __naked void stack_load_preserves_const_precision_subreg(void)
        : __clobber_common);
 }
 
+SEC("xdp")
+__description("32-bit spilled reg range should be tracked")
+__success __retval(0)
+__naked void spill_32bit_range_track(void)
+{
+       asm volatile("                                  \
+       call %[bpf_ktime_get_ns];                       \
+       /* Make r0 bounded. */                          \
+       r0 &= 65535;                                    \
+       /* Assign an ID to r0. */                       \
+       r1 = r0;                                        \
+       /* 32-bit spill r0 to stack. */                 \
+       *(u32*)(r10 - 8) = r0;                          \
+       /* Boundary check on r0. */                     \
+       if r0 < 1 goto l0_%=;                           \
+       /* 32-bit fill r1 from stack. */                \
+       r1 = *(u32*)(r10 - 8);                          \
+       /* r1 == r0 => r1 >= 1 always. */               \
+       if r1 >= 1 goto l0_%=;                          \
+       /* Dead branch: the verifier should prune it.   \
+        * Do an invalid memory access if the verifier  \
+        * follows it.                                  \
+        */                                             \
+       r0 = *(u64*)(r9 + 0);                           \
+l0_%=: r0 = 0;                                         \
+       exit;                                           \
+"      :
+       : __imm(bpf_ktime_get_ns)
+       : __clobber_all);
+}
+
 char _license[] SEC("license") = "GPL";