CVE-2026-23294: bpf: Fix race in devmap on PREEMPT_RT
In the Linux kernel, the following vulnerability has been resolved:
bpf: Fix race in devmap on PREEMPT_RT
On PREEMPT_RT kernels, the per-CPU xdp_dev_bulk_queue (bq) can be
accessed concurrently by multiple preemptible tasks on the same CPU.
The original code assumes bq_enqueue() and __dev_flush() run atomically
with respect to each other on the same CPU, relying on
local_bh_disable() to prevent preemption. However, on PREEMPT_RT,
local_bh_disable() only calls migrate_disable() (when
PREEMPT_RT_NEEDS_BH_LOCK is not set) and does not disable
preemption, which allows CFS scheduling to preempt a task during
bq_xmit_all(), enabling another task on the same CPU to enter
bq_enqueue() and operate on the same per-CPU bq concurrently.
This leads to several races:
1. Double-free / use-after-free on bq->q[]: bq_xmit_all() snapshots
cnt = bq->count, then iterates bq->q[0..cnt-1] to transmit frames.
If preempted after the snapshot, a second task can call bq_enqueue()
-> bq_xmit_all() on the same bq, transmitting (and freeing) the
same frames. When the first task resumes, it operates on stale
pointers in bq->q[], causing use-after-free.
2. bq->count and bq->q[] corruption: concurrent bq_enqueue() modifying
bq->count and bq->q[] while bq_xmit_all() is reading them.
3. dev_rx/xdp_prog teardown race: __dev_flush() clears bq->dev_rx and
bq->xdp_prog after bq_xmit_all(). If preempted between
bq_xmit_all() return and bq->dev_rx = NULL, a preempting
bq_enqueue() sees dev_rx still set (non-NULL), skips adding bq to
the flush_list, and enqueues a frame. When __dev_flush() resumes,
it clears dev_rx and removes bq from the flush_list, orphaning the
newly enqueued frame.
4. __list_del_clearprev() on flush_node: similar to the cpumap race,
both tasks can call __list_del_clearprev() on the same flush_node,
the second dereferences the prev pointer already set to NULL.
The race between task A (__dev_flush -> bq_xmit_all) and task B
(bq_enqueue -> bq_xmit_all) on the same CPU:
Task A (xdp_do_flush) Task B (ndo_xdp_xmit redirect)
---------------------- --------------------------------
__dev_flush(flush_list)
bq_xmit_all(bq)
cnt = bq->count /* e.g. 16 */
/* start iterating bq->q[] */
<-- CFS preempts Task A -->
bq_enqueue(dev, xdpf)
bq->count == DEV_MAP_BULK_SIZE
bq_xmit_all(bq, 0)
cnt = bq->count /* same 16! */
ndo_xdp_xmit(bq->q[])
/* frames freed by driver */
bq->count = 0
<-- Task A resumes -->
ndo_xdp_xmit(bq->q[])
/* use-after-free: frames already freed! */
Fix this by adding a local_lock_t to xdp_dev_bulk_queue and acquiring
it in bq_enqueue() and __dev_flush(). These paths already run under
local_bh_disable(), so use local_lock_nested_bh() which on non-RT is
a pure annotation with no overhead, and on PREEMPT_RT provides a
per-CPU sleeping lock that serializes access to the bq.
Security readout for executives and security teams
Plain-English summary
A race condition in Linux PREEMPT_RT kernels can corrupt memory while XDP devmap queues transmit or flush network frames. A local, low-privileged attacker may be able to trigger use-after-free, double-free, data corruption, or system failure. Successful exploitation requires specific timing and affected BPF/XDP activity.
Executive priority
Prioritize affected real-time Linux hosts that permit untrusted local users or process high-value network traffic through XDP devmaps. Patch promptly through supported kernel channels. Systems without PREEMPT_RT or relevant XDP devmap use have lower apparent urgency, subject to verification.
Technical view
On PREEMPT_RT, local_bh_disable() may prevent migration without preventing preemption. Two tasks can therefore access the same per-CPU xdp_dev_bulk_queue concurrently, racing bq_enqueue() against __dev_flush() and bq_xmit_all(). Outcomes include stale frame reuse, double-free, queue corruption, orphaned frames, and invalid list operations. The fix serializes both paths using local_lock_t and local_lock_nested_bh().
Likely exposure
Exposure is limited to Linux systems using PREEMPT_RT and the affected XDP devmap paths. The bundle identifies Linux 6.18, 6.18.17, 6.19.7, and 7.0 as affected, but does not clearly define complete version ranges. Standard non-RT kernels are not described as vulnerable.
Exploitation context
The CVSS vector indicates local access, low privileges, high attack complexity, no user interaction, and potentially high confidentiality, integrity, and availability impact. The source bundle reports no CISA KEV listing and provides no evidence of active exploitation.
Researcher notes
The vulnerability depends on same-CPU task preemption during shared per-CPU queue operations. The source documents four race outcomes and a locking correction. It does not provide proof-of-concept exploitation, confirmed attacks, complete affected-version ranges, or distribution-specific package status. Avoid inferring remote exploitability from the networking context.
Mitigation direction
Apply an official Linux or distribution kernel containing the cited local_lock_t fix.
Confirm the distribution’s security advisory maps its packaged kernel to an upstream fixed commit.
Until patched, restrict untrusted local access to systems running affected PREEMPT_RT kernels.
Reduce unnecessary use of affected BPF/XDP devmap workloads where operationally safe.
Validation and detection
Determine whether each system runs a PREEMPT_RT kernel and uses XDP devmap functionality.
Record kernel package versions and compare them with current distribution security guidance.
Verify the kernel source or vendor changelog includes one of the cited fixes or an equivalent backport.
After updating, confirm the fixed kernel is running and repeat normal XDP networking regression tests.
Generated from the cited source records. This long-tail analysis has not been individually reviewed by a named human.
Potential ATT&CK relevance
Conservative CVE-to-ATT&CK context
These mappings and lookup hints may be relevant to the vulnerability behavior, CWE, affected product, or exposure path. Glexia-inferred context is not an official MITRE, ATT&CK, CWE, or CVE Program mapping.
ATT&CK lookup starting points
Use these exact CWE pages and searches to review the Glexia ATT&CK library from this CVE's weakness and description context.
cve · low confidence lookup
CVE-2026-23294 mapping review
Open the CVE-to-ATT&CK bridge for reviewed, inferred, or future official mappings tied to this CVE.
These fields come from the CVE record and ADP containers, not from Glexia's Take. They preserve time-varying source decisions such as CISA SSVC, KEV status, CVSS metrics, and provider references.
1CVSS vectors
3Timeline events
0ADP providers
4Source links
CVSS vector scores
1 official score
We collect every scored CVSS vector available in the official CNA and ADP containers. When more than one version is present, the table keeps the source vectors side by side instead of collapsing them into the highest score.