
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · qemu-nvme-sgl-bar
QEMU v11.1.2 (4fc49f46dc95d4a27de2509e7fceb2931e91faeb) - NVMe
クラス: UAF(不完全な BAR0 拒否リスト。SGL DMA が MMIO にまたがる)。到達範囲: ローカル(ゲスト)。
nvme_map_addr は CVE-2021-3929 の残骸である。iomem チェックは開始アドレスのみを見ている。BAR0 の直前から始まり MBAR に食い込む SGL データブロックが受け入れられる。Identify は依然として NVME_CTRL_SGLS_SUPPORT_NO_ALIGN を報告する。PRP はページ境界に揃った BAR にまたがることはできない。SGL はできる。
その SGL を使った NVMe READ は nvme_blk_read -> dma_blk_read を通る。バウンス DMA はその後、DMA ヘルパーのコールバックから、NVMe の mem_reentrancy_guard BH の外で、ゲストのディスクバイト列を address_space_write によって BAR0 上に書き込む。ゲストが選んだゼロが CC に着地する。nvme_ctrl_reset は、生きた NvmeRequest がまだ完了パス上にある間に実行される。
ゲストの NVMe ドライバは SGL を BAR0 にまたがらせ、DMA アンマップからコントローラをリセットし、生きたリクエストと競合させることができる。
| ID | CVE 未割当 |
| CWE | CWE-119 / CWE-416 |
| CVSS | High: 8.2 CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H |
| 製品 | QEMU |
| 影響を受けるバージョン | v11.1.2 (4fc49f46) |
| 認証 | NVMe コントローラ(SGL)を持つゲストカーネル |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1:18720 qtest のみ |
誰が: NVMe PCI デバイスを持つ信頼されていないゲストカーネル。ゲストからホストへ。
| 手法 | シンク | 権限 |
|---|---|---|
NVMe READ SGL addr=0xdfffffec len=0x1000(BAR0 の 0xe0000000 の 0x14 手前から開始) | nvme_map_addr / nvme_addr_is_iomem は開始アドレスのみ | マッピングが受け入れられる。BAR0 内から開始する Control Identify は依然として 0x4004(DATA_TRAS_ERROR | DNR)を返す。 |
バウンスのアンマップが LBA のゼロを CC に書き込む | DMA バウンスの address_space_write が BAR0 へ、nvme_write_bar | CSTS.RDY が低下する。 ログに pci_nvme_mmio_stopped。コントローラのリセットは NVMe BH 内のゲスト MMIO ストアからではなく、DMA ヘルパーから発生する。 |
ゲストが制御するディスクバイト列が CC やその他の BAR0 レジスタに載る。リセットは進行中の AIO をキャンセルするが、DMA アンマップ/完了処理の最中にあるリクエストは、生きた NvmeRequest / SQ / CQ と依然として競合する。CVE-2021-3929 と同じクラスであり、拒否リストはまたがる SGL をカバーしていなかった。DIF バウンス(AIO コールバックからの nvme_tx)にも同じ穴がある。
コントローラが停止する(CSTS.RDY=0、mmio-stopped=1)。このラボではハイパーバイザプロセスは稼働し続ける(asan=0)。NvmeRequest のネストしたリセットによる UAF が推測される次の段階であり、今回の実行で出力された証拠ではない。
なし。NVMe BAR0 はゲストから可視である。
0x4004。nvme_post_cqes BH はガードされており、ネストした MMIO は MEMTX_ACCESS_ERROR となる。このラボは RIP 制御やゲストからホストへのシェルを実証するものではない。クラスは MMIO へのまたがり DMA と、生きたリクエストに対するコントローラリセットである。
CVE-2021-3929 は、NVMe マッピングの開始位置として iomem を拒否するようにツリーを教えました。私は、SGL データブロックの終端がそのテストに含まれているかどうかを尋ねました。含まれていません。CMB/PMR はすでに両端をチェックしています。BAR0 はチェックしていません。Identify は非アライメント SGL をアドバタイズします。
誤った道:PRP(ページ境界に制限され、前のページからページアライメントされた BAR に忍び込むことはできません);管理コマンド(SGL は拒否されます);最初の READ で ASan が発火することを期待する(証拠となるのは CSTS.RDY と pci_nvme_mmio_stopped であり、ヒープレポートではありません)。
cd lab
./run.sh
対象は 127.0.0.1:18720(qtest)のみ。Pin は github.com/qemu/QEMU のタグ v11.1.2 / 4fc49f46 からクローン。ループバック。証人専用。ディスクイメージは 1 MiB のゼロで、バウンス書き込みが CC.EN=0 になるようにしている。
SUCCESS qemu-nvme-sgl-bar control-sc=0x4004 span-addr=0xdfffffec span-end=0xe0000fec csts-rdy-before=1 csts-rdy-after=0 mmio-stopped=1 asan=0 QEMU-NVME-SGL-BAR-WITNESS
リプレイ: python3 qemu-nvme-sgl-bar-Abraxas-Labs.py。
[addr, addr+len) のいずれかのバイトが BAR0(および MSI-X)内に存在する場合、CMB/PMR と同様にマッピングを拒否します。nvme_addr_is_iomem は開始アドレスではなく範囲を受け取るべきです。CVE-2021-3929 の制御として、開始アドレスが BAR0 内にある場合の拒否は維持します。
4fc49f46dc95d4a27de2509e7fceb2931e91faebnvme_map_addr / nvme_addr_is_iomemGNU Affero GPL v3.0。LICENSE を参照してください。ループバックラボ専用です。保証はありません。