Care to argue how something based on sharing memory could ever be more secure than sending messages over pipes or sockets (between different processes)?
Care to argue how something based on sharing memory could ever be more secure than sending messages over pipes or sockets (between different processes)?
* For example, DoS-safe
... where the sharing is mediated by the kernel. You can't access the pipe/socket buffers directly from a user-space program.
EDIT: IIRC, POSIX message queues, at least on Solaris, are implemented SHM and clever queue bookkeeping. But MQs are not sockets or pipes.
There's no fundamental reason shared memory should be less safe than sockets (say); ultimately it's just bytes. Shared memory has a bad reputation because of how it behaves when processes sharing memory run concurrently, especially if they're both writing, but that's not a concern when we're talking about a unikernel interacting with the host, because there's no need to have anything happen concurrently there.
So you choose ONE for the message-passing mechanism. If the process does not incorporate code that opens a pipe and reads from it, you cannot force it to do so. Alternatively, there are all of these and you want to add VMCALL to that soup as well.
> There's no fundamental reason shared memory should be less safe than sockets (say); ultimately it's just bytes.
We're talking about a unikernel writing to the hypervisor's address space. A bug in the hypervisor's validation (or another exploit) will allow it to overwrite arbitrary memory in the hypervisor. Sockets will not.
But then you find that somewhere in the lower layers of the framework/interpreter you were using there's something that relies on it. You disable all the sysctls you thought you weren't using and then your image library turns out to need them. Once the functionality has ever existed in the ecosystem, it's very hard to get away from.
> Alternatively, there are all of these and you want to add VMCALL to that soup as well.
I want to deprecate all the others at the same time, otherwise there would indeed be no point.
> We're talking about a unikernel writing to the hypervisor's address space. A bug in the hypervisor's validation (or another exploit) will allow it to overwrite arbitrary memory in the hypervisor. Sockets will not.
What's the difference between a unikernel sending data to the hypervisor and a process sending data to the kernel? The data always has to cross the boundary one way or another. Why would one approach be any more or less safe than the other?
So you refrain from using the framework in question because the very same framework wouldn't work at all in the hypothetical VM because files do not exist there. You have to write everything from scratch using only your IPC mechanism of choice, just like with VMCALL.
> What's the difference between a unikernel sending data to the hypervisor and a process sending data to the kernel?
Ultimately, trust.
1. The developers. I have more confidence in the implementors of, say, Linux kernel, than in developers of, say, Chrome or Firefox or Safari.
2. Testing. Kernels routinely handle successfully vastly more corner-cases than web-browsers. [Yes, I see upon all of current Linux, Windows, etc. installations as continuous, live, in-production testing.]
If kernels were as shabby as today's browsers, nobody would use them for anything but toys. On the other hand, try to find a person who gets genuinely surprised when a web browser crashes.
It's always going to take a new standard and a new community/ecosystem that fits things into that new standard or rewrites the things that can't be fitted. The only way such an effort can ever hope to succeed is a) an extremely clear standard with a rigorous conformance test b) a way to run legacy programs that don't comply with the standard c) but in such a way that there are still incentives for programs to move onto the new way.
In theory we could create a stripped-down linux that only offered one limited form of IPC and then start porting libraries and processes to run on that stripped-down linux. But it would be difficult to get a consensus on exactly what system calls etc. are allowed, and what would you do for running legacy processes? You have to add the alternative IPC systems etc. back in and add an opt-out mechanism, and then a) every component, even well-behaved ones, loses the advantages of the new system (fast booting, low overhead and so on) b) there's very little incentive for a component to ever be ported to the new system.
> 1. The developers. I have more confidence in the implementors of, say, Linux kernel, than in developers of, say, Chrome or Firefox or Safari.
I'm not sure where web browsers comes into it. I have a lot more confidence in the unikernel folks than the container folks from what I've seen of their tool choices and code quality.
> Kernels routinely handle successfully vastly more corner-cases than web-browsers.
Kernels get very little direct exposure to actively hostile userspace programs, and local privilege escalation vulnerabilities are relatively common - indeed I'd say more common than browser vulnerabilities.
VMCALL is too flexible for being able to call it a "standard". What does the original article suggest? Yeah, define a struct and pass a pointer to it. As "standard" as defining protobuf messages.
Heck, even the "big" (Xen, HyperV, VMWare, VirtualBox) hypervisors don't agree on their hypercalls.
The problem of having multiple incompatible OS-interfaces is repeating itself, just one level below, on the hypervisor level. Madness.
Ironically, these problems would not exist had the world gone the way of IDL and microkernels.
> b) a way to run legacy programs that don't comply with the standard
No-go unless the VM implements all of the stuff that you want to get rid of.
Plus, whatever you decide to run in a VM may want to talk to a service in another VM. How do they talk to each other? [continue the exercise until you reimplement one or more of existing IPC mechanisms].
I see it as another path to a very similar end state. A unikernel running under a hypervisor is much like a process running under a microkernel.
> No-go unless the VM implements all of the stuff that you want to get rid of.
Legacy components can run under a traditional linux VM running under the same hypervisor. If you've got, say, a gnarly image processing piece that needs to talk to a task queue over unix domain sockets or something, you run them both in the same VM; you can get on with your business, but at the same time that doesn't impact the isolation of your other components, performance/scalability cost is only borne by the component that's causing it, so there's an adequate incentive to properly isolate that component (or maybe not - if it's not causing reliability or performance issues it can stay as it is, that's fine too).
> Plus, whatever you decide to run in a VM may want to talk to a service in another VM. How do they talk to each other?
In a way that's always traditionally been used for untrusted communications (e.g. network sockets), so that they know not to trust each other.
So your "trusted" components now incorporate a TCP/IP or another network stack. Plus you'll somehow have to authenticate the other end...
And yes, whenever one component talks to another they have to authenticate themselves; that's much of the point.
If the routing unikernel is untrusted, how are you going to prevent another unikernel to impersonate it and route on behalf of it?
> And yes, whenever one component talks to another they have to authenticate themselves; that's much of the point.
So... separate processes running under different users + unix or TCP sockets + user-based firewall rules does the thing?
If an attacker compromises it the worst they can do is block messages causing a DoS.
> So... separate processes running under different users + unix or TCP sockets + user-based firewall rules does the thing?
Yes except that with that approach you still have all the other ways those processes could interfere with each other.
Yes, you're right, add to that seccomp: http://man7.org/linux/man-pages/man2/seccomp.2.html