Skip to content

QEMU RTL8139 network device emulation overflow

Bir QEMU device-emulation kusuru (CVE-2015-5165): RTL8139 C+ offload path'i IP packet length'ini yanlış hesaplar ve guest'e ~64 KB uninitialised host-process heap sızdırır — bir guest-to-host escape'inin info-leak yarısı.

Mechanism

Note

QEMU, Realtek RTL8139 NIC'ini host user-space process'i içinde emule eder. "C+" mode'u, hw/net/rtl8139.c içinde guest tarafından sağlanan packet header'larını parse ederek TCP/IP transmit offload'unu (segmentation, checksum'lar) yapar. Isolation invariant'ı, emulator'ün packet/payload length'lerini yalnızca validate edilmiş header field'larından türetmesidir; böylece okuyup ilettiği host-process memory'sinin miktarı, guest'in packet'e gerçekten koyduğu byte'larla bound olur. CVE-2015-5165 o invariant'ı kırar: rtl8139_cplus_transmit_one(), ip_data_len = be16_to_cpu(ip->ip_len) - hlen'i ip->ip_len >= hlen'i kontrol etmeden hesaplar. ip_data_len bir unsigned short olduğu için, ip->ip_len = hlen - 1'e sahip forge edilmiş bir packet subtraction'ı ~0xFFFF'e wrap ettirir; dolayısıyla emulator packet'in içerdiğinden çok daha fazlasını kopyalar — uninitialised QEMU heap'i okur ve guest'e (ve wire'a) geri gönderir. Bu, host→guest sınırını aşan bir out-of-VM read'tir: guest, asla görmemesi gereken host-process memory'sini öğrenir.

Bu saf bir information-disclosure primitive'idir, ama tam bir escape'in load-bearing ilk aşamasıdır: sızdırılmış heap içeriği QEMU process'inde ASLR'yi yener, ardından ayrı bir write primitive'i (örn. PCNET overflow'u CVE-2015-7504) hassas şekilde nişanlanabilir. Chaining pattern'i için bkz. qemu-slirp-guest-to-host-escape-chain.md.

Kardeş not QEMU PCNET network device emulation overflow ile karıştırma: bu (RTL8139, CVE-2015-5165) bir out-of-VM read / info-leak'tir (ip_len underflow ile host heap sızdırır), PCNET (CVE-2015-7504) ise farklı bir device'ta bir OOB write/overflow olan ADDFCS CRC append'idir. Aynı Phrack escape chain'inde birlikte kullanılırlar ama ayrı CVE'ler ve ayrı bug class'larıdır.

Walkthrough

Public referans: Phrack 70 "VM escape — QEMU Case Study" (Talbi & Fariello). Kavramsal, halihazırda patch'lenmiş path — weaponise edilmiş host layout'u yok:

  1. Guest, RTL8139'u C+ mode'una programlar ve IP header'ı ip->ip_len = hlen - 1 set eden crafted bir Ethernet/IP frame için bir transmit descriptor post eder.
  2. rtl8139_cplus_transmit_one() içinde ip_data_len = ip->ip_len - hlen kabaca 0xFFFF'e underflow eder; böylece offload path'i ~64 KB'ı payload olarak ele alır.
  3. Emulator, packet'i takip eden host heap region'ından o kadarını okur ve transmit eder. Makale, leak'in guest'e döndürülen ~43 fragmented packet (toplam ~64 KB) olarak geldiğini rapor eder.
  4. Guest, leak'i tanınabilir host pointer'lar için tarar. Makale, dump'ın ObjectPropertyAccessor *get/*set/*resolve/*release function pointer'larının sabit page offset'lerine sahip olduğu 80-byte'lık ObjectProperty chunk'ları içerdiğini belirtir — QEMU .text base'ini (ve system, execv vb. için PLT entry'lerini) recover eder. Tekrarlayan PHY_MEM + 0x78 değeri, guest physical memory'sinin QEMU'nun VA'sında nereye map'lendiğini açığa çıkarır.

Warning

Bug class'ı için belgelenmiş tarihsel, patch'lenmiş bir issue. Bu kayıt kavramsaldır; public Phrack makalesinin halihazırda yayınladığının ötesinde hiçbir exploit offset'i ya da host heap layout'u vermez.

Representative trigger shape (illustrative pseudocode)
/* guest builds a C+ Tx descriptor for a forged IP frame */
ip->ip_hl  = 5;                 /* hlen = 20 */
ip->ip_len = htons(20 - 1);     /* underflows ip_data_len in the emulator */
rtl8139_post_cplus_tx(desc, frame);
/* host returns ~64 KB of uninitialised heap as fragmented packets */

Beklenen gözlem: guest, gönderdiğinden çok daha fazla byte geri alır ve bunlar non-zero host pointer'ları içerir; patch'lenmiş bir host'ta transmit reddedilir/zero-length olur.

Detection

  • Host tarafı: instrumented QEMU/ASAN build'leri rtl8139_cplus_transmit_one()'daki over-read'i flag'ler; length'i descriptor payload'ını aşan outbound frame'ler anormaldir.
  • Guest-behaviour tarafı: bir guest'in ip_len < ip_hl*4 olan IP frame'lerle RTL8139 C+ offload'unu sürmesi, gerçek bir TCP/IP stack'inin emit ettiği bir şey değildir.

Mitigation

  • CVE-2015-5165 (XSA-140) için QEMU/Xen fix'ini uygula: C+ offload path'inde ip_data_len'i hesaplamadan önce ip_len >= hlen'i validate et.
  • Non-emulated bir NIC backend'i (vhost/virtio, tap) tercih et ya da legacy device emulation'ına ihtiyaç duymayan guest'ler için RTL8139 C+ offload'unu devre dışı bırak.
  • Defense-in-depth: device-emulation process'ini sandbox'lanmış/deprivilege edilmiş çalıştır (seccomp, SELinux/sVirt); böylece bir info leak önemsizce host kontrolüne yükseltilemez.

References

  • Mehdi Talbi & Paul Fariello, "VM escape — QEMU Case Study", Phrack 70: https://phrack.org/issues/70/5
  • Xen Security Advisory XSA-140 (CVE-2015-5165): https://ipads.se.sjtu.edu.cn/xsa/XSA-140.html