1
votes

Why isn’t virtual address (VA) separation enough to mitigate the various spectre & meltdown flaws? I mean the generic ones, not including the one that attacks the intel p-cache == v-cache hack; that was such an obviously bad idea, I can’t find any sympathy.

As a base line:

  1. My kernel address space (AS) only shares one text and data page with the user AS. Those pages contain just enough code and data to save and store registers; load a new memory context, and jump to the appropriate place. Thus, there are no interesting addresses to uncover here.

  2. No process ASs from exec have any VAs in common. That is, every VA allocation is taken from a common pool, so that even shared objects like libc are at a different address in every process. Most unix-derived folks would find this odd, but it is certainly feasible; I did it once by mistake^H*10/for testing.

  3. Fork()’d processes images are sandboxed if they are in separate access control domains, to prevent cross leakage. Sandboxing can involve context switch cache eviction, cpusets that exclude hyper-threads, all the way up to a non-interference kernel.

I understand that [1] is the basic mitigation for meltdown-related problems; and [2] is a broadening of [1] so it applies to spectre. [3] would cause performance problems, but again, limited to just those cases.

1
What are you talking about with attacks the intel p-cache == v-cache hack? I understand exactly what Spectre and Meltdown are and how they work, but that doesn't sound anything like either of them. It sounds like you're talking about a VIPT L1d cache that avoids aliasing problems by being associative enough that the index bits all come from the offset within a page (and thus translate for free, so the cache behaves like a PIPT but can still do the TLB translation in parallel with fetching data+tags from the indexed set). That's not the cause of Meltdown.Peter Cordes

1 Answers

3
votes

Meltdown attack depend on (speculatively) accessing the target virtual address directly (from within the attacking process)1.

But Spectre is not. You prime the branch predictor so that the code under attack speculatively accesses its own virtual address space, which it has permission to do. Branch-predictor aliasing means you can usually / sometimes prime the prediction for a branch at a virtual address you can't / don't have mapped. (e.g. in the kernel.)

The usual side-channel, a cache-read attack, is based on evicting the cache for an array in your own address space. But other side-channels are possible to get the Spectre data from the target back to the attacker, like priming the cache and then looking for which entry was evicted by a conflict-miss for an address which aliases some memory in the process under attack. (Harder because L3 cache in modern x86 CPUs uses a complex indexing function, unlike simpler caches which use a simple range of bits as the index. But possibly you could use L2 or L1d misses. L2 miss / L3 hit should still be measurably longer than an L2 hit.)

Or with SMT (e.g. Hyperthreading), an ALU timing attack where the Spectre gadget creates data-dependent ALU port pressure. In this case the only relevant memory access is the data under attack (which is allowed by the hardware, only mis-speculation of the branch causes a rollback, not a load fault).


When attacking the kernel, it will have the physical memory pages of the attacking process mapped somewhere. (Most kernels map all of physical memory to a contiguous range of virtual addresses, allowing easy access to any physical address.) Caching is based on physical addresses, not virtual.

A Spectre gadget that makes a cache line hot via a different mapping for the same page still works.

In the context of a system call, the kernel usually keeps user-space memory mapped to the same virtual addresses it was using inside the process, so system calls like read and write can copy between user-space and the pagecache. And many system calls pass user-space pointers to filenames. So when attacking the kernel, a Spectre gadget can directly use user-space addresses in the attacking process.

The Spectre gadget itself could maybe even be in user-space memory, although with separate page tables to work around Meltdown, you might mitigate that by setting the kernel page tables to have user-space VAs mapped without exec permission.


Footnote 1: Meltdown is a bypass for the U/S bit in the page tables, allowing user-space to potentially read any memory the kernel leaves mapped. And yes, [1] is a sufficient workaround. See http://blog.stuffedcow.net/2018/05/meltdown-microarchitecture/.