I personally feel the Zig is a much better fit to the kernel. It's C interoperability is far better than Rust's, it has a lower barrier to entry for existing C devs and it doesn't have the constraints the Rust does. All whilst still bringing a lot of the advantages.
...to the extent I could see it pushing Rust out of the kernel in the long run. Rust feels like a sledgehammer to me where the kernel is concerned.
It's problem right now is that it's not stable enough. Language changes still happen, so it's the wrong time to try.
From a safety perspective there isn't a huge benefit to choosing Zig over C with the caveat, as others have pointed out, that you need to enable more tooling in C to get to a comparable level. You should be using -Wall and -fsanitize=address among others in your debug builds.
You do get some creature comforts like slices (fat pointers) and defer (goto replacement). But you also get forced to write a lot of explicit conversions (I personally think this is a good thing).
The C interop is good but the compiler is doing a lot of work under the hood for you to make it happen. And if you export Zig code to C... well you're restricted by the ABI so you end up writing C-in-Zig which you may as well be writing C.
It might be an easier fit than Rust in terms of ergonomics for C developers, no doubt there.
But I think long-term things like the borrow checker could still prove useful for kernel code. Currently you have to specify invariants like that in a separate language from C, if at all, and it's difficult to verify. Bringing that into a language whose compiler can check it for you is very powerful. I wouldn't discount it.
> Zig, for all its ergonomic benefits, doesn’t make memory management safe like Rust does.
Not like Rust does, no, but that's the point. It brings both non-nullable pointers and bounded pointers (slices). They solve a lot of problem by themselves. Tracking allocations is still a manual process, but with `defer` semantics there are many fewer foot guns.
> I kind of doubt the Linux maintainers would want to introduce a third language to the codebase.
The jump from 2 to 3 is smaller than the jump from 1 to 2, but I generally agree.
> I kind of doubt the Linux maintainers would want to introduce a third language to the codebase.
That was where my argument was supposed to go. Especially a third language whose benefits over C are close enough to Rust's benefits over C.
I can picture an alternate universe where we'd have C and Zig in the kernel, then it would be really hard to argue for Rust inclusion.
(However, to be fair, the Linux kernel has more than C and Rust, depending on how you count, there are quite a few more languages used in various roles.)
IMHO Zig doesn't bring enough value of its own to be worth bearing the cost of another language in the kernel.
Rust is different because it both:
- significantly improve the security of the kernel by removing the nastiest class of security vulnerabilities.
- And reduce cognitive burden for contributors by allowing to encode in thr typesystem the invariants that must be upheld.
That doesn't mean Zig is a bad language for a particular project, just that it's not worth adding to an already massive project like the Linux kernel. (Especially a project that already have two languages, C and now Rust).
Pardon my ignorance but I find the claim "removing the nastiest cla ss of security vulnerabilities" to be a bold claim. Is there ZERO use of "unsafe" rust in kernel code??
Aside from the minimal use of unsafe being heavily audited and the only entry point for those vulnerabilities, it allows for expressing kernel rules explicitly and structurally whereas at best there was a code comment somewhere on how to use the API correctly. This was true because there was discussion precisely about how to implement Rust wrappers for certain APIs because it was ambiguous how those APIs were intended to work.
So aside from being like 1-5% unsafe code vs 100% unsafe for C, it’s also more difficult to misuse existing abstractions than it was in the kernel (not to mention that in addition to memory safety you also get all sorts of thread safety protections).
In essence it’s about an order of magnitude fewer defects of the kind that are particularly exploitable (based on research in other projects like Android)
Not zero, but Rust-based kernels (see redox, hubris, asterinas, or blog_os) have demonstrated that you only need a small fraction of unsafe code to make a kernel (3-10%) and it's also the least likely places to make a memory-related error in a C-based kernel in the first place (you're more likely to make a memory-related error when working on the implementation of an otherwise challenging algorithm that has nothing to do with memory management itself, than you are when you are explicitly focused on the memory-management part).
So while there could definitely be an exploitable memory bug in the unsafe part of the kernel, expect those to be at least two orders of magnitude less frequent than with C (as an anecdotal evidence, the Android team found memory defects to be between 3 and 4 orders of magnitude less in practice over the past few years).
It removes a class of security vulnerabilities, modulo any unsound unsafe (in compiler, std/core and added dependency).
In practice you see several orders of magnitude fewer segfaults (like in Google Android CVE). You can compare Deno and Bun issue trackers for segfaults to see it in action.
As mentioned a billion times, seatbelts don't prevent death, but they do reduce the likelihood of dying in a traffic accident. Unsafe isn't a magic bullet, but it's a decent caliber round.
> Our historical data for C and C++ shows a density of closer to 1,000 memory safety vulnerabilities per MLOC. Our Rust code is currently tracking at a density orders of magnitude lower: a more than 1000x reduction.
"Unsafe" rust still upholds more guarantees than C code. The rust compiler still enforces the borrow checker (including aliasing rules) and type system.
There are devices that do not have access to memory, and you can write a safe description of such a device's registers. The only thing that is inherently unsafe is building DMA descriptors.
Zig as a language is not worth, but as a build system it's amazing. I wouldn't be surprised if Zig gets in just because of the much better build system than C ever had (you can cross compile not only across OS, but also across architecture and C stlib versions, including musl). And with that comes the testing system and seamless interop with C, which make it really easy to start writing some auxiliary code in Zig... and eventually it may just be accepted for any development.
I agree with you that it's much more interesting than the language, but I don't think it matters for a project like the Kernel that already had its build system sorted out. (Especially since no matter how nice and convenient Zig makes cross-compilation if you start a project from scratch, even in Rust thanks to cargo-zigbuild, it would require a lot of efforts to migrate the Linux build system to Zig, only to realize it doesn't support all the needs of the kernel at the start).
I have no doubt C will be around for a long time, but I think Rust also has a lot of staying power and won’t soon be replaced.