Spectre - Meltdown speculative side channels
5.3.15· Hardware › Advanced Microarchitecture
Core Mechanism: The Speculative Execution Window
How Speculative Execution Creates Vulnerabilities
Modern out-of-order processors architectural state (registers, memory jo programs ko visible hai) ko microarchitectural state (caches, branch predictors, TLBs) se alag rakhte hain. Jab speculation hoti hai:
WHY speculation exists: Memory CPU se ~200× slower hai. Har branch ya memory access ka wait karna billions of cycles waste kar deta. Branch prediction + speculative execution CPU ko probable paths par kaam karne dete hain wait karte waqt.
WHAT goes wrong: CPU promise karta hai ki wrong speculation architecturally invisible hogi — mispredicted instructions kabhi commit nahi hote, registers roll back ho jaate hain. Lekin yeh SIRF architectural state roll back karta hai. Cache contents, ek microarchitectural side effect, persist karte hain.
HOW the attack works:
- Train the predictor (CPU ko ek pattern expect karao)
- Trigger speculative execution with malicious code
- Extract secrets through cache timing side channels
Meltdown: Breaking Kernel Isolation
Derivation: Kernel Memory Kyun Accessible Ho Jaati Hai
Step 1: Normal Protection Mechanism
x86 mein, page tables ka supervisor bit kernel memory mark karta hai. User-mode access trigger karni chahiye:
Step 2: Out-of-Order Timing Gap
Protection check retire stage mein hoti hai (jab instruction commit karti hai). Lekin execution stage pehle run hoti hai:
Time 0: Load kernel_addr issued
Time 1: Load executes out-of-order (data fetched to cache)
Time 2: Load retires → permission check → #PF raised → instruction aborted
Gap = Time 1 to Time 2 jahan kernel data cache mein hai.
Step 3: Encoding Secret into Cache
// Attacker code
char kernel_secret = *kernel_addr; // Faults, BUT executes first
char dummy = probe_array[kernel_secret * 4096]; // Also executes before faultWHY this step?: Fault ke baad, kernel_secret lost ho jaata hai. Lekin agar kernel_secret = 0x41 hai, toh probe_array[0x41000] hold karne wali cache line ab cached hai. Attacker measure karta hai ki kaun si cache line hot hai.
Byte value hai jahan .
WHY 4096-byte spacing? Cache lines typically 64 bytes ki hoti hain. Page size (4 KB) se spacing karna ensure karta hai ki har byte value ek ALAG cache line mein map ho, false sharing avoid karke.
// 2. Speculative load of kernel memory if (0) { // Always false, but predictor might mispredict char secret = (char)kernel_address; // This load executes speculatively before page fault probe_array[secret * 4096] = 1; // Encodes secret in cache }
// 3. Measure timing to recover secret for (int i = 0; i < 256; i++) { uint64_t start = __rdtsc(); char dummy = probe_array[i * 4096]; uint64_t time = __rdtsc() - start; if (time < CACHE_THRESHOLD) printf("Secret byte =0x%02x\n", i); }
**Why this step?** `if (0)` block architecturally kabhi execute nahi hota, lekin branch predictors ke paas multi-bit history hoti hai. Agar hum pehle unhe `if (1)` se train karein, toh woh speculatively block mein enter kar sakte hain ek baar.
## Spectre: Poisoning the Branch Predictor
> [!definition] Spectre (CVE-2017-5753, CVE-2017-5715)
> Attacks ki ek class jo ==CPU ke branch predictor ko train== karti hai ek security check ko mispredict karane ke liye, jisse attacker-chosen code paths ka speculative execution hota hai jo microarchitectural state ke through secrets leak karta hai. Meltdown ke unlike, victim code khud hi leaky operations perform karta hai.
### Variant 1: Bounds Check Bypass (BCB)
**Scenario**: Bounds check wala code:
```c
if (x < array_size) {
y = array[x];
z = data[y * 4096]; // Dependent load
}
Attack Setup:
- Train the predictor: Valid
xke saath hazaron baar call karo → predictor seekhta hai branch taken hai - Exploit: Malicious
x = address - &arrayke saath call karo- Predictor branch ko taken mispredict karta hai
- Speculative path
array[x]load karta hai (actuallyaddress),data[y*4096]mein encode karta hai
- Extract:
data[]par cache timing measure karo
Why it works: Comparison x < array_size compute karne mein ~cycles lagte hain (may involve array_size ke liye memory fetch). Branch predictor 1 cycle mein history use karke decide karta hai. Speculative window = compute time.
// Attacker training phase for (int i = 0; i < 1000; i++) { _mm_clflush(&array1_size); // Slow down the check victim_function(i % array1_size); // Train branch as taken }
// Attack _mm_clflush(&array1_size); size_t malicious_x = (size_t)&secret - (size_t)array1; victim_function(malicious_x); // Speculatively reads secret
// Timing analysis recovers secret
**Why flush array1_size?** Comparison `x < array1_size` ko slower banata hai (cache miss), speculative window ko widen karta hai.
### Variant 2: Branch Target Injection (BTI)
**Mechanism**: ==Branch Target Buffer (BTB)== ko poison karo, jo indirect jump targets predict karta hai:
```c
void (*func_ptr)(void) = user_input;
func_ptr(); // Indirect call
Attacker BTB ko train karta hai func_ptr destination mispredict karne ke liye → CPU speculatively victim ke address space mein gadget code execute karta hai.
Why indirect branches? Direct branches target instruction encode karte hain. Indirect branches (function pointers, virtual calls, returns) ke liye prediction chahiye — BTB store karta hai (branch_address, history) → target_address.
BT aliasing: BTBs low address bits se index karte hain. Alag virtual addresses jinke matching low bits hain, collide karte hain:
0x1234 par attacker code victim code 0xFF1234 ke use kiye gaye entry ko poison kar sakta hai.
Why it's wrong: Spectre ANY code ko affect karta hai jisme:
- Secret-dependent data par based conditional branches hon
- Speculation windows (saare modern CPUs)
- Shared microarchitectural state (processes ke beech bhi)
Spectre mein demonstrate kiya gaya hai: OS kernels, hypervisors, TEEs (SGX), cryptographic libraries, language runtimes. Vulnerability CPU ki optimization strategy mein hai, software mein nahi.
The fix: Software mitigations (retpoline, speculation barriers) + microcode updates + architectural changes (IBRS, STIBP).
Mitigations and Performance Trade-offs
Software Mitigations
- KPTI (Kernel Page Table Isolation) — Meltdown
- User/kernel mode ke liye alag page tables
- User page tables mein kernel memory unmapped
- Cost: Har syscall/interrupt TLB flush karta hai (5-30% overhead)
-
Retpoline — Spectre v2
- Indirect jumps ko return-based trampoline se replace karo
- BTB ki jagah return stack buffer (RSB) exploit karta hai
; Instead of: jmp *%rax call set_up_target capture_spec: pause jmp capture_spec set_up_target: mov %rax, (%rsp) ; Overwrite return address ret ; RSB predicts capture_spec, actual target is rax- Cost: Indirect-call-heavy workloads ke liye ~10-30%
-
Speculation Barriers — Spectre v1
lfence(x86): Execution serialize karo, speculation block karo
if (x < size) { lfence(); // Force condition resolution before continuing y = array[x]; }- Cost: Har barrier par 20-40 cycles
Typical ranges:
- Syscall-heavy: 20-30% (KPTI)
- Indirect-call-heavy: 15-25% (Retpoline)
- Tight bounds-check loops: 5-10% (lfence)
Hardware Mitigations
Modern CPUs add karte hain:
- IBRS (Indirect Branch Restricted Speculation): Predictor sharing disable karo
- STIBP (Single Thread Indirect Branch Predictors): Sibling hyperthreads ko isolate karo
- SSBD (Speculative Store Bypass Disable): Speculative load-store bypassing block karo
WHY not just disable speculation? Performance 2-5× reduce ho jaata. Modern architectures iske upar rely karti hain.
// With lfence mitigation for (int i = 0; i < N; i++) { if (index[i] < SIZE) { _mm_lfence(); sum += array[index[i]]; } }
// Measure: cycles = rdtsc_after - rdtsc_before // Typical: ~40 cycles/iteration → ~60 cycles/iteration
**Why this step?** Real impact quantify karta hai. Microbenchmarks worst case dikhate hain; real apps average ~5-10% karte hain doosre bottlenecks ki wajah se.
> [!recall]- Ek 12-Saal-Ke Bachche Ko Samjhao
> Socho ek bahut fast student (CPU) homework kar raha hai. Faster jaane ke liye, woh next problem par kaam start kar deta hai current wala finish karne se pehle — yahi speculation hai. Woh patterns dekh ke guess karta hai agla problem kya hai.
Ab socho kuch problems ek teacher-only cabinet (kernel memory) mein lock hain. Ek din, student realize karta hai: "Agar main locked cabinet mein jhank loon JABKI main guess kar raha hoon, aur jo dekha uspe depend karke ek specific toy touch karoon, phir baad mein check karoon kaun sa toy garam hai... toh main secret answers figure out kar sakta hoon!" Teacher kehta hai "Hey, tumhe dekhne ki permission nahi thi!" aur student se likhaa hua jawab mitaata hai. Lekin toy abhi bhi garam hai — evidence abhi bhi wahan hai.
Yahi Spectre/Meltdown hai. CPU apne galat jawaab erase kar deta hai lekin "garam toy" (cache) erase karna bhool jaata hai. Hackers measure karte hain kaun sa toy garam hai secrets churaane ke liye. Fix: behtar locks (KPTI), slower but safer guessing (retpoline), aur CPU ko sikhana ki toys touch karne se pehle double-check kare (lfence).
> [!mnemonic] S.P.E.C.T.R
> - **S**peculative execution checks se pehle
> - **P**redictor poisoning (training phase)
> - **E**ncoding secrets in cache state
> - **C**ache timing reveals information
> - **T**ransient instructions leave traces
> - **R**ollback sirf registers fix karta hai (cache nahi)
> - **E**xploit microarchitectural side effects
## Connections
- [[Branch Prediction]] — trained predictors Spectre attacks enable karte hain
- [[Cache Memory Hierarchy]] — timing differences side channels enable karte hain
- [[Virtual Memory and Paging]] — page table isolation (KPTI) Meltdown mitigate karta hai
- [[Out-of-Order Execution]] — speculative windows create karta hai
- [[Privilege Levels and Protection Rings]] — attacked isolation boundaries
- [[TLB (Translation Lookaside Buffer)]] — KPTI se flush hota hai, performance cost
- [[Hyperthreading and SMT]] — shared microarchitectural state attack surface badhata hai
---
#flashcards/hardware
Meltdown aur Spectre mein key difference kya hai? :: Meltdown out-of-order execution exploit karta hai user space se directly kernel memory padhne ke liye (CPU bug), jabki Spectre branch predictor ko train karta hai victim code ko trick karne ke liye taaki woh apne khud ke secrets leak kare (sahi-kaam-karte CPUs ko affect karta hai).
Woh do microarchitectural states kaun si hain jo vulnerability create karti hain? ::: Architectural state (registers, memory — correctly rolled back) aur microarchitectural state (cache, branch predictors — mispeculation ke baad NOT rolled back).
Cache timing attacks mein probe array 4096 bytes apart kyun spaced hoti hai? ::: Yeh ensure karne ke liye ki har possible byte value (0-255) ek ALAG cache line mein map ho, false sharing avoid karte hue. 4 KB = page size > cache line size (64 B).
Speculative execution window kya hai? ::: Woh time gap jab ek speculative instruction execute hoti hai aur jab CPU realize karta hai speculation galat thi aur abort karta hai. Typically 10-50 cycles. Branch prediction latency ya slow condition computation se create hota hai.
Retpoline Spectre v2 ko kaise mitigate karta hai? ::: Indirect jumps ko ek return-based trampoline se replace karta hai jo poisonable branch target buffer (BTB) ki jagah return stack buffer (RSB) exploit karta hai, attacker-controlled speculation targets prevent karta hai.
KPTI kya karta hai aur uska cost kya hai? ::: Kernel Page Table Isolation user-mode page tables se kernel memory unmap karta hai, Meltdown block karta hai. Cost: har syscall/interrupt par TLB flushes se 5-30% overhead.
lfence (speculation barrier) Spectre v1 ke against effective kyun hai? ::: Yeh execution serialize karta hai — CPU ko condition fully resolve karne ke liye force karta hai aage badhne se pehle, woh speculative window eliminate karta hai jahan bounds checks bypass ho sakte hain.
In vulnerabilities fix karne ke liye aap speculation fully disable kyun nahi kar sakte? ::: Modern CPUs performance ke liye speculation par rely karte hain — disable karne se 2-5× slowdown aa jaata. Speculation memory latency (200+ cycles) aur branch misprediction costs (10-20 cycles) hide karta hai.
BTB aliasing kya hai aur yeh Spectre v2 ko kaise enable karta hai? ::: Branch Target Buffer low address bits use karke index karta hai. `0x1234` par attacker code woh BTB entry poison kar sakta hai jo victim code `0xFFFF1234` use karta hai, jisse mispredicted indirect jumps attacker-chosen gadgets tak ho jaate hain.
Cache timing microarchitectural state ko observable information mein kaise convert karta hai? ::: Cache hits (~4 ns) memory misses (~200 ns) se ~50× faster hoti hain. Probe array locations ke access times measure karke, attackers determine karte hain ki speculative execution kaunsi cache line laya, secret value reveal karta hai.
## 🖼️ Concept Map
```mermaid
flowchart TD
A[Speculative Execution] -->|hides latency of| B[Slow Memory ~200x]
A -->|guided by| C[Branch Prediction]
A -->|separates| D[Architectural State]
A -->|leaves traces in| E[Microarchitectural State]
D -->|rolled back on| F[Misprediction]
E -->|NOT rolled back| F
E -->|includes| G[Cache Contents]
G -->|leaked via| H[Cache Timing Side Channel]
A -->|enables attacks| I[Spectre]
A -->|enables attacks| J[Meltdown]
J -->|reads| K[Kernel Memory]
J -->|exploits gap before| L[Page Fault #PF]
L -->|checked at| M[Retire Stage]
K -->|encoded into| G
G -->|decoded by| H
H -->|extracts| N[Secret Value]