* [PATCH bpf-next 0/2] bpf: Preserve pointer spill metadata during half-slot cleanup
@ 2026-06-15 8:09 Nuoqi Gui
2026-06-15 8:09 ` [PATCH bpf-next 1/2] " Nuoqi Gui
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Nuoqi Gui @ 2026-06-15 8:09 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest, Nuoqi Gui
__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 <gnq25@mails.tsinghua.edu.cn>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH bpf-next 1/2] bpf: Preserve pointer spill metadata during half-slot cleanup
2026-06-15 8:09 [PATCH bpf-next 0/2] bpf: Preserve pointer spill metadata during half-slot cleanup Nuoqi Gui
@ 2026-06-15 8:09 ` Nuoqi Gui
2026-06-15 8:48 ` bot+bpf-ci
2026-06-15 17:19 ` Eduard Zingerman
2026-06-15 8:09 ` [PATCH bpf-next 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills Nuoqi Gui
2026-06-17 15:20 ` [PATCH bpf-next v2 0/2] bpf: Preserve pointer spill metadata during half-slot cleanup Nuoqi Gui
2 siblings, 2 replies; 12+ messages in thread
From: Nuoqi Gui @ 2026-06-15 8:09 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest, Nuoqi Gui
__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 <gnq25@mails.tsinghua.edu.cn>
---
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
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH bpf-next 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills
2026-06-15 8:09 [PATCH bpf-next 0/2] bpf: Preserve pointer spill metadata during half-slot cleanup Nuoqi Gui
2026-06-15 8:09 ` [PATCH bpf-next 1/2] " Nuoqi Gui
@ 2026-06-15 8:09 ` Nuoqi Gui
2026-06-15 17:19 ` Eduard Zingerman
2026-06-17 15:20 ` [PATCH bpf-next v2 0/2] bpf: Preserve pointer spill metadata during half-slot cleanup Nuoqi Gui
2 siblings, 1 reply; 12+ messages in thread
From: Nuoqi Gui @ 2026-06-15 8:09 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest, Nuoqi Gui
Add a verifier regression test for a pointer spill whose high half is
cleaned dead while the low half remains live. Force checkpoint creation
with BPF_F_TEST_STATE_FREQ and assert the verifier log reaches the
checkpoint and the subsequent 32-bit fill before rejecting the partial fill
from a non-scalar spill.
Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
---
.../testing/selftests/bpf/progs/verifier_spill_fill.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
index 6bc721accbae..0174887e28f5 100644
--- a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
+++ b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
@@ -1359,4 +1359,22 @@ __naked void var_off_write_over_scalar_spill(void)
: __clobber_all);
}
+SEC("socket")
+__description("partial fill from cleaned pointer spill")
+__failure
+__log_level(2)
+__msg("1: (05) goto pc+0")
+__msg("2: (61) r0 = *(u32 *)(r10 -4)")
+__msg("invalid size of register fill")
+__flag(BPF_F_TEST_STATE_FREQ)
+__naked void partial_fill_from_cleaned_pointer_spill(void)
+{
+ /* Spill R1(ctx), then force a checkpoint and half-slot cleanup. */
+ asm volatile ("*(u64 *)(r10 - 8) = r1;"
+ "goto +0;"
+ "r0 = *(u32 *)(r10 - 4);"
+ "exit;"
+ ::: __clobber_all);
+}
+
char _license[] SEC("license") = "GPL";
--
2.34.1
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: Preserve pointer spill metadata during half-slot cleanup
2026-06-15 8:09 ` [PATCH bpf-next 1/2] " Nuoqi Gui
@ 2026-06-15 8:48 ` bot+bpf-ci
2026-06-15 9:17 ` Nuoqi Gui
2026-06-15 17:19 ` Eduard Zingerman
1 sibling, 1 reply; 12+ messages in thread
From: bot+bpf-ci @ 2026-06-15 8:48 UTC (permalink / raw)
To: gnq25, ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, shuah
Cc: bpf, linux-kernel, linux-kselftest, gnq25, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1991 bytes --]
> 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: 2cb27158adb3 ("bpf: poison dead stack slots")
> Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
Is the Fixes: tag pointing at the right commit?
The commit referenced, 2cb27158adb3 ("bpf: poison dead stack slots"), adds
STACK_POISON handling in kernel/bpf/verifier.c and does not contain the
half-slot cleanup logic being corrected here.
The 4-byte half-slot cleanup in __clean_func_state() that downgrades a
still-live STACK_SPILL low half to STACK_MISC/STACK_ZERO and clears the
saved spilled_ptr metadata without checking for SCALAR_VALUE was introduced
by be23266b4a08 ("bpf: 4-byte precise clean_verifier_state"). That commit
added the lo_live/hi_live model and the exact block this patch corrects:
if (lo_live && stype == STACK_SPILL) {
be23266b4a08 predates both 2cb27158adb3 and this fix. Should the tag be:
Fixes: be23266b4a08 ("bpf: 4-byte precise clean_verifier_state")
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/27533304560
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Re: [PATCH bpf-next 1/2] bpf: Preserve pointer spill metadata during half-slot cleanup
2026-06-15 8:48 ` bot+bpf-ci
@ 2026-06-15 9:17 ` Nuoqi Gui
0 siblings, 0 replies; 12+ messages in thread
From: Nuoqi Gui @ 2026-06-15 9:17 UTC (permalink / raw)
To: bot+bpf-ci
Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, shuah, bpf, linux-kernel,
linux-kselftest, martin.lau, clm, ihor.solodrai
> -----Original Messages-----
> From: bot+bpf-ci@kernel.org
> Send time:Monday, 15/06/2026 16:48:49
> To: gnq25@mails.tsinghua.edu.cn, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, eddyz87@gmail.com, memxor@gmail.com, martin.lau@linux.dev, song@kernel.org, yonghong.song@linux.dev, jolsa@kernel.org, emil@etsalapatis.com, shuah@kernel.org
> Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, gnq25@mails.tsinghua.edu.cn, ast@kernel.org, andrii@kernel.org, daniel@iogearbox.net, martin.lau@kernel.org, eddyz87@gmail.com, yonghong.song@linux.dev, clm@meta.com, ihor.solodrai@linux.dev
> Subject: Re: [PATCH bpf-next 1/2] bpf: Preserve pointer spill metadata during half-slot cleanup
>
> > 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: 2cb27158adb3 ("bpf: poison dead stack slots")
> > Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
>
> Is the Fixes: tag pointing at the right commit?
>
> The commit referenced, 2cb27158adb3 ("bpf: poison dead stack slots"), adds
> STACK_POISON handling in kernel/bpf/verifier.c and does not contain the
> half-slot cleanup logic being corrected here.
>
> The 4-byte half-slot cleanup in __clean_func_state() that downgrades a
> still-live STACK_SPILL low half to STACK_MISC/STACK_ZERO and clears the
> saved spilled_ptr metadata without checking for SCALAR_VALUE was introduced
> by be23266b4a08 ("bpf: 4-byte precise clean_verifier_state"). That commit
> added the lo_live/hi_live model and the exact block this patch corrects:
>
> if (lo_live && stype == STACK_SPILL) {
>
> be23266b4a08 predates both 2cb27158adb3 and this fix. Should the tag be:
>
> Fixes: be23266b4a08 ("bpf: 4-byte precise clean_verifier_state")
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/27533304560
Yes, be23266b4a08 is the right Fixes target.
The bug is in the half-slot cleanup logic introduced by that commit:
when the high half is dead and the low half remains live, it can downgrade
the still-live STACK_SPILL bytes to STACK_MISC/STACK_ZERO and clear the
spilled_ptr metadata.
2cb27158adb3 only changed the dead-slot marker to STACK_POISON and did not
introduce that half-slot spill cleanup behavior.
I will update the tag to:
Fixes: be23266b4a08 ("bpf: 4-byte precise clean_verifier_state")
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: Preserve pointer spill metadata during half-slot cleanup
2026-06-15 8:09 ` [PATCH bpf-next 1/2] " Nuoqi Gui
2026-06-15 8:48 ` bot+bpf-ci
@ 2026-06-15 17:19 ` Eduard Zingerman
1 sibling, 0 replies; 12+ messages in thread
From: Eduard Zingerman @ 2026-06-15 17:19 UTC (permalink / raw)
To: Nuoqi Gui, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu,
Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest
On Mon, 2026-06-15 at 16:09 +0800, Nuoqi Gui wrote:
> __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 <gnq25@mails.tsinghua.edu.cn>
> ---
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
[...]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH bpf-next 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills
2026-06-15 8:09 ` [PATCH bpf-next 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills Nuoqi Gui
@ 2026-06-15 17:19 ` Eduard Zingerman
0 siblings, 0 replies; 12+ messages in thread
From: Eduard Zingerman @ 2026-06-15 17:19 UTC (permalink / raw)
To: Nuoqi Gui, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu,
Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest
On Mon, 2026-06-15 at 16:09 +0800, Nuoqi Gui wrote:
> Add a verifier regression test for a pointer spill whose high half is
> cleaned dead while the low half remains live. Force checkpoint creation
> with BPF_F_TEST_STATE_FREQ and assert the verifier log reaches the
> checkpoint and the subsequent 32-bit fill before rejecting the partial fill
> from a non-scalar spill.
>
> Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
> ---
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
[...]
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH bpf-next v2 0/2] bpf: Preserve pointer spill metadata during half-slot cleanup
2026-06-15 8:09 [PATCH bpf-next 0/2] bpf: Preserve pointer spill metadata during half-slot cleanup Nuoqi Gui
2026-06-15 8:09 ` [PATCH bpf-next 1/2] " Nuoqi Gui
2026-06-15 8:09 ` [PATCH bpf-next 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills Nuoqi Gui
@ 2026-06-17 15:20 ` Nuoqi Gui
2026-06-17 15:20 ` [PATCH bpf-next v2 1/2] " Nuoqi Gui
2026-06-17 15:20 ` [PATCH bpf-next v2 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills Nuoqi Gui
2 siblings, 2 replies; 12+ messages in thread
From: Nuoqi Gui @ 2026-06-17 15:20 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest, Nuoqi Gui
__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`.
v1->v2:
- Correct the Fixes tag to be23266b4a08 ("bpf: 4-byte precise
clean_verifier_state")
Link to v1: https://patch.msgid.link/20260615-f01-06-half-slot-pointer-spill-v1-0-47f1c18a8965@mails.tsinghua.edu.cn
---
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: 20260617-f01-06-half-slot-pointer-spill-a4a81eeab2cb
Best regards,
--
Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH bpf-next v2 1/2] bpf: Preserve pointer spill metadata during half-slot cleanup
2026-06-17 15:20 ` [PATCH bpf-next v2 0/2] bpf: Preserve pointer spill metadata during half-slot cleanup Nuoqi Gui
@ 2026-06-17 15:20 ` Nuoqi Gui
2026-06-22 21:10 ` patchwork-bot+netdevbpf
2026-06-17 15:20 ` [PATCH bpf-next v2 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills Nuoqi Gui
1 sibling, 1 reply; 12+ messages in thread
From: Nuoqi Gui @ 2026-06-17 15:20 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest, Nuoqi Gui
__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>
---
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
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH bpf-next v2 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills
2026-06-17 15:20 ` [PATCH bpf-next v2 0/2] bpf: Preserve pointer spill metadata during half-slot cleanup Nuoqi Gui
2026-06-17 15:20 ` [PATCH bpf-next v2 1/2] " Nuoqi Gui
@ 2026-06-17 15:20 ` Nuoqi Gui
2026-06-17 16:02 ` bot+bpf-ci
1 sibling, 1 reply; 12+ messages in thread
From: Nuoqi Gui @ 2026-06-17 15:20 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan
Cc: bpf, linux-kernel, linux-kselftest, Nuoqi Gui
Add a verifier regression test for a pointer spill whose high half is
cleaned dead while the low half remains live. Force checkpoint creation
with BPF_F_TEST_STATE_FREQ and assert the verifier log reaches the
checkpoint and the subsequent 32-bit fill before rejecting the partial fill
from a non-scalar spill.
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
---
.../testing/selftests/bpf/progs/verifier_spill_fill.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
index 6bc721accbae..0174887e28f5 100644
--- a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
+++ b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
@@ -1359,4 +1359,22 @@ __naked void var_off_write_over_scalar_spill(void)
: __clobber_all);
}
+SEC("socket")
+__description("partial fill from cleaned pointer spill")
+__failure
+__log_level(2)
+__msg("1: (05) goto pc+0")
+__msg("2: (61) r0 = *(u32 *)(r10 -4)")
+__msg("invalid size of register fill")
+__flag(BPF_F_TEST_STATE_FREQ)
+__naked void partial_fill_from_cleaned_pointer_spill(void)
+{
+ /* Spill R1(ctx), then force a checkpoint and half-slot cleanup. */
+ asm volatile ("*(u64 *)(r10 - 8) = r1;"
+ "goto +0;"
+ "r0 = *(u32 *)(r10 - 4);"
+ "exit;"
+ ::: __clobber_all);
+}
+
char _license[] SEC("license") = "GPL";
--
2.34.1
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH bpf-next v2 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills
2026-06-17 15:20 ` [PATCH bpf-next v2 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills Nuoqi Gui
@ 2026-06-17 16:02 ` bot+bpf-ci
0 siblings, 0 replies; 12+ messages in thread
From: bot+bpf-ci @ 2026-06-17 16:02 UTC (permalink / raw)
To: gnq25, ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, shuah
Cc: bpf, linux-kernel, linux-kselftest, gnq25, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1307 bytes --]
> selftests/bpf: Cover half-slot cleanup of pointer spills
>
> Add a verifier regression test for a pointer spill whose high half is
> cleaned dead while the low half remains live. Force checkpoint creation
> with BPF_F_TEST_STATE_FREQ and assert the verifier log reaches the
> checkpoint and the subsequent 32-bit fill before rejecting the partial fill
> from a non-scalar spill.
>
> Acked-by: Eduard Zingerman <eddyz87@gmail.com>
> Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
This is a regression test for a verifier bug where a partial 32-bit fill
from a pointer spill whose high half was cleaned dead could read a
non-scalar stack slot past the register-fill check.
The half-slot cleanup that destroys the spilled_ptr metadata when the hi
half is dead was introduced in __clean_func_state() by:
be23266b4a08 ("bpf: 4-byte precise clean_verifier_state")
Should this test carry a Fixes: tag pointing at that commit, matching the
accompanying fix?
Fixes: be23266b4a08 ("bpf: 4-byte precise clean_verifier_state")
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/27700639579
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH bpf-next v2 1/2] bpf: Preserve pointer spill metadata during half-slot cleanup
2026-06-17 15:20 ` [PATCH bpf-next v2 1/2] " Nuoqi Gui
@ 2026-06-22 21:10 ` patchwork-bot+netdevbpf
0 siblings, 0 replies; 12+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-06-22 21:10 UTC (permalink / raw)
To: Nuoqi Gui
Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, shuah, bpf, linux-kernel,
linux-kselftest
Hello:
This series was applied to bpf/bpf.git (master)
by Alexei Starovoitov <ast@kernel.org>:
On Wed, 17 Jun 2026 23:20:20 +0800 you wrote:
> __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.
>
> [...]
Here is the summary with links:
- [bpf-next,v2,1/2] bpf: Preserve pointer spill metadata during half-slot cleanup
https://git.kernel.org/bpf/bpf/c/3a354149bcea
- [bpf-next,v2,2/2] selftests/bpf: Cover half-slot cleanup of pointer spills
https://git.kernel.org/bpf/bpf/c/8816d94303f0
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-06-22 21:10 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-15 8:09 [PATCH bpf-next 0/2] bpf: Preserve pointer spill metadata during half-slot cleanup Nuoqi Gui
2026-06-15 8:09 ` [PATCH bpf-next 1/2] " Nuoqi Gui
2026-06-15 8:48 ` bot+bpf-ci
2026-06-15 9:17 ` Nuoqi Gui
2026-06-15 17:19 ` Eduard Zingerman
2026-06-15 8:09 ` [PATCH bpf-next 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills Nuoqi Gui
2026-06-15 17:19 ` Eduard Zingerman
2026-06-17 15:20 ` [PATCH bpf-next v2 0/2] bpf: Preserve pointer spill metadata during half-slot cleanup Nuoqi Gui
2026-06-17 15:20 ` [PATCH bpf-next v2 1/2] " Nuoqi Gui
2026-06-22 21:10 ` patchwork-bot+netdevbpf
2026-06-17 15:20 ` [PATCH bpf-next v2 2/2] selftests/bpf: Cover half-slot cleanup of pointer spills Nuoqi Gui
2026-06-17 16:02 ` bot+bpf-ci
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox