5.3.15 · D5Advanced Microarchitecture
Question bank — Spectre - Meltdown speculative side channels
Before we start, one anchor everyone confuses — hold these two pictures apart:
True or false — justify
TorF: When the CPU discovers a misprediction, it undoes everything the wrong-path instructions did.
False. It undoes the architectural state (registers, committed memory) but leaves microarchitectural footprints — most importantly, cache lines the wrong path pulled in. That leftover is the whole attack surface.
TorF: Meltdown works because the permission check in the page table is buggy or missing.
False. The check is present and correct; it just happens late (at retire), while the forbidden load already ran early out-of-order and touched the cache. It's a timing/ordering flaw, not a missing check.
TorF: In Meltdown the attacker's program ends up holding the secret byte in one of its registers.
False. The register value is discarded when the page fault aborts the instruction. The secret is recovered indirectly by measuring which cache line the secret-indexed probe touched.
TorF: Spectre and Meltdown are the same bug with two names.
False. Meltdown breaks privilege isolation (user reads kernel across a fault). Spectre makes the victim's own trusted code speculatively misbehave via a poisoned predictor — no privilege violation is needed inside the victim.
TorF: Spectre v1 requires the attacker to inject their own instructions into the victim.
False. The leaky instructions are the victim's legitimate
array[x] load. The attacker only supplies a malicious x and pre-trains the branch, then the victim's own code leaks under misprediction.TorF: A perfectly random branch predictor (50/50 guessing) would defeat Spectre v1.
Mostly true but useless. If the predictor could not be trained, the attacker couldn't reliably force the wrong-path speculation. But a random predictor also destroys performance, which is the entire reason Branch Prediction exists — so it's not a real option.
TorF: Meltdown can read any physical memory on the machine, always.
Partly. It reads memory mapped into the attacker's address space (classically, the kernel's direct-map of all RAM). If a region isn't mapped at all, there's no cached entry to leak — which is exactly why KPTI works.
TorF: The cache-timing side channel is what leaks the secret; speculation is optional.
False. Both are required. Speculation is what lets a forbidden or wrong-path load run at all; the cache side channel is the readout mechanism that survives the rollback. Remove either and the attack collapses.
TorF: Flushing the cache before the attack helps the defender.
False here — the attacker flushes the probe array first (
clflush) so that afterward exactly one hot line stands out. A clean starting cache is the attacker's measuring instrument, not a defense.Spot the error
Find the flaw: "Meltdown is safe on my CPU because it never executes if(0) blocks — dead code is dead."
The
if(0) block never commits, but the predictor can still speculatively enter it before the condition resolves. "Dead architecturally" is not "never executed microarchitecturally."Find the flaw: "Spectre v1's speculative window exists because the branch itself is slow."
The branch prediction is fast (~1 cycle). The window exists because computing the condition (
x < array_size) is slow — e.g. array_size is a cache miss. The gap between the fast guess and the slow truth is the exploit window.Find the flaw: "We space the probe array by 64 bytes because that's the cache-line size."
Spacing by 64 B would let neighbouring secret values land on the same line (prefetching, adjacent-line effects) and blur the readout. You space by 4096 B (a page) so each of the 256 byte-values maps to a clearly distinct line.
Find the flaw: "Retpoline fixes Spectre by making indirect jumps predict correctly."
Retpoline doesn't make prediction correct — it removes the BTB from the loop by converting the indirect jump into a
ret, steering any speculation into a harmless spin (pause; jmp) instead of an attacker-poisoned target.Find the flaw: "KPTI stops Meltdown by making the page-table permission check happen earlier."
KPTI changes what is mapped, not when checks run. It unmaps kernel pages from the user page tables, so the forbidden address has no valid translation to speculatively load — the secret was never reachable to cache.
Find the flaw: "Branch Target Injection needs the attacker and victim to share the exact same branch address."
They only need matching low address bits. The BTB indexes with
branch_addr mod 2^n, so 0x1234 and 0xFF1234 alias to the same entry — this collision is what lets attacker training poison a victim branch.Find the flaw: "Since Meltdown leaks through cache, disabling the cache would fix it with no downside."
It would kill the side channel and cripple performance by ~100×, since the entire cache hierarchy exists to hide 200 ns memory latency. Not a usable fix.
Why questions
Why must the secret be multiplied (e.g. secret * 4096) before indexing the probe array?
To spread each possible byte value onto its own distinct cache line/page. Without the stride, distinct secrets would collide in one line and become indistinguishable by timing.
Why does the attacker train the predictor with many legitimate calls before striking once?
Predictors use multi-bit history/saturating counters, so one wrong call still predicts "taken." Training biases the predictor so the single malicious call speculates down the leaky path.
Why is Meltdown considered easier to fully fix in hardware than Spectre?
Meltdown is a single specific ordering bug (permission check after out-of-order fetch), so CPUs can add the check into the speculative path. Spectre exploits speculation in general — the CPU's core optimization strategy — so there's no single line to fix.
Why does SMT make some Spectre variants worse?
Sibling threads on one core share microarchitectural resources (BTB, predictors, some caches). An attacker thread can poison predictor state or observe cache timing of a victim thread running simultaneously on the same core.
Why does flushing array1_size from cache help the attacker in Spectre v1?
A cache miss on
array1_size makes evaluating x < array1_size slow, widening the speculative window and giving the wrong-path load more time to complete and leave a cache footprint.Why can't we simply "roll back the cache" after a misprediction like we roll back registers?
Register rollback is cheap (a few renamed entries). The cache is large, shared, and its contents are the very thing that makes the CPU fast — snapshotting/restoring it per speculation would erase all performance benefit and add huge complexity.
Why does Spectre v2 target indirect branches specifically?
Indirect branches (function pointers, virtual calls, returns) don't encode their target in the instruction, so the CPU must guess the target from the BTB. That guessed target is exactly what the attacker poisons; direct branches have a fixed encoded target with far less to poison.
Edge cases
Edge case: What if the forbidden address in Meltdown maps to a page that is not present at all (not just protected)?
If there's no translation and no data anywhere in the hierarchy, the speculative load has nothing to bring into cache — so KPTI-style unmapping (not merely protecting) is what neuters the leak.
Edge case: What happens if the secret byte is 0x00?
Then
probe_array[0 * 4096] is the hot line. 0x00 is a perfectly valid recoverable value — but attackers often pre-flush and sometimes handle index 0 carefully because prefetchers can accidentally warm the very first line.Edge case: Two different byte values happen to land on cache lines that are both hot after one run. What went wrong?
Likely noise or prefetching — an adjacent-line/stride prefetcher pulled in a neighbour, or a prior run left residue. Attackers repeat and take a statistical majority, and use unpredictable access order, to suppress this.
Edge case: The victim's branch condition resolves faster than the CPU can start the speculative load. Effect on Spectre v1?
The speculative window shrinks toward zero and the leaky load may never complete before rollback — no cache footprint, no leak. This is why attackers actively slow the condition (flush
array_size) to keep the window open.Edge case: A CPU that commits instructions strictly in order but still fetches data out of order — is it Meltdown-safe?
Not necessarily. In-order commit is normal; the danger is out-of-order data fetch before the permission check. If the forbidden fetch reaches cache before the fault, the leak still exists.
Recall One-line summary you must be able to say
Question: In one sentence, what single fact makes both Spectre and Meltdown possible? ::: Rolling back the architectural state after wrong speculation does not erase the microarchitectural footprints (cache lines) the wrong path left behind.