What Spectre Actually Exploits

This chapter examines the mechanism that links commercial RISC-V processors to Spectre: how a prediction can send execution down the wrong path, and how that path can leave evidence after the processor discards it. The goal is not to memorize four attack names, but to understand the conditions that make a transient operation observable and therefore relevant to isolation.

A processor can be correct and still leave evidence

A processor’s architectural state is the part a program is supposed to observe: register values, memory updates, exceptions, and control flow after instructions have committed. Microarchitectural state is the machinery used to produce that result—queues, predictors, caches, and other internal structures. Programs normally do not need to know the difference. Spectre exists in the gap between them.

An out-of-order processor keeps many instructions in flight so that it can use available execution resources instead of waiting for every earlier operation to finish. It also predicts control or data flow. A branch may have a condition that is not resolved yet, but the processor can guess its likely direction and begin executing instructions from that path. A memory operation may also proceed based on a prediction about dependencies. If the guess is right, the work can eventually become part of the normal instruction stream. If it is wrong, the processor must prevent the wrong-path instructions from changing the program’s official result.

That rollback is necessary, but it is not necessarily a complete erasure. A transient instruction may access a cache line, influence a predictor, or affect another measurable resource before the condition that justified it is known to be false. When the processor later discovers the misprediction, it can remove the instruction’s architectural effects while leaving some internal trace behind. A cache line can be faster to access. A predictor entry can prefer a different outcome. The program sees a correction; an observer may see a history.

The basic Spectre chain has four roles. First, an attacker influences some prediction state or arranges inputs that make a security-sensitive prediction likely. Second, the attacker triggers a victim path at a moment when the processor has not resolved the relevant condition. Third, a wrong-path operation uses a value or address that the architectural program would have rejected. Finally, the attacker measures a residual effect through a covert channel and infers something about the transient operation. The sensitive value does not need to be returned by the victim function. It only needs to affect an observable part of the machine before rollback.

sequenceDiagram participant A as Attacker participant P as Predictor state participant V as Victim execution participant C as Cache or covert channel A->>P: Influence history or target state A->>V: Trigger the victim path V->>P: Consult prediction state P-->>V: Speculative direction V->>C: Wrong-path operation leaves a residue V-->>V: Architectural resolution rolls back the path A->>C: Observe timing or another signal C-->>A: Infer information about the transient operation

The diagram shows why the attack is not simply “run an illegal instruction.” The processor can preserve architectural rules and still expose an observable side effect. It also shows why the attacker needs more than speculation. There must be a useful victim gadget, a way to influence the relevant prediction or dependency, and an observation channel with enough signal to distinguish outcomes. Remove any one of those conditions and the same speculative capability may not become a practical disclosure.

This distinction is important when discussing RISC-V. The base instruction semantics tell software what committed operations mean; they do not, by themselves, tell software how a commercial core predicts a branch, how long wrong-path work can continue, or which internal effects survive correction. Those are properties of the implementation and its configuration. The four Spectre families make that hidden dependency easier to see because each targets a different part of the processor’s machinery.

Four ways to put the wrong path in motion

PHT: a conditional branch learns the wrong lesson

Spectre-PHT, commonly associated with the first Spectre variant, targets the history used to predict direct conditional branches. Consider a bounds check. Architecturally, the check is supposed to establish that an index is valid before a later load uses it. An attacker can repeatedly present inputs that make the branch follow one direction, encouraging the predictor to learn that pattern. A later input can violate the bound. If the processor predicts the familiar direction before the new condition is resolved, the dependent load may execute transiently with an out-of-bounds index.

The important point is not the particular array pattern. It is the separation between the check’s logical meaning and the time at which the processor acts on its prediction. The branch eventually resolves and the wrong path is discarded, but a transient load may already have influenced a cache-based channel. PHT attacks therefore expose a dependency between a control-flow check and later data access. A defense must either prevent unsafe work from proceeding or ensure that the transient path cannot use the untrusted result to create a useful signal.

BTB: an indirect branch can be redirected

Spectre-BTB targets the branch target buffer, which helps predict where an indirect branch will go. An indirect branch does not have one fixed destination encoded in the instruction; its target depends on a register or other runtime state. If the predictor has been trained to associate the branch with a different target, the processor may transiently begin executing an attacker-chosen gadget before the real target is known.

This mechanism differs from a bounds-check bypass. The attacker is not merely trying to use a bad index at a legitimate location. The goal is to redirect transient control flow toward code that is architecturally unreachable from the victim’s intended path. That makes the availability of gadgets and the way target entries are indexed important. An attacker may train the same branch, or may use a different branch that collides in the predictor. The latter is an out-of-place attack: the instructions used for training and exploitation differ, but the predictor treats them as related.

BTB behavior also illustrates why privilege boundaries cannot be inferred from branch semantics alone. If entries are tagged or partitioned by privilege level, a user process may be unable to poison a kernel branch through the tested path. If predictor state is shared within a privilege domain, attacks across processes or within kernel code can remain possible. The same indirect-branch instruction can therefore sit inside different practical threat surfaces on different processors.

RSB: returns depend on a separate prediction structure

Spectre-RSB, or return-oriented speculation, targets the return stack buffer. A return instruction normally uses information associated with earlier calls, and the RSB predicts which address should receive control when the callee returns. If that history diverges from the architectural call stack, transient execution may continue at an unintended location.

The RSB has its own failure modes. Deep call chains can exhaust the entries available to the processor. Domain transitions or unusual control-flow patterns can also change the relationship between the predicted and architectural stacks. What happens after underflow is therefore security-relevant: a processor might stall, continue along a different path, or consult another prediction structure. A software defense such as a retpoline depends on those details. It is not enough to know that a return instruction exists; one must know what the implementation predicts when the expected return history is no longer available.

STL: a dependency prediction can expose stale data

Spectre-STL, also called a store-to-load or speculative store-bypass attack, does not primarily redirect control flow. It targets a prediction about whether a load depends on an earlier store. If the processor decides too early that the operations are independent, the load can transiently read an older value before the true dependency is resolved.

That gives Spectre a different shape. The suspicious operation may be an ordinary load, and the security failure comes from the processor’s ordering assumption rather than a branch target. A defense that protects conditional branches may not address it. This is why “add a fence after every bounds check” cannot be treated as a complete answer to the family of transient-execution problems. The state being predicted, and the dependency that must be made safe, determine the relevant protection.

Together, PHT, BTB, RSB, and STL show that Spectre is a set of relationships between software structure and prediction machinery. They share the broad pattern of transient work leaving evidence, but they do not share one trigger, one gadget shape, or one mitigation boundary. That diversity is central to evaluating RISC-V: an implementation may expose one family strongly, constrain another through privilege partitioning, and behave differently again when firmware changes a predictor setting.

Why sharing changes the attack

The USENIX study uses two distinctions to describe how an attacker and victim interact with predictor state. A same-address attack trains and exploits the same instruction. A cross-address attack trains one instruction and relies on a colliding entry associated with another address. In-place attacks use the target branch itself; out-of-place attacks use a different branch to influence a shared prediction structure. These are not merely labels for a table. They identify where the state crosses a boundary.

The boundary may be inside one process, between processes, or between privilege levels. Same-address, in-place behavior can be the most direct because the training operation and the victim operation are closely coupled. Cross-address and out-of-place behavior tests whether an attacker can find an alias in the predictor and whether the processor retains enough shared state across a context switch. A processor can therefore resist one form while remaining susceptible to another without contradiction.

Privilege separation is especially easy to overread. A user/kernel split in one branch predictor may stop cross-privilege poisoning for that structure, but it does not make every microarchitectural resource private. Same-privilege processes may still share prediction state. An intra-kernel program may still reach a vulnerable path. A different Spectre family may use a structure that is not protected by the same partition. “The predictor is isolated” is incomplete unless the speaker identifies which predictor, which domains, and which attack relationship.

The same reasoning applies to firmware defaults. If a branch-target predictor is disabled, one attack path may be harder to use on that configuration. Enabling it changes the available surface without changing the ISA or the application binary. Conversely, a feature that is disabled by default is not evidence that every deployment has the same setting. Configuration is part of the security state and needs to be observable and maintained like any other security control.

Speculation is necessary, not sufficient

A transient capability becomes a security issue only when several conditions align. The attacker needs code execution in the relevant environment under the study’s threat model, a victim instruction sequence that can use the transient value, enough influence over prediction or dependency state, and a covert channel that carries information out. The cache is a common channel because a transient access can change later access time, but the general principle is broader: the residual state must be measurable and correlated with the secret.

The victim gadget is a mediator between prediction and disclosure. It supplies the operation that turns a mispredicted condition into an observable distinction. Without such a gadget, a predictor may still be controllable but have no sensitive consequence. Without a channel, a transient load may happen without giving the attacker a usable signal. Without enough predictor influence, the wrong path may occur too rarely or too briefly. This is why an empirical attack result should report not only that speculation exists, but also which configuration, sharing relationship, and measurement method made the result reliable.

The converse matters too. A failure of one attack configuration does not prove that the processor is safe. The study’s taxonomy exists partly to avoid that inference. A cross-privilege PHT path can fail because a predictor is partitioned, while a same-privilege path succeeds. An RSB attack can depend on underflow behavior that differs from BTB behavior. A processor may show no leakage through the tested cache channel while another residual resource remains unexplored. Security conclusions must follow the tested mechanism and channel.

The implication for an open ISA

For commercial RISC-V, the mechanism sets a clear standard for what must be specified and what must be measured. The instruction set provides a common language for software, but the attack surface is shaped by out-of-order execution, prediction structures, dependency handling, privilege partitioning, and firmware configuration. Two processors can execute the same program and still offer different opportunities for transient manipulation. A mitigation that relies on one processor’s RSB underflow behavior or on an observed serialization effect cannot silently become a universal RISC-V guarantee.

The study of the SiFive P550 and T-Head Xuantie C910/C920 is valuable because it tests these relationships on commercial out-of-order designs rather than leaving them in the realm of hypothetical research cores. The next question is empirical: which of the attack families appear on those processors, with what reliability, and under which configurations? Once those measurements are on the table, the security discussion can move from the abstract possibility of Spectre to the concrete difference between a shared ISA and the machines that implement it.

References