Skip to content

Rust Is "Stable" in the Linux Kernel: What That Means

Linux 7.0 dropped the experimental label from Rust. Most coverage read that as a technical milestone. It wasn't and the actual constraints, including a Rust version now pinned to Debian Stable, are more interesting.

Share
A platform of matte grey blocks with crisper, lighter blocks set into it, glowing lines tracing the boundary between the two materials

Linux 7.0 removed the experimental designation from Rust support. Four years after the infrastructure landed in 6.1, writing a kernel driver in Rust is officially supported rather than quietly tolerated.

The coverage has largely read this as a technical milestone — as though something in the compiler or the abstractions crossed a threshold in April. That isn't what happened, and the actual story is more interesting than the version-number one.

In this post:

What Actually Changed

Miguel Ojeda's mailing-list framing is the clearest account. Rust was merged into mainline in 6.1 to determine whether the language was suitable for the kernel, whether it was "worth the tradeoffs, technically, procedurally and socially." Following discussions at the 2025 Maintainers Summit and Linux Plumbers Conference, he was comfortable declaring the effort a success and dropping the experiment flag.

Read that list of three again, because it's the whole point. The technical question is: can you write correct, performant kernel code in Rust? Drivers that shipped and worked answered that some time ago. The procedural and social questions were the open ones: can maintainers be expected to accept Rust patches into their subsystems, and is the community willing to carry two languages indefinitely?

So the change in 7.0 is a governance change, not an engineering one. Before it, a maintainer could decline a Rust contribution because the whole thing was provisional. After it, the bar for a Rust patch is the same as the bar for a C patch. That's a meaningful shift in what a contributor can expect when they send work upstream, and it's a bad description of a compiler improvement.

The practical evidence is in recent releases: Linux 6.19 made it possible to write I2C drivers in Rust and added module parameter support for Rust drivers, and the Nova driver, the open-source Rust effort for NVIDIA hardware, has continued preparing for Turing GPU support through 7.0. These are ordinary subsystem-by-subsystem expansions, arriving on their own schedule, not a step change that coincided with a label being removed.

What Didn't Change

Here is the part almost every summary omits, and it's the reason the quotation marks in the title are earned.

The kernel's Rust code still depends on unstable compiler features. The Rust for Linux project says so plainly in its own version policy: newer Rust versions can't be guaranteed to work because of the unstable features in use, and removing the need for them is a project priority. In practice, every release since the initial minimum has worked, but "it has worked so far" and "it is guaranteed to work" are different claims, and only one of them is what most people hear in the word stable.

There's a nice mitigation in place, and it's underrated. The kernel is now build-tested in Rust's own pre-merge CI. Every change attempting to land in the Rust compiler is tested against the kernel and merged only if it passes.

Think about the direction of that dependency for a moment. The Rust project has volunteered to treat the Linux kernel as a gate on its own compiler releases. Nothing comparable has ever existed on the C side. The kernel spent decades working around GCC's behaviour rather than the other way round. It's a genuinely unusual arrangement, and it does more to make Rust-in-the-kernel dependable than the removal of a label does.

The Version Numbers That Actually Matter

If you build kernels, this is the section you came for. Be careful with secondary sources here: a lot of what currently ranks for this topic gets these numbers wrong, and I've seen the merge release given as 5.19 and the minimum toolchain given as 1.93, neither of which is right.

From the kernel's own documentation and the Rust for Linux version policy:

Minimum Rust Minimum Bindgen
Kernels before 7.1 1.78.0 0.65.1
Linux 7.1 1.85.0 0.71.1
Linux 6.18.y (LTS) 1.78.0

Two things worth noting. Rust support was merged in 6.1; a documented minimum Rust version has existed since 6.11, with 1.78.0 as the initial floor. Stable and LTS kernels can have different requirements than mainline, which is why 6.18.y sits where it does.

If you're on a reasonably current distribution, you're already fine. The project lists Arch, Debian 13 and newer, Fedora, Gentoo, and Ubuntu 25.10 and 26.04 LTS as meeting the requirements, with Ubuntu 24.04 LTS workable via versioned packages. Toolchains installed through rustup work, and kernel.org provides slim LLVM and Rust toolchains if you'd rather not involve your distribution at all.

The Kernel Pinned Its Language Version to Debian

This is the decision I find most interesting, and it's had almost no coverage.

Since early 2026, the Rust for Linux policy has been to follow Debian Stable's Rust version as the minimum supported version. That's why 7.1 moves to 1.85.0 and Bindgen 0.71.1. Those are the versions in Debian 13 (Trixie), which became the stable release in August 2025.

So the Linux kernel's minimum language version now depends on a downstream distribution's release cadence.

Stated plainly, it sounds odd, and it's worth sitting with why it's actually sensible. Debian Stable is the slowest-moving thing that anyone seriously builds kernels on. Pin to it, and you get a floor that, by construction, satisfies everything else — Fedora, Ubuntu, Arch, openSUSE all sit at or above it comfortably. You also get a predictable, externally-determined schedule rather than an argument on the mailing list every cycle about whether a given compiler feature is worth requiring.

There's a testing argument buried in it too, and it's the part I'd emphasise. Pinning to the most conservative real-world target means the version you build with is the version nearly everyone else builds with. The gap between "works on the maintainer's machine" and "works on the distribution's build farm" narrows to something close to zero. That's the same class of decision as choosing a CI baseline, made at the scale of an entire project.

The Clang Tradeoff Arriving in 7.1

Linux 7.1 introduces CONFIG_RUST_INLINE_HELPERS, an experimental option that improves performance for Rust code in the kernel by inlining C helper functions into Rust.

It comes with a real constraint. It depends on using LLVM Clang as the kernel C compiler rather than GCC, and the major version of Clang must match the Rust compiler version—both because the mechanism relies on linking LLVM IR from the C helpers with the Rust IR before object code is generated. It does work for loadable kernel modules.

Follow that through, and anyone shipping kernels hits a fork in the road. The best-performing Rust configuration is available only to a Clang-built kernel with a version-matched toolchain. Distributions that build with GCC, the most traditional, must choose between their existing compiler and the performance ceiling for Rust code.

It's experimental and optional today, so nobody has to decide anything yet. But if Rust code continues expanding into performance-sensitive paths, this becomes a question that distributions have to answer rather than defer. It's the most concrete unresolved tradeoff in the whole story, and it has nothing to do with memory safety.

What This Actually Changes About Testing

The claim you'll hear is that memory safety reduces the testing burden. I think that's precisely backwards, and it's worth being clear about why.

Memory-safety bugs are the category that testing has always been worst at catching. A use-after-free doesn't reliably fail; it corrupts something, and the symptom surfaces later, somewhere else, under a particular allocator state or timing that your test run didn't happen to produce. A data race passes ten thousand times and fails on the machine with more cores. These bugs are non-deterministic; they manifest far from their cause, and they're the reason kernel debugging has a reputation.

Logic bugs are the category testing is good at. Wrong register written, an error path that doesn't clean up, an off-by-one in a buffer length calculation, a state machine that doesn't handle a device disappearing mid-transaction. Those are deterministic, and a well-written test catches them every time.

Rust eliminates much of the first category at compile time. It eliminates none of the second. So a Rust driver needs the same functional test coverage as a C driver. The compiler proves a narrow property about memory access, not that your driver talks to the hardware correctly.

But there is a real benefit, and it's one I'd argue matters more than the headline:

Your test failures become interpretable again. In a C driver, an intermittent failure has at least three plausible explanations: a race in your test harness, a logic bug in the driver, or memory corruption originating three subsystems away that has nothing to do with the code you're looking at. That third possibility is what makes kernel debugging expensive, because you can't rule it out and you can't reproduce it on demand. Remove most of it, and an intermittent failure becomes much more likely to be a genuine logic bug in what you're testing.

That's a triage improvement rather than a coverage improvement, and triage cost is where engineering time actually goes. I've made the same argument about flaky tests in application code: a test that fails one run in twenty is reporting something true, and teams learn to ignore those reports because investigating them is expensive. Cheaper investigation means fewer ignored reports.

And the corollary that should shape your review process: unsafe blocks are where the guarantee stops. Every abstraction over a kernel API has one somewhere, because the kernel API is C. Those blocks and the boundaries around them are where scrutiny and testing effort belong, because they're the only places where C's failure modes are still live. A Rust driver isn't uniformly safe; it's safe except at a small number of clearly marked points, which is a considerable improvement precisely because the points are marked.

My Take

"Stable" declarations are social artefacts, and it's healthier to read them that way. Ojeda's three-part test- technical, procedural, and social is unusually honest about this, and I wish more projects framed it the same way. The technical question was settled by working drivers well before April. What 7.0 settled is that a maintainer can no longer decline Rust because it might not be permanent. That is a real and valuable thing to settle. It just isn't a compiler milestone, and treating it as one leads people to expect guarantees that the version policy explicitly declines to make.

The pre-merge CI arrangement is the part I'd point to as evidence, if I had to pick one. A label can be removed by consensus. A standing commitment from the Rust project to gate compiler merges on kernel builds costs someone real infrastructure and real time, every day, indefinitely. Revealed preference is more informative than a declaration, and this is the strongest signal in the whole story.

Having shipped Swift when it was young, I recognise this shape. A language doesn't become dependable at a version number. It becomes dependable when the ecosystem around it stops treating breakage as the adopter's problem — when the toolchain vendor tests against you rather than expecting you to keep up. Swift took years to get there and the intervening period was genuinely painful. Rust in the kernel has arrived at that arrangement remarkably early, and largely because the Rust project volunteered rather than because the kernel demanded it.

The unglamorous conclusion, if you're not writing drivers: the thing that will actually affect you is the toolchain requirement, not the language debate. If you build kernels — for embedded targets, for a distribution, for a CI image — the practical consequences are a Rust minimum that now moves in step with Debian Stable, a Bindgen requirement that moves with it, and an emerging question about whether you build with Clang or GCC. That's a build-infrastructure story, and it's the one worth noting.

And the honest caveat I'd want stated in any post on this: unstable compiler features are still in use, and the project says removing them is a priority rather than something already done. Anyone telling you the experiment is finished in the strong sense — that the toolchain dependency is fully resolved — is telling you something the primary sources don't say. The direction of travel is clearly right. The destination hasn't been reached.

FAQ

When was Rust merged into the Linux kernel?
Version 6.1. A documented minimum Rust version has existed since 6.11, initially 1.78.0.

What does "stable" mean in Linux 7.0?
That Rust is accepted as a permanent part of kernel development and Rust patches face the same bar as C ones. It does not mean the toolchain dependency is fully resolved — unstable compiler features remain in use.

What's the minimum Rust version?
1.78.0 with Bindgen 0.65.1 for kernels before 7.1; 1.85.0 with Bindgen 0.71.1 from 7.1, following Debian 13 (Trixie). LTS kernels differ — 6.18.y sits at 1.78.0.

Why does the kernel follow Debian's Rust version?
Since early 2026, the policy has been to use Debian Stable's version as the minimum. It's the most conservative real-world target, so anything satisfying it also satisfies faster-moving distributions.

Do I need Clang to build Rust kernel code?
Not in general. But CONFIG_RUST_INLINE_HELPERS in 7.1, which improves Rust performance, requires Clang as the kernel's C compiler with a matching LLVM major version.

Does Rust remove the need to test kernel drivers?
No. It largely removes a class of memory-safety bugs that testing was poor at catching anyway, and leaves logic bugs — the class testing catches well — entirely intact.