Skip to content

QEMU e1000e MMIO-address use-after-free (CVE-2020-15859)

QEMU'nun emüle Intel 82574 (e1000e) NIC'inde guest-to-host bir use-after-free; burada bir guest, bir transmit paketinin data address'ini e1000e'nin kendi MMIO BAR'ına işaret ettirir ve device'ın packet-send path'inin operasyon ortasında emulator state'ini free edip yeniden kullanmasına neden olur.

Mechanism

Note

Bir QEMU device modeli, paket data'sını address_space_* DMA helper'larıyla guest RAM'den okur. Isolation invariant, bir paketin data address'inin emüle bir MMIO region'unu değil sıradan guest memory'sini adlandırmasıdır. CVE-2020-15859'da e1000e transmit path'i (hw/net/e1000e_core.c), e1000e'nin kendi MMIO BAR'ına çözümlenen guest tarafından sağlanan bir data address'i onurlandırdı. Send routine DMA "read"ini gerçekleştirdiğinde, access bunun yerine e1000e'ye re-enter eden bir MMIO operasyonu olarak dispatch edildi; bu, dış send frame'inin hâlâ canlı bir pointer tuttuğu transmit/descriptor state'ini ilerletebilir, sıfırlayabilir ya da free edebilir. Geri dönüşte dış frame free edilmiş emulator memory'sini dereference eder — tamamen guest kontrolünde bir use-after-free. Bozulan object host QEMU process'inde yaşadığı için bug guest→host sınırını aşar: en azından bir host denial of service, potansiyel olarak daha fazlası.

Bu, daha geniş QEMU DMA-reentrancy bug sınıfının somut bir örneğidir — qemu-e1000e-dma-reentrancy-use-after-free ve qemu-address-space-map-dma-reentrancy-reentry-into-device içinde görülen aynı invariant ihlali.

Walkthrough

Public, hâlihazırda patch'lenmiş advisory'den alındı (oss-security, Red Hat Bugzilla, upstream qemu-devel patch). Yalnızca kavramsal reproduction — weaponize edilmiş bir chain, heap layout ya da offset yok.

  1. Guest driver, e1000e'yi ayağa kaldırır ve bir transmit descriptor kurar.
  2. Descriptor'ın buffer address'ini normal guest RAM'e işaret ettirmek yerine, guest packet data address'ini e1000e'nin MMIO BAR address'ine ayarlar.
  3. Device, paketi göndermeye başlar ve buffer için DMA access'ini çıkarır. Target MMIO olduğu için, access e1000e register path'ine geri teslim edilir — send routine mid-flight iken device'a re-enter ederek.
  4. Re-enter edilen path, dış frame'in hâlâ referans verdiği descriptor ya da context state'ini mutate eder/free eder; geri dönüşte dış frame free edilmiş object'i kullanır → UAF.
  5. Vulnerable bir build'de bu bir QEMU crash olarak tezahür eder; grooming ile free edilmiş bir slot prensipte yeniden ele geçirilebilir ve temiz bir crash'in ötesine escalate olabilir.

Warning

Bug sınıfı için belgelenmiş tarihsel, patch'lenmiş bir sorun (QEMU 4.2.0 dönemi). Bu giriş kavramsal yükseklikte kalır: hiçbir host heap grooming, struct offset ya da end-to-end escape verilmez.

Reentrancy-guard concept (closes the class)
/* before dispatching an I/O access into a device region */
if (mr->dev && mr->dev->mem_reentrancy_guard.engaged_in_io) {
    return MEMTX_ACCESS_ERROR;   /* reject re-entry, do not recurse */
}
/* ... otherwise mark engaged, perform access, then clear ... */

Detection

  • Host tarafı: guest NIC aktivitesiyle ilişkilenen, hw/net/e1000e_core.c transmit/send kodunda kök salan QEMU abort'ları / AddressSanitizer use-after-free raporları.
  • Behavioral: (RAM yerine) device MMIO içine düşen bir NIC packet buffer address'i programlayan bir guest, herhangi bir meşru driver için anormaldir ve DMA target'ların gözlemlenebilir olduğu yerde güçlü bir telemetry sinyalidir.
  • Tek bir guest'e bağlı crash-loop / tekrarlanan QEMU restart'ları bir DoS göstergesidir.

Mitigation

  • CVE-2020-15859 için upstream QEMU fix'ini uygulayın (distro backport'ları: Debian DLA, Ubuntu, Red Hat, SUSE) ve device mem_reentrancy_guard reentrancy korumasını içeren bir build çalıştırın.
  • Bu attack surface'i daraltmak için untrusted guest'ler için emüle e1000e yerine virtio-net'i tercih edin.
  • Defense-in-depth: QEMU process'ini confine edin (seccomp, SELinux/sVirt, unprivileged bir kullanıcı olarak çalıştırın) ki bir UAF, host takeover değil sınırlanmış bir crash'e indirgensin.

References

  • oss-security — CVE-2020-15859 (e1000e use-after-free while sending packets): https://www.openwall.com/lists/oss-security/2020/07/21/3
  • Red Hat Bugzilla 1859168 — CVE-2020-15859: https://bugzilla.redhat.com/show_bug.cgi?id=1859168
  • NVD — CVE-2020-15859: https://nvd.nist.gov/vuln/detail/CVE-2020-15859
  • Debian DLA-2560-1 (qemu security update): https://lists.debian.org/debian-lts-announce/2021/02/msg00024.html