6 ms·
No. The paper notes that Spectre can, and will in the future be able to defeat all programming language level techniques of isolation. With properly designed Oo
by Tuna-Fish 8y ago
No. The paper notes that Spectre can, and will in the future be able to defeat all programming language level techniques of isolation. With properly designed OoO, Spectre cannot defeat process isolation. The fundamental lesson that everyone must take to heart is that in the future, any code running on a system, including things like very high-level languages running on interpreters, always have full read access to the address space of the process they run in. Process isolation is the most granular security boundary that actually works.
Or in other words, running javascript interpreters in the same address space as where you manage crypto is not something that can be done. Running code from two different privilege levels in the same VM is not something that can be done. Whenever you need to run untrusted code, you need to spin up a new OS-managed process for it.
- downer52 8y agoExcept there was a time before this class of exploitation. And so, now, there cannot be a time after? Doubtful.
- elihu 8y agoWhat about languages that prevent the program from reading the current time or determining whether some local computation finished before or after some external event? (I'm thinking of something like Haskell code that's executing outside of the IO monad.) Perhaps we just need to have a more restricted idea about what untrusted code is allowed to do.
- gizmo686 8y agoIn concept this could work. In practice, you bassicly need to design the language (or at least compiler and runtime) with this in mind from the beggining, otherwise you might forget about some backdoor. Eg, if you do Haskell and just verify the function you are running is not in the IO monad, you might miss some usage of UnsafePerformIO. Even if you check their code, if you let them specify dependencies they might manages to sneak a buggy use of UnsafePerformIO into a library they submitted to hackage. Plus, your restriction is essentially: no clock, no contact with the outside world, no threading, and a carefully considered interface to the host program to prevent time leaks. For many usecases, this is not workable
- elihu 8y agoBy "something like Haskell code executing outside the IO monad", I meant something like Haskell with the obvious backdoors turned off. (Ghc has a "safe haskell" option to disallow things like unsafePerformIO.) Disallowing direct access to the outside world is a big restriction, but it may be that a lot of the things you'd want to do inside a sandboxed application that aren't safe could be delegated to trusted code through an appropriate interface. Threading isn't necessarily a problem; the Haskell Par monad for instance should be fine as there is no program-visible way to know which of two sub-tasks executed in parallel finished first.
- gizmo686 8y agoFunny you mention Par. I suspect its IVar type could be used as a backdoor. The doc says to not return it, but Haskell does not enforce this.
- cannabis_sam 8y agoHow would that work?
- elihu 8y agoI think the problem is that runPar is currently allowed to return an IVar to the code that called it, which could then pass that IVar into a different runPar invocation. That's not something the runtime system expects, or the type system should allow.
- elihu 8y agoI looked that up in my copy of "Parallel and Concurrent Programming in Haskell" by Simon Marlow, and indeed you're right -- the runPar function shouldn't let you return an IVar, but it does. This is planned to be "fixed in a future release", but the current online documents say about the same thing. Presumably, this could be fixed easily by using the phantom type trick (same as ST) but it would make the type signatures ugly and possibly break existing code. (Maybe there's a more modern alternative to phantom types?) So, yeah, you might not want to use the Par monad as it's currently implemented in ghc as your secure parallel sandbox. The online docs suggest using lvish if you want a safer Par monad interface, which I'm not familiar with (though the lvish docs say that it's not referentially transparent if you cheat and use Eq or Ord instances that lie). The general idea seems sound, though -- it should be possible to have parallelism in a sandbox environment without allowing the sandboxed program to conditionally execute code based on which of several threads finished some task first.
- twtw 8y ago> With properly designed OoO, Spectre cannot defeat process isolation It's worth noting that no existing or announced common hardware is "properly designed" according to this condition. Even the "fixed" Intel hardware that's been announced is still vulnerable to spectre v1 across process boundaries.
- Zenst 8y agoI'm not aware of a spectre v1 attack for the altair 8800, or indeed any of the CPU's of that era, Z80, 6502, 8086/8.... But then, things moved on, standard ways to add more cache with multiple cores was lapped up and later on we found a design flaw that echoed back for a decade or more upon all these multi-core CPU's. Though in fairness and to put some context upon all this, CPU design is more complex than writing TAX laws. Yet we have exploits for TAX laws appearing and used all the time by large corporations. Whilst the comparison is not ideal and some would say, unfair. It does highlight that nothing is perfect and what we may class as perfect today (or darn close), could and may very well be classed as swiss cheese in the future. It gets down to how far away that future is. After all, we still have encryption utilised that we have (on paper) shown to be flawed to future quantum CPU's! But in a World that was aware of Y2k decades before the event, the penchant of business to drive everything to the last minute for profit will always be a factor in advancements. After all, if CPU cores had isolated caches instead of sharing, then that would mitigate so many issues, yet it would cost more to make and most consumers would not appreciate the extra cost for what to them is little value in return above and beyond the cheaper solution. That's business for you and CPU's are made by them for profit.
- Tuna-Fish 8y ago> It's worth noting that no existing or announced common hardware is "properly designed" according to this condition. Even the "fixed" Intel hardware that's been announced is still vulnerable to spectre v1 across process boundaries. AMD Zen is. Spectre v1 (bounds check bypass) only works inside processes. All it allows you to do is to read any memory location currently mapped into your address space, and so it gives anything that can execute code complete read access to the address space of the process it's running in. On Intel CPUs, this also allows reading the kernel address space, unless kpti is used. Eventually, the ability to read kernel memory will be removed, and so kpti becomes unneccessary. On all AMD post-BD cpus, spectre v1 cannot be used to read kernel address space. All the rest of spectre (and meltdown) can eventually be fixed, but it is effectively impossible to make a cpu that is both fast and doesn't exhibit spectre v1.
- pcwalton 8y agoSo this is something that I've never gotten a full answer to: what is the difference between a "thread" and a "process" in this model? This isn't a facetious question. A thread is just, at its core, a process that shares memory with another process. (In fact, this is how threads are implemented on Linux.) But all, or virtually all, processes also share memory with other processes. Text pages of DLLs are shared between processes. Browser processes have shared memory buffers, needed for graphics among other things. What separates processes that share memory from threads that share memory regarding Spectre? Is it the TLB flush when switching between processes that doesn't occur between threads? Or something else?
- twtw 8y agoFor meltdown (spectre v3, iirc) It's not so much sharing memory as sharing address space. Processes have different page tables. Threads within a process share page tables. For spectre v1 and v2, right now (on existing hardware) mostly nothing separates threads from processes. In the future, process isolation is a good candidate for designing hardware + system software such that different processes are isolated (via partitioning the caches, etc). You probably still want threads within a process to share cache hits.
- pcwalton 8y agoSo, if that's true, why is Chrome considered to have solved Spectre? Browser content processes from different domains share some memory. Moreover, if process boundaries don't have any effect on the branch predictor on current hardware, then why is process separation relevant at all? Doesn't all this mean Spectre is still an issue?
- twtw 8y agoI guess I jumped the gun a bit in my comment above. In terms of the possibility of exploit, as I understand there isn't at this point any isolation between processes. In terms of the ease of exploit, being able to run untrusted code in the same process as the victim helps quite a bit. Otherwise, you have to find a gadget (i.e. qualifying bounds check for v1, indirect branch for v2) in the victim process that you can exploit from the attacker process. Possible, but quite a bit harder than making your own gadget. This all ignores the forward looking reasons process isolation is a good idea. I can't keep track of the latest mitigations in Linux, but they pretty much all will only help between processes by flushing various hardware data structures. And hopefully someday we will have hardware actually designed to restore the guarantees of isolation between processes. I'm pretty sure this is accurate, but I'm just a random guy on the internet so don't trust my word for it too much.
- phkahler 8y ago>> The paper notes that Spectre can, and will in the future be able to defeat all programming language level techniques of isolation. That's why I said we need trusted cores - i.e. ones that don't implement speculative execution or share cache with other cores. Untrusted code needs to be run in physical isolation, not just virtual isolation. But the real solution to all of this is not to run untrusted code at all. This raises the question of how we come to trust the code we run. The simplest and most obvious thing we need to do is disable javascript. I mean how can you possibly trust code that came in a 3rd party payload used for advertising? How can you trust anything from Facebook? Or any of them? The answer is that you can't and in may cases should not.
- rasz 8y ago>and will in the future be able to defeat umm, "on today's hardware"
- brianpgordon 8y agoPutting aside the fact that I don't think you're actually disagreeing with the parent, I don't think it's really accurate to say that all programming level techniques of isolation are defeatable. The paper enumerates a specific set of vulnerable language features (e.g. "Indexed data structures with dynamic bounds checks"). The paper doesn't say much about languages lacking these features. Also, I believe retpoline is a (nearly?) perfect software fix for Intel's microarchitecture.