VYPR
High severity7.0NVD Advisory· Published Mar 25, 2026· Updated Apr 2, 2026

CVE-2026-23294

CVE-2026-23294

Description

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.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A race condition in the Linux kernel's devmap on PREEMPT_RT allows concurrent access to per-CPU bulk queues, leading to use-after-free and corruption.

Vulnerability

Overview

CVE-2026-23294 is a race condition in the Linux kernel's devmap (BPF device map) implementation that affects systems running with PREEMPT_RT (real-time preemption). The root cause is that on PREEMPT_RT kernels, local_bh_disable() does not fully disable preemption, only migration. This breaks the atomicity assumption that bq_enqueue() and __dev_flush() run without interruption on the same CPU. Consequently, multiple preemptible tasks on the same CPU can concurrently access the per-CPU xdp_dev_bulk_queue (bq), leading to several types of corruption [1][2][3].

Exploitation

Conditions

An attacker does not need special privileges beyond the ability to trigger BPF program execution that uses devmap redirection. The race occurs on a single CPU when a task executing __dev_flush() (via xdp_do_flush()) is preempted by another task that calls bq_enqueue(). This can happen under normal scheduling on PREEMPT_RT kernels. No network-level attack is required; the vulnerability is triggered by local kernel execution paths.

Impact

Successful exploitation can result in: - Double-free or use-after-free of frames in bq->q[], as bq_xmit_all() may transmit and free frames that are later accessed by a resumed task. - Corruption of bq->count and bq->q[] pointers, leading to memory corruption. - Orphaning of enqueued frames when dev_rx and xdp_prog pointers are cleared prematurely. - A race on flush_node list operations causing list corruption.

These issues can lead to system crashes, memory corruption, or potentially privilege escalation if an attacker can control freed memory.

Mitigation

The fix has been backported to stable kernel trees via commits [1], [2], and [3]. Users should update to the latest stable kernel that includes these patches. For systems that cannot immediately update, avoiding the use of BPF devmap on PREEMPT_RT kernels may reduce risk, but the only complete mitigation is applying the kernel fix.

AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

0

No patches discovered yet.

Vulnerability mechanics

AI mechanics synthesis has not run for this CVE yet.

References

3

News mentions

0

No linked articles in our index yet.