__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: 2cb27158adb3 ("bpf: poison dead stack slots")
Signed-off-by: Nuoqi Gui <[email protected]>
---
 kernel/bpf/states.c | 13 +++++++------
 1 file 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.

-- 
2.34.1


Reply via email to