Paravirtualized device descriptor confusion (virtio used-ring metadata abuse)¶
Split-ring'in bir tarafının, diğer tarafın sağladığı ring metadata'sına bounds-check yapmadan güvendiği bir virtio bug sınıfı — sahte bir used-ring entry'sinin
id'si ya dalen'i doğrudan bir array index'i ya da copy length'i olarak kullanılır ve trust boundary boyunca out-of-bounds memory corruption üretir.
Mechanism¶
Note
virtio bir split virtqueue kullanır: bir descriptor table, bir available ring
(driver -> device: hangi buffer'lar hazır) ve bir used ring (device -> driver: hangi
buffer'lar tüketildi ve kaç byte yazıldı). Her struct vring_used_elem device
tarafından yazılan iki field taşır: id (tamamlanan chain'in head descriptor
index'i) ve len (yazılan byte'lar).
Güvenlik kontratı, her tarafın diğer tarafın kontrol ettiği metadata'yı validate etmesidir. Bug sınıfı bu validation eksik olduğunda ortaya çıkar:
idconfusion: bir consumer used ring'denid'yi okur veid < queue->numkontrolünü yapmadan onu doğrudan sabit boyutlu bir per-descriptor info array'ini (info[id],recv_events[id], ...) index'lemek için kullanır. Aralık dışı biridbir out-of-bounds array access'ine (read ya da write) dönüşür.lenunderflow: kodlen - header_sizegibi bir payload boyutu hesaplar; sahte birlenheader'dan küçükse, unsigned çıkarma kocaman bir değere underflow eder, bu da sonra fazla büyük birmemcpy'yi sürer — bir out-of-bounds write.
Kırılan invariant ring-metadata, paravirtual boundary boyunca untrusted input'tur.
Simetrik olarak, host/QEMU tarafında aynı tehlike driver tarafından kontrol
edilen descriptor-table/available-ring field'ları (length'ler, index'ler, zincirlenmiş
next pointer'lar) için vardır: guest tarafından sağlanan bir descriptor length/index'e
güvenen emulated bir device OOB'a sürülebilir — bu confusion'ın device-emulation biçimi
ve bir guest-to-host escape vektörü.
Walkthrough¶
Public reference: used-ring id/len validation boşluklarını belgeleyen RT-Thread
advisory'si (RT-Thread/rt-thread#11326); ring layout'u için OASIS virtio spec'i.
Kavramsal reprodüksiyon (consumer tarafı, id confusion):
- Kötü niyetli producer (ele geçirilmiş bir backend ya da host tarafı aynada kötü
niyetli bir guest driver),
id>= queue size olan birvring_used_elemyazar. - Consumer onu dequeue eder ve hiç bound check'i olmadan
info[id]yapar: - Aralık dışı index sabit array'in ötesini okur/yazar ve komşu state'i corrupt eder.
len underflow varyantı (virtio-net tarzı):
payload = e.len - VIRTIO_NET_HDR_SIZE; // e.len < HDR_SIZE -> unsigned wrap
rt_memcpy(dst, src, payload); // huge length -> OOB write
Beklenen gözlemlenebilir: hazırlanmış bir used ring ile consumer crash eder ya da komşu veri yapıları corrupt olur — "doğrudan ve güvenilir" bir cross-trust-boundary corruption primitive'i.
Warning
Yalnızca kontrol ettiğin sistemlere karşı test et. Aynı pattern host tarafında (guest descriptor length'lerine/index'lerine güvenen QEMU/vhost emulated device'ları) klasik bir VM-escape yüzeyidir — bu KB'deki QEMU virtio CVE'lerine bak (virtio-net descriptor UAF, virtio DMA reentrancy double-free).
Detection¶
- Code audit: used-ring
id/len'inin (ya da device tarafında descriptor-table length/index'inin) her kullanımı, bir index ya da copy size olarak kullanılmadan önce bounds-check'lenmelidir. - Ring metadata'sını (aralık dışı
id, sub-headerlen) driver/device'a karşı fuzz'la ve OOB fault'ları için izle (ASAN/KASAN).
Mitigation¶
- Index'lemeden önce
id < queue_size'ı validate et; reddet ya da clamp'le. len'den türetilen boyutlar için checked arithmetic kullan; herhangi bir copy'den öncelen >= header_size'ı velen <=gerçek descriptor capacity'sini doğrula.- Diğer taraftan gelen tüm ring metadata'sını düşmanca input olarak ele al; etkilenen virtio driver'ları/device'ları için vendor fix'lerini uygula.
References¶
- RT-Thread advisory — "Malicious virtio backend can trigger guest-kernel memory corruption through unvalidated used-ring ids and lengths" (issue #11326). https://github.com/RT-Thread/rt-thread/issues/11326
- OASIS — "Virtual I/O Device (VIRTIO) Version 1.1" (split virtqueue, used ring,
vring_used_elem). https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html