systemd loves Rust
58 points by lorenzleutgeb
58 points by lorenzleutgeb
Well, by "loves Rust", they mean "no Rust standard library, no external dependencies, and no Rust anywhere but leaf binaries." Which, if that brings them joy, more power to them.
I mean, that's Rust too. I love my bells-and-whistles Rust with Cargo and crates.io and all that, but I also love that those are not mandatory. You can fit Rust into all sorts of more constrained environments and get all the benefits of the language (albeit not of the ecosystem).
They love "Rust, the language" like the Linux kernel Rust developers or the various embedded developers singing Rust's praises do.
I've written Rust "shell scripts" where they don't really depend on the ecosystem and are purely there so that I can have APIs that return Option<T> or Result<T, E> instead of things like Python's os.getcwd documentation just assuming Everyone Knows™ that getcwd is unavoidably fallible at the kernel level, or bash being annoying with its opt-out whitespace splitting and retrofitted array support.
That's loosely analogous to what they're doing with their internal alternative to calling libc functions. Using "Rust, the means of having a nicer type system".
I've written Rust "shell scripts" where they don't really depend on the ecosystem
Do you run them with cargo run? Or they are just very lean compiled binaries that you manage?
There's a nightly cargo feature on track for stabilization for this usecase: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#script
Generally lean compiled binaries I manage, because I find Cargo's too eager to find excuses to do a rebuild with an invalidated build cache. Using rust-analyzer, bacon, and --release in the same project? You're on borrowed time. rustup update? That's a rebuild. Compiling both the host app and the WASIp2 plugins for it without forcing separate target directories? Yup. etc. etc. etc.
Once the nightly cargo scripts feature is stabilized and rust-analyzer supports it, I'l re-evaluate something like https://rust-script.org/ since the main place I still use Python (aside from stuff where the Rust ecosystem isn't there yet like memory-safe Qt QWidgets bindings, SQL databasing with Django ORM/SQLAlchemy+Alembic "derive is authoritative and will be diffed against the in-database schema"-style autogeneration of draft migrations and abstracting over SQLite's limited ALTER TABLE, and Django's ecosystem of reusable apps) is truly "too simple for me to be motivated to manage a new project folder" things.
I've happily used scriptisto, it seems to cache correctly and I like that it supports many languages.
For me, the deal-breaker is that the tooling other than the compiler driver doesn't yet support single-file projects. That killed the experiment before I evaluated rust-script's caching behaviour.
With Python, my Vim integrations for things like ruff and mypy Just Work™ for lone .py files... even if I am still torn on whether to bake stuff like mypy --strict into the IDE-default configuration at the cost of an increased risk of forgetting to make sure they're in the project configs and applying properly. (eg. That's why I have a stock ~/.gitignore)
If it's big enough to benefit from Rust, then it's also big enough to benefit from things like cargo clippy and cargo fmt. (with use_small_heuristics = "Max", dammit. I don't have a portrait-oriented monitor.)
I don't have a portrait-oriented monitor.
I definitely do not mean to suggest that you should change your formatting preferences, but one easily could have a landscape monitor and still have a portrait editing window, if one has the editing window side by side with, e.g., documentation or a list of compilation errors.
OK, let me rephrase that. My monitors are only 1024px, 1080px, and 1024px tall, respectively. I don't want to spend the money to buy a large-format 4K display. (i.e. a 4K monitor equivalent to keeping my existing three-monitor spread at a DPI that allows me to fit the same amount of readable text horizontally, but doubling the height, with no "smart TV" spyware looking for compatible devices within neighboring houses to passwordlessly exfiltrate "demographic information" from the camera and microphone via technologies in the vein of Amazon Sidewalk.)
I'm already used to having two or three :vsplit columns in my Vim with use_small_heuristics = "Max".
Hell, it's inconvenient enough reaching over my row of monitors to get at some of the books on my bookshelves as-is and I have things below the monitors that I reach for which would also be obstructed if I made them taller to fit more useless whitespace.
It makes sense to enforce the usage of project-level abstractions. I suppose they mean no_std but still use core
I mean, they're not necessarily doing anything wrong. But core is basically bare metal and compiler intrinsics. There's no way to allocate memory or really do anything at all. It's perfectly sensible for kernel-level code where you don't have a memory allocator until you build one. (The one thing you do get is a lot of iterator machinery, including over byte slices.)
And while Rust is neat at that low a level, it's just barely recognizable as normal Rust.
Also, this means that they're committing to rebuilding all their own collection types on top of custom fallible allocation routines and unsafe. Which means that they may not have as much security auditing as the Rust std library. std isn't perfect, but it's frequently used as a testbed for people's theorem provers. Which has flushed some bugs in the past.
To be clear, I'm not criticizing them. I'm just pointing out that they're choosing to throw away pretty much everything but the borrow checker and iterators, and build from scratch, which likely requires lots of unsafe. So they won't see the same cost/benefit tradeoffs as "normal" Rust projects. Which may make sense.
(EDIT: Looking at some of their code, they seem to have already rebuilt an entire standard library using their own abstractions. But they've made it far enough to start seeing many of the benefits of Rust at higher levels, by that point. But that was a lot of code to rewrite.)
that sounds like there was a hole in the ecosystem for a more constrained standard library, and they are filling it in. hopefully some of the community will be interested in polishing it up as its own thing other people can use in similar situations.
Did they rewrite things like Vec and similar? I supposed they wanted to implement interfaces to the data structures already present in the C code.
There is a systemd_shared::alloc::Vec at src/rust/systemd-shared/alloc.rs:362-370, see also commit 626261b.
Interesting. Quote from there:
A growable array on the heap, like
alloc::vec::Vecbut without the paths that abort when memory runs out: whatever may allocate returns an error instead.
So indeed they are not reimplementing things for the sake of it, there are important API differences.
What stands out to me from that quote (and checking the rest of the linked code) is that that entire file is LLM-generated, including the SAFETY: comments that are meant to explain why the unsafe Rust is valid (!).
At least in my experience writing unsafe Rust can be quite subtle (there's a whole book about it for a reason!), so that strategy strikes me as kind of insane. Then again, if they're using LLMs for their C maybe it's about as insane as what they were already doing...
Oh, that's most unfortunate. There are already several popular Rust crates which implement standard collections with fallible allocation semantics, crates which are widely used in embedded and small kernel contexts.
Apparently they just decided to vibe slop a bunch of unsafe code instead of taking a dependency on a popular, well-established crate that does one thing (with almost no transitive dependencies)? That's certainly a choice.
I didn’t realise that it was AI-written. Yes that’s pretty insane for a fundamental software like systemd but that’s life nowadays I guess…
Yes, to me keyring-setup.rs (for example) looks like that's what they are doing.
I guess they gotta start somewhere ☺️
no-std is a standard Rust development mode, well supported by the library ecosystem. It's not common, but neither is it unheard of, to use it in a security-critical application extremely tightly tied to kernel behavior that would already forbid any actual function in std by policy. The value of the Rust language is not in std::fs::OpenOptions. Neither is it necessarily the case that the library ecosystem is forbidden just because they're not using Cargo; you can use crates.io dependencies with Bazel, I assume there's a way to do the same thing with Meson. But even if they are forbidding that, again, that's not where the most significant improvement over C can be found. (What would systemd even want to import? Maybe nix?) The point of Rust is to isolate your unsafety to small bits of code with well defined pre- and post-conditions, then freely write normal 'business logic' without worrying about unsafety at all, and then take this same strategy towards type correctness, and mutability correctness, and so on.