Skip to content
This repository has been archived by the owner on Feb 28, 2023. It is now read-only.

Document policy on Spectre and similar vulnerabilities. #42

Open
lachlansneff opened this issue Jun 1, 2018 · 8 comments
Open

Document policy on Spectre and similar vulnerabilities. #42

lachlansneff opened this issue Jun 1, 2018 · 8 comments
Labels
design Design Discussions documentation help wanted Extra attention is needed question Further information is requested

Comments

@lachlansneff
Copy link
Contributor

While we're coming up with a policy in the dark sanctuary of the gitter room, we'd still like input on what people think we should decide here.

Right now, we're leaning towards mostly ignoring possible issues involving spectre, but allowing users to run untrusted code inside a hardware-protection domain, similar to singularity.

@lachlansneff lachlansneff added help wanted Extra attention is needed question Further information is requested design Design Discussions documentation labels Jun 1, 2018
@gmorenz
Copy link
Contributor

gmorenz commented Jun 1, 2018

I wanted to write down my thoughts on why I support this a bit more coherently.

Most permissions are more to guard against mistakes, then to provide security against malicious actors. This is why we have a principal of least privilege even for instructions we control completely. Why giving people nopasswd sudo access makes sense. Why people like being able to run docker (the command to send messages to the daemon) without being root, even though it's trivial to escalate privileges to root. Etc.

Most of the time I only have two classes of security based privileges, let's call them trusted and untrusted. Trusted code has access to everything I care about, so restricting it with permissions is unnecessary. Untrusted code is run in a sandbox anyways, and could run in a hardware protection domain. Let's go through some examples to see what I mean:

In normal desktop code, nearly everything is trusted. The exceptions are programs I run in my browser, and the very rare binary that I really don't trust and run in a VM (for normal users the second category of untrusted code doesn't exist). Any code that runs under my user account has to be trusted, because there is no way in hell I would notice if it started ptracing my bash sessions and caused sudo to instead run fake_sudo that forwarded stuff to sudo but stole my password and ran other commands with the same permissions (just one example of a way to escalate privileges without using a vulnerability). Likewise if I made another user account and su'd to it, a process could do something like ptrace bash, make it not actually exit on ctrl-D but pretend to, and then do the above (or some more direct route like privilege escalation, finding a file I left around with permissive privileges, etc).

On server's I get a similar split. Some applications might be successfully walled out of root access, but pretty much everything falls into the category "program that can access user data (which is all I really care about protecting in the first place)", or "untrusted program that I'm running for a user". I imagine most people running servers have a pretty similar divide.

There are exceptions to this model. The obvious one is shared servers where many people have accounts protected from eachother via user privileges (e.g. nearlyfreespeech.net). I think those are relatively rare in the days of cheap VPSes, and we can mostly ignore for now. If you ran one of those and really wanted to you could (in the future) force every user process to run in a hardware protectd domain.

Another sorta-exception is mobile computing. Here people run lots of mostly untrusted apps, and use permissions to determine what they can access. To the extent that you believe that bypassing those permissions is impossible, we are giving up some capability here. To the extent that you think the long stream of android vulnerabilities suggests that these permissions are only really important for controlling what processes are allowed to do, instead of what they can do, it's completely irrelevant.

And finally, all this is irrelevant anyways if we one day get non-broken hardware. So I'd rather not gimp nebulet today to mitigate a vulnerability that may not even matter by the time nebulet becomes at all mainstream.

@orent
Copy link

orent commented Jun 4, 2018

The Meltdown and Spectre attacks are all based on speculative execution that accesses pages which are mapped but have their permissions disabled.

The solution is simple: never map such pages. A page in the virtual address space is either mapped and accessible on unmapped - never mapped but inaccessible. Note that this only refers to read or execute permission. Pages can have their write access enabled or disabled, as required.

If the webassembly mechanism is, indeed, strong enough to safely run untrusted code in ring 0 (the whole point of Nebulet) then you need not worry about these attacks at all.

@lachlansneff lachlansneff added this to the Minimal Viable Product milestone Jun 11, 2018
@lachlansneff
Copy link
Contributor Author

Actually, we may not have to worry too much about spectre and meltdown. The property of the wasm runtime on Nebulet that allows it to elide software bounds-checking may be enough, when matched with retpolines, to mitigate all variants of spectre and meltdown.

@orent
Copy link

orent commented Jun 12, 2018

Let’s say we have only wasm32 user processes. Give each one a whole 4GB address space. You have 2^16 of them under the current 48 bit limit.

All pages in that space are either mapped or unmapped. No pages are mapped-but-not-allowed. All access is by instructions that add a 64 bit process base to a 32 bit user pointer.

There is just no way to exploit speculative execution this way.

Wasm64 is a bit more complicated, but equivalent.

@IsaacWoods
Copy link

How much of the advantages of not having to do real context switches does that negate though?

@lachlansneff
Copy link
Contributor Author

@IsaacWoods As far as I can tell, none.

@IsaacWoods
Copy link

@lachlansneff for a start, wouldn't you need to flush the TLB? Depending on how much kernel code you're calling into (wasm runtime code?), that will at least have some impact?

@lachlansneff
Copy link
Contributor Author

@IsaacWoods Actually no, the reason why I've gone with a single address space for all the processes is to avoid needing to flush the tlb (And some other stuff).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
design Design Discussions documentation help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants