Skip to content

L1D cache flush (L1TF)

Bir trust boundary'yi geçmeden önce (başlıca VMENTER'da) L1 data cache'ini evict et, böylece kötü amaçlı bir guest ya da sibling thread, host'un L1D'de bıraktığı her şeyi okumak için L1 Terminal Fault / Foreshadow kullanamaz.

Mechanism

Neden çalışır

L1 Terminal Fault (L1TF, CVE-2018-3615/3620/3646; "Foreshadow") bir transient fault'tur: bir paging-structure entry'si present değilken (ya da başka türlü fault verdiğinde), bazı Intel CPU'ları, terminal fault raise edilmeden önce, PTE'nin frame bit'lerinden oluşan fiziksel adreste L1 data cache'inde bulunan data'yı yine de speculatively forward eder. PTE'leri şekillendirebilen bir saldırgan — kendi EPT-translated PTE'lerini kontrol eden bir guest ya da bir sibling SMT thread'i — böylece L1D'de o anda yerleşik herhangi bir line'ı, host/ hypervisor sırları dahil, okuyabilir.

İki tamamlayıcı savunma vardır:

  • PTE inversion (her zaman açık, sıfır maliyet): kernel, "present olarak işaretlenmemiş PTE'lerin address bit'lerinin asla cacheable fiziksel belleğe işaret etmemesini" sağlar, böylece present-olmayan bir user PTE'si gizli fiziksel line'lara yönlendirilemez.
  • L1D flush virtualization durumu için: "Bir guest'in L1D'de present olan data'ya saldıramayacağından emin olmak için hypervisor, guest'e girmeden önce L1D'yi flush eder." L1D bir kez boşaldığında, L1TF transient load'u işe yarar hiçbir şeye çözülmez.

Invariant: sınır geçişi anında L1D hiçbir sır tutmuyorsa, L1D içeriğinin bir L1TF forward'ı hiçbir şey sızdırmaz.

Walkthrough

1. L1TF durumunu oku. sysfs dosyası, PTE inversion'ı artı VMX flush modunu ve SMT durumunu özetler:

$ cat /sys/devices/system/cpu/vulnerabilities/l1tf
Mitigation: PTE Inversion; VMX: cache flushes, SMT vulnerable

2. VMENTER'da KVM L1D flush'ını kontrol et. kvm-intel.vmentry_l1d_flush= parametresi üç mod alır:

never   - disables the mitigation
cond    - flush only when code between VMEXIT and VMENTER can leak host memory (default)
always  - flush L1D on every VMENTER (maximum protection)

Boot'ta, module yüklemede ya da runtime'da sysfs üzerinden ayarla:

# boot:        kvm-intel.vmentry_l1d_flush=always
# runtime:
$ echo always > /sys/module/kvm_intel/parameters/vmentry_l1d_flush

3. Non-VMX prctl interface'i. Hassas bir task'tan bir context switch'te L1D'yi flush etmek için kernel, l1d_flush=on boot parametresiyle gate'lenen per-task bir opt-in sunar; "task scheduled out edildiğinde ve gelen task farklı bir process'e ait olduğunda L1D cache'inin bir flush'ı gerçekleştirilir." CPU'nun bir hardware L1D-flush'ı varsa o kullanılır; "mitigation için software fallback desteklenmez."

Hardware flush primitive'i

Desteklenen yerde flush, IA32_ARCH_CAPABILITIES üzerinden duyurulan özel IA32_FLUSH_CMD MSR'si (L1D_FLUSH komutu) aracılığıyla tetiklenen architectural L1D write-back/invalidate'idir. IA32_ARCH_CAPABILITIES'te ARCH_CAP_RDCL_NO raporlayan CPU'lar Meltdown/L1TF'den etkilenmez ve flush gerektirmez.

Tek başına flush'lamak SMT'yi kapsamaz

L1D flush, "SMT etkinken bir fiziksel CPU core'unun sibling thread'lerinde eş zamanlı execute eden, farklı process'lere ait task'lar" için hiçbir şey yapmaz — bir sibling, flush ile kullanım arasında L1D'yi refill edebilir/gözlemleyebilir. Bu yüzden VMX'te tam L1TF koruması ayrıca SMT'yi devre dışı bırakmayı ya da strict core scheduling'i gerektirir. Flush'lamanın performans maliyeti, VMEXIT frekansına bağlı olarak "%1 ile %50" arasında değişir.

Detection

Yalnızca operasyonel: l1tf (ve ilgili mds) vulnerabilities dosyaları ve /sys/module/kvm_intel/parameters/vmentry_l1d_flush değeri mevcut durumu raporlar.

Mitigation

(Residual risk.) always flush'lamayla bile eş zamanlı SMT sibling'leri açıkta kalır; production rehberi L1D flush'ı SMT devre dışı ya da core scheduling ile eşleştirir. PTE inversion, user-space (non-VMX) vektörünü ele alır ama cross-guest L1D maruziyetini değil; ki tam olarak VMENTER flush'ının ele aldığı şey budur.

References