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

bpf: test the correct stack liveness of tail calls

A new test is added: caller_stack_write_tail_call tests that the live
stack is correctly tracked for a tail call.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Martin Teichmann <martin.teichmann@xfel.eu>
Link: https://lore.kernel.org/r/20251119160355.1160932-5-martin.teichmann@xfel.eu
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Eduard Zingerman and committed by
Alexei Starovoitov
8f7cf305 e40f5a6b

+50
+50
tools/testing/selftests/bpf/progs/verifier_live_stack.c
··· 292 292 "exit;" 293 293 ::: __clobber_all); 294 294 } 295 + 296 + struct { 297 + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 298 + __uint(max_entries, 1); 299 + __type(key, __u32); 300 + __type(value, __u32); 301 + } map_array SEC(".maps"); 302 + 303 + SEC("socket") 304 + __failure __msg("invalid read from stack R2 off=-1024 size=8") 305 + __flag(BPF_F_TEST_STATE_FREQ) 306 + __naked unsigned long caller_stack_write_tail_call(void) 307 + { 308 + asm volatile ( 309 + "r6 = r1;" 310 + "*(u64 *)(r10 - 8) = -8;" 311 + "call %[bpf_get_prandom_u32];" 312 + "if r0 != 42 goto 1f;" 313 + "goto 2f;" 314 + "1:" 315 + "*(u64 *)(r10 - 8) = -1024;" 316 + "2:" 317 + "r1 = r6;" 318 + "r2 = r10;" 319 + "r2 += -8;" 320 + "call write_tail_call;" 321 + "r1 = *(u64 *)(r10 - 8);" 322 + "r2 = r10;" 323 + "r2 += r1;" 324 + "r0 = *(u64 *)(r2 + 0);" 325 + "exit;" 326 + :: __imm(bpf_get_prandom_u32) 327 + : __clobber_all); 328 + } 329 + 330 + static __used __naked unsigned long write_tail_call(void) 331 + { 332 + asm volatile ( 333 + "r6 = r2;" 334 + "r2 = %[map_array] ll;" 335 + "r3 = 0;" 336 + "call %[bpf_tail_call];" 337 + "*(u64 *)(r6 + 0) = -16;" 338 + "r0 = 0;" 339 + "exit;" 340 + : 341 + : __imm(bpf_tail_call), 342 + __imm_addr(map_array) 343 + : __clobber_all); 344 + }