]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests/bpf: Test widen_imprecise_scalars() with different stack depth
authorEduard Zingerman <eddyz87@gmail.com>
Fri, 14 Nov 2025 02:57:30 +0000 (18:57 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 14 Nov 2025 17:26:28 +0000 (09:26 -0800)
A test case for a situation when widen_imprecise_scalars() is called
with old->allocated_stack > cur->allocated_stack. Test structure:

    def widening_stack_size_bug():
      r1 = 0
      for r6 in 0..1:
        iterator_with_diff_stack_depth(r1)
        r1 = 42

    def iterator_with_diff_stack_depth(r1):
      if r1 != 42:
        use 128 bytes of stack
      iterator based loop

iterator_with_diff_stack_depth() is verified with r1 == 0 first and
r1 == 42 next. Causing stack usage of 128 bytes on a first visit and 8
bytes on a second. Such arrangement triggered a KASAN error in
widen_imprecise_scalars().

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20251114025730.772723-2-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/progs/iters_looping.c

index 05fa5ce7fc594c38bbc253af51809375e0b46dc4..d00fd570255a99087d4332b7fc1eaa136f2bc37e 100644 (file)
@@ -161,3 +161,56 @@ int simplest_loop(void *ctx)
 
        return 0;
 }
+
+__used
+static void iterator_with_diff_stack_depth(int x)
+{
+       struct bpf_iter_num iter;
+
+       asm volatile (
+               "if r1 == 42 goto 0f;"
+               "*(u64 *)(r10 - 128) = 0;"
+       "0:"
+               /* create iterator */
+               "r1 = %[iter];"
+               "r2 = 0;"
+               "r3 = 10;"
+               "call %[bpf_iter_num_new];"
+       "1:"
+               /* consume next item */
+               "r1 = %[iter];"
+               "call %[bpf_iter_num_next];"
+               "if r0 == 0 goto 2f;"
+               "goto 1b;"
+       "2:"
+               /* destroy iterator */
+               "r1 = %[iter];"
+               "call %[bpf_iter_num_destroy];"
+               :
+               : __imm_ptr(iter), ITER_HELPERS
+               : __clobber_common, "r6"
+       );
+}
+
+SEC("socket")
+__success
+__naked int widening_stack_size_bug(void *ctx)
+{
+       /*
+        * Depending on iterator_with_diff_stack_depth() parameter value,
+        * subprogram stack depth is either 8 or 128 bytes. Arrange values so
+        * that it is 128 on a first call and 8 on a second. This triggered a
+        * bug in verifier's widen_imprecise_scalars() logic.
+        */
+       asm volatile (
+               "r6 = 0;"
+               "r1 = 0;"
+       "1:"
+               "call iterator_with_diff_stack_depth;"
+               "r1 = 42;"
+               "r6 += 1;"
+               "if r6 < 2 goto 1b;"
+               "r0 = 0;"
+               "exit;"
+               ::: __clobber_all);
+}