data built 2026-10-19T13:16:53Z

Look up another CVE · open CVE-2026-93127 in the interactive tracker

CVE-2026-93127

bpf: Drop scalar id on sign-extending narrowing stack fills

7.8 EPSS 0.2% AV:L

Published 2026-09-17 (31 days ago) by the Linux kernel CNA. Subsystem kernel/bpf. Debian urgency: unimportant.

What to do, per Debian release

Debian's own status for CVE-2026-93127 in every release this site tracks, and what each one means in practice. Every status below is the one the Debian Security Team publishes for this CVE. source

ReleaseStatus VersionWhat this means
Debian 12bookwormnot affected6.1.190-1Nothing to do. bookworm never shipped the vulnerable code.
Debian 13trixienot affected6.12.113-1Nothing to do. trixie never shipped the vulnerable code.
Debian 14forkyfixed7.2.6-1Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts.
Debian unstablesidfixed7.2.6-1Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts.

The vulnerability

What the bug is

When a spilled scalar is filled back with a sign-extending narrowing load (BPF_MEMSX), check_stack_read_fixed_off() copies the spilled register including its scalar id, but coerce_reg_to_size_sx() then sign-extends the filled register's value. If the same slot is also filled with a plain zero-extending load (BPF_MEM), both destination registers share the id yet hold different values. A later 'if <zext-reg> == const' then refines the sign-extended register through sync_linked_regs() to a value it does not have at runtime (e.g. the verifier believes 0x80000000 while the register is 0xffffffff80000000), which can be turned into an out-of-bounds access. Drop the shared scalar id at the sign-extension site in check_mem_access() when sign extension actually changes the value, mirroring the BPF_MOVSX handling in check_alu_op() (no_sext = reg_umax < 2^(size*8-1)).

Where it lives

The fix touches these files. If the subsystem is one you do not use, the practical exposure is lower, though the package is still the vulnerable one.

kernel/bpf/verifier.c

What this is
BPF [CORE]MAINTAINERS section matched on kernel/bpf/verifier.c · bpf@vger.kernel.org · Maintained

Check it on the machine

grep -wE 'CONFIG_BPF|CONFIG_BPF_SYSCALL' /boot/config-$(uname -r)

Reads the booted kernel's own configuration, on the machine and nowhere else. =y is built in, =m is a module, and an is not set line means the code is not there.

Show whether Debian builds this, per release

Debian builds this code. Every release below compiles the affected file into the kernels it ships.

  • bookworm, trixie, forky, sidy
y
built into the kernel image on every flavour - only a patch removes it
Build switches
CONFIG_BPF, CONFIG_BPF_SYSCALL
Reads as
all on means the file is compiled; any one off means it is not.

From the configuration Debian publishes for every kernel flavour it builds. It covers only the architectures Debian ships a linux-config package for, and nothing about a kernel you built yourself. Debian's own status above stays authoritative about the source package.MAINTAINERS kbuild Makefiles Debian linux-config packages

Signals

Published
2026-09-17 (31 days ago)source
CVSS
7.8 high
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:Hsource recompute it
Attack vector
local (AV:L)source
EPSS
0.17%, higher than 5.3% of all CVEssource
CISA KEV
not listedthe KEV catalogue
Debian urgency
unimportantsource
Subsystem
kernel/bpf

Upstream fixes

The versions the CNA records as introducing and fixing this, and the commit for each. source

IntroducedFixed inCommit
7.07.2.6f3614622dc41
7.07.32cb5f4ca695e

Why the CNA scored it this way

Quoted from the kernel CNA's own scoring file, word for word. A highlighted metric carries the most severe value CVSS v3.1 defines for it, which is what pushes the score up. source

AV:LAttack vector, local
The attacker-controlled input is BPF bytecode supplied via bpf(BPF_PROG_LOAD) in SYSCALL_DEFINE5(bpf) → bpf_prog_load() → bpf_check() → do_check_insn(); the bug fires on local BPF_LDX BPF_MEMSX/BPF_MEM stack fills in check_mem_access(), not on a remote protocol message.
AC:LAttack complexity, low
The attacker writes the instruction sequence; ldsx_fill_scalar_id_not_shared deterministically spills a u32 with bit 31 set, fills it with *(s32*) into r4 and *(u32*) into r5, then uses if r5 == 0x80000000 so sync_linked_regs() poisons r4, with no race or external state.
PR:LPrivileges required, low
check_stack_write_fixed_off()/check_stack_read_fixed_off() only preserve spilled scalar ids when env->bpf_capable, set from bpf_token_capable(CAP_BPF) in bpf_check(); unprivileged socket-filter loads therefore miss this path. CAP_BPF is delegable into a user namespace via bpf_token_create(), so this is Low, not init-namespace root.
UI:NUser interaction, none
The attacker loads the crafted program with bpf(BPF_PROG_LOAD), creates the hash map, and triggers bpf_map_lookup_elem plus the MEMSX/MEM fills themselves; no other user must mount media, open a file, or otherwise act.
S:UScope, unchanged
The confused r4 offset is applied to a PTR_TO_MAP_VALUE from bpf_map_lookup_elem() and corrupts host kernel heap in the same security authority; this is a verifier-bypass local privilege escalation, not a KVM/IOMMU guest-to-host crossing.
C:HConfidentiality impact, high
After sync_linked_regs() copies known 0x80000000 onto the sign-extended r4 (runtime 0xffffffff80000000), r4 >>= 63 is believed 0 but is 1, so r0 += r4; *(u8*)(r0+7) on the 8-byte map value is an accepted out-of-bounds kernel read; repeating r0 += r4 yields an arbitrary-length read primitive.
I:HIntegrity impact, high
The same false r4==0 bound lets the verifier accept a store through that map-value pointer (replace the *(u8*)(r0+7) load with a store); repeating r0 += r4 before the store is an arbitrary kernel heap write usable for control-flow hijacking.
A:HAvailability impact, high
The accepted program performs an out-of-bounds access on the bpf_map_lookup_elem() result (the selftest is rejected after the fix with "R0 max value is outside of the allowed memory range"); that heap OOB can oops or panic the kernel.