Linux KVM shadow-page permission miscompute (CVE-2021-38198)¶
KVM'in shadow MMU'su, yanlış inherit edilmiş access permission'larıyla bir shadow page'i yeniden kullandı, böylece ateşlemesi gereken bir guest protection fault'u sessizce eksik kaldı.
Mechanism¶
Note
Bir software (shadow) MMU'da, KVM guest'in page table'larını walk eder ve full walk'un effective access right'larını enforce ederken guest mapping'ini yansıtan host tarafı "shadow" page table'ları kurar. Bir leaf için effective permission, walk boyunca her ancestor entry'sinin R/W/U-S bit'lerinin logical AND'idir.
Kırılan invariant: bir shadow page, parent'larından inherit ettiği access right'ları cache'ler, yani aynı lower-level table'ı farklı permission chain'leri üzerinden gösteren iki guest page table'ı tek bir shadow page'i paylaşMAMAlıdır. Buggy kod, inherit edilen permission'ı walk boyunca taşınan tek bir scalar (pt_access) olarak izledi; her seviye boyunca AND hesaplamak yerine etkin biçimde yalnızca son non-leaf entry'sinin effective permission'ını tüm non-leaf entry'leri için kullandı. Aynı gfn'e daha-permissive ve daha-az-permissive bir ancestor chain üzerinden ulaşılabildiğinde, KVM, kısıtlanması gereken erişimler için permissive chain altında üretilmiş bir shadow page'i yeniden kullanabiliyordu. Sonuç bir eksik guest protection page fault'udur: guest, hardware-equivalent walk'un fault'layacağı bir erişim yapar (örneğin, bir upper-level entry'sinin read-only işaretlediği bir page'e write), ama bayat shadow page buna izin verir. Bu, guest'in kendi intra-guest protection boundary'sini hypervisor'ın MMU'su içinde geçer.
Walkthrough¶
Upstream fix, arch/x86/kvm/mmu/paging_tmpl.h'a dokunan commit b1bd5cba3306'dur ("KVM: X86: MMU: Use the correct inherited permissions to get shadow page"). Kavramsal olarak, public commit'ten:
- Bir lower-level page table'ının iki ayrı higher-level entry tarafından referans verildiği guest paging yapıları kur — biri geniş erişim veren, diğeri kısıtlayan bir chain (örneğin, bir ara seviyede farklı R/W ya da U/S bit'leri).
- Bir gfn'e permissive chain üzerinden dokun, böylece KVM combined (permissive)
pt_access'i kaydeden bir shadow page allocate eder. - Aynı gfn'e restrictive chain üzerinden ulaş. Inherit edilen permission per seviye yerine tek bir değer olarak izlendiğinden, KVM daha katı chain için ayrı bir tane allocate etmek yerine mevcut shadow page'i match'ledi/yeniden kullandı.
- Erişim, guest'in kendi table'larının gerektirdiği protection fault olmadan devam eder.
Düzeltici değişiklik (kavramsal)
Patch, tek pt_access scalar'ını per-level bir array (pt_access[PT_MAX_FULL_LEVELS]) ile değiştirir, böylece walker her seviyede inherit edilen permission'ları biriktirir ve karşılaştırır. Shadow-page lookup'u o zaman farklı ancestor permission'larına sahip chain'leri ayırt eder ve inherit edilen right'lar farklı olduğunda ayrı bir shadow page'i zorlar.
Warning
Bu bir guest-to-host escape değil, bir intra-guest correctness/availability bug'ıdır (bir guest kendi protection'larını yanlış enforce eder). Etki denial-of-service / yanlış protection davranışı olarak derecelendirilir. Öncelikle hardware two-dimensional paging (EPT/NPT) yerine shadow paging kullanan setup'ları etkiler.
Detection¶
- Shadow MMU aktifken (EPT/NPT yok, örneğin
ept=0/npt=0, ya da nested/emulated MMU path'leri) KVM çalıştıran host'lar ilgili exposure surface'idir; hangi guest'lerin hardware SLAT olmadan çalıştığını envanterle. - Beklenmedik memory-corruption oops'ları, guest'in read-only işaretlediği page'lere sahte "good" write'lar ya da guest workload'undan ziyade KVM module sürümüyle ilintili instability raporlayan guest kernel'leri için dikkatli ol.
- Kernel telemetrisi: KVM MMU tracepoint'lerini (
kvm_mmu_get_page,kvm_mmu_sync_page) enable et ve fuzzing/validation sırasında ayrışan permission'lara sahip mapping'ler arasında anormal shadow-page reuse'u ara. - Temiz bir network/host-log IOC'si yoktur; detection en iyi şekilde version inventory artı crash-signal monitoring (
dmesg'tekikvm/KASANsatırları) olarak çerçevelenir.
Mitigation¶
- Patch'le. Commit
b1bd5cba3306içeren bir kernel'e güncelle (Linux 5.12.11 ve sonrası, artı distro backport'ları). Otoriter fix budur. - Hardware SLAT'ı tercih et. CPU desteklediği yerde, guest'leri EPT (Intel) / NPT (AMD) enable şekilde çalıştır ki KVM shadow MMU permission-inheritance path'ine güvenmesin.
- Paylaşılan kernel'lere güveni azalt. Guest kernel boundary'sini yalnızca defense-in-depth olarak ele al; kendi page protection'larını yanlış enforce eden bir guest in-guest privilege escalation'a yardımcı olabilir, yani guest kernel'lerini de patch'li tut.
- Uzun ömürlü host'larda dağıtım security update'lerini (örneğin Debian LTS advisory'leri) uygula.