Rust for Linux kernel, priced both ways
Memory safety is a total-cost question, not a security slogan.
Every ranking page argues that memory-safety bugs are most of the serious ones. Fewer do the math both ways. This one weighs the energy and the patch-cycle savings against an honest cost ledger, then hands you a rule for where the trade pays.
- Roughly two-thirds of the memory-safety CVE class designed out at compile time
- The same safety a managed runtime gives, at about 1.03x the energy of C
- Fewer emergency patch cycles across a decade-plus of service
- unsafe blocks where the abstraction has to touch raw hardware
- ABI and bindings churn against a moving C kernel
- Build-toolchain complexity and a real human learning curve
Sustainable in both senses
fewer joules per task + fewer forced patch cycles per decade
Both hold only where a memory bug is catastrophic. At the kernel and driver boundary that is exactly the case. This post ends in the rule for where it is not.
Rust for Linux kernel: the sustainability math for memory-safe systems code
Everyone argues the security case. This is the total-cost-of-ownership case, both ways: the energy tax of the alternative, the patch cycles you design out, and an honest cost ledger.
Why the kernel is the one layer where a memory bug is total#
Start with stakes, because they decide everything that follows. A memory bug is not equally dangerous everywhere. Instead its cost depends entirely on where it runs. In a leaf command-line tool a bad pointer crashes one short-lived process, and you restart it. In the kernel the same bad pointer sits in ring 0, with a view of all physical memory.
Because the kernel is the substrate under every workload, its faults are total, not local. A use-after-free in a driver can hand an attacker the whole address space. Therefore the kernel is exactly the layer where the argument for memory safety is strongest. It is also the layer with 30 million lines of C already in place, which is why the trade is not obvious.
The substrate every workload sits on#
Picture the stack as layers of blast radius. The diagram below traces one syscall down from user space into the kernel and out to hardware. On the way it marks where a fault is contained and where a fault is catastrophic.
Read the two dotted edges as the whole argument in miniature. Both point at the same sink. Because the memory manager owns every page and drivers are the biggest attack surface, a single bad pointer in either reaches everything. This is the same substrate that eBPF's shift of logic into the kernel pushes even more work into, which raises the stakes further.
Blast radius: one use-after-free, ring 0#
Consider the plainest kernel bug there is. A driver frees an object, then touches it again on an error path. In user space that is a crash. In the kernel it is a write to memory the allocator may have already handed to something else. Consequently an attacker who controls the timing can steer that write into a privileged structure.
This is why the class matters so much at this layer. The bug is not exotic. However the consequence is maximal, because ring 0 has no outer ring to contain it. So the question is not whether memory safety is nice. Instead it is whether removing this bug class pays for itself over the life of the system.
How big is the memory-safety class, really?#
Before pricing a fix, size the problem honestly. The famous claim is that memory-safety bugs are about 70 percent of serious security defects. However that number is real, and it deserves its caveats. Below are three independent first-party datasets, each landing near two-thirds, and each with an honest limit.
Three first-party datasets that independently land near two-thirds#
No single source proves a universal law. Yet three that were measured separately, by teams with different codebases, agreeing near the same fraction, is strong evidence. Read the caveat column as carefully as the number.
| Source | Memory-safety share | What was measured | Honest caveat |
|---|---|---|---|
| Chromium | Memory-safety share~70% | What was measured70% of 912 high or critical security bugs since 2015; about half were use-after-free | Honest caveatA browser is not a kernel; the codebase is C++ heavy |
| Microsoft MSRC | Memory-safety share~70% | What was measuredAbout 70% of CVEs assigned each year were memory-safety issues | Honest caveatAggregated across Microsoft products, not the Linux kernel |
| Google Android | Memory-safety share76% to 24% | What was measuredMemory-safety share of new-code bugs as new code moved to memory-safe languages | Honest caveatA share of NEW code over time, not the whole tree |
Notice what the caveats do. They stop you overclaiming. Because none of these is the Linux kernel exactly, the honest read is a range, not a constant. Still, the range is consistent, and it is large. Around two-thirds of serious defects come from one class the language can address. For example, you can read the primary numbers at the Chromium memory-safety page.
What "designing it out" looked like in the field#
The Android dataset is the most useful, because it measured a change, not a snapshot. As Google moved new Android code to memory-safe languages including Rust, it tracked the memory-safety share of new-code vulnerabilities year over year. The result is the clearest field evidence we have that the class is designable-out.
76%
New-code memory-safety share (2019)
24%
New-code memory-safety share (2024)
As new Android code moved to memory-safe languages, the memory-safety share of new-code vulnerabilities fell from 76% in 2019 to 24% in 2024, and Google reported Rust changes rolling back at less than half the rate of the C++ they replaced. This is the field evidence that the class is designable-out, not just theory.
| Option | share of vulnerabilities in newly written Android code, Google, 2019 to 2024 |
|---|---|
| New-code memory-safety share (2019) | 76% |
| New-code memory-safety share (2024) | 24% |
Source: Google Security Blog, Eliminating Memory Safety Vulnerabilities in Android (2024)
Read the mechanism behind the drop. Google did not rewrite the old tree. Instead it wrote new code in memory-safe languages and let the old code age out. Consequently the vulnerability share fell without a mass rewrite. That distinction, new code versus the whole tree, is the exact hinge the cost argument turns on later.
What Rust for Linux kernel code changes at compile time#
Now look at the mechanism, because it is what makes the price so low. Rust removes this bug class with no garbage collector and no runtime tax. The whole cost is paid by the compiler, once, at build time. Below is the exact use-after-free from earlier, in C and then in Rust.
The exact use-after-free the borrow checker rejects#
Compare the two panels line for line. The C version compiles cleanly and ships the bug. The Rust version cannot build at all, because ownership moved the value and the borrow checker refuses a use after the move.
/* A use-after-free the C compiler accepts without a single warning.
This is the shape of a large share of kernel memory-safety CVEs. */
struct device *dev = acquire_device();
release_device(dev); /* dev is freed here */
/* ... later, on an error path, or from a second thread ... */
dev->status = STATUS_IDLE; /* use-after-free: dev points at freed memory.
The build succeeds. The bug ships. */ // The same shape in Rust. The borrow checker rejects it at COMPILE time,
// so this code can never build, let alone ship.
let dev = acquire_device();
release_device(dev); // dev is MOVED into release_device and dropped
dev.status = Status::Idle; // error[E0382]: borrow of moved value: dev
// value used here after move
// The compiler refuses. No runtime, no GC, no cost. Read the Rust error as the entire value proposition. Because ownership is tracked in the type system, the misuse is a type error, caught before the binary exists. Therefore there is nothing to detect at runtime, nothing to garbage-collect, and nothing to slow down. The safety is structural, and the runtime cost is close to zero. That is the difference between a memory-safe managed runtime and memory-safe native code, and it is the whole reason Rust for Linux kernel work is even plausible.
What safe Rust eliminates vs what stays in unsafe#
Be precise about the boundary, because overclaiming here is dishonest. Safe Rust removes a specific set of bug classes. However Rust also has an unsafe keyword, and kernel code uses it wherever the abstraction has to touch raw hardware. The table decomposes what is covered and what is not.
| Bug class | Safe Rust | Mechanism | Still possible? |
|---|---|---|---|
| Use-after-free | Safe RustEliminated | MechanismOwnership and move semantics; a value has one owner | Still possible?Only inside unsafe raw-pointer code |
| Double free | Safe RustEliminated | MechanismA value is dropped exactly once | Still possible?Only with manual freeing in unsafe |
| Buffer overflow | Safe RustEliminated | MechanismBounds-checked slices and indexing | Still possible?Only via raw pointer arithmetic in unsafe |
| Data race | Safe RustEliminated | MechanismSend and Sync plus the borrow rules across threads | Still possible?Only in unsafe cross-thread code |
| Bugs inside unsafe blocks | Safe RustNOT covered | Mechanismunsafe deliberately opts out of the checks | Still possible?Yes, by definition |
| ABI and bindings drift | Safe RustNOT covered | MechanismThe C side is still C; this is churn, not a memory bug | Still possible?Yes, and it is a real maintenance cost |
Read the last two rows as the honest floor. Because unsafe exists, Rust is not a magic wand. Instead it shrinks the trusted, hand-audited surface to the small share of code that truly needs raw access. In practice the goal is a thin, reviewed unsafe core under a large safe surface. That is a real improvement, and it is not the same as zero risk.
Axis 1. Environmental sustainability: the energy tax of the alternative#
Here is the first cost axis most pages miss entirely. Memory safety has more than one implementation. You can buy it with a garbage-collected managed runtime, or with native code and ownership. Because those two routes draw wildly different amounts of energy, the choice has a carbon cost that compounds across a fleet and a decade.
Normalised energy across implementations#
The clearest data here is from a controlled study that ran identical tasks across languages and measured energy. The chart normalises every result to C at 1.00, so the bars read as a multiple of the native baseline. Watch how far a managed runtime sits above native code.
Show data table
| Item | Energy per task, C = 1.00 |
|---|---|
| C | 1 x C energy |
| Rust | 1.03 x C energy |
| Java | 1.98 x C energy |
| JavaScript | 4.45 x C energy |
| Python | 75.88 x C energy |
Normalised to C at 1.00, Rust draws about 1.03x, Java about 1.98x, JavaScript about 4.45x, and Python about 75.88x for an equivalent task. A managed runtime buys memory safety at 2x to 76x the energy; Rust buys the SAME safety at a ~3% premium over C. Figures are from Pereira et al., Energy Efficiency across Programming Languages.
Read the gap as the tax nobody bills. Because Rust holds energy at roughly 1.03 times C, it delivers memory safety at a ~3 percent premium over the fastest native code. In contrast a managed runtime pays 2x to 76x for the same guarantee. So for a driver-class workload, choosing Rust over Java saves about 95 joules per 100, and over Python about 7,485 joules per 100. The full method is in the Energy Efficiency across Programming Languages study. This is the same locality principle behind how the CPU cache hierarchy shapes low-level performance: less waste, closer to the metal, fewer joules.
The crash-and-reboot energy nobody bills#
There is a second energy cost that never shows up in a benchmark. A memory-safety bug in production does not only leak or crash. It also forces recovery. First the node reboots. Then it re-provisions. Meanwhile traffic fails over, and the whole cycle burns energy for zero useful work.
Because designing out a CVE class removes a share of those incidents, it removes their recovery energy too. Still, this cost is real but hard to measure precisely, so treat it as a directional argument, not a headline number. Still, over a decade and a large fleet, avoided reboots are avoided joules. The maintenance axis makes that concrete next.
Axis 2. Maintenance sustainability: patch cycles over a decade#
The second cost axis is labour, and it is the one a finance team actually feels. Every serious memory-safety CVE in a shipped kernel triggers an emergency response. You test a patch, stage it, roll it across the fleet, and verify it. That cycle costs real hours, and it repeats for every bug in the class.
One CVE class removed = N fewer emergency cycles#
Do the arithmetic over the life of the system, not one quarter. A kernel serves for a decade-plus, so the patch cycles accumulate. Because memory-safety bugs are roughly two-thirds of serious kernel CVEs, removing most of that class proportionally removes the emergency cycles they generate. Therefore the saving is not a one-off. Instead it is a recurring cost avoided, every year, for the life of the fleet.
Be careful to price only what is avoidable. Rust does not remove logic bugs, and it does not touch the C that already ships. However it does shrink the single largest CVE class in new code. So the honest claim is narrow and still large. Fewer memory-safety CVEs mean fewer forced patch cycles, and each forced cycle you skip is labour you keep.
Compute it for your fleet#
A worked average is still someone else's fleet. Yours has a specific size, a specific workload, and a specific cost per emergency cycle. So set your own numbers and read the ten-year delta. The instrument computes both axes at once: the maintenance labour designed out, and the energy tax avoided versus a managed runtime. The verdict band flips as you change the workload profile, because where memory safety belongs depends on the blast radius.
- Maintenance saved (10 yr)
- $5.71M
- Energy avoided (10 yr)
- 4.28 GWh
- Carbon avoided
- 1710.0 t
- Total 10-year delta
- $6.22M
A kernel / driver fault runs in the most privileged part of the machine, so each memory-safety CVE forces a real emergency cycle. Over 10 years across 500 nodes, designing out that class avoids about 714 emergency cycles, worth $5.71M in labour. Choosing native Rust over Java for the same safety avoids 4.28 GWh of energy. The one-time abstraction cost, on the order of a thousand-plus lines of wrappers, is paid once.
| Axis | What it measures | Physical result | Dollar value |
|---|---|---|---|
| Maintenance | Emergency patch cycles designed out | 714 cycles | $5.71M |
| Energy | Managed-runtime tax avoided vs Rust | 4.28 GWh | $513K |
| Total | Ten-year sustainability delta | 1710.0 t CO2 | $6.22M |
Fleet 500 nodes, Kernel / driver workload, Java (1.98x) energy counterfactual, $8K per emergency cycle. Over 10 years the model avoids about 714 emergency patch cycles worth $5.71M, and 4.28 GWh of energy worth $513K. Total ten-year delta $6.22M. Verdict: Memory safety belongs here.
An illustrative planning model, not a benchmark. The maintenance axis assumes memory-safety bugs are about 70 percent of serious CVEs and that Rust designs out about two-thirds of that class, per the Chromium and Android data cited above. The energy axis normalises to C at 1.00 and prices the managed-runtime alternative at the Pereira et al. ratios, over an illustrative 900 kWh per node-year at 0.12 dollars per kWh. Real numbers move with your hardware, energy price, and CVE history, so use the bands to find your regime, then measure your own fleet before you commit. The kernel itself is native C or Rust, never a managed runtime; the energy axis models the broader systems layer where a garbage-collected runtime is the memory-safe alternative you would otherwise reach for.
Watch the verdict move as you switch the workload. Because a kernel or driver fault is catastrophic, the model recommends adopting there even at a modest fleet size. In contrast a leaf tool sits on the wrong side of the line, since its crashes are cheap to recover from. In practice this is planning math, so measure your own fleet before you commit to a rewrite.
What Rust for Linux kernel support is today (2025 to 2026, no overstatement)#
First, ground the discussion in current reality, not hype. Rust for Linux kernel support is real, in-tree, and shipping drivers, but it is young and still churning. The timeline below traces the arc, with the maintainer-debate inflection marked honestly.
In-tree since 6.1, real drivers, the Asahi GPU#
The mechanism arrived before the drivers did. First the infrastructure merged. Then real hardware followed. The debate about maintenance cost came later, once the churn was concrete.
- 6.1 (Dec 2022)
Rust merges into the mainline kernel
The Rust for Linux kernel infrastructure lands in Linux 6.1: the toolchain, core bindings, and a sample module. It ships disabled by default, as scaffolding, not yet as drivers.
- 2023
First real drivers and the Asahi GPU
The Asahi Linux project writes an Apple M1 GPU driver in Rust, one of the first substantial in-tree Rust drivers on real, complex hardware, at roughly 1,500 lines of abstraction plus the driver.
- 2024
Drivers land, the maintainer debate sharpens
More subsystems gain Rust abstractions. A public disagreement over the cost of maintaining Rust bindings against a moving C API leads a lead contributor to step back, exposing a real trade-off.
- Late 2025
Called no longer experimental
The project is described as past its experimental phase. The mechanism is proven; the remaining cost is ecosystem churn, not viability.
Read the arc without spin. Because the infrastructure is in-tree and drivers ship on real hardware, the technology is proven. However the ecosystem is still maturing, and the maintenance model is genuinely contested. You can follow the primary sources at rust-for-linux.com and the kernel Rust documentation, and the 6.1 merge is written up in the Linux 6.1 changelog.
The maintainer debate and its real trade-offs#
Take the disagreement seriously, because it is the honest core of the cost side. Rust bindings wrap a C API that keeps moving. Therefore every change on the C side can ripple into the Rust abstractions that depend on it. That is real, recurring work, and reasonable maintainers disagree on who should carry it.
Do not read the debate as a verdict against Rust. Instead read it as a priced cost. Because the churn is real, it belongs in the ledger, not in a footnote. The LWN coverage of the maintainer discussion lays out both sides without cheerleading, which is exactly the register this decision deserves. The Asahi GPU work is documented in the project's own tales of the M1 GPU driver.
The honest cost ledger: what this is NOT free of#
Pair every benefit with its price, or the argument is propaganda. The energy and patch-cycle savings are real. So are the costs below, and pretending otherwise would fail any software engineer reading carefully. The callout names all four honestly.
unsafe blocks, ABI churn, build complexity, human cost#
Read the ledger as the guardrail against false equivalence. Because these costs are concentrated in setup and in maintenance, they favour new code over rewrites, and hot privileged paths over cold leaf ones. That is not a hedge. Instead it is the exact shape of the decision rule this post ends on.
Where memory safety belongs, and where the cost isn't justified#
Bring both axes and the cost ledger into one rule you can act on. The principle is simple. Spend the abstraction cost where a memory bug is catastrophic and the code is new or hot. Skip it where a crash is cheap and the code already ships and works.
A rule you can apply on Monday#
Next, map the rule onto concrete workloads, so it is usable, not abstract. The table gives a verdict per workload shape, matching the interactive ledger above. Read it as a starting point, then price your own case with the calculator.
| Workload | Blast radius | New or legacy | Verdict |
|---|---|---|---|
| Kernel drivers | Blast radiusTotal (ring 0) | New or legacyNew drivers, new hardware | VerdictYes, adopt |
| Network-stack buffers | Blast radiusHigh (parses untrusted input) | New or legacyNew or hot paths | VerdictYes, adopt |
| Userland service | Blast radiusContained to one process | New or legacyNew code | VerdictMaybe, selectively |
| Real-time firmware | Blast radiusHigh, but tight constraints | New or legacyMature, certified toolchains | VerdictLikely no, not yet |
| Leaf CLI or tooling | Blast radiusTrivial (short-lived process) | New or legacyEither | VerdictNo, not worth the cost |
Notice the pattern across the rows. Memory safety earns its place when the blast radius is large and the code is new or hot. In contrast it does not earn a rewrite of stable code whose crashes are cheap, and it waits where certified toolchains are not ready, as with much real-time firmware. That is the calm, even-handed answer the security-only pages skip. For the layers underneath this decision, it helps to see the full stack a request traverses down to the kernel, and for how this codebase is even maintainable at scale, how the Linux kernel's own Git workflow scaled distributed development. Price your own case, then spend the cost only where the numbers clear the bar.