Skip to content

SpectreRewind

Transient-execution attack'leri için contention-based bir covert channel; receiver instruction'larını transient victim kodundan mantıksal olarak önce issue ederek ve functional-unit contention'ını "geçmişten" gözlemleyerek tek bir hardware thread (SMT yok) üzerinde çalışır.

Mechanism

Note

Önceki contention covert channel'ları (port contention, execution-unit contention) simultaneous multithreading'e ihtiyaç duyar: sibling logical core üzerindeki bir spy thread, victim thread'in aynı anda yarattığı contention'ı ölçer. SpectreRewind bu gereksinimi ortadan kaldırır. İçgörüsü, bir out-of-order core'un nasıl çalıştığına dayanır: micro-op'lar Re-Order Buffer (ROB)'a logical program order'da girer, ama operand'ları ve gereken functional unit kullanılabilir hale geldikçe execution unit'lere out of order issue edilir. Long-latency bir functional unit — floating-point division unit — aynı anda yalnızca bir consumer'a hizmet edebilir. Attacker bir FP-division instruction zincirini (receiver) program order'da daha erkene yerleştirir ve transient olarak execute edilen secret-dependent kod (transmitter) program order'da daha geç issue olur ama aynı FP-division unit için çekişirse, o zaman transmitter'ın contention'ı kendinden önce gelen receiver'ı yavaşlatır. Issue order program order'dan decouple edildiği için, receiver fiilen kendisinden sonra gelen instruction'ların ürettiği bir sinyali gözlemler — bu yüzden "Rewind": tek bir thread üzerinde geçmiş instruction'lara secret sızdırmak.

Walkthrough

Covert channel, bir bit'i "transient kod FP-div unit'ini kullandı mı kullanmadı mı" olarak encode eder; attacker'ın kendi daha erken division zincirini zamanlayarak okunur.

  1. Receiver'ı kur. Yavaş FP division'lardan oluşan bir dependency chain emit et ve etrafına start/end timestamp'leri kaydet; bu zincir program order'da daha erken oturur.

  2. Transient transmitter'ı trigger et. Bir Spectre/Meltdown gadget'ı, ya bir FP division issue eden ya da etmeyen secret-dependent bir operasyonu transient olarak execute eder.

  3. Contention'ı gözle. Transient kod da division unit'ini kullandıysa, tek FP-div port'u için receiver chain ile çekişmiş ve receiver'ın ölçülen latency'sini uzatmıştır:

// Receiver: time a chain of FP divisions issued early in program order.
// A later (transient) division contends for the same FP-div unit and
// stretches this measured time -> one leaked bit.
double x = init;
unsigned long t0 = rdtscp_serialize();
for (int i = 0; i < CHAIN; i++) x = divisor / x;   // serial FP-div chain
unsigned long t1 = rdtscp_serialize();
sink(x);
int bit = ((t1 - t0) > CONTENTION_THRESHOLD);      // slow => transmitter divided
  1. Decode et. Threshold üzerindeki bir latency 1 olarak decode olur; altındaki 0 olarak.
Beklenen davranış
Channel type:  functional-unit contention (FP division port)
Threads:       single hardware thread  (no SMT required)
Direction:     receiver issued LOGICALLY BEFORE the transient transmitter
Bandwidth:     ~100 KB/s, error rate < 0.01% (reported)
Demonstrated:  Meltdown receiver; also inside Chrome's JavaScript engine

Warning

Ne SMT'ye ne de cache-based bir channel'a ihtiyaç duyduğu için, SpectreRewind transmit/receive çiftinin sibling SMT thread'lerinde co-resident olması gerektiğini varsayan ya da yalnızca Flush+Reload tarzı cache aktivitesini gözleyen savunmaları etkisiz kılar.

Detection

Tespiti zordur: channel, bir cache izi değil, paylaşılan bir functional unit üzerinde single-thread bir timing farkıdır. Speculation barrier'larına bitişik sıkı FP-division timing loop'larını izlemek en iyi ihtimalle sezgiseldir.

Mitigation

Transient window'u kapatmak transmitter'ı ortadan kaldırır: gadget'ta speculation'ı serialize et (lfence), speculative load hardening uygula ve architecture'ın Meltdown/Spectre fix'lerini deploy et. High-resolution timer'ları devre dışı bırakmak ve timing jitter eklemek receiver için noise floor'u yükseltir ama alttaki contention'ı kaldırmaz.

References