QEMU PCNET network device emulation overflow¶
QEMU'nun AMD PC-Net II (
pcnet) emulation'ında bir heap buffer overflow (CVE-2015-7504): loopback mode'da ADDFCS'li bir received frame, sabit 4096-byte'lıkbuffer'ın ötesine bir CRC ekleyerek host'taki komşu birqemu_irqpointer'ını corrupt eder.
Mechanism¶
Note
QEMU'nun pcnet NIC model'i, received-frame byte'larını PCNetState
içindeki sabit bir uint8_t buffer[4096]'da tutar. Isolation invariant'ı,
pcnet_receive()'in o buffer'a asla 4096 byte'tan fazla yazmamasıdır. Bug,
loopback test mode'unun ADDFCS transmit-descriptor flag'i ile
birleşmesindedir: ADDFCS set edildiğinde, model frame'e 4-byte'lık bir
Ethernet FCS/CRC ekler (src[size+0..3] = ...; size += 4;) ama size'ı
buffer'a karşı yeniden kontrol etmez. Tam 4096-byte'lık bir loopback frame
süren bir guest, CRC append'inin 4096..4099 index'lerine yazmasını sağlar —
out of bounds, doğrudan struct'ta buffer'ı takip eden field'ın, yani
qemu_irq irq pointer'ının üzerine.
Bu, guest→host sınırını aşar çünkü PCNetState QEMU host process'inde yaşar.
Overflow, bir host function/IRQ pointer'ının üzerine guest-controlled byte'lar
yazar; QEMU daha sonra device IRQ'yu raise ettiğinde (qemu_set_irq() corrupt
olmuş IRQState'i dereference eder ve handler'ını çağırır), control flow
yeniden yönlendirilebilir — QEMU ayrıcalıklarıyla host code execution. Bir
guest'in controller'ı loopback'e programlaması için CAP_SYS_RAWIO gerekir.
(Phrack QEMU case study tam olarak bu struct adjacency'sini weaponize eder.)
Kardeş not QEMU RTL8139 network device emulation overflow ile karıştırma: bu (PCNET, CVE-2015-7504) bir OOB write/overflow primitive'idir (host pointer'ı corrupt eder), RTL8139 (CVE-2015-5165) ise farklı bir device'ta farklı bir bug class olan bir out-of-VM read / heap info-leak'tir. Tam bir escape'te ikisi tamamlayıcıdır — leak ASLR'yi yener, bu write control flow'u ele geçirir — ama ayrı CVE'ler ve ayrı tekniklerdir.
Walkthrough¶
Public, halihazırda patch'lenmiş materyal: Phrack 70 "VM escape — QEMU Case Study" ve Red Hat/Debian advisory'leri. Yalnızca kavramsal reproduction path'i:
- Guest'ten, pcnet controller'ını loopback test mode'una programla ve transmit descriptor'da ADDFCS'i etkinleştir.
- Loopback'te
pcnet_receive()'inbuffer'a ~4096 byte kopyalayacağı şekilde boyutlandırılmış bir frame transmit et. - ADDFCS path'i,
size'dan sonra 4 CRC byte'ı ekleyerekbuffer[4096]'in ötesine, komşuirqpointer field'ına yazar. - Frame'i, hesaplanan CRC'si seçilen bir değere eşit olacak şekilde seçerek
attacker,
irq'nun üzerine controlled bir pointer yazar; bir sonrakiqemu_set_irq()onu dereference eder.
Warning
Tarihsel, patch'lenmiş bir issue (CVE-2015-7504). Yalnızca kavramsal — burada hiçbir host heap layout'u, gadget address'i ya da tam escape chain'i sağlanmıyor.
Vulnerable shape (illustrative, from the public write-up)
/* hw/net/pcnet.c, pcnet_receive() — src = s->buffer (4096 byte) */
if (!s->looptest) {
memcpy(src, buf, size);
/* non-loopback: 4 zero FCS byte'ı eklenir (yine size += 4) */
src[size] = src[size+1] = src[size+2] = src[size+3] = 0;
size += 4;
} else { /* loopback test mode + ADDFCS */
uint32_t fcs = ~0;
uint8_t *p = src;
while (p != &src[size]) CRC(fcs, *p++);
*(uint32_t *)p = htonl(fcs); /* size may already == 4096 -> */
size += 4; /* OOB CRC write over adjacent irq ptr */
}
Beklenen gözlem: bir guest'ten gelen loopback-mode pcnet aktivitesinin ardından QEMU crash/corruption; non-exploit bir denemede ise host tarafında bir abort.
Detection¶
- Host tarafı: pcnet loopback aktivitesi ile korele QEMU
qemu/qemu-kvmcrash'i; ASanpcnet_receive'de bir heap-buffer-overflow write flag'ler. - Behavioral: bir guest'in pcnet loopback test mode + ADDFCS'i etkinleştirmesi ve max-size frame'ler göndermesi, herhangi bir gerçek driver için anormaldir.
- İlgili kardeş CVE-2015-7512, non-loopback large-MTU overflow varyantını kapsar.
Mitigation¶
- CVE-2015-7504 için QEMU fix'ini uygula (
pcnet_receive()içinde receive size'ını — eklenen FCS dahil —sizeof(buffer)'a karşı bound et). - Modern bir NIC model'i (virtio-net / e1000e) tercih et ve ihtiyaç duymayan guest'lerden legacy pcnet device'ını kaldır.
- Defense-in-depth: QEMU'yu sandbox'lanmış/deprivilege edilmiş olarak çalıştır (seccomp, SELinux/sVirt); böylece bir host-process overflow'u tam host kontrolü olmaz.
References¶
- Talbi & Fariello, "VM escape — QEMU Case Study", Phrack 70:5: https://phrack.org/issues/70/5
- Red Hat Bugzilla (CVE-2015-7504, pcnet heap overflow / XSA-162): https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2015-7504