summaryrefslogtreecommitdiff
path: root/tools/testing
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2026-03-25 00:59:37 +0300
committerAlexei Starovoitov <ast@kernel.org>2026-03-25 03:00:16 +0300
commit9f7d8fa6817e2709846fc7f5c9f60254e536d138 (patch)
tree3129f7066d12b5589503281d168d05da3a40e05e /tools/testing
parent4639eb9e30ab10c7935c7c19e872facf9a94713f (diff)
downloadlinux-9f7d8fa6817e2709846fc7f5c9f60254e536d138.tar.xz
selftests/bpf: Test variable length stack write
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>
Diffstat (limited to 'tools/testing')
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_spill_fill.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
index a2b6d99628da..672e4446181e 100644
--- a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
+++ b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
@@ -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";