CVE-2026-90269: bpf: Reject load-acquire from pointers requiring fault protection
In the Linux kernel, the following vulnerability has been resolved:
bpf: Reject load-acquire from pointers requiring fault protection
A BPFLOADACQ is not rewritten to a BPFPROBEMEM load by the verifier, unlike a regular BPFLDX, 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 BPFLDX would have had that fault protection applied to, i.e. the ones bpfconvertctxaccesses() turns into BPFPROBEMEM: a bare PTRTOBTFID, PTRTOBTFID | PTRUNTRUSTED, PTRTOBTFID | MEMALLOC | PTRUNTRUSTED and PTRTOMEM | MEMRDONLY | PTRUNTRUSTED.
This is reachable e.g. by loading ->mm out of a trusted taskstruct yields an untrusted pointer to mmstruct, and it is NULL for a kernel thread:
[...] SEC("tpbtf/schedswitch") int BPFPROG(demo, bool preempt, struct taskstruct prev, struct taskstruct next) { struct mmstruct mm = next->mm; / untrusted /
outldx = (u64)mm->pgd; / BPFLDX / outacq = loadacquire(&mm->pgd); / BPFLOADACQ / return 0; } [...]
Both dereference the same pointer, but only the BPFLDX is protected (x86-64 JIT, jump targets shown prog-relative):
[...] ; outldx = (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 [...] ; loadacquire(&mm->pgd) 53: movq %rsi, %rdi 56: movq 184(%rdi), %rax <-- no check, no extable entry [...]
Note that BPFPROBEMEM is not visible in a bpftool xlated dump, as bpfinsnpreparedump() rewrites it back to BPFMEM.
A PTRTRUSTED 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 BPFLOADACQ 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 Software
Event History
Frequently Asked Questions
Who can realistically trigger this issue?
The issue is reachable by a BPF program that performs a load-acquire through certain pointer types requiring fault protection. The example uses a BTF tracepoint program reading next->mm, where the pointer can be NULL for a kernel thread.
What is the impact of a successful trigger?
A fault during the generated plain load can panic the kernel because the JIT code has no exception table entry for the BPF_LOAD_ACQ access. Equivalent regular BPF_LDX accesses are fault-protected, but load-acquire accesses were not rewritten to protected probe-memory loads.
What does the fix change?
The verifier now rejects BPF_LOAD_ACQ source pointer types for which regular BPF_LDX accesses would receive fault protection. This prevents JIT compilation of unprotected load-acquire operations through those pointers.