Micro-op Cache Attack (I See Dead uops)¶
x86 micro-op (decode edilmiş-instruction) cache'i üzerinden secret'ları sızdırma; bu yapı L1 instruction cache'inin öncesinde durur ve mevcut birçok Spectre fence'inden sağ çıkar.
Mechanism¶
Note
Modern x86 çekirdekleri, karmaşık instruction'ları bir kez micro-op'lara decode eder ve hot kodu yeniden decode etmeyi atlamak için sonucu küçük, set-associative bir micro-op cache'inde (Intel DSB / AMD op cache) cache'ler. Bir kod bölgesinin bu cache'te hit mi yoksa miss mi olduğu, son execution geçmişinin bir fonksiyonudur ve o timing ölçülebilir. Micro-op cache, L1i cache'inden önce danışıldığı için, klasik instruction-cache ya da branch mitigation'larının kapsamadığı bir covert/side kanal oluşturur.
"I See Dead µOps" (Ren, Moody, Taram, Jordan, Tullsen, Venkat; ISCA 2021) iki sonuç
gösterir. Birincisi, tamamen micro-op-cache contention'ından inşa edilmiş bir
same-thread / cross-thread covert kanal. İkincisi ve transient execution için daha
önemlisi: x86 LFENCE serializing fence, execution'ın ilerlemesini durdurur ama
transient (yanlış tahmin edilmiş) execution sırasında micro-op'ların micro-op
cache'ine doldurulmasını flush etmez ya da önlemez. Yani bir Spectre gadget'ı,
fence'ten sonra ve squash'tan sonra süren secret-bağımlı durumu micro-op cache'ine
işleyebilir ve LFENCE tabanlı Spectre v1 mitigation'larını etkisiz kılabilir.
Walkthrough¶
Micro-op-cache covert kanalı bir cache Prime+Probe'u yansıtır, ama contention'a giren kaynak data-cache set'leri değil micro-op-cache set'leridir:
Prime : execute enough distinct code "ways" to fill a target micro-op-cache set
Victim: runs; if its code maps to that set it evicts the attacker's micro-ops
Probe : re-execute the primed code blocks; time them
fast -> still cached -> victim did NOT touch the set (bit 0)
slow -> re-decoded -> victim touched the set (bit 1)
Transient varyant, LFENCE'in micro-op-cache fill'lerini geçit altına almamasını istismar eder:
// Spectre-v1-style gadget, "protected" by LFENCE
if (x < array1_size) { // mispredicted true; x is out of bounds
_mm_lfence(); // stops data load speculation...
secret = array1[x]; // ...but transient decode still fills uop cache
transmit_via_uop_cache(secret); // imprint persists past the squash
}
Kanal front end'de yaşadığı için, imprint daha sonra data load'larını zamanlayarak değil, saldırgan kodunun decode'unu zamanlayarak geri kazanılır — LFENCE/data-cache flush'lamasının onu kapatmamasının nedeni budur.
Detection¶
Micro-op-cache baskısı, front-end performance counter'larında (DSB hit/miss,
Intel'de idq.dsb_* olayları) ortaya çıkar. Ayrıcalıksız bir process'ten anormal
derecede yüksek re-decode oranları zayıf bir göstergedir; kesin bir mimari imza
yoktur.
Mitigation¶
- Micro-op cache'i ayrıcalık/bağlam sınırlarında flush etmek ya da partition'lamak (paper'da önerildi) kanalı kapatır ama front-end throughput'una mal olur.
- SMT'yi devre dışı bırakmak cross-thread varyantı kaldırır.
- Not: AMD'nin yanıtı, mevcut mitigation'ların kendi parçalarında bypass edildiğinin gösterilmediğini belirtir ve yeni bir mitigation önermez; tehdit modeli en çok LFENCE-only Spectre savunmalarına karşı keskindir.