Skip to content

QEMU virtio-gpu integer overflow leak chain (virtio-gpu + VNC + SLIRP)

virtio-gpu'nun image-size matematiğindeki bir integer overflow, bounds check'ler için orijinal (devasa) boyutları bırakırken bir host surface'i eksik allocate ediyor; chain'in disclosure yarısı ise QEMU'nun kendi VNC server'ını bir SLIRP loopback bağlantısı üzerinden (10.0.2.2:5900) sürerek host heap'ini guest'e geri okuyor.

Mechanism

Note

virtio-gpu, guest'in sağladığı width, height ve pixel format'tan boyutlandırılmış host tarafı bir backing surface allocate eder. Boyut, width * bpp'den bir stride türeten ve height * stride döndüren calc_image_hostmem() tarafından hesaplanır. İzolasyon invariant'ı şudur: guest'in sağladığı her boyut range-check edilmeli, böylece allocation en az aynı boyutları kullanan her sonraki erişim kadar büyük olmalıdır. Bug bunu kırıyor: 0x40000000 civarında bir guest width ve 32-bit pixel'lerle width * bpp (ve yuvarlanmış stride) 32 bit'i overflow eder, böylece allocation birkaç yüz byte'a çöker — ancak truncate edilmemiş width hâlâ res->width'te saklanır ve sonraki transfer/scanout bound'ları için kullanılır. Sonraki 2D transfer'ler (transfer_to_host_2d) ardından guest byte'larını minik host buffer'ının çok ötesine yazar: guest-kontrollü bir host-heap out-of-bounds write'ı. Eşleşen read / leak primitive'i QEMU'nun SLIRP loopback üzerinden erişilen VNC server'ını yeniden kullanır: guest, emulate edilmiş NIC'i üzerinden 10.0.2.2:5900'e (QEMU'nun kendi VNC port'u) bir TCP socket açar ve bir FramebufferUpdateRequest gönderir; QEMU aktif scanout surface'ini — ham QEMU heap byte'larını — guest'e "pixel" olarak geri serialize eder. Over-allocate edilmiş/over-read edilmiş surface'i VNC readback'iyle birleştirmek, OOB write'la eşleşip bir guest→host escape chain'i oluşturan ASLR-kıran bir heap info-leak verir.

Walkthrough

Public kaynak: Calif.io, "MAD Bugs: QEMU and UTM Escape" (ZDI-CAN-27578; QEMU 11.0.0'da düzeltildi). Kavramsal path, yalnızca açıklayıcı fragment:

  1. Yayımlandığı haliyle overflow eden size routine'i:
static uint32_t calc_image_hostmem(pixman_format_code_t pformat,
                                   uint32_t width, uint32_t height) {
    int bpp    = PIXMAN_FORMAT_BPP(pformat);
    int stride = ((width * bpp + 0x1f) >> 5) * sizeof(uint32_t);
    return height * stride;   /* overflows for large width */
}
  1. Guest width = 0x40000001, bpp = 32 ile bir 2D resource oluşturur; stride sarmalanır ve yalnızca minik bir buffer allocate edilir, oysa res->width büyük değeri korur.
  2. OOB write: bir transfer_to_host_2d (ya da resource-flush/attach path'i) büyük boyutları kullanarak guest-kontrollü byte'ları kopyalar ve küçük boyutlu host allocation'ının ötesine yazar.
  3. OOB read / leak: guest içinden, SLIRP üzerinden 10.0.2.2:5900'e bir TCP bağlantısı açın, bir FramebufferUpdateRequest gönderin ve width*height*4 ham heap byte'ı alın — VNC server QEMU heap içeriğini "sanki bir ekran koruyucuymuş gibi" geri verir ve ASLR'yi kırar.
  4. Leak ve write ile, surface/pixman_implementation_t tarzı indirect pointer'lar control flow'a doğru bozulur (public writeup bunu macOS arm64 / UTM emulation mode'da gösterir).
Gözlemlenebilir etki

Patch'lenmemiş bir build'de OOB write bir virtio-gpu host-heap corruption üretir (transfer path'inde ASan OOB-write); VNC-over-SLIRP read'i guest'e non-display heap verisi döndürür. İyi niyetli guest'ler asla 0x40000001 genişliğinde resource istemez ya da guest içinden host'larının VNC port'una bağlanmaz.

Warning

Açıklanmış, düzeltilmiş chain (ZDI-CAN-27578, QEMU 11.0.0). Public writeup seviyesinde gösterilmiştir — under-allocation root cause'u ve leak primitive'i — tam silahlandırılmış macOS payload'ı ya da heap-grooming reçetesi yeniden üretilmeden.

Detection

  • Bir resource aşırı bir width/height ile oluşturulduktan sonra virtio-gpu 2D transfer path'lerinde host tarafı ASan/crash; res->width ile backing allocation boyutu arasındaki uyuşmazlık.
  • Network anomalisi: bir guest'in 10.0.2.2'ye (SLIRP gateway) port 5900'de bir TCP bağlantısı açması — yani guest'in host'un kendi VNC server'ına ulaşması — bu leak tekniğinin güçlü bir göstergesidir.
  • virtio-gpu resource-create/transfer komutlarını boundary boyutlarıyla fuzz etmek integer overflow'u yüzeye çıkarır.

Mitigation

  • QEMU 11.0.0+'a (ya da boyutları gerçek allocation'a karşı doğrulayan ZDI-CAN-27578 fix'ini taşıyan bir vendor build'ine) güncelleyin.
  • QEMU'nun VNC server'ını guest'ten erişilebilir adreslere bağlamayın; VNC'yi user-mode SLIRP üzerinden açmaktan kaçının ve 10.0.2.2:5900'ü guest'ten firewall'la engelleyin. Emulate edilmiş NIC üzerinden geri yönlendirilmeyen bir unix-socket ya da yalnızca localhost VNC tercih edin.
  • Guest'in bir display'e ihtiyacı olmadığı yerde virtio-gpu / 3D'yi kapatın; heap corruption'ın sınırlanması için QEMU'yu sandboxing ile unprivileged çalıştırın.

References