QEMU intel-hda DMA-reentrancy stack overflow (CVE-2021-3611)¶
Kötü niyetli bir guest, emüle Intel HD Audio controller'ını DMA yoluyla kendi command processor'una re-enter ettirip host stack'ini tüketebilir ve QEMU'yu crash'letebilir (guest-to-host DoS).
Mechanism¶
Bug sınıfı: device MMIO yoluyla sınırsız DMA reentrancy / recursion
Intel HDA controller'ı, intel_hda_corb_run() içinde guest-programlanan bir
Command Output Ring Buffer (CORB) işler. Ring'i çalıştırmak DMA içerir: device,
ldl_le_dma() / stl_le_pci_dma() gibi helper'lar üzerinden guest physical
memory'yi okur/yazar. Kırılan invariant, bir device'ın DMA target'ının sıradan
RAM olduğunun varsayılması, dolayısıyla bir DMA access'inin senkron olarak device
emülasyonuna re-enter edemeyeceğidir.
Modern bir QEMU'da bir device'ın DMA yaptığı address, global memory map üzerinden
çözümlenir; bu MMIO region'larını — HDA controller'ının kendi register'ları dahil
— içerir. Bir guest, CORB/response DMA pointer'larını, ring işlenirken yapılan bir
DMA write'ının HDA MMIO penceresinin içine geri düşeceği şekilde programlayabilir. O
MMIO write, HDA register-write handler'ını senkron olarak yeniden çağırır, bu da
intel_hda_corb_run()'ı yeniden tetikler — recursive olarak, derinlik sınırı
olmadan.
Her recursion, host'ta C stack frame'leri ekler. Guest aliasing'i kontrol ettiği ve döngüyü sürdürebildiği için, recursion host thread'inin stack'i tükenene dek çalışır ve bir stack overflow (SIGSEGV) üretir. Sınır aşılır çünkü guest-controlled DMA address'leri host control flow'unu sınırsız self-recursion'a yönlendirir — klasik bir device DMA reentrancy hatası, burada bir heap corruption yerine bir stack OOB olarak düşer.
Walkthrough¶
Public GitLab issue ve ASAN trace'ine dayalı kavramsal reproduction.
-
Guest, HDA controller'ını yapılandırır ve CORB/response DMA region'unu controller'ın kendi MMIO aralığına geri alias yapan bir address'e işaret ettirir.
-
CORB engine'i başlatmak device'ın "komutları işlemesine" neden olur, ama her DMA write-back command işlemesini yeniden tetikler.
Conceptual recursion (logical fragments, not an exploit)
intel_hda_corb_run()
-> ldl_le_dma()/stl_le_pci_dma() # DMA touches guest "memory"
-> address resolves to HDA MMIO # alias back into own registers
-> intel_hda_mmio_write() # synchronous device write handler
-> intel_hda_corb_run() # re-entered, deeper stack frame
-> ... (repeats until host stack is exhausted)
- Yüzlerce frame'den sonra host stack'i overflow eder. ASAN/debug build'leri,
intel_hda_corb_runve DMA/physical-memory translation katmanı boyunca uzun tekrarlanan bir frame pattern'iyleAddressSanitizer: stack-overflowraporlar.
Asıl bug reentrancy'dir, herhangi tek bir fonksiyon değil
Hata yapısaldır: aynı emülasyon path'i, gerçekleştirdiği bir yan etki (DMA) yoluyla re-enter edilebilir. Bu, bir device'ın kendi access'inin device modeline geri döngülendiği diğer QEMU DMA-reentrancy sorunlarıyla aynı kök neden ailesidir.
Fix (QEMU 7.0.0 ile gönderildi), daha geniş DMA-reentrancy sertleştirmesinin bir parçasıdır: device modelleri DMA yoluyla senkron olarak re-enter edilmeye karşı korunur, böylece recursive loop stack tüketilmeden önce kırılır.
Detection¶
Host ve telemetry sinyalleri
- Crash signature: tekrarlanan bir
intel_hda_corb_rundöngüsünden oluşan çok derin bir call stack'e sahip QEMU SIGSEGV — normal tek-frame'lik bir fault'a karşı ayırt edici. - ASAN build'leri: HDA command işlemesi altında physical-memory/
memcpypath'inde tetiklenenAddressSanitizer: stack-overflow. - Behavioural anomaly: HDA CORB/RIRB DMA base register'larını (RAM yerine) PCI MMIO BAR aralıklarına işaret edecek şekilde programlayan bir guest anormaldir; device MMIO'ya alias yapan DMA descriptor'ları güçlü bir reentrancy göstergesidir.
- Fuzzing parity: bu sınıf rutin olarak
qtest/libfuzzer device harness'leri tarafından yüzeye çıkarılır — aynı harness'ler iyi regression detector'ları olur.
Mitigation¶
Remediation
- Patch: intel-hda DMA reentrancy fix'ini içeren QEMU 7.0.0 ya da sonrasına (ya da bir distro backport'una, örn. RHEL/SUSE güncellemeleri) yükseltin.
- Reduce attack surface: audio'ya ihtiyaç duymayan guest'lerden
intel-hda/hdaaudio device'ını atlayın; sunucularda emüle sound card olmamasını tercih edin. - Compiler/OS defenses: stack overflow guard page'ler tarafından yakalanır (temiz bir abort'a çevrilir); QEMU'yu stack korumalarıyla derlemek ve test filolarında ASAN altında çalıştırmak regression'ları erken yakalamaya yardımcı olur.
- Confinement: QEMU'yu
-sandbox on(seccomp) ve SELinux/AppArmor ile çalıştırın ki bir crash sınırlansın ve tek bir tenant'a atfedilebilir olsun.