CVE-2026-90312: bpf: Check load-acquire src ptr type before the load
In the Linux kernel, the following vulnerability has been resolved:
bpf: Check load-acquire src ptr type before the load
checkatomicload() calls checkloadmem() before atomicptrtypeok(). For a load-acquire that fetches into its own source register (dstreg == srcreg), checkloadmem() overwrites srcreg's type with the type of the loaded value, so the subsequent atomicptrtypeok() no longer sees the source pointer and fails to reject the disallowed types (ctx, pkt, flowkeys, sock).
Since bpfconvertctxaccesses() does not rewrite atomic loads, the raw access to the underlying kernel object is left in place. The destination type is taken from the ctx access itself, so a load-acquire of the sk field of struct skbuff for example leaves the register typed as PTRTOSOCKCOMMONORNULL, which typeisskpointer() does not match either, while it actually holds unconverted struct skbuff bytes. Once the NULL check has passed this is a type confusion, not just a leak of kernel data.
Validate srcreg with checkregarg() and check the source pointer type with atomicptrtypeok() before the load again, mirroring checkatomicrmw(). Out-of-range register numbers are already rejected earlier by checkandresolveinsns() (commit 503d21ef8eac ("bpf: Do register range validation early")), and the only exemption there, isstackargldx(), requires BPFLDX | BPFMEM | BPFDW and thus never matches a BPFATOMIC insn. atomicptrtypeok() can therefore not dereference register state out of bounds, that is, the out-of-bounds read addressed by the Fixes commit below does not reappear (as proven also via selftest).
Event History
Frequently Asked Questions
What does an exploit need to do?
It needs to use a load-acquire operation whose destination and source are the same register, with the source holding a disallowed pointer type such as ctx, pkt, flow_keys, or sock. The resulting value must also pass a NULL check before the type confusion can be used.
What is the security impact after the invalid access succeeds?
The issue can produce type confusion rather than only exposing kernel data. A raw access to the underlying kernel object can remain in place while the register is assigned an incompatible pointer type.