Skip to content

QEMU USB EHCI reachable assertion / DMA map failure DoS

QEMU'nun EHCI USB controller emülasyonundaki kontrol edilmeyen bir DMA-map failure, bir guest'in bir USB packet'i, sonraki usb_packet_unmap()'in bir reachable assertion'a çarptığı bir state'e sürüklemesine ve host QEMU process'ini abort etmesine izin verir (CVE-2020-25723).

Mechanism

İzolasyon invariant'ı: başarısız bir DMA map host'u değil, transfer'i abort etmelidir

Bir USB transfer'i emüle etmek için EHCI, guest-physical buffer'ları (guest'in programladığı qTD/iTD data pointer'larından) dma_memory_map() çağıran usb_packet_map() üzerinden host'un kullanabileceği bir scatter/gather list'e map'ler. Bu map meşru olarak başarısız olabilir — örneğin guest, transfer'i map'lenemeyen bir adres aralığına (MMIO, map'lenemeyen bir delik veya tükenmiş bir bounce-buffer/IOMMU penceresi) yönelttiğinde. Controller'ın koruması gereken invariant şu: mapping başarısız olursa, packet'i temizce fail et.

EHCI model'i, usb_packet_map()'in return değerini kontrol etmiyordu. İşleme, buffer map'lenmiş gibi devam etti ve sonraki bir usb_packet_unmap() (veya hw/usb/hcd-ehci.c içindeki packet state'ini koruyan assertion), guest'in bozuk transfer'inin false hâle getirdiği bir assert()'e çarptı. assert(), abort() çağırdığı için, guest-controlled bir koşul, host QEMU process'ini deterministik olarak sonlandırır. Sınır aşımı, klasik "reachable assertion"dır: guest input, ulaşılamaz varsayılan bir host invariant'ına ulaşır.

Walkthrough

oss-security açıklamasına ve Red Hat Bugzilla 1898579'a dayanır; upstream'de usb_packet_map() return değerini kontrol ederek düzeltildi.

  1. Guest, EHCI'ye bağlı bir USB device'ı ekler/kullanır (controller mevcut olmalıdır, örn. -device usb-ehci).

  2. Guest, data buffer pointer'ı QEMU'nun bir host buffer'ına DMA-map edemediği guest-physical memory'yi referans alan bir transfer descriptor (qTD) kurar.

  3. EHCI'nin transfer path'i, buffer'ı çevirmek için usb_packet_map() çağırır; çağrı başarısız olur ama return değeri yok sayılır, böylece packet tutarsız bir state'te ilerler.

    Fix'in kavramsal şekli (map sonucunu kontrol et)
    /* hw/usb/hcd-ehci.c — illustrative of the upstream fix direction */
    if (usb_packet_map(&p->packet, &p->sgl)) {
        /* DMA map failed: tear down cleanly instead of
           proceeding to a later usb_packet_unmap() assert() */
        qemu_sglist_destroy(&p->sgl);
        return -1;
    }
    
  4. Patch'siz model'de transfer, usb_packet_unmap() / packet-state assertion'ına ulaşır, bu da false olarak değerlendirilir ve abort() tetikler.

  5. Gözlemlenebilir sonuç: QEMU, hw/usb/hcd-ehci.c'yi adlandıran bir assertion mesajı yazdırır ve QEMU process'i çıkar — guest içinden bir host denial of service.

Tarihî / patch'li

Düşük şiddetli DoS (host code execution yok), açıklanmış ve düzeltilmiş. Yalnızca patch'li/lab sistemlerde, yetkili defensive testing için kullan.

Detection

  • Crash signature: usb_packet_unmap / hw/usb/hcd-ehci.c'yi referans alan bir assertion failure ile QEMU'nun abort etmesi doğrudan parmak izidir.
  • Core/abort monitoring: QEMU'dan gelen SIGABRT'yi bir security event olarak ele al; guest USB etkinliğiyle tetiklenen bir assert()-driven çıkış anormaldir.
  • Fuzzing: qTD/iTD buffer pointer'larını map'lenemeyen aralıklara doğru mutate eden USB-controller fuzzing'i, bu ailedeki reachable-assertion bug'larını yeniden üretir; bkz. ../hypervisor/snapshot-based-greybox-hypervisor-fuzzing.md.
  • Guest behavior: buffer'ları normal RAM dışına (MMIO/map'lenmemiş aralıklara doğru) düşen USB transfer'lerini tekrar tekrar programlayan bir guest şüphelidir.

Mitigation

  • Patch: usb_packet_map() return değerini kontrol eden ve sonradan assert etmek yerine transfer'i fail eden QEMU 5.2.0 veya sonrasına güncelle (fix commit 2fdb42d840400d58f2e706ecca82c142b97bcbd6).
  • Reduce attack surface: USB gerekmedikçe bir EHCI controller'ı güvenilmeyen guest'lere açma; minimal/gerekli controller model'ini tercih et.
  • Confinement: QEMU'yu seccomp (-sandbox on) ve sVirt/SELinux'lü unprivileged bir uid altında çalıştır, böylece abort olmuş bir process contained olur ve management tooling tarafından host etkisi olmadan auto-restart edilir.
  • Operational: guest kaynaklı tekrarlayan QEMU abort'larını geçici crash'ler olarak ele almak yerine onlar için alert ver.

References