Since the 1990s, processors—the brains of computers—have pushed processing speed to its limits by predicting ahead of time where a program will go and performing calculations in advance. Since a vulnerability was discovered in 2018, the industry has ensured safety by resetting this prediction mechanism to a clean state immediately before handling sensitive operations. However, the tiny gap that exists between the moment the reset instruction is issued and the moment the predictor is actually used has become the entry point for a new attack.

AD

Speculative Execution and the Historical Problem Left Behind by Spectre

The Logic of Looking Ahead to Overcome the Limits of Processing Speed

For more than half a century, processors—the brains of computers—have continually devised ways to increase clock frequency. At the core of this effort lies a technology called Speculative Execution.

Modern programs consist of countless conditional branch instructions. In a process that checks whether a given user has legitimate authority, an approval process runs if the user has authority, and a rejection process runs if not. When a processor encounters a conditional branch instruction, reading data from main memory takes hundreds of clock cycles. If the processor waited for this data before proceeding, most of its computational units would sit idle.

To avoid this, processors use an internal mechanism called a branch predictor to guess, based on past execution history, which path is highly likely to be taken, and execute the relevant instructions in advance. This prediction is supported by dedicated hardware structures such as the BTB (Branch Target Buffer), which stores branch target addresses, and the RSB (Return Stack Buffer), which records return addresses from function calls. These structures hold past execution results as tables, serving as guideposts for when the same instruction appears again. If the prediction is correct, processing proceeds quickly. If the prediction is wrong, the results computed ahead of time are discarded, and the processor's state is rolled back to the correct path. At first glance, it appears as though nothing happened, but a minute physical trace remains in the cache memory indicating that specific data was loaded.

The Impact of Spectre, Which Steals Data from Residual Traces

In 2018, a technique was discovered that measures the difference in data read times from these residual traces to steal confidential information that should not be accessible. This was the Spectre vulnerability, which shook the industry.

An attacker runs their own program on the same processor as the victim's program, then measures the time it takes to access a specific memory region. If the data exists in the cache, the access finishes in a few nanoseconds; if it must be fetched from main memory, it takes hundreds of nanoseconds. This technique is called Flush+Reload: it evicts specific data from the cache in advance, then reloads it after the victim's process runs and measures the timing, allowing the results of speculative execution to be read with high precision. By observing this time difference, the attacker infers what the victim's program loaded during speculative execution, reconstructing confidential information bit by bit.

In particular, a variant known as Spectre v2 targets the branch predictor itself. A program's branch predictor is a resource shared across the entire system. An attacker feeds the predictor a large number of dummy branch instructions, training it with a false history that always jumps to a specific address under certain conditions. When control then passes to the victim's program, the victim's program follows the false history planted by the attacker and speculatively executes a jump to an unexpected address. Data that the victim process unintentionally loaded remains in the cache, and the attacker extracts information from it. Chip manufacturers have been forced to build multilayered defenses spanning both software and hardware.

The Pitfall Hidden in the Defense of "Cleaning Before Use"

The Basic Strategy of Resetting the Predictor

The current mainstream defense approach against Spectre v2 is a mitigation strategy based on disabling the prediction mechanism. Mechanisms such as Intel's eIBRS and AMD's Safe RET fall into this category. For example, Intel's eIBRS logically separates the predictor's history by privilege level, preventing history left by a low-privilege program from affecting a high-privilege program. AMD's mechanism similarly resets the predictor's internal state whenever privilege levels switch.

The logic behind these defenses is straightforward. The operating system erases the predictor's history at the moment execution authority transitions from a general user program to the kernel, which manages the entire system. Even if a malicious program has set a trap in the branch predictor, it can simply be flushed away right before entering a highly sensitive area. The idea is to neutralize any attacker interference by resetting to a clean state immediately before use. A strong checkpoint has been established to prevent suspicious learned history on the user side from carrying over into the kernel side.

Bringing a Software Vulnerability Model into the Physical Layer

However, Daniël Trujillo and Mengjia Yan, researchers at the Massachusetts Institute of Technology Computer Science and Artificial Intelligence Laboratory (MIT CSAIL), spotted a hidden assumption in this defense: the assumption that from the moment the predictor's data is erased until the moment the now-supposedly-safe predictor is actually used, no malicious process intervenes.

In the world of software, there is a long-known vulnerability class called TOCTOU (Time-of-Check to Time-of-Use), which exploits the tiny time gap between checking a file's access permissions and actually opening the file. If another program swaps out the file immediately after the permission check, a file that should be inaccessible can end up being accessed.

The research team brought this concept into the dimension of hardware microarchitecture. There is a slight but nonzero time gap between the moment a processor receives an instruction to clear the predictor and the moment it next executes an instruction that uses branch prediction. They named this attack class, which targets this gap, TONTOU (Time-of-Neutralization to Time-of-Use), and presented it at the security conferences Black Hat USA 2024 and USENIX Security '24.

AD

Hardware Interrupts That Pierce the 6-Byte Gap

The Limits of Reset: It Doesn't Happen in Zero Clocks

Even when the defense mechanism resets the predictor, in the physical processing of electrical signals within the processor, the clearing and the subsequent use do not occur simultaneously in zero clock cycles. According to the research team's analysis, on AMD's Zen 2 architecture, this gap spans 2 instructions, a distance of 6 bytes.

Processors run at speeds of several gigahertz—that is, several billion clock pulses per second. Normally, no other program can slip in during such an extremely short window. The gap of 2 instructions passes in a matter of nanoseconds, and it was considered nearly impossible to deliberately target it from outside.

Precision Targeting Through Timer Manipulation

The research team therefore developed a technique that abuses hardware interrupts. A computer's operating system has a mechanism for pausing the currently running process and inserting a different process, in order to respond to events such as keyboard input or the arrival of a network packet.

In a Linux environment, even an ordinary user without special privileges can, through a system call, set an interrupt timer with nanosecond-level precision. The attacker triggers the interrupt at the exact moment when just 2 instructions execute—right after the processor resets the predictor, and right before the sensitive code uses branch prediction.

When an interrupt occurs, the processor suspends the currently executing process and runs a different program within the kernel called an interrupt handler. This interrupt handler itself executes numerous branch instructions in the course of its own processing. As a result, the branch predictor, which had just been cleared, has the branch history of the interrupt handler newly recorded into it. Consequently, the predictor that the defense mechanism worked hard to keep clean is contaminated again with malicious state, and control then returns to the original process. The research team calls this specific attack technique INTERRUPT INJECTION.

Stretching Time by Manipulating the Cache Hierarchy

Deliberate Cache Depletion via a Sibling Thread

Even with a highly precise timer setting, hitting a gap of just a few nanoseconds with an interrupt is extremely difficult. To solve this problem, the research team employed a tactic that stretches out the timing window using the processor's cache hierarchy.

Computer memory has a layered structure: a small but extremely fast L1 cache, an intermediate L2 cache, and a large but slow main memory. The team used a separate thread running on the same physical core to overwrite the L1 and L2 cache regions holding the target instructions with a large amount of irrelevant data. Because modern processors share caches across multiple threads, when one thread accesses a large amount of memory, the data that the other thread needs gets evicted from the cache.

When the processor tries to execute the instruction immediately preceding the gap, that instruction's data has already vanished from the fast cache. The processor is then forced to fetch the data from slow main memory, and processing stalls for hundreds of clock cycles. This delay artificially stretches out the time it takes to pass through the 6-byte gap, and the probability of the interrupt landing successfully rose dramatically, from 5 percent to 12 percent.

Guiding the Attack Route Through Register Control

Having succeeded in stretching out the timing window, the attacker layered on further refinements to increase precision. When interrupt handling finishes and control returns to the original process, unless the direction of the jump is controlled, the speculative execution that leaks information will not occur.

The research team analyzed in detail the system calls referenced during the execution of the interrupt handler, and identified instructions whose specific register values are easy for an attacker to control. When invoking a system call, an attacker can set arbitrary values in general-purpose registers. This value gets loaded into the predictor during the execution of the interrupt handler, and is recorded as a fake jump history pointing to an address specified by the attacker. By manipulating the registers exactly as intended, the attacker reliably trains the supposedly clean branch predictor, after the interrupt ends, to learn a malicious jump target. Through this precise guidance, the target process ends up speculatively executing into the memory region the attacker desires, on its own.

AD

The Wall of Privilege Separation, Collapsing in 18 Minutes

The Experimental Environment That Slips Past Mitigations

This theoretical vulnerability carries enough destructive power to succeed as an actual attack. The research team conducted verification experiments using an AMD Zen 2 system running Linux 6.1.4 with all default Spectre v2 countermeasures enabled.

Comparison Item Conventional Spectre v2 Attack TONTOU (INTERRUPT INJECTION)
Attack timing Before the defense mechanism runs The gap between the defense mechanism running and the actual branch processing
Primary targeted state The entire branch predictor history The empty branch predictor immediately after being cleaned
Defense mechanism bypassed Software-based boundary checks, etc. Latest mitigations such as AMD Safe RET and Intel eIBRS
System function exploited The program's ordinary branch instructions Nanosecond-level hardware timer interrupts

Leaking Confidential Data at 5.47 Bytes per Second

Launching the attack from an ordinary user process without special privileges, the team succeeded in reading data from kernel memory at a rate of 5.47 bytes per second. The accuracy of the reads reached 91.97 percent.

The target was a sensitive file storing the password hashes of all users on the system. Modern operating systems enforce strict privilege separation to prevent ordinary users from accessing the core of the system. Normally, this file can only be read by a system administrator with the highest privileges.

However, in 5 out of 10 trials, the team successfully pinpointed the exact location of the file and read its contents. Each successful attempt took an average of about 18 minutes. The leak rate of 5.47 bytes per second may seem slow at first glance, but it is more than sufficient to steal confidential information such as password hashes or encryption keys. Given just a few hours, data that could shake the foundations of a system could end up in the hands of outsiders. The fact that a confidential file could be exfiltrated at this speed and accuracy, even in the latest environment where defense mechanisms are supposedly active, demonstrates the limits of current disabling-based mitigations. According to the research team, branch mispredictions could also be induced on other architectures, including Intel's Cascade Lake Refresh and Arrow Lake, as well as AMD's Zen 4.

Toward a Fundamental Rethinking of Hardware Design

The Limits of Patch-Based Symptomatic Treatment

In response to the discovered vulnerability, AMD and Intel are moving forward with software patches through Linux kernel updates. These are attempts to restrict control over specific registers, minimizing the impact of an interrupt landing in the gap.

However, in the physical processing of hardware, unless the clearing and use of the predictor can be executed within the same clock cycle, it is difficult to completely eliminate the time gap itself. Even if a software update narrows the gap of a few instructions, as long as room remains for an external interrupt to slip in, the risk that a similar technique will reappear in a different form does not disappear.

An Unresolved Problem Lurking at the Foundation of the Architecture

In their pursuit of processing speed, the latest processors have intertwined complex prediction mechanisms with interrupt handling in ever more layers. How should the minute time gap lurking at the foundation of the architecture be eliminated at the design stage?

This problem is not limited to the existing x86 architecture. As long as different instruction set architectures such as RISC-V and ARM implement speculative execution and interrupt mechanisms, gaps arising from the same underlying principle could potentially occur there as well. Achieving complete defense will require hardware design changes, such as mechanisms that delay the timing of interrupt occurrence on the processor side, or that completely isolate the predictor's state on a per-context basis.

How can a race condition of just a few nanoseconds, occurring at the boundary between software and hardware, be prevented at the physical layer of silicon? Under what conditions should interrupts be permitted against an increasingly complex prediction mechanism? Unresolved questions remain for the design of next-generation processors.