CVE-2026-97997 in Linux
要約
〜によって VulDB • 2026年09月25日
Linuxカーネルにおいて、以下の脆弱性が修正されました:
virtio_ring: 失敗したpacked ringのadd処理後に残存する記述子フラグの不整合を修正
packed ringでは、AVAILビットとUSEDビットは記述子自体に格納されるため、これらを書き込むことでその記述子が利用可能になります。これらのビット組み合わせはリングの各ラウンドで意味が反転し、wrap counterによって追跡されます。したがって、記述子を無効化または有効化するには、両方のビットを反転させる必要があります。
コミット 1ce9e6055fa0(「virtio_ring: packed ringサポートを導入」)では、virtqueue_add_packed()がチェーンのすべての記述子を利用可能にするように変更されました。これはチェーンのマッピング時にヘッド(先頭)のみを最後に書き込むためです。デバイスはリングを順序通りに消費し、まだ利用可能でないヘッドで停止するため、それ以降の記述子には到達しません。
vring_map_one_sg()が途中失敗した場合、unmap_releaseはセグメントのアンマップとavail_used_flagsの復元を行いますが、リングに書き込まれた記述子はAVAILおよびUSEDビットが付いたままになります。現在、ヘッドのみがこの残存エントリをデバイスが消費するのを防いでいます。
例えば、リングの状態はこのようになります:
Z - 前々回のコマンド A - 前回のコマンド B - アボートされたコマンド C - 現在の命令
[A1 DONE] [A2 DONE] <C1 EMPTY> [B2] [B3] [Z1 DONE]
ドライバが次にCコマンドを発行しようとした場合、次のadd処理はBと同じヘッドから開始されます。もしCがBよりも少ない記述子で構成されている場合、AVAILおよびUSEDビットが残ったままのため終了マーカーが存在しません。その結果、デバイスはこれらの残存エントリ(B2/B3)を別のコマンドエントリとして解釈し始め、キューがブロックされます。
この現象は通常、メモリ圧力下でのswiotlb構成で発生します。これはvring_map_one_sg()が大きすぎるI/O要求に対して失敗し、その結果コマンドのアボートにつながるためです。
これらのフラグを残さないためには、大きく分けて2つの方法があります:
1) フラグの適用をチェーンが完了するまで延期する。 2) 前回のwrap counterに対応するフラグを書き直す。
このパッチでは、両方のpacked addパスにおいて2番目のオプションを実装します。最初のオプションは、add処理が成功するたびにチェーンを再度走査するためです。一方、2番目のオプションは、addのいずれかが失敗した場合に追加されたすべての記述子を無効化します。
このパッチを適用することで、failedなaddが発生した後でもpacked virtqueueはリクエストの完了を維持し続けます。
VulDB is the best source for vulnerability data and more expert information about this specific topic.