HermiTux: A Binary-Compatible Unikernel
ssrg-vt.github.io
ssrg-vt.github.io
I envision a system that can use static analysis to chose system calls, find libraries (ldd), and perhaps even choose between appropriate algorithms (thread schedulers) all based on the particular program it is going to run. In other words Kernels that optimize themselves based on the program much like compilers optimize programs based on the various things like architecture. I think uni-kernels have great potential.
Also for system calls that are not security concerns or performance concerns why not continue to proxy them to the host kernel as Hermit core does?
It seems counter intuitive to me. It seems you're saying that static analysis cannot reach every branch of the program (and thus its underlying system libraries).
I'm surely missing something and would be grateful to anyone helping me out!
You could provide hints for these circumstances, or change a program to work differently to avoid the practice, but having library resolution delayed until runtime and until after the program has started is a real thing.
That is, let's say syscall 1 is definitely used, syscall 2 is definitely not used, whether syscall 3 is used depends on halting problem. Including only 1 and 3 to unikernel is safe and better than including all of 1, 2, 3.
“First, hardware-enforced isolation such as the use of SGX or EPT is fundamentally stronger than software-enforced isolation (containers/software LibOS), as shown by the current trend of running containers within VMs for security”
I don’t think that’s true. High-assurance security used to demand products use as many hardware defenses as possible. That was good for a while. Then, the hardware started having serious problems we’d have to work around. They seemed to be screwing them all up at some point with MMU and virtualization working better than average (most tested). Muen went with decision to use just one mechanism to avoid multiple, failure modes with software written in SPARK Ada for verification of safety. It did better with Meltdown/Spectre than many. More problems coming in on HW side, including attacks focused on SGX.
I think their assumption is thoroughly refuted at this point for modern, complex hardware. I’d depend on the hardware as little as I can using as simple hardware as I can get away with. Then, build the software as strong as possible around the most battle-tested mechanisms to reduce number of changes needed. seL4 on ARM and Muen on x86 are examples. If one has a massive budget, then build extensions to hardware that make securing software easier. Then, do the same thing again building highly-assured kernels on those heavily-verified, hardware extensions.
A better link: https://github.com/ssrg-vt/hermitux-kernel
The link in the article seems to be apps that use the kernel?
take the hello world example. Correct me if I'm wrong, but if one runs it 1000 times in parallel in a single namspace and it will be using close to 1x memory (i.e. like it was running once, assuming the vast majority of memory would be shared), run it 1000 times in parallel in 1000 docker containers and its memory impact will be closer to 1000x (i.e. no shared memory going on).
Those are seriously not the only two things that matter. Not by a long shot. Depending on what you are doing there are other serious concerns like security, OS Noise and other performance concerns. From the literature I've been reading security is a huge concern when deploying containers. From experience I can tell you that Dev-Ops with containers can be a nightmare and a half costing companies heavily.
Saying Ease-of-Use and Memory footprint is all that matters is serious misinformation that no research or other literature or anecdote supports.
That said, at least, ease of use is coming. There are some tools on the market right now that make Unikernels fairly easy to use Ops and BoxFuse come to mind.
Why are containers any more dangerous/vulnerable/prone to leaks than deploying say... a standalone REST API not in a container?
Its not about one service, its about n services running on the same resource partitioned hardware. If one gets compromised how likely is that to affect other services running on other partitions. Containers (High, shared kernel), Unikernels (Lower, different kernel, hardware supported isolation - almost like running n different physical machines).
We can play with risk estimation, but in practice, both containers and VMs were affected by memory sharing failures already. We know that syscall/ioctl issues exist. And we know that virtualisation issues exist.
How would the performance ande memory usage of those three things compare?
raw system call overhead: this isn't alot, but in an i/o heavy application it shows up as a reasonable percentage of work.
general purpose network machinery: things like kernel thread context switches for interrupts and networking likely wouldn't be there in the more bare bones systems. also none of the firewall/packet filter/netgraph checks will be there. its also possible that a single application network service might revert to a pure polling model and avoid interrupt context switches entirely.
unix interface: your standalone web server interface might be very well written to not use the copying tcp read(), and use direct callbacks or thread handoffs instead of select/poll/kqueue
other system gunk: none of the usual daemons and their kernel state needs to be there, and they wont be waking up and stealing cycles from your service. you should expect a much tighter service latency
another factor at play here is that alot of the general OS paths have had substantial work on them (interrupt coalescing, thread scheduling, memory management etc). that kind of effort may not be replicated in the simple standalone version. so by throwing that away you're losing some of the good along with the bad (where the bad here is otherwise useful generality, not something really objectively bad)
as mentioned in the HT writeup, startup time can be vanishingly small if thats of importance to you.
overall there should be some modest performance gains, but really not enough to drive adoption solely on that basis. for me the real win is radically simplified management.
given that everyone is building/using management layers over OS instances in a cloud context - is it really useful to carry around that large amount of additional machinery to manage the per-OS configuration? if I can trivially build and deploy new instances and wire them into my service, do I need chef anymore? do I need to fuss with user permissions in a world where no one is really logging in?
why manage a firewall, which assumes that all sorts of random junk might be running and we need to implement a policy for safety. with tools like this I can construct a system which by construction only responds to requests for the service of interest.
do I need to maintain a shell environment for monitoring and debugability? maybe - but effective distributed deployments already use distributed monitoring and tracing tools that are arguably more effective - even for general purpose OS deployments.
Of course, you’re throwing away a lot. But for certain applications (like HFT), the potential benefits seem very attractive.