The actual problem with this, after you have satisfied yourself about the numerous non-problems, is that practically any real app in wasm has calls to library code implemented in C or C++ and compiled to real asm to implement the extended Javascript runtime, that you would not want running in ring 0. To those are added all the kernel-mode functions that must be used correctly. (If the app can be provoked to use them wrong, boom.)
So, the plausible use is an implicitly trusted app not exposed to untrusted input, that is system-call bound, and that you want to distribute cross-platform without recompiling to targets that have installed this module in a known kernel version. It seems easier just to distribute source for a kernel module; or kernel modules built for the (2? 3 tops) architectures required.
I'm not sure why linking third party code is a concern, it all must live inside the sandbox provided by the runtime. This reduces the trust requirements from depending on a (software | hardware) solution where the hardware portion cannot be audited, and by 2018 are no longer to be considered trustworthy by default, to only depending on access and bounds checks implemented by a single body of code visible to everyone.
The 'system call interface' available to those buggy libraries need be no more capable than existed previously, that system calls are serviced without switching protection mode need not extend the potency of any possible attacks.
A future implementation of this style of design will have much better security and auditability properties than anything that has ever popularly existed in the past. It may have originated with the web, but I welcome wasm and all the market punch it promises to bear on ancient and long-unquestioned corners of our software stack like this. (Naturally I was also a Microsoft Singularity fan)
How does WebAssembly fix hardware issues? For example, take Rowhammer. I don't see how running your code in a VM fixes Rowhammer; surely there would still be some mapping of data in wasm to RAM, and I don't see why a sufficiently motivated individual couldn't determine and subsequently exploit that mapping.
Or what does WASM do about the concerns that major CPU vendors embed a second co-processor running untrusted, unauditable code with ring -1 access alongside the main CPU?¹
¹which may or may not be active, depending on CPU model and configuration. I've never really fully understood when it is, or isn't, but I think it's somewhat moot.
Further, this assumes the runtime (which is not just the WASM runtime: system calls and other functionality will inevitably need access to the actual, underlying hardware in order to do their job) from being buggy, and since the code is now in ring 0, you get all the consequences of that. (Full, unrestricted access to everything. At least previously, you'd need to find some root exploit to get that.)
(Also, as another poster hints below, since everything is running inside the same protection layer from the CPU's point of view, what prevents you from just running the same attack, in spirit, as Spectre? Only now, there is no protection — everything is ring 0 — so the CPU is "correct" to speculate a read. Sure, the VM will deny it to the code inside the VM, but that didn't matter in the case of Spectre?)
> since the code is now in ring 0, you get all the consequences of that
No you don't. Because WASM does not provide many of the facilities that real assembly provides. So, for instance, there is no way to stack-smash using WASM instructions, regardless of the any security problems in the code itself, or even outright malicious code. It just can't do it.
More generally for VMs, there are secure VMs which provide a mathematical proof that the code will, for instance, observe memory safety. Such a proof is much better than ring-level protection, because :
1) You can verify the proof. Good luck verifying the hardware implementation of ring-level security in processors
2) It doesn't take any resources at runtime
3) the proof can be verified at code load time, so insecure code (accidentally insecure or otherwise) just doesn't start executing, ever
4) It doesn't allow for manufacturers to hide "secure coprocessors" or any other bullshit like that
> I'm not sure why linking third party code is a concern, it all must live inside the sandbox provided by the runtime.
Some runtime stuff implements operations not expressible in JS, and not permitted in the sandbox. You may not want that code in the kernel. Anyway, if random kernel functions can be called from the sandbox, it would be easy to misuse them. Untrusted input might trick code into misusing them from in the sandbox, via nominally valid operations.
Does webasm protect against integer overflow, or unaccounted unsigned wraparound? Not all exploitable bugs are pointer violations.
> "it all must live inside the sandbox provided by the runtime."
Processes with a strong user model are already one of the most effective isolation mechanisms in an operating system. Continually hardening your VM/runtime that was ported into the kernel, in my opinion, either results in either you building a microkernel or recreating the userspace/kernel separation that already exists?
Parent comment refers to running buggy code in ring 0, however in a design like wasmjit, that code would be compiled first to wasm, and the actual code running in-kernel is a derivation that includes bounds checking on at least memory operations. The original code never "runs" in ring 0, what runs is a derivation that includes a software equivalent of the hardware isolation we're used to and have relied on for the past 20 years.
While I haven't studied wasmjit, the most obvious implementation is to run system calls naturally, with a global "struct task" existing as before that defines the semantics of the current context, including details like the current UID and capability mask - in other words, without effort, read() and open() could be made to behave identically to before, it's just that the caller now lives in a software sandbox rather than a hardware sandbox, and most/all expensive hardware reconfiguration was avoided
I read through it and this is indeed how it works. Wasm as a language provides the restrictions that the MMU provides for machine code. You can't read from/write to arbitrary pointers in wasm.
The load8_s instruction will check that the computed offset into the memory of size 64KB (1 wasm page) does not index past the bounds of 64KB. If it does, the program will trap.
WebAssembly protects the host from memory corruption by the user module. To do this it does a bounds check before executing the load. It does not protect a user module from itself. It does not change the semantics of C.
> It does not protect a user module from itself. It does not change the semantics of C.
Which is my whole point, WebAssembly does not protect memory corruption inside of the module code, which allows for security exploits anyway.
On my sample code if I expose func() to the host, and it gets called with 200 as parameter for a buffer size of 100 bytes, no trap will ocurr.
On a real use case that call might induce an internal memory corruption that will, for example, change the behavior of other functions exposed to the host.
If you wish I can provide an example how to do that, which you can try out in your favorite spec compliant Web Assembly implementation.
Current WASM spec is a MVP. There will be other ways to expose functionality to the host that should be safer. See future proposals. Your points are valid though.
How is this relevant to wasmjit? User space programs written in C can already corrupt themselves. As far as I can tell there is no new inherent risk to kernel stability by running wasm code in kernel space as long as the wasm spec is followed. Just like wasm programs aren't able to corrupt the browser sandbox in which they run.
The sandbox gives a false sense of security, because it opens a new attack vector.
Apparently you fail to understand how security exploits are taken.
For example, lets say I have an authentication module provided as WebAssembly, written in C.
The browser makes use of the said WebAssembly module to authenticate the user.
Now we make a cross site scripting attack that calls the WebAssembly functions in a sequence that triggers memory corruption inside of the module, thus influencing how the authentication functions work.
Afterwards the JavaScript functions that call those WebAssembly ones, might authenticate a bad user that would otherwise be denied access.
This is a moot point, the entire kernel is written in C. Since all code running on your computer involves kernel code running in ring 0, by your logic that would imply something is wrong, but it's not. System calls verify all input before executing.
So, the plausible use is an implicitly trusted app not exposed to untrusted input, that is system-call bound, and that you want to distribute cross-platform without recompiling to targets that have installed this module in a known kernel version. It seems easier just to distribute source for a kernel module; or kernel modules built for the (2? 3 tops) architectures required.
[edit: spelling error.]