QEMU USB EHCI resource consumption DoS¶
EHCI isochronous transfer descriptor'larından (iTD'ler) kapalı bir döngü kuran bir guest, QEMU'nun
ehci_process_itd'sinin list'i sonsuza dek gezmesine yol açar, bir host CPU'sunu %100'de sabitler ve host'u aç bırakır (CVE-2015-8558).
Mechanism¶
İzolasyon invariant'ı: descriptor-list gezintisi sonlanmalıdır
EHCI'nin periodic/async schedule'ları, transfer descriptor'larından guest tarafından kurulan linked list'lerdir. Controller'ın state machine'i (ehci_advance_state), guest'in sağladığı "next" pointer'larını takip eder ve her iTD/siTD'yi ehci_process_itd üzerinden işler. Örtük invariant, guest'in sonlu, sonlanan bir list sağlamasıdır. Bunu zorlayan hiçbir şey yok: guest, next-pointer'ı önceki bir descriptor'a geri işaret eden bir descriptor programlayarak bir döngü oluşturabilir.
Vulnerable kodda, controller gerçek bir isochronous transfer yapmayan descriptor'ları işliyorsa, loop asla ileriye doğru ilerleme kaydetmez ve asla çıkmaz — ehci_advance_state dairesel list boyunca ilerlemeye devam eder. İş, host QEMU vCPU/IO thread'inde çalışır, bu yüzden yalnızca VM-içi ayrıcalığa sahip bir guest, host CPU'sunu süresiz tüketir. Bu, izolasyon sınırını bir resource-exhaustion DoS olarak aşar: guest, host memory'sini okuyamaz ama host scheduling'i ele geçirir.
Walkthrough¶
Red Hat Bugzilla 1277983'e ve upstream fix'e (commit 156a2e4dbffa85997636a7a39ef12da6f1b40254) dayanır.
-
Guest'in bir EHCI controller'ı vardır (
-device usb-ehci) ve periodic frame list / async schedule'ı programlar. -
Guest, link pointer'ı önceki bir iTD'yi referans alan bir iTD oluşturur, kapalı bir döngü yaratır ve descriptor'ları, gerçekte hiçbir active transaction yapılmayacak şekilde düzenler.
-
Controller,
ehci_advance_state→ehci_process_itd'ye girer ve döngüyü takip eder. Tüketilecek active transfer olmadan ve sonlanma olmadan, işleme sonsuza dek tekrar eder.Fix'in kavramsal şekli (hiçbir transfer olmadığında error döndür)
/* hw/usb/hcd-ehci.c — direction of the upstream fix */ static int ehci_process_itd(EHCIState *ehci, EHCIitd *itd, uint32_t addr) { int xfers = 0; /* ... for each active transaction: do the transfer; xfers++ ... */ /* If we processed no active transaction, signal an error so the scheduler stops instead of looping on a descriptor cycle. */ return xfers ? 0 : -1; }xfers == 0olduğunda-1döndürmek, caller'ın schedule gezintisinden çıkmasını sağlar, böylece guest tarafından kurulan bir iTD loop'u artık sonsuza dek dönemez. -
Host'taki gözlemlenebilir sonuç: bir QEMU thread'i bir CPU çekirdeğini %100'de sabitler; guest ve host yanıt vermez hâle gelir (DoS), crash olmadan.
Tarihî / patch'li
Orta şiddetli DoS (CPU/resource exhaustion, memory disclosure veya code execution yok), açıklanmış ve upstream'de düzeltilmiş. Yalnızca lab/defensive kullanım.
Detection¶
- Host CPU signature: guest boştayken %100'de takılı tek bir QEMU IO/vCPU thread'i birincil göstergedir; zamanın
ehci_process_itd/ehci_advance_stateüzerinde yoğunlaştığını gösteren bir host profiler/perf örneği bunu doğrular. - Liveness watchdogs: guest workload'u olmadan tam bir host çekirdeğini tüketen bir VM'i işaretleyen management-plane sağlık kontrolleri bu DoS'u yüzeye çıkarır.
- Fuzzing: iTD/siTD link pointer'larını döngülere mutate eden USB schedule fuzzing'i, bunu ve ilişkili EHCI loop bug'larını yeniden üretir (kardeş bir siTD varyantı ayrıca raporlandı).
- Related sibling bug: siTD işleme path'inin oss-security'de benzer bir infinite-loop raporu vardı; detection mantığı hem iTD hem de siTD gezintilerini kapsamalıdır.
Mitigation¶
- Patch: hiçbir transfer olmadığında
ehci_process_itd'nin bir error döndürmesini sağlayan, böylece scheduler'ın bir descriptor döngüsünü gezmeyi durdurduğu commit156a2e4dbffa85997636a7a39ef12da6f1b40254(2.5.x / distroqemu 1:2.5+dfsg-2ve sonrasında dağıtıldı) içeren QEMU'ya güncelle. - Reduce surface: USB'ye ihtiyaç duymayan guest'ler için EHCI controller'ı dahil etme; gereken minimal controller model'ini tercih et.
- Resource caps: QEMU vCPU ve emülatör thread'lerini pin'le/sınırla (cgroups CPU quota,
cputune), böylece döngüye giren bir device model tüm host'u aç bırakamaz. - Confinement: QEMU'yu seccomp ve unprivileged bir uid altında çalıştır, böylece hatalı davranan bir guest kendi slice'ına contained olur.