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:
- 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 */
}
- Guest
width = 0x40000001,bpp = 32ile bir 2D resource oluşturur; stride sarmalanır ve yalnızca minik bir buffer allocate edilir, oysares->widthbüyük değeri korur. - 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. - OOB read / leak: guest içinden, SLIRP üzerinden
10.0.2.2:5900'e bir TCP bağlantısı açın, birFramebufferUpdateRequestgönderin vewidth*height*4ham heap byte'ı alın — VNC server QEMU heap içeriğini "sanki bir ekran koruyucuymuş gibi" geri verir ve ASLR'yi kırar. - Leak ve write ile, surface/
pixman_implementation_ttarzı 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/heightile oluşturulduktan sonra virtio-gpu 2D transfer path'lerinde host tarafı ASan/crash;res->widthile backing allocation boyutu arasındaki uyuşmazlık. - Network anomalisi: bir guest'in
10.0.2.2'ye (SLIRP gateway) port5900'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.