
A long two months: Reflecting on mitigating Meltdown - bcantrill
https://blog.cooperi.net/a-long-two-months
======
userbinator
_segmentation is the closest feature really, and it was thrown out for 64-bit
AMD64_

That was one of the "big things" with the 286 and protected mode, and enhanced
even further with the 386, so it's a bit ironic and sad that it can't be done
in 64-bit mode --- and I'm sure it could be done in a backwards-compatible
manner if AMD chose to (double-wide descriptors seem to be a reasonably
popular thought), but it feels like a lot of the decisions made with AMD64
were more just to spite Intel than benefit anything or anyone else.

Related: [http://www.pagetable.com/?p=25](http://www.pagetable.com/?p=25)

~~~
dcow
It's not so insidious as you suggest (from your link):

 _VMware chose not to support 64 bit virtualization until AMD reintroduced
(optional) segment limits on later models of their Opteron and Athlon 64 CPUs.
Intel never implemented 64 bit segment limits on their EM64T /Intel64 CPUs,
because their 64 bit processors soon implemented VT/Vanderpool, which also
worked around the problem. So this is why VMware requires a certain model and
stepping of the AMD CPU line or a VT-enabled Intel CPU in order to support 64
bit virtualization._

 _Intel_ was the one that dropped segment limits, AMD added them in later...

It sounds more like advances in hardware virtualization yielded better
solutions than a bunch of additional segment registers and slow context
switches. It's only now that we realize without those you can trick a
processor into fetching memory it shouldn't and that the only viable software
solution has been to effectively implement separate page tables and enforce
copying between their stack contexts at the user/kernel boundary anyway (so
we're back where we started with slow context switches).

In theory, you could mitigate specter by running every process in its own
hardware virtualized address space, right? It's just much more complicated to
do that because you'd need to move the kernel to the hypervisor ring or
rewrite everything to communicate entirely using a shared physical resource
like a network interface. If VT-x allowed shared memory regions with ownership
restrictions (does it?) you wouldn't even need to do that.

~~~
bitwize
Every process already _does_ run in its own virtualized address space, without
VT-x. That's what virtual memory is and does. Spectre can cross process
boundaries at points where processes have the same memory mapped into their
private address space (to wit: shared libs). If you enable VT-x VMs to share
chunks of memory, you'll have the same damn problem. (This may be what
"Spectre type 2" is, I'm not sure).

~~~
dcow
I thought the issue was that under the same kernel all pages mapped into
memory can be read because the processor does not perform the virtual memory
checks for the speculatively executing code...which is why the fix involves
unmapping pages on context switches. VT-x gives you "physical" isolation not
virtual, I thought. Like two VT-x spaces don't share the same page table
mappings, do they? I could be completely wrong.

~~~
bitwize
> I thought the issue was that under the same kernel all pages mapped into
> memory can be read because the processor does not perform the virtual memory
> checks for the speculatively executing code...which is why the fix involves
> unmapping pages on context switches.

That's Meltdown. In Meltdown's case, the processor does not perform the check
to see whether a mapped page is privileged, kernel memory (ring 0) or
unprivileged, user space memory before speculatively executing it, and that's
where the need to unmap kernel pages before leaving a syscall (and remap them
before entering one) comes from. Spectre is confined to a single process's
address space, so assuming no processes share code, an attacker would only be
able to leak information from within the same process via Spectre. Which is
enough a vulnerablility to warrant concern, as with precise enough timers you
could exfiltrate information (passwords, etc.) from anywhere in a browser
process via JavaScript. The problem is, processes share code all the time, via
shared libs, which makes Spectre attacks able to cross process boundaries.

VT-x is a hardware virtualization layer. It doesn't provide some sort of
_physical_ barrier to different contexts running on the same CPU wired to the
same RAM leaking memory.

~~~
mgerdts
> The problem is, processes share code all the time, via shared libs, which
> makes Spectre attacks able to cross process boundaries.

I don't think that is how it works. Just because multiple processes map the
same code (read-only) doesn't mean that they also have mappings to each
others' data. If two processes shared mappings to the same data (e.g. after a
fork() with no exec()) then what you say may be true.

Just because I can write a program that uses libc doesn't mean that I can use
that as a means to extract ssh keys from an ssh-agent that also is using libc.

~~~
bitwize
Actually, it does. By warming up the branch-target buffer to call a particular
function (called a "gadget") inside libc as the attacker, you can induce the
victim process to speculatively execute that function, and thereby leak data.
It's a bit more complicated and involved than Meltdown, or Spectre within the
same process, but it _is_ possible and depending on the gadget chosen, any
data within the victim process could be recovered.

~~~
mgerdts
I think you are now confirming what I was saying. The attacker uses a gadget
in libc (or any other code) to cause side effects that are effective for
reading memory within the process's address space.

Since each process has its own address space, this does not allow process A to
read memory from process B's address space. For this to happen, process A (the
attacker) would need to interact with process B to cause the speculation to
happen within process B. Or, as stated in the spectre paper:

> Drawing from return- oriented programming (ROP) [33], in this method the
> attacker chooses a gadget from the address space of the victim and
> influences the victim to execute the gadget speculatively.

Speculation performed within process A (my web browser) doesn't give you
access to the data within process B (ssh-agent).

Maybe I misunderstood the intent of your sentence that I initially quoted.

[edit to fix formatting]

~~~
bitwize
Process A uses repeated calls to the gadget to trick the CPU into thinking
"hey, that's a frequently jumped to place, I'd better remember that for
speculative execution." Then when Process B runs, when it comes up on a branch
instruction, it calls the gadget speculatively, bringing with it information
about process B across the call. This may require some interaction with
Process B, but it's minimal (opening a socket that Process B is listening on
might be enough).

Whatever computation resulted from the speculative call is discarded BUT its
effect on the cache is NOT. Process A can thus use timing information to
determine what's in the cache and thus, exfiltrate data from process B.

So no, you can't read memory across process boundaries directly. The CPU's
virtual memory mechanism provides at least that much. The significance of
Meltdown and Spectre is, that isn't enough. Using speculative execution, cache
trickery, and timing-based attacks, information CAN be exfiltrated from a
process even with virtual memory protection in place.

If this gets you paranoid about your ssh-agent leaking data, good. One
(relatively) easy way to mitigate this is to use the retpoline compilation
technique, which replaces function calls with a RET to the function location.
Because the target of a RET, being on the stack, is unknown up until the
moment it happens, current CPUs do not speculate across a RET. (Though were it
not for Meltdown and Spectre, maybe future CPUs might have made some guesses?)
So Process B could not be induced to speculatively call the gadget if it were
compiled with retpoline.

