> The merge window for the 6.1 release brought in basic support for writing kernel code in Rust — with an emphasis on "basic". It is possible to create a "hello world" module for 6.1, but not much can be done beyond that. There is, however, a lot more Rust code for the kernel out there; it's just waiting for its turn to be reviewed and merged into the mainline. Miguel Ojeda has now posted the next round of Rust patches, adding to the support infrastructure in the kernel.
If I'm writing my own out of tree Rust module (for the sole purpose of fun), I wonder how hard it would be to bring in external no-std crates?
Rust as a language feels unusually high level for something running in kernelspace, although it never really sacrifices any control. But I wonder how far we can reasonably go in making kernelspace feel like userspace, by importing more of the language's 'vocabulary types', and maybe a few of the best utility crates for comfort.
But besides people having fun out of tree, the kernel has plenty of fundamental complexity that can't very well be reduced. That tends to be the good complexity, the meat of it.
What I would like to see is things that aren't essential complexity becoming nicer.
Simple cultural things like better error messages when the tooling fails, or documentation becoming more common rather than the exception. None of this is guaranteed to magically happen just because there's a bit of infrastructure where Make can call rustc. But here's to hoping =)
Not the OP, but I would assume that necessary complexity is at least where the complexity mirrors whatever real world complexity it is implementing, thinking particularly of protocol stacks like usb, networking, etc.
Depends on what kind of problems you you find interesting, but since it's so close to the metal, and since people want their kernel to be fast, there tends to be a lot of clever algorithms, intricate locking, architecture-specific considerations, dealing with the hardware, all sorts of pretty interesting things you wouldn't usually find in regular business logic.
Take filesystem code for example. It can sound like a conceptually simple and well trodden topic, but if you try writing one there's a pretty large design space and tons of interesting problems to try to solve. And then because of concurrency and the need for performance, there can be very intricate locking to the point it can be challenging to hold the whole model in your head all at once (you can have truncates, writes, mmap, all sorts of very different operations in flight in parallel that interract in funny ways).
Or memory models. Reading memory-barriers.txt is a lesson in humility, I believe you can count on your fingers and toes the number of people in this world who can truly claim intimate familiarity with all the corner-cases and details implied by the model in that little text file =)
But take practically any big subsystem of the kernel, and there tends to be plenty of interesting domain-specific problems and challenges.
I believe they're referring to the essential complexity of the domain. An operating system has some "lower bound" on how complex it can be, which is rather high.
But some stuff doesn't _have_ to be hard. Like OP said, there's no inherent reason for error messages and failures to be cryptic or documentation to be sparse. The system could be more transparent or modular, easier to debug/analyze, etc.
I think there's an example in GCC vs Clang here, but I'm not qualified to comment.
This is more a question of policy than mechanism - I'd imagine at least a provisional policy is in place, but the only to be found somewhere in the relevant kernel mailing lists.
> I wonder how hard it would be to bring in external no-std crates
Wasn't this a thing that would not happen at all? at least that is what I remember from previous discussions. Another question would be how do you avoid an explosion of crates with different versions for each module.
Not a kernel hacker, but if it's just for fun, I don't know if you'd need to limit yourself to no_std crates. Allocation is supported (if it wasn't, then Rust's stdlib wouldn't be adding fallible allocation APIs to support the kernel usecase (and even if crates in the wild aren't using these APIs and abort on OOM, again, this is just for fun)). Meanwhile, I feel like OS-specific stuff performed by libstd (e.g. threads, networking) must surely be supportable somehow, since the OS is right there and all its facilities still exist, even if you might need to adjust codegen to account for the difference between kernelspace and userspace (I assume you would need to compile against a specific target?).
Although Rust for Linux has its own alloc, that isn't really alloc. It is like if you wanted Coke and got Pepsi, if you just wanted fizzy brown beverage you're fine, but if you actually cared this isn't OK.
Rust's String (the mutable owned string type from alloc) implements AddAssign meaning you can write fname += ".txt" and that works, but Rust for Linux doesn't allow that. This is just a really obvious example, there are many other differences
You can't use methods that may panic on OOM like Vec::push or Box::new. This means that close to 100% of crates that use the stdlib won't be usable in the kernel without modifications.
My understanding isn't that you _can't_, but that you _aren't allowed to_ by kernel policy. (The risk being that the kernel will panic on OOM, which is not an acceptable way for the kernel to deal with OOM conditions.)
If this is out of tree, AFAIK you can use these all you want. Whether or not you _should_ is obviously a different matter.
In Rust for Linux their custom alloc library does not have that function offering instead Vec::try_push(&mut self, value: T) -> Result<(), TryReserveError>
OK and... ? What purpose does an always-failing allocator for Vec have? I guess maybe it's useful for some unit testing cases, but otherwise it seems pointless.
So few people actually do their development/testing in truly-sandboxed environments that I don't think that there's actually much of a difference in practice between malicious code running in userspace vs malicious running in kernelspace ( https://xkcd.com/1200/ ). Of course, I'd love if sandboxed dev environments became more usable and widespread.
I expect it to be possible in near future that you develop, say, a web server in Rust in userspace, and with a few changes run it in kernelspace, with improved performance.
It can absolutely make things faster. If your program is running on data that exists in the kernel you don't need to copy it over to userland/ perform expensive context switching.
It can make things faster is not the same as simply running it in the kernel will make it faster. There are definitely certain situations that making use of fewer context switches helps with, and where page mapping isn't sufficient, but if you just write an entire user-space web server, then just compile it as a kernel module, expecting it to see a notable performance improvement, you're going to be disappointed.
edit to clarify: the reason it won't help (much) is because most of the things it would help with have already been optimized via features like CoW pages, the VDSO, sendfile, etc.
Yes, it can still have significant benefits. Async IO is an attempt to get around the performance issues and, given lots of kernel support that largely does not exist today, it can bridge the gap to a degree, but it's never going to match just avoiding the entire issue.
You can use things like XDP to get a lot of performance back but 0 context switches/ 0 copies
is always going to be faster.
Rust is a manual memory managed language, it literally has nothing inexpressible that C could do. Hell, C is a “higher level” language in that it doesn’t have any way for SIMD instructions.
To add something concrete, you can manually free memory as well based on some dynamic property if you wish.
I think bringing Rust into Linux was a really bad idea. IMO Rust has yet to prove it isn’t another overly complicated C++ waiting to make projects almost incomprehensible to understand. It does not provide the same easy ramp up that C provided when working on most of the system software stack on Linux. There’s also still too few standalone projects using it to consider it a proper candidate for folding into such a large project forever.
I am surprised Linus agreed to this given that he doesn’t like C++ and usually errs on the side of clear over clever, and we have yet to see tangible benefits of using Rust.
I have worked as a C++ dev, but am definitely not a C++ expert by any means.
My take however is that C++ is inherently a complex language due to deliberately not sacrificing backwards-compatability of the syntax and semantics, which has been creating a mess as the language has evolved: there are many, many things to define semantically in order to "fit" a new piece in this old already-elaborate puzzle that is the C++ standard.
At least not yet. My fear is it's _very_ easy to fall in to the same trap as C++ has, and become a big mess. Scott Meyers have a very nice talk here: https://www.youtube.com/watch?v=KAWA1DuvCnQ about all these traps and pifalls that we have to deal with in C++.
That said, I'm starting a bit with rust and enjoy it so a lot, especially the tooling alone is worth it - and if I never have to write another line of C++, I would be very happy (ofc the real world argues I have a lot of C++ code that will need maintenance).
When I tried Rust I came from Python and it was clearly too much for me to comprehend but after 2 years of C programming and 1 year of C++ programming, the problem Rust tries to solve make a lot more sense and I know understand the problem it's trying to solve. I am trying to use it again things like the borrow checker and Traits now make a lot of sense to me. I am also looking forward at not having to write C++ again. I haven't looked into C++17 and beyond though I must admit.
If you stick to a subset of C++ it's not so ugly since that's before all the new stuff got bolted on. Rust might undergo similar uglification, but the clean subset should still be there and is better than any clean subset of C++. I still hope that doesn't happen though.
Give it 10 years and people will feel similarly about Rust. They’re both just super-complicated languages.
Some devs thrive on that, but most people can’t and shouldn’t have to. And you can see that contrary to what some in the Rust community are saying, there’s a push to use Rust for web. Bonkers.
If you get the chance, do take a serious look at Rust (as in, write something significant in it). You might be surprised at just how suitable it is for high level stuff.
I (re)wrote a < 1kloc program in it from C++ and I found that it had its good and bad parts, like everything.
But there’s too much overlap with C++ and not enough projects. IMO Rust has proven that it can survive, but by far hasn’t reached enough popularity to justify a switch and keeping two complex yet similar languages in ones head is unwise. So I’d rather focus on Go and Python which actually bring something complementary to the table.
I find most languages are fairly simple. The std lib that goes along with them on the other hand... Those are the monsters in the room. Take java for example. Do you think java is verbose because it is java? Or is it because of the libraries you use?
When you boil code down to its bare essentials it is moving stuff from one part of memory with a possible transform to another. C does that exceedingly well and gets out of the way. However, the heavy price we pay for that is low type/bounds checking. Pretty much all other languages have tried to get the 'get out the way of part' but with type checking. Rust has taken the approach of you ask for memory and it is tracked at compile time. Not a bad idea. But it seems to trip some people up. Especially if you do not 'get' the idea of object/memory ownership. Which is something you have to do manually in C/C++. C++ has started to put wrappers around all this junk which helps.
Honestly the rust web frameworks are quite good. I don't find them any more verbose than say typescript or golang because enough higher level types exist to abstract away complexity. Majority of api code is just crud and business logic so it makes any difference in which language it's written in terms of complexity.
And the rust ORM libraries are catching up with other languages so there is no additional advantage from picking a gc collected language.
The way C is written in the kernel is really unlike the C you typically encounter in the wild. Try reading it and tell me how comprehensible you find it and how easily people ramp up into kernel contributions.
and we have yet to see tangible benefits of using Rust
Is that the royal we? Have you actually (successfully) tried writing something in it?
I am surprised Linus agreed to this given that he doesn’t like C++
Maybe Linus has lost the plot after decades of careful stewardship. Or maybe it is an opportune moment for a closer second look. Who knows.
Sometimes that is what I try to do when my expectations are subverted if I care enough about the subject.
Can you share some concrete examples where you think "kernel C" is really unlike normal C? Sure, there will be couple of additional things the programmer needs to be aware of (e.g. special care needed when inside interrupt handlers and when holding spinlocks) but overall it doesn't visually look that different.
Macros, the ugly side of C, Rust. Shame Zig didn't come before rust, imagining kernel data structures written in Zig, brings a smile.
Right on point that kernel style C is its own unique world, with a steep learning curve, so lets add Rust with its own steep learning curve. Rust readability isn't any better than kernel C, guess I'm missing the 10,000 hours of reading Rust.
Of course it would a big oops simile, but use after free isn't something that has happened to me in 40 years but I keep testing for it in other peoples code ;)
> IMO Rust has yet to prove it isn’t another overly complicated C++ waiting to make projects almost incomprehensible to understand
Rust is relatively easy to read I think. The borrow checker is what gets all the hate, but that is an issue for writing, not reading. If anything, things like pattern matching make otherwise long if chains easier to read IMO
> we have yet to see tangible benefits of using Rust
Rust eradicates whole classes of errors in safe code, and unsafe code is more safe than the equivalent C or C++. The only theoretical way to not have a tangible reduction in errors would be to believe that a C programmer is good enough to never commit the error classes Rust eradicates, and believe Rust usage would increase the number of logic errors. This seems incredibly unlikely to me.
Perhaps you can clarify - if you're saying unsafe rust that performs undefined behaviour is unsafe regardless of the safe bits, then you'll have no disagreement. If on the other hand you're suggesting that it's possible to have well defined unsafe rust that exposes a lack of safety across the unsafe boundary, then you're going to have to explain a bit more...
In Rust, casting a *mut to a &mut (the standard method of allowing safe code to mutate an object) is unsafe if other &, &mut, or Pin<&mut> exists, regardless of whether or not you commit a use-after-free. In C++, the equivalent code interchangeably using * and & is safe until you actually commit a use-after-free. This makes it harder to write correct Rust code mixing safe and unsafe code.
It's not just dereferencing invalid */& that's illegal in Rust, but constructing and dereferencing valid &/&mut in ways that don't respect tree-shaped mutability.
I've put together a playground at https://play.rust-lang.org/?version=stable&mode=debug&editio.... "Object graph" architectures are common in C++ and sometimes necessary in Rust when building GUI applications or emulators. Rust's pointer aliasing rules invalidate otherwise-correct code, placing roadblocks in the way of writing correct code. And there's so much creation of &mut (which invalidates aliasing pointers for the duration of the &mut, and invalidates sibling &mut and all pointers constructed from them), that's so implicit I don't know what's legal and what's not by auditing code. (Box<T> used to also invalidate aliasing pointers, but this may be changed. The current plan for enabling self-reference is Pin<&mut T>, but the exact semantics for how and when putting a &mut T in a wrapper struct makes it not invalidate self-reference and incoming pointers, is still not specified.)
I've heard statements that addr_of_mut! is an interim API, and the situation may be improved with &raw and unsafe-deref syntax (https://faultlore.com/blah/fix-rust-pointers/). But I expect a production systems language to be an improvement upon C/C++'s usability in their strongest domains out of the box (much like how Send/Sync as marker types not creating UB beyond C++ makes threading more tractable, and enums are superior to std::variant). Instead today's Rust pointer rules redefines swathes of C and C++'s use cases and design patterns as undefined behavior, and the alternative approaches are ugly to express in safe code (Cell/RefCell), and easy to get wrong and tricky and ugly to get right in unsafe code (see my playground), with the promise that they were trying to make programming easier and are trying to create a suitable replacement someday down the line (7 years and counting after Rust 1.0).
Thanks for the explanation. Self referential structures are indeed problematic.
I'm actually pretty sanguine about the general case of invalidating C/C++ patterns. It doesn't surprise me that some new computer science is going to be necessary to help deal with the edge cases exposed by mainstreaming a new paradigm.
My goal is not to invent new computer science, but to create a language where programming is not "puzzle solving" (https://news.ycombinator.com/item?id=33694124), like needing to work with ghost cells (didn't try firsthand yet) since pointer algorithms are laden with syntactic salt and pitfalls (note that pointers is not C/C++ patterns but fundamental systems programming), working with Rust's num traits that describe the properties of numbers rather than directly saying your FFT code is generic over f32 and f64, hacking in sealed traits using underspecified and disputed visibility rules (attempting to match the type of a sum type at compile time), chaining iterator combinators rather than writing code where program order matches execution order, not being able to index into strings when parsing unless I convert to &[u8] then spend extra O(n) runtime validating the remaining text is valid UTF-8.
From experience, I find that "puzzle solving" tends to result in very good code. I recently had the experience of fundamentally changing the design of a decent chunk of code (think maybe 3 weeks work) for which I had integration tests that were comprehensive. Once I had the rust compiling, the tests passed first time. I've had this sort of experience in Rust several times, and never in other languages (primarily C and Python). It wasn't a trivial implementation in Rust - I had to think carefully how to craft it to make effective use of Rust idioms, but the result is great.
It feels to me that the question comes down to whether changing paradigms is worth it. I have found overwhelmingly that it has been and with my hard won battle scars, I'll stay here.
What I see as Rust's advances in programming experience (I assume you also like enums with payloads, bounds checking by default, structured threading to avoid C++'s "data races by default", fat pointers over storing vtables in objects, the hashmap Entry API) should be able to stand on their own. I want to be able to use them in a language which doesn't obstruct me from applying working patterns in areas (general single-threaded memory lifetime management) where I rarely make mistakes (unlike with threading), and find Rust's current options to be regressions (only offering easy access to special cases like Box/Rc/Arc/RefCell, I can write imperative code with loops and matches, but the community largely juggles higher-order functions into Option/Result/Iterator methods, which leak upon contact with side effects). Though I'm unsure if you find the asepcts I criticize to be positives, or merely less of an issue than I see it.
Separately, I've been loosely following gcc-rs's development, which has uncovered some surprising hidden complexity in rustc's operation leaking into the Rust language's behavior. For example, for loops "requires Iterators that will need generics and traits to be implemented first" (https://thephilbert.io/2021/02/15/gcc-rust-weekly-status-rep...) and these abstractions likely don't get optimized away in debug builds, and resolving method calls can take dozens of steps evaluating Deref and adding and removing & and &mut (https://thephilbert.io/2022/01/31/gcc-rust-weekly-status-rep...). I think that bidirectional type inference (one time extracting a lambda from a method argument to a variable broke argument inference), complex method call resolution algorithms, and defining the semantics of code (not just validity as with borrow checking) through complex trait resolver algorithms now being reimplemented in Prolog (Chalk and possibly datafrog), collectively do Rust a disservice in fulfilling the role of a transparent, explicit, well-specified language.
For now I'm just waiting for the language I'm hoping for (whether or not it's a language you want to use). My fear is that the inertia and resources of C and C++ on one end, and Rust and pcwalton calling Zig with general-case memory management a "massive step backwards for the industry" on the other end, have drained away available resources from a language (Zig, Nim?, Hare?, etc.) which uses abstraction and higher-order functions sparingly in places where they resolve problems without causing harm, rather than making them the most viable option in the language by crippling alternatives.
Interesting. I think my perspective is that the handrails are so useful that I can live with the few cases they get in the way, because it's rare they're actually a performance sticking point. Indeed, the handrails (at least in principle) can add much in terms of performance with e.g. the strong no-alias guarantees and iterator semantics. I guess if you spend all your time writing complicated graph based data structures over pointers you might have a different opinion!
I write C++, Kotlin and Go code day to day, and I respectfully disagree. the syntax is incredibly terse. Most rust code I've encountered sprinkles macros with functions, which have slightly different semantics (note this is not an indictment of C or C++'s macros, far from it), and the combination of macros, pattern matching and unwrap lead to code like [0], which frankly I find incredibly difficult to work with.
> Rust eradicates whole classes of errors in safe code, and unsafe code is more safe than the equivalent C or C++.
Completely agree here, and nopt only does it do that it does so _without sacrificing performance_ in many cases.
I suspect the style and library code used matters greatly. Said differently, the constructs that Rust has make it _possible_ IMO to write code that is easier to read than equivalent C. Obviously even this depends, as the simplest use case will look very simple in C, but the most complex use case it is possible to write cleaner looking code in Rust due to he inclusion of higher level constructs that C simply does not have, so it typically resorts to hiding this via macros.
I've only interacted with a small amount of rust code over the last 3-4 years, but it's all been a similar style to the above. I'd love to be proven wrong with any examples of well written understandable rust code though!
Where is `threshold` and `offset` coming from?
How come running `cargo test` in directory `base32ct` actually tests nothing (I get 0 everywhere) despite there being some test code? Messed up `Cargo.toml` file? sighs
The purpose is to enter the if block if and only if the pattern is matched. In your example, if "need_explicit_dep_argument_path" matches enum "DepArgumentRequirePath::NotNeeded" the if block will be entered (else it will be skipped). This is a bit of an atypical example as there are no bindings in the pattern match, but most times there are, and they are then scoped within the if block. For example:
let my_option = Some("test");
if let Some(my_str) = my_option {
println!("I matched this string: {my_str}");
}
I guess that's going to be the bigger accomplishment on all of this.
People keep talking about memory safety ad nauseam, but I think everyone is missing the point.
It is in fact possible. "Linux KPI is the FreeBSD effort for providing a Linux compatibility interface to make it easier to bring Linux DRM drivers to FreeBSD and for them to remain up-to-date against Linux upstream."
Ah... Well FreeBSD on the Apple M1 is highly unlikely, so this is going to be a non-issue in the near term.
And none of the existing DRM drivers are likely to be rewritten in Rust.
In the medium term, maybe some in-kernel dependencies might end up getting rewritten in Rust, or maybe some brand-new architecture may have a greenfield development in Rust.
I'm going to speculate that FreeBSD on commodity graphics hardware is safe enough for a few years, but that longer term Rust compatibility might have to be added to the Linux KPI.
> I think bringing Rust into Linux was a really bad idea. IMO Rust has yet to prove it isn’t another overly complicated C++ waiting to make projects almost incomprehensible to understand.
Isn't that already the case? Rust now is very different from Rust in the early days and is also exponentially more unintuitive. Maybe that's fine, I don't know, but I'm personally very much struggling with its quirks.
What early days is this referring to? In any case, regardless of one's opinions on Rust's overall difficulty, I find it difficult to argue that the language's ergonomics have done anything but improve over time.
> Rust now is very different from Rust in the early days
Rust pre 1.0 kinda doesn't count.
The whole point of 1.0 is that there is a guarantee that there will be no more dramatic changes to the language.
> exponentially more unintuitive
Almost nothing about any programming language is really intuitive.
You mean that C uses paradigms that are intuitive to you due to your experience with it or similar languages.
Rust uses different paradigms that are more immediately intuitive to people with experience in functional languages. And the borrow checker. Which is probably immediately intuitive to nobody, but worth it.
I feel like Rust is pretty much as intuitive as C. Which is too say. Not intuitive at all. With the exception of pure FP languages I haven't even seen a language that is really intuitive.
>> we have yet to see tangible benefits of using Rust.
As a long-time C and C++ programmer, I have to disagree. C and C++ have been great and so much software has been written using them, but the time has come to move on.
The majority of software security bugs are due to the lack of controls in C and C++. This is not an opinion or an anecdote, it is a fact:
Linus is more pragmatic than you think. He's cautious and resistant to faddish trends, but he can be convinced. I think Rust has a ways to go before it's ready for the kernel proper (the architecture support being the big thing), but if it does get there I think he can be open to the idea of a switchover.
To be frank I have no idea what his opinion of Rust is but if there is a guy who has it in him to make that kind of decision it's Linus. He changed software twice he can do a third time.
The difference is that Rust is safe by default. The `unsafe` keyword serves as documentation that the code it applies to should be reviewed extra carefully for soundness. C++ on the other hand is unsafe by default, and all code must be reviewed extra carefully to verify soundness. Unless of course you wrote linters to prevent anyone from using constructs that can possibly be used unsafely without a manual “I know what I’m doing” override, but I think despite all the recent progress in static analysis this still isn’t possible
The first case is at least documented that it's the programmer's responsibility that the view should not outlive the object pointed to.
Finally, the address sanitizer helps you with that, however I wonder how many actually do use sanitizers?
Overall, I agree that something could have been done to prevent temporary objects at all. From my newbie point over view, it seems the standard API has the tendency to be lower level rather than ergonomic: it's up to you to know how to use it (and fuck up with it). Quite sad, because that kind of makes the language more difficult to use than it should be. I don't have enough knowledge, and I wonder if making the constructor on (const std::string&&) private/deleted would have been enough to prevent it?
The second case I guess the principle is similar. Not sure if the sanitizer finds the error there, but still scary.
There is a discussion that without rust's move semantics C++ cannot reach the safety levels of Rust. But rust's move semantic cannot be brought to C++ without breaking an existing code.[1]
In a short, C++ approach is to give any object a "blank state" which it must turn into after the value was moved from it. It is an attempt to track state "value was moved out" dynamically. Rust tracks it statically by treating a variable whose value was moved out as uninitialized variable and ensuring that are no accesses to uninitialized variables.
Yeah, I do understand the main principle behind it, and I think an address sanitizer helps here - I did some tests and the ASAN coming with Clang 14.0.0 catches the bug (at runtime, of course).
It's a different approach, and definitely less efficient than compile-time checking, but if your program is not too complex I think it's OK. Especially if you use such sanitizers at the unit test level.
I don't have enough experience to say if it actually works in general though, because as usual everything on paper is always working.
>"Finally, the address sanitizer helps you with that, however I wonder how many actually do use sanitizers?"
I use C++ to write general backend servers / web apps among the other things. Not a single one ever deployed without passing sanitizer tests.
Not that my code would ever look like the examples above. I personally consider modern C++ safe enough for decent level programmer.
Of course I can not guarantee safety buy my servers run non stop servicing tens of thousands of client for months between updates without any hick-ups.
I looked at Rust to see if it can offer me any practical advantage vs modern C++ for what I do and so far did not see anything convincing enough.
I've written software for enterprises of Bell scale, but yes the team was small and always under my control. I still work mostly alone (hire subcontractors occasionally). My interactions with other systems is by network APIs so I do not have incompetents screwing with my code.
I understand that this is rather unique position but this is what I wanted, worked for and had managed to achieve. I mostly design and create products from start to finish for my clients. Been on my own for 20+ years already.
BTW. I doubt that Rust or any language for that matter can be a cure from shitty programmers. Some help sure but they'll manage to fuck things up regardless on a different level.
> The first case is at least documented that it's the programmer's responsibility that the view should not outlive the object pointed to.
This is the problem with naked pointers in the first case. We've had I don't know how many years of experience to tell us that relying on programmers to not make mistakes is a terrible idea. If documenting requirements fixed these issues we would still just be able to write C.
The problem with sanitizers is they're an opt-in addition, and like static analysis tools they have a tendency to be have some false positives, which causes people to distrust then and say "but I'd never make that mistake". Compiling with asan enabled would cause our CI build times to double, as we'd need to build with and without (and we have 4 configurations over 3 platforms. My previous project had 3 configurations over 9 platforms).
In my opinion, if you can't handle a sharp knife, you've got no business being in the kitchen.
It seems that the primary security argument is that N-1 types of issues is better than N. I would argue that the formula is really N - 1 + X, and that we're all focused on the very positive "-1" aspect, but what's the value of X? In other words, what are we trading off by using Rust instead of C in the kernel? Why trade a language which we know the pitfalls of (N) for a language that's potentially adding X pitfalls, and if you're going to argue that Rust has no pitfalls, then to me that's just the kool-aid talking. Realistically, in a new language, you don't know if X is 0, and adding unknown unknowns are precisely the one thing you do not want in a critical piece of software like a kernel.
Furthermore, if OSes need to be secure, and system kernels need to be even more secure, which we all agree on, then all you're doing by advocating against using a stable language with known pitfalls like C is you're lowering the knowledge bar ("hey look I can write kernel code now because I won't introduce memory issues!"), thereby increasing the pool of people who will make logical mistakes out of lack of knowledge, which you will not eliminate with static analysis.
C is not ideal, but it's a practical way to gate the entry to critical software, because
1. C, the language, has a handful of pitfalls, while the software written in any language has orders of magnitude more avenues to exploit it (e.g. access permissions, communication protocols, environmental assumptions, etc).
2. Most of what's difficult in C stems from the realities of dealing with computer architectures. If you can't be bothered to learn the ins and outs of C, you're not fit to write portable low level machine code in a kernel just yet. Just because we can be reasonably sure you won't introduce a memory problem is not sufficient guarantee that you won't do stupid things in the kernel that will cause security problems in a different way.
In the end, I hope I'm wrong about Rust and X is 0, but it seems to me that there's a much better way to ensure we get to an N-1 situation without an X: introduce the borrow checker in C.
Why throw the baby with the bath water? The software industry is very aware by now of the pitfalls of rewriting a project instead of making incremental changes. Bring the memory safety to C. You get 50 years of stability and well documented issues, while still removing a whole class of bugs. Now that would be an absolute win.
But Rust builds on top of that 50 years of experience, stability and known issues and has solved a lot of them. What does C have to offer that Rust doesn't?
I don't think it's fair to blame the issues that code written in C can have on incompetence.
> But Rust builds on top of that 50 years of experience
Is it? Rewrites only succeed if the original people rewrite the original code, because code is just a serialization of someone's thoughts. That's why it's the people who are the most important assets in a project, not the code. When the original people leave, projects typically fail.
Rust is not being written by the same people who made GCC. It's a different group of people who are trying to do better than C. I wish them best of luck, but to say that they're "building on top of 50 years of experience" is implying that the software they generate is as good as software that has been battle tested for decades on numerous architectures.
> I don't think it's fair to blame the issues that code written in C can have on incompetence.
It's not a blaming game. Code written in C has issues because C has issues, but are you then saying that Rust has no issues? Will never have any issues? What's the bar here?
>It's not a blaming game. Code written in C has issues because C has issues, but are you then saying that Rust has no issues? Will never have any issues? What's the bar here?
Rust eliminates an entire class of issues that constitute 70% of C bugs (and largely the most critical bugs at that) by design. Nobody's saying Rust has no issues and never will, but they are saying that this is an objective improvement.
> Nobody's saying Rust has no issues and never will
Ok, so we agree that Rust must have some issues, some of them undiscovered yet. What suggests that Rust won't introduce issues that will be larger than the 70% of issues that it solves with C? Because to me, it just sounds like we can't know so we're being hopeful that we don't run into that situation.
Seatbelts have issues. Some of them undiscovered yet. What suggests that Seatbelts won't introduce issues that will be larger than the 70% of issues that it solves with crashes? Because to me, it just sounds like we can't know so we're being hopeful that we don't run into that situation.
What a ridiculous way to make an argument. Even a silly seatbelt had to wait for about 10 years after being released before it was required to be in cars. Maybe write a few other kernels in Rust before using it in billions of devices? But no, shoot straight for Linux because "C bad, Rust good".
> It's not a blaming game. Code written in C has issues because C has issues, but are you then saying that Rust has no issues? Will never have any issues? What's the bar here?
For a given value of "issues," that's an accurate portrayal. Statically verified memory safety at the language level is a central part of Rust's mission statement. This is an essential difference from C in how it approaches that problem space. Rust might "have issues" in the sense that compiler bugs are exposed by particular edge cases, or that dealing with certain problems is needlessly difficult or verbose, but reducing everything to "issues" to portray it as equivalent to C is absurd. You might as well say they both have "syntax" and conclude that all code written in Rust is still written in C.
If professional chefs would constantly maim themself and each other despite extensive occupancy safety training, knives have no place in the hands of a responsible professional.
Using C is the SE equivalent of taping down one button of the two-hand control device of a die cutter.
Kernel hackers are considered the most skilled people in the whole profession. The Linux kernel is one of the most read source code on the planet. The code is audited to death. Much of the research into static code analysis starts there. They have tools available most other people don't. That's what i mean.
If, what ever the happens there, is not up to your standard of professionalism, maybe your standard is unrealistic?
That's not training. That's being thrown in the lake to learn how to swim.
Now you're measuring how many people drowned, and you're saying "let's enforce that everyone use a flotation device, and there will be fewer deaths".
Sure, but there will also be fewer actual swimmers.
To make this more concrete, you can't look at something in aggregate and say "well, we are having this one type of issue, let's just throw everything away and start over".
Yes we must do something, I just don't think that Rust is the best answer. Maybe have an actual safety training. The language is hard. Write a compiler for it, study the spec, simplify the spec, upgrade the language, etc.
Just because you didn't understand my argument doesn't make it in bad faith.
If working on the Linux kernel is the training then you're measuring incidents that occur _during training_.
The whole point of training is to practice and make mistakes _before_ the actual work. Once they're considered experts, you can measure the knife cuts in their work.
I understand your argument. It works with starting from a massive misrepresentation of what I have said (aka bad faith). Your argument is fatally flawed due to the reason i stated. And that's why there is nothing to be said to the substance, other than what was written and this discussion was and remains over.
>It does not misrepresent what you said, and failure to see that means you did not actually understand it
Oh yes, I do. I do know what i mean and I can see that your quote of it was either extremely unintelligent, something you can by definition not see, or intentionally miss representing and therefore bad faith and therefore something you by definition lie about.
I'm heavily leaning to bad faith, because you never make any attempts to refute arguments anywhere in the whole thread.
So, of course, I'm obviously correct on on this one, so it's good thing either of us wasted any time talking on the substance.
Some of the first software I ever wrote was C and then C++. I’ve since worked on Billion+ line Java code bases. I’ve also worked professionally in python, ruby, Type/JavaScript.
When I picked up Rust 15 years into writing software, it taught me to write better code.
Let me repeat that: even after extensive training and professional use of other languages, rustc the compiler taught me to write better code.
If you’re looking for a “we should train people better to not make mistakes” you want people to learn software development from rustc. That training is very transferable back to C and C++ and even Java. Could this automated “teacher” be better? Sure. Could it be less strict? In certain cases sure. Is it the best training program we have? This best I’ve ever seen.
> Most of what's difficult in C stems from the realities of dealing with computer architectures
This is patently untrue. What do malloc and free have to do with computer architecture? Most of C's difficulty is deficiency of the language unrelated to its low level nature.
> What do malloc and free have to do with computer architecture?
You're talking about a library at this point, but ultimately the root cause for allocating memory is because memory is limited, unlike, say CPU time. We do not allocate CPU time explicitly, even though there could be a CPU architecture that could support that, and C would run on it.
> Most of C's difficulty is deficiency of the language unrelated to its low level nature
Do you think that comparing signed and unsigned integers is also unrelated to CPU architectures?
> if you can't handle a sharp knife, you've got no business being in the kitchen.
Sure, and we have driving licenses to make sure people know how to handle a car, but you won't find a race driver who doesn't use seatbelts. Because even the best humans are still human.
Arguing against safety measures because you think you're too skilled to make mistakes is also something to be avoided.
See, you're arguing that Rust is putting seatbelts in racecars, when what is really happening is you're replacing racecars that have no seatbelts with Corollas that have seatbelts.
We agree though that adding memory safety to C would be the equivalent of racecars with seatbelts.
Bit of a stretch to call Rust a Corolla. A lot of the time they both compile to equivalent assembly, and when they don't, the run-time performance is usually very close.
Sure, let's be more accurate. Replace the Corolla with BrandNewCarX. How do you know the engine won't blow up 5 laps into the race? You objectively can't know, because the only way to find out is to perform extensive testing over a long period of time, so as far as I'm concerned whoever is adding Rust into the kernel is making the kernel a testbed for Rust and if it doesn't go as planned, everyone will be paying the price. Since Rust is already in the kernel, I hope all the Rust fans are right about it.
> How do you know the engine won't blow up 5 laps into the race? You objectively can't know, because the only way to find out is to perform extensive testing over a long period of time
Well it's been 6 years since Rust 1.0 was released. And it's had extensive adoption over that time period, including in projects used in vast numbers of devices and services. Firefox runs on Rust, Dropbox runs on Rust, AWS and Cloudflare are both using Rust for core services. Android is shipping Rust. Microsoft is looking at adopting it in Windows. What would count as a long time for you?
If I look at Perl, I'd say about 25 years. People were equally excited about it at the time. It took a few decades for everyone to agree it's a net negative to use it in a project, even though it's still very good at what it does.
> How do you know the engine won't blow up 5 laps into the race?
Lol you do realise this is a dunk on C right? 40 years of experience and we have seen all kinds of stupid shit written by very smart people. Just imagine if the kernel wasn’t written in C and someone wants to introduce C instead.
I do wish that rust had stayed a simpler language, but I do think it started about as simple as you could while having a borrow checker. The fact that c2rust transpilers (for unsafe rust) popped up so soon after its release years ago, is good evidence that at least a subset of rust is only slightly syntactically different to c. Even if you only had to add lifetime notations to c, the amount of code that would have to be rewritten is vast. And a lot of the extra stiff in rust is to lower the performance cost of safety. Like avoiding runtime bounds checking or unnecessary copies while keeping the benefits. Tl;dr I don't think c with a borrow checker and bounds checking is what we want performance wise. I think that is pretty much carbon.
If you want robust and well known, pick ada/spark. That language and it's culture is all about security and has been for decades. It also doesn't have quite the performance of c and rust.
And about the sharp knife... I have worked embedded c++ for decades now, some safety critical where we inspected the assembly generated and verified 100% code and branch coverage, on the assembly. I have made one memory safety error that escaped test in those years. That has been found yet...
I'm not in the kernel culture so I don't know. But it doesn't seem like it values things like static analysis, unit test coverage, san builds etc. It seems from the outside they are simply relying on their knife skills instead of measuring the quality of their work. Microsoft and Google both say over 70% of their exploits have come from memory safety errors. So it isnt M-1 + x. It is M0.3 + X. And rust isn't super new, so we have some ideas about X from early production use in firefox and dropbox. And we have an idea about how many knife users never cut themselves given even just the recent history like beacown.
Thank you for a thoughtful response. I do hope I am wrong and we as an industry end up in a better spot overall, though I suspect Rust is not the language that's going to get us there. Most accounts I've read or conversations I've had with people who used Rust in large projects boil down to "it's not worth fighting the language", so my general impression is that Rust is the Perl of this decade, and I'm excited for the next generation of languages after Rust, because they will have to consider the safety aspect.
In the three projects I've been on that used rust, there really hasn't been much of that. Mostly I have been surprised at how high level it feels even with all the control. I do think the type of project makes a difference. I have been doing mostly dsp type stuff. And coming at it from the mindset of ocaml or modern c++ (value semantics etc.) Vs the ansi c mindset I used on TI DSPs back in the day makes a big difference. And that is the problem with bolting on the safety. The borrow checker doesn't just find mistakes, it also forces you to code in a different style so it can reliabily do so. Not necessarily a better style, but not slower either, a different and easier style for it to check. The syntax could have been closer to c, but the style would end up being similar. As far as all the complexity getting added, ferrocene or someone like them may end up making a safety critical subset like spark is to ada, that is simpler to do formal verification on. That would be a good subset for drivers and kernels.
> C is not ideal, but it's a practical way to gate the entry to critical software
Aw, yes, the C makes genius programmers meme. I think we've seen very little evidence this is the case. C may be useful to know. Learning C well, because it is difficult, may be useful. These things are speculative, but let's grant them. Unfortunately for you, the proof of the pudding is in the eating? The fact that lots of C code has lots of problems should be an indication that, not only is C not working to solve many modern problems, but that, if C gives us geniuses, we aren't seeing the results.
> introduce the borrow checker in C
You: Just glue on some wings and see if it flies...
Me: That's not how this works! That's not how any of this works!
> I'm only claiming that to be effective at C you must understand computer architecture well.
You still have this problem: We have lots and lots of buggy C code in critical software.
If your claim is to be effective at C you must understand computer architecture well, but unfortunately few are effective at C, because few really understand computer architecture well, and unfortunately we have lots of buggy C code as a result, I'm not sure where you are after that?
Is it possible C hasn't worked as the gate you say it has worked as?
> to be effective at C you must understand computer architecture well.
So long as we are here, I would also quibble with this claim. Knowing loads about C, or more specifically how to prevent C memory safety issues, is perhaps not the best indication one knows anything about network security or cryptography. In fact, we know the reverse is the case. There are plenty of OpenSSL devs who are domain experts in cryptography, who have not proven themselves well adapted to deal with C memory safety issues. Something like Rust sounds perfect for such a use case?
> Right, because the only way to fix problems is to rewrite? Typical inexperienced programmer attitude.
What do you think writing a borrow checker for C would entail?! Do I think it would be a tremendous effort, with little gained? Oh yeah. Do I think we should just use Rust for new software? Yep, because why wait for this C borrow checker? I just don't get it. I think saying "Just use Rust" makes me sensible. "Let's build a borrow checker for C!" is tilting at windmills.
I've programmed in C for 20 years and Rust for 3 and I'm a _much_ better programmer after using Rust. From experience, Rust doesn't make you a lazy programmer, it makes you a much better programmer.
I don't disagree, but this is objectively just hope. The only reason N*7 is huge is because C's adoption. There is nothing to suggest that Rust's N*(bad issue %) is smaller than Cs if it had the same adoption as C. It's fanbase is just trying to increase its presence at the expense of C, to then be able to say "see, we did it, we replaced C and we're better off!", but today, it's equally likely that the outcome is going to be "well, we didn't know about <insert issue here> at the time".
It's not so much hope as it is just me being an expert in security and rust and being able to state that very confidently based on my deep understanding of the relevant fields. I could be wrong in the sense that all things are unknowable and truth doesn't exist, but I think I'm right.
> In my opinion, if you can't handle a sharp knife, you've got no business being in the kitchen.
Great! So we agree that no person should have any business writing C. It's proven time and time again that even the best of the best C developers can't write safe C code.
I am excited for the future of rust, but I am worried about where the language is today. It is simply a young, unstable language. There are lots of features you need the nightly compiler for, and there are large breaking changes with every edition every few years.
This is fine for many use cases, but not for the Linux Kernel IMO.
> There are lots of features you need the nightly compiler for
inaccurate
There are lots of features that are currently nightly-only. you may or may not need these depending on what you are doing.
In particular kernel development does require quite a few nightly-only features, but there is no reason to think that all of these won't make it into stable rust in due course.
> and there are large breaking changes with every edition every few years
I feel like you agree with me. All these things that the kernel needs from rust will slowly be stabilized over the next few years. The features will land in future editions of rust. Upgrading to those new editions will involve breaking changes.
Yes, but there is no rush to migrate to the new edition - once stabilised the new features will continue to exist in nightly, in the same form as in stable.
And yes, presumably at some stage there will be a migration of the kernel from nightly to stable. There may be breaking changes. This will be a one time thing, and, (based on the current difference between nightly and stable and rate of change) not much more of a hurdle than changing C editions or gcc versions.
Yes, you can stay on an old edition forever and not experience any of the breaking changes. But there are features that the kernel needs that rust does not support yet, such as a fallible allocation API. These features will trickle in over the next few years. In order to use them, all of the kernel's rust code will have to jump versions and deal with the breaking changes.
This happens rarely and is not considered especially burdensome.
Currently it is believed that Rust editions would be handled similarly and be no more burdensome.
The kernel absolutely does not do this "every few years".
Linux was written from day 1 in "ANSI C", which is C89 (Edit - it was actually C89 with GNU extensions. Thanks for the corrections). Only now, after 30 years of development, are they considering moving to C99, which is itself over 20 years old.
This is laughably untrue. If it were so, ClangBuiltLinux project would have been trivial, but it was anything but. Linux was written from day 1 in GCC C, and it still is.
> Linux was written from day 1 in "ANSI C", which is C89.
Actually, Linux was written from day 1 in the GCC dialect of C (that is, "gnu89"), using GCC extensions without worry. Compiling the kernel with clang only became possible after clang implemented nearly all GCC extensions the kernel used.
Sure, but bumping the minimum version of a compiler is a way different thing than taking in a new version of a language. Rust will involve a lot of the later, which is bad for the kernel IMO.
The list of backwards incompatibilities in the 2021 edition was pretty small.
I don't think that there will be a need to migrate language versions all that often, and, based on what I've seen of how Rust handles backwards compatibility, I don't think it will be an especially big leap.
I would normally agree with this, but Rust for Linux project in fact uses lots of unstable Rust features, and unstable Rust features in fact break a lot (as they should). Unstable Rust is in fact more painful than GCC C, so pain of upgrade is a genuine con against Rust. I just think benefit is larger.
Will changes to interfaces in nightly be handled similarly to how internal kernel API changes are handled? - i.e. if your code is in-tree then the mantainers of the Rust integration will update your code to ensure compatibility with the new nightly interface.
You don't need to switch editions, new language feature generally are available in old editions too. For example, generic associated types, which came out two weeks ago, work fine in edition 2015.
Incorrect. Library features like the fallible allocation API are available to all editions, for better or worse - it also means you can't make breaking changes to the standard library ever, not even with a new edition.
New language features may require a new edition, though the vast majority of them don't - here's the list of all the changes in Edition 2021 (a new one is released every 3 years): https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html
At work we don’t use the nightly compiler and never have. It’s quite rare that this bothers us. If you need an unstabilized feature, there is almost always a crate that emulates it.
I find it funny they got it added to Kernel when there is really no good documentation or experience with how the two different memory models will mix together? Maybe I'm missing something obvious.
My understanding is that it might not be entirely settled yet, and is still being discussed. That could explain why there isn't much solid documentation written yet
There's plenty of discussion out there - just not much in the way of nicely formatted documentation. There is a consensus on the way forward, but it remains to be seem how many tricky details can be resolved.
I have used both Rust and C++ professionally (Rust for nearly four years now) and the advantages of Rust over C++ are still absolutely clear. I’m not a Rust fanboy (I think it’s great in some ways and bad in others) but comparing it to the monstrosity that is C++ is simply wrong.
I'm really happy about the inclusion of Rust in the linux kernel. Not because it is Rust but because it shows that we can evolve. And I hope in a thousand years we aren't still stuck on C or Rust but "moved on" to even better things. It would make me quite hypothetically sad if in a thousand years we were still using tools designed by hackers in the infancy of computer science.
>As can be seen, these patches are slowly building the in-kernel Rust code up so that real functionality can be implemented in Rust, but this process has some ground to cover yet. It's not clear whether more Rust code will be proposed for 6.2, or whether this is the full set. The pace of change may seem slow to developers who would like to start doing real work in Rust, but it does have the advantage of moving in steps that can be understood — and reviewed — by the kernel community. The Rust-for-Linux work has been underway for a few years already; getting up to full functionality may well take a while longer yet.
I'm really tired of the cargo culted idea that Rust is a silver bullet and C hasn't evolved since the 1970s. Neither of those things are true.
The vast majority of people spouting opinions on Rust don't even write systems software, and have never even compiled a kernel driver. Linux, systemd, grub are all written in C and continue to have fewer flaws than trivial userland applications that allow for privilege escelation. The kernel core is incredibly high quality C, and time would be better spent working on the actual kernel security model. Dennis Ritchie himself wrote a paper about the deficiencies of the Unix security model which was designed for a trusting and shared computing environment.
But of course updating the API surface isn't as sexy as writing in a new cool programming language.
Cargo culting this notion that Rust is good because it is a security silver bullet is both ignorant AND dangerous because it moves the focal point away from the areas that actually need work to make Linux more secure. It's also completely asinine to assume that poorly written Rust will have fewer flaws than expertly written C that has been vetted for literally decades.
Iterative improvement has ALWAYS been the answer over throw everything away and start fresh. C tooling has gotten better over the decades, the C standard has evolved, and people will continue to successfully write secure and performant applications in C.
Edit:
Also are you upset that people still use hammers in 2022? I guess if we aren't throwing away all of our tools instead of improving on their design we aren't really seeing any *Progress*
> It's also completely asinine to assume that poorly written Rust will have fewer flaws than expertly written C that has been vetted for literally decades.
No one is advocating for writing the kernel in “poorly-written Rust”. This whole post is one giant, obvious straw man.
And as always when this comes up, Rust is currently slated to be used for new development. Even putting aside the safety aspect, Rust has a lot of nice high level language features without too much overhead.
If the code is only battle tested you have a problem. If you did the correct thing and have written the actual tests for each of the lessons learned nothing stops you from porting these over to Rust.
If you don't have the tests you just listed another reason why using a language with better safety guarantees that will not let broken things compile is a good idea.
The way I see it even battle tested old code can become a liability, if it's surrounding and dependencies change.
It's often impractical to fully test every single aspect of all code. An example that I've seen several times is bottlenecks in unexpected places. Once was due to false sharing, another due to worse standard library QoI.
There’s some merit to “replacing battle tested code with new code”, but (1) a straight port can significantly mitigate these risks and (2) the parent explicitly compared “poorly-written Rust” with “expertly-written C”, so I think your steelman is far too charitable (I’m all for charitable interpretation but the charitable interpretation must bear some semblance to the original).
I think the only thing I can say wrt poorly/expertly written is I haven't met very many people capable of writing top-quality Rust (most are "I've used it for a side project or two"), whereas my professional network is filled with C experts.
I expect this is due to the types of jobs I work, but the point stands: if we were to try to replace C with Rust we would likely get at most "journeyman" quality.
Even if the average C developer is more expert than the average Rust developer, I don't think the kernel will be developed by an average developer of either language.
> The vast majority of people spouting opinions on Rust don't even write systems software, and have never even compiled a kernel driver.
I have done this. I don't anymore, but my entry into the software world was exploitation of C code and I was particularly interested in the Linux kernel. I'm not really an expert on it, but I've certainly worked with many. Here's an example of some of the work my company has done, which I was not the main driver for but was involved [0]. You'll note the zero days and n days in the Linux kernel. I really don't think compiling a kernel driver is very hard, uncommon, or relevant experience here.
We also attacked Firecracker, a Rust project, and I'd say I'm quite experienced in the language.
> Linux, systemd, grub are all written in C and continue to have fewer flaws
If by "Linux" you mean the Linux kernel, absolutely not, and I can't imagine anyone informed would say that. Linux has tons of bugs all the time.
> The kernel core is incredibly high quality C, and time would be better spent working on the actual kernel security model
A few things:
1. This isn't a zero sum game. Some people are working on making existing kernel code safer, some people are working on Rust, some people are working on new approaches to access control.
2. If an attacker can exploit the kernel your security model doesn't matter, they'll bypass the thing enforcing it.
3. Rewriting the entire kernel's privilege concept is a sort of hilarious ask since it's completely counterproductive (there are tons of powerful access mechanisms in the kernel already) and would be extremely costly.
> It's also completely asinine to assume that poorly written Rust will have fewer flaws than expertly written C that has been vetted for literally decades.
lol sorry, this just really gets me. The Linux kernel is not expertly written C, nor is it being vetted for decades. That's just... so wrong. The kernel codebase is riddled with flaws that are often exploitable. You're just... so so wrong on this.
Further, auditing Rust code for memory safety errors is trivial compared to C. As we showed in our post on Firecracker we could basically just "grep forunsafe" and then manually trace the code from that point.
> Iterative improvement has ALWAYS been the answer over throw everything away and start fresh.
No one is throwing anything away, you obviously are very confused about what Rust in the kernel means.
> and people will continue to successfully write secure and performant applications in C.
At first glance, this is a hilarious statement, but it ultimately makes me sad that developers are so ignorant about computer security that they'd feel ok saying something so obviously wrong to anyone who knows wtf they're talking about.
> Also are you upset that people still use hammers in 2022? I guess if we aren't throwing away all of our tools instead of improving on their design we aren't really seeing any Progress
Nobody is claiming Rust is a silver bullet, least of all Rust itself which is quite explicit about this.
What it does, however, is assure that an unsafe-free program will not contain any of a certain class of bugs, including invalid memory accesses or data races.
At the same time, it is an objective fact that a huge proportion of serious exploits and vulnerabilities are caused by exactly this kinds of bugs, no matter how much people like you go "just write correct code bro". Formal verification is the way forward and Rust is an excellent first step.
As a bonus, even if you wrapped your whole program in `unsafe`, Rust is a miles better systems programming language than C, in terms of features (imho of course).
> Linux, systemd, grub are all written in C and continue to have fewer flaws than trivial userland applications that allow for privilege escelation.
Obviously you have never experienced or oversaw what goes in the linux kernel mailing list.
Yes, for the average user Linux is rock solid, but behind the curtains lies the countless sweats of kernel contribuitors fighting the bugs, regressions, memory leaks and crashes.
As someone who does SMD work on hardware using microscopes I would not be able to fix these PCBs (or that analogy) using a hammer.
This is like saying "Uhh mountains are unsafe, I don't get why they put up a handrail at that crowded vantage point over there".
Whether a tool/safety mesure is appropriate is always is about context. I have literally met zero people who work on security or safety critical (e.g. embedded, networking, ...) C code who do not welcome the guarantees Rust brings. It is a complete no-brainer. The ones that complain are the I am a genius who never makes mistakes"-crowd. So precisely the people you should never* let anywhere near anything safety critical.
I write C and I delved into Rust and I can tell you that I trust a vomitted out piece of Rust I wrote more than a piece of C I carefully vetted — and there are rational resons for that. The things that can go wrong at any given point in a C code are more, the ways they can go undetected are more and so on.
Anybody who claims otherwise has not put in the legwork themselves.
Rust is incredibly rigid and stringent by default and if something compiles you can be sure that it now just needs it's logic tested (which is a joy to do in that language).
I dabble in Rust, no genuine dislike of the language but the awkward syntax is what keeps me writing modern C++ as a middle-ground between the scary badlands of archaic C and the triple wrapped rigid Rustlands.
Though, as you mention, if required I will gladly write it if the situation warrants such a tool. Any suggestions for idiomatic testing?
> Also are you upset that people still use hammers in 2022? I guess if we aren't throwing away all of our tools instead of improving on their design we aren't really seeing any Progress
Have you seen the hammers available in 2022? Not shitty $10 at the DIY store hammers, the kind professionals use? They're making hammers out of Titanium. They're engineering the hammers to produce the best trade offs between striking force and rebound, to deliver a tool that's more effective but hurts less to use for a full day's work.
People have continued to fail to write secure and performant applications in C at an unacceptable rate.
Furthurmore, in 2022 large scale professionals (and in this allegory, kernel devs are that kind) are more likely to use industrial hammers which have nothing in common with the hammers of the 18th century apart from the name and their basic function of hammering.
What does the relatively slow pace of Rust integration mean for the Apple Silicon GPU driver, which appears to be largely functional at this point but is written in Rust? Will the developers have to maintain a separate kernel branch with more robust Rust support for an extended period?
I don't think pace is slow. I am actually surprised how fast it is going. Code review is a good practice, and I think Rust patches are being reviewed nearly as fast as possible.
Hopefully not before they've sorted out the architecture support. It's fine to write drivers that only target one platform in a compiler that only targets that platform, but core systems need to be able to run on all the CPU architectures that Linux supports, which I understand is still a superset of the ones that rust supports.
I am growing closer to being convinced that Rust is here to stay and will actually become the main systems programming language of the next few decades.
I think there's a couple of compatible perspectives that are both correct but often framed as mutually exclusive:
1. Rust will become the main language for new projects
2. There will still be an enormous amount of C that will be maintained for many decades and the majority of "lines of (systems) code" will be C rather than Rust for decades
This is a good development and shows that there is appetite to move on to new, safer languages.
What would be even better, IMHO, would be to bring full software fault isolation (SFI) into the kernel and move to a model where many kernel services are implemented as Wasm modules.
The kernel internally makes no promises about ABI even in C, why would that change for Rust?
For userspace, Rust doesn't export anything new to userspace. The kernel APIs remain as they were, and Linus has the same view as ever about whether it's OK to break userspace.
> The kernel internally makes no promises about ABI even in C
There might be two different definitions of “ABI” in this thread.
The kernel indeed makes no promises regarding e.g. the order in which structure members are declared or the stability of that order from version to version.
It probably can be said, though, to promise (through its interaction with the C compiler) that if you take a structure declaration as it appears in the source code, then in a normally-compiled kernel that structure will be laid out in a manner that’s predictable and most probably even described in a human-readable document. Those rules usually have not changed for decades (even if I sometimes wish they were different).
As far as I know, unless you ask for that specifically, the Rust compiler does not promise any of that, the only documentation for what it will do by default is the source code, and it is free to change the rules from version to version with no notice.
I mean how do they plan to interop between C and Rust code. Either in the same library or across shared libraries (if written in Rust, what does it export on the API surface such that C code can call into it)?
It's all a balance. Rust is simpler than C++, and the complexity it adds relative to C pays for itself pretty significantly in correctness (C++ is more complex and provides fewer/weaker correctness guarantees). Moreover, there aren't many systems languages to choose from--at least not many that are not super-niche. Even Ada is pretty niche with little mindshare/enthusiasm.
I think there is a question of "Wait till when?" Its not like these kind of languages pop up all the time, let alone get adoption. Rust checks most of the important boxes, and the few it doesn't do well they are working on.
Unless rust can link to its stdlib dynamically by default, its size is the biggest problem for any mid-range embedded boards(there are lots of them) due to the static link with rust's stdlib. Nowadays a few simple rust binaries will be close to 50MB when there are only 16MB or 64MB storage(if using c/c++, 1MB will suffice, rust is 40x larger). writing a busybox-like all-in-one rust binary could be a workaround but it is hard to do in practice.
Are you talking about binaries compiled for bare-metal embedded? In such cases you usually simply do not have `std`. And how do you think dynamic linking would help here? If anything, it will make total size bigger since compiler will not be able to perform dead code elimination.
When people talk about big Rust binaries they often forget to strip debug information. Doing it can easily shed half of the binary size. And there are other relatively well known ways of reducing binary size (such as strategically using dynamic dispatch instead of monomorphization, using abort for panics, compiling with opt-level=z/s, etc.).
If you are building for an embedded board, you don't need to follow the defaults; you can enable the flag to dynamically link to Rust's standard library, and the main disadvantage of doing so (that Rust's standard library doesn't have yet a stable ABI) is not an issue when you're always rebuilding everything.
Even with stdlib, the concept is the same: if you want small binaries, you have to work on it, you don't just get the smallest ones out of the box. Seems like sibling commentors have already explained the biggest tips so I'll just leave it at that.
While you may be talking about larger boards, the fact that Rust code can fit into even smaller ones means Rust isn't the issue here.
You typically use build-std and possibly abort on panics or immediate-abort to disable the string formatting code in stdlib, and you do fat LTO. after stripping the binary, it’s pretty damn small.
If you want even further savings on std, you can use an utility that LZMA compresses the different ELF sections of your binary and unpacks them to memory at runtime. That’s language agnostic though…
Regarding multiple rust binaries each bundling a copy of stdlib and inflating the space, this approach would only link the bits of the stdlib each binary uses, but still it’s not ideal. Three approaches I can think of are:
1. Use a file system that compresses its contents like btrfs or zfs or their embedded variant. It should reduce the redundancies.
2. Go the busybox way, as you said. This requires work but it’s definitely doable.
3. Link stdlib dynamically. There is a way, I believe. Rust maintains a “stable” ABI as long as you use the same rustc version if I’m not mistaken.
4. This is ridiculous, so I don’t even count this as a way, but what if you just stored the .a static libs and did the linking on demand into a temporary file that would then be executed?
I personally have never encountered 50MiB optimized stripped and LT optimized rust binaries, only ‘materialized’ which was like 138MiB but it contained debug symbols, no LTO and is quite a large database application.
You will, when in 5 years some proprietary Rust kernel module compiled with the IBM Rustbelt Rust compiler does not work together with other Rust kernel modules compiled with the standard Rust compiler.
Hm... I could screenshot a single character and say: "I chose this character because if it's removed, the no one can log into twitter, and the whole system stops working.
Or maybe I'd show a line of code that initiates advertiser charges, and say: "without this line of code we'd just be giving away as space, and we would lose most our revenue!
But actually, I'd probably try to find a fiendishly complex snarl of logic (yeah, I sometimes do those, on my bad days) to befuddle the poor fella with.
Why would the first non-c language allowed in the kernel be a language that doesn’t even have a standard? Also we’re bringing NPM style supply chain problems to the kernel now? And this is done in the name of security? It’s not the language itself I don’t like, I would like rust a lot more if it had a standard and didn’t have a supply chain (aptly named cargo) problem. It’s pretty obvious to me that software took a nosedive when finding a package became considered a good way write high quality software.
reply