QEMU floppy FDC NULL pointer deref (CVE-2021-20196)¶
Privileged bir guest, uninitialized bir floppy drive seçip FDC emulator'ünü bir NULL pointer dereference'a sürebilir ve host QEMU process'ini crash'letebilir (guest-to-host DoS).
Mechanism¶
Bug sınıfı: guest-selectable bir index üzerinde kontrol edilmemiş device-backing pointer
QEMU'nun floppy disk controller'ı (FDC), bir drive struct dizisi tutar. Her drive,
VM yapılandırmasına bağlı olarak host tarafında bir block backend'e
(BlockBackend *blk) sahip olabilir ya da olmayabilir. Emulator'ün tutması
gereken invariant şudur: o anda seçili drive'ın blk'ini dereference eden her
kod path'i, önce gerçekten bir block device'ın attach edildiğini doğrulamalıdır.
Digital Output Register (DOR), guest'in bir ioport yazmasıyla
(FD_REG_DOR -> fdctrl_write_dor()) hangi drive'ın "current" olduğunu seçmesine
izin verir. Yazılan değerin düşük bit'leri (value & FD_DOR_SELMASK) doğrudan
drive dizisini index'ler ve aktif drive'ı ayarlar. Bir guest dolayısıyla bir
backend ile hiç initialize edilmemiş bir drive slot'unu seçebilir. Sonraki bir
read/write ioport komutu (fdctrl_read_data() / fdctrl_write_data())
çalıştığında, cur_drv->blk'e uzanır ve emulator bir NULL pointer dereference
eder.
Security boundary aşılır çünkü guest selector'ı tamamen kontrol eder (mimari olarak meşru bir I/O port yazması), ancak host kodu seçili drive'ın backed olduğuna güvendi. Sonuç, guest tarafından çıkarılan well-formed bir operasyondan kaynaklanan host tarafı bir crash'tir — memory corruption yok, ama virtualization sınırı boyunca temiz bir availability kırılması.
Walkthrough¶
Public advisory'den ve upstream "check drive block device before usage" patch'inden alınan üst düzey, kavramsal reproduction.
- Guest, slot'unun
blkbackend'i attach edilmemiş bir drive index'i seçerek FDC Digital Output Register'ına birioportyazması yapar.
Conceptual selection + trigger (logical fragments, not an exploit)
-
QEMU içinde,
fdctrl_write_dor()current-drive pointer'ını tamamen guest tarafından sağlanan selector bit'lerinden günceller. -
Data-phase handler'ı ardından
blk == NULLikencur_drv->blk'i block-layer koduna kadar izler, NULL'u dereference eder ve QEMU process'ini abort eder.
Bir guest buna nasıl ulaşıyor
Path yalnızca standart, belgelenmiş FDC I/O port'larını kullanır. Emüle FDC'ye port I/O yapabilen herhangi bir guest context'i (tipik olarak guest içinde privileged) ona ulaşabilir; egzotik bir state machine kurulumu gerekmez.
Fix, un-backed bir drive'ın asla aktif olarak ele alınmaması için defansif guard'lar ekler:
/* Conceptual shape of the upstream fix (paraphrased) */
/* fdctrl_write_dor(): only switch current drive if it has a backend */
if (fdctrl->drives[value & FD_DOR_SELMASK].blk != NULL) {
/* update selected drive */
}
/* fdctrl_read_data()/fdctrl_write_data(): bail out early if !cur_drv->blk */
if (!cur_drv->blk) {
return; /* refuse the data phase instead of dereferencing NULL */
}
Detection¶
Host ve telemetry sinyalleri
- Process crash: QEMU SIGSEGV ile sonlanır; tek bir guest'le ilişkilenen QEMU
binary'sinde bir segfault için host loglarını
(
journalctl,/var/log/libvirt/qemu/<domain>.log,dmesg) kontrol edin. - ASAN/debug build imzası: FDC data path'i içinde bir NULL (address
0x0/ küçük offset) read ya da write (fdctrl_read_data/fdctrl_write_data-> block backend access). - Anomaly: floppy media / floppy backend yapılandırılmamış bir VM'de FDC
ioportaktivitesi (data read'leri izleyen DOR yazmaları) yapan bir guest şüphelidir — meşru guest'ler boş bir FDC'yi nadiren dürter. - Fleet pattern: tek bir tenant'a atfedilebilir tekrarlanan, kısa ömürlü QEMU restart'ları, host instability'den ziyade guest-triggered bir DoS'a işaret eder.
Mitigation¶
Remediation
- Patch: "fdc: check drive block device before usage (CVE-2021-20196)" fix'ini içeren bir QEMU build'ine ya da onu shipleyen bir distro paketine (örn. Red Hat / Ubuntu / SUSE backport'ları) yükseltin.
- Reduce attack surface: ihtiyacı olmayan guest'lere bir floppy controller
attach etmeyin (
-nodefaultsve-device floppy/fdc'yi atlayın); mevcut olmayan bir device dürtülemez. - Defense in depth: QEMU'yu azaltılmış ayrıcalıklarla ve confinement ile (dedike
UID,
-sandbox onüzerinden seccomp, SELinux/AppArmorsvirtprofilleri) çalıştırın ki bir crash sınırlı kalsın ve atfedilmesi kolay olsun. - Availability hardening: QEMU/libvirt'i denetleyin ki crash olan bir instance restart edilsin ve uyarı versin, bir DoS girişiminin etkisini sınırlayarak.
References¶
- Red Hat Bugzilla 1919210 (CVE-2021-20196)
- Upstream patch: "fdc: check drive block device before usage (CVE-2021-20196)"
- Launchpad bug #1912780 — Null pointer failure in fdctrl_read()
- Ubuntu CVE-2021-20196
- Related primitive: null-pointer-dereference
- Related: QEMU MemoryRegionOps NULL deref MMIO (CVE-2020-15469)