CVE-2026-90269
NoneCVSS
—
EPSS
0.2%
Published
Sep 17, 2026
CISA due date
—
Cloudanix analysis
A flaw in the Linux kernel's eBPF handling can let certain programs crash the whole computer instead of safely dealing with bad memory access.
- Exploitation
- Local Privilege
- Attacker needs
- Low Privilege
- Complexity
- Moderate
- Impact
- Denial Of Service
- Component
- OS kernel
- Class
- Memory Corruption
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
The verifier fails to rewrite BPF_LOAD_ACQ instructions on certain untrusted pointer types (PTR_TO_BTF_ID, PTR_TO_BTF_ID|PTR_UNTRUSTED, etc.) into BPF_PROBE_MEM, so the JIT emits an unprotected load that triggers an unhandled page fault and kernel panic.
Why it matters to the business
Systems running affected kernels may experience unexpected crashes when eBPF programs that use load-acquire on pointers derived from task_struct or similar structures are loaded or executed, disrupting services and requiring reboots.
How an attack unfolds
An attacker loads a BPF program (for example attached to a tracepoint) that obtains an untrusted pointer such as next->mm and then performs a load_acquire on a field inside it; the missing fault-protection rewrite causes the load to fault without an exception-table entry, panicking the kernel.
How to fix it
Apply the upstream kernel commit that adds the BPF_LOAD_ACQ source-pointer check in the verifier; rebuild and deploy the patched kernel across all affected systems.
How to confirm the fix worked
Confirm the verifier now rejects BPF_LOAD_ACQ on the listed pointer types by attempting to load the reproducer program; verify the patch appears in the running kernel source or via kernel version strings after update.
Typical attack path
- Craft a BPF program that dereferences an untrusted pointer (e.g., task_struct->mm) with BPF_LOAD_ACQ
- Attach the program to a tracepoint or other hook reachable by the attacker
- Trigger program execution to induce the unprotected load and kernel fault
How to detect it
Search kernel logs and panic dumps for oops traces containing BPF instruction sequences or references to load-acquire operations on task_struct-derived pointers; correlate with recent BPF program loads via audit logs.
What your security team should do
- Prioritize kernel updates on systems that permit unprivileged BPF loading
- Temporarily disable unprivileged BPF via sysctl where eBPF is not required
- Monitor kernel oops/panic logs for BPF-related faults until patches are applied
The record
In the Linux kernel, the following vulnerability has been resolved: bpf: Reject load-acquire from pointers requiring fault protection A BPF_LOAD_ACQ is not rewritten to a BPF_PROBE_MEM load by the verifier, unlike a regular BPF_LDX, so the JIT emits a plain load with no exception table entry and a fault panics the kernel instead of being handled. Reject the source pointer types that a BPF_LDX would have had that fault protection applied to, i.e. the ones bpf_convert_ctx_accesses() turns into BPF_PROBE_MEM: a bare PTR_TO_BTF_ID, PTR_TO_BTF_ID | PTR_UNTRUSTED, PTR_TO_BTF_ID | MEM_ALLOC | PTR_UNTRUSTED and PTR_TO_MEM | MEM_RDONLY | PTR_UNTRUSTED. This is reachable e.g. by loading ->mm out of a trusted task_struct yields an untrusted pointer to mm_struct, and it is NULL for a kernel thread: [...] SEC("tp_btf/sched_switch") int BPF_PROG(demo, bool preempt, struct task_struct *prev, struct task_struct *next) { struct mm_struct *mm = next->mm; /* untrusted */ out_ldx = (__u64)mm->pgd; /* BPF_LDX */ out_acq = load_acquire(&mm->pgd); /* BPF_LOAD_ACQ */ return 0; } [...] Both dereference the same pointer, but only the BPF_LDX is protected (x86-64 JIT, jump targets shown prog-relative): [...] ; out_ldx = (__u64)mm->pgd; 17: movq $-10485760, %r10 1e: movq %rsi, %r11 21: addq $184, %r11 28: subq %r10, %r11 2b: movabsq $140737498841088, %r10 35: cmpq %r10, %r11 38: ja 0x3e <-- kernel addr? 3a: xorl %edi, %edi <-- no: dst = 0, skip the load 3c: jmp 0x45 3e: movq 184(%rsi), %rdi <-- yes: load + extable entry [...] ; load_acquire(&mm->pgd) 53: movq %rsi, %rdi 56: movq 184(%rdi), %rax <-- no check, no extable entry [...] Note that BPF_PROBE_MEM is not visible in a bpftool xlated dump, as bpf_insn_prepare_dump() rewrites it back to BPF_MEM. A PTR_TRUSTED pointer is deliberately not on the list. Such a load is not converted either, but it does not need to be, since the pointer is guaranteed live, so load-acquire from it stays allowed. The check is gated on BPF_LOAD_ACQ so that atomic RMW and store-release error messages are unchanged; writes (RMW / store-release) to such pointers are already rejected elsewhere, so only load-acquire needs this.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|