Skip to content

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:

  1. KVM device'ına erişimi olan yerel bir kullanıcı (örneğin nested VMX'li bir VM ya da KVM_RUN issue edebilen bir process), VMX preemption timer'ı seçilmiş bir tick değeriyle enable olacak şekilde guest VMCS'ini programlar.
  2. KVM o vCPU için backing hrtimer'ı arm eder.
  3. 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.
  4. 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)
/* On vCPU teardown / VMX uninit, the backing hrtimer MUST be cancelled
 * before any vCPU/VMX state it references can be freed. */
hrtimer_cancel(&vmx->nested.preemption_timer);

Ö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 hrtimer expiry'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.

References