|How Meltdown Works|
|Written by Mike James|
|Friday, 05 January 2018|
The news is full of Meltdown and Spectre attacks that appear to work on a wide range of current CPUs, particularly on Intel processors dating from 1995 on. The interesting part of the story is how the exploits work and how they could have been built into processors for so long without anyone noticing.
Also see: How Spectre Works
Of the two exploits Metldown is the easier to understand, implement and apparently protect against. It stems from the way a modern processor will try to run programs faster by using speculative execution. If you know how CPUs work at the simplest level you might be surprised to discover how sophisticated a modern processor has become. For example, most modern CPUs will execute code in parallel, including code that might never be needed. The usual example is branch prediction. If the flow of control divides at an if statement then you can make things go faster by executing the most likely branch ahead of the test. You might discover that you evaluated the wrong branch, i.e. the then rather than the else, but then you simply throw away your computation and start on the other branch.
This all seems very innocent and the whole idea of speculative execution doesn't seem to be a security risk. What could possibly go wrong?
Of course, the inventive mind of the "hacker" is able to fashion even the most innocent feature into an exploit and so it is with speculative execution. Suppose you write some code that loads some data that is in the operating system protected area - the kernel - and uses this data to compute the address of an element in an array to access something like:
The getByte instruction returns a value in the range 0 to 255 and this is used to access an element of the probeArray, which is 255 elements long. If this worked you would have successfully read a byte of data from the kernel - something you are not supposed to be able to do because this is private data and includes passwords, keys and so on. Indeed it doesn't work because the kernel memory is protected and the getByte instruction will fail with a runtime exception and the rest of your program will terminate. You never get to access the array element based on the data.
Now throw into the mix speculative execution. The processor will most likely have executed the probeArray access speculatively before the exception occurs - exceptions are complex and slow. This still isn't a security problem because the speculative results are thrown away and not made available in user space.
No harm done as speculative execution has eventually not made any changes to the system.
Not quite true because an element of the probeArray has been accessed and is now in the system cache. Before we started the program we made sure that none of the elements of probeArray were in the cache. So now all we have to do is read each element of the probeArray and measure how long the access takes. The access that is faster than the rest is the element that was cached by the speculative execution. Once we know which element was cached we know the value of data.
The speculative execution changed the architectural state of the CPU and this provides a covert channel through which we can smuggle secret data.
This means that we can now read any kernel memory location and discover what is stored there simply by trying to execute an illegal access and making use of speculative execution and caching to find what data would have been retrieved if it hadn't been illegal.
With some real world additions and complications, this is how Meltdown works. The researchers who uncovered the vulnerability implemented it and managed to read any Kernel memory location:
"With exception handling, we achieved average reading speeds of 123 KB/s when leaking 12 MB of kernel memory. Out of the 12 MB kernel data, only 0.03 % were read incorrectly. Thus, with an error rate of 0.03 %, the channel capacity is 122 KB/s."
Meltdown didn't actually work on AMD and ARM processors in the sense that it didn't retrieve any valid data however the general principle was shown to work - both architectures did execute instructions beyond the illegal instruction. It is speculated that the reason it didn't work might be the exact timing of the exception and all that is needed is some tweaking of the code.
The fix for Meltdown is to disable any memory mapping between kernel and user memory apart from areas that need to be shared - interrupt tables for example. This is done by the KAISER patch that is available for Linux. More advanced and better protection requires the use of indirection to hide kernel addresses - trampoline code. This slows programs that make a lot of use of the system.
"Meltdown changes the situation entirely. Meltdown shifts the granularity from a comparably low spatial and temporal granularity, e.g., 64-bytes every few hundred cycles for cache attacks, to an arbitrary granularity, allowing an attacker to read every single bit. This is nothing any (cryptographic) algorithm can protect itself against. KAISER is a short-term software fix, but the problem we uncovered is much more significant."
You can blame Intel and the other hardware manufacturers if you want to, but designing hardware for performance is a tough job. Designing it for performance and security is next to impossible:
"We expect that Meltdown and Spectre open a new field of research to investigate in what extent performance optimizations change the microarchitectural state, how this state can be translated into an architectural state, and how such attacks can be prevented."
Moritz Lipp, Michael Schwarz, Daniel Gruss, Thomas Prescher, Werner Haas, Stefan Mangard, Paul Kocher, Daniel Genkin, Yuval Yarom and Mike Hamburg
Revised paper now on ArXiv
or email your comment to: firstname.lastname@example.org
|Last Updated ( Wednesday, 10 January 2018 )|