Rust in Linux
On memory-safety and Linux
- posted: 2024-12-02
- topics: linux, c, rust, memory-safety, kernel
- status: in progress
- confidence: moderate
There exists a certain inevitability to some technological transitions. Like the gradual replacement of assembly with C in systems programming, or the shift from horses to automobiles for transportation, these changes arrive not as revolutions but as slow-motion avalanches – initially imperceptible, then suddenly inescapable.
We may be witnessing such a transition with Rust's integration into the Linux kernel.
The Linux kernel has been C's domain for over three decades. Linus Torvalds famously wrote the first version in 1991, and since then, millions of lines of C code have accumulated to create what powers the vast majority of the world's servers, Android phones, and countless embedded devices. It runs our civilization's infrastructure with remarkable reliability, considering the inherent dangers of its implementation language.
C is powerful, flexible, and fundamentally unsafe.
Memory errors in C - buffer overflows, use-after-free vulnerabilities, null pointer dereferences - have been the source of countless security vulnerabilities. According to Microsoft, approximately 70% of the CVEs they address each year are memory safety issues1. Google's Chrome team reports similar findings - about 70% of their serious security bugs are memory safety problems2.
The Linux kernel, being written in C, is susceptible to these same classes of bugs. CVE databases overflow with memory-related vulnerabilities in the kernel. While Linux developers are exceptionally skilled and employ various mitigations (from careful code review to static analyzers), they're ultimately fighting against their programming language's fundamental design.
Enter Rust.
Rust was designed from the ground up to prevent memory safety issues at compile time. Its ownership system ensures that memory is always accessed correctly without requiring garbage collection. The compiler acts as a stern but helpful guardian, preventing you from shooting yourself in the foot. You cannot use a pointer after it's been freed. You cannot access an array out of bounds. You cannot have data races between threads. The compiler simply won't allow it.
What makes this especially compelling is that Rust achieves this safety without sacrificing performance. Unlike languages with garbage collection, Rust's memory safety guarantees have essentially zero runtime cost - all the checking happens during compilation.
This is why in 2021, Linus Torvalds cautiously approved the addition of Rust to the Linux kernel3. The first Rust code landed in the 6.1 kernel release in late 2022, marking a historic shift in kernel development philosophy.
It's worth examining why this matters.
The Linux kernel has three paths forward regarding memory safety:
-
Status quo: Continue writing everything in C, relying on careful coding, testing, and increasingly sophisticated static analyzers to catch bugs before they ship.
-
Incremental safety: Add new code in Rust while maintaining existing C code, creating a hybrid kernel over time.
-
Complete rewrite: Abandon C entirely and rewrite the kernel in a memory-safe language.
Option 3 is essentially a non-starter. The Linux kernel represents millions of lines of battle-tested code developed over decades. A complete rewrite would be a multi-decade project with questionable benefits. The risks of introducing new bugs during such a massive rewrite would likely outweigh the memory safety benefits for many years.
Option 1 has worked remarkably well so far. The Linux kernel powers most of the internet despite being written in an unsafe language. Sophisticated tools like Coverity and KASAN (Kernel Address Sanitizer) catch many potential issues before they reach production. But these tools can't catch everything, and each new vulnerability discovered in the wild represents a potential security breach.
Option 2 - the hybrid approach - is the pragmatic middle ground. It acknowledges the reality that the existing C code isn't going anywhere soon while allowing new code to be written in a safer language. Over time, critical components could be rewritten in Rust, gradually improving the kernel's overall safety posture.
Google appears to be betting heavily on this approach. In April 2023, they announced official support for Rust in the Android kernel, stating: "Memory safety bugs in C and C++ continue to be the most-difficult-to-address source of security vulnerabilities in the Android platform and across the software industry."
The Linux kernel's Rust integration isn't just a technical curiosity - it's potentially a watershed moment in systems programming. If successful, it could mark the beginning of the end for C's dominance in operating system development.
But there are significant challenges:
First, there's the issue of interoperability. Rust code needs to interact seamlessly with existing C code, which requires careful API design and thorough testing. The kernel team has made progress here, but it's an ongoing challenge.
Second, there's the question of expertise. The pool of developers who understand both Rust and kernel development is much smaller than the pool of experienced C kernel developers. This could slow adoption and create knowledge silos within the development community.
Third, there's the matter of Rust's stability and tooling. While Rust itself is remarkably mature for its age, its tools and ecosystem are still evolving. The kernel requires exceptional stability from its toolchain.
Despite these challenges, the direction seems clear. Memory safety vulnerabilities are too costly to ignore, and Rust offers a path to eliminate them without sacrificing performance.
I'm reminded of how slowly and then suddenly technological transitions can happen. Few people in 2010 would have predicted that Rust would be merged into the Linux kernel within a decade. Yet here we are.
The transition won't be quick or easy. The Linux kernel will contain C code for decades to come. But as new subsystems are written in Rust and existing ones are gradually ported, the security benefits will accumulate. Each line of Rust code represents one less potential buffer overflow, one less use-after-free vulnerability.
In a world increasingly dependent on software, where a single kernel vulnerability can potentially affect billions of devices, these improvements matter. They represent real security gains for real people - fewer data breaches, fewer compromised devices, fewer exploited systems.
Perhaps in thirty years, we'll look back on the 2020s as the decade when systems programming began its long transition from memory-unsafe to memory-safe languages. The decade when writing new critical infrastructure in C became as anachronistic as writing it in assembly had been a generation earlier.
The avalanche has begun. It's too early to tell how far-reaching the effects will be, but the first stones are already tumbling down the mountain.