Skip to content

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.

References