The technically inclined can read the papers at Meltdown and Spectre but I will try for a less technical explanation.
Processor chips are supposed to be able to run multiple programs at once, while keeping the data of each program secret from the others. There is a special privileged program, called the operating system kernel, that coordinates all the activity. The kernel is necessarily allowed to read the data of any user program.
This isolation between the data of different programs, and between the secret data of the kernel and that of all user programs, is done by something called virtual memory. VM gives each program the illusion of a private memory space while in fact all the programs are using bits of the underlying real memory in a way coordinated by the kernel.
A user program simply does not have any way to ask for the contents of arbitrary real memory (and thus be able to read secrets of other program.) The memory of other programs is not present at all in the virtual memory of the attacker.
The relation between the user programs and the OS is a little different. For convenience, the kernel ususally has the entire physical memory “mapped” in its own virtual address space, and the kernel’s virtual space is also present in the virtual space of every user program. This is not supposed to be a problem because the kernel part of the memory is marked “kernel use only” and that restriction is enforced by the hardware. If a user program tries to read kernel memory, the hardware says “nope!”.
All this is just background.
Meltdown is a way for user programs to read kernel virtual memory, even though they are not supposed to be able to do it.
Spectre is a way for user programs to read the virtual memory of other user programs, even though they are not supposed to be able to do it.
Virtual memory is only one of the ways in which processors present a view that is different from the underlying reality. Another is the so called “architecture”. Most PC’s have an architecture called x86, due to Intel. AMD also makes chips with an x86 architecture. The architecture is the stuff that is visible to a program: instructions, registers, memory, and so forth. The general outline of a computer architecture is that of a central processing unit, containing registers and instructions, which talk to a memory unit, containing data. Neither thing is true, and hasn’t been true for 30 years.
Memory isn’t simply memory anymore! If you’ve looked inside a PC, you’ve seen those flat rulers with chips on them plugged in edgewise to the motherboard. Those are main memory. That part is true. The problem is that they are way too slow. It can take 60 to 100 nanoseconds to get data from main memory. In that time, the CPU can execute maybe 200–300 instructions. Something had to be done. Inside the CPU chip, there are smaller faster memories called cache. They automatically hold the most recently accessed and most frequently accessed data from memory. This works because programs tend to access the same stuff over and over and also to access nearby stuff.
CPUs aren’t just CPUs anymore! Executing a single instruction involves a 5–10 step process, fetching the instruction, decoding what it means, fetching the data it needs, maybe doing some complicated arithmetic, and storing the answer back where it goes. If CPUs did these things one at a time, they would be too slow, so the operation of many instructions are overlapped in a pipeline of work. It turns out that that is not nearly enough speedup, so many modern CPUs execute instructions “out of order”. They look ahead at instructions that are coming up and do as many as they can, even though earlier instructions have not finished. In order to avoid vast confusion, instructions are only allowed to finish in order, with “later” results being held in temporary storage until earlier instructions finish, even though all the work for the later instructions has already been done. Modern CPUs also engage in “speculative execution” which means they actually guess at what instructions will need to be executed sometime in the future and do them right away. Things like this happen due to IF THEN ELSE instructions in the program that could cause different instructions to execute. The CPU doesn’t really know which way the IF THEN ELSE (called a branch) will go, so it makes a very well educated guess.
Out of order and speculative execution are especially interesting due to those long memory delays. The CPU can be thinking about and running instructions several hundred instructions ahead of the “commit point”.
None of this violates the architectural rules. The program doesn’t see the results of instructions that were never supposed to execute, and can’t read memory it is not entitled to see…. Well it turns out it can.
The trick of Meltdown allows a program to read kernel virtual memory even though that is forbidden. The meltdown program, by some modest bluffing, tricks the CPU into speculatively executing a read from kernel memory and then using the result to choose which data to read from user memory.
The results of these reads are never reported to the user program, and in fact by the time the program logic gets to that point, the CPU knows the read would never have been executed anyway, so it doesn’t even produce the exception that would normally happen when a user program breaks the rules and tries to read kernel memory.
But… in the underlying physical machine, the microarchitecture, the reads from memory did happen, and that data was read into the caches we talked about earlier.
The user program can then measure how long it takes to read each location in the user memory and figure out that one of them is a lot faster than the others. That one is the one that was already brought into cache by the read that was never supposed to happen.
In short, the CPU speculatively executes a forbidden instruction, and leaves faint echos in the timing of reading different memory locations, and those echos permit the meltdown attack to read, pretty quickly and reliably, secret data from the OS kernel.
Spectre is even more subtle. In Spectre, a user program can affect the behavior of a different user program by tricking the processor into speculatively executing a read whose address is under control of the attacker. The program being attacked would never do this normally, and doesn’t even find out about it, because all the speculative work is thrown away. However, in the underlying hardware, the read did happen and leaves some of those faint echos in the form of detectably different timing of events that the attacker can measure.
None of this is new, unfortunately! Processor chips have had the features that enable Meltdown and Spectre for over 20 years, and they went unnoticed. Fortunately, Meltdown is relatively easy to fix in software, at some cost in performance, by patching the operating system, If kernel memory is not mapped into user space, even with protections, then the user program cannot learn anything. Spectre is harder to fix and at present seems to require patching every program individually that you wish to protect. And this is the good news!
This business of computers leaking information by subtle changes in timing that can be caused by and measured by an attacker is a kind of thing called a “Side Channel Attack” in the security business. Unfortunately, there is no general way to protect against side channel attacks. All that anyone knows how to do is to limit the rate at which the attacker can steal data. That’s good if you are trying to prevent the theft of something big, like a digital movie, but it doesn’t really help if you are trying to prevent the theft of something small, like a password.
Already in the month or so since Meltdown and Spectre came to light we have additional problems, such as “Meltdown Plus” that exploits a completely different microarchitectural mechanism.
It may be that the only thing to do is to have multiple small CPUs that are really quite independent, so you never never run untrusted software on the main processor, but only in a private little machine that shares nothing