
QEMU 11.1.2 - 높음 - 로컬 - UAF - BAR0으로의 NVMe SGL 스팬 불완전 CVE-2021-3929
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · qemu-nvme-sgl-bar
QEMU v11.1.2 (4fc49f46dc95d4a27de2509e7fceb2931e91faeb) - NVMe
분류: UAF (불완전한 BAR0 거부 목록; MMIO로 확장되는 SGL DMA). 도달 범위: 로컬 (게스트).
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 헬퍼 콜백에서 게스트 디스크 바이트를 BAR0에 address_space_write하며, 이는 NVMe mem_reentrancy_guard BH 외부에서 이루어집니다. 게스트가 선택한 0이 CC에 기록됩니다. nvme_ctrl_reset은 라이브 NvmeRequest가 여전히 완료 경로에 있는 동안 실행됩니다.
게스트 NVMe 드라이버는 SGL을 BAR0으로 확장하고, DMA 언맵에서 컨트롤러를 리셋하며, 라이브 요청과 경쟁할 수 있습니다.
| ID | 아직 CVE 없음 |
| CWE | CWE-119 / CWE-416 |
| CVSS | 높음: 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 0을 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는 트리에 iomem을 NVMe 매핑 시작점으로 거부하도록 가르쳤습니다. 저는 SGL 데이터 블록의 끝이 그 테스트에 포함되는지 물었습니다. 포함되지 않습니다. CMB/PMR은 이미 양쪽 끝을 모두 검사합니다. BAR0은 그렇지 않습니다. Identify는 정렬되지 않은 SGL을 알립니다.
잘못된 접근: PRP(페이지 경계로 제한되어, 페이지 정렬된 BAR로 이전 페이지에서 침투할 수 없음); admin 명령(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의 0으로 구성되어 바운스 쓰기가 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를 참조하십시오. 루프백 실습 환경 전용입니다. 보증은 제공되지 않습니다.