selftests/bpf: half-dead scalar zero stack spill test

A test case demonstrating unsafe pruning when spill of a scalar zero
spilled on a first pass in replaced by STACK_ZERO in the
__clean_func_state().

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260827-bug-011-cleanfunc-stack-zero-simple-v1-v1-2-c0e996589a52@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Eduard Zingerman 2026-08-27 15:48:24 -07:00 committed by Alexei Starovoitov
parent 2f3536bff8
commit c6ff14f1cd

View File

@ -1403,6 +1403,46 @@ __naked void partial_fill_from_cleaned_pointer_spill(void)
::: __clobber_all);
}
SEC("raw_tp")
__failure
__msg("access may be outside object bounds")
__flag(BPF_F_TEST_STATE_FREQ)
__naked void imprecise_scalar_spill_half_dead(void)
{
asm volatile (
/*
* Fork two paths: the one explored first spills an imprecise zero,
* the one explored second, an imprecise non-zero scalar.
*/
"call %[bpf_get_prandom_u32];"
"if r0 > 42 goto 1f;"
"r6 = 0;"
"goto 2f;"
"1:"
/* causes out of bounds access on a second path. */
"r6 = 100500;"
"2:"
/* Force a checkpoint before the spill. */
"goto +0;"
"*(u64 *)(r10 - 8) = r6;"
/*
* Force stack cleanup, only the low half of the spill is alive,
* so the dead high half is degraded to raw stack bytes.
* Buggy verifier converted it to STACK_ZERO w/o proper precision propagation.
*/
"goto +0;"
"r7 = *(u32 *)(r10 - 4);"
/* Use r7 as an offset into a one-byte buffer. */
"r1 = %[single_byte_buf] ll;"
"r1 += r7;"
"r0 = *(u8 *)(r1 + 0);"
"exit;"
:
: __imm(bpf_get_prandom_u32),
__imm_addr(single_byte_buf)
: __clobber_all);
}
/* check valid spill/fill, ptr to tp buffer */
SEC("raw_tracepoint.w")
__success