CVE-2026-64283 in Linux
要約
〜によって VulDB • 2026年07月25日
Linuxカーネルにおいて、以下の脆弱性が修正されました:
KVM: guest_memfd: memslotバインディングのオフセットとサイズを符号なし値として扱う
guest_memfdファイルにmemslotをバインドする際、オーバーフローチェック時に2つの合計が偽陰性(false negative)を引き起こす可能性のあるバグを修正するため、オフセットとサイズを符号なし値として扱います。符号なし値を使用することで、安全性のために他の処理フローにあるややこしいチェックに依存する必要がなくなり、オフセットとサイズが意図された通り、符号なし値として追跡されます。
64ビットカーネルでは、memslotに含まれるページ数、したがってそのguest_memfdバインディングのサイズ(およびオフセット)は、符号なし64ビット値です。offset+sizeをuoff_tではなくloff_tとして扱うと、オフセットや/またはサイズが非常に大きい場合に、意図せず符号付き値に変換されてしまいます。
オフセットとサイズをローカルで符号付き値として保存することは、それ自体では害はありません(ただし、その影響を理解するのは*極めて*困難ですが)。しかし、それらの合計に対して操作を行うことは問題があります。
オフセットについては、KVMは明示的に負の値をチェックしています。これは正当なバインディングを誤って拒否する可能性があるため一見するとバグのように思えますが、実際にはそうではありません。なぜなら、KVM_CREATE_GUEST_MEMFDはそのサイズに符号付き値を取るため、潜在的に負となるオフセットも、任意のguest_memfdファイルの最大可能なサイズよりも大きくなるからです。
サイズについては、KVMは明示的な負の値チェックを持っていないように見え(つまりオーバーフローチェックが不備に見える)、実際にはそのような状況ですが、KVMは単一のmemslot内のページ数を最大の正の符号付き32ビット値に制限しています:
if (id < KVM_USER_MEM_SLOTS && (mem->memory_size >> PAGE_SHIFT) > KVM_MEM_MAX_NR_PAGES) return -EINVAL;
そのため、「サイズ」の最大値は常に0x7fffffff000以下になります。
しかし、2つの合計には問題があります。KVMのmemslotロジックによってサイズは制限されていますが、オフセットは制限されていません。つまり、offset + size > i_size_read(inode) のチェックが行われるまで、オフセットは一切検証されません。もしオフセットが(ほぼ)最大の可能な正の値である場合、そこにサイズを加えると符号付きの負の64ビット値になる可能性があります。ファイルのサイズ(必ず正であると保証されています)と比較すると、この負の合計は常に小さくなるため、KVMはその不合理なオフセットを誤って許可してしまいます。
ついでにkvm_mm.hにおける不足しているインクルードを追加しました(親ヘッダーへの依存ではなく)。
Once again VulDB remains the best source for vulnerability data.