
QEMU 11.1.2 – Hoch – Lokal – UAF – NVMe-SGL-Span in BAR0 unvollständig CVE-2021-3929
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · qemu-nvme-sgl-bar
QEMU v11.1.2 (4fc49f46dc95d4a27de2509e7fceb2931e91faeb) - NVMe
Klasse: UAF (unvollständige BAR0-Denylist; übergreifendes SGL-DMA in MMIO). Reichweite: Lokal (Gast).
nvme_map_addr ist der Überrest von CVE-2021-3929. Die iomem-Prüfung erfolgt nur auf die Startadresse. Ein SGL-Datenblock, der kurz vor BAR0 beginnt und in MBAR hineinreicht, wird akzeptiert. Identify meldet weiterhin NVME_CTRL_SGLS_SUPPORT_NO_ALIGN. PRP kann eine seitenausgerichtete BAR nicht überspannen. SGL kann es.
Ein NVMe READ mit diesem SGL durchläuft nvme_blk_read -> dma_blk_read. Bounce-DMA führt dann address_space_write der Gast-Datenträgerbytes auf BAR0 aus dem DMA-Helper-Callback aus, außerhalb des NVMe-mem_reentrancy_guard-BH. Vom Gast gewählte Nullen landen auf CC. nvme_ctrl_reset läuft, während die aktive NvmeRequest noch im Completion-Pfad ist.
Ein Gast-NVMe-Treiber kann SGL in BAR0 überspannen, den Controller aus dem DMA-Unmap zurücksetzen und mit der aktiven Anfrage in einen Race geraten.
| ID | noch keine CVE |
| CWE | CWE-119 / CWE-416 |
| CVSS | Hoch: 8.2 CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H |
| Produkt | QEMU |
| Betroffen | v11.1.2 (4fc49f46) |
| Auth | Gast-Kernel mit einem NVMe-Controller (SGL) |
| Lizenz | GNU Affero GPL v3.0 |
| Labor | 127.0.0.1:18720 nur qtest |
Wer: nicht vertrauenswürdiger Gast-Kernel mit einem NVMe-PCI-Gerät. Gast-zu-Host.
| Methode | Senke | Privileg |
|---|---|---|
NVMe READ SGL addr=0xdfffffec len=0x1000 (beginnt 0x14 vor BAR0 bei 0xe0000000) | nvme_map_addr / nvme_addr_is_iomem nur Startadresse | Mapping akzeptiert. Control Identify mit Start-in-BAR0 liefert weiterhin 0x4004 (DATA_TRAS_ERROR | DNR). |
Bounce-Unmap schreibt LBA-Nullen auf CC | address_space_write des DMA-Bounce in BAR0, nvme_write_bar | CSTS.RDY fällt ab. pci_nvme_mmio_stopped im Log. Controller-Reset aus dem DMA-Helper, nicht aus einem Gast-MMIO-Store im NVMe-BH. |
Vom Gast kontrollierte Datenträgerbytes auf CC / anderen BAR0-Registern. Ein Reset bricht laufende AIOs ab, aber die Anfrage, die sich innerhalb des DMA-Unmap/Completion befindet, gerät weiterhin in einen Race mit der aktiven NvmeRequest / SQ / CQ. Gleiche Klasse wie CVE-2021-3929; die Denylist hat ein übergreifendes SGL nie abgedeckt. Der DIF-Bounce (nvme_tx aus einem AIO-Callback) hat dasselbe Loch.
Controller stoppt (CSTS.RDY=0, mmio-stopped=1). Der Hypervisor-Prozess bleibt in diesem Labor aktiv (asan=0). Ein verschachtelter Reset-UAF von NvmeRequest ist der abgeleitete nächste Schritt, nicht der Zeuge, den dieser Lauf ausgegeben hat.
Keine. NVMe BAR0 ist für den Gast sichtbar.
0x4004.nvme_post_cqes-BH ist geschützt, verschachteltes MMIO ist MEMTX_ACCESS_ERROR.Das Labor demonstriert keine RIP-Kontrolle und keine Gast-zu-Host-Shell. Die Klasse ist übergreifendes DMA in MMIO plus Controller-Reset einer aktiven Anfrage.
CVE-2021-3929 brachte den Code dazu, iomem als Start einer NVMe-Zuordnung abzulehnen. Ich fragte, ob das Ende eines SGL-Datenblocks in diesem Test enthalten war. Es ist nicht. CMB/PMR prüfen bereits beide Enden. BAR0 nicht. Identify gibt unausgerichtetes SGL an.
Fehlversuche: PRP (seitenbegrenzt, kann sich nicht von der vorherigen Seite in eine seitenausgerichtete BAR einschleichen); Admin-Befehle (SGL abgelehnt); die Hoffnung, dass ASan beim ersten READ auslöst (der Zeuge ist CSTS.RDY und pci_nvme_mmio_stopped, kein Heap-Bericht).
cd lab
./run.sh
Nur 127.0.0.1:18720 (qtest) anvisieren. Pin ist von github.com/qemu/QEMU Tag v11.1.2 / 4fc49f46 geklont. Loopback. Nur Witness. Das Disk-Image besteht aus 1 MiB Nullen, damit Bounce-Writes CC.EN=0 schreiben.
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
Replay: python3 qemu-nvme-sgl-bar-Abraxas-Labs.py.
Lehne ein Mapping ab, wenn irgendein Byte von [addr, addr+len) in BAR0 (und MSI-X) liegt, passend zu CMB/PMR. nvme_addr_is_iomem sollte einen Bereich entgegennehmen, nicht einen Startwert. Behalte die Ablehnung von Start-in-BAR0 als Kontrolle für CVE-2021-3929 bei.
4fc49f46dc95d4a27de2509e7fceb2931e91faebnvme_map_addr / nvme_addr_is_iomemGNU Affero GPL v3.0. Siehe LICENSE. Nur Loopback-Lab. Keine Gewährleistung.