QEMU eepro100 DMA-reentry stack overflow (CVE-2021-20255)¶
QEMU'nun emüle Intel i8255x (eepro100) NIC'inde guest-to-host bir denial of service; burada guest-programlanan DMA, device'ın controller-command handler'ına re-enter ederek host QEMU process'i stack'ini tüketene dek sınırsız recursion yapar.
Mechanism¶
Note
eepro100 modeli (hw/net/eepro100.c), guest-driven bir command block (CB)
listesi işler: her command descriptor'ı guest memory'den DMA'lar, üzerinde işlem
yapar ve bir sonrakine olan link'i izler. Örtük invariant, DMA read'lerin sıradan
guest RAM'i hedeflemesi ve command işlemenin ileri ilerleme kaydetmesidir.
CVE-2021-20255'te bir guest, controller'ı, bir command işlenirken yapılan bir
DMA'nın device'ın kendi command-processing path'ine re-enter edeceği şekilde
(bir DMA-reentrancy koşulu) programlayabilir. Bu path'te hiçbir şey derinliği
sınırlamadığı ya da döngüyü kırmadığı için, handler her re-entry'de kendini geri
çağırarak sınırsız bir recursion inşa eder. Host QEMU thread'inin call
stack'i overflow edene dek büyür ve process'i abort eder. Corruption host'ta
olduğu için, low-privileged bir guest guest→host sınırını bir denial of service
olarak aşar (ve crash'ten önce yanan host CPU'su).
Bu, QEMU DMA-reentrancy UAF/loop ailesinin bir stack-exhaustion kardeşidir — qemu-e1000e-mmio-address-use-after-free içindeki heap-UAF şekliyle ve qemu-e1000-tx-descriptor-infinite-loop içindeki infinite-loop şekliyle karşılaştırın.
Walkthrough¶
Public, hâlihazırda patch'lenmiş advisory'den (oss-security, Red Hat / SUSE Bugzilla, upstream qemu-devel patch). Yalnızca kavramsal reproduction.
- Guest, eepro100'ü ayağa kaldırır ve kontrol ettiği memory'de bir command-block listesi inşa eder.
- DMA access'i (descriptor fetch / data move) device'a geri çözümlenen bir command ayarlar, böylece bir command'ı işlemek düz RAM'e dokunmak yerine controller-command routine'ine re-enter eder.
- Her re-entry, bir derinlik sınırı ya da cycle break olmadan command-processing call chain'inin bir başka frame'ini push eder — infinite recursion.
- Host QEMU thread'inin stack'i overflow edene dek büyür; process abort eder (guard page üzerinde SIGSEGV) — temiz bir host DoS.
Warning
Tarihsel, patch'lenmiş bir sorun (5.x dönemine kadar QEMU'yu etkiler). Bu giriş kavramsal kalır: tuning yapılmış bir recursion-depth primitive'i ya da herhangi bir escape değil, bug sınıfını ve invariant'ı adlandırır.
Reentrancy-guard concept (closes the class)
/* a device I/O dispatch refuses to recurse into itself */
if (dev->mem_reentrancy_guard.engaged_in_io) {
return; /* drop / error the re-entrant access instead of recursing */
}
dev->mem_reentrancy_guard.engaged_in_io = true;
/* ... process command ... */
dev->mem_reentrancy_guard.engaged_in_io = false;
Detection¶
- Host tarafı: bir stack-overflow imzasına sahip QEMU crash'i — backtrace'i derin,
tekrarlanan eepro100 command-processing frame'leri (
hw/net/eepro100.c) gösteren bir SIGSEGV; AddressSanitizer "stack-overflow" raporları. - Resource telemetry: QEMU process'i ölmeden hemen önce eepro100 path'inde bir vCPU'yu sürekli %100'e süren bir guest, güçlü bir DoS sinyalidir.
- Behavioral: DMA target'ları RAM yerine device MMIO'ya çözümlenen NIC command-block descriptor'ları, herhangi bir meşru driver için anormaldir.
Mitigation¶
- CVE-2021-20255 için upstream QEMU fix'ini uygulayın ve device
mem_reentrancy_guardreentrancy korumasına sahip bir build çalıştırın (distro backport'ları: Debian, Ubuntu, Red Hat, SUSE). - Untrusted guest'ler için legacy emüle eepro100 yerine
virtio-net'i tercih edin. - Defense-in-depth: QEMU'yu confine edin (seccomp, SELinux/sVirt, unprivileged kullanıcı) ve otomatik guest restart/quarantine politikalarını enable edin ki bir host DoS sınırlansın.
References¶
- oss-security — CVE-2021-20255 (eepro100 stack overflow via infinite recursion): https://www.openwall.com/lists/oss-security/2021/02/25/1
- Red Hat Bugzilla 1930646 — CVE-2021-20255: https://bugzilla.redhat.com/show_bug.cgi?id=1930646
- SUSE Bugzilla 1182651 — CVE-2021-20255: https://bugzilla.suse.com/show_bug.cgi?id=1182651