Rewriting the Linux Kernel in Rust? The Ambitious Project ‘moss’
“Writing an operating system? Isn’t that Linus’s territory?”“Can Rust write a kernel? Aren’t you afraid of unsafe code blowing you up?”“Linux compatibility? You mean it can run BusyBox and that’s considered compatible?”
Hold on, today we won’t boast or make empty promises; instead, let’s take a closer look at a newly emerging yet ambitious open-source project on GitHub—moss. It is a Unix-like kernel written in Rust, compatible with Linux user-space programs, targeting the aarch64 (ARM64) architecture, and it can already run most BusyBox commands!
Even more astonishing, it actually incorporates <span>async/await</span> in the kernel and claims that the “compiler helps prevent deadlocks”? Is this a technical breakthrough or just youthful naivety?
Fasten your seatbelts; today we will peel back the layers of moss from a perspective that even a layman can understand. Along the way, we’ll discuss:Why is now the best time to rewrite the kernel in Rust?
1. When Rust Meets the Kernel: It’s Not About “Can It?” But “How Can It Be Done Safely?”
Let’s start with a painful fact:The Linux kernel written in C is still one of the most complex, massive, and fragile pieces of software in the world.
Why is it fragile? Because C lacks memory safety. A pointer going out of bounds, an uninitialized variable, or a forgotten resource release can lead to system crashes or, worse, privilege escalation by hackers. Linus himself has complained: “We have spent 30 years fixing bugs, but new bugs keep coming in.”
The core selling point of Rust is memory safety + zero-cost abstractions. It eliminates the vast majority of memory errors at compile time through three mechanisms: Ownership, Borrow Checker, and Lifetimes—without garbage collection and without requiring programmers to manually manage pointers.
As a result, the call for “rewriting the kernel in Rust” has been growing louder in recent years. Microsoft has created Rust for Windows, Google extensively uses Rust in Fuchsia, and even the mainline Linux kernel has started accepting Rust modules (since version 5.19).
But note:These are merely “modules” or “drivers”. The few projects that dare to start from scratch and write a complete kernel in Rust while claiming “Linux compatibility” are few, and moss is one of them.
🌟 Key Point: moss is not a toy OS; its goal is clear—binary compatibility with Linux user-space programs. This means that your compiled
<span>/bin/ls</span>and<span>/bin/cat</span>can theoretically run directly on moss!
2. The Four Pillars of moss: Architecture, Asynchronous, Processes, File System
Opening moss’s README, you’ll find it doesn’t boast of “disruptive innovation” but honestly lists four core modules. Let’s break them down one by one:
1. Architecture and Memory Management: Building for ARM64
Currently, moss only supports aarch64 (ARM64), which is a smart choice. The ARM server ecosystem, Raspberry Pi, and Apple M series chips are all thriving, and the documentation is comprehensive.
However, it has a trick up its sleeve:The hardware abstraction layer (HAL) is designed very cleanly. This means that in the future, porting to x86_64 or RISC-V would theoretically only require rewriting the HAL, with little to no changes needed in the upper logic.
In terms of memory management, moss has done the following:
- Enabled MMU: Virtual memory is standard for modern OSes; moss not only enables it but also manages the page tables itself.
- Copy-on-Write (CoW): When forking, it doesn’t immediately copy the entire memory, saving resources and improving efficiency.
- User-space/Kernel-space safe copy: Provides async versions of
<span>copy_to_user</span>/<span>copy_from_user</span>to prevent kernel from directly accessing user addresses, which could lead to crashes. - Buddy Allocator: A classic algorithm for managing physical memory, moss uses it to allocate large contiguous physical pages.
- smalloc: A small memory allocator used during the startup phase, specifically for handling early memory reservations.
💡 Life Analogy: Imagine you opened a shared office space (the kernel). The MMU is like a security system; each tenant (process) has their own virtual room number, but the actual physical location is managed by you. CoW is like “template room reuse”—a new client comes to view the office, and they first see someone else’s room (read-only); if they decide to rent, you renovate it to their specifications (copy on write). Safe copy is like a “delivery locker”—user items cannot be directly delivered to the office; they must be handed over through a transfer station (kernel buffer).
2. Asynchronous Kernel: Letting System Calls “Sleep Soundly”
This is the most impressive operation of moss—introducing <span>async/await</span> into the kernel!
In traditional kernels, once a system call needs to wait (for example, reading from disk or waiting for a network packet), it has to “sleep” and manually release locks. A slight misstep can lead to deadlocks: A holds a lock and goes to sleep, B wants the lock but gets stuck, and A can’t wake up…
moss’s approach is:All non-trivial syscalls are written as <span>async fn</span>. When you <span>.await</span>, the Rust compiler automatically checks—You cannot await while holding a spinlock! Because awaiting may trigger a task switch, and a spinlock must be held in a context where interrupts are disabled.
In other words:The compiler acts as your “deadlock gatekeeper”.
For example, suppose you want to implement the <span>read()</span> system call:
async fn sys_read(fd: usize, buf: UserPtr<u8>, count: usize) -> Result<usize> {<br /> let file = current_task().files.get(fd)?;<br /> // This may need to wait for disk IO, so it's async<br /> let data = file.read_async(count).await?;<br /> // Safe copy to user space (also async)<br /> buf.write_all_async(&data).await?;<br /> Ok(data.len())<br />}
If you accidentally added a <span>spinlock.lock()</span> in this code and then <span>.await</span>, cargo build will throw an error directly! It won’t even reach runtime.
🤯 Shock Point: This elevates the verification of “concurrent correctness” from “relying on programmer experience and code review” to “compiler enforcement”. While it doesn’t solve all problems (like logical deadlocks), it at least eliminates the most common pitfalls.
3. Process Management: Not Just Fork, But Also Clone and Signals
moss currently implements 49 Linux system calls, which may not sound like many? But BusyBox’s 300+ commands actually rely on only a small subset of them. For example, commands like <span>ls</span>, <span>cat</span>, <span>echo</span>, and <span>ps</span> can basically run.
Key syscalls include:
<span>fork</span>/<span>clone</span>: Create processes/threads. moss supports the full<span>clone()</span>parameters, meaning it can create lightweight threads (similar to pthread).<span>execve</span>: Load and execute a new program.<span>wait4</span>: Parent process waits for child process to exit.- Signals: Supports sending and handling SIGTERM, SIGKILL, etc.
The scheduler is currently a simple round-robin, but the README mentions that the next step is to implement task load balancing (migrating tasks between cores via IPI). This is crucial for multi-core ARM devices (like Raspberry Pi 4B).
4. VFS and File System: From RAM to FAT32
moss implements a virtual file system (VFS) layer, which is a prerequisite for supporting multiple file systems.
Current drivers include:
- Ramdisk: A block device in memory, with the rootfs packed in at startup.
- FAT32 (read-only): Can mount FAT32 partitions on SD cards or images.
- devtmpfs: Dynamically generates device nodes under
<span>/dev</span>(like<span>/dev/ttyS0</span>).
Although it can currently only read FAT32, the author’s roadmap clearly states that they plan to implement ext2/4 read/write support. Once achieved, it will be able to directly mount standard Linux root file systems!
3. libkernel: Enabling Unit Testing for Kernel Code
What is the most painful part of writing a kernel?Debugging is hard, testing is hard, reproducing is hard. A bug can cause the entire system to blue screen, with no logs produced.
moss’s solution is clever:It abstracts core logic into the <span>libkernel</span> library and makes it architecture-independent.
What does this mean?
- The page table management code you write on an x86 laptop canbe directly tested locally with
<span>cargo test</span>, without needing to burn it onto an ARM development board. - Address types (
<span>VA</span>/<span>PA</span>/<span>UA</span>) are encapsulated with strong types to avoid misuse. - Synchronization primitives (spinlock, mutex, condvar) all have corresponding test cases.
- Currently, there are 230+ unit tests covering memory management, containers, synchronization, and more.
🛠️ Developer’s Blessing: Previously, writing kernel code meant that changing a single line required recompiling, starting QEMU, and checking the results, taking 5 minutes for one cycle. Now, most logic can be tested on the host in seconds, improving efficiency by more than tenfold!
4. Hands-On: Get moss Running in 5 Minutes
Talk is cheap; let’s run moss ourselves and see what it looks like.
Environment Setup (Ubuntu/Debian)
# Install QEMU (ARM64 emulator)<br />sudo apt install qemu-system-aarch64<br /><br /># Install FAT32 tools (for creating rootfs)<br />sudo apt install dosfstools<br /><br /># Install cross-compilation toolchain (to compile user-space programs like bash)<br />sudo apt install gcc-aarch64-linux-gnu<br /><br /># Install ARM official bare-metal toolchain (to compile the kernel)<br /># Download link: https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads<br /># After extracting, add the bin directory to PATH<br />export PATH=$PATH:/path/to/gcc-arm-13.2-2023.07-x86_64-aarch64-none-elf/bin<br />
Clone & Run
git clone https://github.com/hexagonal-sun/moss<br />cd moss<br />cargo run --release<br />
If all goes well, you will see QEMU start and enter a shell, with a prompt that looks something like <span>moss#</span>. Try entering:
ls /<br />cat /proc/cpuinfo<br />echo "Hello from moss!"<br />
⚠️ Note: Currently, user-space programs are packaged using the
<span>mkrootfs-aarch64.sh</span>script with BusyBox and a few tools. If you want to add your own programs, you need to cross-compile them using<span>aarch64-linux-gnu-gcc</span>and place them in the rootfs.
5. The Ambitions and Challenges of moss: Can It Really Replace Linux?
Let’s pour a bucket of cold water:It is impossible in the short term.
The current state of moss is more like a “proof of concept”. It proves that:
- Writing a Linux-compatible kernel with basic functionality in Rust is feasible.
- async/await can be used in kernel scenarios and can enhance safety.
- Decoupling architecture + unit testing can greatly improve the kernel development experience.
However, there is still a long way to go before it is production-ready:
- Network Stack: TCP/IP is still nowhere in sight, let alone HTTP.
- Device Drivers: Only ramdisk and FAT32 are available, with no USB, WiFi, or GPU support.
- Performance Optimization: The scheduler and memory allocator are still basic versions.
- Syscall Coverage: 49 vs. Linux’s 400+, there’s a huge gap.
However,its value lies not in “replacement” but in “inspiration”.
Imagine the future:
- Cloud vendors using microkernels like moss to run serverless functions (FaaS), starting faster and having a smaller attack surface.
- Embedded devices using it for safety-critical systems, where Rust’s memory safety can prevent many CVEs.
- In education, students can use it to learn OS principles without facing the maze of millions of lines of Linux kernel code.
6. Why Now? The “Right Time, Right Place, Right People” for Rust Kernels
Ten years ago, no one dared to think about writing a kernel in Rust. Why is it possible now?
Right Time: The Rust Ecosystem Has Matured
<span>no_std</span>support is comprehensive, allowing bare-metal programming without the standard library.<span>async</span>runtimes (like<span>embassy</span>and<span>smol</span>) have proven feasible in embedded domains.- LLVM’s optimization for AArch64 is good enough, generating code efficiency close to C.
Right Place: Open Hardware + Powerful Simulation Tools
- QEMU can perfectly simulate ARM64, allowing development without real hardware.
- Cheap ARM boards like Raspberry Pi are widespread, facilitating real machine testing.
- The rise of RISC-V provides more scenarios for new kernels to land.
Right People: Community Consensus is Forming
- The Linux kernel accepting Rust is equivalent to official recognition of its feasibility.
- Tech giants like Microsoft, Google, and Amazon are investing resources to improve the toolchain.
- Developers’ demand for memory safety is unprecedentedly strong (just look at how many high-risk vulnerabilities appear each year).
7. For Those Who Want to Contribute: How to Help moss?
The README of moss ends with: “Contributions are welcome!” If you’re interested, you can start with these directions:
- Write Drivers: For example, UART, GPIO, USB Host. The HAL design of moss is very clear, making it easy to add new drivers.
- Port Architectures: Try to port moss to x86_64 or RISC-V. The HAL layer is ready for you.
- Add Syscalls: Implement missing system calls (like
<span>mmap</span>and<span>socket</span>) by referring to the Linux man page. - Improve the Scheduler: Implement CFS (Completely Fair Scheduler) or deadline scheduling.
- Write ext2/4 Drivers: This is a key focus in the roadmap, and the community will definitely welcome it.
Moreover, with the unit tests in <span>libkernel</span>, your code can be thoroughly validated before merging, so you don’t have to worry about “crashing upon submission”.
Conclusion: Not to Replace Linux, But to Expand the Possibilities of Operating Systems
moss will not become the next Linux, but it may be the prototype of the next generation of secure, reliable, and verifiable operating systems.
In this era of explosive AI and the Internet of Everything, we need not only powerful systems but also trustworthy foundational software. The memory safety provided by Rust, combined with modern engineering practices (like unit testing and modularity), may be the key to breaking the deadlock.
Finally, let me leave you with a quote, which I suspect is the spiritual kernel of the moss author:
“I don’t want to defeat Linux; I just want to prove—writing a kernel doesn’t have to be a nerve-wracking experience.“
So, are you ready to <span>git clone</span> this young kernel and contribute a brick?
Further Reading:
- Linux Kernel Rust Documentation[1]
- Writing an OS in Rust (Tutorial)[2]
- The Async Kernel Debate (LWN)[3]
Project Address: https://github.com/hexagonal-sun/moss
References
[1]
Linux Kernel Rust Documentation: https://docs.kernel.org/rust/
[2]
Writing an OS in Rust (Tutorial): https://os.phil-opp.com/
[3]
The Async Kernel Debate (LWN): https://lwn.net/Articles/853749/