Detecting speculative leaks with compositional semantics cover

Detecting speculative leaks with compositional semantics

XAVER FABIAN
CISPA Helmholtz Center for Information Security, Germany and University of Trento, Italy
MARCO GUARNIERI
IMDEA Software Institute, Spain
BORIS KÖPF
Azure Research, Microsoft, UK
JOSE F. MORALES
IMDEA Software Institute, Spain
MARCO PATRIGNANI
University of Trento, Italy
JAN REINEKE
Saarland University, Germany
ANDRES SANCHEZ
Amazon, Spain

Abstract

Speculative execution enhances processor performance by predicting intermediate results and executing instructions based on these predictions. However, incorrect predictions can lead to security vulnerabilities, as speculative instructions leave traces in microarchitectural components that attackers can exploit. This is demonstrated by the family of Spectre attacks. Unfortunately, existing countermeasures to these attacks lack a formal security characterization, making it difficult to verify their effectiveness.
In this paper, we propose a novel framework for detecting information flows introduced by speculative execution and reasoning about software defenses. The theoretical foundation of our approach is speculative non-interference (SNI), a novel semantic notion of security against speculative execution attacks. SNI relates information leakage observed under a standard non-speculative semantics to leakage arising under a semantics that explicitly model speculative execution. To capture their combined effects, we extend our framework with a mechanism to safely compose multiple speculative semantics, each focussing on a single aspect of speculation.This allows us to analyze the complex interactions and resulting leaks that can arise when multiple speculative mechanisms operate together. On the practical side, we develop Spectector, a symbolic analysis tool that uses our compositional framework and leverages SMT solvers to detect vulnerabilities and verify program security with respect to multiple speculation mechanisms. We demonstrate the effectiveness of Spectector through evaluations on standard security benchmarks and new vulnerability scenarios.
Authors' addresses: Xaver Fabian, CISPA Helmholtz Center for Information Security, Saarbrücken, Germany, [email protected] and University of Trento, Trento, Italy; Marco Guarnieri, IMDEA Software Institute, Madrid, Spain, [email protected]; Boris Köpf, Azure Research, Microsoft, UK; Jose F. Morales, IMDEA Software Institute, Madrid, Spain; Marco Patrignani, University of Trento, Trento, Italy, [email protected]; Jan Reineke, Saarland University, Saarbrücken, Germany; Andres Sanchez, Amazon, Madrid, Spain.

1. Introduction

Speculative execution avoids pipeline stalls by predicting the results of intermediate computations and by speculatively executing instructions based on such predictions. Whenever a prediction turns out to be incorrect, the processor squashes the speculatively executed instructions, thereby rolling back their effects on the architectural state, which consists of registers, flags, and memory. However, the execution of speculative instructions leaves footprints in a CPU's microarchitectural components (like caches, predictors, and internal buffers) that may persist even after these instructions have been squashed. As shown by Spectre [1] and follow-up attacks [2, 3, 4, 5, 6, 7, 8, 9], these microarchitectural side effects can be exploited to compromise the security of programs and to leak information about speculatively accessed data.
Speculative Leaks Modern CPUs employ a wide range of speculation mechanisms (branch predictors, memory disambiguators, etc.) that are used to speculate over different kinds of instructions and intermediate results, such as conditional branches [1], indirect jumps [1], store and load operations [10], return instructions [2, 11], and load addresses and loaded results [12, 13, 14]. All these speculation mechanisms can be exploited by attackers to leak data.
Code snippets vulnerable to different kinds of speculation attacks.

Code snippets vulnerable to different kinds of speculation attacks.

As an example, the code in is vulnerable to a Spectre-PHT attack [1], which exploits speculation over branch instructions. Whenever the branch prediction mispredicts the outcome of the condition y > size\texttt{y > size}y > size on the theorem, this results in speculatively executing the theorem, which leaks the out-of-bounds value pointed by A[y]\texttt{A[y]}A[y] through the data cache. As another example, depicts a code snippet vulnerable to a Spectre-STL attack [10], which exploits speculation over memory disambiguation checks. Whenever the memory write on the theorem is predicted to have a different address than the memory read *p\texttt{*p}*p on the theorem, the content of secret\texttt{secret}secret is leaked to an attacker. Essentially, the memory write in the theorem is bypassed because of speculation.
The majority of well-known attacks [1, 2, 3, 10, 15] only exploit leaks introduced by individual speculation mechanisms, e.g., branch predictors in Spectre-PHT () and memory disambiguators in Spectre-STL (). However, some speculative leaks only arise due to the interaction of multiple mechanisms. For example, the code in can speculatively leak the value of &secret in the theorem whenever (1) the memory write to p in the theorem is predicted to have a different address then the memory read *p on the theorem, and (2) the branch instruction on the theorem is mispredicted as taken. This leak, therefore, arises from the combination of two speculation mechanisms—branch prediction and memory disambiguation prediction—and it cannot be detected when considering the two mechanisms in isolation.
Limitations of existing leak-detection approaches Since the discovery of Spectre [1], a number of approaches have been proposed for reasoning about the security of programs against speculative leaks [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27].
These approaches employ a wide array of techniques for reasoning about leaks (e.g., symbolic execution [16, 17, 18, 19, 20, 21], abstract interpretation [22], testing [23, 24, 25, 26, 27]), but they all share a critical limitation. They support only fixed speculation mechanisms, such as branch prediction [28, 21, 20, 17, 29] and memory disambiguation prediction [19, 16, 30], which are hard-coded, e.g., in the underlying formal models. As a result, extending them to reason about a new speculation mechanism is often complicated (e.g., it might require modifying the underlying formal model and updating the corresponding security proofs), since none of these approaches has been designed in a compositional manner.
As shown by code snippets like, sound reasoning about speculative leaks in a program requires accounting for all speculation mechanisms, since ignoring some mechanisms might lead to missed leaks. Unfortunately, (1) we lack a precise understanding of the speculation mechanisms implemented in current CPUs, as demonstrated time and again by attacks discovering previously unknown speculation mechanisms, and (2) new CPU generations often implement refined and improved speculation mechanisms to improve performance [13, 12]. Since we cannot develop an analysis that would account for future microarchitectures, approaches for reasoning about speculative leaks must be compositional and easy to extend whenever a new speculation mechanism is discovered. However, we currently lack a precise characterization of security against speculative leaks and an associated program analysis framework that is extensible and compositional in the underlying speculation mechanisms.
Our approach: In this paper, we develop a novel, principled approach for reasoning about leaks introduced by speculatively executed instructions and for reasoning about software defenses against Spectre-style attacks. Our approach is backed by a semantic characterization of security against speculative leaks and it comes with an algorithm, based on symbolic execution, for proving the absence of leaks. Crucially, our approach is compositional. It allows specifying individual operational semantics—each one capturing the effects of a different speculation mechanism—and combining them in a single composed semantics, which captures leaks arising from the interactions of all these mechanisms, thereby leading to simpler formalizations. Additionally, these semantics can be directly integrated in our verification algorithm, whose soundness proof is compositional and defined in terms of the component semantics, thereby maximizing proof reuse. Next, we describe our contributions in more detail:
  • Modeling speculation: We propose a generalized template for modeling the effects of speculative execution as an operational semantics. Our template extends an architectural (non-speculative) semantics (Section 3) to a speculative semantics (Section 4) that captures the effects of speculatively executed instructions. In a nutshell, the speculative semantics follow mispredicted paths for a bounded number of steps before backtracking and restarting the architectural execution, while relying on a prediction oracle to model the speculation mechanism. Note that this template is flexible enough to capture both control-flow and data-flow speculation. Following this template, we introduce five speculative semantics (denoted ghostB{\text{ghost}_{\mathbf{\textcolor{CarnationPink}{B}}}}ghostB​, ghostJ{\text{ghost}_{\textit{\textcolor{BlueGreen}{J}}}}ghostJ​, ghostS{\text{ghost}_{\texttt{\textcolor{Emerald}{S}}}}ghostS​, ghostR{\text{ghost}_{\mathsf{\textcolor{RedOrange}{R}}}}ghostR​, and ghostSLS{\text{ghost}_{\texttt{\textcolor{DarkOrchid}{SLS}}}}ghostSLS​) which capture speculation over branches, jumps, stores, and return instructions (Section 6). This is the most comprehensive collection of individual speculative semantics in a single framework to date.
  • Speculative non-interference: We propose speculative non-interference (Section 5), a novel semantic notion of security against speculative execution attacks. Speculative non-interference is based on comparing a program with respect to two different semantics:
    1. a standard, non-speculative semantics, which we use as a proxy for the intended program behavior, and (b) a speculative semantics that captures the effects of speculation induced by one or more speculation mechanisms, which captures the effect of speculatively executed instructions.
    In a nutshell, speculative non-interference requires that speculatively executed instructions do not leak more information into the microarchitectural state than what the intended behavior does, i.e., than what is leaked by the standard, non-speculative semantics.
    To capture "leakage into the microarchitectural state", we consider an observer of the program execution that sees the locations of memory accesses and jump targets. This observer model is commonly used for characterizing "side-channel free" or "constant-time" code [31, 32] in the absence of detailed models of the microarchitecture. Under this observer model, an adversary may distinguish two initial program states if they yield different traces of memory locations and jump targets. Speculative non-interference (SNI) requires that two initial program states can be distinguished under the speculative semantics only if they can also be distinguished under the standard, non-speculative semantics.
    The speculative semantics, and hence SNI, depends on the decisions taken by the prediction oracle. We show that one can abstract away from the specific oracle by considering a worst-case oracle that always mispredicts. SNI w.r.t. this always-mispredict oracle implies SNI w.r.t. a large class of prediction strategies. This allows reasoning about speculative leaks while ignoring the details of the specific prediction strategy, which are often undocumented.
  • Composition framework: We propose a framework for composing speculative semantics that capture speculation due to different mechanisms (Section 7). The framework allows specifying individual semantics for each speculation mechanism and combining them into a composed semantics. The combination yields a single operational semantics which can be used to reason about leaks involving the different kinds of speculation it comprises (as in). We also formalize the key properties of our framework: if the individual semantics fulfill some (expected) safety conditions (which we prove for all the semantics we combine), then the composed semantics is well-formed and can be used to reason about leakage in a sound manner. That is, whenever a program is leaky under one of the individual semantics then it is leaky under the composed semantics and, vice versa, whenever a program is SNI under the composed semantics, then it is SNI w.r.t. all individual semantics. We apply the composition framework to all our individual semantics, thereby obtaining 18 combined speculative semantics (Section 8).
  • Checking speculative non-interference: We propose SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR (Section 9), an algorithm to automatically prove that programs satisfy SNI w.r.t. any speculative semantics (or composition) in our framework. Given a program ppp, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR uses symbolic execution with respect to the speculative semantics to derive a concise representation of the traces of memory accesses and jump targets during execution along all possible program paths. Based on this representation, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR creates a symbolic formula capturing that, whenever two initial program states produce the same (instruction and data) memory access patterns in the standard semantics, they also produce the same access patterns in the speculative semantics. Validity of this formula for each program path implies SNI.
  • Implementation and evaluation: We implement a prototype of SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR (Section 10), with a front-end parsing (a subset of) x86 assembly and a back-end that uses the Z3 SMT solver to perform symbolic execution against all our speculative semantics (and their combinations) and to determine whether programs contain speculative leaks. We validate SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR on both existing microbenchmarks (for speculation on branches, indirect jumps, store and return instructions) and on new ones (for speculative leaks arising from combinations of speculation mechanisms) that we introduce. These microbenchmarks contain both leaky programs as well as programs patched with well-known compiler-level countermeasures against Spectre. Using SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR, we successfully (1) detect all leaks pointed out in [33], (2) detect novel, subtle leaks that are out of the scope of existing approaches that check for known vulnerable code patterns [20], (3) detect leaks arising from speculation over multiple mechanisms that are not detected by existing symbolic approaches [34], and (4) identify cases where compilers unnecessarily inject countermeasures, i.e., opportunities for optimization without sacrificing security.
Scope of this paper This paper provides a unified, extended, and updated version of the results presented in two conference papers by [28] and [35]. In addition to the original results from [28, 35], (1) the paper introduces a general template for speculative operational semantics that generalizes existing formalizations, (2) it adds new speculative semantics for straight-line speculation and for speculation over indirect jumps (and their combinations), and (3) it provides additional technical details about the speculative semantics as well as about composition proofs. The paper is accompanied by an updated version of SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR (with an updated evaluation) that supports all new speculative semantics and combinations presented in the paper. Overall, we see this paper as a unified reference for the modeling of speculative leaks at program level and for the SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR program analysis tool.
Additional materials The SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR program analysis tool is open-source and available at [36]. Given the number of different speculative semantics studied in this paper, we leave the full formalization of all semantics, technicalities, and proof details to the associated technical report, which is available at [37].

2. Illustrative example

To illustrate our approach, we show how SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR applies to the SPECTRE-PHT{\mathchoice{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptscriptstyle PECTRE}-P{\scriptscriptstyle HT}}}{\text{SPECTRE-PHT}}}SPECTRE-PHT example [1] shown in using a speculative semantics capturing branch speculation.

Spectre-PHT

The program checks whether the index stored in the variable y is less than the size of the array A, stored in the variable size. If that is the case, the program retrieves A[y], amplifies it with a multiple (here: 512) of the cache line size, and uses the result as an address for accessing the array B.
If size is not cached, evaluating the branch condition requires traditional processors to wait until size is fetched from main memory. Modern processors instead speculate on the condition's outcome and continue the computation. Hence, the memory accesses in line 2 may be executed even if y≥size\texttt{y} \geq \texttt{size}y≥size.
When size becomes available, the processor checks whether the speculated branch is the correct one. If it is not, it rolls back the architectural (i.e., ISA) state's changes and executes the correct branch. However, the speculatively executed memory accesses leave a footprint in the microarchitectural state, in particular in the cache, which enables an adversary to retrieve A[y], even for y≥size\texttt{y} \geq \texttt{size}y≥size, by probing the array B.

Detecting leaks with Spectector

SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR automatically detects leaks introduced by speculatively executed instructions, or proves their absence. Specifically, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR detects a leak whenever executing the program under the speculative semantics, which captures that the execution can go down a mispredicted path for a bounded number of steps, leaks more information into the microarchitectural state than executing the program under a non-speculative semantics.

Algorithm 1: Spectre-PHT - Assembly code

mov size, % mov y, % cmp % jbe END mov A(% shl $9, % mov B(% and %
To illustrate how SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR operates, we consider the x86 assembly translation of's program (cf. Algorithm 1). SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR performs symbolic execution with respect to the speculative semantics to derive a concise representation of the concrete traces of memory accesses and program counter values along each path of the program. These symbolic traces capture the program's effect on the microarchitectural state.
During speculative execution, the speculatively executed parts are determined by the predictions of the branch predictor. As shown in Section 6.1, leakage due to speculative execution is maximized under a branch predictor that mispredicts every branch. The code in Algorithm 1 yields two symbolic traces w.r.t. the speculative semantics that mispredicts every branch:
start⋅rlb⋅τ‾wheny<size\textcolor{RoyalBlue}{\mathtt{start}} \cdot\textcolor{RoyalBlue}{\mathtt{rlb}}\cdot \overline{\tau} \quad \text{when} \quad \texttt{y} < \texttt{size}
start⋅τ‾⋅rlbwheny≥size\textcolor{RoyalBlue}{\mathtt{start}} \cdot \overline{\tau} \cdot \textcolor{RoyalBlue}{\mathtt{rlb}} \quad \text{when} \quad \texttt{y} \geq \texttt{size}
where τ‾=load (A+y)⋅load (B+A[y] * 512)\overline{\tau}= \textcolor{RoyalBlue}{\mathtt{load}}\ (\texttt{A} + \texttt{y} ) \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ (\texttt{B} +\texttt{A[y] * 512})τ=load (A+y)⋅load (B+A[y] * 512). Here, the argument of load\textcolor{RoyalBlue}{\mathtt{load}}load is visible to the observer, while start\textcolor{RoyalBlue}{\mathtt{start}}start and rlb\textcolor{RoyalBlue}{\mathtt{rlb}}rlb denote the start and the end of a misspeculated execution. The traces of the non-speculative semantics are obtained from those of the speculative semantics by removing all observations in between start\textcolor{RoyalBlue}{\mathtt{start}}start and rlb\textcolor{RoyalBlue}{\mathtt{rlb}}rlb.
Trace Equation 1 shows that whenever y is in bounds (i.e., y<size\texttt{y} < \texttt{size}y<size) the observations of the speculative semantics and the non-speculative semantics coincide (i.e. they are both τ‾\overline{\tau}τ). In contrast, Trace Equation 2 shows that whenever y≥size\texttt{y} \geq \texttt{size}y≥size, the speculative execution generates observations τ‾\overline{\tau}τ that depend on A[y] whose value is not visible in the non-speculative execution. This is flagged as a leak by SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR.

Proving Security with Spectector

The CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG 7.0.0 C++ compiler implements a countermeasure, called speculative load hardening [38], that applies conditional masks to addresses to prevent leaks into the microarchitectural state. Algorithm 2 depicts the protected output of CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG on the program from.

Algorithm 2: Spectre-PHT - Assembly code with speculative load hardening. Clang inserted instructions 3, 6, 9, and 11.

mov size, % mov y, % mov $ [^1][^2]0, % cmp % jbe END cmovbe $-1, % mov A(% shl$9, % or % mov B(% or % and %
The symbolic execution of the speculative semantics produces, as before, Trace Equation 1 and Trace Equation 2, but with
τ‾=load (A+y)⋅load (B+(A[y] * 512) ∣ mask),\overline{\tau}= \textcolor{RoyalBlue}{\mathtt{load}}\ (\texttt{A} + \texttt{y} ) \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ (\texttt{B} +(\texttt{A[y] * 512}) \,|\, \mathit{mask}),
where mask=ite(y<size,0x0,0xFF..FF)\mathit{mask} = \mathbf{ite}(\texttt{y} < \texttt{size},\texttt{0x0},\texttt{0xFF..FF})mask=ite(y<size,0x0,0xFF..FF) corresponds to the conditional move in line 666 and ∣|∣ is a bitwise-or operator. Here, ite(y<size,0x0,0xFF..FF)\mathbf{ite}(\texttt{y} < \texttt{size},\texttt{0x0},\texttt{0xFF..FF})ite(y<size,0x0,0xFF..FF) is a symbolic if-then-else expression evaluating to 0x0\texttt{0x0}0x0 if y<size\texttt{y} < \texttt{size}y<size and to 0xFF..FF\texttt{0xFF..FF}0xFF..FF otherwise.
The analysis of Trace 1 is as before. For Trace 2, however, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR determines (via a query to Z3 [39]) that, for all y≥size\texttt{y}\ge \texttt{size}y≥size there is exactly one observation that the adversary can make during the speculative execution, namely load (A+y)⋅load (B+0xFF..FF)\textcolor{RoyalBlue}{\mathtt{load}}\ (\texttt{A} + \texttt{y} ) \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ (\texttt{B} + \texttt{0xFF..FF})load (A+y)⋅load (B+0xFF..FF), from which it concludes that no information leaks into the microarchitectural state, i.e., the countermeasure is effective in securing the program.

3. uASM Language

In this section, we present μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM, a simple assembly-style language serving as the basis for our framework. We start by describing the attacker model we consider (Section 3.1). Then, we present the syntax (Section 3.2) and the base non-speculative semantics (Section 3.3) of μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM.

3.1 Observations and Attacker Model

We adopt a commonly-used attacker model [28, 21, 16, 19, 40, 41, 42, 29]: a passive attacker observing the execution of a program through events τ\tauτ. These events, which we call observations, model timing leaks through cache and control flow while abstracting away low-level microarchitectural details. Specifically, we consider an attacker that observes the program counter and the locations of memory accesses during computation. This attacker model is commonly used to formalize timing side-channel free code [31, 32], without requiring microarchitectural models. In particular, it captures through data and instruction caches without requiring an explicit cache model.
Obs::= load n∣store n∣pc n∣call f∣ret nτ::= ε∣Obsτ‾::= ∅∣τ‾⋅τ\begin{aligned} \mathit{Obs} \mathrel{::=}&\ \textcolor{RoyalBlue}{\mathtt{load}}\ n \mid \textcolor{RoyalBlue}{\mathtt{store}}\ n \mid \textcolor{RoyalBlue}{\mathtt{pc}}\ n \mid \textcolor{RoyalBlue}{\mathtt{call}}\ f \mid \textcolor{RoyalBlue}{\mathtt{ret}}\ n & \tau \mathrel{::=}&\ \varepsilon \mid \mathit{Obs} & \overline{\tau} \mathrel{::=}&\ \emptyset \mid \overline{\tau}\cdot \tau \end{aligned}
The store n\textcolor{RoyalBlue}{\mathtt{store}}\ nstore n and load n\textcolor{RoyalBlue}{\mathtt{load}}\ nload n events denote read and write accesses to memory location nnn, so they capture leaks through the data cache. In contrast, pc n\textcolor{RoyalBlue}{\mathtt{pc}}\ npc n, call f\textcolor{RoyalBlue}{\mathtt{call}}\ fcall f, and ret n\textcolor{RoyalBlue}{\mathtt{ret}}\ nret n events record the control-flow of the program, thereby capturing leaks through, for instance, the instruction cache. An observation τ\tauτ is either an event Obs\mathit{Obs}Obs or the empty observation ε\varepsilonε. Traces τ‾\overline{\tau}τ are sequences of observations; we indicate sequences of elements [e1;⋯ ;en][e_1; \cdots; e_n][e1​;⋯;en​] as eˉ\bar{e}eˉ, and adding an element eee to eˉ\bar{e}eˉ as eˉ⋅e\bar{e} \cdot eeˉ⋅e.

3.2 Syntax of uASM

**Figure 2:** Syntax of the $\mu$ $\textsc{Asm}$ language

Figure 2: Syntax of the μ\mu ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}} language

μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM is an assembly-like language whose syntax is presented in Figure 2. In μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM, programs ppp are sequences of mappings from natural numbers nnn (i.e., the instruction address or label) to instructions iii.
Instructions iii include skipping skip\mathbf{skip}skip, register assignments x←ex \leftarrow ex←e, loads load x,e\mathbf{load}\ x, eload x,e, stores store x,e\mathbf{store}\ x, estore x,e, indirect jumps jmp e\mathbf{jmp}\ ejmp e, conditional branches beqz x,l\mathbf{beqz}\ x, lbeqz x,l, conditional assignments x←e′?ex \xleftarrow{e'?} exe′?​e, speculation barriers spbarr\mathbf{spbarr}spbarr, calls call f\mathbf{call}\ fcall f, and returns ret\mathbf{ret}ret. Speculation barriers (spbarr\mathbf{spbarr}spbarr) and conditional assignments (x←e′?ex \xleftarrow{e'?} exe′?​e) are both commonly used to implement Spectre countermeasures. In particular, speculation barriers stop speculation outright, whereas conditional assignments are often used to replace branching instructions.
Instructions can refer to expressions eee, which are constructed by combining registers and values with unary ⊖\ominus⊖ and binary ⊗\otimes⊗ operators. Registers come from the set Regs\mathit{Regs}Regs, containing register identifiers and designated registers pc\mathbf{pc}pc and sp\mathbf{sp}sp modelling the program counter and stack pointer respectively, whereas values come from the set Vals\mathit{Vals}Vals, which includes natural numbers and ⊥\bot⊥. Note that we use ⊥\bot⊥ to denote the termination of the program.
We say that a program is well-formed if (1) it does not contain duplicate labels, (2) it contains an instruction labelled with 000, i.e., the initial instruction, and (3) it does not contain branch instructions of the form n:beqz x,n+1n : \mathbf{beqz}\ x, n+1n:beqz x,n+1. Note that the last constraint ensures that the all outcomes of branch instructions are always reflected in the value of the program counter.

Example 1: Spectre-PHT Example

The SPECTRE-PHT{\mathchoice{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptscriptstyle PECTRE}-P{\scriptscriptstyle HT}}}{\text{SPECTRE-PHT}}}SPECTRE-PHT example from can be expressed in μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM as follows:
0:x←y<size1:beqz x,⊥2:load z,A+y3:z←z∗5124:load w,B+z5:temp←temp & w\begin{aligned} & 0 : x \leftarrow \mathtt{y} < \mathtt{size} \\ & 1 : \mathbf{beqz}\ x, \bot \\ & 2 : \mathbf{load}\ z, \mathtt{A} + \mathtt{y} \\ & 3 : z \leftarrow z * 512 \\ & 4 : \mathbf{load}\ w, \mathtt{B} + z \\ & 5 : \mathtt{temp} \leftarrow \mathtt{temp}\ \&\ w \end{aligned}
quot;*. Program states $\langle p, \sigma \rangle \in \Omega$ consist of a program $p$ and a configuration $\sigma$. The program $p$ is used to look up the current instruction, whereas the configuration $\sigma = \langle m,a \rangle$ records the state of the memory $m$ and register file $a$. Memories map addresses (which are natural numbers) to values, whereas register files map register identifiers to values. " data-original-markdown=" Here, registers $\mathtt{y}$, $\mathtt{size}$, and $\mathtt{temp}$ store the respective variables. Similarly, registers $\mathtt{A}$ and $\mathtt{B}$ store the memory addresses of the first elements of the arrays $\mathtt{A}$ and $\mathtt{B}$. In the following, we use instruction keywords to denote the set of all instructions of a given type. For instance, $\mathbf{beqz}$ is the set of all branch instructions, i.e., $\mathbf{beqz} = \{\mathbf{beqz}\ x, l \mid x \in \mathit{Regs} \wedge l \in \mathit{Vals}\}$. ### 3.3 Non-speculative Semantics of uASM We now introduce the standard, non-speculative semantics of $\mu$ $\textsc{Asm}$ program, which models their execution on a platform without speculation. For this, we describe next the small-step operational non-speculative semantics $\xrightarrow{}$. The judgment for this semantics is $\langle p, \sigma \rangle \xrightarrow{\tau} \langle p, \sigma' \rangle$ and it reads: *"a program state $\langle p, \sigma \rangle$ steps to a new program state $\langle p, \sigma' \rangle$ producing observation $\tau
quot;*. Program states $\langle p, \sigma \rangle \in \Omega$ consist of a program $p$ and a configuration $\sigma$. The program $p$ is used to look up the current instruction, whereas the configuration $\sigma = \langle m,a \rangle$ records the state of the memory $m$ and register file $a$. Memories map addresses (which are natural numbers) to values, whereas register files map register identifiers to values. " data-source-offset="27227" class="markdown-segment">
Here, registers y\mathtt{y}y, size\mathtt{size}size, and temp\mathtt{temp}temp store the respective variables. Similarly, registers A\mathtt{A}A and B\mathtt{B}B store the memory addresses of the first elements of the arrays A\mathtt{A}A and B\mathtt{B}B.
In the following, we use instruction keywords to denote the set of all instructions of a given type. For instance, beqz\mathbf{beqz}beqz is the set of all branch instructions, i.e., beqz={beqz x,l∣x∈Regs∧l∈Vals}\mathbf{beqz} = \{\mathbf{beqz}\ x, l \mid x \in \mathit{Regs} \wedge l \in \mathit{Vals}\}beqz={beqz x,l∣x∈Regs∧l∈Vals}.

3.3 Non-speculative Semantics of uASM

We now introduce the standard, non-speculative semantics of μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM program, which models their execution on a platform without speculation. For this, we describe next the small-step operational non-speculative semantics →\xrightarrow{}​.
The judgment for this semantics is ⟨p,σ⟩→τ⟨p,σ′⟩\langle p, \sigma \rangle \xrightarrow{\tau} \langle p, \sigma' \rangle⟨p,σ⟩τ​⟨p,σ′⟩ and it reads: "a program state ⟨p,σ⟩\langle p, \sigma \rangle⟨p,σ⟩ steps to a new program state ⟨p,σ′⟩\langle p, \sigma' \rangle⟨p,σ′⟩ producing observation τ\tauτ". Program states ⟨p,σ⟩∈Ω\langle p, \sigma \rangle \in \Omega⟨p,σ⟩∈Ω consist of a program ppp and a configuration σ\sigmaσ. The program ppp is used to look up the current instruction, whereas the configuration σ=⟨m,a⟩\sigma = \langle m,a \rangleσ=⟨m,a⟩ records the state of the memory mmm and register file aaa. Memories map addresses (which are natural numbers) to values, whereas register files map register identifiers to values.
Configurations σ::= ⟨m,a⟩Prog. States Ω::= ⟨p,σ⟩RegisterFile a::= ∅∣r;x↦vRegisters x∈ RegsMemory m::= ∅∣m;n↦vwhere n∈ N\begin{aligned} \text{Configurations } \sigma \mathrel{::=} &\ \langle m, a \rangle & \text{Prog. States } \Omega \mathrel{::=} &\ \langle p, \sigma \rangle \\ \mathit{Register File}~a \mathrel{::=} &\ \emptyset \mid r; x \mapsto v & \mathit{Registers}~ x \in &\ \mathit{Regs} \\ \mathit{Memory}~m \mathrel{::=} &\ \emptyset \mid m; n \mapsto v & \mathit{where }~ n \in &\ \mathbb{N} \end{aligned}
Figure 3 presents the rules defining the non-speculative semantics →\xrightarrow{}​. The rules rely on the evaluation of expressions (indicated as ⟦e⟧(a)=n\llbracket e \rrbracket(a) = n[[e]](a)=n) where expression eee is evaluated to value nnn under register file aaa. In the rules, a[x↦n]a[x \mapsto n]a[x↦n], where x∈Regs∪Nx \in \mathit{Regs} \cup \mathbb{N}x∈Regs∪N and n∈Valsn\in \mathit{Vals}n∈Vals, denotes the update of a map (memory or registers), whereas a(x)a(x)a(x) denotes reading from a map. Finally, σ(x)\sigma(x)σ(x), where x∈Regsx \in \mathit{Regs}x∈Regs and σ=⟨m,a⟩\sigma = \langle m,a \rangleσ=⟨m,a⟩, denotes a(x)a(x)a(x).
\begin{figure}[!ht]\small {\bf Expression evaluation} \begin{align*} \llbracket n \rrbracket(a) = n & & \llbracket x \rrbracket(a) = a(x) & & \llbracket \ominus e \rrbracket(a) = \ominus \llbracket e \rrbracket(a) & & \llbracket e_1 \otimes e_2 \rrbracket(a) = \llbracket e_1 \rrbracket(a) \otimes \llbracket e_2 \rrbracket(a) \end{align*} \noindent\hrulefill\ \raisebox{-0.5ex}{\fbox{$\langle p,\sigma \rangle \xrightarrow{\tau} \langle p, \sigma' \rangle$}} \hrulefill\hrulefill\hrulefill \def\thetyperule{Skip}\refstepcounter{typerule}\label{tr:skip-paper}{\begin{array}c\textsf(Skip) \inference{ p(a(\mathbf{pc})) = \mathbf{skip} }{ \langle p, \langle m, a \rangle \rangle \xrightarrow \langle p, \langle m, a[\mathbf{pc} \mapsto a(\mathbf{pc})+1] \rangle \rangle }\end{array}} \def\thetyperule{Barrier}\refstepcounter{typerule}\label{tr:barr-paper}{\begin{array}c\textsf(Barrier) \inference{ p(a(\mathbf{pc})) = \mathbf{spbarr} }{ \langle p, \langle m,a \rangle \rangle \xrightarrow \langle p, \langle m,a[\mathbf{pc} \mapsto a(\mathbf{pc}) + 1] \rangle \rangle }\end{array}} \def\thetyperule{Assign}\refstepcounter{typerule}\label{tr:assign-paper}{\begin{array}c\textsf(Assign) \inference{ p(a(\mathbf{pc})) = x \leftarrow e & x \neq \mathbf{pc} }{ \langle p, \langle m, a \rangle \rangle \xrightarrow \langle p, \langle m, a[\mathbf{pc} \mapsto a(\mathbf{pc})+1,x \mapsto \llbracket e \rrbracket(a)] \rangle \rangle }\end{array}} \def\thetyperule{ConditionalUpdate-Sat}\refstepcounter{typerule}\label{tr:condup-sat-paper}{\begin{array}c\textsf(ConditionalUpdate-Sat) \inference{ p(a(\mathbf{pc})) = x \xleftarrow{e'?} e & \llbracket e' \rrbracket(a) = 0 x \neq \mathbf{pc} }{ \langle p, \langle m,a \rangle \rangle \xrightarrow \langle p, \langle m,a[\mathbf{pc} \mapsto a(\mathbf{pc}) + 1, x \mapsto \llbracket e \rrbracket(a)] \rangle \rangle }\end{array}} \def\thetyperule{ConditionalUpdate-Unsat}\refstepcounter{typerule}\label{tr:ns-condup-unsat-paper}{\begin{array}c\textsf(ConditionalUpdate-Unsat) \inference{ p(a(\mathbf{pc})) = x \xleftarrow{e'?} e & \llbracket e' \rrbracket(a) \neq 0 x \neq \mathbf{pc} }{ \langle p, \langle m,a \rangle \rangle \xrightarrow \langle p, \langle m,a[\mathbf{pc} \mapsto a(\mathbf{pc}) + 1] \rangle \rangle }\end{array}} \def\thetyperule{Terminate}\refstepcounter{typerule}\label{tr:terminate-paper}{\begin{array}c\textsf(Terminate) \inference{ p(a(\mathbf{pc})) = \bot }{ \langle p, \langle m, a \rangle \rangle \xrightarrow \langle p, \langle m, a[\mathbf{pc} \mapsto \bot] \rangle \rangle }\end{array}} \def\thetyperule{Load}\refstepcounter{typerule}\label{tr:ns-load}{\begin{array}c\textsf(Load) \inference{ p(a(\mathbf{pc})) = \mathbf{load}\ x, e & x \neq \mathbf{pc} & n = \llbracket e \rrbracket(a) }{ \langle p, \langle m, a \rangle \rangle \xrightarrow{\textcolor{RoyalBlue}{\mathtt{load}}\ n} \langle p, \langle m, a[\mathbf{pc} \mapsto a(\mathbf{pc})+1, x \mapsto m(n)] \rangle \rangle }\end{array}} \def\thetyperule{Store}\refstepcounter{typerule}\label{tr:ns-store}{\begin{array}c\textsf(Store) \inference{ p(a(\mathbf{pc})) = \mathbf{store}\ x, e & n = \llbracket e \rrbracket(a) }{ \langle p, \langle m, a \rangle \rangle \xrightarrow{\textcolor{RoyalBlue}{\mathtt{store}}\ n} \langle p, \langle m[n \mapsto a(x)], a[\mathbf{pc} \mapsto a(\mathbf{pc})+1] \rangle \rangle }\end{array}} \def\thetyperule{Beqz-Sat}\refstepcounter{typerule}\label{tr:ns-beqz-sat}{\begin{array}c\textsf(Beqz-Sat) \inference{ p(a(\mathbf{pc})) = \mathbf{beqz}\ x, \ell & a(x) = 0 }{ \langle p, \langle m, a \rangle \rangle \xrightarrow{\textcolor{RoyalBlue}{\mathtt{pc}}\ \ell} \langle p, \langle m, a[\mathbf{pc} \mapsto \ell] \rangle \rangle }\end{array}} \def\thetyperule{Beqz-Unsat}\refstepcounter{typerule}\label{tr:ns-beqz-unsat}{\begin{array}c\textsf(Beqz-Unsat) \inference{ p(a(\mathbf{pc})) = \mathbf{beqz}\ x, \ell & a(x) \neq 0 }{ \langle p, \langle m, a \rangle \rangle \xrightarrow{\textcolor{RoyalBlue}{\mathtt{pc}}\ a(\mathbf{pc})+1} \langle p, \langle m, a[\mathbf{pc} \mapsto a(\mathbf{pc}) +1] \rangle \rangle }\end{array}} \def\thetyperule{Jmp}\refstepcounter{typerule}\label{tr:jmp-paper}{\begin{array}c\textsf(Jmp) \inference{ p(a(\mathbf{pc})) = \mathbf{jmp}\ e & \ell = \llbracket e \rrbracket(a) }{ \langle p, \langle m, a \rangle \rangle \xrightarrow{\textcolor{RoyalBlue}{\mathtt{pc}}\ \ell} \langle p, \langle m, a[\mathbf{pc} \mapsto \ell] \rangle \rangle }\end{array}} \def\thetyperule{Call}\refstepcounter{typerule}\label{tr:ns-call}{\begin{array}c\textsf(Call) \inference{ p(a(\mathbf{pc})) = \mathbf{call}\ f & \mathcal{F}(f) = n & a' = a[\mathbf{pc} \mapsto n, \mathbf{sp} \mapsto a(\mathbf{sp}) - 8] & m' = m[a'(\mathbf{sp}) \mapsto a(\mathbf{pc}) + 1] }{ \langle p, \langle m, a \rangle \rangle \xrightarrow{\textcolor{RoyalBlue}{\mathtt{call}}\ f} \langle p, \langle m', a' \rangle \rangle }\end{array}} \def\thetyperule{Ret}\refstepcounter{typerule}\label{tr:ns-ret}{\begin{array}c\textsf(Ret) \inference{ p(a(\mathbf{pc})) = \mathbf{ret} & l = m(a(\mathbf{sp})) a' = a[\mathbf{pc} \mapsto l, \mathbf{sp} \mapsto a(\mathbf{sp}) + 8] }{ \langle p, \langle m, a \rangle \rangle \xrightarrow{\textcolor{RoyalBlue}{\mathtt{ret}}\ l} \langle p, \langle m, a' \rangle \rangle }\end{array}} \caption{The non-speculative small-step semantics of $\mu$ \textsc{Asm}.} \label{ns-semantics} \end{figure}
Most of the rules of the semantics in Figure 3 are standard; we describe selected rules below. Branch instructions emit observations recording the outcome of the branch (the section, the section), while memory operations emit observations recording the accessed memory (the section, the section). A call to function fff is a jump to the function's starting line number nnn, as indicated by the function map F\mathcal{F}F. A call stores the return address on the stack at the value of the stack pointer sp\mathbf{sp}sp and decreases sp\mathbf{sp}sp (the section). A return does the inverse: it looks up the return address via the stack pointer sp\mathbf{sp}sp and then increases the stack pointer (the section).
\begin{figure}[!ht] \centering <center> \noindent\hrulefill\ \raisebox{-0.5ex}{\fbox{{\left(\langle p,\sigma \rangle\right)\mathghost_{\mathit{NS}}\overline{\tau}\xspace}}} \hrulefill\hrulefill\hrulefill <br> \def\thetyperule{NS-Reflection}\refstepcounter{typerule}\label{tr:ns-reflect-paper}{\begin{array}c\textsf(NS-Reflection) <br> \inference{\langle p, \sigma \rangle \Downarrow_{\varepsilon} \langle p, \sigma \rangle }\end{array}} <br> \def\thetyperule{NS-Single}\refstepcounter{typerule}\label{tr:ns-single-paper}{\begin{array}c\textsf(NS-Single) <br> \inference{ \langle p, \sigma \rangle \Downarrow_{\overline{\tau}\xspace} \langle p, \sigma'' \rangle & \langle p, \sigma'' \rangle \xrightarrow{\tau} \langle p, \sigma' \rangle }{\langle p, \sigma \rangle \Downarrow_{\overline{\tau}\xspace \cdot \tau} \langle p, \sigma' \rangle }\end{array}} <br> \def\thetyperule{NS-Trace}\refstepcounter{typerule}\label{tr:ns-trace-paper}{\begin{array}c\textsf(NS-Trace) <br> \inference{ \exists \sigma' & \sigma' \in \mathit{FinalConf} & \langle p, \sigma \rangle \Downarrow_{\overline{\tau}\xspace} \langle p, \sigma' \rangle }{ \left(\langle p,\sigma \rangle\right)\mathghost_{\mathit{NS}}\overline{\tau}\xspace }\end{array}} <br> \def\thetyperule{NS-Beh}\refstepcounter{typerule}\label{tr:ns-beh-paper}{\begin{array}c\textsf(NS-Beh) <br> \inference{ \mathit{Beh}_NS(p) = \{\overline{\tau}\xspace \mid \exists \sigma \in \mathit{InitConf}. \left(\langle p,\sigma \rangle\right)\mathghost_{\mathit{NS}}\overline{\tau}\xspace \} }\end{array}} </center> \caption{The Reflexive-transitive-closure of $\xrightarrow{}$ and behaviour of $\mu$ \textsc{Asm} programs.} \label{fig:uasm-non-spec:beheavior} \end{figure}
\noindent\hrulefill\ \raisebox{-0.5ex}{\fbox{{\left(\langle p,\sigma \rangle\right)\mathghost_{\mathit{NS}}\overline{\tau}\xspace}}} \hrulefill\hrulefill\hrulefill
\def\thetyperule{NS-Reflection}\refstepcounter{typerule}\label{tr:ns-reflect-paper}{\begin{array}c\textsf(NS-Reflection)
\inference{\langle p, \sigma \rangle \Downarrow_{\varepsilon} \langle p, \sigma \rangle }\end{array}}
\def\thetyperule{NS-Single}\refstepcounter{typerule}\label{tr:ns-single-paper}{\begin{array}c\textsf(NS-Single)
\inference{ \langle p, \sigma \rangle \Downarrow_{\overline{\tau}\xspace} \langle p, \sigma'' \rangle & \langle p, \sigma'' \rangle \xrightarrow{\tau} \langle p, \sigma' \rangle }{\langle p, \sigma \rangle \Downarrow_{\overline{\tau}\xspace \cdot \tau} \langle p, \sigma' \rangle }\end{array}}
\def\thetyperule{NS-Trace}\refstepcounter{typerule}\label{tr:ns-trace-paper}{\begin{array}c\textsf(NS-Trace)
\inference{ \exists \sigma' & \sigma' \in \mathit{FinalConf} & \langle p, \sigma \rangle \Downarrow_{\overline{\tau}\xspace} \langle p, \sigma' \rangle }{ \left(\langle p,\sigma \rangle\right)\mathghost_{\mathit{NS}}\overline{\tau}\xspace }\end{array}}
\def\thetyperule{NS-Beh}\refstepcounter{typerule}\label{tr:ns-beh-paper}{\begin{array}c\textsf(NS-Beh)
\inference{ \mathit{Beh}NS(p) = {\overline{\tau}\xspace \mid \exists \sigma \in \mathit{InitConf}. \left(\langle p,\sigma \rangle\right)\mathghost{\mathit{NS}}\overline{\tau}\xspace } }\end{array}}
\caption{The Reflexive-transitive-closure of $\xrightarrow{}$ and behaviour of $\mu$ \textsc{Asm} programs.} \label{fig:uasm-non-spec:beheavior}
\end{figure}
Figure 4 presents the rules for deriving the trace of observations associated with an execution according to the non-speculative semantics $\xrightarrow{}$. We denote by $\left(\langle p,\sigma \rangle\right)\mathsf{ghost}_{\mathit{NS}}\overline{\tau}$ the trace $\overline{\tau}$ associated with executing the program $p$ starting from an initial configuration $\sigma$ until reaching a final configuration $\sigma'$ (the section) using the reflexive-transitive-closure $\Downarrow$ of the non-speculative semantics $\xrightarrow{}$ (the section and). To simplify our notation, we introduce the shorthand $\mathit{Beh}_{NS}(p, \sigma)$ to denote the specific trace $\tau$ generated by this execution. Finally, the *non-speculative behaviour* $\mathit{Beh}_{NS}(p)$ of a program $p$ is the set of all traces generated by all possible initial states for program $p$ (the section). ## 4. Modelling Speculative Execution In this section, we propose a general approach for modeling, at program-level, the effects of speculative execution induced by different kinds of speculation mechanisms. For this, we extend a non-speculative (i.e., architectural) semantics to a *speculative semantics* that is equipped with a *prediction oracle* (which captures how predictions are made) used to explore mispredicted paths. For this, we first informally explain the core concepts behind our model (Section 4.1). Then, we formalize prediction oracles and prediction histories (Section 4.2). We conclude by presenting the states and the evaluation relation associated with the (speculative) oracle semantics (Section 4.3). We remark that here we present only a general template for defining the oracle semantics. Such template needs to be instantiated to capture specific speculation mechanisms, and we do so in Section 6 for a large class of mechanisms. In the following, we indicate a speculative semantics as $\mathsf{ghost}_{x}$, where the metavariable $x$ is used as a placeholder indicating the type of speculation mechanism. ### 4.1 High-level Description The core idea behind our approach is to extend a non-speculative semantics—like the one from Section 3—to a *speculative semantics* that captures the effect of speculatively executed instructions. For this, our speculative semantics is parametric in two components: (1) a set $\mathit{instr}_{\mathsf{ghost}}$ of $\mu$ $\textsc{Asm}$ instructions that might trigger speculation, and (2) a *prediction oracle* ${\mathcal{O}}$ capturing the prediction strategy associated with the modeled speculation mechanism. In a nutshell, our speculative semantics works as follows. All instructions not in $\mathit{instr}_{\mathsf{ghost}}$ are executed as in the standard non-speculative semantics. In contrast, whenever an instruction in $\mathit{instr}_{\mathsf{ghost}}$ is reached, the oracle ${\mathcal{O}}$ is queried to obtain the next predicted state, which records the effects of the prediction. For instance, for branch prediction, the program counter in the predicted state is updated to decide which of the two branches to execute speculatively. To enable a subsequent rollback in case of a misprediction, a snapshot of the current program state is taken, before starting a *speculative transaction*. In this speculative transaction, the program is executed speculatively starting from the predicted state for a bounded number $w$ of computation steps, called the speculative window. To abstract from the complexity of estimating the actual speculative window (which depends on the details of a CPU's microarchitecture), in our model the speculation window $w$ is also provided by the prediction oracle. At the end of a speculative transaction, the correctness of the prediction is evaluated: (1) If the prediction was *correct*, the transaction is committed and the computation continues using the current configuration. (2) In contrast, if the prediction was *incorrect*, the transaction is aborted, the original configuration is restored, and the computation continues on the correct branch. In the following sections, we formalize the behavior intuitively described above in the general structure of the *speculative oracle semantics*, whereas in Section 6 we will present instantiations of the oracle semantics (and $\mathit{instr}_{\mathsf{ghost}}$) for different speculation mechanisms. ### 4.2 Prediction Oracles In our semantics, the prediction oracle serves two distinct purposes: (1) predicting the next program state (i.e., modeling how the speculation mechanism works), and (2) determining the length of the speculative transactions (i.e., determining for how long the speculative execution lasts). Our notion of prediction oracle is general enough to account for both control-flow speculation, such as branch prediction, and data-flow speculation, such as value prediction. A *prediction oracle* ${\mathcal{O}}$ is a partial function that takes as input a program $p$, a prediction history $h$, and the current program state $\sigma$ such that $p(\sigma(\mathbf{pc}))$ is an instruction triggering speculation, i.e., $p(\sigma(\mathbf{pc})) \in \mathit{instr}_{\mathsf{ghost}}$. The prediction oracle returns as output a triple $\langle \delta, w, \tau \rangle$, where $\delta \in \mathit{Conf}$ is a partial configuration indicating the predicted values, $w \in \mathbb{N}$ represents the speculative transaction's length, and $\tau$ is a (potentially empty) observation. One can then join the returned partial configuration $\delta$ with the current configuration $\sigma$, indicated as $\sigma \uplus \delta$, to obtain the next speculative configuration. Informally, $\sigma \uplus \delta$ simply updates $\sigma$ with the values in $\delta$ at the same places (registers, memory locations, etc). We say that a prediction oracle ${\mathcal{O}}$ has *speculative window at most* $w$ if the length of the transactions generated by its predictions is at most $w$, i.e., for all programs $p$, histories $h$, and configurations $\sigma$, ${\mathcal{O}}(p, h, \sigma) = \langle \delta,w', \tau \rangle$, for some $\delta, \tau$ such that $w' \leq w$. Taking into account the prediction history enables us to capture history-based predictors, a general class of predictors that base their decisions on past behaviors. Formally, a *prediction history* is a sequence of triples $\langle \ell, \mathit{id}, \delta \rangle$, where $\ell \in \mathit{Vals}$ is the label of an instruction related to speculation, $\mathit{id}\in \mathbb{N}$ is the unique identifier of the transaction that triggered speculation, and $\delta$ are the predicted values.

Example 2: Control-flow Prediction

The "backward taken forward not taken" (BTFNT) branch predictor, implemented in early CPUs [43], predicts the branch as taken if the target instruction address is lower than the program counter. It can be formalized by the BTFNT\mathit{BTFNT}BTFNT oracle below, for a fixed speculative window www, as follows:
BTFNT(p,h,σ)=⟨[pc↦ℓ′′],w,pc ℓ′′⟩, where ℓ′′=min(σ(pc)+1,ℓ′) and p(σ(pc))=beqz x,ℓ′\mathit{BTFNT}(p, h, \sigma) = \langle [\mathbf{pc} \mapsto \ell'' ],w, \textcolor{RoyalBlue}{\mathtt{pc}}\ \ell'' \rangle \text{, where } \ell'' = \mathit{min}(\sigma(\mathbf{pc})+1, \ell') \text{ and } p(\sigma(\mathbf{pc})) = \mathbf{beqz}\ x, \ell'
BTFNT\mathit{BTFNT}BTFNT speculatively updates the program counter to the minimum of the branch target ℓ′\ell'ℓ′ and the branch-not-taken target (i.e., σ(pc)+1\sigma(\mathbf{pc})+1σ(pc)+1). Note that the BTFNT\mathit{BTFNT}BTFNT oracle is static, that is, it is independent of the prediction history hhh. Dynamic branch predictors, such as simple 2-bit predictors and more complex correlating or tournament predictors [43], can also be formalized using prediction oracles.

Example 3: Data-flow Prediction

[24] discovered that certain Intel CPUs speculate on division operations, called Zero Dividend Injection (ZDI), thereby resulting in a restricted form of value prediction. We model this behavior with the following oracle, which predicts that the upper bits of a 128-bit by 64-bit division operation are 000:
ZDI(p,h,σ)=⟨δ,w,ϵ⟩, where p(σ(pc))=k←(x:y)÷z and δ=[k↦(0:y)÷z].\mathit{ZDI}(p, h, \sigma) = \langle \delta, w, \epsilon \rangle\text{, where } p(\sigma(\mathbf{pc})) = k \leftarrow (x:y) \div z \text{ and } \delta= [k \mapsto (0:y) \div z].
Above, (x:y)(x:y)(x:y) denotes the 128-bit value obtained by concatenating registers xxx and yyy whereas ÷\div÷ is the division operator.

4.3 Oracle Semantics

Next, we formalize the speculative oracle semantics. We start by formalizing the states over which the semantics operates and continue by presenting the evaluation relation given a prediction oracle O{\mathcal{O}}O.
Speculative States The speculative oracle semantics operates on speculative states XxX_{x}Xx​, each one consisting of a stack of speculative instances Ψx\Psi_{x}Ψx​. Each instance Ψx\Psi_{x}Ψx​ contains the program ppp, a counter ctr\mathit{ctr}ctr that uniquely identifies the speculative transaction associated with the instance, a configuration σ\sigmaσ, the prediction history hhh, and the remaining speculation window nnn describing the number of instructions that can still be executed speculatively (or ⊥\bot⊥ when no speculation is happening). Depending on the specific speculation that is modelled, additional data might be tracked (indicated with ⋯\cdots⋯ below as well as in the evaluation rules).
Spec. States Xx::= Ψ‾xSpec. Instances Ψx::= ⟨p,ctr,σ,h,n,⋯ ⟩\begin{aligned} \textit{Spec. States } X_{x} \mathrel{::=}&\ \overline{\Psi}_{x} & \textit{Spec. Instances } \Psi_{x} \mathrel{::=}&\ \langle p, \mathit{ctr}, \sigma, h, n, \cdots \rangle \end{aligned}
Evaluation rules We describe the speculative oracle semantics, given a prediction oracle Ox{\mathcal{O}}_xOx​, with the relation ⇝xOx⊆Xx×Obs∗×Xx\leadsto_{x}^{{\mathcal{O}}_{x}} \subseteq X_{x} \times \mathit{Obs}^* \times X_{x}⇝xOx​​⊆Xx​×Obs∗×Xx​, which describes how speculative states are modified along the computation while producing observations capturing leaks. To denote the start and end of speculative transactions, we extend the set of observations Obs\mathit{Obs}Obs to include three new observations startx n\textcolor{RoyalBlue}{\mathtt{start}}_{x}\ nstartx​ n, rlbx n\textcolor{RoyalBlue}{\mathtt{rlb}}_{x}\ nrlbx​ n, and commitx n\textcolor{RoyalBlue}{\mathtt{commit}}_{x}\ ncommitx​ n marking the start and end (with a commit or a rollback) of speculative transaction with id nnn respectively.
Obs::= ⋯∣startx n∣rlbx n∣commitx n\begin{aligned} \mathit{Obs} \mathrel{::=}&\ \cdots \mid \textcolor{RoyalBlue}{\mathtt{start}}_{x}\ n \mid \textcolor{RoyalBlue}{\mathtt{rlb}}_{x}\ n \mid \textcolor{RoyalBlue}{\mathtt{commit}}_{x}\ n \end{aligned}
\begin{figure}[!ht] <center> \noindent\hrulefill\ \raisebox{-0.5ex}{\fbox{{\overline{\Psi}_x\xspace \xleadsto{\tau}_x^{{\mathcal{O}}_x} \overline{\Psi}_x\xspace'}}} \hrulefill\hrulefill\hrulefill <br> \def\thetyperule{O-Context}\refstepcounter{typerule}\label{tr:o-context}{\begin{array}c\textsf(O-Context) <br> \inference{\Psi_x \xleadsto{\tau}_x^{{\mathcal{O}}_x} \overline{\Psi}_x\xspace' & \mathit{canStep}(\overline{\Psi}_x\xspace\cdot \Psi_x) <br> \text{if} p(\Psi_x . \sigma(\mathbf{pc})) = \mathbf{spbarr}\ \text{then} \overline{\Psi}_x\xspace'' = \mathit{zeroes}(\overline{\Psi}_x\xspace)\ \text{else} \overline{\Psi}_x\xspace'' = \mathit{decr}(\overline{\Psi}_x\xspace) }{\overline{\Psi}_x\xspace \cdot \Psi_x \xleadsto{\tau}_x^{{\mathcal{O}}_x} \overline{\Psi}_x\xspace'' \cdot \overline{\Psi}_x\xspace' }\end{array}} <br> \def\thetyperule{O-Rollback}\refstepcounter{typerule}\label{tr:o-rollback}{\begin{array}c\textsf(O-Rollback) <br> \inference{\langle p,\sigma'' \rangle \xrightarrow{\tau} \langle p,\sigma''' \rangle & (\sigma''' \neq \sigma'' \uplus \delta \text{ or } p, \sigma' \vdash \text{fin})}{ \overline{\Psi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, h, n, \cdots \rangle \cdot \langle p, \mathit{ctr}', \sigma', h', 0, \cdots \rangle^{\langle \sigma'',\delta \rangle} \cdot \overline{\Psi}_x\xspace' \xleadsto{\textcolor{RoyalBlue}{\mathtt{rlb}}_x\ \mathit{ctr} \cdot \tau}_x^{{\mathcal{O}}_x} \overline{\Psi}_x\xspace \cdot \langle p, \mathit{ctr}', \sigma''', h', n-1, \cdots \rangle }\end{array}} <br> \def\thetyperule{O-Commit}\refstepcounter{typerule}\label{tr:o-commit}{\begin{array}c\textsf(O-Commit) <br> \inference{ \langle p,\sigma'' \rangle \xrightarrow{\tau} \langle p,\sigma''' \rangle & (\sigma''' = \sigma'' \uplus \delta \text{ or } p, \sigma' \vdash \text{fin}) }{ \overline{\Psi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, h, n, \cdots \rangle \cdot \langle p, \mathit{ctr}', \sigma', h', 0, \cdots \rangle^{\langle \sigma'',\delta \rangle} \cdot \overline{\Psi}_x\xspace' \xleadsto{\textcolor{RoyalBlue}{\mathtt{commit}}_x\ \mathit{ctr}}_x^{{\mathcal{O}}_x} \overline{\Psi}_x\xspace \cdot \langle p, \mathit{ctr}', \sigma', h', n, \cdots \rangle \cdot \overline{\Psi}_x\xspace' }\end{array}} </center> <center> \noindent\hrulefill\ \raisebox{-0.5ex}{\fbox{{\Psi_x \xleadsto{\tau}_x^{{\mathcal{O}}_x} \overline{\Psi}_x\xspace'}}} \hrulefill\hrulefill\hrulefill <br> \def\thetyperule{O-NoSpec}\refstepcounter{typerule}\label{tr:o-noSpec}{\begin{array}c\textsf(O-NoSpec) <br> \inference{ p(\sigma(\mathbf{pc})) \notin \mathit{instr}_{\mathghost} \cup \{\mathbf{spbarr} \} & \langle p,\sigma \rangle \xrightarrow{\tau} \langle p,\sigma' \rangle }{\langle p, \mathit{ctr}, \sigma, h, n + 1, \cdots \rangle \xleadsto{\tau}_x^{{\mathcal{O}}_x} \langle p, \mathit{ctr}, \sigma', h, n, \cdots \rangle }\end{array}} <br> \def\thetyperule{O-barr}\refstepcounter{typerule}\label{tr:o-barr}{\begin{array}c\textsf(O-barr) <br> \inference{p(\sigma(\mathbf{pc})) = \mathbf{spbarr} & \sigma \xrightarrow{\tau} \sigma' }{\langle p, \mathit{ctr}, \sigma, h, n, \cdots \rangle \xleadsto{\tau}_x^{{\mathcal{O}}_x} \langle p, \mathit{ctr}, \sigma', h, 0, \cdots \rangle }\end{array}} <br> \def\thetyperule{O-Spec}\refstepcounter{typerule}\label{tr:o-spec}{\begin{array}c\textsf(O-Spec) <br> \inference{ p(\sigma(\mathbf{pc})) \in \mathit{instr}_{\mathghost} & {\mathcal{O}}(p,n,h, \sigma) = \langle \delta, w, \tau \rangle <br> h' = h \cdot \langle \sigma(\mathbf{pc}), n+1, \delta \rangle & \overline{\tau}\xspace = \textcolor{RoyalBlue}{\mathtt{start}}_x\ \mathit{ctr} \cdot \tau }{\langle p, \mathit{ctr}, \sigma, h, n + 1, \cdots \rangle \xleadsto{\overline{\tau}\xspace}_x^{{\mathcal{O}}_x} \langle p, \mathit{ctr}, \sigma, h, n+1, \cdots \rangle \cdot \langle p, \mathit{ctr} + 1, \sigma \uplus \delta, h', w, \cdots \rangle^{\langle \sigma,\delta \rangle} }\end{array}} </center> \caption{Evaluation rules for the speculative oracle semantics $\xleadsto{}_{x}^{{\mathcal{O}}_{x}}$ given an oracle ${\mathcal{O}}_x$}\label{fig:oracle-semantics:general} \end{figure}
\noindent\hrulefill\ \raisebox{-0.5ex}{\fbox{{\overline{\Psi}_x\xspace \xleadsto{\tau}_x^{{\mathcal{O}}_x} \overline{\Psi}_x\xspace'}}} \hrulefill\hrulefill\hrulefill
\def\thetyperule{O-Context}\refstepcounter{typerule}\label{tr:o-context}{\begin{array}c\textsf(O-Context)
\inference{\Psi_x \xleadsto{\tau}_x^{{\mathcal{O}}_x} \overline{\Psi}_x\xspace' & \mathit{canStep}(\overline{\Psi}_x\xspace\cdot \Psi_x)
\text{if} p(\Psi_x . \sigma(\mathbf{pc})) = \mathbf{spbarr}\ \text{then} \overline{\Psi}_x\xspace'' = \mathit{zeroes}(\overline{\Psi}_x\xspace)\ \text{else} \overline{\Psi}_x\xspace'' = \mathit{decr}(\overline{\Psi}_x\xspace) }{\overline{\Psi}_x\xspace \cdot \Psi_x \xleadsto{\tau}_x^{{\mathcal{O}}_x} \overline{\Psi}_x\xspace'' \cdot \overline{\Psi}_x\xspace' }\end{array}}
\def\thetyperule{O-Rollback}\refstepcounter{typerule}\label{tr:o-rollback}{\begin{array}c\textsf(O-Rollback)
\inference{\langle p,\sigma'' \rangle \xrightarrow{\tau} \langle p,\sigma''' \rangle & (\sigma''' \neq \sigma'' \uplus \delta \text{ or } p, \sigma' \vdash \text{fin})}{ \overline{\Psi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, h, n, \cdots \rangle \cdot \langle p, \mathit{ctr}', \sigma', h', 0, \cdots \rangle^{\langle \sigma'',\delta \rangle} \cdot \overline{\Psi}_x\xspace' \xleadsto{\textcolor{RoyalBlue}{\mathtt{rlb}}_x\ \mathit{ctr} \cdot \tau}_x^{{\mathcal{O}}_x} \overline{\Psi}_x\xspace \cdot \langle p, \mathit{ctr}', \sigma''', h', n-1, \cdots \rangle }\end{array}}
\def\thetyperule{O-Commit}\refstepcounter{typerule}\label{tr:o-commit}{\begin{array}c\textsf(O-Commit)
\inference{ \langle p,\sigma'' \rangle \xrightarrow{\tau} \langle p,\sigma''' \rangle & (\sigma''' = \sigma'' \uplus \delta \text{ or } p, \sigma' \vdash \text{fin}) }{ \overline{\Psi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, h, n, \cdots \rangle \cdot \langle p, \mathit{ctr}', \sigma', h', 0, \cdots \rangle^{\langle \sigma'',\delta \rangle} \cdot \overline{\Psi}_x\xspace' \xleadsto{\textcolor{RoyalBlue}{\mathtt{commit}}_x\ \mathit{ctr}}_x^{{\mathcal{O}}_x} \overline{\Psi}_x\xspace \cdot \langle p, \mathit{ctr}', \sigma', h', n, \cdots \rangle \cdot \overline{\Psi}_x\xspace' }\end{array}}
\noindent\hrulefill\ \raisebox{-0.5ex}{\fbox{{\Psi_x \xleadsto{\tau}_x^{{\mathcal{O}}_x} \overline{\Psi}x\xspace'}}} \hrulefill\hrulefill\hrulefill
\def\thetyperule{O-NoSpec}\refstepcounter{typerule}\label{tr:o-noSpec}{\begin{array}c\textsf(O-NoSpec)
\inference{ p(\sigma(\mathbf{pc})) \notin \mathit{instr}
{\mathghost} \cup {\mathbf{spbarr} } & \langle p,\sigma \rangle \xrightarrow{\tau} \langle p,\sigma' \rangle }{\langle p, \mathit{ctr}, \sigma, h, n + 1, \cdots \rangle \xleadsto{\tau}_x^{{\mathcal{O}}_x} \langle p, \mathit{ctr}, \sigma', h, n, \cdots \rangle }\end{array}}
\def\thetyperule{O-barr}\refstepcounter{typerule}\label{tr:o-barr}{\begin{array}c\textsf(O-barr)
\inference{p(\sigma(\mathbf{pc})) = \mathbf{spbarr} & \sigma \xrightarrow{\tau} \sigma' }{\langle p, \mathit{ctr}, \sigma, h, n, \cdots \rangle \xleadsto{\tau}_x^{{\mathcal{O}}x} \langle p, \mathit{ctr}, \sigma', h, 0, \cdots \rangle }\end{array}}
\def\thetyperule{O-Spec}\refstepcounter{typerule}\label{tr:o-spec}{\begin{array}c\textsf(O-Spec)
\inference{ p(\sigma(\mathbf{pc})) \in \mathit{instr}
{\mathghost} & {\mathcal{O}}(p,n,h, \sigma) = \langle \delta, w, \tau \rangle
h' = h \cdot \langle \sigma(\mathbf{pc}), n+1, \delta \rangle & \overline{\tau}\xspace = \textcolor{RoyalBlue}{\mathtt{start}}_x\ \mathit{ctr} \cdot \tau }{\langle p, \mathit{ctr}, \sigma, h, n + 1, \cdots \rangle \xleadsto{\overline{\tau}\xspace}_x^{{\mathcal{O}}_x} \langle p, \mathit{ctr}, \sigma, h, n+1, \cdots \rangle \cdot \langle p, \mathit{ctr} + 1, \sigma \uplus \delta, h', w, \cdots \rangle^{\langle \sigma,\delta \rangle} }\end{array}}
\caption{Evaluation rules for the speculative oracle semantics \xleadstoxOx\xleadsto{}_{x}^{{\mathcal{O}}_{x}}\xleadstoxOx​​ given an oracle Ox{\mathcal{O}}_xOx​}\label{fig:oracle-semantics:general} \end{figure}
Next, we describe in detail the rules formalizing the oracle semantics, which capture the intuition from Section 4.1 and are depicted in Figure 5. Whenever none of the speculative instances in the current state has a speculative window of $0$ or is stuck (denoted by $\mathit{canStep}(\overline{\Psi}_{x})$), the computation proceeds by doing one step for the instance at the top of the stack (the section) and by updating the speculative window of the other instances. In particular, if the instruction to be executed in the topmost instance is a speculative barrier, then all speculative windows are set to 0 ($\overline{\Psi}_{x}'' = \mathit{zeroes}(\overline{\Psi}_{x})$), otherwise all windows are decremented by $1$ ($\overline{\Psi}_{x}'' = \mathit{decr}(\overline{\Psi}_{x})$). In the topmost speculative instance, instructions that do not trigger speculation (i.e., they are not in $\mathit{instr}_{\mathsf{ghost}}$) are executed following the non-speculative semantics while also decrementing the current speculative window by 1 (the section). Speculation barriers are handled similarly except for setting the speculative window in the topmost instance to $0$ (the section). Finally, the section handles instructions that trigger speculation (i.e., those that belong to $\mathit{instr}_{\mathsf{ghost}}$). In this case, the oracle is queried to obtain the prediction $\delta$ and the next speculative window $w$, and a new speculative instance (starting from the predicted state $\sigma \uplus \delta$ and with an updated prediction history $h'$) is pushed on top of the stack to start the new speculative transaction. This fresh speculative instance is decorated with the original program state $\sigma$ and with the predicted values $\delta$, which will later on be used to determine whether the transaction should be committed or rolled back. The rule also appends the observation $\textcolor{RoyalBlue}{\mathtt{start}}_{x}\ n$ to the trace to record the beginning of a speculative transaction. A speculative transaction must be finalized (committed or rolled back) whenever its speculation window reaches $0$ or the execution cannot proceed further. We refer to the latter case as the instance being 'stuck', formally indicated by the judgment $p, \sigma' \vdash \text{fin}$. This judgment holds whenever the current instruction is undefined, i.e., $p(sigma(\mathbf{pc})) = \bot$ (see). To determine whether to commit or rollback, the semantics inspects the snapshot state $\sigma$ and prediction $\delta$ that decorate the instance $\Psi_{x}^{\langle \sigma,\delta \rangle}$ whose window has reached $0$. - If the prediction was *correct* (i.e., doing one step from $\sigma$ results indeed in the predicted state $\sigma \uplus \delta$), the transaction is committed and the computation continues using the current configuration (the section). - If the prediction was *incorrect* (i.e., doing one step from $\sigma$ produces a state different from the predicted state $\sigma \uplus \delta$), the transaction is aborted and the computation continues on the correct branch (the section). Thus, committing and rolling back speculative transactions happen along the stack of states. Rolling back deletes all the instances above the rolled back instance, whereas committing updates the configuration, the counter, the prediction history $h$ and additional data tracked by the semantics of the instance below and the committed instance is deleted. the section and also record the end of speculative transactions on the trace with the $\textcolor{RoyalBlue}{\mathtt{commit}}_{x}\ n$ and $\textcolor{RoyalBlue}{\mathtt{rlb}}_{x}\ n$ observations respectively. Analogously to the non-speculative case, the behaviour $\mathit{Beh}^{{\mathcal{O}}}_{x}(p)$ of a program $p$ under the oracle semantics is the set of all traces generated from an initial state until termination. **Non-Speculative Consistency** Fundamentally, a valid speculative semantics must preserve the program's architectural behaviour. Speculation should only introduce observational side-effects during transient execution, without altering the program's non-speculative behaviour. We formalize this correctness requirement in Property 4, stating that the standard non-speculative behaviour can be exactly recovered from the oracle behaviour by applying the non-speculative projection $\mathord{\upharpoonright_{ns}}$, which (1) removes from the trace $\tau$ any sub-trace enclosed between $\textcolor{RoyalBlue}{\mathtt{start}}_{x}\ n$ and $\textcolor{RoyalBlue}{\mathtt{rlb}}_{x}\ n$ for some $n$, and then (2) drops all remaining $\textcolor{RoyalBlue}{\mathtt{start}}_{x}\ n$ and $\textcolor{RoyalBlue}{\mathtt{commit}}_{x}\ n$ observations. In Section 6, we prove that all our specualtive semantics instances satisfy Property 4.

Property 4: NS Consistency Oracle

BehNS(p)=BehxO(p)↾ns\mathit{Beh}_{NS}(p) = \mathit{Beh}^{{\mathcal{O}}}_{x}(p)\mathord{\upharpoonright_{ns}}BehNS​(p)=BehxO​(p)↾ns​

5. Speculative non-interference

In this section, we introduce speculative non-interference (SNI, Section 5.1), a semantic notion characterizing the leaks introduced by speculatively-executed instructions. Next, we introduce the notion of always-mispredict speculative semantics (Section 5.2), that is, a speculative semantics that facilitates reasoning about leaks w.r.t. any prediction oracle.

5.1 Speculative Non-Interference

Speculative non-interference (SNI) is a semantic notion of security characterizing those information leaks that are introduced by speculative execution. Intuitively, SNI requires that programs do not leak more information under the speculative semantics than what is leaked under the non-speculative semantics.
SNI is parametric in a policy ϕ\phiϕ and in the speculative semantics xxx, which models how the program executes. The policy ϕ\phiϕ describes which parts of the program are public/low information, i.e., those that are known by an adversary. Formally, a security policy PPP is a finite subset of Regs∪N\mathit{Regs} \cup \mathbb{N}Regs∪N specifying the low register identifiers and memory addresses. Two configurations σ,σ′\sigma, \sigma'σ,σ′ are called low-equivalent for a policy ϕ\phiϕ, written σ∽ϕσ′\sigma \backsim_{\phi} \sigma'σ∽ϕ​σ′, if they agree on all register and memory locations in ϕ\phiϕ.

Example 5: Example Policy for Example 1

A policy PPP for the program from Example 1 may state that the content of the registers y\mathtt{y}y, size\mathtt{size}size, A\mathtt{A}A, and B\mathtt{B}B is non-sensitive, i.e., P={y,size,A,B}P = \{\mathtt{y}, \mathtt{size},\mathtt{A}, \mathtt{B}\}P={y,size,A,B}.
Policies need not be manually specified but can in principle be inferred from the context in which a piece of code executes, e.g., whether a variable is reachable from public input or not.
A program ppp satisfies SNI (Definition 6) for a speculative semantics xxx if \ul{any pair of low-equivalent initial configurations σ\sigmaσ and σ′\sigma'σ′} that \ul{generate the same observations under the non-speculative semantics} also \ul{generate the same observations under the speculative semantics to}.

Definition 6: Speculative Non-Interference

Program ppp satisfies SNI (denoted p⊢xSNIp \vdash_{x} \text{SNI}p⊢x​SNI) for a speculative semantics xxx if for all σ\sigmaσ, σ′\sigma'σ′, if \ul{σ∽ϕσ′\sigma \backsim_{\phi} \sigma'σ∽ϕ​σ′} and \ul{BehNS(p,σ)=BehNS(p,σ′)\mathit{Beh}_{NS}(p, \sigma)= \mathit{Beh}_{NS}(p, \sigma')BehNS​(p,σ)=BehNS​(p,σ′)} then \expandafter\ul{Behxω(p,σ)=Behxω(p,σ′)\mathit{Beh}^{\omega}_x(p, \sigma) = \mathit{Beh}^{\omega}_x(p, \sigma')Behxω​(p,σ)=Behxω​(p,σ′)}.
Speculative non-interference is a variant of non-interference. While non-interference compares what is leaked by a program with a policy specifying the allowed leaks, speculative non-interference compares the program leakage under two semantics, the non-speculative and the speculative one. The security policy and the non-speculative semantics, together, specify what the program may leak under the speculative semantics.1
1.
Conceptually, the non-speculative semantics induces declassification assertions for the speculative semantics [44].

Example: SNI for Example 1

The program ppp from Example 1 does not satisfy speculative non-interference for the BTFNT oracle from Example 2 and the policy PPP from Example 5. Consider two initial configurations σ:=⟨m,a⟩,σ′:=⟨m′,a′⟩\sigma:= \langle m,a \rangle, \sigma':=\langle m',a' \rangleσ:=⟨m,a⟩,σ′:=⟨m′,a′⟩ that agree on the values of y\mathtt{y}y, size\mathtt{size}size, A\mathtt{A}A, and B\mathtt{B}B but disagree on the value of B[A[y]∗512]\mathtt{B}[\mathtt{A}[\mathtt{y}] * 512]B[A[y]∗512]. Say, for instance, that m(a(A)+a(y))=0m(a(\mathtt{A}) + a(\mathtt{y})) = 0m(a(A)+a(y))=0 and m′(a′(A)+a′(y))=1m'(a'(\mathtt{A}) + a'(\mathtt{y})) = 1m′(a′(A)+a′(y))=1. Additionally, assume that y≥size\mathtt{y} \geq \mathtt{size}y≥size.
Executing the program under the non-speculative semantics produces the trace pc ⊥\textcolor{RoyalBlue}{\mathtt{pc}}\ \botpc ⊥ when starting from σ\sigmaσ and σ′\sigma'σ′. Moreover, the two initial configurations are indistinguishable with respect to the policy PPP. However, executing ppp under the speculative semantics produces two distinct traces:
τ= start 0⋅pc 3⋅load v1⋅load (a′(B)+0)⋅rlb 0⋅pc ⊥τ′= start 0⋅pc 3⋅load v1⋅load (a′(B)+1)⋅rlb 0⋅pc ⊥\begin{aligned} \tau =&\ \textcolor{RoyalBlue}{\mathtt{start}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 3 \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ v_1 \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ (a'(\mathtt{B})+0) \cdot \textcolor{RoyalBlue}{\mathtt{rlb}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ \bot \\ \tau' =&\ \textcolor{RoyalBlue}{\mathtt{start}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 3 \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ v_1 \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ (a'(\mathtt{B})+1) \cdot \textcolor{RoyalBlue}{\mathtt{rlb}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ \bot \end{aligned}
where v1=a(A)+a(y)=a′(A)+a′(y)v_1 = a(\mathtt{A}) + a(\mathtt{y}) = a'(\mathtt{A}) + a'(\mathtt{y})v1​=a(A)+a(y)=a′(A)+a′(y). Therefore, ppp does not satisfy speculative non-interference.

5.2 Always-Mispredict (AM) Semantics

The oracle speculative semantics from Section 4.3 and, as a result, SNI are parametric in the prediction oracle O{\mathcal{O}}O. Often, however, it is desirable to obtain security guarantees w.r.t any prediction oracle, since the details about speculation mechanisms might differ between different CPUs or may even be unknown. To this end, we introduce a variant of the speculative semantics, which we call the always-mispredict speculative semantics, that facilitates reasoning about leaks w.r.t. any prediction oracle. We formally define the AM semantics as a speculative template rather than a concrete mechanism. This template abstracts the core logic of exploring mispredicted paths and serves as a unified foundation for the specific instantiations defined in Section 6.
For simplicity, consider the case of branch prediction. In this case, leakage due to speculative execution is maximized under a predictor that mispredicts every time. This intuition holds true unless speculative transactions are nested, where a correct prediction of a nested branch sometimes yields more leakage than a misprediction.

Example 7

Consider the following variation of the SPECTRE{\mathchoice{\text{S{\scriptsize PECTRE}}}{\text{S{\scriptsize PECTRE}}}{\text{S{\scriptscriptstyle PECTRE}}}{\text{SPECTRE}}}SPECTRE- PHT{\mathchoice{\text{P{\scriptsize HT}}}{\text{P{\scriptsize HT}}}{\text{P{\scriptscriptstyle HT}}}{\text{PHT}}}PHT example [1] from Figure, and assume that the function benign() runs for longer than the speculative window and does not leak any information.
Then, under a branch predictor that mispredicts every branch, the speculative transaction corresponding to the outer branch will be rolled back before reaching line 4. On the other hand, given a correct prediction of the inner branch, line 4 would be reached and a speculative leak would be present.
A simple but inefficient approach to deal with this challenge would be to consider both cases, correct and incorrect predictions, upon every branch. This, however, would result in an exponential explosion of the number of paths to consider. Furthermore, it would not be applicable to speculation mechanisms where there might be more than one incorrect prediction, e.g., indirect branch speculation or value speculation.
Intuition To address these issues, we introduce the always-mispredict speculative semantics that differs from the oracle speculative semantics in three key ways: (1)
  • It mispredicts every time, hence its name. For every instruction that might trigger speculation (i.e., the instruction belongs to instrghost\mathit{instr}_{\mathsf{ghost}}instrghost​), the always-mispredict semantics first speculatively explores all possible wrong paths for a bounded number of steps and then continues with the correct one. Thus, the semantics is not parametric in the prediction oracle.
  • It initializes the length of every non-nested transaction to www, and the length of every nested transaction to the remaining length of its enclosing transaction, decremented by 111.
  • Upon executing instructions, only the remaining length of the innermost transaction is decremented.
The consequence of these modifications is that nested transactions do not reduce the number of steps that the semantics may explore the correct path for, after the nested transactions have been rolled back. In Example 7, after rolling back the nested speculative transaction, the outer transaction continues as if the nested branch had been correctly predicted in the first place, and thus the speculative leak in line 4 is reached.
\begin{figure} <center> \noindent\hrulefill\ \raisebox{-0.5ex}{\fbox{{\overline{\Phi}_x\xspace \xrightswishingghost{\mathit{\tau}}\mathrel{\vphantom{\to}}_x \overline{\Phi}_x\xspace'}}} \hrulefill\hrulefill\hrulefill <br> \def\thetyperule{AM-NoSpec}\refstepcounter{typerule}\label{tr:am-noBranch}{\begin{array}c\textsf(AM-NoSpec) <br> \inference{ p(\sigma(\mathbf{pc})) \notin \mathit{instr}_{\mathghost} \cup \{\mathbf{spbarr} \} & \langle p,\sigma \rangle \xrightarrow{\tau} \langle p,\sigma' \rangle }{ \overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, n + 1, \cdots \rangle \xrightswishingghost{\mathit{\tau}}\mathrel{\vphantom{\to}}_x \overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma', n, \cdots \rangle }\end{array}} <br> \def\thetyperule{AM-barr}\refstepcounter{typerule}\label{tr:am-barr}{\begin{array}c\textsf(AM-barr) <br> \inference{p(\sigma(\mathbf{pc})) = \mathbf{spbarr} & \sigma \xrightarrow{\tau} \sigma' }{\overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, n, \cdots \rangle \xrightswishingghost{\mathit{\tau}}\mathrel{\vphantom{\to}}_x \overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma', 0, \cdots \rangle }\end{array}} <br> \def\thetyperule{AM-Spec}\refstepcounter{typerule}\label{tr:am-spec}{\begin{array}c\textsf(AM-Spec) <br> \inference{p(\sigma(\mathbf{pc})) = \mathit{instr}_{\mathghost} & \langle p, \sigma \rangle \xrightarrow{\tau} \langle p, \sigma' \rangle & j = min(\omega, n) <br> \overline{\tau}\xspace = \tau \cdot \textcolor{RoyalBlue}{\mathtt{start}}_x\ \mathit{ctr} \cdot \cdots }{\overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, n + 1 \rangle \xrightswishingghost{\mathit{\overline{\tau}\xspace}}\mathrel{\vphantom{\to}}_x \overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma', n \rangle \cdot \Phi_x' }\end{array}} <br> \def\thetyperule{AM-Rollback}\refstepcounter{typerule}\label{tr:am-rollback}{\begin{array}c\textsf(AM-Rollback) <br> \inference{ \Phi_x' . n = 0\ \text{or}\ p, \Phi_x'. \sigma \vdash \text{fin} }{ \overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, n \rangle \cdot \Phi_x' \xrightswishingghost{\mathit{\textcolor{RoyalBlue}{\mathtt{rlb}}_x\ \mathit{ctr}}}\mathrel{\vphantom{\to}}_x \overline{\Phi}_x\xspace \cdot \langle p, \Phi_x' . \mathit{ctr}', \sigma, n \rangle }\end{array}} </center> \caption{Always-mispredict speculative semantics}\label{fig:am-rules} \end{figure}
\noindent\hrulefill\ \raisebox{-0.5ex}{\fbox{{\overline{\Phi}_x\xspace \xrightswishingghost{\mathit{\tau}}\mathrel{\vphantom{\to}}_x \overline{\Phi}x\xspace'}}} \hrulefill\hrulefill\hrulefill
\def\thetyperule{AM-NoSpec}\refstepcounter{typerule}\label{tr:am-noBranch}{\begin{array}c\textsf(AM-NoSpec)
\inference{ p(\sigma(\mathbf{pc})) \notin \mathit{instr}
{\mathghost} \cup {\mathbf{spbarr} } & \langle p,\sigma \rangle \xrightarrow{\tau} \langle p,\sigma' \rangle }{ \overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, n + 1, \cdots \rangle \xrightswishingghost{\mathit{\tau}}\mathrel{\vphantom{\to}}_x \overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma', n, \cdots \rangle }\end{array}}
\def\thetyperule{AM-barr}\refstepcounter{typerule}\label{tr:am-barr}{\begin{array}c\textsf(AM-barr)
\inference{p(\sigma(\mathbf{pc})) = \mathbf{spbarr} & \sigma \xrightarrow{\tau} \sigma' }{\overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, n, \cdots \rangle \xrightswishingghost{\mathit{\tau}}\mathrel{\vphantom{\to}}_x \overline{\Phi}x\xspace \cdot \langle p, \mathit{ctr}, \sigma', 0, \cdots \rangle }\end{array}}
\def\thetyperule{AM-Spec}\refstepcounter{typerule}\label{tr:am-spec}{\begin{array}c\textsf(AM-Spec)
\inference{p(\sigma(\mathbf{pc})) = \mathit{instr}
{\mathghost} & \langle p, \sigma \rangle \xrightarrow{\tau} \langle p, \sigma' \rangle & j = min(\omega, n)
\overline{\tau}\xspace = \tau \cdot \textcolor{RoyalBlue}{\mathtt{start}}_x\ \mathit{ctr} \cdot \cdots }{\overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, n + 1 \rangle \xrightswishingghost{\mathit{\overline{\tau}\xspace}}\mathrel{\vphantom{\to}}_x \overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma', n \rangle \cdot \Phi_x' }\end{array}}
\def\thetyperule{AM-Rollback}\refstepcounter{typerule}\label{tr:am-rollback}{\begin{array}c\textsf(AM-Rollback)
\inference{ \Phi_x' . n = 0\ \text{or}\ p, \Phi_x'. \sigma \vdash \text{fin} }{ \overline{\Phi}_x\xspace \cdot \langle p, \mathit{ctr}, \sigma, n \rangle \cdot \Phi_x' \xrightswishingghost{\mathit{\textcolor{RoyalBlue}{\mathtt{rlb}}_x\ \mathit{ctr}}}\mathrel{\vphantom{\to}}_x \overline{\Phi}_x\xspace \cdot \langle p, \Phi_x' . \mathit{ctr}', \sigma, n \rangle }\end{array}}
\caption{Always-mispredict speculative semantics}\label{fig:am-rules}
\end{figure}
**Formalization** The state $\Sigma_{x}$ of the AM semantics is a stack of speculative instances $\Phi_{x}$. As shown in all rules in Figure 6, reductions in the always-mispredict semantics happen only on top of the stack. Each instance $\Phi_{x}$ contains the program $p$, a counter $\mathit{ctr}$ that identifies the speculative transaction , a configuration $\sigma$, and the remaining speculation window $n$ describing the number of instructions that can still be executed speculatively (or $\bot$ when no speculation is happening). Depending on the specific speculation that is modelled, additional data is tracked (indicated with $\cdots$ in the rules). Throughout the paper, we fix the maximal speculation window, i.e., the maximum number of speculative instructions, to a global constant $\omega$.
Spec. States Σx::= Φ‾xSpec. Instances Φx::= ⟨p,ctr,σ,n,⋯ ⟩\begin{aligned} \textit{Spec. States } \Sigma_{x} \mathrel{::=}&\ \overline{\Phi}_{x} & \textit{Spec. Instances } \Phi_{x} \mathrel{::=}&\ \langle p, \mathit{ctr}, \sigma, n, \cdots \rangle \end{aligned}
Modifications (1)–(3) are captured in the four rules given in Figure 6. The judgement for the AM semantics is: Σx→τxΣx′\Sigma_{x} \xrightarrow{\mathit{\tau}}_{x} \Sigma_{x}'Σx​τ​x​Σx′​. If the instruction is not related to speculation and it is not a speculation barrier, then the speculative instance on the top of the stack is updated according to the non-speculative semantics →\xrightarrow{}​ (the section). In contrast, whenever the current instruction is a speculation barrier spbarr\mathbf{spbarr}spbarr, the remaining speculation window of the topmost instance is set to 000.
Whenever speculation starts, one or more speculative instances are pushed on top of the stack (the section) and when speculation ends, the speculative instance is then popped (the section). Finally, we note that how exactly the new speculative instances are created w.r.t. the auxiliary data depends on the specific speculative semantics, as we show in Section 6. This is reflected in not specifying how the new speculative instances Φ‾x′\overline{\Phi}_{x}'Φx′​ are defined.
The always-mispredict behaviour Behxω(p)\mathit{Beh}^{\omega}_x(p)Behxω​(p) of a program ppp is the set of all traces generated from an initial state until termination using the reflexive-transitive closure of →x\xrightarrow{\mathit{}}_{x}​x​. Crucially, it is possible to connect the AM semantics and the non-speculative semantics through the non-speculative projection ↾ns\mathord{\upharpoonright_{ns}}↾ns​, which removes from a trace τ‾\overline{\tau}τ all events related to speculation. We lift the projection ↾ns\mathord{\upharpoonright_{ns}}↾ns​ to the behaviour of a program ppp in the natural way.
We require that any instantiation of this template (e.g., for branches or stores) preserves the non-speculative behaviour of the program (Similar to the Oracle Semantics in Section 4.3). We formalize this as a correctness requirement that all our instances must satisfy:

Property 8: NS Consistency AM

BehNS(p)=Behxω(p)↾ns\mathit{Beh}_{NS}(p) = \mathit{Beh}^{\omega}_x(p)\mathord{\upharpoonright_{ns}}BehNS​(p)=Behxω​(p)↾ns​
The goal of the AM semantics is to derive security guarantees that are independent of the choice of a prediction oracle. Property 9 formalizes this intuition by precisely connecting the oracle and the AM semantics of any speculative semantics ghostx\mathsf{ghost}_{x}ghostx​. In particular, Property 9 states that checking SNI w.r.t. the AM semantics is sufficient to obtain security guarantees w.r.t. all prediction oracles. That is, if a program is SNI w.r.t. the always-mispredict semantics, then it is SNI irrespectively of the choice of prediction oracle. Similarly, if a program violates SNI w.r.t. the always-mispredict semantics, then there is one prediction oracle for which SNI is violated. As we show in Section 6, this holds for all instances studied in this paper.

Property 9: Oracle Overapproximation

p⊢xSNI iff ∀O.p⊢xOSNIp \vdash_{x} \text{SNI} ~\text{iff}~ \forall {\mathcal{O}}\ldotp p \vdash_{x}^{{\mathcal{O}}} \text{SNI}p⊢x​SNI iff ∀O.p⊢xO​SNI

6. Instances of Speculative Semantics

Here we present specific instances of speculative semantics modelling the effect of speculative execution over branch instructions (Section 6.1), store\mathbf{store}store instructions (Section 6.2), ret\mathbf{ret}ret instructions (Section 6.3, Section 6.4) and indirect jump instructions (Section 6.5) using the semantics templates presented in Section 4.
Before detailing these specific instances, we must establish the properties that well-formed semantics must satisfy in our framework. We summarise these properties in a single definition:

Definition 10: Well-Formed Speculative Semantics

A speculative semantics ghostx\mathsf{ghost}_{x}ghostx​ is safe (denoted {\vdash{ ghostx\mathsf{ghost}_{x}ghostx​} WFSS\mathit{WFSS}WFSS}) if:
  • Oracle Overapproximation: p⊢xSNI iff ∀O.p⊢xOSNIp \vdash_{x} \text{SNI} ~\text{iff}~ \forall {\mathcal{O}}\ldotp p \vdash_{x}^{{\mathcal{O}}} \text{SNI}p⊢x​SNI iff ∀O.p⊢xO​SNI
  • NS Consistency: Behxω(p)↾ns=BehNS(p)=BehxO(p)↾ns\mathit{Beh}^{\omega}_x(p)\mathord{\upharpoonright_{ns}} = \mathit{Beh}_{NS}(p) = \mathit{Beh}^{{\mathcal{O}}}_{x}(p)\mathord{\upharpoonright_{ns}}Behxω​(p)↾ns​=BehNS​(p)=BehxO​(p)↾ns​
  • Symbolic Consistency: Behxω(p)=μ⁡(BehxS(p))\mathit{Beh}^{\omega}_x(p) = \operatorname{\mu}(\mathit{Beh}^{\mathcal{S}}_{x}(p))Behxω​(p)=μ(BehxS​(p))
Intuitively, a well-formed speculative semantics is made of three components: an AM semantics, an oracle semantics, and a symbolic AM semantics.
First, the AM semantics must overapproximate the oracle semantics (for any oracle), guaranteeing that it is sufficient to check a program ppp for SNI w.r.t. the AM semantics. Next, both the AM and the Oracle semantics must preserve the non-speculative behaviour of a program ppp. Applying the non-speculative projection (↾ns\mathord{\upharpoonright_{ns}}↾ns​) to their traces exactly recovers the standard non-speculative behaviour. Thus, we can execute ppp only once to get the (non-)speculative behaviour of that program run.
Finally, to enable automated verification, we require the Symbolic AM semantics. The Symbolic Consistency property mandates that the concrete AM traces exactly match the concretization of the symbolic traces, where μ⁡(BehxS(p))\operatorname{\mu}(\mathit{Beh}^{\mathcal{S}}_{x}(p))μ(BehxS​(p)) conceptually denotes the instantiation of the symbolic traces using concrete models μ⁡\operatorname{\mu}μ that satisfy the collected path conditions.
For conciseness' sake, here we only present the concrete AM semantics in full detail and refer to the technical report for the full details of the oracle/symbolic semantics [37], and defer the detailed discussion of how the symbolic semantics is utilized in practice to the implementation of SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR in Section 9. For each of the speculative semantics, we prove that they satisfy all validity requirements, that is, that they are well-formed speculative semantics according to Definition 10.

6.1 Spec-B: Speculation on Branch Instructions

Modern hardware uses a branch predictor to predict the outcome of branching decisions since this speeds up program execution. However, mispredictions can be steered and exploited by attackers leading to SPECTRE-PHT{\mathchoice{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptscriptstyle PECTRE}-P{\scriptscriptstyle HT}}}{\text{SPECTRE-PHT}}}SPECTRE-PHT attacks [1].

6.1.1 The AM Semantics

At every branch instruction, the always-mispredict semantics first speculatively executes the wrong branch for a fixed number of steps and then continues with the correct one. As a result, this semantics is deterministic and agnostic to implementation details of the branch predictor.
The state ΣB\Sigma_{\mathbf{\textcolor{CarnationPink}{B}}}ΣB​ of the AM semantics is a stack of speculative instances ΦB\Phi_{\mathbf{\textcolor{CarnationPink}{B}}}ΦB​ where reductions happen only on top of the stack. Each instance ΦB\Phi_{\mathbf{\textcolor{CarnationPink}{B}}}ΦB​ contains the program ppp, a counter ctr\mathit{ctr}ctr that uniquely identifies the speculation instance, a configuration σ\sigmaσ, and the remaining speculation window nnn describing the number of instructions that can still be executed speculatively (or ⊥\bot⊥ when no speculation is happening). In this semantics, we have instrghost=beqz\mathit{instr}_{\mathsf{ghost}} = \mathbf{beqz}instrghost​=beqz since branches are the source of speculation.
Spec. States ΣB::= Φ‾BSpec. Instances ΦB::= ⟨p,ctr,σ,n⟩\begin{aligned} \textit{Spec. States } \Sigma_{\mathbf{\textcolor{CarnationPink}{B}}} \mathrel{::=}&\ \overline{\Phi}_{\mathbf{\textcolor{CarnationPink}{B}}} & \textit{Spec. Instances } \Phi_{\mathbf{\textcolor{CarnationPink}{B}}} \mathrel{::=}&\ \langle p, \mathit{ctr}, \sigma, n \rangle \end{aligned}
The judgement for the AM semantics is: ΣB→τBΣB′\Sigma_{\mathbf{\textcolor{CarnationPink}{B}}} \xrightarrow{\mathit{\tau}}_{\mathbf{\textcolor{CarnationPink}{B}}} \Sigma_{\mathbf{\textcolor{CarnationPink}{B}}}'ΣB​τ​B​ΣB′​.
\mytoprule{\phiStackB \specarrowB{\tau} \phiStackB'}
rule\text{rule}
rule\text{rule}
rule\text{rule}
rule\text{rule}
As mentioned, Section 6.1.1 pushes a new speculative state with the wrong branch, followed by the state with the correct one. When speculation ends, Section 6.1.1 pops the related state. All other instructions are handled by delegating back to the non-speculative semantics (Section 6.1.1).
Section 6.1.1 differs slightly from what was presented before in Section 5.2: it applies to instructions that are not branch or barrier instructions and are not in the metaparameter ZBZ_{\mathbf{\textcolor{CarnationPink}{B}}}ZB​ (in gray). The latter is a set of instructions and is part of our composition framework (which we explain in Section 7.1). Instantiating ZBZ_{\mathbf{\textcolor{CarnationPink}{B}}}ZB​ allows us to restrict when to apply non-speculative steps in composed semantics. When we consider ghostB{\mathsf{ghost}_{\mathbf{\textcolor{CarnationPink}{B}}}}ghostB​ in isolation, ZBZ_{\mathbf{\textcolor{CarnationPink}{B}}}ZB​ is the empty set (so, Section 6.1.1 applies to everything except branch and barrier instructions). However, we will instantiate ZBZ_{\mathbf{\textcolor{CarnationPink}{B}}}ZB​ in different manners when building the composed semantics. In the following, we write ghostBZB{\mathsf{ghost}_{\mathbf{\textcolor{CarnationPink}{B}}}}^{Z_{\mathbf{\textcolor{CarnationPink}{B}}}}ghostB​ZB​ to stress the value of ZBZ_{\mathbf{\textcolor{CarnationPink}{B}}}ZB​ when needed but we often omit ZBZ_{\mathbf{\textcolor{CarnationPink}{B}}}ZB​ for simplicity.
The always-mispredict behaviour BehBω(p)\mathit{Beh}^{\omega}_{\mathbf{\textcolor{CarnationPink}{B}}}(p)BehBω​(p) of a program ppp is the set of all traces generated from an initial state until termination using the reflexive-transitive closure of →B\xrightarrow{\mathit{}}_{\mathbf{\textcolor{CarnationPink}{B}}}​B​.
Note that Section 6.1.1, Section 6.1.1 and Section 6.1.1 are direct instantiations of the general rules described in Section 5.2. This holds true for all the other speculative semantics that we will present, thus, we omit them.

6.1.2 Oracle Semantics

At every branch instruction, the oracle semantics queries the explicit oracle OB{\mathcal{O}}_{\mathbf{\textcolor{CarnationPink}{B}}}OB​ for the branching decision.
Here, we summarize the key differences with the AM semantics. First, speculative instances are extended to track the branching history hhh, which records the outcomes of prior branch instructions. Second, when executing a beqz\mathbf{beqz}beqz instruction, the oracle predicts the branch outcome (based on the branching history hhh) and a new speculative instance is pushed on top of the stack (Section 6.1.2). Finally, whenever the speculation window of an instance anywhere on the stack reaches 000, the execution needs to be rolled back or committed.
\mytoprule{\PsiB \SEspecarrowB{\tau} \PsiB'}
rule\text{rule}
rule\text{rule}
As in the oracle-semantics template, rolling back deletes all the instances above the rolled back instance, whereas committing updates the configuration, the counter and the branching history hhh of the instance below and the committed instance is deleted. These rules are not shown since they are direct instantiations of the general oracle rules presented in Section 4.3.

6.2 Spec-S: Speculation on Store Instructions

Modern processors write store\mathbf{store}stores to main memory asynchronously to reduce delays caused by the memory subsystem. Processors employ a Store Queue where not-yet-committed store\mathbf{store}store instructions are stored before being permanently written to memory. When executing a load\mathbf{load}load instruction, the processor first inspects the store queue for a matching memory address. If there is a match, the value is retrieved from the store queue (called store-to-load forwarding), and otherwise, the memory request is issued to the memory subsystem. To speed up computation, processors employ memory disambiguation predictors to predict if the memory addresses of loads and stores match. Since the prediction can be incorrect, processors may speculatively bypass a store\mathbf{store}store instruction in the store queue, leading to a load\mathbf{load}load instruction retrieving a stale value [10].

Example: Spectre-STL

Consider the code in, which is the μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM translation of:
% Assume that the store\mathbf{store}store instructions in the theorem and the theorem are still in the store queue and not yet committed to main memory.
A misprediction of the memory disambiguator for the load\mathbf{load}load instruction in the theorem causes it to bypass the store\mathbf{store}store instruction in the theorem and retrieve the value from the stale store\mathbf{store}store instruction in the theorem. The speculative access of the memory is then leaked into the microarchitectural state by the array access into B in the theorem.
Here, we present the speculative AM semantics (Section 6.2.1) and the corresponding oracle semantics (Section 6.2.2).

6.2.1 Speculative Semantics

The overall structure of the ghostS{\mathsf{ghost}_{\texttt{\textcolor{Emerald}{S}}}}ghostS​ semantics is similar to that of ghostB{\mathsf{ghost}_{\mathbf{\textcolor{CarnationPink}{B}}}}ghostB​: speculative execution is modelled using a stack of speculative states, instructions that do not start speculative transactions are executed by delegating back to the non-speculative semantics, and speculative transactions are rolled back whenever the speculative window reaches 0. The key difference between ghostS{\mathsf{ghost}_{\texttt{\textcolor{Emerald}{S}}}}ghostS​ and ghostB{\mathsf{ghost}_{\mathbf{\textcolor{CarnationPink}{B}}}}ghostB​ is the differing source of speculation instrghost\mathit{instr}_{\mathsf{ghost}}instrghost​. Here instrghost=store\mathit{instr}_{\mathsf{ghost}} = \mathbf{store}instrghost​=store for ghostS{\mathsf{ghost}_{\texttt{\textcolor{Emerald}{S}}}}ghostS​ instead of instrghost=beqz\mathit{instr}_{\mathsf{ghost}} = \mathbf{beqz}instrghost​=beqz as in ghostB{\mathsf{ghost}_{\mathbf{\textcolor{CarnationPink}{B}}}}ghostB​.
The states used in ghostS{\mathsf{ghost}_{\texttt{\textcolor{Emerald}{S}}}}ghostS​ are similar to those of ghostB{\mathsf{ghost}_{\mathbf{\textcolor{CarnationPink}{B}}}}ghostB​:
Spec. States ΣS::= Φ‾SSpec. Instance ΦS::= ⟨p,ctr,σ,n⟩\begin{aligned} \textit{Spec. States } \Sigma_{\texttt{\textcolor{Emerald}{S}}} \mathrel{::=}&\ \overline{\Phi}_{\texttt{\textcolor{Emerald}{S}}} & \textit{Spec. Instance } \Phi_{\texttt{\textcolor{Emerald}{S}}} \mathrel{::=}&\ \langle p, \mathit{ctr}, \sigma, n \rangle \end{aligned}
We also add a bypass n\textcolor{RoyalBlue}{\mathtt{bypass}}\ nbypass n observation denoting that the store\mathbf{store}store instruction at program counter nnn was speculatively bypassed.
ObsS::= Obs∣bypass n\begin{aligned} \mathit{Obs}_{\texttt{\textcolor{Emerald}{S}}} \mathrel{::=}&\ \mathit{Obs} \mid \textcolor{RoyalBlue}{\mathtt{bypass}}\ n \end{aligned}
The judgement ΣS→τSΣS′\Sigma_{\texttt{\textcolor{Emerald}{S}}} \xrightarrow{\mathit{\tau}}_{\texttt{\textcolor{Emerald}{S}}} \Sigma_{\texttt{\textcolor{Emerald}{S}}}'ΣS​τ​S​ΣS′​ describes how ΣS\Sigma_{\texttt{\textcolor{Emerald}{S}}}ΣS​ steps to ΣS′\Sigma_{\texttt{\textcolor{Emerald}{S}}}'ΣS′​ emitting observation τ\tauτ. As in ghostB{\mathsf{ghost}_{\mathbf{\textcolor{CarnationPink}{B}}}}ghostB​, reductions only happen on top of the stack.
rule\text{rule}
To model the effect of bypassing a store\mathbf{store}store instruction, Section 6.2.1 bypasses the store\mathbf{store}store instruction by increasing the program counter without updating the memory and starts a new speculative transaction by pushing a new speculative instance on top of the state. A load\mathbf{load}load instruction loading from the same memory location as the bypassed store\mathbf{store}store instruction, therefore, retrieves a stale value.
The set BehSω(p)\mathit{Beh}^{\omega}_{\texttt{\textcolor{Emerald}{S}}}(p)BehSω​(p) contains all traces generated from an initial state until termination using the reflexive-transitive closure of →S\xrightarrow{\mathit{}}_{\texttt{\textcolor{Emerald}{S}}}​S​.

6.2.2 Oracle Semantics

Instead of bypassing store\mathbf{store}store, the oracle semantics employs an oracle O{\mathcal{O}}O that decides if the store\mathbf{store}store instruction should be speculatively bypassed or not. As before, the behaviour BehSO(p)\mathit{Beh}^{{\mathcal{O}}}_{\texttt{\textcolor{Emerald}{S}}}(p)BehSO​(p) of a program ppp is the set of all traces starting from an initial state until termination using the reflexive-transitive closure of the oracle semantics.

6.3 Spec-R: Speculation on Return Instructions

The return-stack buffer (RSB) is a small stack the CPU uses to save return addresses upon call\mathbf{call}call instructions. These saved return addresses are speculatively used when the function returns because accessing the RSB is faster than looking up the return address on the stack (stored in main memory). This works well because return addresses rarely change during function execution. However, mispredictions can be exploited by an attacker [3, 2].

Example: Return Speculation Vulnerability

Consider the example in and recall that register sp\mathbf{sp}sp is used to find return addresses saved on the stack.
**Figure 7:** Control Flow of the vulnerable program in. A red arrow indicates a speculative control flow that happens because of misprediction with the RSB.

Figure 7: Control Flow of the vulnerable program in. A red arrow indicates a speculative control flow that happens because of misprediction with the RSB.

Each function call pushes a return address on the stack and decrements the sp\mathbf{sp}sp register. After reaching the function Manip\textunderscore Stack, the sp\mathbf{sp}sp register is incremented (Section 6.3). Thus, sp\mathbf{sp}sp points to the previous return address on the stack (i.e., Section 6.3), and the non-speculative execution continues in Main and terminates. However, the return address of the call in Section 6.3 is Section 6.3 and it is on top of the RSB. Thus, the CPU speculatively executes lines Section 6.3–Section 6.3 and leaks the secret.
This section describes the AM semantics (Section 6.3.1) and the oracle semantics (Section 6.3.2), Then, it discusses formalising different implementations of the RSB in the CPU (Section 6.3.3).

6.3.1 Speculative Semantics

Unlike before, the state of ghostR{\mathsf{ghost}_{\mathsf{\textcolor{RedOrange}{R}}}}ghostR​ contains a model of the RSB which is used to retrieve return addresses instead of relying on the stack.
Thus, speculative instances of ghostR{\mathsf{ghost}_{\mathsf{\textcolor{RedOrange}{R}}}}ghostR​ are extended with an additional entry R\mathbb{R}R for tracking the RSB, whose size is limited by a global constant Rsize\mathbb{R}_{size}Rsize​ denoting the maximal RSB size. A speculative instance ΦR\Phi_{\mathsf{\textcolor{RedOrange}{R}}}ΦR​ now consists of the program ppp, the counter ctr\mathit{ctr}ctr, the configuration σ\sigmaσ, the speculation window ω\omegaω, and the RSB R\mathbb{R}R. As before, a state ΣR\Sigma_{\mathsf{\textcolor{RedOrange}{R}}}ΣR​ is a stack of speculative instances Φ‾R\overline{\Phi}_{\mathsf{\textcolor{RedOrange}{R}}}ΦR​.
Spec. States ΣR::= Φ‾RSpec. Instance ΦR::= ⟨p,ctr,σ,R,n⟩\begin{aligned} \textit{Spec. States } \Sigma_{\mathsf{\textcolor{RedOrange}{R}}} \mathrel{::=}&\ \overline{\Phi}_{\mathsf{\textcolor{RedOrange}{R}}} & \textit{Spec. Instance } \Phi_{\mathsf{\textcolor{RedOrange}{R}}} \mathrel{::=}&\ \langle p, \mathit{ctr}, \sigma, \mathbb{R}, n \rangle \end{aligned}
As before, in ΣR→τRΣR\Sigma_{\mathsf{\textcolor{RedOrange}{R}}} \xrightarrow{\mathit{\tau}}_{\mathsf{\textcolor{RedOrange}{R}}} \Sigma_{\mathsf{\textcolor{RedOrange}{R}}}ΣR​τ​R​ΣR​ reductions happen on the top of the stack and in this semantics we have instrghost=call∪ret\mathit{instr}_{\mathsf{ghost}} = \mathbf{call} \cup \mathbf{ret}instrghost​=call∪ret since both call\mathbf{call}call and ret\mathbf{ret}ret instructions interact with the RSB and ret\mathbf{ret}ret instructions are the source of speculation.
rule\text{rule}
rule\text{rule}
During call\mathbf{call}call instructions (Section 6.3.1), the return address is pushed on top of the RSB (if there is space available) and during ret\mathbf{ret}ret instructions, the return address stored on the RSB is used if the entry on top of the RSB is different from the one stored on the stack (Section 6.3.1). Then, the rule creates a new speculative instance that uses the return address from the RSB R\mathbb{R}R. Note that speculation only happens when the return address from the RSB differs from the one on the stack (stored in m(a(sp))m(a(\mathbf{sp}))m(a(sp))).
Here, we overview how our semantics behaves with empty and full RSB. Whenever the RSB is empty, executing a ret\mathbf{ret}ret instruction does not cause speculation and we return to the address pointed by sp\mathbf{sp}sp. In contrast, whenever the RSB is full, executing a call\mathbf{call}call instruction does not add entries to the RSB, i.e., we model an acyclic RSB.2
2.
We follow the way AMD processors handle this kind of speculation [3].
The behaviour BehRω(p)\mathit{Beh}^{\omega}_{\mathsf{\textcolor{RedOrange}{R}}}(p)BehRω​(p) is the set of all traces generated from an initial state until termination using →R\xrightarrow{\mathit{}}_{\mathsf{\textcolor{RedOrange}{R}}}​R​.

6.3.2 Oracle Semantics

Unlike before, the oracle cannot decide the outcome of the ret\mathbf{ret}ret instruction, because the CPU always uses the return address stored in the RSB (if there is one) and it does not speculate otherwise [19]. The only thing the oracle decides here is the size of the speculation window ω\omegaω.

6.3.3 Different Behaviours of Empty and Full RSBs

Modern CPUs use different RSB implementations that differ in the way they handle underflows and overflows, i.e., when the RSB is empty or full [3]. For example, cyclic RSB implementations overwrite old entries when the RSB is full. Alternatively, CPUs can fallback to other predictors (like the indirect branch predictor) to predict return addresses whenever the RSB is empty.
In our model, the RSB is not cyclic and there is no speculation when the RSB is empty (Section 6.3.3).
rule\text{rule}
We remark that extending ghostR{\mathsf{ghost}_{\mathsf{\textcolor{RedOrange}{R}}}}ghostR​ to support different RSBs implementations can be done with minimal effort.

6.4 Spec-SLS: Straightline Speculation

Modern CPUs use the Branch Target Buffer (BTB) to assist with branch prediction. The BTB is indexed by possible jump instructions and predicts the next program counter. However, it also stores information about the type of branch (i.e. no branch, direct branch, indirect branch, or return) encountered at that location. Thus, it can happen that the BTB correctly predicts the location of a branch but mispredicts the type of the branch. For example, a ret\mathbf{ret}ret instruction can be mispredicted to have the type no branch which in turn means that the CPU speculatively executes code right past the ret\mathbf{ret}ret instruction. This kind of speculation is called straight-line speculation (SLS) [11, 45]. Note that a non-branch instruction can also be predicted as a branch which results in ghost jumps. Here, however, we focus only on straight-line speculation.

Example: Straightline Speculation Vulnerability

Consider the example in:
Code vulnerable to straightline speculation.

Code vulnerable to straightline speculation.

% Assume that p\texttt{p}p is an attacker-controlled value during the execution.
After the execution of the ret\mathbf{ret}ret instruction, the BTB of the processor predicts a no branch for the ret\mathbf{ret}ret instruction. Thus, the processor speculatively bypasses the ret\mathbf{ret}ret instruction and executes the following load\mathbf{load}load instruction in the theorem.
The speculative access of the memory is then leaked into the microarchitectural state by the array access into B\texttt{B}B in the theorem.
This section describes the AM semantics (Section 6.4.1) and the oracle semantics (Section 6.4.2).

6.4.1 Speculative Semantics

\mytoprule{\phiStackSLS \specarrowSLS{\tau} \phiStackSLS'}
rule\text{rule}
Judgement ΣSLS→τSLSΣSLS′\Sigma_{\texttt{\textcolor{DarkOrchid}{SLS}}} \xrightarrow{\mathit{\tau}}_{\texttt{\textcolor{DarkOrchid}{SLS}}} \Sigma_{\texttt{\textcolor{DarkOrchid}{SLS}}}'ΣSLS​τ​SLS​ΣSLS′​ describes how ΣSLS\Sigma_{\texttt{\textcolor{DarkOrchid}{SLS}}}ΣSLS​ steps to ΣSLS′\Sigma_{\texttt{\textcolor{DarkOrchid}{SLS}}}'ΣSLS′​ emitting observation τ\tauτ. As in ghostB{\mathsf{ghost}_{\mathbf{\textcolor{CarnationPink}{B}}}}ghostB​, reductions only happen on top of the stack. Here we have instrghost=ret\mathit{instr}_{\mathsf{ghost}} = \mathbf{ret}instrghost​=ret because ret\mathbf{ret}ret instructions are the source of speculation.
To model the effect of bypassing a ret\mathbf{ret}ret instruction, Section 6.4.1 bypasses the ret\mathbf{ret}ret instruction by increasing the program counter instead of using the return address to update the program counter and starts a new speculative transaction by pushing a new speculative instance on top of the state. This is in contrast to speculation on ret\mathbf{ret}ret in ghostR{\mathsf{ghost}_{\mathsf{\textcolor{RedOrange}{R}}}}ghostR​, which uses the RSB to update the program counter accordingly.
The set BehSLSω(p)\mathit{Beh}^{\omega}_{\texttt{\textcolor{DarkOrchid}{SLS}}}(p)BehSLSω​(p) contains all traces generated from an initial state until termination using the reflexive-transitive closure of →SLS\xrightarrow{\mathit{}}_{\texttt{\textcolor{DarkOrchid}{SLS}}}​SLS​.

6.4.2 Oracle Semantics

Instead of bypassing every ret\mathbf{ret}ret instruction, the oracle semantics employs an oracle O{\mathcal{O}}O that decides if the ret\mathbf{ret}ret instruction should be speculatively bypassed or not. As before, the behaviour BehSLSO(p)\mathit{Beh}^{{\mathcal{O}}}_{\texttt{\textcolor{DarkOrchid}{SLS}}}(p)BehSLSO​(p) of a program ppp is the set of all traces starting from an initial state until termination using the reflexive-transitive closure of the oracle semantics.

6.5 Spec-J: Speculation on (Indirect) Jump Instructions

Modern processors use an indirect branch predictor to predict the outcome of indirect branches. Indirect branches are branches where the outcome is not known until the execution of the program. For example, jmp r1\mathbf{jmp}\ \texttt{r1}jmp r1, which jumps to the location specified by register r1\texttt{r1}r1. Instead of waiting for the value of r1r1r1 to be available, the processor predicts the jump target based on the branch target buffer. However, attackers can poison the content of the branch target buffer, which allows the attacker to speculatively divert the control flow of the program [1].
**Figure 8:** Example program vulnerable to jump speculation () and a version restricting the jump speculation using $\textbf{endbr}$ instructions ().

Figure 8: Example program vulnerable to jump speculation () and a version restricting the jump speculation using endbr\textbf{endbr} instructions ().

Example: A Program Exploiting Jump Speculation

Consider the example in implementing a small jump table. In Section 6.5 until Section 6.5 the program assigns the jump target to r1\texttt{r1}r1 depending on the value of x\texttt{x}x. Next, the indirect jump in Section 6.5 executes and non-speculative execution continues at either J1 or J2. In both cases, execution terminates by jumping to the end in Section 6.5, By exploiting jump speculation, an attacker could guide the indirect jump in Section 6.5 to Section 6.5 thus leaking the contents of the private variable p\texttt{p}p in Section 6.5.
This section describes the AM semantics (Section 6.5.1), the oracle semantics (Section 6.5.2).

6.5.1 Speculative Semantics

The attacker can inject any address as the new jump target, making analysis especially tricky. Consider a hypothetical speculation rule capturing the speculative behaviour of indirect jumps (note, this is not the version we use, which is presented below):
rule\text{rule}
rule\text{rule}
rule\text{rule}
Section 6.5.1 allows the execution to speculatively jump to any location and we would need to create a speculative instance for each of these locations. Here, Section 6.5.1 and Section 6.5.1 are helpers creating the speculative transactions and we use x⊂ex \subset ex⊂e to denote the subexpressions of eee, thereby ensuring that only indirect jumps are used for speculation.
However, creating a speculative instance for each location in the program makes the analysis of the program infeasible because of the amount of states that need to be explored. Furthermore, against such a model, almost any "interesting" program would be considered insecure since speculation is, in practice, unrestricted.
One of the techniques employed by modern CPUs to restrict the scope of indirect-jump speculation is (hardware) control-flow-integrity (CFI) [46]. CFI leverages tags to mark valid jump targets in the code and ensures that the code can only jump to these tagged targets. There are different ways tagging and enforcement mechanisms can be implemented (see [47] for a comprehensive survey). We will focus on the hardware implementations of CFI of Intel (Intel-CET [48]) and ARM (branch target identification [49]) because they are available on new hardware and are supposed to apply also to transient instructions.
Both implementations add a new instruction endbr\mathbf{endbr}endbr (in the case of ARM this instruction is called bti\mathbf{bti}bti) that marks the legal targets of indirect jumps in a program and enables coarse-grained forward edge control flow integrity. Enforcement is done by a state machine in hardware that ensures only valid jumps are allowed. Furthermore, all available standard compilers (i.e. GCC{\mathchoice{\text{G{\scriptsize CC}}}{\text{G{\scriptsize CC}}}{\text{G{\scriptscriptstyle CC}}}{\text{GCC}}}GCC, CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG) already emit these endbr\mathbf{endbr}endbr instructions and these instructions are handled as no-ops if the current hardware does not support CFI, making it backwards-compatible. Thus, we similarly add a endbr\mathbf{endbr}endbr instruction to μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM, which marks legal targets for indirect jumps in the program and otherwise behaves like a skip\mathbf{skip}skip instruction (the section). This restricts the scope of indirect-jump speculation and allows for a tractable analysis.
rule\text{rule}rule
First, we keep track of all possible allowed jump targets in the program. We collect the instruction number for each endbr\mathbf{endbr}endbr instruction into a labelset LLL defined as follows: Lp={i∣∀i∈N.p(i)=endbr}L_p = \{i \mid \forall i \in \mathbb{N} \ldotp p(i) = \mathbf{endbr} \}Lp​={i∣∀i∈N.p(i)=endbr}. We will omit ppp in LpL_pLp​ if it is clear from context. One possible way to modify the program in with endbr\mathbf{endbr}endbr instruction is the program in. Then, the labelset is defined as: L={v2-endbr1,v2-endbr2}L = \{\text{v2-endbr1},\text{v2-endbr2}\}L={v2-endbr1,v2-endbr2}. Next, we modify the rule for non-speculative jumps by requiring that the jump target is part of the allowed jump targets LLL (Section 6.5.1):
rule\text{rule}rule
Note that for all other semantics, we can define the set of possible jump targets to be all instruction labels in the program to recover the original rule for non-speculative jumps.
Next, we define the new speculative semantics:
\mytoprule{\PhiJ \specarrowJ{\tau} \phiStackJ'}
rule\text{rule}
We replace the unmitigated Section 6.5.1 with the constrained Section 6.5.1. The main difference lies in the definition of the allowed jump target set. The set SSS in the unmitigated rule allows jumps to arbitrary addresses in the program. In the new rule this is restricted to LLL, allowing jumps only to targets designated by endbr\mathbf{endbr}endbr instructions. When an indirect branch is encountered, Section 6.5.1 creates a speculative instance for each target in LLL, excluding the correct non-speculative target. Thus, the rule creates exactly ∣L∣−1\vert L\vert - 1∣L∣−1 speculative instances. Consider the example in where L={v2-endbr1,v2-endbr2}L = \{\text{v2-endbr1},\text{v2-endbr2}\}L={v2-endbr1,v2-endbr2}. Because Section 6.5.1 can only speculatively jump to targets in LLL, execution cannot speculatively reach Section 6.5, successfully preventing the leakage of the private variable p\texttt{p}p.
Crucially, because this rule creates a set of instances rather than a single misprediction (diverging from the standard single-target template in Section 5.2), it introduces an asymmetry between start and rollback observations: A single startJ ctr\textcolor{RoyalBlue}{\mathtt{start}}_{\textit{\textcolor{BlueGreen}{J}}}\ \mathit{ctr}startJ​ ctr observation is now associated with multiple rollback observations (exactly ∣L∣−1\vert L \vert -1∣L∣−1 many).3 However, because the speculative instances are pushed onto the execution stack sequentially, their execution is strictly nested. The resulting trace exhibits the following structure, where inner transactions are rolled back before the outer transaction concludes:
startJ ctr⋯rlbJ ctr+∣L∣−2⋯rlbJ ctr\textcolor{RoyalBlue}{\mathtt{start}}_{\textit{\textcolor{BlueGreen}{J}}}\ \mathit{ctr} \cdots \textcolor{RoyalBlue}{\mathtt{rlb}}_{\textit{\textcolor{BlueGreen}{J}}}\ \mathit{ctr} + \vert L \vert -2 \cdots \textcolor{RoyalBlue}{\mathtt{rlb}}_{\textit{\textcolor{BlueGreen}{J}}}\ \mathit{ctr}
3.
We could have decided to add matching startJ ctr\textcolor{RoyalBlue}{\mathtt{start}}_{\textit{\textcolor{BlueGreen}{J}}}\ \mathit{ctr} observations to Section 6.5.1 to balance the startJ i\textcolor{RoyalBlue}{\mathtt{start}}_{\textit{\textcolor{BlueGreen}{J}}}\ i and the rlbJ i\textcolor{RoyalBlue}{\mathtt{rlb}}_{\textit{\textcolor{BlueGreen}{J}}}\ i.
This nesting guarantees the correctness of the non-speculative projection function ↾ns\mathord{\upharpoonright_{ns}}↾ns​. Since ↾ns\mathord{\upharpoonright_{ns}}↾ns​ erases the trace segment between a start event and its matching rollback (here, the final rlbJ ctr\textcolor{RoyalBlue}{\mathtt{rlb}}_{\textit{\textcolor{BlueGreen}{J}}}\ \mathit{ctr}rlbJ​ ctr), all intermediate speculative events—including the nested rollbacks—are correctly removed from the trace.

6.5.2 Oracle Semantics

Instead of predicting all of the possible indirect jmp\mathbf{jmp}jmp targets, the oracle chooses one of the possible jump targets in LLL and continues only with this one choice. As before, the behaviour BehJO(p)\mathit{Beh}^{{\mathcal{O}}}_{\textit{\textcolor{BlueGreen}{J}}}(p)BehJO​(p) of a program ppp is the set of all traces starting from an initial state until termination using the reflexive-transitive closure of the oracle semantics.

6.6 Safety of Semantics

We conclude this section by proving the core properties satisfied by all semantics. Theorem 11 characterizes that all the speculative semantics presented in the paper are well-formed speculative semantics, i.e., (1) their always-mispredict version over-approximates the corresponding oracle version, (2) they are consistent under non-speculative trace projection, and (3) their symbolic version is consistent with the corresponding non-symbolic version.

Theorem 11: Well-Formed Speculative Semantics

The following statements hold:
  • (ghost\mathsf{ghost}ghost is WFSS\mathit{WFSS}WFSS) ghost\mathsf{ghost}ghost
  • (ghost\mathsf{ghost}ghost is WFSS\mathit{WFSS}WFSS) ghost\mathsf{ghost}ghost
  • (ghost\mathsf{ghost}ghost is WFSS\mathit{WFSS}WFSS) ghost\mathsf{ghost}ghost
  • (ghost\mathsf{ghost}ghost is WFSS\mathit{WFSS}WFSS) ghost\mathsf{ghost}ghost
  • (ghost\mathsf{ghost}ghost is WFSS\mathit{WFSS}WFSS) ghost\mathsf{ghost}ghost

7. A Framework for Composing Speculative Semantics

Although the instances of speculative semantics presented in Section 6 each capture one specific aspect of speculation (e.g., ghost\mathsf{ghost}ghost captures branch speculation) , they do not capture the vulnerability in (restated here for clarity) as the traces of Example 12 show.

Example 12: SNI for Figure 9

The traces generated are:
τ‾B1=τ‾B2:=store p⋅store p⋅startB 0⋅load p⋅load A+public⋅rlbB 0⋅pc 9τ‾S1=τ‾S2:=...⋅store p⋅startS 1⋅bypass 1⋅pc ⊥⋅rlbS 1⋅pc ⊥\begin{aligned} \begin{split} \overline{\tau}_{\mathbf{\textcolor{CarnationPink}{B}}}^1 = \overline{\tau}_{\mathbf{\textcolor{CarnationPink}{B}}}^2 := {}& \textcolor{RoyalBlue}{\mathtt{store}}\ p \cdot \textcolor{RoyalBlue}{\mathtt{store}}\ p \cdot \textcolor{RoyalBlue}{\mathtt{start}}_{\mathbf{\textcolor{CarnationPink}{B}}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ p \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ A + public \cdot \textcolor{RoyalBlue}{\mathtt{rlb}}_{\mathbf{\textcolor{CarnationPink}{B}}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 9 \end{split}\\ \begin{split} \overline{\tau}_{\texttt{\textcolor{Emerald}{S}}}^1 = \overline{\tau}_{\texttt{\textcolor{Emerald}{S}}}^2 := {}& ... \cdot \textcolor{RoyalBlue}{\mathtt{store}}\ p \cdot \textcolor{RoyalBlue}{\mathtt{start}}_{\texttt{\textcolor{Emerald}{S}}}\ 1 \cdot \textcolor{RoyalBlue}{\mathtt{bypass}}\ 1 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ \perp \cdot \textcolor{RoyalBlue}{\mathtt{rlb}}_{\texttt{\textcolor{Emerald}{S}}}\ 1 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ \perp \end{split} \end{aligned}
The program in Figure 9 seems secure since there is no secret value leaked in the speculative transaction; thus the program satisfies SNI for ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost in isolation. However, this program speculatively leaks when considering speculation over beqz\mathbf{beqz}beqz and store\mathbf{store}store instructions, but we would need a combined semantics to detect this vulnerability.
**Figure 9:** $\operatorname{sembs}$ example.

Figure 9: sembs⁡\operatorname{sembs} example.

The vulnerability only appears when the branch predictor (Section 6.1) and the memory disambiguator (Section 6.2) are used together. Intuitively, we know that CPUs use all the speculation mechanisms described here (and many others as well) at the same time. Thus, we should not only focus on these individual speculation mechanisms in isolation but we need to look at their combinations as well. That is, we need a way to compose the different semantics into new semantics that can reason about these "combined" leaks.
This section presents a novel, general framework for composing two speculative semantics xxx and yyy, each one capturing the effects of a single speculation mechanism, to allow for speculation from both mechanisms xxx and yyy. The semantics xxx and yyy are also called the source semantics of the composition. Next, we first introduce the new composed semantics, which consists of an always-mispredict semantics, an oracle semantics, and a symbolic semantics (Section 7.1). Then, we present the notion of well-formed composition which we use to study the properties of composed semantics (Section 7.2).
New Notation The states Σxy\Sigma_{xy}Σxy​, instances Φxy\Phi_{xy}Φxy​, and the trace model Obsxy\mathit{Obs}_{xy}Obsxy​ are defined as the union of the source parts. Furthermore, we define a projection function ↾xy\mathord{\upharpoonright_{xy}}↾xy​ and two projections ↾xyx\mathord{\upharpoonright_{xy}^{x}}↾xyx​ and ↾xyy\mathord{\upharpoonright_{xy}^{y}}↾xyy​ that return the first and second projection of the pair from ↾xy\mathord{\upharpoonright_{xy}}↾xy​. These functions are lifted to states by applying them pointwise:
Obsxy:= Obsx∪ObsyΦxy:= Φx∪ΦyΣxy:= Σx∪Σy↾xy ⁣:Φxy↦(Φx,Φy)↾xyx ⁣: Φxy↦Φx↾xyy ⁣: Φxy↦Φy\begin{aligned} & \mathit{Obs}_{xy} \vcentcolon=\ \mathit{Obs}_{x} \cup \mathit{Obs}_{y} & & \Phi_{xy} \vcentcolon=\ \Phi_{x} \cup \Phi_{y} & \Sigma_{xy} \vcentcolon=\ \Sigma_{x} \cup \Sigma_{y}\\ &\mathord{\upharpoonright_{xy}} \colon \Phi_{xy} \mapsto (\Phi_{x}, \Phi_{y}) & &\mathord{\upharpoonright_{xy}^{x}} \colon\ \Phi_{xy} \mapsto \Phi_{x} & \mathord{\upharpoonright_{xy}^{y}} \colon\ \Phi_{xy} \mapsto \Phi_{y} \end{aligned}
For example, the ΦS+R\Phi_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}}ΦS+R​ state resulting from the union of ΦS\Phi_{\texttt{\textcolor{Emerald}{S}}}ΦS​ and ΦR\Phi_{\mathsf{\textcolor{RedOrange}{R}}}ΦR​ states (from Section 6.2.1 and Section 6.3.1 respectively) is ⟨p,ctr,σ,R,n⟩\langle p, \mathit{ctr}, \sigma, \mathbb{R}, n \rangle⟨p,ctr,σ,R,n⟩, as it contains all common elements (the program ppp, the counter ctr\mathit{ctr}ctr, the state σ\sigmaσ, and the speculation count nnn) plus the return stack buffer R\mathbb{R}R from ΦR\Phi_{\mathsf{\textcolor{RedOrange}{R}}}ΦR​ only. Taking the ⋅↾S+RS\cdot\mathord{\upharpoonright^{\texttt{\textcolor{Emerald}{S}}}_{\texttt{\textcolor{Emerald}{S}}+\mathsf{\textcolor{RedOrange}{R}}}}⋅↾S+RS​ of a ΦS+R\Phi_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}}ΦS+R​ state returns the ΦS\Phi_{\texttt{\textcolor{Emerald}{S}}}ΦS​ subpart, i.e., all but the return stack buffer.
We overload ↾xyx\mathord{\upharpoonright_{xy}^{x}}↾xyx​ and ↾xyy\mathord{\upharpoonright_{xy}^{y}}↾xyy​ to also work on traces τ‾\overline{\tau}τ. The projection τ↾xyx\tau\mathord{\upharpoonright_{xy}^{x}}τ↾xyx​ deletes all speculative transactions (marked by starty id\textcolor{RoyalBlue}{\mathtt{start}}_{y}\ \mathit{id}starty​ id and rlby id\textcolor{RoyalBlue}{\mathtt{rlb}}_{y}\ \mathit{id}rlby​ id) not generated by the source semantics xxx. The definition of ↾xyy\mathord{\upharpoonright_{xy}^{y}}↾xyy​ is similar by replacing xxx with yyy:
ε↾xyx= ε(τ⋅τ‾)↾xyx= τ⋅(τ‾)↾xyx(starty id⋅⋯rlby id⋅τ‾)↾xyx= τ‾↾xyx\begin{aligned} \varepsilon\mathord{\upharpoonright_{xy}^{x}} =~ \varepsilon \qquad\qquad (\tau \cdot \overline{\tau})\mathord{\upharpoonright_{xy}^{x}} =&~ \tau \cdot (\overline{\tau})\mathord{\upharpoonright_{xy}^{x}} \\ (\textcolor{RoyalBlue}{\mathtt{start}}_{y}\ \mathit{id} \cdot \cdots \textcolor{RoyalBlue}{\mathtt{rlb}}_{y}\ \mathit{id} \cdot \overline{\tau})\mathord{\upharpoonright_{xy}^{x}} =&~ \overline{\tau}\mathord{\upharpoonright_{xy}^{x}} \end{aligned}
We indicate source semantics for xxx and yyy as ghostx\mathsf{ghost}_{x}ghostx​ and ghosty\mathsf{ghost}_{y}ghosty​ respectively and use ghostxy\mathsf{ghost}_{xy}ghostxy​ to indicate the composed semantics.

7.1 Combined Speculative Semantics

The combined semantics delegates back to the source semantics of xxx and yyy to model the effects of both speculation mechanisms (modeled by xxx and yyy). This is captured in the two core rules below:
rule\text{rule}rule
rule\text{rule}rule
The combined semantics does a step by either delegating back to the xxx source semantics (Section 7.1) or to the yyy one (Section 7.1).4 The rules rely on metaparameter ZxyZ_{xy}Zxy​, which is a pair of two metaparameters Zxy:=(Zx,Zy)Z_{xy} \vcentcolon= (Z_{x}, Z_{y})Zxy​:=(Zx​,Zy​) — one for xxx and one for yyy. We overload the projections ↾xyx\mathord{\upharpoonright_{xy}^{x}}↾xyx​ and ↾xyy\mathord{\upharpoonright_{xy}^{y}}↾xyy​ to extract the corresponding metaparameter from ZxyZ_{xy}Zxy​, e.g., Zxy↾xyx=ZxZ_{xy}\mathord{\upharpoonright_{xy}^{x}} = Z_{x}Zxy​↾xyx​=Zx​.
4.
To simplify notation, we omit that the Φx∖Φy\Phi_{x} \setminus \Phi_{y} parts of state Φxy\Phi_{xy} in x-step (similar Φy∖Φx\Phi_{y} \setminus \Phi_{x} in y-step) do not change between Φxy\Phi_{xy} and Φ‾xy′\overline{\Phi}_{xy}'.
The role of ZZZ is central to making the composed semantics work as expected. It restricts how the combined semantics delegates execution to the components to ensure that the correct rule is applied.
With Z=(∅,∅)Z = (\emptyset,\emptyset)Z=(∅,∅), consider the execution of the beqz\mathbf{beqz}beqz instruction in the theorem in Figure 9. The combined semantics ghost\mathsf{ghost}ghost can use Section 7.1 to delegate back to ghost\mathsf{ghost}ghost for beqz\mathbf{beqz}beqz instructions, creating a new speculative transaction (Section 6.1.1). However, ghost\mathsf{ghost}ghost can also use Section 7.1, because beqz\mathbf{beqz}beqz instructions are also handled by ghost\mathsf{ghost}ghost. Unfortunately, this does not start speculation, which happens only on store\mathbf{store}store instructions (Section 6.2.1).
Intuitively, ghost\mathsf{ghost}ghost should delegate back to ghost\mathsf{ghost}ghost, so Section 7.1 should not be applicable. This can be obtained by instantiating ZB+S=(store,beqz)Z_{\mathbf{\textcolor{CarnationPink}{B}} + \texttt{\textcolor{Emerald}{S}}} = (\mathbf{store}, \mathbf{beqz})ZB+S​=(store,beqz), so that its projections are ZB=storeZ_{\mathbf{\textcolor{CarnationPink}{B}}} = {\mathbf{store}}ZB​=store and ZS=beqzZ_{\texttt{\textcolor{Emerald}{S}}} = {\mathbf{beqz}}ZS​=beqz. Now, ghost\mathsf{ghost}ghost can only apply Section 7.1 on the beqz\mathbf{beqz}beqz of the theorem, because ZSZ_{\texttt{\textcolor{Emerald}{S}}}ZS​ ensures that ghost\mathsf{ghost}ghost cannot execute beqz\mathbf{beqz}beqz instructions, as depicted in the full rule for ghost\mathsf{ghost}ghost below (where we indicate the instructions derived from ZS=beqzZ_{\texttt{\textcolor{Emerald}{S}}} = \mathbf{beqz}ZS​=beqz in blue):
rule\text{rule}
Having clarified the intuition behind the semantics, we can define the behaviour Behxyω()\mathit{Beh}^{\omega}_{xy}()Behxyω​() as the set of all traces generated from initial states until termination using →xy\xrightarrow{\mathit{}}_{xy}​xy​.

7.1.1 Oracle Combination

Instead of using one oracle, the combination uses a pair of oracles, one from each source semantics. When delegating back to either source, the correct oracle of the source is handed over to the source semantics.

7.1.2 Symbolic Combination

Instead of using the AM semantics for delegation, the combined symbolic semantics ghostxyS\mathsf{ghost}_{xy}^{\mathcal{S}}ghostxyS​ uses the symbolic source semantics for delegation. Furthermore, the new notation (union, projections) is lifted to the symbolic combination to create the symbolic states ΣxyS\Sigma_{xy}^{\mathcal{S}}ΣxyS​. The behaviour BehxyS(p)\mathit{Beh}^{\mathcal{S}}_{xy}(p)BehxyS​(p) of program ppp is the set of all traces generated using the symbolic semantics.

7.2 Properties of Composition

We now illustrate the benefits of our composition framework. For this, we first introduce a notion of well-formed composition (Section 7.2.1), which intuitively tells when a combined semantics "makes sense". Then, we show that for well-formed compositions, if the source semantics are WFSS\mathit{WFSS}WFSS, so is the combined semantics (Section 7.2.2). Since we proved this property for any well-formed composition in our framework, all (well-formed) compositions we present in Section 8 are WFSS\mathit{WFSS}WFSS for free. This proof reuse and extensibility is our framework's key advantage over having ad-hoc semantics combining multiple speculation mechanisms, which requires one to manually prove the WFSS\mathit{WFSS}WFSS results we instead obtain for free.

7.2.1 Well-formed Compositions

The well-formedness conditions for the composition in Definition 13 ensures that the delegation between the source semantics is done properly. Note that these conditions are the minimal set of assumptions that let us derive WFSS\mathit{WFSS}WFSS of the combined semantics for free:

Definition 13: Well-Formed Composition

A composition ghostxy\mathsf{ghost}_{xy}ghostxy​ of two speculative semantics ghostx\mathsf{ghost}_{x}ghostx​ and ghosty\mathsf{ghost}_{y}ghosty​ is well-formed, written ⊢ghostxy:WFC{\vdash{\mathsf{ghost}_{xy}}:\mathit{WFC}}⊢ghostxy​:WFC, if:
  • (Confluence) Whenever Σxy→τxyΣxy′\Sigma_{xy}\xrightarrow{\mathit{\tau}}_{xy}\Sigma_{xy}'Σxy​τ​xy​Σxy′​ and Σxy→τxyΣxy′′\Sigma_{xy}\xrightarrow{\mathit{\tau}}_{xy}\Sigma_{xy}''Σxy​τ​xy​Σxy′′​, then Σxy′=Σxy′′\Sigma_{xy}' = \Sigma_{xy}''Σxy′​=Σxy′′​.
  • (Projection preservation) For all ppp, Behxω(p)=Behxyω((p))↾xyx\mathit{Beh}^{\omega}_x(p) = \mathit{Beh}^{\omega}_{xy}((p))\mathord{\upharpoonright_{xy}^{x}}Behxω​(p)=Behxyω​((p))↾xyx​ and Behyω(p)=Behxyω((p))↾xyy\mathit{Beh}^{\omega}_y(p) = \mathit{Beh}^{\omega}_{xy}((p))\mathord{\upharpoonright_{xy}^{y}}Behyω​(p)=Behxyω​((p))↾xyy​.
  • (Relation preservation) If Σxy≈xyXxy\Sigma_{xy}\thickapprox_{xy}X_{xy}Σxy​≈xy​Xxy​ and Σxy→τ‾xy∗Σxy′\Sigma_{xy}\xrightarrow{\mathit{\overline{\tau}}}_{xy}^{*}\Sigma_{xy}'Σxy​τ​xy∗​Σxy′​ then Xxy⇝xyOxyXxy′X_{xy}\leadsto_{xy}^{{\mathcal{O}}_{xy}}X_{xy}'Xxy​⇝xyOxy​​Xxy′​ and Σxy′≈xyXxy′\Sigma_{xy}'\thickapprox_{xy}X_{xy}'Σxy′​≈xy​Xxy′​.
  • (Symbolic preservation) If ΣxyS→τSxySΣxyS′\Sigma_{xy}^{\mathcal{S}}\xrightarrow{\mathit{\tau_{\mathcal{S}}}}_{xy}^{\mathcal{S}}\Sigma_{xy}^{\mathcal{S}'}ΣxyS​τS​​xyS​ΣxyS′​ and μ⁡ΣxyS=Σxy\operatorname{\mu}{\Sigma_{xy}^{\mathcal{S}}} = \Sigma_{xy}μΣxyS​=Σxy​, then there is Σxy′\Sigma_{xy}'Σxy′​ s.t. Σxy→μ⁡(τS)xyΣxy′\Sigma_{xy}\xrightarrow{\mathit{\operatorname{\mu}(\tau_{\mathcal{S}})}}_{xy}\Sigma_{xy}'Σxy​μ(τS​)​xy​Σxy′​ and μ⁡ΣxyS′=Σxy′\operatorname{\mu}{\Sigma_{xy}^{\mathcal{S}'}} = \Sigma_{xy}'μΣxyS′​=Σxy′​.
Next, we explain the well-formedness conditions:
  • Confluence (point 1) ensures that the non-determinism of the combined semantics (that non-deterministically delegates back to its sources) is not harmful. Consider the assignment in the theorem in. ghost\mathsf{ghost}ghost can delegate to either ghost\mathsf{ghost}ghost or ghost\mathsf{ghost}ghost to reduce the assignment. If the combined semantics is confluent, then it does not matter which source rule executes the assignment in the theorem in, the semantics reaches the same state either way.
  • Projection preservation (point 2) ensures that the combined semantics is not hiding or forgetting traces of its sources. Any observable emitted by a source semantics must be propagated to the combined one, this is also the reason why Obsxy\mathit{Obs}_{xy}Obsxy​ is defined as the union of the source Obs\mathit{Obs}Obs.
  • To explain relation preservation (point 3), we need to mention a technical detail: the state relation (denoted ≈xy\thickapprox_{xy}≈xy​ and defined in our technical report) between the AM states (Σxy\Sigma_{xy}Σxy​) and the Oracle ones (XxyX_{xy}Xxy​). Intuitively, two states are related if they are the same or if one is waiting on a speculation of the other to end. Then, point (3) ensures that whenever we start from related states (Σxy≈xyXxy\Sigma_{xy}\thickapprox_{xy}X_{xy}Σxy​≈xy​Xxy​) and we do one or more steps of the AM composed semantics (→τ‾xy∗\xrightarrow{\mathit{\overline{\tau}}}_{xy}^{*}τ​xy∗​), then we can always find a related state (Σxy′≈xyXxy′\Sigma_{xy}'\thickapprox_{xy}X_{xy}'Σxy′​≈xy​Xxy′​) that is reachable by performing one or more steps of the composed oracle semantics (⇝xyOxy\leadsto_{xy}^{{\mathcal{O}}_{xy}}⇝xyOxy​​). This fact is used when proving that SNI of a program under the composed AM semantics implies SNI under the composed oracle semantics (point 1 of Definition 10). Thus, it is not important for the AM and the Oracle semantics to produce the same traces, just that the two AM traces and the two Oracle traces are pairwise equivalent – which follows from the state relation.
  • Finally, symbolic preservation (point 4) ensures that any step of the always-mispredict composed semantics corresponds to the concretization of a step of the symbolic composed semantics (and vice versa5). Note that proving symbolic preservation is almost trivial whenever both source semantics enjoy the same property (like our semantics ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost).
5.
For space reasons, Definition 13 only reports one direction (with a simplified notation).

7.2.2 WFSS\mathit{WFSS}WFSS Preservation

The key result of this section is that well-formed compositions whose sources are well-formed speculative semantics (WFSS\mathit{WFSS}WFSS) are also WFSS\mathit{WFSS}WFSS (Theorem 14). Note that our proof of Theorem 14\IfEqCase{false}{{true}{, available in the companion technical report [37], }} holds for any well-formed composition in our framework and, therefore, it applies for free to all the compositions in Section 8.

Theorem 14: ghostxy\mathsf{ghost}_{xy} is WFSS\mathit{WFSS}

If ⊢ghostx WFSS{\vdash{\mathsf{ghost}_{x}}~\mathit{WFSS}}⊢ghostx​ WFSS and ⊢ghosty WFSS{\vdash{\mathsf{ghost}_{y}}~\mathit{WFSS}}⊢ghosty​ WFSS and ⊢ghostxy:WFC{\vdash{\mathsf{ghost}_{xy}}:\mathit{WFC}}⊢ghostxy​:WFC, then ⊢ghostxy WFSS{\vdash{\mathsf{ghost}_{xy}}~\mathit{WFSS}}⊢ghostxy​ WFSS.
As a corollary of Theorem 14, we obtain that the security of well-formed compositions is related to the security of their components (Theorem 15). In particular, whenever a program is insecure w.r.t. one of the components, then it is insecure w.r.t. the composed semantics. Dually, if a program is secure w.r.t. the composed semantics, then it is secure w.r.t. the single components. Note, however, that there are programs that are secure for the single components but insecure w.r.t. the composed semantics like.

Theorem 15: Combined SNI Preservation

Whenever ⊢ghostxy:WFC{\vdash{\mathsf{ghost}_{xy}}:\mathit{WFC}}⊢ghostxy​:WFC holds:
  • If p̸⊢xSNIp \not\vdash_{x} \text{SNI}p⊢x​SNI or p̸⊢ySNIp \not\vdash_{y} \text{SNI}p⊢y​SNI, then p̸⊢xySNIp \not\vdash_{xy} \text{SNI}p⊢xy​SNI.
  • If p⊢xySNIp \vdash_{xy} \text{SNI}p⊢xy​SNI, then p⊢xSNIp \vdash_{x} \text{SNI}p⊢x​SNI and p⊢ySNIp \vdash_{y} \text{SNI}p⊢y​SNI.
These results have an immediate practical impact on SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR: (1) the analysis of SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR relies on the (symbolic) speculative semantics, (2) the source semantics ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost are WFSS\mathit{WFSS}WFSS, (3) well-formed compositions are also WFSS\mathit{WFSS}WFSS, and (4) the composition of ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost are well-formed. So, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR equipped with any combination of the ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost produces sound results, i.e., whenever the tool proves that a program is leak-free then the program satisfies SNI. In the next section, we describe all the compositions and prove they are well-formed (this implies that they are WFSS\mathit{WFSS}WFSS thanks to Theorem 14).

8. Instantiating our Framework

Partial order of the different combinations that we instantiate using our framework

Partial order of the different combinations that we instantiate using our framework

We instantiate our combination framework with all possible combinations of ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost, yielding 18 combinations depicted in Figure 10. Combinations of ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost are impossible because they speculate on the same instructions (ret\mathbf{ret}ret). Thus, we cannot set the metaparameter ZZZ in a sensible way (more details in Section 11). Since we cannot describe all of the combinations in detail, we focus on two representative combinations: ghost\mathsf{ghost}ghost (Section 8.1) and ghost\mathsf{ghost}ghost (Section 8.2); the other combinations can be instantiated in a similar way.
For each of these, we overview the combined AM semantics using examples and we prove that the combined semantics is well-formed, i.e., it satisfies Definition 13.
\IfEqCase{false}{{true}{Full details and well-formedness proofs of all other combinations are available in the companion technical report [37]}} .

8.1 Spec-S+R Composition

To combine semantics using our framework, we need to define the states, observations, and metaparameter ZS+RZ_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}}ZS+R​ for the composed semantics ghost\mathsf{ghost}ghost. The combined state ΣS+R\Sigma_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}}ΣS+R​ is the union of the states ΣS\Sigma_{\texttt{\textcolor{Emerald}{S}}}ΣS​ and ΣR\Sigma_{\mathsf{\textcolor{RedOrange}{R}}}ΣR​; thus it contains the RSB R\mathbb{R}R as well.
Spec. States ΣS+R::= Φ‾S+RSpec. Instance ΦS+R::= ⟨p,ctr,σ,R,n⟩\begin{aligned} \textit{Spec. States } \Sigma_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}} \mathrel{::=}&\ \overline{\Phi}_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}} & \textit{Spec. Instance } \Phi_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}} \mathrel{::=}&\ \langle p, \mathit{ctr}, \sigma, \mathbb{R}, n \rangle \end{aligned}
The union ObsS+R\mathit{Obs}_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}}ObsS+R​ of the trace models ObsS\mathit{Obs}_{\texttt{\textcolor{Emerald}{S}}}ObsS​ and ObsR\mathit{Obs}_{\mathsf{\textcolor{RedOrange}{R}}}ObsR​ is defined as:
ObsS+R::= startS n∣startR n∣rlbS n∣rlbR n∣bypass n∣...\begin{aligned} \mathit{Obs}_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}} \mathrel{::=}&\ \textcolor{RoyalBlue}{\mathtt{start}}_{\texttt{\textcolor{Emerald}{S}}}\ n \mid \textcolor{RoyalBlue}{\mathtt{start}}_{\mathsf{\textcolor{RedOrange}{R}}}\ n \mid \textcolor{RoyalBlue}{\mathtt{rlb}}_{\texttt{\textcolor{Emerald}{S}}}\ n \mid \textcolor{RoyalBlue}{\mathtt{rlb}}_{\mathsf{\textcolor{RedOrange}{R}}}\ n \mid \textcolor{RoyalBlue}{\mathtt{bypass}}\ n \mid ... \end{aligned}
To define the metaparameter ZS+RZ_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}}ZS+R​, we need to identify the instructions that are related with speculative execution for each component semantics. For ghost\mathsf{ghost}ghost, the only instruction associated with speculative execution is store\mathbf{store}store, since the semantics can only speculatively bypass stores. For ghost\mathsf{ghost}ghost, even though the semantics speculates only over ret\mathbf{ret}ret instructions, call\mathbf{call}call instructions also affect speculative execution since ghost\mathsf{ghost}ghost pushes return addresses onto the RSB R\mathbb{R}R when executing call\mathbf{call}calls. Therefore, we set the metaparameter ZS+RZ_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}}ZS+R​ to (call∪ret,store)( \mathbf{call} \cup \mathbf{ret}, \mathbf{store})(call∪ret,store). This ensures that in ghost\mathsf{ghost}ghost, store\mathbf{store}store instructions are only executed by delegating back to ghost\mathsf{ghost}ghost whereas call\mathbf{call}call and ret\mathbf{ret}ret instructions are only executed by delegating back to ghost\mathsf{ghost}ghost.
Theorem 16 states the combination of ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost described above is well-formed. Given that ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost are WFSS\mathit{WFSS}WFSS (Theorem 11), we can derive "for free" that ghost\mathsf{ghost}ghost is WFSS\mathit{WFSS}WFSS (Theorem 14).

Theorem 16: ghost\mathsf{ghost} is well-formed

ghost\mathsf{ghost}ghost
$\operatorname{semsr}$ example.

semsr⁡\operatorname{semsr} example.

presents a program that contains a leak that can be detected only by ghost\mathsf{ghost}ghost but not by its components ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost. Execution starts on the theorem by calling the function Speculate\mathit{Speculate}Speculate and it continues at the theorem. Next, the function Manip_Stack\mathit{Manip\_Stack}Manip_Stack is called and the stack pointer sp\mathbf{sp}sp is incremented (the theorem). This modifies the return address of the function Manip_Stack\mathit{Manip\_Stack}Manip_Stack to now point to the theorem (the return address of the call\mathbf{call}call to Speculate\mathit{Speculate}Speculate). Under ghost\mathsf{ghost}ghost, mispredicting the return address of Manip_Stack\mathit{Manip\_Stack}Manip_Stack using the RSB leads to continuing the execution at the theorem. However, the store\mathbf{store}store instructions in the theorem overwrites the secret value stored in the theorem. Then, the load\mathbf{load}load instructions in the theorem and the theorem emit only public values. As a result, no secret is leaked and speculation ends. Similarly, under ghost\mathsf{ghost}ghost, speculation over store bypasses has no effect in because the store\mathbf{store}store instruction in the theorem is never reached and function Manip_Stack\mathit{Manip\_Stack}Manip_Stack returns to the theorem. Therefore, the leak is missed under ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost, i.e., Cref\text{Cref}Cref and Cref\text{Cref}Cref.
However, under the combined semantics ghost\mathsf{ghost}ghost, the store\mathbf{store}store instruction on the theorem is now speculatively bypassed and when returning from function Manip_Stack\mathit{Manip\_Stack}Manip_Stack the execution speculatively continues from the theorem. Now, the load\mathbf{load}load instructions are executed and the secret is leaked, as shown in the traces below. Since secret\mathit{secret}secret is a high value, there are low-equivalent configurations σ1,σ2\sigma^1, \sigma^2σ1,σ2 that differ in the value of secret\mathit{secret}secret. Thus, there are two traces that differs in the observation load secret\textcolor{RoyalBlue}{\mathtt{load}}\ secretload secret (highlighted in gray). Hence, the program is not secure under the combined semantics, i.e., Cref\text{Cref}Cref.
trace\text{trace}
The relation between the source semantics and their composition is visualised in Figure 11, which shows the insecure programs (with respect to SNI) detected under the different semantics. The combined semantics encompasses all vulnerable programs of ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost and additional programs like. These additional programs are the reason why the semantics ghost\mathsf{ghost}ghost is "stronger than the sum of its parts" ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost.
**Figure 11:** Relating $\mathsf{ghost}$, $\mathsf{ghost}$ and $\mathsf{ghost}$ w.r.t. SNI.

Figure 11: Relating ghost\mathsf{ghost}, ghost\mathsf{ghost} and ghost\mathsf{ghost} w.r.t. SNI.

8.2 Spec-B+J+S+R Composition

We conclude this section by combining four semantics ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost (as mentioned, a combination with five semantics is not possible because ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost speculate on the same instruction). Our framework (Section 7) allows us to only combine a pair of source semantics into a combined one. For simplicity, we present ghost\mathsf{ghost}ghost as a direct combination of the four source semantics (technically, we obtain ghost\mathsf{ghost}ghost by combining ghost\mathsf{ghost}ghost with ghost\mathsf{ghost}ghost).
The metaparameter ZB+J+S+RZ_{\mathbf{\textcolor{CarnationPink}{B}} + \textit{\textcolor{BlueGreen}{J}} + \texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}}ZB+J+S+R​ (which we represent as a quadruple of values) is :
ZB=def(call∪ret∪store∪jmp)ZJ=def(call∪ret∪store∪beqz)ZS=def(call∪ret∪beqz∪jmp)ZR=def(beqz∪store∪jmp)ZB+J+S+R=def(ZB,ZJ,ZS,ZR)\begin{aligned} Z_{\mathbf{\textcolor{CarnationPink}{B}}} {\mathrel{\overset{\text{def}}{=}}}& (\mathbf{call} \cup \mathbf{ret} \cup \mathbf{store} \cup \mathbf{jmp}) \\ Z_{\textit{\textcolor{BlueGreen}{J}}} {\mathrel{\overset{\text{def}}{=}}}& (\mathbf{call} \cup \mathbf{ret} \cup \mathbf{store} \cup \mathbf{beqz}) \\ Z_{\texttt{\textcolor{Emerald}{S}}} {\mathrel{\overset{\text{def}}{=}}}& (\mathbf{call} \cup \mathbf{ret} \cup \mathbf{beqz} \cup \mathbf{jmp}) \\ Z_{\mathsf{\textcolor{RedOrange}{R}}} {\mathrel{\overset{\text{def}}{=}}}& (\mathbf{beqz} \cup \mathbf{store} \cup \mathbf{jmp}) \\ Z_{\mathbf{\textcolor{CarnationPink}{B}} + \textit{\textcolor{BlueGreen}{J}} + \texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}} {\mathrel{\overset{\text{def}}{=}}}& (Z_{\mathbf{\textcolor{CarnationPink}{B}}}, Z_{\textit{\textcolor{BlueGreen}{J}}}, Z_{\texttt{\textcolor{Emerald}{S}}}, Z_{\mathsf{\textcolor{RedOrange}{R}}}) \end{aligned}
As a result, the combined semantics ghost\mathsf{ghost}ghost can only delegate to the corresponding speculative semantics for the appropriate speculation sources.
As stated in Theorem 17, ghost\mathsf{ghost}ghost is well-formed and we derive that ghost\mathsf{ghost}ghost is WFSS\mathit{WFSS}WFSS through Theorem 14.

Theorem 17: ghost\mathsf{ghost} is well-formed

ghost\mathsf{ghost}ghost
**Figure 12:** $\mathsf{ghost}$ example.

Figure 12: ghost\mathsf{ghost} example.

Figure 12 depicts a leaky program that can be detected only under ghost\mathsf{ghost}ghost, since the program satisfies SNI under ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost. Under ghost\mathsf{ghost}ghost, the store\mathbf{store}store instruction in the theorem is bypassed. Therefore, when returning from the Manip_Stack\mathit{Manip\_Stack}Manip_Stack function, the program mispredicts the return address and speculatively returns to the theorem. Here, the indirect jump in the theorem mispredicts and execution continues speculatively in the theorem. Finally, the beqz\mathbf{beqz}beqz instruction in the theorem is mispredicted and the load\mathbf{load}load instructions are executed, which leaks the secret value.
The resulting traces, differing in the value of secret exposed by the load secret\textcolor{RoyalBlue}{\mathtt{load}}\ secretload secret observation (highlighted in gray), are given below:
trace\text{trace}
Thus, the program is not secure, i.e., Cref\text{Cref}Cref.

9. Detecting Speculative Information Flows : The Spectector algorithm

This section presents SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR, a program analysis for detecting speculative leaks or proving their absence. The core idea behind SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR is to formally compare a program's behavior under speculative execution against its standard, non-speculative execution. A leak is identified if the speculative execution reveals information that is not revealed by the non-speculative execution. To make this comparison comprehensive, analyzing every possible concrete execution is infeasible. Therefore, Spectector leverages symbolic execution to represent all possible program behaviors concisely as a set of symbolic traces. Our approach requires two key formalisms:
  1. A symbolic non-speculative semantics to establish the program's intended, baseline behavior (Section 9.1).
  2. A symbolic architectural model (AM) semantics to model the processor's speculative behavior (Section 9.2).
By analyzing the symbolic traces generated from both semantics with an SMT solver, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR can identify discrepancies that correspond to memory or control-flow leaks. If no such discrepancies are found, the program is proven secure against the modeled speculative behaviors (Section 9.3). Finally, we discuss the implementation of SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR within the CIAO{\mathchoice{\text{C{\scriptsize IAO}}}{\text{C{\scriptsize IAO}}}{\text{C{\scriptscriptstyle IAO}}}{\text{CIAO}}}CIAO logic programming system [50] (Section 9.4).

9.1 Symbolic Non-Speculative Semantics for uASM

To establish a ground truth for our analysis, we first define the program's intended behavior using a symbolic non-speculative semantics, denoted by the relation ⟨p,σS⟩→τSS⟨p,σS′⟩\langle p, \sigma_{\mathcal{S}} \rangle \xrightarrow{\tau_{\mathcal{S}}}_{\mathcal{S}} \langle p, {\sigma_{\mathcal{S}}}' \rangle⟨p,σS​⟩τS​​S​⟨p,σS​′⟩.
This semantics lifts the concrete non-speculative semantics ⟨p,σ⟩→τ⟨p,σ′⟩\langle p, \sigma \rangle \xrightarrow{\tau} \langle p, \sigma' \rangle⟨p,σ⟩τ​⟨p,σ′⟩ to operate over symbolic values instead of concrete ones. We now detail the key extensions.
Symbolic program states consist of a program ppp and a symbolic configuration σS::=⟨sm,sa⟩\sigma_{\mathcal{S}} \mathrel{::=} \langle sm, sa \rangleσS​::=⟨sm,sa⟩.
Concrete memories mmm are replaced with symbolic memories smsmsm, modeled as symbolic memories using the standard theory of arrays [51]. We model memory updates as triples of the form write(sm,se,se′)\mathbf{write}(sm,se,se')write(sm,se,se′), which update the symbolic memory smsmsm by assigning the symbolic value se′\mathit{se}'se′ to the symbolic location se\mathit{se}se. Memory reads read(sm,se)\mathbf{read}(sm, \mathit{se})read(sm,se) retrieve the value at symbolic memory location se\mathit{se}se in smsmsm. read(sm,se)\mathbf{read}(sm, \mathit{se})read(sm,se) and write(sm,se,se′)\mathbf{write}(sm, \mathit{se},se')write(sm,se,se′) are used in Section 9.1 and Section 9.1 respectively, which is the only difference to the concrete non-speculative semantics. Concrete register assignments aaa are replaced with symbolic register assignments sasasa, which are functions mapping registers to symbolic expressions.
Symbolic expressions represent computations over symbolic values. A symbolic expression se\mathit{se}se is a concrete value n∈Valsn \in \mathit{Vals}n∈Vals, a symbolic value s∈SymbValss \in \mathit{SymbVals}s∈SymbVals, an if-then-else expression ite(se,se′,se′′)\mathbf{ite}(\mathit{se},\mathit{se}',\mathit{se}'')ite(se,se′,se′′), or the application of a unary ⊖\ominus⊖ or a binary operator ⊗\otimes⊗.
se:=n∣s∣ite(se,se′,se′′)∣⊖se∣se⊗se′\mathit{se} := n \mid s \mid \mathbf{ite}(\mathit{se},\mathit{se}',\mathit{se}'') \mid \ominus \mathit{se} \mid \mathit{se} \otimes \mathit{se}'
Most operational rules of →S\xrightarrow{}_{\mathcal{S}}​S​ are straightforward extensions of the concrete semantics, and we omit them. The primary differences w.r.t. the concrete μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM semantics arise when handling memory operations and control-flow statements with symbolic values, which are formalized in the operational semantics rules below.
::: {.visual-block}
:::

rule\text{rule}rule
rule\text{rule}rule
rule\text{rule}rule
rule\text{rule}rule
rule\text{rule}rule
rule\text{rule}rule
When symbolically executing a program, we may produce observations whose values are symbolic. To account for this, we introduce symbolic observations of the form load se\textcolor{RoyalBlue}{\mathtt{load}}\ seload se and store se\textcolor{RoyalBlue}{\mathtt{store}}\ sestore se for symbolic load and store instructions.
Furthermore, because of the symbolic execution, we need to keep track if certain paths in our program are feasible. We encode this information using symPc(se)\textcolor{RoyalBlue}{\mathtt{symPc}}(\mathit{se})symPc(se) observations, which record the choices made at branches and jumps. We can see these observations in action in Section 9.1 and Section 9.1. Because xxx cannot be evaluated to a value, the symbolic semantics decides if the branch is taken or not and records this decision in the observation symPc(sa(x)=0)\textcolor{RoyalBlue}{\mathtt{symPc}}(sa(x) = 0)symPc(sa(x)=0) Without these observations, we could later concretize x to a value unequal to 000 even though the branch was not taken, making the path infeasible in a concrete program execution. To explore all paths of the program, our symbolic tool will negate these symbolic branching observations to explore the other branches as well. The path condition pthCnd(τS‾) ⁣ ⁣= ⁣ ⁣⋀symPc(se)∈τse\mathit{pthCnd}(\overline{\tau_{\mathcal{S}}})\!\!=\!\!\bigwedge_{\textcolor{RoyalBlue}{\mathtt{symPc}}(\mathit{se}) \in \tau} \mathit{se}pthCnd(τS​​)=⋀symPc(se)∈τ​se of trace τ\tauτ is the conjunction of all symbolic branching conditions in τ\tauτ.
The value of a symbolic expression se\mathit{se}se depends on a valuation function μ⁡:SymbVals→Vals\operatorname{\mu}: \mathit{SymbVals} \to \mathit{Vals}μ:SymbVals→Vals mapping symbolic values to concrete ones. The evaluation μ⁡(se)\operatorname{\mu}(se)μ(se) is also standard. We write μ⁡⊨se\operatorname{\mu} \vDash \mathit{se}μ⊨se to denote that symbolic expression se\mathit{se}se is satisfiable for a valuation μ⁡\operatorname{\mu}μ, i.e., μ⁡(se)≠0\operatorname{\mu}(\mathit{se}) \neq 0μ(se)=0. Every valuation that satisfies a symbolic run's path condition maps the symbolic run to a concrete one. Finally, we write ⊨se\vDash \mathit{se}⊨se to denote that there exists a valuation μ⁡\operatorname{\mu}μ such that μ⁡⊨se\operatorname{\mu} \vDash \mathit{se}μ⊨se.
The symbolic non-speculative behaviour BehNSS(p)\mathit{Beh}_{NS}^{\mathcal{S}}(p)BehNSS​(p) of a program ppp is the set of all traces generated by all possible initial states for program ppp.
Theorem 18 connects the symbolic and concrete non-speculative semantics via the concretization function μ⁡\operatorname{\mu}μ:

Theorem 18: NS: Symbolic Consistency

BehNS(p)=μ⁡(BehNSS(p))\mathit{Beh}_{NS}(p) = \operatorname{\mu}(\mathit{Beh}_{NS}^{\mathcal{S}}(p))BehNS​(p)=μ(BehNSS​(p)).
This allows us to use the symbolic non-speculative semantics in our tool SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR with confidence that it behaves equivalently to the concrete non-speculative semantics.

9.2 Symbolic Always-Mispredict Semantics

To enable automated verification, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR implements a symbolic always-mispredict semantics. Structurally, this semantics perfectly mirrors the concrete always-mispredict semantics introduced earlier, with the sole distinction that it operates over symbolic expressions and relies on the symbolic non-speculative step relation →S\xrightarrow{}_{\mathcal{S}}​S​ rather than its concrete counterpart. \IfEqCase{false}{{true}{Thus, we omit details related to this semantics and refer to the technical report [37]}} .
We denote by μ⁡((⟨p,σS⟩)ghostxωτS‾)\operatorname{\mu}({(\langle p,\sigma_{\mathcal{S}}\rangle)}\mathsf{ghost}^{\omega}_{x}{\overline{\tau_{\mathcal{S}}}})μ((⟨p,σS​⟩)ghostxω​τS​​) the set {(⟨p,σS⟩)ghostxω(μ⁡(τS‾))∣μ⊨pthCnd(τS‾)}\{{(\langle p,\sigma_{\mathcal{S}}\rangle)}\mathsf{ghost}^{\omega}_{x}{(\operatorname{\mu}(\overline{\tau_{\mathcal{S}}}))}\mid\mu\vDash\mathit{pthCnd}(\overline{\tau_{\mathcal{S}}})\}{(⟨p,σS​⟩)ghostxω​(μ(τS​​))∣μ⊨pthCnd(τS​​)} and lift it to BehxS(p)\mathit{Beh}^{\mathcal{S}}_{x}(p)BehxS​(p). Here (⟨p,σS⟩)ghostxωτS‾{(\langle p,\sigma_{\mathcal{S}}\rangle)}\mathsf{ghost}^{\omega}_{x}{\overline{\tau_{\mathcal{S}}}}(⟨p,σS​⟩)ghostxω​τS​​ denotes the run of the program ppp with initial configuration σS\sigma_{\mathcal{S}}σS​ generating τS‾\overline{\tau_{\mathcal{S}}}τS​​ for the symbolic always-mispredict semantics xxx.
Symbolic Consisteny
Fundamentally, a valid symbolic analysis must faithfully capture all possible concrete executions of a program. The symbolic always-mispredict semantic should explore the exact same set of execution paths and generate the same observations as its concrete counterpart, merely operating over symbolic values and constraints. We formalize this correctness requirement in Property 19, stating that the concrete always-mispredict behaviour can be exactly recovered from the symbolic behaviour by applying the concretization function.

Property 19: Symbolic Consistency AM

Behxω(p)=μ⁡(BehxS(p))\mathit{Beh}^{\omega}_x(p) = \operatorname{\mu}(\mathit{Beh}^{\mathcal{S}}_{x}(p))Behxω​(p)=μ(BehxS​(p))
Because we have proven that all our speculative semantics and their combinations satisfy the requirements of our framework (i.e., they are well-formed speculative semantics), they inherently satisfy Property 19. This allows us to use all of the symbolic semantics in our tool SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR with confidence that they behave equivalently to the concrete semantics.

Example 20: Symbolic Trace for Example 1

Executing the program from Example 1 under the symbolic speculative semantics ghost\mathsf{ghost}ghost with speculative window 222 yields the following two symbolic traces:
τ1:=symPc(y<size)⋅startB 0⋅pc 2⋅pc 10⋅rlbB 0⋅pc 3⋅load A+y⋅load B+read(sm,(A+y))∗512τ2:=symPc(y≥size)⋅startB 0⋅pc 3⋅load A+y⋅load B+read(sm,(A+y))∗512⋅rlbB 0⋅pc 2⋅pc 10\begin{aligned} \tau_1 := \textcolor{RoyalBlue}{\mathtt{symPc}}({\mathtt{y}} < {\mathtt{size}}) \cdot \textcolor{RoyalBlue}{\mathtt{start}}_{\mathbf{\textcolor{CarnationPink}{B}}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 2 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 10 \cdot \textcolor{RoyalBlue}{\mathtt{rlb}}_{\mathbf{\textcolor{CarnationPink}{B}}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 3 \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ {\mathtt{A}} + {\mathtt{y}} \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ {\mathtt{B}} + \mathbf{read}(sm, ({\mathtt{A}} + {\mathtt{y}}) )*512 \\ \tau_2 := \textcolor{RoyalBlue}{\mathtt{symPc}}({\mathtt{y}} \geq {\mathtt{size}}) \cdot \textcolor{RoyalBlue}{\mathtt{start}}_{\mathbf{\textcolor{CarnationPink}{B}}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 3 \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ {\mathtt{A}} + {\mathtt{y}} \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ {\mathtt{B}} + \mathbf{read}(sm, ({\mathtt{A}} + {\mathtt{y}}) )*512 \cdot \textcolor{RoyalBlue}{\mathtt{rlb}}_{\mathbf{\textcolor{CarnationPink}{B}}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 2 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 10 \end{aligned}

9.3 The Spectector Algorithm

Algorithm 1: SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}} program analysis

Require: A program SecureSecure, a security policy InsecureInsecure, a speculative window SpectectorSpectector.
0Ensure: SecureSecure if InsecureInsecure satisfies speculative non-interference with respect to the policy SecureSecure and speculative semantics ghostx\mathsf{ghost}_{x}; InsecureInsecure otherwise
1procedure SpectectorSpectector(p,P,wp, P,w)
2for each symbolic run τ‾∈BehxS(p)\overline{\tau} \in \mathit{Beh}^{\mathcal{S}}_{x}(p) do
3  if MEMLEAK(τ‾,P)∨CTRLLEAK(τ‾,P){\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}}(\overline{\tau},P) \vee {\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}}(\overline{\tau},P) then
4    return{InsecureInsecure}
5  end if
6end for
7return{SecureSecure}
8end procedure
9procedure MEMLEAK{\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}} (τ‾,P\overline{\tau}, P)
10ψ←pthCnd(τ‾)1∧2∧polEqv(P)∧\psi \gets \mathit{pthCnd}(\overline{\tau})_{1 \wedge 2} \wedge \mathit{polEqv}(P) \wedge
11obsEqv(τ‾↾ns)∧¬obsEqv(τ‾↾se)\qquad \qquad \mathit{obsEqv}(\overline{\tau}\mathord{\upharpoonright_{ns}}) \wedge \neg \mathit{obsEqv}(\overline{\tau}\mathord{\upharpoonright_{se}})
12return{SATISFIABLE(ψ){\mathchoice{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptscriptstyle ATISFIABLE}}}{\text{SATISFIABLE}}}(\psi)}
13end procedure
14procedure CTRLLEAK{\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}} (τ‾,P\overline{\tau}, P)
15for each prefix ν⋅symPc(se)\nu \cdot \textcolor{RoyalBlue}{\mathtt{symPc}}(\mathit{se}) of τ‾↾se\overline{\tau}\mathord{\upharpoonright_{se}} do
16  ψ←pthCnd(τ‾↾ns⋅ν)1∧2∧polEqv(P)∧\psi \gets \mathit{pthCnd}(\overline{\tau}\mathord{\upharpoonright_{ns}}\cdot \nu)_{1 \wedge 2} \wedge \mathit{polEqv}(P) \wedge
17  obsEqv(τ‾↾ns)∧¬sameSymbPc(se)\qquad \qquad \quad \mathit{obsEqv}(\overline{\tau}\mathord{\upharpoonright_{ns}}) \wedge \neg \mathit{sameSymbPc}(se)
18  if SATISFIABLE(ψ){\mathchoice{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptscriptstyle ATISFIABLE}}}{\text{SATISFIABLE}}}(\psi) then
19    return{⊤\top}
20  end if
21end for
22return{⊥\bot}
23end procedure
The SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR program analysis approach is presented in Algorithm 1. It relies on two procedures: MEMLEAK{\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}}MEMLEAK and CTRLLEAK{\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}}CTRLLEAK, to detect leaks resulting from memory and control-flow instructions, respectively. We start by discussing the SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR algorithm and next explain the MEMLEAK{\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}}MEMLEAK and CTRLLEAK{\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}}CTRLLEAK procedures.
SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR takes as input a program ppp, a policy PPP specifying the non-sensitive information, and a speculative window www. The algorithm iterates over all symbolic runs produced by the symbolic always-mispredict speculative semantics (lines 2-4). For each trace τ‾∈BehxS(p)\overline{\tau} \in \mathit{Beh}^{\mathcal{S}}_{x}(p)τ∈BehxS​(p), the algorithm checks whether τ‾\overline{\tau}τ speculatively leaks information through memory accesses or control-flow instructions. If this is the case, then SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR has found a witness of a speculative leak and it reports ppp as INSECURE{\mathchoice{\text{I{\scriptsize NSECURE}}}{\text{I{\scriptsize NSECURE}}}{\text{I{\scriptscriptstyle NSECURE}}}{\text{INSECURE}}}INSECURE. If none of the traces contains speculative leaks, the algorithm terminates returning SECURE{\mathchoice{\text{S{\scriptsize ECURE}}}{\text{S{\scriptsize ECURE}}}{\text{S{\scriptscriptstyle ECURE}}}{\text{SECURE}}}SECURE (line 5).

Detecting leaks caused by memory accesses

The procedure MEMLEAK{\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}}MEMLEAK takes as input a trace τ‾\overline{\tau}τ and a policy PPP, and it determines whether τ‾\overline{\tau}τ leaks information through symbolic load\textcolor{RoyalBlue}{\mathtt{load}}load and store\textcolor{RoyalBlue}{\mathtt{store}}store observations. The check is expressed as a satisfiability check of a constraint ψ\psiψ. The construction of ψ\psiψ is inspired by self-composition [52], which reduces reasoning about pairs of program runs to reasoning about single runs by replacing each symbolic variable xxx with two copies x1x_1x1​ and x2x_2x2​. We lift the subscript notation to symbolic expressions.
The constraint ψ\psiψ is the conjunction of four formulas:
  • pthCnd(τ)1∧2\mathit{pthCnd}(\tau)_{1 \wedge 2}pthCnd(τ)1∧2​ stands for pthCnd(τ‾)1∧pthCnd(τ‾)2\mathit{pthCnd}(\overline{\tau})_{1} \wedge \mathit{pthCnd}(\overline{\tau})_{2}pthCnd(τ)1​∧pthCnd(τ)2​, which ensures that both runs follow the path associated with τ‾\overline{\tau}τ.
  • polEqv(P)\mathit{polEqv}(P)polEqv(P) introduces constraints x1=x2x_1 = x_2x1​=x2​ for each register x∈Px\in Px∈P and read(sm1,n)=read(sm2,n)\mathbf{read}(sm_1,n) = \mathbf{read}(sm_2,n)read(sm1​,n)=read(sm2​,n) for each memory location n∈Pn \in Pn∈P, which ensure that both runs agree on all non-sensitive inputs.
  • obsEqv(τ‾↾ns)\mathit{obsEqv}(\overline{\tau}\mathord{\upharpoonright_{ns}})obsEqv(τ↾ns​) introduces a constraint se1=se2\mathit{se}_1 = \mathit{se}_2se1​=se2​ for each load se\textcolor{RoyalBlue}{\mathtt{load}}\ \mathit{se}load se or store se\textcolor{RoyalBlue}{\mathtt{store}}\ \mathit{se}store se in τ↾ns\tau\mathord{\upharpoonright_{ns}}τ↾ns​, which ensures that the non-speculative observations associated with memory accesses are the same in both runs.
  • ¬obsEqv(τ‾↾se)\neg \mathit{obsEqv}(\overline{\tau}\mathord{\upharpoonright_{se}})¬obsEqv(τ↾se​) ensures that at least one speculative observation associated with memory accesses differs among the two runs.
If ψ\psiψ is satisfiable, there are two PPP-indistinguishable configurations that produce the same non-speculative traces (since pthCnd(τ‾)1∧2∧polEqv(P)∧obsEqv(τ‾↾ns)\mathit{pthCnd}(\overline{\tau})_{1 \wedge 2} \wedge \mathit{polEqv}(P) \wedge \mathit{obsEqv}(\overline{\tau}\mathord{\upharpoonright_{ns}})pthCnd(τ)1∧2​∧polEqv(P)∧obsEqv(τ↾ns​) is satisfied) and whose speculative traces differ in a memory access observation (since ¬obsEqv(τ‾↾se)\neg \mathit{obsEqv}(\overline{\tau}\mathord{\upharpoonright_{se}})¬obsEqv(τ↾se​) is satisfied), i.e. a violation of SNI.

Detecting leaks caused by control-flow instructions

To detect leaks caused by control-flow instructions, CTRLLEAK{\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}}CTRLLEAK checks whether there are two traces in τ\tauτ's concretization that agree on the outcomes of all non-speculative branch and jump instructions, while differing in the outcome of at least one speculatively executed branch or jump instruction.
In addition to pthCnd(τ‾)\mathit{pthCnd}(\overline{\tau})pthCnd(τ), obsEqv(τ‾)\mathit{obsEqv}(\overline{\tau})obsEqv(τ), and polEqv(P)\mathit{polEqv}(P)polEqv(P), the procedure relies on the function sameSymbPc(se)\mathit{sameSymbPc}(\mathit{se})sameSymbPc(se) that introduces the constraint se1↔se2\mathit{se}_1 \leftrightarrow \mathit{se}_2se1​↔se2​ ensuring that se\mathit{se}se is satisfied in one concretization iff it is satisfied in the other.
CTRLLEAK{\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}}CTRLLEAK checks, for each prefix ν⋅symPc(se)\nu \cdot \textcolor{RoyalBlue}{\mathtt{symPc}}(\mathit{se})ν⋅symPc(se) in τ‾\overline{\tau}τ's speculative projection τ‾↾se\overline{\tau}\mathord{\upharpoonright_{se}}τ↾se​, the satisfiability of the conjunction of pthCnd(τ‾↾ns⋅ν)1∧2\mathit{pthCnd}(\overline{\tau}\mathord{\upharpoonright_{ns}} \cdot \nu)_{1 \wedge 2}pthCnd(τ↾ns​⋅ν)1∧2​, polEqv(P)\mathit{polEqv}(P)polEqv(P), obsEqv(τ‾↾ns)\mathit{obsEqv}(\overline{\tau}\mathord{\upharpoonright_{ns}})obsEqv(τ↾ns​), and ¬sameSymbPc(se)\neg \mathit{sameSymbPc}(\mathit{se})¬sameSymbPc(se). Whenever the formula is satisfiable, there are two PPP-indistinguishable configurations that produce the same non-speculative traces, but whose speculative traces differ on program counter observations, i.e. a violation of SNI.

Example: Example Application of Spectector

Consider the trace from Example 20:
τ‾:=symPc(y≥size)⋅startB 0⋅pc 3⋅load A+y⋅load B+read(sm,(A+y))∗512⋅rlbB 0⋅pc 2⋅pc 10\overline{\tau} := \textcolor{RoyalBlue}{\mathtt{symPc}}({\mathtt{y}} \geq {\mathtt{size}}) \cdot \textcolor{RoyalBlue}{\mathtt{start}}_{\mathbf{\textcolor{CarnationPink}{B}}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 3 \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ {\mathtt{A}} + {\mathtt{y}} \cdot \textcolor{RoyalBlue}{\mathtt{load}}\ {\mathtt{B}} + \mathbf{read}(sm, ({\mathtt{A}} + {\mathtt{y}}) )*512 \cdot \textcolor{RoyalBlue}{\mathtt{rlb}}_{\mathbf{\textcolor{CarnationPink}{B}}}\ 0 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 2 \cdot \textcolor{RoyalBlue}{\mathtt{pc}}\ 10
MEMLEAK{\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}}MEMLEAK detects a leak caused by the observation load B+read(sm,(A+y))∗512\textcolor{RoyalBlue}{\mathtt{load}}\ {\mathtt{B}} + \mathbf{read}(sm, ({\mathtt{A}} + {\mathtt{y}}) )*512load B+read(sm,(A+y))∗512. Specifically, it detects that there are distinct symbolic valuations that agree on the non-speculative observations but disagree on the value of load B+read(sm,(A+y))∗512\textcolor{RoyalBlue}{\mathtt{load}}\ {\mathtt{B}} + \mathbf{read}(sm, ({\mathtt{A}} + {\mathtt{y}}) )*512load B+read(sm,(A+y))∗512. That is, the observation depends on sensitive information that is not disclosed by τ‾\overline{\tau}τ's non-speculative projection.

Soundness and Completeness

Theorem 21 states that SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR deems secure only speculatively non-interferent programs, and all detected leaks are actual violations of SNI.

Theorem 21: Correctness Spectector

If SPECTECTOR(p,P,w){\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}(p, P,w)SPECTECTOR(p,P,w) terminates, then SPECTECTOR(p,P,w)=SECURE{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}(p, P,w) = {\mathchoice{\text{S{\scriptsize ECURE}}}{\text{S{\scriptsize ECURE}}}{\text{S{\scriptscriptstyle ECURE}}}{\text{SECURE}}}SPECTECTOR(p,P,w)=SECURE iff the program ppp satisfies speculative non-interference w.r.t. the policy PPP and all prediction oracles O{\mathcal{O}}O with speculative window at most www.
The theorem follows from Oracle Overapproximation and Symbolic Consistency of the speculative semantics. Importantly, both conditions are part of our well-formed speculative semantics definition (Definition 10). Since ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost are well-formed speculative semantics ghost\mathsf{ghost}ghost and our combinations are well-formed (Definition 13), we have that all the combinations are WFSS\mathit{WFSS}WFSS as well. Thus, we get Theorem 21 for free for all the combinations.

9.4 Spectector Implementation

We implement our approach in our tool SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR, which is available at [36]. The tool, which is implemented on top of the CIAO{\mathchoice{\text{C{\scriptsize IAO}}}{\text{C{\scriptsize IAO}}}{\text{C{\scriptscriptstyle IAO}}}{\text{CIAO}}}CIAO logic programming system [50], consists of three components: a front end that translates x86 assembly programs into μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM, a core engine implementing Algorithm 1, and a back end handling SMT queries.

x86 Front End

The front end translates AT&T/GAS and Intel-style assembly files into μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM. It currently supports over 120 instructions: data movement instructions (mov\mathbf{mov}mov, etc.), logical, arithmetic, and comparison instructions (xor\mathbf{xor}xor, add\mathbf{add}add, cmp\mathbf{cmp}cmp, etc.), branching and jumping instructions (jae\mathbf{jae}jae, jmp\mathbf{jmp}jmp, etc.), conditional moves (cmovae\mathbf{cmovae}cmovae, etc.), stack manipulation (push\mathbf{push}push, pop\mathbf{pop}pop, etc.), and function calls6 (call\mathbf{call}call, ret\mathbf{ret}ret).
6.
We model the so-called "near calls", where the callee is in the same code segment as the caller.
It currently does not support privileged x86 instructions, e.g., for handling model specific registers and virtual memory. Further, it does not support sub-registers (like eax\mathtt{eax}eax, ah\mathtt{ah}ah, and al\mathtt{al}al) and unaligned memory accesses, i.e., we assume that only 64-bit words are read/written at each address without overlaps. Finally, the translation currently maps symbolic address names to μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM instruction addresses, limiting arithmetic on code addresses.

Core Engine

The core engine implements Algorithm 1. It relies on a concolic approach to implement symbolic execution that performs a depth-first exploration of the symbolic runs. Starting from a concrete initial configuration, the engine executes the program under the symbolic always-mispredict speculative semantics while keeping track of the symbolic configuration and path condition. It discovers new runs by iteratively negating the last (not previously negated) conjunct in the path condition until it finds a new initial configuration, which is then used to re-execute the program concolically. In our current implementation, indirect jumps are not included in the path conditions, and thus new symbolic runs and corresponding inputs are only discovered based on negated branch conditions.7 This process is interleaved with the MEMLEAK{\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}}MEMLEAK and CTRLLEAK{\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}}CTRLLEAK checks and iterates until a leak is found or all paths have been explored.
7.
We plan to remove this limitation in a future release of our tool.

SMT Back End

The Z3 SMT solver [39] acts as a back end for checking satisfiability and finding models of symbolic expressions using the BITVECTOR{\mathchoice{\text{B{\scriptsize ITVECTOR}}}{\text{B{\scriptsize ITVECTOR}}}{\text{B{\scriptscriptstyle ITVECTOR}}}{\text{BITVECTOR}}}BITVECTOR and ARRAY{\mathchoice{\text{A{\scriptsize RRAY}}}{\text{A{\scriptsize RRAY}}}{\text{A{\scriptscriptstyle RRAY}}}{\text{ARRAY}}}ARRAY theories, which are used to model registers and memory. The implementation currently does not rely on incremental solving, since it was less efficient than one-shot solving for the selected theories.

Implementation of the Speculative Semantics and the Combinations in Spectector

We implemented all our semantics (the symbolic versions of ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost plus all 18 compositions from Section 8) in SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR. The implementation of compositions closely follows the structure of our framework. As in Section 8, selecting one of the composed semantics in SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR sets the metaparameter Z, which is used to delegate back to the correct individual semantics.

10. Evaluation

This section reports on two case studies in which we apply SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR to analyze the security of programs. The goals of the first case study are (1) to determine whether speculative non-interference realistically captures speculative leaks and (2) to assess SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR ’s precision Therefore, we analyze various examples targeting the different Spectre versions we want to capture with our speculative semantics (Section 10.1).
The goal of our second case study is to investigate if the combined speculative semantics allow us to capture stronger attacks that are not captured by individual semantics. Thus, we create code snippets that are only exploitable using a combination of different Spectre attacks and check if SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR using the combined semantics can detect leaks (Section 10.2).
All code snippets as well as all scripts to reproduce our results are available in our public repository at https://spectector.github.io/.

10.1 Case Study: Detecting Leaks w.r.t. Individual Speculative Semantics

Using SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR, we analyze a corpus of 41 microbenchmarks containing speculative leaks generated by different speculation mechanisms in isolation (Section 6). With these experiments, we aim to show that speculative non-interference and our individual speculative semantics can correctly identify speculative leaks associated with speculation over branches, indirect jumps, store-bypasses and return instructions.

10.1.1 Benchmarks

We start from 41 snippets of code containing leaks resulting from speculation over beqz\mathbf{beqz}beqz, store\mathbf{store}store, load\mathbf{load}load, jmp\mathbf{jmp}jmp, and ret\mathbf{ret}ret instructions (and their combinations). We compile these snippets using various compilers, compiler options, and mitigations, thereby obtaining a corpus of 291 x64 assembly programs, which we analyse with SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR. Next, we describe next in detail the composition of our benchmark corpus:
  • Spectre-PHT: 15 snippets are variants of the Spectre-PHT vulnerability by Kocher [33]. For each of the 15 snippets, we analyse the assembly programs obtained using different compilers and compiler options. For compilers, we rely on three state-of-the-art compilers: Microsoft VISUAL C++{\mathchoice{\text{V{\scriptsize ISUAL} C++}}{\text{V{\scriptsize ISUAL} C++}}{\text{V{\scriptscriptstyle ISUAL} C++}}{\text{VISUAL C++}}}VISUAL C++ versions v19.15.26732.1 and v19.20.27317.96, Intel ICC{\mathchoice{\text{I{\scriptsize CC}}}{\text{I{\scriptsize CC}}}{\text{I{\scriptscriptstyle CC}}}{\text{ICC}}}ICC v19.0.0.117, and CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG v7.0.0 and compile each snippet using two different optimization levels (-O0 and -O2) and three mitigation levels:
    1. UNP{\mathchoice{\text{U{\scriptsize NP}}}{\text{U{\scriptsize NP}}}{\text{U{\scriptscriptstyle NP}}}{\text{UNP}}}UNP: we compile without any SPECTRE{\mathchoice{\text{S{\scriptsize PECTRE}}}{\text{S{\scriptsize PECTRE}}}{\text{S{\scriptscriptstyle PECTRE}}}{\text{SPECTRE}}}SPECTRE mitigations. (b) FEN{\mathchoice{\text{F{\scriptsize EN}}}{\text{F{\scriptsize EN}}}{\text{F{\scriptscriptstyle EN}}}{\text{FEN}}}FEN: we compile with automated injection of speculation barriers.8 (c) SLH{\mathchoice{\text{S{\scriptsize LH}}}{\text{S{\scriptsize LH}}}{\text{S{\scriptscriptstyle LH}}}{\text{SLH}}}SLH: we compile using speculative load hardening.9
8.
Fences are supported by CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}} with the flag -x86-speculative\-load-hardening-lfence, by ICC{\mathchoice{\text{I{\scriptsize CC}}}{\text{I{\scriptsize CC}}}{\text{I{\scriptscriptstyle CC}}}{\text{ICC}}} with -mconditional\-branch=all-fix, and by VISUAL C++{\mathchoice{\text{V{\scriptsize ISUAL} C++}}{\text{V{\scriptsize ISUAL} C++}}{\text{V{\scriptscriptstyle ISUAL} C++}}{\text{VISUAL C++}}} with /Qspectre.
9.
Speculative load hardening is supported by CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}} with the flag -x86-speculative-load-hardening.
Compiling each of the 15 examples from [33] with each of the 3 compilers, each of the 2 optimization levels, and each of the 2-3 mitigation levels, yields a corpus of 240 x64 assembly programs. For each program, we specify a security policy that flags as "low" all registers and memory locations that can either be controlled by the adversary or can be assumed to be public. This includes variables y and size, and the base addresses of the arrays A\texttt{A}A and B\texttt{B}B as well as the stack pointer.
  • Spectre-BTB: 2 snippets are variants of the SPECTRE-BTB{\mathchoice{\text{S{\scriptsize PECTRE}-B{\scriptsize TB}}}{\text{S{\scriptsize PECTRE}-B{\scriptsize TB}}}{\text{S{\scriptscriptstyle PECTRE}-B{\scriptscriptstyle TB}}}{\text{SPECTRE-BTB}}}SPECTRE-BTB vulnerability. They exploit speculation over indirect jump instructions and were created by ourselves. For each snippet, we also analyze manually patched versions obtained by inserting LFENCE{\mathchoice{\text{L{\scriptsize FENCE}}}{\text{L{\scriptsize FENCE}}}{\text{L{\scriptscriptstyle FENCE}}}{\text{LFENCE}}}LFENCE s after every ENDBR{\mathchoice{\text{E{\scriptsize NDBR}}}{\text{E{\scriptsize NDBR}}}{\text{E{\scriptscriptstyle NDBR}}}{\text{ENDBR}}}ENDBR instruction and automatically patched versions using the retpoline [53] countermeasure.10 This results in a corpus of 6 x64 assembly programs.
10.
Retpoline is supported by GCC{\mathchoice{\text{G{\scriptsize CC}}}{\text{G{\scriptsize CC}}}{\text{G{\scriptscriptstyle CC}}}{\text{GCC}}} with the flag -mindirect-branch=thunk.
To make the analysis tractable, we use the endbr instruction for CFI (see Section 6.5). Note that these endbr instructions were automatically added by the compiler.
  • Spectre-STL: 13 snippets are variants of the Spectre-STL vulnerability. They exploit speculation over memory disambiguation, and they have been used as benchmarks in prior work [16, 30]. For each snippet, we also analyze a patched version where a manually inserted LFENCE{\mathchoice{\text{L{\scriptsize FENCE}}}{\text{L{\scriptsize FENCE}}}{\text{L{\scriptscriptstyle FENCE}}}{\text{LFENCE}}}LFENCE instruction stops speculation over store-bypasses and prevents the leak. This results in a corpus of 26 x64 assembly programs.
  • Spectre-RSB: 5 snippets are variants of the Spectre-RSB vulnerability. They exploit speculation over return instructions, and they are obtained from the safeside [54] and transientfail [55] projects11. For each snippet, we also analyze manually patched versions obtained by (1) inserting LFENCE{\mathchoice{\text{L{\scriptsize FENCE}}}{\text{L{\scriptsize FENCE}}}{\text{L{\scriptscriptstyle FENCE}}}{\text{LFENCE}}}LFENCE s after call instructions (i.e., at the instruction address where ret\mathbf{ret}ret speculatively returns), and (2) using the modified retpoline defense proposed in ([3], Section 6.1). This results in a corpus of 15 x64 assembly programs.
  • Spectre-SLS: 2 snippets are variants of the Spectre-SLS vulnerability. They exploit speculation over return instructions and were created by ourselves.
11.
Out of the three Spectre-RSB examples from safeside [54], we analyze the only one that works against an acyclic RSB like the one supported by ghostR{\mathsf{ghost}_{\mathsf{\textcolor{RedOrange}{R}}}}. Programs ca_ip, ca_oop, and sa_ip from transientfail [55] rely on concurrent execution. Since SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}} does not support concurrency, we hardcode the worst-case interleaving in terms of speculative leakage in our benchmark.
For each snippets, we also analyze a manually patched version obtained by inserting LFENCE{\mathchoice{\text{L{\scriptsize FENCE}}}{\text{L{\scriptsize FENCE}}}{\text{L{\scriptscriptstyle FENCE}}}{\text{LFENCE}}}LFENCE s after every return instruction, resulting in a corpus of 4 x64 assembly programs.12
12.
We note that compilers like CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}} have the option mharden-sls-all to automatically protect the code. However, this countermeasure inserts an int3 instruction after every return on x86. Since interrupts and exceptions are not handled by SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}, they cannot be translated to μ\mu ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}. An lfence behaves similarly in this case.

10.1.2 Experimental Setup

The benchmarks for Spectre-PHT are compiled as described in the section above. The benchmarks for Spectre-STL, Spectre-RSB, and Spectre-SLS are implemented in C and compiled with GCC{\mathchoice{\text{G{\scriptsize CC}}}{\text{G{\scriptsize CC}}}{\text{G{\scriptscriptstyle CC}}}{\text{GCC}}}GCC 11.1.0 and we manually inserted lfence/modified retpoline countermeasures in the patched versions. The benchmarks for Spectre-BTI are also implemented in C and lfences were inserted manually while retpoline was added automatically by the compiler into the patched programs.
The benchmarks for Spectre-PHT were run on a Linux machine (kernel 4.9.0-8amd64) with Debian 9.0, a Xeon Gold 6154 CPU, and 64 GB of RAM. All other experiments were run on a laptop with a Dual Core Intel Core i5-7200U CPU and 8GB of RAM.
**Figure 13:** Analysis of Kocher's examples [33], compiled with different compilers and options. For each of the 15 examples, we analyzed the unpatched version (denoted by $\textsc{Unp}$), the version patched with speculation barriers (denoted by $\textsc{Fen}$), and the version patched using speculative load hardening (denoted by $\textsc{Slh}$). Programs have been compiled without optimizations (`-O0`) or with compiler optimizations (`-O2`) using the compilers $\textsc{Visual C++}$ (two versions), $\textsc{Icc}$, and $\textsc{Clang}$. $\circ$ denotes that $\textsc{Spectector}$ detects a speculative leak, whereas ${\color{black}\bullet}\mathllap{\circ}$ indicates that $\textsc{Spectector}$ proves the program secure.

Figure 13: Analysis of Kocher's examples [33], compiled with different compilers and options. For each of the 15 examples, we analyzed the unpatched version (denoted by UNP{\mathchoice{\text{U{\scriptsize NP}}}{\text{U{\scriptsize NP}}}{\text{U{\scriptscriptstyle NP}}}{\text{UNP}}}), the version patched with speculation barriers (denoted by FEN{\mathchoice{\text{F{\scriptsize EN}}}{\text{F{\scriptsize EN}}}{\text{F{\scriptscriptstyle EN}}}{\text{FEN}}}), and the version patched using speculative load hardening (denoted by SLH{\mathchoice{\text{S{\scriptsize LH}}}{\text{S{\scriptsize LH}}}{\text{S{\scriptscriptstyle LH}}}{\text{SLH}}}). Programs have been compiled without optimizations (-O0) or with compiler optimizations (-O2) using the compilers VISUAL C++{\mathchoice{\text{V{\scriptsize ISUAL} C++}}{\text{V{\scriptsize ISUAL} C++}}{\text{V{\scriptscriptstyle ISUAL} C++}}{\text{VISUAL C++}}} (two versions), ICC{\mathchoice{\text{I{\scriptsize CC}}}{\text{I{\scriptsize CC}}}{\text{I{\scriptscriptstyle CC}}}{\text{ICC}}}, and CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}. ∘\circ denotes that SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}} detects a speculative leak, whereas ∙∘{\color{black}\bullet}\mathllap{\circ} indicates that SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}} proves the program secure.

10.1.3 Results for Spectre-PHT

Figure 13 depicts the results of applying SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR to the 240 Spectre-PHT examples. We highlight the following findings:
  • SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR detects the speculative leaks in almost all unprotected programs, for all compilers (see the UNP{\mathchoice{\text{U{\scriptsize NP}}}{\text{U{\scriptsize NP}}}{\text{U{\scriptscriptstyle NP}}}{\text{UNP}}}UNP columns). The exception is Example #8, which uses a conditional expression instead of the if statement of:
temp &= B[A[y<size?(y+1):0]*512];
At optimization level -O0, this is translated to a (vulnerable) branch instruction by all compilers, and at level -O2 to a (safe) conditional move, thus closing the leak. See Appendix A.1 for the corresponding CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG assembly.
  • The CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG and Intel ICC{\mathchoice{\text{I{\scriptsize CC}}}{\text{I{\scriptsize CC}}}{\text{I{\scriptscriptstyle CC}}}{\text{ICC}}}ICC compilers defensively insert fences after each branch instruction, and SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR can prove security for all cases (see the FEN{\mathchoice{\text{F{\scriptsize EN}}}{\text{F{\scriptsize EN}}}{\text{F{\scriptscriptstyle EN}}}{\text{FEN}}}FEN columns for CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG and ICC{\mathchoice{\text{I{\scriptsize CC}}}{\text{I{\scriptsize CC}}}{\text{I{\scriptscriptstyle CC}}}{\text{ICC}}}ICC). In Example #8 with options -O2 and FEN{\mathchoice{\text{F{\scriptsize EN}}}{\text{F{\scriptsize EN}}}{\text{F{\scriptscriptstyle EN}}}{\text{FEN}}}FEN, ICC{\mathchoice{\text{I{\scriptsize CC}}}{\text{I{\scriptsize CC}}}{\text{I{\scriptscriptstyle CC}}}{\text{ICC}}}ICC inserts an lfence instruction, even though the baseline relies on a conditional move, see line 10 below. This lfence is unnecessary according to our semantics, but may close leaks on processors that speculate over conditional moves.
mov y, % lea 1(% mov size, % xor % cmp % cmovb % mov temp, % mov A(% shl $9, % lfence and B(% mov %
  • For the VISUAL C++{\mathchoice{\text{V{\scriptsize ISUAL} C++}}{\text{V{\scriptsize ISUAL} C++}}{\text{V{\scriptscriptstyle ISUAL} C++}}{\text{VISUAL C++}}}VISUAL C++ compiler, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR automatically detects all leaks pointed out in [33] (see the FEN{\mathchoice{\text{F{\scriptsize EN}}}{\text{F{\scriptsize EN}}}{\text{F{\scriptscriptstyle EN}}}{\text{FEN}}}FEN 19.15 -O2 column for VCC{\mathchoice{\text{V{\scriptsize CC}}}{\text{V{\scriptsize CC}}}{\text{V{\scriptscriptstyle CC}}}{\text{VCC}}}VCC). Our analysis differs from Kocher's only on Example #8, where the compiler v19.15.26732.1 introduces a safe conditional move, as explained above. Moreover, without compiler optimizations (which is not considered in [33]), SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR establishes the security of Examples #3 and #5 (see the FEN{\mathchoice{\text{F{\scriptsize EN}}}{\text{F{\scriptsize EN}}}{\text{F{\scriptscriptstyle EN}}}{\text{FEN}}}FEN 19.15 -O0 column). The latest VCC{\mathchoice{\text{V{\scriptsize CC}}}{\text{V{\scriptsize CC}}}{\text{V{\scriptscriptstyle CC}}}{\text{VCC}}}VCC compiler additionally mitigates the leaks in Examples #4, #12, and #14 (see the FEN{\mathchoice{\text{F{\scriptsize EN}}}{\text{F{\scriptsize EN}}}{\text{F{\scriptscriptstyle EN}}}{\text{FEN}}}FEN 19.20 column).
  • SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR can prove the security of speculative load hardening in Clang (see the SLH{\mathchoice{\text{S{\scriptsize LH}}}{\text{S{\scriptsize LH}}}{\text{S{\scriptscriptstyle LH}}}{\text{SLH}}}SLH column for CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG), except for Example #10 with -O2 and Example #15 with -O0.

Example 10 with Speculative Load Hardening

Example #10 differs from in that it leaks sensitive information into the microarchitectural state by conditionally reading the content of B[0], depending on the value of A[y].
if (y < size) if (A[y] == k) temp &= B[0];
SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR proves the security of the program produced with CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG -O0 and speculative load hardening.
However, at optimization level -O2, CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG outputs the following code that SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR reports as insecure.
mov size, % mov y, % mov $0, % cmp % jbe END cmovbe $-1, % or % mov k, % cmp % jne END cmovne$-1, % mov B, % and % jmp END
The reason for this is that CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG masks only the register %rbx that contains the index of the memory access A[y], cf. lines 6–7. However, it does not mask the value that is read from A[y]. As a result, the comparison at line 9 speculatively leaks (via the jump target) whether the content of A[``0xFF...FF``] is k. SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR detects this subtle leak and flags a violation of speculative non-interference.
While this example nicely illustrates the scope of SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR, it is likely not a problem in practice: First, the leak may be mitigated by how data dependencies are handled in modern out-of-order CPUs. Specifically, the conditional move in line 6 relies on the comparison in Line 4. If executing the conditional leak effectively terminates speculation, the reported leak is spurious. Second, the leak can be mitigated at the OS-level by ensuring that 0xFF...FF is not mapped in the page tables, or that the value of A[``0xFF...FF``] does not contain any secret. Such contextual information can be expressed with policies (see Section 5.1) to improve the precision of the analysis.
Note: Personal Communication with C. Marinas
\begin{figure*} \begin{subtable}[t]{.45\linewidth} \vspace{0pt} \centering \begin{tabular}{llccc} \toprule \multirow{2}{*}{Test case} & & \multicolumn{2}{c}{$ {\mathrightghost_{\texttt{\textcolor{Emerald}{S}}}}$} \\ \cline{3-4} & & None & Fence \\ \midrule case01 &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case02 &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case03 & (\textcolor{PineGreen}{S}) & ${\color{black}\bullet}\mathllap{\circ}$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case04 & (\textcolor{red}{I})& $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case05 &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case06 &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case07 &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case08 &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case09& (\textcolor{PineGreen}{S}) & ${\color{black}\bullet}\mathllap{\circ}$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case10 &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case11 &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case12 &(\textcolor{PineGreen}{S}) & ${\color{black}\bullet}\mathllap{\circ}$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ case13 & (\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ \midrule \end{tabular} \vspace{-5pt} \subcaption{Results for the Spectre-STL programs under the $ {\mathrightghost_{\texttt{\textcolor{Emerald}{S}}}}$ semantics against unpatched programs (column "None") and programs patched with \texttt{lfence} (column "Fence").} \label{t:table-v4} \end{subtable} \hspace{2em} \begin{subtable}[t]{.45\linewidth} \centering \vspace{0pt} \begin{tabular}{llcccc} \toprule \multirow{2}{*}{Test case} & & \multicolumn{3}{c}{$ {\mathrightghost_{\mathsf{\textcolor{RedOrange}{R}}}}$} \\ \cline{3-5} & & None & Fence & Mod. Retpoline \\ \midrule $ret2spec\_c\_d$ &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ $ca\_ip$ & (\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ $ca\_oop$ & (\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ $sa\_ip$ &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ $sa\_oop$ & (\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ \bottomrule \end{tabular} \vspace{-5pt} \subcaption{Results for the Spectre-RSB programs under the $ {\mathrightghost_{\mathsf{\textcolor{RedOrange}{R}}}}$ semantics against unpatched programs (column "None"), programs patched with \texttt{lfence} (column "Fence"), and programs patched with the modified \texttt{retpoline} defense proposed in ([3], S6.1) (column "Mod. Retpoline").} \label{t:table-v5} \end{subtable} \begin{subtable}[t]{.47\linewidth} \centering \begin{tabular}{llcccc} \toprule \multirow{2}{*}{Test case} & & \multicolumn{3}{c}{$ {\mathrightghost_{\textit{\textcolor{BlueGreen}{J}}}}$} \\ \cline{3-5} & & None & Fence & Retpoline \\ \midrule caseJ01 &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ caseJ02& (\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ \bottomrule \end{tabular} \subcaption{Results for the Spectre-BTB programs under the $ {\mathrightghost_{\textit{\textcolor{BlueGreen}{J}}}}$ semantics against unpatched programs (column "None"), programs patched with \texttt{lfence} (column "Fence"), and programs patched with the \texttt{retpoline} defense proposed in [53] (column "Retpoline").} \label{t:table-v2} \end{subtable} \hspace{1em} \begin{subtable}[t]{.47\linewidth} \centering \begin{tabular}{llccc} \toprule \multirow{2}{*}{Test case} & & \multicolumn{2}{c}{$ {\mathrightghost_{\texttt{\textcolor{DarkOrchid}{SLS}}}}$} \\ \cline{3-4} & & None & Fence \\ \midrule caseSLS01 &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ caseSLS02 &(\textcolor{red}{I}) & $\circ$ & ${\color{black}\bullet}\mathllap{\circ}$ \\ \bottomrule \end{tabular} \subcaption{Results for the Spectre-SLS programs under the $ {\mathrightghost_{\texttt{\textcolor{DarkOrchid}{SLS}}}}$ semantics against unpatched programs (column "None"), programs patched with \texttt{lfence} (column "Fence").} \label{t:table-sls} \end{subtable} \vspace{-10pt} \caption{Result of the analysis of our benchmarks for $ {\mathrightghost_{\textit{\textcolor{BlueGreen}{J}}}}$, $ {\mathrightghost_{\texttt{\textcolor{Emerald}{S}}}}$, $ {\mathrightghost_{\mathsf{\textcolor{RedOrange}{R}}}}$ and $ {\mathrightghost_{\texttt{\textcolor{DarkOrchid}{SLS}}}}$. For each program, $\circ$ denotes that \textsc{Spectector}\xspace finds a violation of SNI under the corresponding semantics, whereas ${\color{black}\bullet}\mathllap{\circ}$ denotes that \textsc{Spectector}\xspace proves the program secure under the semantics. Next to each program, we report if the program is \textcolor{PineGreen}{S} ecure or \textcolor{red}{I} nsecure in its unpatched version. } \label{tab:evaluation} \end{figure*}
Results for Spectre-BTB the section reports the analysis of the programs in the Spectre-BTB benchmark. Using the ghostJ{\mathsf{ghost}_{\textit{\textcolor{BlueGreen}{J}}}}ghostJ​ semantics, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR detected leaks (i.e., violations of SNI) in all unpatched programs. Furthermore, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR proved that the manually patched programs using lfence and the automatically patched programs using the retpoline countermeasure satisfy SNI, i.e., they are free of speculative leaks.

10.1.4 Results for Spectre-STL

the section reports the results of analysing the programs in the Spectre-STL benchmark.13 Using the ghostS{\mathsf{ghost}_{\texttt{\textcolor{Emerald}{S}}}}ghostS​ semantics, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR successfully detected leaks (i.e., violations of SNI) in all unpatched programs, except programs 03, 09, and 12 which do not contain speculative leaks (consistently with other analysis results [16, 30]). Observe that Binsec/Haunted [16] flags program 13 as secure since the program can only speculatively leak initial values from the stack, which Binsec/Haunted treats as public by default [34]. Since we assume initial memory values to be secret (like [30]), SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR correctly detected the leak in program 13. SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR also successfully proved that all patched programs (where an lfence is added between store\mathbf{store}store instructions) satisfy SNI and are free of speculative leaks.
13.
We had to slightly modify programs 02, 05, and 06 due to limitations of SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}} 's x86 front-end when dealing with global values (programs 05 and 06) and 32-bit addressing (program 02). We had to limit the speculation window, due to vanilla SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}} 's limitations in symbolic execution, when analyzing program 09, which contains a loop.

10.1.5 Results for Spectre-RSB

the section reports the analysis results on the Spectre-RSB programs. Using ghostR{\mathsf{ghost}_{\mathsf{\textcolor{RedOrange}{R}}}}ghostR​, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR successfully detected leaks in all unpatched programs. Moreover, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR successfully proved that the patched programs where a lfence instruction is added after every call\mathbf{call}call satisfy SNI, i.e., they are free of speculative leaks. SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR also successfully proved secure the programs patched using the modified retpoline defense proposed by [3], which replaces return instructions with a construct that traps the speculation in an infinite loop.

10.1.6 Results for Spectre-SLS

the section reports the analysis results on the Spectre-SLS programs. Using ghostSLS{\mathsf{ghost}_{\texttt{\textcolor{DarkOrchid}{SLS}}}}ghostSLS​, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR successfully detected leaks in all unpatched programs and proved the security (i.e. SNI) of the patched programs where an LFENCE{\mathchoice{\text{L{\scriptsize FENCE}}}{\text{L{\scriptsize FENCE}}}{\text{L{\scriptscriptstyle FENCE}}}{\text{LFENCE}}}LFENCE instruction was added after every return instruction.

10.2 Case Study: Detecting Leaks w.r.t. Combined Speculative Semantics

Using SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR, we analyze a corpus of 18 microbenchmarks containing speculative leaks generated by a combination of speculation mechanisms (for all composed semantics from Section 8). In particular, we consider one microbenchmark for each of all possible combinations of the ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost semantics, i.e., 18 combined semantics (as mentioned, combinations containing both ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost are not possible). With these experiments, we aim to show that our combined semantics can detect novel leaks that are otherwise undetectable when considering single speculation mechanisms in isolation.

10.2.1 Benchmarks

For each of the 18 combined semantics, we manually crafted an example μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM program that has a speculative leak under that specific combination. For each program, we also analyze a manually patched version where lfence instructions prevent speculative leaks. We refer to this benchmark, consisting of 36 μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM programs, as Spectre-Comb.

10.2.2 Experimental Setup

For each μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM program in Spectre-Comb, we run SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR with all individual speculative semantics as well as all their combinations. All experiments were run on a laptop with a Dual Core Intel Core i5-7200U CPU and 8GB of RAM.

Table 1: Results of the analysis. For each program, ∘\circ denotes that SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}} finds a violation of SNI whereas ∙∘{\color{black}\bullet}\mathllap{\circ} denotes that SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}} proves the program secure under the corresponding semantics. The different programs were devised to be vulnerable under a specific combination. The numbers correspond to that specific version 1=B1 = \mathbf{\textcolor{CarnationPink}{B}}, 2=J2 = \textit{\textcolor{BlueGreen}{J}}, 4=S4 = \texttt{\textcolor{Emerald}{S}}, 5=R5 = \mathsf{\textcolor{RedOrange}{R}} and 6=SLS6 = \texttt{\textcolor{DarkOrchid}{SLS}}. For example, comb125 was devised to be vulnerable under ghost\mathsf{ghost}.

Program \mathrightghostB {\mathrightghost_{\mathbf{\textcolor{CarnationPink}{B}}}} \mathrightghostJ {\mathrightghost_{\textit{\textcolor{BlueGreen}{J}}}} \mathrightghostS {\mathrightghost_{\texttt{\textcolor{Emerald}{S}}}} \mathrightghostR {\mathrightghost_{\mathsf{\textcolor{RedOrange}{R}}}} \mathrightghostSLS {\mathrightghost_{\texttt{\textcolor{DarkOrchid}{SLS}}}} \mathrightghostB+J {\mathrightghost_{\mathbf{\textcolor{CarnationPink}{B}} + \textit{\textcolor{BlueGreen}{J}}}} \mathrightghostB+S {\mathrightghost_{\mathbf{\textcolor{CarnationPink}{B}} + \texttt{\textcolor{Emerald}{S}}}} \mathrightghostB+R {\mathrightghost_{\mathbf{\textcolor{CarnationPink}{B}} + \mathsf{\textcolor{RedOrange}{R}}}} \mathrightghostB+SLS {\mathrightghost_{\mathbf{\textcolor{CarnationPink}{B}} + \texttt{\textcolor{DarkOrchid}{SLS}}}} \mathrightghostJ+S {\mathrightghost_{\textit{\textcolor{BlueGreen}{J}} + \texttt{\textcolor{Emerald}{S}}}} \mathrightghostJ+R {\mathrightghost_{\textit{\textcolor{BlueGreen}{J}} + \mathsf{\textcolor{RedOrange}{R}}}} \mathrightghostJ+SLS {\mathrightghost_{\textit{\textcolor{BlueGreen}{J}} + \texttt{\textcolor{DarkOrchid}{SLS}}}} \mathrightghostS+R {\mathrightghost_{\texttt{\textcolor{Emerald}{S}} + \mathsf{\textcolor{RedOrange}{R}}}} \mathrightghostS+SLS {\mathrightghost_{\texttt{\textcolor{Emerald}{S}} + \texttt{\textcolor{DarkOrchid}{SLS}}}}
comb12 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∘\circ ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb14 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∘\circ ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb15 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∘\circ ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb16 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∘\circ ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb24 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∘\circ ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb25 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∘\circ ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb26 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∘\circ ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb45 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∘\circ ∙∘{\color{black}\bullet}\mathllap{\circ}
comb46 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∘\circ
comb124 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb125 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb126 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb145 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb146 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb245 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb246 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb1245 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}
comb1246 ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ} ∙∘{\color{black}\bullet}\mathllap{\circ}

10.2.3 Results for Spectre-Comb

Table 1 reports the results of our analysis on the Spectre-Comb programs, which involve leaks arising from a combination of multiple speculation mechanisms.
SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR equipped with the individual semantics ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost is not able to detect the speculative leaks in any of the 18 programs and, therefore, proves them secure. This is expected since the programs contain leaks that arise from a combination of semantics.
SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR can successfully identify leaks in all programs when using the semantics corresponding to that example. For example, comb25 is proven insecure by the respective semantics ghost\mathsf{ghost}ghost.
Furthermore, as Figure 10 suggests, all 'stronger' semantics (higher in the combination lattice) also detect the vulnerability in the programs made for a 'weaker' semantics (lower in the combination lattice) and the 'weaker' ones do not detect the vulnerability of programs made for 'stronger' semantics. For example, comb25 is also proven to be insecure by SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR when using ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, while the program comb1245 can only be proven insecure by ghost\mathsf{ghost}ghost.
Semantics that are in no particular order in the lattice like ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost are also not able to detect the vulnerability in comb1246 and comb1245 respectively. This is expected since they each miss one speculative mechanism necessary to detect the vulnerability.
Because there is no combination of all our source speculative semantics ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost, there is also no unique combination that can find the leaks in all programs in Spectre-Comb. However, using ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR is able to successfully detect leaks in all programs.
We also analyzed programs manually patched with lfence statements. The examples are not shown here for brevity and can be found with the other code snippets at [36]. As before, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR successfully proves the security of all patched programs. Even for leaks that arise from multiple speculation mechanisms, it is often sufficient to insert a single lfence to secure the entire program, e.g., an lfence after the beqz\mathbf{beqz}beqz instruction in comb15 is enough to make the program SNI with respect to ghost\mathsf{ghost}ghost.

11. Discussion

11.1 Scope of the Models

Lifting the results of the security analysis for our speculative semantics to real-world CPUs is only possible to the extent that these semantics capture the information flows in the target system. Thus, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR 's result may incorrectly classify programs as secure (if our semantics do not capture information flows happening in real-world CPUs) or insecure (if our semantics admit speculations that are impossible on real systems).
We capture "leakage into the microarchitectural state" using the relatively powerful observer of the program execution that sees the location of memory accesses and the jump targets. This observer could be replaced by a weaker one, which accounts for more detailed models of a CPU's memory hierarchy, and SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR could be adapted accordingly, e.g. by adopting the cache models from CacheAudit [56]. We believe, however, that highly detailed models are not actually desirable for several reasons:
  1. they encourage brittle designs that break under small changes to the model, (b) they have to be adapted frequently, and (c) they are hard to understand and reason about for compiler developers and hardware engineers.
The "constant-time" observer model adopted in this paper has proven to offer a good tradeoff between precision and robustness [31, 32].

11.2 Other Speculation Mechanisms

There are many speculation mechanisms beyond those modeled in the speculative semantics ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost, ghost\mathsf{ghost}ghost and ghost\mathsf{ghost}ghost from Section 6:
  • CPUs speculate over ret\mathbf{ret}ret instructions in different ways. For instance, there are many different ways of implementing return stack buffers (e.g., cyclic versus acyclic RSBs [3] or RSBs that fall back to indirect branch prediction [8]). This kind of speculation can be modeled by modifying the Section 6.3.1 rule in ghost\mathsf{ghost}ghost.
  • Many proposals for value prediction over different kinds of instructions exist [57, 58, 14]. While naive speculative semantics might have to explore all possible values as prediction, semantics that model specific prediction mechanisms might restrict the set of predicted values (thereby leading to a more tractable analysis).
We expect that most of these mechanisms can be modeled as speculative semantics satisfying our well-formedness conditions. Hence, they could work with our composition framework.

11.3 Limitations of Composition

Our composition framework has two main limitations:
  • The metaparameter ZZZ is expressed in terms of μ\muμ ASM{\mathchoice{\text{A{\scriptsize SM}}}{\text{A{\scriptsize SM}}}{\text{A{\scriptscriptstyle SM}}}{\text{ASM}}}ASM instructions, i.e., the smallest unit of computation in our framework. Since ZZZ restricts how the composed semantics delegates execution to its sources, this limit the expressiveness of composed semantics. For instance, ghost\mathsf{ghost}ghost cannot speculate over the implict store\mathbf{store}store writing the return address to the stack that happens as part of call\mathbf{call}call instructions.
  • Our framework does not support combinations where a single instruction performs speculation-relevant changes in both source semantics. For instance, consider a combination of ghost\mathsf{ghost}ghost with ghost\mathsf{ghost}ghost. Here, both semantics start different speculative transactions on executing ret\mathbf{ret}ret instructions. However, instantiating ZZZ as (∅,∅)(\emptyset, \emptyset)(∅,∅), which enables both speculations, violates the confluence well-formedness condition for the composed semantics, whereas setting Z=(x,y)Z = (x,y)Z=(x,y) so that only one of xxx and yyy is ret\mathbf{ret}ret would only capture one of the two speculation mechanisms.
We leave addressing both limitations as future work.

11.4 Different flavours of Non-Interference

Here, we discuss the relation of SNI with other well-known notions of security against side-channel leaks.

11.4.1 General Non-Interference

We start by introducing General Non-Interference (GNI), a notion of security capturing that secrets do not leak through side channels. This notion is adapted from the hardware-software contracts framework of [21] into our setting.

Definition 22: General Non-Interference (GNI)

Program ppp satisfies GNI (denoted p⊢xGNIp \vdash_{x} \text{GNI}p⊢x​GNI) for a semantics xxx iff for all σ\sigmaσ, σ′\sigma'σ′, if σ∽ϕσ′\sigma \backsim_{\phi} \sigma'σ∽ϕ​σ′ then Behxω(p,σ)=Behxω(p,σ′)\mathit{Beh}^{\omega}_x(p, \sigma) = \mathit{Beh}^{\omega}_x(p, \sigma')Behxω​(p,σ)=Behxω​(p,σ′).
In a nutshell, a program ppp satisfies GNI for a given semantics xxx if any pair of low-equivalent initial configurations σ\sigmaσ and σ′\sigma'σ′ results in the same observations, i.e., Behxω(p,σ)=Behxω(p,σ′)\mathit{Beh}^{\omega}_x(p, \sigma) = \mathit{Beh}^{\omega}_x(p, \sigma')Behxω​(p,σ)=Behxω​(p,σ′).
Observe that GNI is an absolute security property [59], that is, it ensures that all observations are the same for any two executions starting from low-equivalent configurations. In contrast, SNI is a relative security property [59]. That is, it ensures that speculatively executed instructions (and, thus, speculative observations) do not leak more information than what is already leaked by the program's non-speculative execution. Naturally, satisfying GNI implies satisfying SNI for the same semantics xxx:

Corollary 23: GNI implies SNI

If p⊢xGNIp \vdash_{x} \text{GNI}p⊢x​GNI then p⊢xSNIp \vdash_{x} \text{SNI}p⊢x​SNI.

11.4.2 Relation with constant-time variants

A common defense against several side-channel timing attacks is the constant-time programming discipline [31, 32]. This programming discipline requires that a program's control flow and memory access patterns are strictly independent of sensitive data.
Following [32], constant-time programming can be modeled as a non-interference property by requiring that low-equivalent executions result in the same architectural control-flow and in the same sequence of memory accesses. That is, we can instantiate constant-time security by requiring the equivalence of the non-speculative trace, as indicated next:

Definition 24: Non-Speculative Constant-Time (CT)

Program ppp satisfies CT (denoted p⊢SeqCTp \vdash \text{SeqCT}p⊢SeqCT) iff for all σ\sigmaσ, σ′\sigma'σ′, if σ∽ϕσ′\sigma \backsim_{\phi} \sigma'σ∽ϕ​σ′ then BehNS(p,σ)=BehNS(p,σ′)\mathit{Beh}_{NS}(p, \sigma) = \mathit{Beh}_{NS}(p, \sigma')BehNS​(p,σ)=BehNS​(p,σ′).
Observe that CT is an instantiation of GNI w.r.t. the non-speculative semantics, i.e., p⊢SeqCT⇔p⊢NSGNIp \vdash \text{SeqCT} \Leftrightarrow p \vdash_{NS} \text{GNI}p⊢SeqCT⇔p⊢NS​GNI. Note also that we named Definition 24 as "Sequential Constant-Time" rather than the more standard "Constant-Time" to stress that CT traditionally applies only to the architectural, non-speculative semantics.
To account for the effects of speculatively executed instructions, several works [19, 60, 41, 16, 29] proposed security conditions that also restrict leaks through speculatively executed instructions. That is, all these works enforce variants of GNI, differing in the underlying speculative semantics or in what observations are part of the trace. For instance, in [19] the low-projection of the final configuration is also part of the trace (in addition to the usual observations associated with the constant-time attacker) to ensure the absence of explicit leaks.
Crucially, we can precisely connect CT, SNI, and GNI. That is, general non-interference w.r.t. a speculative semantics xxx is exactly the conjunction of constant-time and speculative non-interference w.r.t. xxx ([21], Proposition 4):

Proposition 25: GNI Decomposition

Given a policy ϕ\phiϕ and a program ppp: p⊢SeqCT∧p⊢xSNI⇔p⊢xGNIp \vdash \text{SeqCT} \land p \vdash_{x} \text{SNI} \Leftrightarrow p \vdash_{x} \text{GNI}p⊢SeqCT∧p⊢x​SNI⇔p⊢x​GNI
Proposition 25 allows us to decompose the check for GNI into two independent checks. An analysis only needs to prove that the program is constant-time (SeqCT) and that it satisfies speculative non-interference (SNI).

11.4.3 Extending Spectector with support for GNI

We conclude by discussing how SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR can be extended to check GNI. As stated above, SeqCT can be obtained by instantiating GNI with the non-speculative semantics, so this extension can be used also to check the classic constant-time property.
Recall that SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR algorithm from Section 9.1 searches for pairs of execution traces that have equivalent non-speculative behavior but differing speculative observations.
To support GNI, we need to modify MEMLEAK{\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}}MEMLEAK and CTRLLEAK{\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}}CTRLLEAK as indicated in Figure 15. Specifically, we enforce that the entire symbolic trace τ‾\overline{\tau}τ can only produce identical concrete observations for all low-equivalent inputs.
For this, we modify MEMLEAK{\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}}MEMLEAK to check the satisfiability of the following formula:
pthCnd(τ‾)1∧2∧polEqv(P)∧¬obsEqv(τ‾)\mathit{pthCnd}({\overline{\tau}})_{1 \wedge 2} \land \mathit{polEqv}(P) \land \neg \mathit{obsEqv}(\overline{\tau})pthCnd(τ)1∧2​∧polEqv(P)∧¬obsEqv(τ).
In particular, pthCnd(τ‾)1∧2\mathit{pthCnd}(\overline{\tau})_{1 \wedge 2}pthCnd(τ)1∧2​ ensures that the same symbolic path is followed, polEqv(P)\mathit{polEqv}(P)polEqv(P) ensures that the initial states are low-equivalent, and ¬obsEqv(τ‾)\neg \mathit{obsEqv}(\overline{\tau})¬obsEqv(τ) asserts that at least one observation (either architectural or speculative) associated with memory accesses differ among the two runs. That is, this formula is satisfiable only if there are two concrete traces associated with the symbolic trace τ‾\overline{\tau}τ where memory operation accesses a different address.
The CTRLLEAK{\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}}CTRLLEAK procedure is modified analogously to ensure that all control-flow observations (architectural or speculative) are identical between traces.
Thus, with minor modifications to the SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR algorithm, we are able to check for GNI-style properties for all the semantics discussed in the paper. The full algorithm for checking GNI can be found in Appendix B.
\begin{figure} \centering \begin{minipage}[t]{0.46\textwidth} \begin{algorithm}[H] \caption{$\textsc{MemLeak}$ for GNI} \label{algorithm:tool-seqct-short} \begin{algorithmic}[1] \Procedure{$\textsc{MemLeak}$}{$\overline{\tau}\xspace, P$} \State{$\psi \gets \mathit{pthCnd}(\overline{\tau}\xspace)_{1 \wedge 2} \wedge \mathit{polEqv}(P) \wedge $} \Statex{$\qquad \qquad \qquad \neg \mathit{obsEqv}(\overline{\tau}\xspace)$} \State{\Return{$\textsc{Satisfiable}(\psi)$}} \EndProcedure \end{algorithmic} \end{algorithm} \end{minipage} \hspace{10pt} \begin{minipage}[t]{0.46\textwidth} \begin{algorithm}[H] \caption{$\textsc{CtrlLeak}$ for GNI} \label{algorithm:tool-gni-short} \begin{algorithmic}[1] \Procedure{$\textsc{CtrlLeak}$}{$\overline{\tau}\xspace, P$} \For{each prefix $\nu \cdot \textcolor{RoyalBlue}{\mathtt{symPc}}(\mathit{se})$ of $\overline{\tau}\xspace$} \State{$\psi \gets \mathit{pthCnd}(\overline{\tau}\xspace\mathord{\upharpoonright_{ns}}\cdot \nu)_{1 \wedge 2} \wedge \mathit{polEqv}(P)$} \Statex{$\qquad \qquad \qquad \wedge \neg \mathit{sameSymbPc}(se)$} \If{$\textsc{Satisfiable}(\psi)$} \State{\Return{$\top$}} \EndIf \EndFor \State{\Return{$\bot$}} \EndProcedure \end{algorithmic} \end{algorithm} \end{minipage} \caption{The modified versions of \textsc{MemLeak} and \textsc{CtrlLeak} for GNI} \label{fig:tool-ext} \end{figure}

12. Related Work

skip Speculative Execution Attacks: After Spectre [1] has been disclosed to the public in 2018, researchers have identified many other speculative execution attacks [2, 3, 4, 5, 6, 7]. These attacks differ in the exploited speculation sources [3, 2, 10], the covert channels [61, 62, 63, 64, 65] used, or the target platforms [66]. We refer the reader to [55] for a survey of existing attacks.
skip Security Properties for Speculative Leaks: Researchers have proposed many program-level properties for security against speculative leaks, which can be classified in three main groups [59]:
  • Non-interference definitions ensure the security of speculative and non-speculative instructions. For instance, speculative constant-time [19, 60, 41, 16, 29] extends the constant-time security condition to account also for transient instructions.
  • Relative non-interference definitions [67, 40, 18, 68] ensure that transient instructions do not leak more information than what is leaked by non-transient instructions. The notion of Speculative Non-Interference (SNI) introduced in this paper falls into this category, as it restricts the information leaked by speculatively executed instructions relative to the program's non-speculative behavior.
  • Definitions that formalise security as a safety property [30, 42], which may over-approximate definitions from the groups above.
Finally, we highlight the relationship between Speculative Constant-Time (SCT) and our properties SNI and GNI. As shown by [19] if the program is sequentially constant-time, SNI, and the resulting architectural states are low-equivalent, then the program is also SCT. In relation to GNI, SCT enforces the exact same trace equivalence but imposes the additional constraint that final architectural states must be low-equivalent. We can verify SCT on top of our SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR-GNI check by explicitly exposing the final architectural state as a terminal observation within the execution trace.
skip Operational Semantics for Speculative Leaks: In the last few years, there has been a growing interest in developing formal models and principled program analyses for detecting leaks caused by speculatively executed instructions. We refer the reader to [59] for a comprehensive survey. In the following, we discuss the approaches that are particularly relevant to our paper.
Some approaches explicitly model microarchitectural components like multiple pipeline stages, caches, and branch predictors. For instance, KLEESpectre [17] and SpecuSym [18] consider a semantics that explicitly models the cache, enabling reasoning about the cache content. [69] go a step further and model a multi-stage pipeline with explicit cache and branch predictor. Their semantics can only model speculation over branch instructions since it lacks store-forwarding or RSB.
[19]'s semantics model speculation over branch instructions, store-bypasses, and return instructions. Differently from our semantics, their 3-stage pipeline semantics explicitly models several microarchitectural components like a reorder buffer and an RSB. Their tool detects violations of speculative constant-time induced by speculation over branch instructions and store-bypasses.
[60] extend the Jasmin [41] cryptographic verification framework to reason about speculative constant-time and supports speculation over store-bypasses and branch instructions. [70] equip Jasmin with an information flow control type system that enforces SCT. However, only against SPECTRE-PHT{\mathchoice{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptscriptstyle PECTRE}-P{\scriptscriptstyle HT}}}{\text{SPECTRE-PHT}}}SPECTRE-PHT attacks.
Binsec/Haunted [16] detect violations of speculative constant-time due to speculation over store-bypasses and branch instructions. For this, they explicitly model the store buffer, which ghost\mathsf{ghost}ghost abstracts away. Blade [29] uses a JIT-step semantics that translates high-level commands (from a WHILE-language) to low-level machine instructions while tracking control-flow predictions. This allows for source-level reasoning and their semantics captures speculation over branch instructions.
While several of these models support multiple speculation mechanisms, these mechanisms are hard-coded and no existing approach provides a composition framework or extensible ways of extending the main theoretical results to new mechanisms "for free". Moreover, while we could have used other semantics as a basis for our framework, this would have resulted in more difficult proofs (since semantics like the one in [19] are significantly more complex than ours).
skip Axiomatic Semantics for Speculative Leaks: A few approaches formalise the effects of speculatively executed instructions using axiomatic semantics inspired by work on weak memory models. For instance, [71] and [72] capture the effects of branch speculation but both lack program analyses.
[30] illustrate how one can model leaks resulting from speculation over branch instructions and store-bypasses using the CAT modeling language for memory consistency, and they present a bounded model checking analysis for detecting speculative leaks. Interestingly, they talk about composing several of their semantics ([30], S IV.F), which should allow them to detect vulnerabilities like (which we detect under ghost\mathsf{ghost}ghost). However, they do not formally characterize compositions and, therefore, they cannot derive interesting results "for free" about the composed semantics (like we do in Theorem 14). Moreover, even though they state that composability is an advantage of axiomatic models, our framework (and tool implementation) shows that composability can be done with operational semantics as well.
skip Secure Compilation for Speculative Leaks: In addition to program analyses like the ones described above, researchers have proposed compiler passes to prevent and mitigate speculative leaks. For instance, [42] and [73] study the security of compiler-level countermeasures implemented in major compilers using Secure Compilation theory, whereas [29] propose a compiler pass for automatically patching speculative leaks using a type system to track speculative leaks.
[74] propose a set of compiler passes that, together with hardware support (e.g. Intel CET-IBT, a shadow stack for return addresses) offers protection against SPECTRE-PHT{\mathchoice{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptscriptstyle PECTRE}-P{\scriptscriptstyle HT}}}{\text{SPECTRE-PHT}}}SPECTRE-PHT, SPECTRE-BTB{\mathchoice{\text{S{\scriptsize PECTRE}-B{\scriptsize TB}}}{\text{S{\scriptsize PECTRE}-B{\scriptsize TB}}}{\text{S{\scriptscriptstyle PECTRE}-B{\scriptscriptstyle TB}}}{\text{SPECTRE-BTB}}}SPECTRE-BTB, SPECTRE-STL{\mathchoice{\text{S{\scriptsize PECTRE}-S{\scriptsize TL}}}{\text{S{\scriptsize PECTRE}-S{\scriptsize TL}}}{\text{S{\scriptscriptstyle PECTRE}-S{\scriptscriptstyle TL}}}{\text{SPECTRE-STL}}}SPECTRE-STL, SPECTRE-RSB{\mathchoice{\text{S{\scriptsize PECTRE}-R{\scriptsize SB}}}{\text{S{\scriptsize PECTRE}-R{\scriptsize SB}}}{\text{S{\scriptscriptstyle PECTRE}-R{\scriptscriptstyle SB}}}{\text{SPECTRE-RSB}}}SPECTRE-RSB, and predictive store forwarding [75]. We note that [74], Section 3.3 showed a counterexample that our semantics ghost\mathsf{ghost}ghost does not catch. When devising our speculative semantics, we encountered a trade-off: keeping the related SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR implementation tractable (albeit imprecise) or making the semantics precise (but not implementable due to state explosion of the tool). We decided to model the speculation in that way to keep the analysis tractable. Furthermore, our case study in Section 10.1 was used by other detection tools as well [16, 30] and our semantics ghost\mathsf{ghost}ghost detects all vulnerabilities there. Thus, we think this is a reasonable trade-off between precision and performance.
skip Detecting Leaks through Testing: The Revizor testing tool [23, 24, 27, 76] and SpecFuzz [25] use fuzz testing to find vulnerabilities caused by speculation in CPUs. Similarly, SpecDoctor by [26] uses differential fuzzing to fuzz for transient vulnerabilities on the RTL level. [77] extend Scam-V [78] to optimize software mitigations for SPECTRE-PHT{\mathchoice{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptsize PECTRE}-P{\scriptsize HT}}}{\text{S{\scriptscriptstyle PECTRE}-P{\scriptscriptstyle HT}}}{\text{SPECTRE-PHT}}}SPECTRE-PHT using a relational testing approach.
AMuLeT [79] adapts Revizor to the design phase. AMuLeT instruments microarchitectural simulators (e.g., gem5) to check secure speculation countermeasures against leakage contracts. LMTest [80] provides a framework for testing cryptographic implementations against parameterized leakage models (defined in a DSL called LmSpec). It generates test cases to detect secret-dependent leaks in the presence of proposed microarchitectural optimizations.
Unlike SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR, these approaches cannot detect the absence of leaks.

13. Conclusion

This paper presented an approach to automatically detect speculative leaks in programs. We introduced speculative non-interference, the first semantic notion of security against speculative execution attacks, and we defined multiple speculative semantics to capture 5 classes of Spectre attacks. Next, we defined a general framework to reason about the composition of different speculative semantics and instantiated the framework with our speculative semantics. Our framework yields safety of the composed semantics (almost) for free, given the safety of its parts. We utilize our theoretical development and implement a program analysis tool called SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR that automatically detects speculative leaks or proves their absence, for our speculative semantics and their combinations.

Acknowledgments

This work is supported by the Spanish Ministry of Science, Innovation, and University under the Ramón y Cajal grant \grantnum{\arabic{thesponsor}}{RYC2021-032614-I}; the Spanish Ministry of Science, Innovation, and University under the project \grantnum{\arabic{thesponsor}}{PID2022-142290OB-I00 ESPADA}; the Spanish Ministry of Science, Innovation, and University under the Europa Excelencia project \grantnum{\arabic{thesponsor}}{EUR2025-164828 SINTRAZAS}; the Spanish Ministry of Science, Innovation, and University under the project \grantnum{\arabic{thesponsor}}{CEX2024-001471-M}; the European Union under the Horizon Europe projects \grantnum{\arabic{thesponsor}}{101230068 PRIMULA} and \grantnum{\arabic{thesponsor}}{101020415 SafeSecS}.
\listoftodos[List of suggested changes]

Appendix

A. Code from Case Studies

A.1 Example #8

In Example #8, the bounds check of is implemented using a conditional operator:
temp &= B[A[y<size?(y+1):0]*512];
When compiling the example without countermeasures or optimizations, the conditional operator is translated to a branch instruction (cf. line 4), which is a source of speculation. Hence, the resulting program contains a speculative leak, which SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR correctly detects.
mov size, % mov y, % cmp % jae .L1 add $1, % jmp .L2 .L1: xor % jmp .L2 .L2: mov A(% shl$ 9, % mov B(% mov temp, % and % mov %
In the UNP{\mathchoice{\text{U{\scriptsize NP}}}{\text{U{\scriptsize NP}}}{\text{U{\scriptscriptstyle NP}}}{\text{UNP}}}UNP -O2 mode, the conditional operator is translated as a conditional move (cf. line 6), for which SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR can prove security.
mov size, % mov y, % xor % cmp % lea 1(% cmova % mov A(% shl $9, % mov B(% and %

A.2 Example #15 in Slh mode

Here, the adversary provides the input via the pointer *y:
if (*y < size) temp &= B[A[*y] * 512];
In the -O0 SLH{\mathchoice{\text{S{\scriptsize LH}}}{\text{S{\scriptsize LH}}}{\text{S{\scriptscriptstyle LH}}}{\text{SLH}}}SLH mode, CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG hardens the address used for performing the memory access A[*y] in lines 8–12, but not the resulting value, which is stored in the register %cx. However, the value stored in %cx is used to perform a second memory access at line 14. An adversary can exploit the second memory access to speculatively leak the content of A[0xFF...FF]. In our experiments, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR correctly detected such leak.
mov $0, % mov y, % mov (% mov size, % cmp % jae END cmovae $-1, % mov y, % mov (% mov % or % mov A(% shl $9, % mov B(% mov temp, % and % mov %
In contrast, when Example #15 is compiled with the -O2 flag, CLANG{\mathchoice{\text{C{\scriptsize LANG}}}{\text{C{\scriptsize LANG}}}{\text{C{\scriptscriptstyle LANG}}}{\text{CLANG}}}CLANG correctly hardens A[*y]'s result (cf. line 10). This prevents information from flowing into the microarchitectural state during speculative execution. Indeed, SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR proves that the program satisfies speculative non-interference.
mov $ 0, % mov y, % mov (% mov size, % cmp % jae END cmovae $-1, % mov A(% shl $ 9, % or % mov B(% or % and %

B. Variants of Spectector

In Section 11.4 we discussed the variation of the SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}}SPECTECTOR algorithm to check for GNI. Here, we will present the full algorithm as well as the algorithm for checking sequential constant-time:

Algorithm 4: SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}} SeqCT

Require: A program SecureSecure, a security policy InsecureInsecure, a speculative window SpectectorSpectector.
0Ensure: SecureSecure if InsecureInsecure satisfies SeqCT with respect to the policy SecureSecure; InsecureInsecure otherwise
1procedure SpectectorSpectector(p,P,wp, P,w)
2for each symbolic run τ‾∈BehxS(p)\overline{\tau} \in \mathit{Beh}^{\mathcal{S}}_{x}(p) do
3  if MEMLEAK(τ‾,P)∨CTRLLEAK(τ‾,P){\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}}(\overline{\tau},P) \vee {\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}}(\overline{\tau},P) then
4    return{InsecureInsecure}
5  end if
6end for
7return{SecureSecure}
8end procedure
9procedure MEMLEAK{\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}} (τ‾,P\overline{\tau}, P)
10ψ←pthCnd(τ‾)1∧2∧polEqv(P)∧\psi \gets \mathit{pthCnd}(\overline{\tau})_{1 \wedge 2} \wedge \mathit{polEqv}(P) \wedge
11¬obsEqv(τ‾↾ns)\qquad \qquad \qquad \neg \mathit{obsEqv}(\overline{\tau}\mathord{\upharpoonright_{ns}})
12return{SATISFIABLE(ψ){\mathchoice{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptscriptstyle ATISFIABLE}}}{\text{SATISFIABLE}}}(\psi)}
13end procedure
14procedure CTRLLEAK{\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}} (τ‾,P\overline{\tau}, P)
15for each prefix ν⋅symPc(se)\nu \cdot \textcolor{RoyalBlue}{\mathtt{symPc}}(\mathit{se}) of τ‾↾ns\overline{\tau}\mathord{\upharpoonright_{ns}} do
16  ψ←pthCnd(τ‾↾ns⋅ν)1∧2∧polEqv(P)∧\psi \gets \mathit{pthCnd}(\overline{\tau}\mathord{\upharpoonright_{ns}}\cdot \nu)_{1 \wedge 2} \wedge \mathit{polEqv}(P) \wedge
17  ¬sameSymbPc(se)\qquad \qquad \qquad \neg \mathit{sameSymbPc}(se)
18  if SATISFIABLE(ψ){\mathchoice{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptscriptstyle ATISFIABLE}}}{\text{SATISFIABLE}}}(\psi) then
19    return{⊤\top}
20  end if
21end for
22return{⊥\bot}
23end procedure

Algorithm 5: SPECTECTOR{\mathchoice{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptsize PECTECTOR}}}{\text{S{\scriptscriptstyle PECTECTOR}}}{\text{SPECTECTOR}}} GNI

Require: A program SecureSecure, a security policy InsecureInsecure, a speculative window SpectectorSpectector.
0Ensure: SecureSecure if InsecureInsecure satisfies general non-interference with respect to the policy SecureSecure and speculative semantics ghostx\mathsf{ghost}_{x}; InsecureInsecure otherwise
1procedure SpectectorSpectector(p,P,wp, P,w)
2for each symbolic run τ‾∈BehxS(p)\overline{\tau} \in \mathit{Beh}^{\mathcal{S}}_{x}(p) do
3  if MEMLEAK(τ‾,P)∨CTRLLEAK(τ‾,P){\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}}(\overline{\tau},P) \vee {\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}}(\overline{\tau},P) then
4    return{InsecureInsecure}
5  end if
6end for
7return{SecureSecure}
8end procedure
9procedure MEMLEAK{\mathchoice{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptsize EM}L{\scriptsize EAK}}}{\text{M{\scriptscriptstyle EM}L{\scriptscriptstyle EAK}}}{\text{MEMLEAK}}} (τ‾,P\overline{\tau}, P)
10ψ←pthCnd(τ‾)1∧2∧polEqv(P)∧\psi \gets \mathit{pthCnd}(\overline{\tau})_{1 \wedge 2} \wedge \mathit{polEqv}(P) \wedge
11¬obsEqv(τ‾)\qquad \qquad \qquad \neg \mathit{obsEqv}(\overline{\tau})
12return{SATISFIABLE(ψ){\mathchoice{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptscriptstyle ATISFIABLE}}}{\text{SATISFIABLE}}}(\psi)}
13end procedure
14procedure CTRLLEAK{\mathchoice{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptsize TRL}L{\scriptsize EAK}}}{\text{C{\scriptscriptstyle TRL}L{\scriptscriptstyle EAK}}}{\text{CTRLLEAK}}} (τ‾,P\overline{\tau}, P)
15for each prefix ν⋅symPc(se)\nu \cdot \textcolor{RoyalBlue}{\mathtt{symPc}}(\mathit{se}) of τ‾\overline{\tau} do
16  ψ←pthCnd(τ‾↾ns⋅ν)1∧2∧polEqv(P)\psi \gets \mathit{pthCnd}(\overline{\tau}\mathord{\upharpoonright_{ns}}\cdot \nu)_{1 \wedge 2} \wedge \mathit{polEqv}(P)
17  ∧¬sameSymbPc(se)\qquad \qquad \qquad \wedge \neg \mathit{sameSymbPc}(se)
18  if SATISFIABLE(ψ){\mathchoice{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptsize ATISFIABLE}}}{\text{S{\scriptscriptstyle ATISFIABLE}}}{\text{SATISFIABLE}}}(\psi) then
19    return{⊤\top}
20  end if
21end for
22return{⊥\bot}
23end procedure

C. Trace Projections

Here, we formalize the speculative projections ↾x\mathord{\upharpoonright_{x}}↾x​ for each of our semantics and the non-speculative projection ↾ns\mathord{\upharpoonright_{ns}}↾ns​.
Non-speculative Trace Projection
Given a trace τ\tauτ, its non-speculative projection contains only the observations that are produced by committed transactions; in other words, rolled-back transactions are removed in the projection. Formally, τ↾ns\tau\mathord{\upharpoonright_{ns}}τ↾ns​ is defined as follows:

Definition: Non-speculative projection

We define the non-speculative projection mutually recursive as
ε↾ns=ετ‾⋅commitx n↾ns=τ‾↾nsτ‾⋅startx n↾ns=τ‾↾nsτ‾⋅rlbx id↾ns=helper(τ‾,id)τ‾⋅τ↾ns=τ‾↾ns⋅τ otherwise \begin{aligned} \varepsilon\mathord{\upharpoonright_{ns}} =& \varepsilon \\ \overline{\tau} \cdot \textcolor{RoyalBlue}{\mathtt{commit}}_{x}\ n\mathord{\upharpoonright_{ns}} =& \overline{\tau}\mathord{\upharpoonright_{ns}} \\ \overline{\tau} \cdot \textcolor{RoyalBlue}{\mathtt{start}}_{x}\ n\mathord{\upharpoonright_{ns}} =& \overline{\tau}\mathord{\upharpoonright_{ns}} \\ \overline{\tau} \cdot \textcolor{RoyalBlue}{\mathtt{rlb}}_{x}\ id \mathord{\upharpoonright_{ns}} =& helper(\overline{\tau}, \mathit{id}) \\ \overline{\tau} \cdot \tau\mathord{\upharpoonright_{ns}} =& \overline{\tau}\mathord{\upharpoonright_{ns}} \cdot \tau ~\text{otherwise} \ \end{aligned}
The helper(helper(helper() is defined as
helper(ε,id)=εhelper(τ‾⋅startx id,id)=τ‾↾nshelper(τ‾⋅τ,id)=helper(τ‾,id) otherwise\begin{aligned} helper(\varepsilon, \mathit{id}) &= \varepsilon \\ helper(\overline{\tau} \cdot \textcolor{RoyalBlue}{\mathtt{start}}_{x}\ \mathit{id}, \mathit{id}) &= \overline{\tau}\mathord{\upharpoonright_{ns}}\\ helper(\overline{\tau} \cdot \tau, \mathit{id}) &= helper(\overline{\tau}, \mathit{id}) ~\text{otherwise} \end{aligned}
Speculative Trace Projections
Given a speculative trace τ\tauτ, its speculative projection contains only the observations produced by rolled-back transactions.

Definition: Speculative Projection

ε↾se= ετ‾⋅rlbx i↾se= helperse(τ‾,i)τ‾⋅τ↾se= τ‾↾se  otherwise\begin{aligned} \varepsilon\mathord{\upharpoonright_{se}} =&~ \varepsilon \\ \overline{\tau} \cdot \textcolor{RoyalBlue}{\mathtt{rlb}}_{x}\ i \mathord{\upharpoonright_{se}} =&~ helper_{se}(\overline{\tau}, i) \\ \overline{\tau} \cdot \tau\mathord{\upharpoonright_{se}} =&~ \overline{\tau}\mathord{\upharpoonright_{se}} \; \text{otherwise} \end{aligned}
helperse(ε,id)=εhelperse(τ‾⋅startx id,id)=τ‾↾sehelperse(τ‾⋅startx id′,id)=helperse(τ‾,id)  if id≠id′helperse(τ‾⋅rlbx id′,id)=helperse(τ‾,id)  ifid≠id′helperse(τ‾⋅commitx id′,id)=helperse(τ‾,id)helperse(τ‾⋅τ,id)=helperse(τ‾,id)⋅τ  otherwise\begin{aligned} helper_{se}(\varepsilon, \mathit{id}) &= \varepsilon \\ helper_{se}(\overline{\tau} \cdot \textcolor{RoyalBlue}{\mathtt{start}}_{x}\ \mathit{id}, \mathit{id}) &= \overline{\tau}\mathord{\upharpoonright_{se}}\\ helper_{se}(\overline{\tau} \cdot \textcolor{RoyalBlue}{\mathtt{start}}_{x}\ \mathit{id}', \mathit{id}) &= helper_{se}(\overline{\tau}, \mathit{id}) \; \text{if }id \neq id'\\ helper_{se}(\overline{\tau} \cdot \textcolor{RoyalBlue}{\mathtt{rlb}}_{x}\ \mathit{id}', \mathit{id}) &= helper_{se}(\overline{\tau}, \mathit{id}) \; \text{if}id \neq id'\\ helper_{se}(\overline{\tau} \cdot \textcolor{RoyalBlue}{\mathtt{commit}}_{x}\ \mathit{id}', \mathit{id}) &= helper_{se}(\overline{\tau}, \mathit{id})\\ helper_{se}(\overline{\tau} \cdot \tau, \mathit{id}) &= helper_{se}(\overline{\tau}, \mathit{id}) \cdot \tau \; \text{otherwise} \end{aligned}

References

[1] Paul Kocher, Jann Horn, Anders Fogh, Daniel Genkin, Daniel Gruss, Werner Haas, Mike Hamburg, Moritz Lipp, Stefan Mangard, Thomas Prescher, Michael Schwarz, and Yuval Yarom. 2019. Spectre Attacks: Exploiting Speculative Execution. In Proceedings of the 40th IEEE Symposium on Security and Privacy (S&P '19).
[2] Esmaeil Mohammadian Koruyeh, Khaled N. Khasawneh, Chengyu Song, and Nael Abu-Ghazaleh. 2018. Spectre Returns! Speculation Attacks Using the Return Stack Buffer. In Proceedings of the 12th USENIX Workshop on Offensive Technologies (WOOT'18). USENIX Association.
[3] Giorgi Maisuradze and Christian Rossow. 2018. Ret2spec: Speculative Execution Using Return Stack Buffers. In Proceedings of the 25th ACM SIGSAC Conference on Computer and Communications Security (CCS '18). ACM.
[4] Atri Bhattacharyya, Alexandra Sandulescu, Matthias Neugschwandtner, Alessandro Sorniotti, Babak Falsafi, Mathias Payer, and Anil Kurmus. 2019. SMoTherSpectre: Exploiting Speculative Execution through Port Contention. In Proceedings of the 26th ACM SIGSAC Conference on Computer and Communications Security (CCS '19). ACM.
[5] Tao Zhang, Kenneth Koltermann, and Dmitry Evtyushkin. 2020. Exploring Branch Predictors for Constructing Transient Execution Trojans. In Proceedings of the 25th International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS '20). ACM.
[6] Enrico Barberis, Pietro Frigo, Marius Muench, Herbert Bos, and Cristiano Giuffrida. 2022. Branch history injection: On the effectiveness of hardware mitigations against cross-privilege Spectre-v2 attacks. In Proceedings of the 31st USENIX Security Symposium (USENIX Security '22). USENIX Association.
[7] Johannes Wikner, Daniël Trujillo, and Kaveh Razavi. 2023. Phantom: Exploiting Decoder-detectable Mispredictions. In MICRO. Paper=https://comsec.ethz.ch/wp-content/files/phantom_micro23.pdfURL=https://comsec.ethz.ch/research/microarch/inception
[8] Johannes Wikner and Kaveh Razavi. 2022. RETBLEED: Arbitrary Speculative Code Execution with Return Instructions. In Proceedings of the 31st USENIX Security Symposium (USENIX Security '22). USENIX Association.
[9] Daniël Trujillo, Johannes Wikner, and Kaveh Razavi. 2023. Inception: Exposing New Attack Surfaces with Training in Transient Execution. In 32nd USENIX Security Symposium (USENIX Security 23). USENIX Association, Anaheim, CA. https://www.usenix.org/conference/usenixsecurity23/presentation/trujillo
[10] J. Horn. 2018. Speculative execution, variant 4: Speculative store bypass. https://bugs.chromium.org/p/project-zero/issues/detail?id=1528. Accessed: 2021-04-11.
[11] ARM. 2020. Whitepaper Straight-line Speculation. https://developer.arm.com/documentation/102825/0100/.
[12] Jason Kim, Jalen Chuang, Daniel Genkin, and Yuval Yarom. 2025a. FLOP: Breaking the Apple M3 CPU via False Load Output Predictions. In USENIX Security.
[13] Jason Kim, Daniel Genkin, and Yuval Yarom. 2025b. SLAP: Data Speculation Attacks via Load Address Prediction on Apple Silicon. In S&P.
[14] Rami Sheikh, Harold W. Cain, and Raguram Damodaran. 2017. Load value prediction via path-based address prediction: Avoiding mispredictions due to conflicting stores. In Proceedings of the 50th Annual IEEE/ACM International Symposium on Microarchitecture (MICRO '17). ACM.
[15] arm. 2020. Straight-line Speculation. https://developer.arm.com/documentation/102825/0100/?lang=en. Accessed: 2022-09-05.
[16] Lesly-Ann Daniel, Sébastien Bardin, and Tamara Rezk. 2021. Hunting the Haunter — Efficient relational symbolic execution for Spectre with Haunted RelSE. In Proceedings of the 28th Annual Network and Distributed System Security Symposium (NDSS '21). The Internet Society.
[17] Guanhua Wang, Sudipta Chattopadhyay, Arnab Kumar Biswas, Tulika Mitra, and Abhik Roychoudhury. 2020. KLEESpectre: Detecting Information Leakage through Speculative Cache Attacks via Symbolic Execution. ACM Transactions on Software Engineering and Methodology 29, 3 (2020).
[18] Shengjian Guo, Yueqi Chen, Peng Li, Yueqiang Cheng, Huibo Wang, Meng Wu, and Zhiqiang Zuo. 2020. SpecuSym: Speculative Symbolic Execution for Cache Timing Leak Detection. In Proceedings of the 42nd ACM/IEEE International Conference on Software Engineering (ICSE '20). ACM.
[19] Sunjay Cauligi, Craig Disselkoen, Klaus v. Gleissenthall, Dean Tullsen, Deian Stefan, Tamara Rezk, and Gilles Barthe. 2020. Constant-Time Foundations for the New Spectre Era. In Proceedings of the 41st ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI '20). ACM.
[20] Guanhua Wang, Sudipta Chattopadhyay, Ivan Gotovchits, Tulika Mitra, and Abhik Roychoudhury. 2021. oo7: Low-Overhead Defense Against Spectre Attacks via Program Analysis. IEEE Transactions on Software Engineering 47, 11 (2021).
[21] Marco Guarnieri, Boris Köpf, Jan Reineke, and Pepe Vila. 2021. Hardware-Software Contracts for Secure Speculation. In Proceedings of the 42nd IEEE Symposium on Security and Privacy (S&P '21). IEEE.
[22] Meng Wu and Chao Wang. 2019. Abstract interpretation under speculative execution. In Proceedings of the 40th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI' 19). ACM, New York, NY, USA. https://doi.org/10.1145/3314221.3314647
[23] Oleksii Oleksenko, Christof Fetzer, Boris Köpf, and Mark Silberstein. 2022. Revizor: Testing Black-Box CPUs against Speculation Contracts. In Proceedings of the 27th ACM International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS '22). ACM.
[24] Oleksii Oleksenko, Marco Guarnieri, Boris Köpf, and Mark Silberstein. 2023. Hide and Seek with Spectres: Efficient discovery of speculative information leaks with random testing. In Proceedings of the 44th IEEE Symposium on Security and Privacy (S&P 2023). IEEE.
[25] Oleksii Oleksenko, Bohdan Trach, Mark Silberstein, and Christof Fetzer. 2020. SpecFuzz: Bringing Spectre-type vulnerabilities to the surface. In 29th USENIX Security Symposium (USENIX Security 20). USENIX Association, 1481–1498. https://www.usenix.org/conference/usenixsecurity20/presentation/oleksenko
[26] Jaewon Hur, Suhwan Song, Sunwoo Kim, and Byoungyoung Lee. 2022. SpecDoctor: Differential Fuzz Testing to Find Transient Execution Vulnerabilities. In Proceedings of the 2022 ACM SIGSAC Conference on Computer and Communications Security (Los Angeles, CA, USA) (CCS '22). Association for Computing Machinery, New York, NY, USA, 1473–1487. https://doi.org/10.1145/3548606.3560578
[27] Jana Hofmann, Emanuele Vannacci, Cedric Fournet, Boris Kopf, and Oleksii Oleksenko. 2023. Speculation at Fault: Modeling and Testing Microarchitectural Leakage of CPU Exceptions. In 32nd USENIX Security Symposium (USENIX Security 23). USENIX Association. https://www.usenix.org/conference/usenixsecurity23/presentation/hofmann
[28] Marco Guarnieri, Boris Köpf, José F. Morales, Jan Reineke, and Andrés Sánchez. 2020b. Spectector: Principled Detection of Speculative Information Flows. In Proceedings of the 41st IEEE Symposium on Security and Privacy (S&P '20).
[29] Marco Vassena, Craig Disselkoen, Klaus von Gleissenthall, Sunjay Cauligi, Rami Gökhan Kıcı, Ranjit Jhala, Dean Tullsen, and Deian Stefan. 2021. Automatically Eliminating Speculative Leaks from Cryptographic Code with Blade. Proceedings of the ACM on Programming Languages 5, POPL (2021).
[30] Hernán Ponce de León and Johannes Kinder. 2022. Cats vs. Spectre: An Axiomatic Approach to Modeling Speculative Execution Attacks. In Proceedings of the 43rd IEEE Symposium on Security and Privacy (S&P '22). IEEE.
[31] David Molnar, Matt Piotrowski, David Schultz, and David Wagner. 2005. The program counter security model: automatic detection and removal of control-flow side channel attacks. In Proceedings of the 8th International Conference on Information Security and Cryptology (Seoul, Korea) (ICISC'05). Springer.
[32] José Bacelar Almeida, Manuel Barbosa, Gilles Barthe, François Dupressoir, and Michael Emmi. 2016. Verifying constant-time implementations. In Proceedings of the 25th USENIX Conference on Security Symposium (SEC'16). USENIX, USA.
[33] P. Kocher. 2018. Spectre Mitigations in Microsoft's C/C++ Compiler. https://www.paulkocher.com/doc/MicrosoftCompilerSpectreMitigation.html. Accessed: 2021-04-11.
[34] Binsec/Haunted Benchmark. 2021. Result of case_13. https://github.com/binsec/haunted_bench/issues/2.
[35] Xaver Fabian, Marco Patrignani, and Marco Guarnieri. 2022. Automatic Detection of Speculative Execution Combinations. In Proceedings of the 29th ACM Conference on Computer and Communications Security (CCS 2022). ACM.
[36] Marco Guarnieri, Boris Köpf, José F. Morales, Jan Reineke, and Andrés Sánchez. 2020a. Spectector – Automatic detection of speculative information flows. https://spectector.github.io/
[37] Xaver Fabian, Marco Guarnieri, Boris Köpf, José F. Morales, Marco Patrignani, Jan Reineke, and Andrés Sánchez. 2025. [Technical Report]. Supplementary Material. Submitted to ACM TOPLAS with this manuscript.
[38] C. Carruth. 2018. Speculative load hardening. https://llvm.org/docs/SpeculativeLoadHardening.html
[39] Leonardo de Moura and Nikolaj Bjørner. 2008. Z3: An Efficient SMT Solver. In Tools and Algorithms for the Construction and Analysis of Systems, C. R. Ramakrishnan and Jakob Rehof (Eds.). Springer Berlin Heidelberg, Berlin, Heidelberg, 337–340.
[40] Roberto Guanciale, Musard Balliu, and Mads Dam. 2020. InSpectre: Breaking and Fixing Microarchitectural Vulnerabilities by Formal Analysis. In Proceedings of the 27th ACM SIGSAC Conference on Computer and Communications Security (CCS '20). ACM.
[41] José Bacelar Almeida, Manuel Barbosa, Gilles Barthe, Arthur Blot, Benjamin Grégoire, Vincent Laporte, Tiago Oliveira, Hugo Pacheco, Benedikt Schmidt, and Pierre-Yves Strub. 2017. Jasmin: High-Assurance and High-Speed Cryptography. In Proceedings of the 24th ACM SIGSAC Conference on Computer and Communications Security (CCS '17). ACM.
[42] Marco Patrignani and Marco Guarnieri. 2021. Exorcising Spectres with Secure Compilers. In Proceedings of the 28th ACM Conference on Computer and Communications Security (CCS '21). ACM.
[43] John L. Hennessy and David A. Patterson. 2011. Computer Architecture, Fifth Edition: A Quantitative Approach (5th ed.). Morgan Kaufmann Publishers Inc., San Francisco, CA, USA.
[44] A. Sabelfeld and D. Sands. 2005. Dimensions and principles of declassification. In 18th IEEE Computer Security Foundations Workshop (CSFW'05). 255–269. https://doi.org/10.1109/CSFW.2005.15
[46] Martín Abadi, Mihai Budiu, Úlfar Erlingsson, and Jay Ligatti. 2005. Control-Flow Integrity. In Proceedings of the 12th ACM Conference on Computer and Communications Security (Alexandria, VA, USA) (CCS '05). Association for Computing Machinery, New York, NY, USA, 340–353. https://doi.org/10.1145/1102120.1102165
[47] Nathan Burow, Scott A. Carr, Joseph Nash, Per Larsen, Michael Franz, Stefan Brunthaler, and Mathias Payer. 2017. Control-Flow Integrity: Precision, Security, and Performance. ACM Comput. Surv. 50, 1 (apr 2017). https://doi.org/10.1145/3054924
[48] Vedvyas Shanbhogue, Deepak Gupta, and Ravi Sahita. 2019. Security Analysis of Processor Instruction Set Architecture for Enforcing Control-Flow Integrity. In Proceedings of the 8th International Workshop on Hardware and Architectural Support for Security and Privacy (HASP '19). ACM.
[50] Manuel V. Hermenegildo, Francisco Bueno, Manuel Carro, Pedro López-García, Edison Mera, José F. Morales, and German Puebla. 2012. An overview of Ciao and its design philosophy. Theory and Practice of Logic Programming 12, 1-2 (2012), 219–252.
[51] Aaron R. Bradley and Zohar Manna. 2007. The Calculus of Computation: Decision Procedures with Applications to Verification. Springer.
[52] Gilles Barthe, Pedro R D'argenio, and Tamara Rezk. 2004. Secure information flow by self-composition. In Proceedings of the 17th IEEE Computer Security Foundations Workshop (CSF '04). IEEE.
[54] Google. 2019. SafeSide. https://github.com/google/safeside
[55] Claudio Canella, Jo Van Bulck, Michael Schwarz, Moritz Lipp, Benjamin von Berg, Philipp Ortner, Frank Piessens, Dmitry Evtyushkin, and Daniel Gruss. 2019. A Systematic Evaluation of Transient Execution Attacks and Defenses. In Proceedings of the 28th USENIX Security Symposium (USENIX Security '19). USENIX Association.
[56] Goran Doychev, Boris Köpf, Laurent Mauborgne, and Jan Reineke. 2015. CacheAudit: A Tool for the Static Analysis of Cache Side Channels. ACM Trans. Inf. Syst. Secur. 18 (2015).
[57] Sparsh Mittal. 2017. A survey of value prediction techniques for leveraging value locality. Concurrency and computation: practice and experience (2017).
[58] Mikko H. Lipasti, Christopher B. Wilkerson, and John Paul Shen. 1996. Value locality and load value prediction. In Proceedings of the 7th International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS '96). ACM.
[59] Sunjay Cauligi, Craig Disselkoen, Daniel Moghimi, Gilles Barthe, and Deian Stefan. 2022. SoK: Practical Foundations for Software Spectre Defenses. In Proceedings of the 43rd IEEE Symposium on Security and Privacy (S&P '22). IEEE.
[60] Gilles Barthe, Sunjay Cauligi, Benjamin Grégoire, Adrien Koutsos, Kevin Liao, Tiago Oliveira, Swarn Priya, Tamara Rezk, and Peter Schwabe. 2021. High-Assurance Cryptography in the Spectre Era. In Proceedings of the 42nd IEEE Symposium on Security and Privacy (S&P '21). IEEE.
[61] Caroline Trippel, Daniel Lustig, and Margaret Martonosi. 2018. MeltdownPrime and SpectrePrime: Automatically-Synthesized Attacks Exploiting Invalidation-Based Coherence Protocols. CoRR (2018). arXiv:1802.03802
[62] Michael Schwarz, Martin Schwarzl, Moritz Lipp, Jon Masters, and Daniel Gruss. 2019. NetSpectre: Read Arbitrary Memory over Network. In Proceedings of the 24th European Symposium on Research in Computer Security (ESORICS '19). Springer.
[63] Julian Stecklina and Thomas Prescher. 2018. LazyFP: Leaking FPU Register State using Microarchitectural Side-Channels. CoRR (2018). arXiv:1806.07480
[64] Alejandro Cabrera Aldaya, Billy Bob Brumley, Sohaib ul Hassan, Cesar Pereida García, and Nicola Tuveri. 2019. Port Contention for Fun and Profit. In 2019 IEEE Symposium on Security and Privacy (SP). 870–887. https://doi.org/10.1109/SP.2019.00066
[65] Moritz Lipp, Andreas Kogler, David Oswald, Michael Schwarz, Catherine Easdon, Claudio Canella, and Daniel Gruss. 2021. PLATYPUS: Software-based Power Side-Channel Attacks on x86. In 2021 IEEE Symposium on Security and Privacy (SP). 355–371. https://doi.org/10.1109/SP40001.2021.00063
[66] Guoxing Chen, Sanchuan Chen, Yuan Xiao, Yinqian Zhang, Zhiqiang Lin, and Ten H. Lai. 2019. Stealing Intel Secrets from SGX Enclaves via Speculative Execution. In Proceedings of the 4th IEEE European Symposium on Security and Privacy (EuroS&P '19). IEEE.
[67] Kevin Cheang, Cameron Rasmussen, Sanjit Seshia, and Pramod Subramanyan. 2019. A Formal Approach to Secure Speculation. In Proceedings of the 32nd IEEE Computer Security Foundations Symposium (CSF '19). IEEE.
[68] Basavesh Ammanaghatta Shivakumar, Jack Barnes, Gilles Barthe, Sunjay Cauligi, Chitchanok Chuengsatiansup, Daniel Genkin, Sioli O’Connell, Peter Schwabe, Rui Qi Sim, and Yuval Yarom. 2023a. Spectre Declassified: Reading from the Right Place at the Wrong Time. In Proceedings of the 44th IEEE Symposium on Security and Privacy (S&P '23). IEEE.
[69] Ross McIlroy, Jaroslav Sevcík, Tobias Tebbi, Ben L. Titzer, and Toon Verwaest. 2019. Spectre is here to stay: An analysis of side-channels and speculative execution. (2019). arXiv:1902.05178
[70] Basavesh Ammanaghatta Shivakumar, Gilles Barthe, Benjamin Gregoire, Vincent Laporte, Tiago Oliveira, Swarn Priya, Peter Schwabe, and Lucas Tabary-Maujean. 2023b. Typing High-Speed Cryptography against Spectre v1. In 2023 IEEE Symposium on Security and Privacy (SP).
[71] Robert J. Colvin and Kirsten Winter. 2019. An Abstract Semantics of Speculative Execution for Reasoning About Security Vulnerabilities. In Proceedings of the 19th Refinement Workshop (Refine '19). Springer.
[72] Craig Disselkoen, Radha Jagadeesan, Alan Jeffrey, and James Riely. 2019. The Code That Never Ran: Modeling Attacks on Speculative Evaluation. In Proceedings of the 40th IEEE Symposium on Security and Privacy (S&P '19). IEEE.
[73] Xaver Fabian, Marco Patrignani, Marco Guarnieri, and Michael Backes. 2025. Do You Even Lift? Strengthening Compiler Security Guarantees against Spectre Attacks (POPL'25). ACM, New York, NY, USA. https://doi.org/10.1145/3704867
[74] N. Mosier, H. Nemati, J. C. Mitchell, and C. Trippel. 2024. Serberus: Protecting Cryptographic Code from Spectres at Compile-Time. In 2024 IEEE Symposium on Security and Privacy (SP). IEEE Computer Society, Los Alamitos, CA, USA, 48–48. https://doi.org/10.1109/SP54263.2024.00048
[75] AMD. 2021. Security analysis of AMD predictive store forwarding. https://www.amd.com/system/files/documents/security-analysis-predictive-store-forwarding.pdf. Accessed: 2024-03-11.
[76] Oleksii Oleksenko, Flavien Solt, Cédric Fournet, Jana Hofmann, Boris Köpf, and Stavros Volos. 2026. Enter, Exit, Page Fault, Leak: Testing Isolation Boundaries for Microarchitectural Leaks. In Proceedings of the 47th IEEE Symposium on Security and Privacy (S&P). https://arxiv.org/abs/2507.06039 To appear.
[77] Tiziano Marinaro, Pablo Buiras, Andreas Lindner, Roberto Guanciale, and Hamed Nemati. 2024. Beyond Over-Protection: A Targeted Approach to Spectre Mitigation and Performance Optimization. In Proceedings of the 19th ACM Asia Conference on Computer and Communications Security (ASIA CCS '24). Association for Computing Machinery, New York, NY, USA. https://doi.org/10.1145/3634737.3637651
[78] Hamed Nemati, Pablo Buiras, Andreas Lindner, Roberto Guanciale, and Swen Jacobs. 2020. Validation of Abstract Side-Channel Models for Computer Architectures. In Computer Aided Verification: 32nd International Conference, CAV 2020, Los Angeles, CA, USA, July 21–24, 2020, Proceedings, Part I. Springer-Verlag, Berlin, Heidelberg. https://doi.org/10.1007/978-3-030-53288-8_12
[79] Bo Fu, Leo Tenenbaum, David Adler, Assaf Klein, Arpit Gogia, Alaa R. Alameldeen, Marco Guarnieri, Mark Silberstein, Oleksii Oleksenko, and Gururaj Saileshwar. 2025. AMuLeT: Automated Design-Time Testing of Secure Speculation Countermeasures. In Proceedings of the 30th ACM International Conference on Architectural Support for Programming Languages and Operating Systems, Volume 2 (ASPLOS '25). ACM. https://doi.org/10.1145/3676641.3716247
[80] Gilles Barthe, Marcel Böhme, Sunjay Cauligi, Chitchanok Chuengsatiansup, Daniel Genkin, Marco Guarnieri, David Mateos Romero, Peter Schwabe, David Wu, and Yuval Yarom. 2024. Testing Side-channel Security of Cryptographic Implementations against Future Microarchitectures. In Proceedings of the 2024 on ACM SIGSAC Conference on Computer and Communications Security (CCS '24). ACM. https://doi.org/10.1145/3658644.3670319