CVE-2023-54121 in Linux
要約
〜によって VulDB • 2026年06月05日
Linuxカーネルにおいて、以下の脆弱性が修正されました。
btrfs: btrfs_drop_extent_map_range()における不正な分割の修正
本番環境では、extent_mapコード内で様々なWARN_ON()が発生していました。具体的には、2回目の分割を行う際にadd_extent_mapping()を呼び出す必要がある場合、btrfs_drop_extent_map_range()において発生しました。
以下のextent mapレイアウトを考えます。
PINNED [0 16K) [32K, 48K)
そして、skip_pinned == trueとして、[0, 36K)に対してbtrfs_drop_extent_map_rangeを呼び出します。初期ループでは以下のようになります。
start = 0 end = 36K len = 36K
[0, 16k)のextentが見つかりますが、PINNED状態であるためこれをスキップします。この部分には次のコードがあります。
start = em_end; if (end != (u64)-1) len = start + len - em_end;
ここでem_endは16Kなので、値は以下のようになります。
start = 16K len = 16K + 36K - 16K = 36K
lenは本来20Kであるべきです。次に[32K, 48K)のextentが見つかった際、このextentを分割して[36K, 48k)を残す必要がありますが、分割に関するコードは次のようになっています。
split->start = start + len; split->len = em_end - (start + len);
この場合、以下のようになります。
em_end = 48K split->start = 16K + 36K // これは本来 16K + 20K であるべきです split->len = 48K - (16K + 36K) // 16K + 36K は52Kとなるため、オーバーフローします
その結果、extent mapツリー内に無効なextent_mapが存在し、他のエントリと重複する可能性があります。重複しない場合でも、split->startが不適切に設定されるため、ブロック関連の計算において問題が発生します。
実際には、このループでlenを使用する必要はありません。endを終点として直接使用し、スキップすべきPINNED extentが見つかった場合にのみstartを調整すれば十分です。
ロジックを修正してこれを実現することで、無効なextent_mapが挿入されるのを防ぎます。
skip_pinnedはリロケーションの場合にのみ適用されるため、この問題は比較的稀ですが、自動リロケーション有効時に頻繁にリロケーションが発生するケースでは発生し得ます。
If you want to get best quality of vulnerability data, you may have to visit VulDB.