Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: 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>

authored by

Eduard Zingerman and committed by
Alexei Starovoitov
6c762611 b0c8e6d3

+53
+53
tools/testing/selftests/bpf/progs/iters_looping.c
··· 161 161 162 162 return 0; 163 163 } 164 + 165 + __used 166 + static void iterator_with_diff_stack_depth(int x) 167 + { 168 + struct bpf_iter_num iter; 169 + 170 + asm volatile ( 171 + "if r1 == 42 goto 0f;" 172 + "*(u64 *)(r10 - 128) = 0;" 173 + "0:" 174 + /* create iterator */ 175 + "r1 = %[iter];" 176 + "r2 = 0;" 177 + "r3 = 10;" 178 + "call %[bpf_iter_num_new];" 179 + "1:" 180 + /* consume next item */ 181 + "r1 = %[iter];" 182 + "call %[bpf_iter_num_next];" 183 + "if r0 == 0 goto 2f;" 184 + "goto 1b;" 185 + "2:" 186 + /* destroy iterator */ 187 + "r1 = %[iter];" 188 + "call %[bpf_iter_num_destroy];" 189 + : 190 + : __imm_ptr(iter), ITER_HELPERS 191 + : __clobber_common, "r6" 192 + ); 193 + } 194 + 195 + SEC("socket") 196 + __success 197 + __naked int widening_stack_size_bug(void *ctx) 198 + { 199 + /* 200 + * Depending on iterator_with_diff_stack_depth() parameter value, 201 + * subprogram stack depth is either 8 or 128 bytes. Arrange values so 202 + * that it is 128 on a first call and 8 on a second. This triggered a 203 + * bug in verifier's widen_imprecise_scalars() logic. 204 + */ 205 + asm volatile ( 206 + "r6 = 0;" 207 + "r1 = 0;" 208 + "1:" 209 + "call iterator_with_diff_stack_depth;" 210 + "r1 = 42;" 211 + "r6 += 1;" 212 + "if r6 < 2 goto 1b;" 213 + "r0 = 0;" 214 + "exit;" 215 + ::: __clobber_all); 216 + }