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_receivefonksiyonunu 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.
- Privileged bir guest driver, FEC'in MMIO register'larını programlayarak
EMRBR = 0(receive buffer size) yazar. - Guest, bir frame'in alınmasına neden olur.
mcf_fec_receiveiç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. - 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:
The fix forces a sane non-zero buffer size:
"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_receivereceive 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.