Merge branch 'bpf-fix-stack-slot-index-for-spectre-v4-nospec-checks'

Nuoqi Gui says:

====================
bpf: Fix stack slot index for Spectre v4 nospec checks

check_stack_write_fixed_off() uses one byte-indexing scheme when checking
whether a fixed-offset stack write needs Spectre v4 sanitization, and another
scheme when recording the write into slot_type[].

For sub-8-byte writes this can make the sanitization check look at bytes that
are not overwritten by the write. A zeroed lower half-slot followed by a write
to the upper half-slot can therefore miss the nospec barrier for the second
write.

Use the same stack-byte index for the sanitization check and the slot update,
and add a focused verifier selftest that expects both half-slot writes to emit
nospec through the unprivileged loader lane.

Bounded impact: this fixes verifier/JIT Spectre v4 mitigation emission for a
fixed-offset stack-write corner case. No architectural verifier memory-safety
bypass, exploit chain, CVE, embargo, or security escalation is claimed.

Fixes: 2039f26f3a ("bpf: Fix leakage due to insufficient speculative store bypass mitigation")

Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
---
Changes in v3:
- selftests/bpf: drop the stray space in the __xlated_unpriv stack-store
  expectations ("(r10 - 4)"/"(r10 - 8)" -> "(r10 -4)"/"(r10 -8)")
- Link to v2: https://lore.kernel.org/bpf/20260618-f01-11-stack-nospec-slot-index-v2-0-ede9495359b6@mails.tsinghua.edu.cn/

Changes in v2:
- drop __caps_unpriv(CAP_BPF) from the selftest
- fix selftest style
- use Fixes: 2039f26f3a per review
- Link to v1: https://lore.kernel.org/bpf/20260617-f01-11-stack-nospec-slot-index-v1-0-e3a080b0cd7e@mails.tsinghua.edu.cn/
====================

Link: https://patch.msgid.link/20260618-f01-11-stack-nospec-slot-index-v3-0-780297041721@mails.tsinghua.edu.cn
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Alexei Starovoitov 2026-06-21 17:51:58 -07:00
commit 3eb21c8691
2 changed files with 24 additions and 1 deletions

View File

@ -3479,7 +3479,8 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
bool sanitize = reg && is_spillable_regtype(reg->type);
for (i = 0; i < size; i++) {
u8 type = state->stack[spi].slot_type[i];
u8 type = state->stack[spi].slot_type[(slot - i) %
BPF_REG_SIZE];
if (type != STACK_MISC && type != STACK_ZERO) {
sanitize = true;

View File

@ -976,4 +976,26 @@ l0_%=: exit; \
: __clobber_all);
}
SEC("socket")
__description("unpriv: Spectre v4 stack write slot index")
__success __success_unpriv
__retval(0)
#ifdef SPEC_V4
__xlated_unpriv("r0 = 0")
__xlated_unpriv("*(u32 *)(r10 -4) = r0")
__xlated_unpriv("nospec")
__xlated_unpriv("*(u32 *)(r10 -8) = r0")
__xlated_unpriv("nospec")
__xlated_unpriv("exit")
#endif
__naked void stack_write_nospec_slot_index(void)
{
asm volatile (" \
r0 = 0; \
*(u32 *)(r10 - 4) = r0; \
*(u32 *)(r10 - 8) = r0; \
exit; \
" ::: __clobber_all);
}
char _license[] SEC("license") = "GPL";