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.
-
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.
-
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.
-
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
- Decode et. Threshold üzerindeki bir latency
1olarak decode olur; altındaki0olarak.
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.