Linux KVM nested VMX preemption-timer UAF (CVE-2019-7221)¶
CVE-2019-7221: KVM'in VMX preemption timer emulation'ı, bir vCPU/VM teardown edildikten sonra bir
hrtimer'ı armed bırakır ve guest'i kontrol eden yerel bir kullanıcının host code execution'a doğru sürebileceği bir use-after-free verir.
Mechanism¶
Bug class: bir kernel timer'ı ile hizmet ettiği object arasında lifetime uyumsuzluğu
Risk altındaki isolation boundary guest/VM-owner -> L0 host kernel'dir. KVM,
Intel VMX preemption timer'ını, bir vCPU'ya bağlı bir kernel high-resolution
timer'ıyla (hrtimer) destekleyerek emulate eder. Kırılan invariant basittir:
her armed hrtimer, gösterdiği memory free edilmeden önce cancel edilmelidir.
Bir guest nested VMX'i preemption timer başlatılacak şekilde konfigüre ettiğinde,
callback'i vCPU/VMX state'ini dereference eden bir hrtimer queue'lanır. Teardown
path'i (vCPU destroy / VM close) o timer'ı koşulsuz cancel etmezse, callback ilişkili
structure free edildikten sonra ateşleyebilir. Sonuç klasik bir
use-after-free'tir: bir kernel timer interrupt'ı
free edilmiş, saldırgan-etkili memory'de gezinir. Kardeş info-leak'le
(CVE-2019-7222) birleştirildiğinde, bu UAF Project Zero dönemi KVM escape
chain'indeki corruption primitive'iydi.
Timer callback'i softirq/timer context'inde kernel privilege'larıyla çalıştığından, buradaki kontrollü bir UAF bir crash'ten çok daha fazlasıdır: L0 içinde bir write/control-flow primitive'idir.
Walkthrough¶
Public advisory ve fix'ten çıkarılan yüksek seviyeli, kavramsal reprodüksiyon:
- KVM device'ına erişimi olan yerel bir kullanıcı (örneğin nested VMX'li bir VM ya da
KVM_RUNissue edebilen bir process), VMX preemption timer'ı seçilmiş bir tick değeriyle enable olacak şekilde guest VMCS'ini programlar. - KVM o vCPU için backing
hrtimer'ı arm eder. - Kullanıcı, teardown'u — vCPU'yu destroy ederek ya da VM'i kapatarak — hâlâ pending timer'a karşı race eder, böylece callback, destroy path'inin zaten release ettiği memory'ye karşı ateşler.
- Free edilen allocation'ı şekillendirerek (heap grooming), dangling timer callback'i saldırgan-etkili içerik üzerinde çalışır ve UAF'ı L0'da kullanılabilir bir corruption primitive'ine dönüştürür.
Upstream fix, callback'in object'inden asla daha uzun yaşayamaması için preemption-timer
hrtimer'ının ilgili teardown/exit path'inde cancel edilmesini sağlar.
Fix'in temsili şekli (arch/x86/kvm/vmx)
Örnekleyici fragment
Snippet, patch niyetinin kavramsal bir temsilidir, birebir kopya değil. Tam satırlar için atıf yapılan kernel.org commit'ine bak.
Detection¶
- KVM timer path'lerinde host kernel oops / use-after-free raporları — backtrace'i
hrtimerexpiry'sinden ve KVM VMX preemption-timer kodundan geçen KASAN "use-after-free" splat'ları en net sinyaldir. - Nested virtualization'ı enable eden ve VMX preemption timer'ı tetikleyen, özellikle vCPU/VM destruction etrafındaki guest'lerle ilintili crash'ler.
- Telemetri: tek bir tenant'tan gelen tekrarlanan kısa ömürlü VM create/destroy churn'ünü KVM-kaynaklı kernel fault'larıyla birleşmiş halde uyar — bir teardown race'inin brute-force edilmesinin karakteristiğidir.
- Bir canary host'ta KASAN-enabled bir debug kernel, bu class'ı silahlandırılmadan önce gözlemlenebilir kılar.
Mitigation¶
- Linux 4.20.x / 5.0'da upstream düzeltildi (commit
ecec76885bcfe3294685dc363fd1273df0d5d65f); dağıtımının patch'li kernel'ini uygula (Red Hat, Ubuntu, Debian, SUSE hepsi update shipledi). /dev/kvm'e erişimi trusted kullanıcılar/servislerle kısıtla; bug yalnızca KVM ioctl'lerini sürebilen bir principal tarafından ulaşılabilir.- Nested virtualization gerekmediği yerde, nested-VMX preemption-timer surface'ini
kaldırmak için devre dışı bırak (
kvm_intel nested=0). - Bu UAF class'ının regression'larını erken yakalamak için test host'larında KASAN ile build/run et.