summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorNuoqi Gui <gnq25@mails.tsinghua.edu.cn>2026-06-17 23:20:20 +0800
committerAlexei Starovoitov <ast@kernel.org>2026-06-22 13:39:34 -0700
commit3a354149bceacadbcf7d7b4766f5ef26a85892ab (patch)
treef70c248c54d1eb7a482354cba127a127520b2a27 /kernel
parent3d8e6fef15db07c9247c1301ec6fa5532d15feb8 (diff)
downloadlinux-next-3a354149bceacadbcf7d7b4766f5ef26a85892ab.tar.gz
linux-next-3a354149bceacadbcf7d7b4766f5ef26a85892ab.zip
bpf: Preserve pointer spill metadata during half-slot cleanup
__clean_func_state() cleans dead stack slots in 4-byte halves. When the high half of a STACK_SPILL slot is dead and the low half remains live, cleanup converts the live low half to STACK_MISC or STACK_ZERO and clears the saved spilled_ptr metadata. That conversion is safe only for scalar spills. For a pointer spill, this metadata clear lets a later 32-bit fill from the still-live half avoid the normal non-scalar register-fill check and be treated as an ordinary scalar stack read. Leave non-scalar spill slots intact in this half-live shape. This is conservative for pruning and preserves the existing check_stack_read_fixed_off() rejection path for partial fills from pointer spills. Fixes: be23266b4a08 ("bpf: 4-byte precise clean_verifier_state") Acked-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn> Link: https://lore.kernel.org/r/20260617-f01-06-half-slot-pointer-spill-v2-1-42b9cdc3cf64@mails.tsinghua.edu.cn Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/states.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/kernel/bpf/states.c b/kernel/bpf/states.c
index 32f346ce3ffc..ea2153cf28d0 100644
--- a/kernel/bpf/states.c
+++ b/kernel/bpf/states.c
@@ -436,12 +436,10 @@ static void __clean_func_state(struct bpf_verifier_env *env,
continue;
/*
- * Only destroy spilled_ptr when hi half is dead.
- * If hi half is still live with STACK_SPILL, the
- * spilled_ptr metadata is needed for correct state
- * comparison in stacksafe().
- * is_spilled_reg() is using slot_type[7], but
- * is_spilled_scalar_after() check either slot_type[0] or [4]
+ * Only scalar spills can be degraded to raw stack bytes
+ * when their high half is dead. Pointer spills need the
+ * saved spilled_ptr metadata so partial fills keep
+ * rejecting as non-scalar register fills.
*/
if (!hi_live) {
struct bpf_reg_state *spill = &st->stack[i].spilled_ptr;
@@ -449,6 +447,9 @@ static void __clean_func_state(struct bpf_verifier_env *env,
if (lo_live && stype == STACK_SPILL) {
u8 val = STACK_MISC;
+ if (spill->type != SCALAR_VALUE)
+ continue;
+
/*
* 8 byte spill of scalar 0 where half slot is dead
* should become STACK_ZERO in lo 4 bytes.