Skip to content

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.

  1. 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.

  2. 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)
  1. Yüzlerce frame'den sonra host stack'i overflow eder. ASAN/debug build'leri, intel_hda_corb_run ve DMA/physical-memory translation katmanı boyunca uzun tekrarlanan bir frame pattern'iyle AddressSanitizer: stack-overflow raporlar.

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_run dö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/memcpy path'inde tetiklenen AddressSanitizer: 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/hda audio 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.

References