QEMU vhost-user-gpu GET_CAPSET OOB write (CVE-2021-3546)¶
vhost-user-gpu backend'i, max boyutu 0 olan bir capset için
VIRTIO_GPU_CMD_GET_CAPSET'i işlerken capability data'sını bir response buffer'ının ötesine yazar.
Mechanism¶
Sınır neden bozuluyor
virgl_cmd_get_capset() (contrib/vhost-user-gpu/virgl.c) içinde response
buffer'ı virgl_renderer_get_cap_set()'ten boyutlandırılır. İhlal edilen
invariant şu: fill boyutu <= ayrılan buffer boyutu olmalıdır. Sorgulanan
capset id'si max_size == 0 (geçersiz/desteklenmeyen) döndürdüğünde, kod yine
de virgl_renderer_fill_caps() çağırır, bu da ayrı vhost-user-gpu helper
process'inde capability data'sını sıfır boyutlu allocation'ın ötesine yazar
(NVD: CWE-787 OOB write).
Walkthrough¶
Kavramsal, public fix'ten.
- Host,
vhost-user-gpuve virgl/3D acceleration etkinken çalışır. - Guest,
max_size'ı 0 olan bir capset id'si içinVIRTIO_GPU_CMD_GET_CAPSETverir. - Handler, sıfır/yetersiz boyutlu bir buffer ayırır ve caps'i onun ötesine
doldurur → helper process'inde OOB write. Kavramsal olarak:
max_size == 0olan path bir capacity check olmadanvirgl_renderer_fill_caps()'i çağırır, yani caps fill'i ayrılan buffer'ın ötesine taşar.
Aşağıdaki snippet vulnerable code DEĞİL; commit 9f22893a'nın eklediği
corrective check (upstream fix) — fill'den önce max_size == 0'ı reddeden
bounds check'in "fixed shape"i (bkz. Mitigation):
/* fixed shape */
if (max_size == 0) { cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; return; }
Detection¶
- Host-side: Guest 3D etkinliği sırasında
vhost-user-gpuhelper crash; ASan/heap-guard,virgl_cmd_get_capsetiçindeki OOB'yi işaretler. - Behavioral: Desteklenmeyen capset id'leri için GET_CAPSET request'leri anormaldir.
Mitigation¶
- Patch: Allocate/fill etmeden önce
max_size == 0'ıVIRTIO_GPU_RESP_ERR_INVALID_PARAMETERile reddeden commit9f22893a'yı uygula; QEMU 6.0 sonrasında düzeltildi. - Configuration workaround: Güvenilmeyen guest'ler için vhost-user-gpu backend'inde virgl/3D acceleration'ı devre dışı bırak.