Show HN: Munal OS: a graphical experimental OS with WASM sandboxing
Showing off the first version of Munal OS, an experimental operating system I have been writing in Rust on and off for the past few years.
https://github.com/Askannz/munal-os
It's an unikernel design that is compiled as a single EFI binary and does not use virtual address spaces for process isolation. Instead, applications are compiled to WASM and run inside of an embedded WASM engine.
Other features:
* Fully graphical interface in HD resolution with mouse and keyboard support
* Desktop shell with window manager and contextual radial menus
* PCI and VirtIO drivers
* Ethernet and TCP stack
* Customizable UI toolkit providing various widgets, responsive layouts and flexible text rendering
* Embedded selection of applications including:
* A web browser supporting DNS, HTTPS and very basic HTML
* A text editor
* A Python terminal
Checkout the README for the technical breakdown.Demo video: https://streamable.com/5xqjcf
This is really interesting and I was wondering how you implemented that using Wasmi. Seems like the code for that is here:
https://github.com/Askannz/munal-os/blob/2d3d361f67888cb2fe8...
It might interest you that newer versions of Wasmi (v0.45+) extended the resumable function call feature to make it possible to yield upon running out of fuel: https://docs.rs/wasmi/latest/wasmi/struct.TypedFunc.html#met...
Seeing that you are already using Wasmi's fuel metering this might be a more efficient or failure proof approach to execute Wasm apps in steps.
An example for how to do this can be found in Wasmi's own Wast runner: https://github.com/wasmi-labs/wasmi/blob/019806547aae542d148...
> It might interest you that newer versions of Wasmi (v0.45+) extended the resumable function call feature to make it possible to yield upon running out of fuel:
That is really interesting! I remember looking for something like that in the Wasmi docs at some point but it must have been before that feature was implemented. I would probably have chosen a different design for the WASM apps if I had it.
Wasmi's fuel metering can be thought of as is there was an adjustable counter and for each instruction that Wasmi executes this counter is decreased by some amount. If it reached 0 the resumable call will yield back to the host (in this case the OS) where it can be decided how to, or if, the call shall be resumed.
For efficiency reasons fuel metering in Wasmi is not implemented as described above but I wanted to provide a simple description.
With this, one is no longer reliant on clocks or on other measures to provide each call its own time frame by providing an amount of fuel for each Wasm app that can be renewed (or not) when it runs out of fuel. So this is useful for building a Wasm scheduler.
How is the performance when using fuel with wasmi?
We are considering to use epoch counter, but for now we just turned fuel off.
In past experiments I remember that fuel metering adds roughly 5-10% overhead to Wasmi executions. The trick is to not bump or decrease a counter for every single executed instruction but instead to group instructions together in so-called basic blocks and bump a counter for the whole group of instructions.
This is also the approach that is implemented by certain Wasm tools to add fuel metering to an existing Wasm binary.
What's the rationale? Just preventing infinite loops from hanging the host?
If the inefficiency is the counter, what if you just calculated an instruction offset - start < threshold every once in a while?
This probably makes no sense, ignore it, I'm way in over my head.
[1] https://github.com/bytecodealliance/wasmtime/issues/4109
[2] https://github.com/bytecodealliance/wasmtime/blob/main/examp...
There is a variety of ways to implement fuel metering with varying trade-offs, e.g. performance, determinism and preciseness.
In this comment I roughly described how Wasmi implements its fuel metering: https://news.ycombinator.com/item?id=44229953
Wasmi's design maxes out on performance and determinism but isn't as precise since instructions are always considered as group.
Thanks! I have lots more too. Are there directions in space? What kind of matter is fire made of? If you shine a laser into a box with one-way mirrors on the inside, will it reflect forever? Do ants feel like they're going in regular motion and we're just going in slow motion? Why do people mainly marry and make friends with people who look extraordinarily similar to themselves? How do futures work in Rust? Why is the C standard still behind a paywall? Let me know if you need any more great questions.
No, because each reflection comes at a cost (some light transformed to heat)
"Why do people mainly marry and make friends with people who look extraordinarily similar to themselves?"
To not get so much surprises and have a more stable life. (I didn't choose that path.)
(But I feel it would be too much OT answering the other questions and don't want to distract from this great submission or the interesting Wasmi concept)
Still, very impressive project!
Seems to me that a bigger downside is that the more apps you have open, the slower each one will become. I don't remember ever having more than like 10 open, but I've definitely had 30 tabs open, so if they're each separate procs then wouldn't that slow each one down by 30x? I guess if the whole computer is fast enough that's fine, but intense processes like video renderers would slow down noticably, even if not fast, even if just going from 1sec to 30sec. But in any case this is a really, really clever shortcut for the general case to get a whole operating system working, which is no small feat, and really exciting!
Is it possible to achieve decent network performance with this IO model? Can it play any tricks with memory to eliminate some of the copies required when hosting WASM in most programs?
I have huge respect for unikernel designs, and this looks amazingly festureful. & Yet… I don't know why it matters to me as much as it does, but I want so very much for wasm to be useful for more than one big precompiled app.
There's all sorts of work going into wasi preview3 right now, to allow sync and async code to co-exist. Once that happens, it feels like wasm will finally have all the necessary ingredients down to be an everything runtime (although I'd hoped the host-object bridging was going to get more love too, & it's not clear to me that there's any itnent to go beyond js-based bridges like rust web-sys, on and on).
I hope we see more interest in wasm runtimes being used to host more dynamic sub environments, to host not just one amazing process but many processes. The promise of wasm components is to give us: standard, portable, lightweight, finely sandboxed, cross-language, compositional module (according to the wonderful talk linked below), and it seems so near, but this status quo of it being used so extensively in unikernel like applications, needing everything compiled ahead of time, feels like the area I want to see wasm expanding into not as a specification (the spec seems there!) but as a practicable doable thing, like what I want wasm components to be good for. Not just a distribution format but a runtime capability.
What is a Component (and Why) https://youtu.be/y3x4-nQeXxc
[1] https://sdegutis.github.io/blog/dear-everyone-hire-me-to-mak...
[2] https://github.com/khvzak/script-bench-rs
Every few years since Xerox PARC, we get yet another attempt to bytecode userspace.
So far only IBM i, ChromeOS and Android managed to stick around, mostly thanks for their owners having the "my way or the highway" attitude, with management willing to support the teams no matter for how long it takes.
/rant mode off
Anyway, all the best for the project, looks cool.
Android could have used anything and it would have been successful, even C++.
These were both successful purely because they're cheap, not because technology.
Great technology sadly wins on merit.
Technology wins on either being cheaply available, in a worse is better fashion, as devs rather drink free lemon juice instead of nice costly orange one, or by having companies with willingness and deep pockets to push it no matter what.
You can see a snippet of it running (and rendering Hacker News) in the demo video.
This readme is really, really interesting to read through.
Why did you use wasmi instead of wasmtime?
I might actually try to use this OS inside a VM.
Half of me wants to port my own reactive GUI lib to Munal.
I just watched the demo video of Munal OS and am still in awe of all of its features. Really impressive work!
https://github.com/khvzak/script-bench-rs
If you are talking about the app isolation through virtualization, then I've been living in this future for quite some time with Qubes OS. The isolation there is also extremely reliable.
SPECTRE and MELTDOWN enter the chat
Now that Redox aims to support WASI too, it would be interesting to see if the syscall interfaces of these two can grow together other time, even as the implementation strategy remains radically different.
It is reminiscent of how basic team communication works in StarCraft 2. You alt-click to ping the minimap (draw allies' attention to something in that general area). If it's something more specific, you can hold alt, and drag-click to open a directional menu, from which you can choose one of four orders: attack, defend, retreat, and OMW. Some pings are also context-sensitive: click on the minerals/gas to say "I want to gather these resources", useful for establishing expansion patterns, strategy in the early game (macro/rush), tech transitions (ping your hydralisk den to say "I'm gonna make hydras"). All of this is key in a game with hundreds of APM and split-second reaction times.
It's a similar story with GUI actions. Power users appreciate good key shortcuts more than almost anything. If you do something thousands of times a day, it needs to be near-instant. The mouse is often disregarded, and IMHO that's because nobody is really doing any serious research in that area. Radial menus pack a lot of actions (where three mouse buttons fall short), exploit Fitt's law, muscle memory, etc. They are also discoverable and provide immediate visual feedback (contrary how "mouse gestures" work in some applications).
Couple notes on the current implementation (from what I've gathered from the video):
- Settle on how many actions *at most* do you want available in the menu (4? 6? 8?), divide the menu accordingly, and display those divisions regardless of whether there's an actionable item. This will help develop muscle memory. If you need more than say 8 actions, the menu might already be getting more crammed than you'd find useful.
- When figuring out where to place stuff, I would suggest prioritising the four cardinal directions for the most common actions, starting with the horizontal positions. "Surprising" or destructive actions (even if un-doable) should be placed at the harder-to-reach positions.
- Keep the actions as consistent as possible between different contexts, e.g. left on the document closes the document, left on the title bar closes the window, but not: left on an icon deletes the file.
Questions worth considering:
- I'm not sure if a launcher is a good use for this model; once you have a dozen apps (or more than 3-4 windows to switch between), it's gonna get awkward. Maybe a more traditional list-menu, and/or a dock? But I'd be intrigued if you come up with something original.
- What happens when you open a menu too close to the screen edge? It's an interesting case to consider. Warping the pointer might be an option (the physical mouse can keep moving, after all).
- Is this going to work well with a trackpad? Maybe use a two/three finger swipe, but that depends on how precise is your hardware.
- What about a trackpoint, or die-hard keyboard users? Perhaps you can trigger the menu by holding down the space key?
Anyway, this is really inspiring.
While working at DreamWorks, I would often watch artists navigate complex marking menu hierarchies and invoke a command before the menu items themselves could actually be read by a non-trained user. In our custom lighting tool, you could execute the marking menu command by invoking the menu command and making them mouse movement before the menu actually drew.
1. https://www.billbuxton.com/MMUserLearn.html 2. https://damassets.autodesk.net/content/dam/autodesk/research...
Liberation isn't found in "fighting", as if there were some kind of ideological showdown that resolved everything. That's a way to drain your energy for living while waiting for a final resolution that never comes. Indeed, by directing it towards "enemies" you can accumulate guilt in yourself, and become increasingly unstable.
Rather, it has to be part of living and personal character, to take opportunities to "do hard things" because they are interesting, not because you are coerced. When you do this, succeed, and pass down the knowledge, the potential opens up to others. You don't have to believe right things to stumble into new ideas.
That is a tad dramatic. You could also say the same thing about any art form.
- Painters spend all of their time working on artwork only a few people will ever see!
- Musicians don't realize how their time is wasted composing music that won't solve any problems!
- People are starving right now, as another writer dares to write a story that simply tries to entertain the reader.
Everything is political, and we all should keep that in mind. We all have effects on society no matter what. But also, it's fine to make a cromulent thing because it's interesting. We've all only got so much time alive, but you're going to squander the experience if you try to min-max impact on those 90-odd years. People do have to live for themselves sometimes, and this person likes making a neat homebrew OS.
Do you listen to music, read books, have sex etc? I bet you do. And I also bet that you would find it pretty ridiculous if someone asked you why you do those things instead of helping humanity.
I for one celebrate any time people invest their efforts in building something unique, new and interesting. This project is absolutely delightful.