
QEMU 11.1.2 - مرتفع - محلي - UAF - امتداد NVMe SGL إلى BAR0 غير مكتمل CVE-2021-3929
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 يقتصر على عنوان البداية فقط. كتلة بيانات SGL التي تبدأ قبل BAR0 بقليل وتمتد إلى MBAR يتم قبولها. لا يزال Identify يُبلّغ عن NVME_CTRL_SGLS_SUPPORT_NO_ALIGN. لا يمكن لـ PRP أن يمتد عبر BAR محاذى للصفحات. أما SGL فيمكنه ذلك.
عملية NVMe READ بهذا SGL تمر عبر nvme_blk_read -> dma_blk_read. ثم يقوم Bounce DMA بـ address_space_write لبايتات قرص الضيف على BAR0 من داخل callback الخاص بـ DMA helper، خارج الـ BH الخاص بـ mem_reentrancy_guard في NVMe. أصفار يختارها الضيف تستقر على CC. يتم تشغيل nvme_ctrl_reset بينما لا يزال NvmeRequest الحي في مسار الإكمال.
يمكن لسائق NVMe في الضيف أن يمتد بـ SGL إلى BAR0، ويعيد تعيين المتحكم من DMA unmap، ويتسابق مع الطلب الحي.
| المعرّف | لا يوجد 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 (يبدأ 0x14 قبل BAR0 عند 0xe0000000) | nvme_map_addr / nvme_addr_is_iomem فحص البداية فقط | تم قبول التعيين. Control Identify مع بداية داخل BAR0 لا يزال يُرجع 0x4004 (DATA_TRAS_ERROR | DNR). |
Bounce unmap يكتب أصفار LBA على CC | address_space_write لـ DMA bounce داخل BAR0، nvme_write_bar | CSTS.RDY ينخفض. pci_nvme_mmio_stopped في السجل. إعادة تعيين المتحكم من DMA helper، وليس من مخزن MMIO للضيف في NVMe BH. |
بايتات قرص يتحكم بها الضيف على CC / سجلات BAR0 الأخرى. إعادة التعيين تلغي AIOs الجارية، لكن الطلب الموجود داخل DMA unmap/الإكمال لا يزال يتسابق مع NvmeRequest / SQ / CQ الحي. نفس فئة CVE-2021-3929؛ قائمة الرفض لم تغطِّ قط SGL ممتدًا. ثغرة DIF bounce (nvme_tx من callback الخاص بـ AIO) لديها نفس الثغرة.
المتحكم يتوقف (CSTS.RDY=0، mmio-stopped=1). تبقى عملية الهايبرفايزر قائمة في هذا المختبر (asan=0). UAF الناتج عن إعادة تعيين متداخلة لـ NvmeRequest هو الخطوة التالية المستنتجة، وليس الشاهد الذي طبعه هذا التشغيل.
لا شيء. BAR0 الخاص بـ NVMe مرئي للضيف.
0x4004.nvme_post_cqes محمي، وMMIO المتداخل هو MEMTX_ACCESS_ERROR.لا يُظهر المختبر التحكم في RIP أو صدفة من الضيف إلى المضيف. الفئة هي DMA ممتد إلى MMIO بالإضافة إلى إعادة تعيين المتحكم لطلب حي.
علّمت CVE-2021-3929 الشجرةَ أن ترفض iomem كبداية تعيين NVMe. سألتُ ما إذا كانت نهاية كتلة بيانات SGL مشمولة في ذلك الاختبار. إنها ليست كذلك. يتحقق CMB/PMR بالفعل من كلا الطرفين. أما BAR0 فلا يفعل. يكشف Identify عن SGL غير محاذى.
مسارات خاطئة: PRP (محدود بالصفحة، ولا يمكنه التسلل إلى BAR محاذى للصفحة من الصفحة السابقة)؛ أوامر admin (SGL مرفوض)؛ الأمل في أن ينطلق ASan عند أول READ (الشاهد هو CSTS.RDY وpci_nvme_mmio_stopped، وليس تقرير heap).
cd lab
./run.sh
استهدف فقط 127.0.0.1:18720 (qtest). يُستنسخ Pin من github.com/qemu/QEMU وسم v11.1.2 / 4fc49f46. Loopback. للشهادة فقط. صورة القرص هي 1 MiB من الأصفار بحيث تكتب bounce 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 نطاقًا، لا نقطة بداية. أبقِ على رفض البداية داخل BAR0 كضابط لـ CVE-2021-3929.
4fc49f46dc95d4a27de2509e7fceb2931e91faebnvme_map_addr / nvme_addr_is_iomemGNU Affero GPL v3.0. راجع LICENSE. مختبر loopback فقط. دون أي ضمان.