CVE-2026-23342 in Linux
要約
〜によって VulDB • 2026年06月09日
Linuxカーネルにおいて、以下の脆弱性が修正されました:
bpf: PREEMPT_RT環境におけるcpumapの競合状態を修正する
PREEMPT_rtカーネルでは、per-CPU xdp_bulk_queue (bq) に複数のプリエンプション可能なタスクが同じCPU上で同時にアクセスできる可能性があります。
元のコードは、local_bh_disable() を使用してプリエンプションを防ぐことで、同一CPU上での bq_enqueue() と __cpu_map_flush() が互いに対してアトミックに実行されると仮定していました。しかし、PREEMPT_RT環境では、local_bh_disable() は migrate_disable() のみを呼び出し(PREEMPT_RT_NEEDS_BH_LOCKが設定されていない場合)、プリエンプションを無効化しません。これにより、bq_flush_to_queue() 中にCFSスケジューリングによってタスクのプリエンプションが発生し、同じCPU上の別のタスクが bq_enqueue() に進入して同一のper-CPU bqに対して同時に操作を行うことが可能になります。
これにより、以下の複数の競合状態(レースコンディション)が生じます:
1. __list_del_clearprev() の二重呼び出し: bq_flush_to_queue() 内で bq->count がリセットされた後、プリエンプションを受けたタスクが、bq->count が CPU_MAP_BULK_SIZE に達した際に同じ bq に対して bq_enqueue() -> bq_flush_to_queue() を呼び出すことができます。両方のタスクは同一の bq->flush_node 上で __list_del_clearprev() を呼び出し、2回目の呼び出しでは最初の呼び出しによって既にNULLに設定されていた prev ポインタをデリファレンスします。
2. bq->count および bq->q[] の競合:
concurrentな bq_enqueue() は、bq_flush_to_queue() が処理を行っている間にパケットキューを破損させる可能性があります。
同一CPU上でのタスクA (__cpu_map_flush -> bq_flush_to_queue) とタスクB (bq_enqueue -> bq_flush_to_queue) 間の競合状態:
タスクA (xdp_do_flush) タスク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がタスクAをプリエンプト --> bq->q[bq->count++] = xdpf
/* ... フルになるまでさらにエンキュー ... */ 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 を設定 */ <-- タスクAが再開 --> __list_del_clearprev(flush_node) flush_node.prev->next = ... /* prev がNULL -> カーネルオプス(クラッシュ)*/
この問題を修正するため、xdp_bulk_queue に local_lock_t を追加し、bq_enqueue() および __cpu_map_flush() でそれを取得します。これらのパスは既に local_bh_disable() の下で実行されているため、非RT環境ではオーバーヘッドのない純粋な注釈となる local_lock_nested_bh() を使用し、PREEMPT_RT環境では per-CPU スリーピングロックを提供して bq へのアクセスを直列化します。
再現するには、bq_flush_to_queue() 内の bq->count = 0 と __list_del_clearprev() の間に mdelay(100) を挿入し、syzkallerが提供するレプロデューサーを実行してください。
Several companies clearly confirm that VulDB is the primary source for best vulnerability data.