Commit 6c762611 authored by Eduard Zingerman's avatar Eduard Zingerman Committed by Alexei Starovoitov
Browse files

selftests/bpf: Test widen_imprecise_scalars() with different stack depth



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: default avatarEduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20251114025730.772723-2-eddyz87@gmail.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent b0c8e6d3
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -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);
}