The Clever Engineering Behind Intel's Chipocalypse
When computer security collides with computer efficiency.
This week it came to light that Intel's x86-64 processors, which power the vast majority of personal computers, have a serious (if overhyped) security bug. It's bad enough to require significant reworking of the Linux and Windows kernels, the basement-level operating system code that's responsible for mediating access to a machine's CPU, system memory (RAM), and input/output (I/O) devices, which include everything from keyboards to hard-discs. Fixing an operating system's kernel is a bit like doing surgery on its brain.
In a computer, the kernel is the root of all roots and has access to everything. There's no hiding from the kernel. Having access to the kernel then means having access to everything on a machine. It's a core principle that the kernel should remain protected from the normal happenings of the surrounding computer. Interactions with the kernel are thus very tightly mediated. For a piece of software to, say, write some data to memory, it has to talk to the kernel via what's known as a system call.
Most developers don't deal with system calls. They're abstracted away, for the most part. To be writing software that makes system calls, you'd most likely be writing code in the C programming language that exists to support other software or higher-level programming languages, like Python or Java. Which doesn't mean system calls are rare. Rather, they happen constantly in a torrent of requests, which are delegated to underlying hardware through a process known as threading. Threading is what gives a computer the appearance of uninterrupted, seamless operation, even though it's really operating within a ceaseless cascade of interruptions.
If the kernel is so protected, how is it constantly interacting with the rest of the machine? It's the solution to this problem that's behind the current bug.
In short, computer programs exist on a machine in the form of processes. A normal PC will have a lot of processes running concurrently (in the terminal, type "ps -A" on Unix/Mac or "tasklist" on Windows to see all your currently running processes). Each one has its own little subsection of computer staked out, with its own private list of memory addresses (available memory slots, basically). The kernel is just kind of omnipresent within all of these processes, a part of them but also separate. A process can access the kernel through its own reserved memory addresses, but the kernel is not contained within that process.
The advantage of this setup is that it reduces the burden of what's known as context switching, which is the sort of messy and slow thing that happens when a processor flips between different processes. What this setup should not do is expose the whole damn kernel to each running process, but that's apparently what's been happening on x86-64 processors for a very long time.
To be sure, it isn't easy to access the kernel via this bug. But it's a Pandora's Box sort of thing—once it's out, it's out.
It's actually been out for a while. Last summer, a computer security researcher named Anders Fogh published a blog post describing the problem. This week, said post was picked up by the Register, and this is what has led to the current fuss, apparently including yesterday's response from Intel. Apple had already deployed a fix in a December macOS update.
The nature of the flaw has to do with the threading I mentioned above. And part of what makes threading work so well and so invisibly is something called "speculative execution."
A key principle in computer systems is instruction pipelining. To optimize processor usage, a system arranges instructions—atomic machine-level units of computation that are at the bottom of all software—in queues intended to minimize the number of wasted processor cycles. It's always looking for instructions that can be run in parallel on different computational subunits, which, in other words, are instructions that don't necessarily depend on the results of other instructions.
To build the most efficient instruction pipelines, the system kind of cheats. What can really slow its pipeline planning down is the fact it's not always known how programs will execute ahead of time. It's common for programs to "branch" conditionally. That is, they might behave in one way or another way depending on the value of a piece of data that's not yet available to the system. So it has to make allowances for that, which, in the worst case, means the system has to anticipate both outcomes.
In speculative execution, the system makes informed guesses as to which branch is most likely to be chosen. In some cases, this means that it may wind up executing instructions before its known whether those instructions need to be executed at all. Sometimes its wrong in its predictions and needs to unspool the results of the wrong branch and then go back and take the other branch. In aggregate, this technique makes for much faster computing.
The catch is that when a processor guesses a branch, it's bypassing an access control check and, for a moment, exposing the protected kernel space to the user space. A clever hacker could theoretically take advantage of this exposure to peak at passwords and keys and other protected resources.
"In order to improve performance, many CPUs may choose to speculatively execute instructions based on assumptions that are considered likely to be true," Google's Matt Vinton and Pat Parseghian explain in a blog post. "During speculative execution, the processor is verifying these assumptions; if they are valid, then the execution continues. If they are invalid, then the execution is unwound, and the correct execution path can be started based on the actual conditions. It is possible for this speculative execution to have side effects which are not restored when the CPU state is unwound, and can lead to information disclosure."
Google found three possible exploits that take advantage of speculative execution and they aren't exclusive to Intel. They're baked into really any processor that uses speculative execution and this includes those from ARM and AMD as well, according to the post. (Though AMD has denied that such a thing would be possible.) Targeting Intel is a bit unfair, but it also seems to have known about this stuff for a long time before going public after a bunch of press and social media chatter.