QEMU PVRDMA shared-buffer use-after-free (CVE-2022-1050)¶
Crafted bir PVRDMA guest driver'ı, Device Shared Region buffer'ı allocate edilmeden önce hardware command'lerini execute eder; böylece
pvrdma_exec_cmd()backing'i olmayan/dangling bir shared buffer üzerinde işlem yapar — host QEMU process'inde bir use-after-free.
Mechanism¶
Note
PVRDMA hardware command'leri host'ta pvrdma_exec_cmd() tarafından dispatch
edilir; bu da request'i okur ve response'u Device Shared Region (DSR)
buffer'ları (dsr_info.dsr) aracılığıyla yazar. Bu shared buffer'lar, guest
DSR'yi programladığında kurulur (DSR-register init path'ine bak); command
execution yalnızca onlar var olduğunda anlamlıdır.
Isolation invariant'ı şudur: device, command'leri backing eden shared
buffer'lar allocate edilip geçerli kalana kadar command'leri execute
etmemeli. Bug, pvrdma_exec_cmd()'in kullanmadan önce DSR'nin allocate
edildiğini doğrulamamasıdır. Bir guest, shared buffer'lar henüz allocate
edilmemişken — kasıtlı olarak (kötü niyetli guest) ya da bir guest/host
address-mapping hatası aracılığıyla — command execution'ı sürebilir; böylece
command path'i backing'i olmayan ya da zaten free edilmiş bir shared buffer'ı
dereference eder. Bu, host process'inde bir use-after-free'dir: QEMU'yu
crash'leyebilir ve grooming ile daha güçlü bir host memory-safety primitive'i
hâline gelir. Guest tarafından gönderilen command'lerden ulaşıldığı ve host
ayrıcalıklarıyla çalıştığı için guest→host sınırını aşar.
Walkthrough¶
Üst düzey, public Red Hat advisory'sinden ve upstream patch "hw/pvrdma: Protect against buggy or malicious guest driver" dan. Yalnızca kavramsal:
- Guest driver, DSR shared buffer'ları düzgün şekilde allocate edilmeden önce (ya da bir mapping hatası onları geçersiz bıraktıktan sonra) hardware command'leri submit etmeyi ayarlar.
- Guest command execution'ı tetikler; host'ta dispatcher
pvrdma_exec_cmd()'e girer. -
pvrdma_exec_cmd(), öncedsr_info->dsr'nin allocate edildiğini kontrol etmeden DSR aracılığıyla request'i okumaya / response'u yazmaya devam eder. -
O guard olmadan, command path'i backing'i olmayan / dangling bir shared buffer'a dokunur — QEMU'yu crash'leyen (availability) ve prensipte host memory corruption'ına bir basamak taşı olan bir use-after-free.
Upstream fix, !dsr_info->dsr check'ini ekler; böylece shared region allocate
edilmemişken command'ler reddedilir.
Observable effect on an unpatched build
Vulnerable bir build'de, DSR allocation'ından önce command execute etmek bir
QEMU crash'i ya da AddressSanitizer altında pvrdma_exec_cmd()'de köklenen bir
heap-use-after-free raporu üretir.
Warning
Tarihsel, düzeltilmiş bir bug (CVE-2022-1050; QEMU 7.x / 8.0 serisinde düzeltildi). Yalnızca disclose edilen guard ve yapı gösteriliyor — hiçbir offset, heap-grooming reçetesi ya da uçtan uca host exploit'i yok.
Detection¶
- Untrusted bir guest'ten gelen PVRDMA command trafiğinden sonra backtrace'i
pvrdma_exec_cmdiçeren ASan heap-use-after-free raporları ya da QEMU SIGSEGV. - DSR (re)initialization'ından önce / civarında gönderilen PVRDMA command'leri ile korele QEMU domain crash'lerini gösteren host/libvirt log'ları.
- Patch'lenmiş build'lerde
rdma_error_reporttarzı "buggy or malicious guest driver" log satırları, bir guest'in allocate edilmiş bir DSR olmadan command denediğini gösterir.
Mitigation¶
pvrdma_exec_cmd()'edsr_info->dsrallocation check'ini ekleyen upstream fix'i uygula (QEMU ≥ 7.0 / distro paketlerine backport'landı).- PVRDMA device'ını untrusted guest'lere expose etme — RDMA'nın gerekli olmadığı yerlerde device model'inden çıkararak bu guest→host surface'ini tamamen kaldır.
- QEMU'yu libvirt altında SELinux/sVirt ve seccomp ile unprivileged çalıştır; böylece bir UAF sandbox'lanmış process'e sınırlı kalır; CI'da device command path'lerinin ASan/UAF-aware fuzzing'ini kullan.
References¶
- Red Hat Bugzilla — CVE-2022-1050: pvrdma use-after-free in pvrdma_exec_cmd()
- qemu-devel — [PATCH v3] hw/pvrdma: Protect against buggy or malicious guest driver
- QEMU commit 31c4b6fb0293 — hw/pvrdma DSR allocation guard
- Related: use-after-free primitive, PVRDMA REG_DSRHIGH uninit pointer, PVRDMA page-table OOB read DoS