systemd Accepts Rust for New Components Only: No Cargo

systemd, which handles Linux startup and service management, has accepted Rust exclusively for new leaf components. Its approach reveals its design philosophy: no porting of existing C code and no Cargo. Key points What happened: Rust infrastructure support was merged into systemd's Git repository through PR #44324, adding 5,144 lines across 54 files and allowing new leaf components to be written in Rust Why it matters: The design uses no Cargo, operates with no_std, provides a custom allocator, and permits only C linkage. It follows the Linux kernel's approach of introducing Rust without breaking existing code Latest developments: The first practical Rust program, systemd-keyring-setup, is still awaiting merge, while Arch and openSUSE face a choice between adding build dependencies and disabling support No Cargo, no_std, C linkage only Christian Brauner, who also maintains the Linux kernel's VFS subsystem, merged pull request #44324 into systemd's Git repository. Ac

systemd Accepts Rust for New Components Only: No Cargo

systemd, which handles Linux startup and service management, has accepted Rust exclusively for new leaf components. Its approach reveals its design philosophy: no porting of existing C code and no Cargo.

Key points

  • What happened: Rust infrastructure support was merged into systemd's Git repository through PR #44324, adding 5,144 lines across 54 files and allowing new leaf components to be written in Rust
  • Why it matters: The design uses no Cargo, operates with no_std, provides a custom allocator, and permits only C linkage. It follows the Linux kernel's approach of introducing Rust without breaking existing code
  • Latest developments: The first practical Rust program, systemd-keyring-setup, is still awaiting merge, while Arch and openSUSE face a choice between adding build dependencies and disabling support

No Cargo, no_std, C linkage only

Christian Brauner, who also maintains the Linux kernel's VFS subsystem, merged pull request #44324 into systemd's Git repository. Across 54 files, it adds 5,144 lines. The infrastructure for writing systemd programs in Rust is now on the main branch.

The PR reworks an earlier RFC, PR #43551, to follow rules agreed upon by systemd maintainers at a hackfest in Berlin. At Lennart Poettering's request, it was split into four PRs. The one now merged is the second, covering the Rust infrastructure itself.

The agreed rules are clear and impose many constraints.

Rust is to be used only for new leaf components: programs at the edge on which other components do not depend. There are no plans to port existing C code to Rust. Meson remains the build system, rather than Cargo. No external crates are introduced, and the code operates with no_std. Only C linkage is permitted, preserving libsystemd-shared and the dlopen mechanism.

Rust's standard library is not included in either the programs or libsystemd-shared.

Joho no Todai confirmed that Rust support is controlled by Meson's -Drust= option, which defaults to auto. It is enabled if the toolchain is found; otherwise, systemd can still be built with C alone.

Encoding C conventions in types

One notable design decision is that it does not even use Rust's standard allocator, the alloc crate.

Rust's standard collections, such as Vec and Box, terminate the program when memory allocation fails. That is unacceptable for system programs running at boot. systemd implements its own Box and Vec, returning an error when allocation fails. In the PR description, Brauner says this follows the same approach as the Linux kernel.

Another design choice moves a problem long dependent on human memory in C into Rust's type system. When handling sensitive data such as private keys, C callers had to remember to call erase_and_free() every time to erase the contents before freeing the memory. Forgetting left sensitive data in freed memory. systemd's Rust implementation provides the type Vec, incorporating erasure on deallocation into allocator behavior. A convention has become a type.

systemd programs written in Rust are designed to be externally indistinguishable from their C counterparts. The output of --help, option parsing, and responses to --introspect-cli are checked for byte-for-byte parity with the C versions by a test script called test-cli-parity.sh. Bindings to libsystemd-shared are generated by bindgen at build time, using the same headers and flags as the library.

Figure omitted — see the original article

The increase in binary size is limited: a comparison of test programs built with LTO and stripped produced a 32KB Rust version and a 20KB C version.

The choice facing distributions

Rust support requires rustc 1.85 or later, bindgen 0.71.1 or later, and Meson 1.4.0 or later. The versions shipped with Debian 13 (Trixie) are sufficient.

Some distributions are already affected. Arch and openSUSE's OBS builds use the --auto-features=enabled flag to build systemd but do not include rustc and bindgen as build dependencies, causing builds to fail as configured. They need either to explicitly set -Drust=disabled or add rustc and bindgen to their build dependencies.

This PR introduces only the Rust infrastructure. Work on the first practical Rust program, systemd-keyring-setup, continues in a separate PR, #44114. It is a boot-time utility for registering X.509 certificates in the kernel's dm-verity, fs-verity, and BPF keyrings. With the infrastructure now in place, it is expected to merge soon.

The Rust support now merged will be included in the future systemd 263 release.

The kernel and systemd: Two foundations accept Rust

In the Linux kernel, Android's Binder driver is moving toward consolidation around its Rust version (in Japanese). NVIDIA's Rust driver Nova has also advanced to formal merge-candidate status (in Japanese). Rust is moving from experimentation toward practical use inside the kernel.

systemd's approach has much in common with the kernel's. Do not rewrite existing code. Do not bring in external dependencies. Implement memory management internally without even using Rust's standard library. Exclude Cargo and integrate with the existing build system.

The methodology is not the only connection. Brauner, the PR's author, is also a Linux kernel developer and explicitly describes the memory management design in the PR as following "the same approach as the kernel." Experience gained working with Rust in the kernel is being brought directly into systemd's design.

In the Linux boot sequence, systemd starts after the kernel. Those two foundations have accepted Rust with a shared philosophy.

Originally published on Joho no Todai. The Japanese original is here.

Share