]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests/bpf: Test variable length stack write
authorAlexei Starovoitov <ast@kernel.org>
Tue, 24 Mar 2026 21:59:37 +0000 (14:59 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 25 Mar 2026 00:00:16 +0000 (17:00 -0700)
Add a test to make sure that variable length stack writes
scrubs STACK_SPILL into STACK_MISC.

Tested-by: Eduard Zingerman <eddyz87@gmail.com>
Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260324215938.81733-2-alexei.starovoitov@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/progs/verifier_spill_fill.c

index a2b6d99628da007f0f7f7c1b8be44ddf2ba589be..672e4446181efe8f437c9ec02400ddbadd160b3d 100644 (file)
@@ -1316,4 +1316,45 @@ __naked void old_imprecise_scalar32_vs_cur_stack_misc(void)
        : __clobber_all);
 }
 
+SEC("raw_tp")
+__success
+__naked void var_off_write_over_scalar_spill(void)
+{
+       asm volatile (
+       /* Get an unknown value bounded to {0, 4} */
+       "call %[bpf_ktime_get_ns];"
+       "r6 = r0;"
+       "r6 &= 4;"
+
+       /* Spill a scalar to fp-16 */
+       "r7 = 0xdeadbeef00000000 ll;"
+       "*(u64 *)(r10 - 16) = r7;"
+
+       /*
+        * Variable-offset 4-byte write covering [fp-12, fp-4).
+        * This touches stype[3..0] of the spill slot at fp-16 but
+        * leaves stype[7..4] as STACK_SPILL. check_stack_write_var_off()
+        * must scrub the entire slot when setting spilled_ptr to NOT_INIT,
+        * otherwise a subsequent sub-register fill sees a non-scalar
+        * spilled_ptr and is rejected.
+        */
+       "r8 = r10;"
+       "r8 += r6;"
+       "r8 += -12;"
+       "r9 = 0;"
+       "*(u32 *)(r8 + 0) = r9;"
+
+       /*
+        * 4-byte read from fp-16. Without the fix this fails with
+        * "invalid size of register fill" because is_spilled_reg()
+        * sees STACK_SPILL while spilled_ptr.type == NOT_INIT.
+        */
+       "r0 = *(u32 *)(r10 - 16);"
+       "r0 = 0;"
+       "exit;"
+       :
+       : __imm(bpf_ktime_get_ns)
+       : __clobber_all);
+}
+
 char _license[] SEC("license") = "GPL";