Skip to content

QEMU ColdFire FEC infinite loop (CVE-2016-9776)

ColdFire Fast Ethernet Controller'ın receive-buffer size register'ını sıfıra programlamak QEMU'nun mcf_fec_receive fonksiyonunu sonsuza dek döngüye sokar ve host CPU'sunu meşgul eder — guest-to-host bir denial of service.

Mechanism

Sınır neden kırılıyor

QEMU, ColdFire FEC NIC'i (hw/net/mcf_fec) host process içinde emüle eder. Gelen frame'ler, boyutu EMRBR (receive buffer size) register'ından alınan guest-provided buffer'lara yazılır. Model, paketi per-buffer boyutla sınırlanmış parçalar halinde kopyalar ve frame tüketilene kadar buffer descriptor'ları üzerinde ilerler. Hata şu: EMRBR herhangi bir validation olmadan sıfır olarak programlanabiliyor, dolayısıyla her döngü iterasyonu hiç ilerleme kaydetmez (sıfır uzunluklu bir buffer) ve receive loop çıkış koşuluna asla ulaşmaz. Bu, bir erişilemez çıkış koşuluna sahip döngü (CWE-835): bir memory-corruption hatasının aksine hiçbir şey üzerine yazılmaz — bunun yerine host vCPU/QEMU thread'i %100'de takılı kalır. İhlal edilen invariant şudur: bir host kopyalama döngüsünü sınırlamak için kullanılan guest-controlled bir uzunluk, non-zero olmaya zorlanmalıdır (ya da döngü ilerlemeyi garanti etmelidir) ki emülasyon her zaman sonlansın. Etki: privileged bir guest, QEMU process'ini crash'letir/askıya alır. Bu bir concurrency/atomicity hatası değil, saf bir liveness (CWE-835) sorunudur; aynı sınıftaki diğer infinite-loop QEMU device-model sorunları için see_also bağlantılarına bakın.

Walkthrough

Public QEMU patch posting ve Bugzilla'dan kavramsal yeniden kurgu; yalnızca mantıksal adımlar.

  1. Privileged bir guest driver, FEC'in MMIO register'larını programlayarak EMRBR = 0 (receive buffer size) yazar.
  2. Guest, bir frame'in alınmasına neden olur. mcf_fec_receive içinde kopyalama döngüsü sıfır buffer boyutunu per-iteration sınırı olarak kullanır, böylece hiç byte tüketmez ve sonlanma testini asla sağlamaz.
  3. Host QEMU thread'i hiçbir ilerleme olmadan aynı receive'i süresiz işleyerek döner — host CPU tükenmesi / denial of service.
Root cause and fix fragment

Vulnerable register write accepted a zero value:

case 0x188:               /* EMRBR */
    s->emrbr = value & 0x7f0;   /* may become 0 */
    break;

The fix forces a sane non-zero buffer size:

s->emrbr = value > 0 ? value & 0x7F0 : 0x7F0;

"QEMU ... built with the ColdFire Fast Ethernet Controller emulator support is vulnerable to an infinite loop ... while receiving packets in 'mcf_fec_receive'." — NVD CVE-2016-9776

Detection

  • Host CPU spin: I/O ilerlemesi olmadan %100'de takılı bir QEMU/vCPU thread'i, guest'in ColdFire FEC NIC'i kullanmasıyla ilişkilendirildiğinde birincil sinyaldir (top/perf, hung-task watchdog'ları).
  • Stack inspection: Bir debugger eklemek, host thread'inin mcf_fec_receive receive path'inde döngüye girdiğini gösterir.
  • Telemetry: FEC receive-buffer size register'ını sıfıra ayarlayan guest yazmaları anormaldir ve device-model logging ile yüzeye çıkarılabilir.

Mitigation

  • Patch: EMRBR'ı non-zero bir değere clamp'leyerek receive loop'un her zaman ilerleme kaydetmesini sağlayan upstream QEMU fix'ini (qemu-devel'de Nov 2016'da yayınlandı) uygulayın.
  • Reduce attack surface: ColdFire FEC, niş bir m68k/ColdFire machine device'ıdır — ihtiyacı olmayan untrusted guest'ler için onu emüle etmeyin.
  • Sandboxing: QEMU'yu seccomp (-sandbox on) ve svirt confinement altında çalıştırın; bunlar bir CPU-spin DoS'unu durdurmasa da, QEMU process'i üzerindeki cgroup CPU quota'ları kaçak bir emülasyon thread'inin host üzerindeki etkisini sınırlar.

References