Linux KVM INVPCID CR0.PG=0 NULL deref (CVE-2022-1789)¶
Shadow paging aktifken, paging devre dışıyken (CR0.PG=0) INVPCID çalıştıran bir guest, hiç install edilmemiş bir MMU
invlpgcallback'ine ulaşır, böylece KVM bir NULL function pointer'ı dereference eder ve host'u crash eder (guest-to-host denial of service).
Mechanism¶
Note
KVM, guest MMU'yu, davranışı aktif paging mode'a göre kurulan function-pointer
callback'ler (örneğin invlpg) üzerinden dispatch edilen bir struct kvm_mmu
olarak modeller. Kodun dayandığı invariant, kvm_mmu_invpcid_gva()'ya yalnızca
invlpg callback'i dolu olan bir MMU ile ulaşılmasıydı. Guest, shadow paging
altında CR0.PG=0 ile INVPCID çalıştırdığında bu varsayım kırılır: o
konfigürasyonda invlpg callback'i set edilmemiştir, ama INVPCID emulation path'i
yine de onun üzerinden çağrı yapar ve host kernel context'inde bir NULL pointer'ı
dereference eder.
Bu klasik bir missing-callback-guard bug'ıdır: handler'ın hiç atanmadığı bir mode'da ulaşılabilen bir code path üzerinde, per-mode bir handler koşulsuz invoke edilir. Unprivileged bir guest'ten ulaşılabilen bir null-pointer-dereference'tır ve bir privilege escalation yerine bir host crash'i verir.
Walkthrough¶
Upstream fix'ten kavramsal reprodüksiyon
(commit 9f46c187e2e6, "KVM: x86/mmu: fix NULL pointer dereference on guest INVPCID", Paolo Bonzini):
- Host, guest'i shadow paging ile çalıştırır (bu MMU rolü için EPT/NPT kullanımda değil).
- Guest paging'i devre dışı bırakır (CR0.PG = 0) ve bir INVPCID instruction'ı issue eder.
- KVM INVPCID'yi emulate eder ve verilen guest-virtual mapping'i current ve previous
root'lar boyunca invalidate etmek için
kvm_mmu_invpcid_gva()çağırır. - O helper
mmu->invlpg(...)'yi invoke eder, ama CR0.PG=0 ileinvlpgcallback'i hiç install edilmemiştir → NULL function-pointer çağrısı → host oops.
Warning
Trigger tamamen guest-controlled'dır ve guest içinde, paging kapalıyken INVPCID çalıştırmanın ötesinde özel bir privilege gerektirmez — hostile ya da buggy bir VM'den az çabalı bir host DoS'u.
Fix shape (conceptual)
Her callback kullanımını guard et:
CR0.PG / EFER.LMA mode kontrolleri eklemek yerine, hem aktif PCID için hem de previous root'ları walk ederken uygulanır.Detection¶
kvm_mmu_invpcid_gva(ve INVPCID emulation path'i) üzerinden geçen bir NULL-deref backtrace'iyle birlikte host kernel oops / panic imzadır.- Crash'i spesifik bir guest'le ilintilendir: fault'tan kısa süre önce INVPCID issue etmiş, özellikle de CR0.PG'yi toggle'layan bir VM.
- Host stability monitoring: untrusted ya da multi-tenant guest çalıştıran host'larda açıklanamayan KVM ilişkili panic'ler, kernel sürümünü patch'e karşı kontrol etmeyi gerektirir.
Mitigation¶
mmu->invlpg'yi çağırmadan önce guard eden upstream fix'i (commit9f46c187e2e6) / vendor backport'larını uygula.- Host kernel'lerini güncel tut; dağıtımlar bunu 2022'de bir stable update olarak shipler.
- Patch'leme geride kaldığında, host'ta untrusted guest kodunu kimin çalıştırabileceğini kısıtla, çünkü bug güvenilir bir guest-triggered host DoS'udur.
İlişkili bir guest-triggered NULL-deref pattern'i için ayrıca bkz. linux-kvm-synic-stimer-msr-null-deref, ve bug class'ı için null-pointer-dereference.