Linux KVM kvm_inject_page_fault info leak (CVE-2019-7222)¶
KVM, memory operand'ı bir MMIO adresine çözülen bazı VMX instruction'larını emulate ettiğinde, initialize edilmemiş bir exception structure taşıyan bir page fault inject eder ve host kernel stack içeriğini CR2 ile page-fault error code üzerinden guest'e leak eder.
Mechanism¶
Note
Bir page fault'ta KVM bir struct x86_exception doldurur (faulting address → CR2,
artı bir error code) ve kvm_inject_page_fault() aracılığıyla onu guest'e inject
eder. Kırılan invariant: bazı emulation path'leri, exception structure tam
initialize edilmemişken injection helper'ını çağırıyordu. Guest-virtual-to-physical
read helper'ları, bir MMIO operand'ı için exception field'larını sıfırlamadan bir
error dönebiliyordu, böylece artakalan initialize edilmemiş kernel stack byte'ları
inject edilen CR2 ve error code'a akıyordu — guest'in okuyabildiği değerler.
Bu bir uninitialized-stack-variable-infoleak'tir: doğrudan bir memory-corruption primitive'i değil, host stack memory'sine guest'in okuyabildiği bir side channel; KASLR'ı zayıflatır ve ileri exploitation'a yardımcı olur.
Walkthrough¶
Upstream patch'ten kavramsal reprodüksiyon ("KVM: x86: work around leak of uninitialized stack contents (CVE-2019-7222)", Paolo Bonzini; Felix Wilhelm tarafından raporlandı):
- Guest, bir memory operand'ı olan emulated bir VMX instruction'ı çalıştırır — VMXON, VMCLEAR, VMPTRLD, VMWRITE (memory form), INVEPT ya da INVVPID.
- Operand pointer'ı, sıradan RAM yerine bir MMIO adresine çözülür.
- KVM'in guest-memory read helper'ı MMIO operand'ında fail eder ve caller, hiç
temizlenmemiş bir exception struct ile "körlemesine"
kvm_inject_page_fault()çağırır. - Inject edilen fault'un CR2 ve error code'u bu yüzden initialize edilmemiş host kernel stack byte'ları içerir; guest bunları fault'tan sonra okur.
Warning
Leak tekrarlanabilir ve guest-driven'dır; bir saldırgan faulting sequence'ı script'ler ve birçok stack word toplayarak zamanla host kernel address randomization'ını yener.
Fix shape (conceptual)
Yalnızca deterministik değerler guest'e ulaşsın diye exception'ı kullanmadan önce sıfırla:
Patch, ideal fix'inhandle_emulation_failure → KVM_EXIT_INTERNAL_ERROR
üzerinden userspace'e abort etmek olduğunu not eder, ama caller'lar buna hazır
değildi, yani sıfırlamak pragmatik geçici workaround'dur.
Detection¶
- Host'tan doğrudan gözlemlemek zordur (crash yok); sinyal, untrusted guest çalıştıran host'larda kernel sürümünü CVE-2019-7222 fix'ine karşı kontrol etmektir.
- Guest tarafı/araştırma telemetrisi: CR2 değerleri guest'in kendi operand adresinden ziyade kernel-range pointer'lara benzeyen tekrarlanan emulated-VMX fault'ları.
- Exception structure'ı initialize etmeden fault inject eden KVM nested-VMX emulation path'leri için audit yap.
Mitigation¶
- Injection'dan önce exception field'larını sıfırlayan upstream fix'i / vendor backport'larını uygula (Şubat 2019'da shiplendi; 4.20.5'e kadar olan kernel'leri etkiledi).
- Host kernel'lerini patch'li tut; fix küçük ve düşük riskli.
- Defense in depth: kullanılmadığı yerde nested virtualization'ı devre dışı bırakmak, emulated-VMX attack surface'inin çoğunu kaldırır.
Ayrıca bkz. linux-kvm-nested-vmx-l2-to-l1-emulation-leak ve uninitialized-stack-variable-infoleak.