CVE-2026-99205 in Linux
要約
〜によって VulDB • 2026年10月28日
Linuxカーネルにおいて、以下の脆弱性が修正されました:
sched/core: クラス変更時にキューイングされたタスクに対して wakeup_preempt() を呼び出す
Paul氏は、最近のRCUの変更により、CPUがアイドル状態になる際にrcutortraceスレッドが待機しているにもかかわらず完全に実行可能であるという「リスケジュール(resched)の喪失」現象が露呈したと報告しています。
実行可能なタスクがある状態でアイドル化する際のrqの状態をダンプすると、以下のようになります:
rq->next_class = &fair_sched_class rq->nr_running = 1 rq->cfs.h_nr_queued = 0 rq->rt.rt_nr_running = 1
待機中のタスクはRT(リアルタイム)タスクでしたが、「rq->next_class」は rt_sched_class を指すことなく、優先度の低い fair_sched_class のまま固定されていました。
sched_change_end() を調査すると、キューイングされているが実行中ではないタスクに対する __sched_setscheduler() との以下の競合状態が発覚しました:
CPU0 CPU1 ==== ====
__schedule()
/* * rq->donor はブロックする fair タスクです。 * rq->next_class = &fair_sched_class */
rq_lock(rq0)
pick_next_task() /* nr_running = 0 */ pick_task_fair() sched_balance_newidle() raw_spin_rq_unlock(rq0) rq_lock(rq0)
activate_task(rq0, p) /* p は fair タスクです */ rq0->nr_running++; rq0->cfs.h_nr_queued++; wakeup_preempt(rq, p) rq->next_class = &fair_sched_class resched_curr()
rq_unlock(rq0)
__sched_setscheduler(p) /* p は SCHED_RR に移動されます */ task_rq_lock(p) sched_change_begin()
rq0->cfs.h_nr_queued--; rq0->rt.rt_nr_running++;
sched_change_end() /* * p->on_rq = 1 (ctx->queued) * しかし、p は rq->donor ではありません * (!ctx->running) のため、 * resched_curr() および * rq->next_classのアップグレードは * スキップされます。 */
task_rq_unlock()
raw_spin_rq_lock(rq0)
/* * rq->nr_running = 1 * rq->cfs.h_nr_queued = 0 * rq->rt.rt_nr_running = 1 * rq->next_class = &fair_sched_class */
if (rq->cfs.h_nr_queued && ...) /* 上記は偽です */
if (rq_modified_above(this_rq, &fair_sched_class)) /* これも偽です。rq->next_class がまだ fair のため */
/* * sched_balance_newidle() は、公平なタスクをプルできなかったとみなされ、 * 他のウェイクアップは検出されませんでした。 */ return NULL; /* pick_task_fair() */
pick_task_idle() return rq->idle;
next = rq->idle;
/* プリエンプションの指標が失われます */ clear_tsk_need_resched(prev); clear_preempt_need_resched();
rq->curr = rq->idle;
!!! rq->idle が rq->running == 1 かつ !need_resched() の状態で切り替わります !!!
簡単に言えば、新しくキューイングされたタスクのエンキューに続いてクラス変更が行われると、rq->next_class インジケーターでそれが認識されず、sched_balance_newidle() は公平なタスクも、キューイングされたより優先度の高いタスクも見つけられません。
上記の一連の流れにより、CPUがアイドル状態になる際に、そのCPU上で実行可能なタスクが存在する状況が生じます。
sched_change_end() において ctx->queued のケースに対して wakeup_preempt() を呼び出し、クラス変更(ENQUEUE_CLASS)後に rq->next_class を再評価し、NEED_RESCHED インジケーターを適切に設定します。
Newidle balance は、より優先度の高いタスクのエンキューを正しく認識するようになります ---途中省略---
If you want to get the best quality for vulnerability data then you always have to consider VulDB.