Running WebAssembly on the Kernel

This is the story of our journey running Wasmer on the Linux kernel

Heyang Zhou
May 16 · 5 min read

Background

“The Second OS”

Many languages and runtimes, including WebAssembly (WASI implementations) and JavaScript (Node.js and browsers), have been trying to build another sandboxed “OS” on top of the real operating system. The second layer, however, incurs a significant overhead in performance.

VM running in Ring 3

The Successor to Cervus

I wrote Cervus — another WebAssembly “usermode” subsystem running in the Linux kernel — about a year ago. Back then WASI didn’t exist and neither did any “production-ready” non-Web WebAssembly runtimes, though the Cervus project has proved that the idea was possible and had great potential.

Why run WebAssembly in the kernel?

Mainly for performance and flexibility.

VM running in Ring 0

Security

Running user code in kernel mode is always a dangerous thing.

  • Out-of-bound memory access: allocate a 6GB virtual address space for each WASM task so that out-of-bound load/stores cannot even be represented
  • Lack of signal-based forceful termination: set the NX bit on WASM code pages when a fatal signal arrives
  • Lack of floating point register state preserving: explicitly save FP state on preemption with kernel_fpu_{begin,end} and preempt_notifier
  • Red Zone not supported in kernel: avoid using Red Zone in the codegen backend

Examples and benchmark

We have created two examples: echo-server and http-server (living in the examples directory of Wasmer main repo).

Even higher performance is expected when the other two Wasmer backends with optimizations (Cranelift and LLVM) are updated to support generating code for the kernel.

Those two examples use WASI (for file abstraction and printing to console) and the asynchronous networking extension (via the kernel-net crate). Take a look at them to learn how to do high-performance networking in kernel-wasm.

How to run it

Before running Wasmer on the kernel, ensure that:

  • Your kernel has preemption enabled. Attempting to run WASM user code without kernel preemption will freeze your system.
  • Kernel headers are installed and the building environment is properly set up.
git clone https://github.com/wasmerio/kernel-wasm.git
make
cd networking && make
cd ../wasi && make
cd ..
sudo insmod kernel-wasm.ko
sudo insmod wasi/kwasm-wasi.ko
sudo insmod networking/kwasm-networking.ko
sudo wasmer run --backend singlepass --loader kernel the_file.wasm
Cowsay running on the Kernel!

Hope you enjoyed reading this article!

While running WebAssembly in the Kernel is certainly dangerous and not the recommended approach for most use cases, it helped us to experiment and learn from the experience first hand.

Wasmer

Universal WebAssembly runtime

Heyang Zhou

Written by

Developer, Musician

Wasmer

Wasmer

Universal WebAssembly runtime