NVD Vulnerability Detail
Search Exploit, PoC
CVE-2026-23342
Summary

In the Linux kernel, the following vulnerability has been resolved:

bpf: Fix race in cpumap on PREEMPT_RT

On PREEMPT_RT kernels, the per-CPU xdp_bulk_queue (bq) can be accessed
concurrently by multiple preemptible tasks on the same CPU.

The original code assumes bq_enqueue() and __cpu_map_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_flush_to_queue(), 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 __list_del_clearprev(): after bq->count is reset in
bq_flush_to_queue(), a preempting task can call bq_enqueue() ->
bq_flush_to_queue() on the same bq when bq->count reaches
CPU_MAP_BULK_SIZE. Both tasks then call __list_del_clearprev()
on the same bq->flush_node, the second call dereferences the
prev pointer that was already set to NULL by the first.

2. bq->count and bq->q[] races: concurrent bq_enqueue() can corrupt
the packet queue while bq_flush_to_queue() is processing it.

The race between task A (__cpu_map_flush -> bq_flush_to_queue) and
task B (bq_enqueue -> bq_flush_to_queue) on the same CPU:

Task A (xdp_do_flush) Task B (cpu_map_enqueue)
---------------------- ------------------------
bq_flush_to_queue(bq)
spin_lock(&q->producer_lock)
/* flush bq->q[] to ptr_ring */
bq->count = 0
spin_unlock(&q->producer_lock)
bq_enqueue(rcpu, xdpf)
<-- CFS preempts Task A --> bq->q[bq->count++] = xdpf
/* ... more enqueues until full ... */
bq_flush_to_queue(bq)
spin_lock(&q->producer_lock)
/* flush to ptr_ring */
spin_unlock(&q->producer_lock)
__list_del_clearprev(flush_node)
/* sets flush_node.prev = NULL */
<-- Task A resumes -->
__list_del_clearprev(flush_node)
flush_node.prev->next = ...
/* prev is NULL -> kernel oops */

Fix this by adding a local_lock_t to xdp_bulk_queue and acquiring it
in bq_enqueue() and __cpu_map_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.

To reproduce, insert an mdelay(100) between bq->count = 0 and
__list_del_clearprev() in bq_flush_to_queue(), then run reproducer
provided by syzkaller.

Summary

En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta:

bpf: Corrige condición de carrera en cpumap en PREEMPT_RT

En kernels PREEMPT_RT, la xdp_bulk_queue (bq) por CPU puede ser accedida concurrentemente por múltiples tareas preemptibles en la misma CPU.

El código original asume que bq_enqueue() y __cpu_map_flush() se ejecutan atómicamente una con respecto a la otra en la misma CPU, confiando en local_bh_disable() para prevenir la preemption. Sin embargo, en PREEMPT_RT, local_bh_disable() solo llama a migrate_disable() (cuando PREEMPT_RT_NEEDS_BH_LOCK no está configurado) y no deshabilita la preemption, lo que permite que la planificación CFS preempte una tarea durante bq_flush_to_queue(), permitiendo que otra tarea en la misma CPU entre en bq_enqueue() y opere en la misma bq por CPU concurrentemente.

Esto conduce a varias condiciones de carrera:

1. Doble __list_del_clearprev(): después de que bq-&gt;count se reinicia en bq_flush_to_queue(), una tarea preemptora puede llamar a bq_enqueue() -&gt; bq_flush_to_queue() en la misma bq cuando bq-&gt;count alcanza CPU_MAP_BULK_SIZE. Ambas tareas luego llaman a __list_del_clearprev() en el mismo bq-&gt;flush_node, la segunda llamada desreferencia el puntero prev que ya había sido establecido a NULL por la primera.

2. Condiciones de carrera de bq-&gt;count y bq-&gt;q[]: bq_enqueue() concurrente puede corromper la cola de paquetes mientras bq_flush_to_queue() la está procesando.

La condición de carrera entre la tarea A (__cpu_map_flush -&gt; bq_flush_to_queue) y la tarea B (bq_enqueue -&gt; bq_flush_to_queue) en la misma CPU:

Tarea A (xdp_do_flush) Tarea B (cpu_map_enqueue)
---------------------- ------------------------
bq_flush_to_queue(bq)
spin_lock(&amp;q-&gt;producer_lock)
/* vaciar bq-&gt;q[] a ptr_ring */
bq-&gt;count = 0
spin_unlock(&amp;q-&gt;producer_lock)
bq_enqueue(rcpu, xdpf)
&lt;-- CFS preempte la Tarea A --&gt; bq-&gt;q[bq-&gt;count++] = xdpf
/* ... más encolamientos hasta llenarse ... */
bq_flush_to_queue(bq)
spin_lock(&amp;q-&gt;producer_lock)
/* vaciar a ptr_ring */
spin_unlock(&amp;q-&gt;producer_lock)
__list_del_clearprev(flush_node)
/* establece flush_node.prev = NULL */
&lt;-- La Tarea A se reanuda --&gt;
__list_del_clearprev(flush_node)
flush_node.prev-&gt;next = ...
/* prev es NULL -&gt; kernel oops */

Solucione esto añadiendo un local_lock_t a xdp_bulk_queue y adquiriéndolo en bq_enqueue() y __cpu_map_flush(). Estas rutas ya se ejecutan bajo local_bh_disable(), por lo que se usa local_lock_nested_bh() que en sistemas no-RT es una anotación pura sin sobrecarga, y en PREEMPT_RT proporciona un bloqueo de suspensión por CPU que serializa el acceso a la bq.

Para reproducir, inserte un mdelay(100) entre bq-&gt;count = 0 y __list_del_clearprev() en bq_flush_to_queue(), luego ejecute el reproductor proporcionado por syzkaller.

Publication Date March 25, 2026, 8:16 p.m.
Registration Date April 27, 2026, 12:18 p.m.
Last Update April 24, 2026, 6:16 a.m.
CVSS3.1 : MEDIUM
スコア 4.7
Vector CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H
攻撃元区分(AV) ローカル
攻撃条件の複雑さ(AC)
攻撃に必要な特権レベル(PR)
利用者の関与(UI) 不要
影響の想定範囲(S) 変更なし
機密性への影響(C) なし
完全性への影響(I) なし
可用性への影響(A)
Affected software configurations
Configuration1 or higher or less more than less than
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.18.1 6.18.17
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.19 6.19.7
cpe:2.3:o:linux:linux_kernel:6.18:-:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc4:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc5:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc6:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc7:*:*:*:*:*:*
Related information, measures and tools
Common Vulnerabilities List

JVN Vulnerability Information
LinuxのLinux Kernelにおける競合状態に関する脆弱性
Title LinuxのLinux Kernelにおける競合状態に関する脆弱性
Summary

Linuxカーネルにおいて、以下の脆弱性が修正されました。bpf: PREEMPT_RT環境下のcpumapにおける競合状態を修正しました。PREEMPT_RTカーネルでは、CPUごとのxdp_bulk_queue (bq)が同一CPU上の複数のプリエンプト可能なタスクから同時にアクセスされうる状況が存在していました。元のコードは、同一CPU上でbq_enqueue()と__cpu_map_flush()が原子的に実行されると仮定し、プリエンプションを防ぐためにlocal_bh_disable()に依存していました。しかしPREEMPT_RTでは、local_bh_disable()はPREEMPT_RT_NEEDS_BH_LOCKが設定されていない場合migrate_disable()のみを呼び出し、プリエンプションを無効化しません。これにより、bq_flush_to_queue()の実行中にCFSスケジューラがタスクをプリエンプトし、同一CPU上で別のタスクがbq_enqueue()に入り、同一のCPUローカルbqに同時アクセスが可能となりました。このことにより、以下の競合が発生しました。1. __list_del_clearprev()の二重呼び出し:bq_flush_to_queue()でbq-countがリセットされた後、プリエンプトされたタスクがbq_enqueue()およびbq_flush_to_queue()を呼び出し、bq-countがCPU_MAP_BULK_SIZEに達した際に両タスクが同一bq-flush_nodeに対して__list_del_clearprev()を呼びます。2度目の呼び出しでは既にNULLに設定されたprevポインタをデリファレンスし、クラッシュを引き起こしました。2. bq-countおよびbq-q[]の競合:同時実行されるbq_enqueue()によってパケットキューがbq_flush_to_queue()処理中に破損する可能性があります。タスクA(__cpu_map_flush - bq_flush_to_queue)とタスクB(bq_enqueue - bq_flush_to_queue)の同一CPU上での競合状態の流れは以下の通りです。 Task A (xdp_do_flush) Task B (cpu_map_enqueue)---------------------- ------------------------bq_flush_to_queue(bq) spin_lock(&q-producer_lock) /* bq-q[]をptr_ringへフラッシュ */ bq-count = 0 spin_unlock(&q-producer_lock) bq_enqueue(rcpu, xdpf) -- CFSプリエンプトでTask A中断 -- bq-q[bq-count++] = xdpf /* ...多数enqueue処理... */ bq_flush_to_queue(bq) spin_lock(&q-producer_lock) /* ptr_ringへフラッシュ */ spin_unlock(&q-producer_lock) __list_del_clearprev(flush_node) /* flush_node.prevをNULLに設定 */ -- Task A再開 -- __list_del_clearprev(flush_node) flush_node.prev-next = ... /* prevがNULLのためカーネルoops発生 */これらの問題を修正するために、xdp_bulk_queueにlocal_lock_tを追加し、bq_enqueue()と__cpu_map_flush()内でロック取得を行います。これらの処理はlocal_bh_disable()の下で既に動作しているため、non-RTではオーバーヘッドのない注釈的意味を持ち、PREEMPT_RTでは同一CPU内でのスリーピングロックとして動作し、bqへのアクセスを直列化するlocal_lock_nested_bh()を使用します。再現手順としては、bq_flush_to_queue()のbq-count = 0と__list_del_clearprev()の間にmdelay(100)を挿入し、syzkaller提供のリプロデューサを実行してください。

Possible impacts 当該ソフトウェアが扱う情報について、外部への漏えいは発生しません。 また、当該ソフトウェアが扱う情報について、書き換えは発生しません。 さらに、当該ソフトウェアが完全に停止する可能性があります。 そして、この脆弱性を悪用した攻撃の影響は、他のソフトウェアには及びません。 
Solution

リリース情報、またはパッチ情報が公開されています。参考情報を参照して適切な対策を実施してください。

Publication Date March 25, 2026, midnight
Registration Date April 27, 2026, 11:25 a.m.
Last Update April 27, 2026, 11:25 a.m.
Affected System
Linux
Linux Kernel 6.18
Linux Kernel 6.18.1 以上 6.18.17 未満
Linux Kernel 6.19 以上 6.19.7 未満
Linux Kernel 7.0
CVE (情報セキュリティ 共通脆弱性識別子)
CWE (共通脆弱性タイプ一覧)
その他
Change Log
No Changed Details Date of change
1 [2026年04月27日]
  掲載
April 27, 2026, 11:25 a.m.