__clean_func_state() cleans stack liveness in 4-byte halves. When the high
half of a spilled register slot is dead but the low half remains live, it can
currently degrade the low half of any STACK_SPILL to raw stack bytes and clear
the saved spilled_ptr metadata.

That is safe for scalar spills, but not for non-scalar pointer spills. A later
partial 32-bit fill from the remaining live half can otherwise avoid the normal
non-scalar spill rejection.

Keep pointer spill provenance intact for that half-live case and add a verifier
regression test for the reported shape.

Validation:

- A raw `bpf(BPF_PROG_LOAD)` reproducer exercises the half-slot cleanup case by
  spilling `r1` as a pointer, executing `goto +0`, and then doing a 32-bit fill
  from `fp-4`.
- Unpatched `bpf-next` at 7bfb93e3475be9de894f1cecd3a727d3e1649b03:
  selftest FAIL as expected because the verifier accepts the partial
  pointer-spill fill.
- Patched with this series: PASS because the verifier rejects the same load at
  `r0 = *(u32 *)(r10 -4)` with `invalid size of register fill`.

---
Nuoqi Gui (2):
      bpf: Preserve pointer spill metadata during half-slot cleanup
      selftests/bpf: Cover half-slot cleanup of pointer spills

 kernel/bpf/states.c                                    | 13 +++++++------
 .../testing/selftests/bpf/progs/verifier_spill_fill.c  | 18 ++++++++++++++++++
 2 files changed, 25 insertions(+), 6 deletions(-)
---
base-commit: 7bfb93e3475be9de894f1cecd3a727d3e1649b03
change-id: 20260615-f01-06-half-slot-pointer-spill-e4bd2665c532

Best regards,
--  
Nuoqi Gui <[email protected]>


Reply via email to