I'm opposed to this, and it's not because of some idiologic kernel-should-be-pure-c thing. I'm opposed to it because the rust compiler is slow. And the rust compiler is written in rust. Compiling rust is a nightmare if you don't have a high-end PC.
I want to be able to actually compile my software if I wish so. This is becoming increasingly difficult. Rust is adding to the problem.
I'm not a fan of rust either, not by a long mile. But current kernel approach to memory safety is a complete, utter, demonstrated failure. Look at last week's CVE-2022-41674:
This is a catastrophic bug, that (after some work on developing an actual RCE) lets anybody within wifi range to get root on your laptop (or phone, or access point). And all it took is this one line:
We've all been repeating the "1000 eyes - all bugs are shallow" mantra for far too long. This one was in the mainline for more than 3 years, and nobody noticed. How many more are lurking there?
Separately I feel "with enough eyes, all bugs are shallow" fails to apply in codebases with many users but most of whom consume it as a black box without looking inside. Some issues making it harder for me to read the code I use:
- The Linux kernel and issuance .so files lack a "view source" button on compiled binaries. And even checking out the matching source, building a replacement binary, and diffing your local changes from the matching source is an arduous progress to setup per program/library from a tarball/Git tag, wait for the computer to finish, install dependency .so files globally, ensure symbols are present, ensure you can breakpoint static functions...
- Dynamic dispatch and generic code might help maintainers and code extensibility but (in my experience) definitely impede external eyeballs from understanding code.
Rust doesn't directly solve overflow errors. What Rust does do is turn them into logic errors, rather than memory issues. To break it down:
* Overflow with the default operators is not UB in Rust, it will either panic or two's compliment wrap, depending on various things (including things you can set to choose this global behavior). This already prevents various issues.
* You can also explicitly choose to do various operations with whatever overflow semantics you want, as you mention with saturated_add and friends.
* Because indexing is bounds checked, where in some languages an overflowed integer would lead to incorrect indexing and therefore possible memory problems, you'll either get a panic or a logic bug, not a memory bug.
* If your integer isn't being used for indexing, you'll end up with some sort of error, but again, at worst a logical error, not a memory error.
is this really that bad of a bug though? i need to be using that driver, and someone near me has to be actively knowing and trying to inject... and it's a DoS ? i'm sincerely asking btw
Driver in question is cfg80211. Majority of popular wireless cards use it.
DoS is the only publicly known exploit, right now. There is understanding that RCE is possible with additional specialist work.
Local packet injection is an implementation detail of the first public PoC. There are other implementations of the same exploit, that deliver packets over the air instead. Including one that runs on ESP32, and attacks unmodified Linux nearby:
> and someone near me has to be actively knowing and trying to inject
Just leave a small board, a battery, and a solar panel on a roof or tree near your office. If RCE is possible with this (people think it is), this would be very valuable.
On a tree near my office, you'd gain access to our network, Microsoft's and a European central bank. Not bad at all.
How would Rust fix this? Here's a Rust program that overflows a u8, with no compile error or warning. https://godbolt.org/z/ME3e9KeMe
You can turn on runtime overflow checking with the Rust compiler, but you can do that with gcc compiling C too.
I guess the answer is that you wouldn't do the memcpy like that in idiomatic Rust - you'd use some higher level construct that gives the compiler more chance to catch your errors. Could anyone comment on how this works in a case like this?
edit: Can't reply to repliers. Defined overflow doesn't help here. A checked_add() function could be used in the Linux kernel in C, just as easily as in Rust. Forcing checked_add() to be used in the Rust compiler would help, but would also have performance and readability impact, which is presumably why it is still being debated.
> How would Rust fix this? [...] I guess the answer is that you wouldn't do the memcpy like that in idiomatic Rust - you'd use some higher level construct that gives the compiler more chance to catch your errors.
Yes, that's the trick: it will be caught not in the u8 overflow, but either in the memcpy equivalent (which is "dst.copy_from_slice(src)"), or in the slice manipulation before it. What happens is that slices in Rust are represented by a "fat pointer", a pair of the starting address and the length, and both the "copy_from_slice" method and the index/index_mut operator check the bounds before doing the operation.
(You could do things using "unsafe" and raw pointers, which have only the starting address without the length, but in idiomatic Rust you'd use slices most of the time.)
In C when you use an inappropriate type (such as u8 here for a size) it's just coerced. In Rust the wrong type doesn't compile. So, I think the programmer is less likely to choose u8 in the first place.
The C language says the unsigned integers wrap. That is, C's 8-bit unsigned integer (e.g. uint8_t or in Linux source u8) behaves the same as Rust's Wrapping<u8> type.
In Rust the u8 type wraps in default release builds, but panics on overflow in debug builds, but this is kernel code so it will definitely be built in release mode with wrapping.
That is because you're using a normal add instead of `checked_add`. There are discussions about forcing the compiler to only allow `checked_x` and `wrapping_x` operations for any mathematical operation within your code.
I'm not sure it's realistic to expect a safety focused compiler to compete with one that doesn't offer those checks.
We should aspire to make it as fast but in the short term a slower compiler in exchange for less CVEs and random buffer overrun crashes seems like a reasonable trade off to me.
Distributions such as Fedora offer build infrastructure[1] that you can use to compile packages to use in your system for testing if you feel your local hardware isn't powerful enough.
Actually C/C++ compilers are shooting themselves in the foot performance-wise with the header mechanism, so writing a compiler that's faster than C/C++ is not that hard. Not sure what the reasons of the Rust compiler being (even more?) slow are, maybe the ability to easily interface with C code has something to do with it?
Last time I checked [1], the Rust part of the Rust compiler is not the slowest. LLVM spends a lot of time processing relatively poor IR code which the Rust compiler emits.
Rust compilation is not intrinsically slow; better IR and more incremental compilation can and will improve it. Incremental compilation (only changed files, not crates) is 7 years in making though.
Thanks for that link! That sounds like the really major factor is the decision to recompile the entire crate when a file in the crate changes. I'm sure that made sense at the time ;) And, if slow compilation is such a pain point, I wonder why it takes seven years and counting to fix this bad decision - incremental compilation might have its edge cases and pitfalls, but other compilers are doing it just fine, so it shouldn't be rocket science?
Other reasons:
- suboptimal LLVM IR code, as you mentioned, and other tech debt
- the preferred strategy of monomorphising generics is fast at runtime, but slow to compile, using trait objects is faster
- the complex type system of course also plays a part
> if slow compilation is such a pain point, I wonder why it takes seven years and counting to fix this bad decision
I'm not sure it was a "bad decision" if it was something that can be addressed after the fact and allowed them to ship working software more quickly.
The vast majority of the popular projects I am aware of have this kind of technical debt, likely due to survivorship bias. Project teams that refuse to take on technical debt are rarely successful enough to become popular.
> if slow compilation is such a pain point, I wonder why it takes seven years and counting to fix this bad decision
Maybe we are giving Rust developers computers that are too fast. ;-)
OTOH, it's always wise to design for the future, so it also makes sense to give Rust developers beefy server grade hardware so they can play with SIMD pipelines and all those extra cores and threads, because that's what workstations will be a couple years from now.
In this case I really have to nitpick about the use of "C/C++": This specific problem really only exists in C++, because there it is common to put implementation code into headers via inline and template functions (worst example is the C++ stdlib), while in C you only put declarations into headers, and just parsing a few hundred lines of struct and function declarations won't blow up your build times (while just including a common C++ stdlib header like <vector> pulls in tens of thousands of lines of tricky template code.
There are languages with similar type safety, which are faster, because the authors have placed focus on having several ways available to compile the code.
I will admit I never understood why Ada never took off (is it only because of the tooling being propertiary for a long time?), but c# is not as memory safe as rust.
The only memory safety that C# lacks in comparisaion with Rust is one special case, data races for in-process data.
For everything else regarding concurrent access to shared data out of process, they are on the same foot.
Ada didn't took off, because of several reasons, price of compilers, on UNIX it was an additional SKU on top of the respective developers SDK that already offered C and C++ in the box, 1980's mainstream hardware wasn't able to cope with it, most OS vendors outside UNIX decide to migrate from their toolchains into C and C++, so again additional money on top of the OS SDK.
>> I will admit I never understood why Ada never took off (is it only because of the tooling being propertiary for a long time?)
Early Ada compilers had expensive licensing and required expensive hardware to run.
By the time GNAT was added to GCC, C++ had already taken over most of the spaces that were not Ada exclusive (meaning safety critical / defense / aerospace niches where either Ada was once mandated or has thrived in despite the original high costs).
It does have GC but that is not the point being made.
I believe the point the author is making is that other languages provide better safety than C and have faster compile times than Rust, therefore Rust should be able to improve its compile times.
If those languages achieve their memory safety at runtime, like C# does with GC, then that becomes relevant to the point of the compile time performance. The C# compiler has to do less as that complexity has been pushed elsewhere with different tradeoffs.
GC is not a roadblock for OS kernel work. Smalltalk is itself an OS and had GC from the start. IBM's i (the descendant of OS/400) most likely has GC as part of its kernel. Lisp machines had hardware-assisted GC.
What you may want to try to avoid is complex and non-deterministic GC, which makes it harder to reason about.
It is certainly a religion, as most people that advocate against it hardly ever learned to use a profiler, or bothered to learn that not all GC languages are alike, and many of them offer the same capabilities like C and C++ for low level coding.
It's not, collaborating on a C# game engine and what I've seen is basically a lot of skirting around GC, because it's impact shows up in profiler. It has gotten to a point arrays and stack alloc are prefered over List and HashSet were basically forbidden in the hottest path.
Except most of C# ecosystem relies on classes and GC. A lot of these problems are caused by overuse of GC-ed classes, and their ease of use.
My take on this is a little different than the comments previous. I tend to side with your position over the default position the GC is workable as a languages base assumption. I think the problem really is an expressiveness issue. In a language conceptualized to have memory managed either manually or GC’d and that said choice should be easily made (i.e. it should not take much work to designate some code path as utilizing a GC’d strategy), but I would say for implementation and performance you would give up being able to easily abstract over the memory strategy.
tr;dl — I’d really prefer the option to determine when I’d like GC, as opposed to dodging the collector to avoid performance hits, hot code can default to manual. Probably not a realistic ask, but it could work.
> I’d really prefer the option to determine when I’d like GC, as opposed to dodging the collector to avoid performance hits
Fair enough. If SS14 used D maybe they wouldn't have these problems.
D and early Rust (pre 0.2, like alpha alpha) had that. Problem is you split your community in two. You get a version of "What GC-color is your function/lib?".
It's a tradeoff for some domains - allow no GC bypass you're going to run into nigh insurmountable performance cliff.
Allow GC as opt-in and you run into issue of splitting your APIs in two.
> "This would be a lot easier if we didn't have malloc()/free()", basically.
Well, not really. It's just some libraries like YamlDotNet copy waaaay more than needed and it shows in serialization. They mostly minimized calling YamlDotNet, but true solution would be a zero copy parser.
Other issue was HashSet operation like Clear had huge impact.
Think they replaced those with arrays.
Third issue was something about flecs and archetype ECS. I don't know if it was a jest, but they mentioned changing GC layout or rewriting GC.
Points is, they now face a steep performance cliff. The only way out of it is through sheer effort.
So no, it's not anti-GC religion. Some domains and GC really badly mix.
I've seen some Rust programs that look nice, but in the kernel, the code ends up making perl'ls propensity for line noise look competitive. I'm sure some of that is the need to shovel between languages, but it does make you wonder if the entire effort is a little misguided.
A full Rust kernel might be neat. A compromised Rust driver inside of a C kernel is never going to be the default choice.
Most of the code committed to the kernel is infrastructure for C<->Rust interoperability. It's the least readable of it all, and as fun to work on as watching paint dry.
As others have pointed out most of the performance hit is in the optimization of the relatively verbose IR code the Rust compiler sends to LLVM, not the Rust compiler itself.
There's been multiple passes at making the Rust compiler faster. It'll happen. There's a GCC-based Rust implementation in the works too.
> No, Nim doesn't have stronger or weaker safety guarantees than Rust [1]. Rust's memory safety is nothing new, either. It is mostly that some older languages like C/C++ are the exceptions in not being memory-safe. There is nothing new or magical about memory safety. LISP was already memory-safe when it was invented in 1958. The only question is how much performance you need to trade away for it (the value is never zero for non-trivial programs, but can vary greatly, depending on whether the language was designed with it in mind or not).
> The main difference between Rust and other languages is that it does some more (but not all [2]) safety checks at compile time rather than at runtime. It also allows you to avoid GC, but does not provide you any memory safety over GC. Rust's borrow checker allows you to statically prove that references are live [3]; a GC simply avoids deallocating any memory that has a live reference to it (on the other hand, a GC can ensure that references remain live even where this is hard or impossible to prove statically). The end result is the same with respect to memory safety (the reason some people want to avoid GC is for performance reasons, not memory safety).
While it's true that memory safety has been done in a lot of languages for a long time this overstates the point. Doing memory safety at compile time is an important change that allows replacing C/C++ in a lot more situations. In the benchmarks game for example Rust has been the only language capable of breaking into the C/C++ league, even after very many years of investment into Java for example.
Rust also uses the same mechanisms to get compile time thread safety with full memory sharing between threads. Does any other language that doesn't have a global lock, throwing away most of the advantage, have that? There are actual new and interesting advantages to the compile time ownership model.
Benchmarks vary wildly but Haskell tends to perform in the same realm as C++, fwiw. It's GC'd, uses immutable data structures, and uses a green threading model that can be easily exploited by user code for extreme levels of parallelism with full memory safety. It's even possible to hold mutable references and share them across threads safely with STM (not a global lock).
If you want fully lock-free it might be possible to prove that with extensions like Liquid Haskell, via Linear types, and is definitely easier to prove with a theorem prover than it is, generally, for C++ code. Not sure about Rust though I realize quite a lot of its moving parts have already been formalized which is super cool.
There are reasons for using Rust but it's not the only game in town. And GC doesn't automatically mean pessimistic performance.
That's outdated information from 2016. Now Nim uses ARC/ORC. ARC implements memory management at compile time like Rust and it's still very fast at compiling.
> The main difference between ARC and Nim GCs is that ARC is fully deterministic - the compiler automatically injects destructors when it deems that some variable (a string, sequence, reference, or something else) is no longer needed. In this sense, it’s similar to C++ with its destructors (RAII). To illustrate, we can use Nim’s expandArc introspection (will be available in Nim 1.4).
> This shows one of the main ARC features: scope-based memory management. A scope is a separate region of code in the program. Scope-based MM means that the compiler will automatically insert destructor calls for any variables which need a destructor after the scope ends. Many Nim constructs introduce new scopes: procs, funcs, converters, methods, block statements and expressions, for and while loops, etc.
> ARC also has so-called hooks - special procedures that can be defined for types to override the default compiler behaviour when destroying/moving/copying the variable. These are particularly useful when you want to make custom semantics for your types, deal with low-level operations involving pointers, or do FFI.
--gc:arc/--mm:arc has been around for a couple years (as per that blog post link) and fairly stable for >1 year. It is slated to become the default automatic memory management strategy in Nim-2.0. The hope is to release 2.0 this year.
You can always make it your own personal default with older versions (e.g. nim-1.6), by editing your $HOME/.config/nim/nim.cfg to say so or doing similar on per project/file basis.
- the Linux project is very likely to stick to simple, fast elements of Rust (based on the excellent approach of the Linux/Rust devs thus far)
- the more Rust is used, the more work will be done to improve its performance
- you can still build a kernel on a low-powered device... i've built kernels that took > 12 hours on, for example, PA-RISC boxes that were once regarded as beefy :-)
- most people don't (and shouldn't) compile their kernel, and by most I mean more than 99%
Could you expand on why people shouldn't compile their kernel?
I think it's fairly useful to compile their own to get a better understanding of what the kernel does and to better suit everyone's needs. For example, if I have little free space on my boot partition and I have my disk encrypted, I want my kernel to be as small as possibile, so I will deselect every driver I don't need. Or maybe the driver for my new device is not included in the kernel builds of my distribution.
Not only I woundn't say that most people shouldn't compile their kernel, I would say that most linux users* should do it at least once, so they can understand the power they have compared to closed-source operaring systems.
*with linux users I mean users that use linux as their main operating system, not people that do ssh once in a while or rarely boots their linux partition
- everyone has better things to do than compile software they didn't write
- a good distro has probably tested it on a bunch of hardware, and hopefully signed it (or at least the packaging), so you know it was securely acquired and built
- you won't learn much at all about the Linux kernel by compiling it... you may learn a tiny introductory about about it by configuring it, but that's still not very much at all, really (it may seem like a lot when you don't know how to measure what you're learning)
- what you should learn from configuring and compiling a Linux kernel is that you don't ever want to be in a situation where you have to do it again (without a really spectacular reason, or being paid)
- if you're compiling a kernel because your boot partition is small... make it bigger, or don't have one at all. come on.
using the same binaries shares the verification for said binary.
a modular kernel with a custom inird (generated by the distro) is small enough for most.
so if you are into adventures or you are in the business of kernel development yes roll your own. anybody else is better served standing on the shoulders of a maintained binary distribution.
I used to work on the Rust compiler itself on a Chromebook with a 1.1GHz dual core, 4G RAM and 32G of disk. That's about as far from a high-end PC you can get. Most mid-range phones nowadays have more processing power and memory than that. And the Rust compiler has been sped up considerably since then. Even with a 4 year old mid-tier PC you can get a complete Rust compile in half an hour. Roughly half of that is building LLVM.
So you can of course compile your Rust compiler. If you are used to compile clang or gcc, it's not that much of a hassle. And the benefits have already been shown. If you only want to compile Rust code, and not develop it, mrustc might also be a good choice for you (it doesn't implement borrowck, just what's needed for codegen).
Finally, if you don't want to use Rust drivers, you can simply configure them out and don't need to build Rust. It'll be quite a long while until Rust will arrive in the kernel outside of drivers (which tend to benefit most from Rust anyway).
BTW, people assume it's slow because of the safety checks, but that's not the case. `cargo check` runs just the checks, and is pretty fast.
Majority of the time is spent in LLVM, because rustc throws a ton of code at it to clean up. This is being addressed by MIR optimizations (rustc's built-in optimizer working on higher-level code) to remove costly abstractions before they become a pile of low-level code to eliminate.
I remember the times when installing Gentoo was a matter of days. Compiling the kernel was a matter of hours. Sure, rustc is slower than gcc, but if you're not constantly compiling your software over and over and over again, then the time spent in the compiler is not your primary concern. Start the compile, go to bed, let it run.
Ha! I was a wimp and did a "stage 3" install back in the day. Or was it stage 2? (shrug). Now I'm even wimpier and just use Fedora.
Came across this page, on the motivations of Gentoo, a few years later:
> Installing a working Linux box used to require over 550 man hours, learning a Nordic language, sacrificing a goat, wading through hundreds of pages of (purposely) inscrutable help files...Old-school Linux users were desperate to find a new way to feel superior.
It honestly wasn't bad at all. Daniel Robbins documentation for Gentoo is still one of the best doc I've ever read and I'm sure he inspired many others. IMO It's actually the greatest thing about Gentoo (along with Portage).
Running Gentoo on 9900KS and 980 Pro SSD with 64GB of memory, kernel compiles in about 8 minutes, the longest project to build I've seen is Chromium and QT Web Engine at ~120m. It's OK but I'm tempted by the new Ryzen CPUs.
I remember spending days to compile KDE fbsd port on Pentium 4, nobody sane should be running Gentoo or any from source rolling release OS on sub-optimal hardware.
Celeron was about the affordable option when Gentoo was released. It was just that: compiling things took time. But even when you ran redhat or suse, you sometimes needed to recompile the kernel to support the features you needed. And that took hours. But it was never a major impediment to using Linux. It was a one-time cost, like a windows install (that also took hours), or a windows update.
It's a fair remark, but your requirement is very niche. There's very few people who will value compilation time over runtime speed, safety, good abstractions, expressiveness.
This ethos played out in the C++ community 5-ish years ago. It turned into a compiler with quadratic behavior, and eventually many people who didn't care at all about compiler performance cared a lot.
It turns out that compiler speed makes development faster, keeps people interested in the language, and ultimately allows more iterations before release (which can be better for speed and safety than throwing in a bunch of extra compile steps).
You misread my comment. I didn't say it was useless, I said there are things with higher priority. And well… unlike Rust, C++ sucked at some of those things too, this I think makes them different.
Rust offers a better trade-off between compilation time and other parameters, than C++.
They didn't say it was useless either; they also said it wasn't a high priority. Developer velocity and ergonomics should always be a high priority for compiler writers.
"High" as in "higher than runtime speed, safety, abstractions, plugin system"? Where would you put it if you had to rank compilation speed with other criteria?
And let's admit even though Rust compilation speed could use some improvement, it's not terrible.
Rust could have been designed for faster compilation without sacrificing runtime speed, safety, good abstractions, expressiveness and whatnot in any regard. The people designing Rust just either did not care or did not have the experience to do so. And it can not be fixed anymore because that would require too much breaking changes.
And yes, a substantial time is also spent for things like the borrow checker but no all of it.
An no, it is not a niche requirement. Short compile times are absolutely critical for developer productivity. One main reason Golang exists and got popular is that people got fed up with how slow C++ is to compile. Not to mention that most people on this earth are not as privileged as to have a beefy machine.
> Rust could have been designed for faster compilation without sacrificing runtime speed, safety, good abstractions, expressiveness
Can you back this up? I'm not a programming language expert, so if there's some common knowledge you're referring to, I'm not aware of it.
> most people on this earth are not as privileged
There's very little "privilege" you need to compile Rust. In my spare time, I develop mainly in Haskell on my ThinkPad X270 and it goes just fine. Building libraries takes time, yes, but you need to do it just once. And while it's building you can think with a piece of paper more — also privilege in a way.
> I'm opposed to this. I want to be able to actually compile my software if I wish so.
So what you're saying is that you're opposed to millions of people having more secure software, and perhaps millions of dollars spared from breaches, because it makes your own occasional singular personal experience of compiling the software faster?
I mean, slow compile times affect everyone who compiles the kernel. And being able to compile things yourself (possibly with patches) is one of the key features of open source...
Considering only compile time is a shallow approach to the idea of using Rust more widely. I would encourage you to think about the aggregate amount of time our industry spends finding, and then fixing, and then repairing the damage done by, classes of bugs which idiomatic Rust completely prevents. It does all this without impacting runtime (like GC language often do).
Fast compute at this point is quite literally the least expensive part of the equation. Machines will get faster. Compilers will get optimized.
We've spent decades optimizing the developer experience (compile times) at the expense of the rigor, robustness, and quality of our resulting product. I've been doing this for 30 years, and I can categorically say that I've spent FAR more time chasing NPE, OBO, and race condition bugs than I would have ever added to my build time with a slightly slower compiler.
The idea here would be to compile in a way that just assumes everything is correct and either crashes catastrophically or produces invalid output otherwise. But in doing so, it should allow at least slightly faster compilation.
You could even remove the need for this "fast and loose" compiler to do any type inference by shipping pre-processed source with all types resolved. However I don't know if this addition would fit your needs if, e.g., your goal is to be able to compile from any given commit rather than only official releases.
At very least it could be an interesting experiment to discover what tradeoffs are possible.
While I lack personal experience with Rust and I really appreciate fast compilers (that is why I am a Go user), over all features and characteristics, Rust seems to be the best choice for safe kernel development. Other posters have described well how urgent it is, to improve the security of kernel code. So just not doing anything about this, doesn't seem to be a good option.
It seems, there is a wide group of developers which thinks that Rust is the best candidate as a kernel development language. If you see issues with that choice, now would be the time to propose an alternative and try to find momentum in the developer community supporting that alternative. While I also lack practical experience there, by all what I heard, ADA could be one. But I don't know how it exactly compares to Rust and what the trade offs are. But so far, no one has pushed for ADA as a possible kernel implementation language.
Just as a data point, my desktop is a Xeon e3-1230 v5, which is the same silicon as the i7 from 2015. The CPU cost $250 new, the entire desktop was $1100 or so, not including the monitors.
Then ran the build step "time ./x.py build -j 8"
...
Build completed successfully in 0:36:53
real 36m53.398s
user 254m52.720s
sys 12m48.289s
Seems pretty reasonable considering it's not a particularly high end desktop from 2015. Seems like a cheap price to pay for increased reliability and security.
Absolutely, and my own experience is that it's possible to create a language with Rust's safety guarantees while making it quick to compile.
I know this because I've managed to add a form of RAII and borrow checking to portable C11, and C is known for being faster than Rust to compile. Imagine what happened if we made a language with that stuff built-in.
The funny thing is that C is also slower to compile than it could be because of headers.
Yeah we should probably optimize for the 0.5% niche of people that care. Who needs builtin in memory and thread safety on core server systems so long as I can compile the kernel on my 486. Oh never mind, they are dropping 486 support too soon. Why can't it stay 1996 forever.
Rust compiler does all the Rust’s magic (where the borrow checker is the biggest part). This magic is really important and helpful, and it's better to do it during compilation, not in runtime (for huge performance benefits).
I'm aware. I know how rust works and why people want it.
I haven't checked the times, but if the borrow checker is really the slowest part, maybe making rust skip it is a valid approach for end users. Sounds like an interesting experiment.
There was a PR merged yesterday which should give us 5-10% improvements in compile times [0]. As long as there are people monitoring and working on compile times, one could optimistically hope that as more companies become willing to throw money at Rust, we'll see improvements over time.
Regardless of how fast one's machine is, I think having some compile caching infra like sscache should help improve time to compile.
The borrow checker is only one reason for the slow compile times. Cargo provides a separate `check` command to only do code & typechecking and that can be much faster than full compilation. LLVM and the way rustc interacts with it also plays a role.
In my experience when compilation takes longer the actual delays are in the last steps, long after the compiler is done checking and printing warnings.
On an unrelated note, I also noticed a large amount of static string literals in the code can slow down compilation to a surprising degree.
Why not skip the whole compilation step and just download the precompiled kernel? There is really no point compiling software you didn’t modify and if you did modify it, you want the borrow checker on.
I mean, if the people that write the code don't skip it, I don't see the issue. The code in the source tree is supposed to be safe, so you might as well not do borrow checking and whatever other safety stuff you have.
If you aren't changing the code yourself, then why not download a binary? And if you are changing it, then you probably don't want to turn off the borrow checker.
It is expected to compile rust with a rust written-compiler (rust fanboys will improve it, probably).
Now, I wonder what is the most reasonable option: writting a naive and simple 'c11' compiler or a naive and simple rust compiler.
I wonder if somebody has done a "syntax complexity diff" between 'c11' and rust.
I know that linux is written in "gcc C", not 'c11'... so...
On the other end of the software stack, we have servo, mozilla web engine written in rust. What's up there? Still a drop of rust in a ocean of c++? (SDK included).
Because after years, if it is still impossible to run servo without c++ code, this is bad omens for kernel rust.
Rust as a language to write kernel drivers for <POPULAR ARCHITECTURE> is a great achievement, but what about all the other architectures that only have a C compiler and do not want/can't to depend on LLVM?
What about the billions poured into LLVM that made writing an optimizing Rust compiler possible in reasonable time, that is still written in C++?
Lastly, I hope to be wrong on this, but watching at Google history being backed by them is, unfortunately, a course,
Therefore, for the Linux kernel specifically, I think the only concern is whether or not GCC remains supported in addition to LLVM - as GCC and Clang are, as far as I know, the only two compilers which actually can be used to build the kernel as we speak. There's work being done on both gcc-rs and rustc_codegen_gcc to allow using GCC as a Rust backend, meaning that all platforms currently supported by the Linux kernel should be eventually capable of being supported without porting a compiler backend.
The kernel community has never been particularly interested in the whole free vs open source software debate. The leadership is mostly pragmatic people.
It’s just that Linux used GCC extensions and no one was interested in doing the work necessary to have it compile on a non-GCC compiler.
That's plainly not true as there are plenty of intra-kernel interfaces that are tagged as GPL only and if your kernel module isn't GPL you can't use said interfaces. For example, they added the GPL tag to the floating point context switch functions which broke ZFS at the time.
I don’t understand your comment. The kernel cares about its license which is indeed the GPL, yes.
But Linux didn’t go out of its way to be incompatible with ZFS out of ideology. Sun intentionally picked a license which would not be compatible. That’s why ZFS lives outside of the main tree.
The ideology that’s driving the Linux kernel development: “shared source code leads to better code, user land should never be broken” are very different from the one that led to GCC gimping itself. Generally speaking the kernel community is very technically oriented and doesn’t go out of its way to prevent things for social reasons.
The kernel devs went out of their way to label a whole bunch of kernel functions as GPL only. It's not about mainlining third party kernel modules, it's about not letting non-GPLed modules use certain functions in the kernel. This includes the fully open source OpenZFS project. It's not about CDDL / GPL incompatibilities. For OpenZFS it was some FPU context switching functions that had to be worked around when the kernel team labelled those functions as GPL only.
You seem confused. There is no mysterious GPL only label in the kernel. The whole thing is licensed under the GPL v2 period. It’s just that some ABI were broken for an unrelated reason as Linux doesn’t guaranty ABI stability and OpenZFS can’t find an alternative which satisfy their dependency needs. The kernel team doesn’t care about out of tree code when making changes. It has always been the rule.
Yes, you are right. I didn’t know the API was tagged. My take seems indeed a bit too extreme.
The kernel does care about enforcing the GPL explicitly on some of the interface it presents to modules to ensure the openness of the code which is indeed a form of statement in favour of open code.
I don’t think the situation was the same regarding compiling only with GCC - after all clang is free software - and I think the heart of my argument still hold: the kernel community makes decisions mostly for reason related to the kernel - even there they just want to force code to be mainlined - rather than for the movement like the FSS.
> are you telling me that Alan Cox had no involvement in the Free Software?
I don’t see how your statement contradicts or is even linked to mine.
The kernel community as a whole very much has little interest into the philosophical arguments surrounding open source. Apart from being convinced that sharing code is the best way to develop a kernel they have next to no active involvement in the whole charade.
See for exemple keeping GPL v2, not opposing TIVOisation, disapproving on technical merits but allowing proprietary drivers and binary blobs.
> the GCC extensions were essential to enforce the GCC supremacy because no other non-free compiler could implement them
Linux uses GCC extensions because they are handy and GCC was the compiler everyone used to compile C projects for a long time. It’s not intentionally done to promote GCC on ideological ground, something pretty much no one cares about in the kernel community.
> The kernel community as a whole very much has little interest into the philosophical arguments surrounding open source
because they didn't have to.
someone already established that it was the foundation, people like Linus Torvalds, Alan Cox, Maddog Hall and many (not too many, actually) others.
The "community" for the longest time has been a bunch of people
"is a small and well-defined group: Linus, Maddog Hall, Alan Cox, and somewhere between 6 and 12 others (varying at times)." (Steven Suson, 1999)
"Watch the linux-kernel mailing list. The "Inner Circle" becomes very obvious. People go in and out of the Circle, so a list probably isn't possible [...] I would say it includes may be 2 dozen people." (Eric Princen, 1999)
> It’s not intentionally done to promote GCC on ideological ground, something pretty much no one cares about in the kernel community.
again: you're talking at the present, I am talking about the first two decades
Torvalds was never a free software zealot in the way the FSS views the movement. He seems to believe open code leads to better code but I don’t think he is against the idea of closed source. He has worked on closed source software himself if I’m not mistaken.
> Torvalds was never a free software zealot in the way the FSS views the movement
Who said anything about zealots?
please, stop putting words in someone else's mouth.
Linus was a big supporter of free software and the fact that the Linux kernel was free software is what compelled many developers to donate their work for free
They didn't do it to improve NT Kernel or Solaris kernel or... you know it.
for some at least, and it was a goal in the first two decades of the Linux kernel community
TL;DR: LLVM and Clang allow non-free (proprietary) extensions
The Clang and LLVM developers reach different conclusions from ours
because they do not share our values and goals. They object to the
measures we have taken to defend freedom because they see the
inconvenience of them and do not recognize (or don't care about) the
need for them. I would guess they describe their work as "open
source" and do not talk about freedom. They have been supported by
Apple, the company which hates our freedom so much that its app store
for the ithings _requires_ all apps to be nonfree. (*)
The nonfree compilers that are now based on LLVM prove that I was
right -- that the danger was real. If I had "opened" up GCC code for
use in nonfree combinations, that would not have prevented a defeat;
rather, it would have caused that defeat to occur very soon.
For GCC to be replaced by another technically superior compiler that
defended freedom equally well would cause me some personal regret, but
I would rejoice for the community's advance. The existence of LLVM is
a terrible setback for our community precisely because it is not
copylefted and can be used as the basis for nonfree compilers -- so
that all contribution to LLVM directly helps proprietary software as
much as it helps us.
The cause of the setback is the existence of a non-copylefted compiler
that therefore becomes the base for nonfree compilers. The identity
of that compiler -- whether it be LLVM, GCC, or something else -- is a
secondary detail. To make GCC available for such use would be
throwing in the towel. If that enables GCC to "win", the victory
would be hollow, because it would not be a victory for what really
matters: users' freedom.
Yeah, the fact that only few years ago Linux was finally buildable with Clang.
If you have any proof that there were other reasons besides "nobody was working on that and the Kernel was using GCC extensions not found anywhere else" I'll be willing to look at them
These debates have been going on since the mid 90s, I don't know why people still ask questions about them, it's ancient history, GCC was the de facto compiler for Linux because Linus decided so and everybody else followed.
If there was no other reason than a philosophical one (the technical one is the GCC extensions) you could have built Linux with MSVC in 1997.
Reminder: the first two decades ended 11 (ELEVEN) years ago.
We are in the fourth decade right now.
> and why are you quoting RMS while talking about development of the linux kernel?
Because Stallman was in charge of GCC and the history of GCC and Linux are almost inextricable from 1991 onwards.
> If you have any proof that there were other reasons besides "nobody was working on that and the Kernel was using GCC extensions not found anywhere else" I'll be willing to look at them
I can't cite sources, but AFAIK Linux uses GNU compiler extensions. The reason is not to lock other compilers out, it's just that some of those extensions are genuinely useful.
> I can't cite sources, but AFAIK Linux uses GNU compiler extensions. The reason is not to lock other compilers out, it's just that some of those extensions are genuinely useful.
Of course.
They are genuinely useful to Linux.
Other did not use those extensions because they did not want to use GCC, for reasons beyond the technical merits, but because GCC is free software
For something to be considered a feature, it has to be beneficial to someone. I'm not arguing that the benefit should manifest in convenience. Who benefits from the Linux kernel not being able to be compiled by a certain compiler, and how?
> For something to be considered a feature, it has to be beneficial to someone
It was beneficial to Linux, the open source and free software, as in GPL licensed, kernel.
It was beneficial to its users.
It was beneficial to the free software movement.
It wasn't beneficial to corporations, probably.
Things in fact have changed when corporate sponsored interests raised around Linux as a money maker platform. And when Apple started its war against GPLv3 (suddenly GCC was not good anymore for them) .
> Who benefits from the Linux kernel not being able to be compiled by a certain compiler, and how?
Again: the fact that Linux was not being able to be compiled by a certain compiler doesn't seem to me it hindered its ability to become the most used platform in the server space (or one of the most used).
Any counter proof?
-----
As already stated: beneficial != convenient
Going to the doctor for regular checks is not convenient, but it's beneficial for your health.
And apple "is" vanguard/blackrock, which is msft/google/starbuck!/etc, keep that in mind.
Apple doing open source feels more like PR than anything else (they do "maintain"/"employ the main dev of" cups if I am not mistaken).
And yes, open source is not enough anymore: we need "lean" open source, and that includes the SDK (excluding de facto the ultra-complex c++ and similar).
The real hard part is, once a piece of lean open source is mostly "done", it is to resist planned obsolescence.
That said, I am a "everything in risc-v assembly" (with interpreters of high level languages written in assembly) kind of guy.
Writing an LLVM backend for <LESS POPULAR ARCH> isn't impossible, it just hasn't been done yet. Writing GNU Rust compiler isn't impossible, it just hasn't been done yet. What better way to encourage it than to write more high quality and useful code in the language. Seems like an unfair criticism to levy.
Compilers are just short running tools. They can hog as much memory for the short period during compilation and die away after that. But a kernel is a critical piece of long software that can have CVE. The criticality is not to have the CVE in the first place.
You will never have the data you're asking for. There are a number of papers about language impact on software quality and they all suffer from numerous issues - there are tons of confounding variables; Use two different devs and you can't account for experience, use the same dev and you taint the second project, use two different projects and you can't account for the differences, etc.
The reality is that whatever data you want is pointless. Anyone who knows what they're talking about should be able to very easily conclude that Rust will have fewer memory safety issues than C. Arguing about that would be silly. I think to nearly the same degree that one can draw the conclusion that Rust code will have fewer CVEs than C. Generally speaking, of course. Individual projects can always be outliers.
Obviously you can't compare 20 years of data with "a few papers"
It means you're comparing hard evidence with something that is theoretical.
Imagine this:
"Cancer has been one of the main causes of death for people around the World, but we have these few papers about this new drug that say that it can beat cancer, se we can say for sure that cancer will not be a main cause for death anymore, without even testing the new drug, because I've read it in these papers here, written by people who work at developing this new drug, so obviously we don't need no data!"
If anything, the liks at the studies posted here prove that memory safety issues went down over the years, even without Rust.
Because, obviously, when going fast to develop something, you cut many corners, then, when your software is stable enough, developers can focus on improving it.
95% of the bugs were memory safety issues doesn't really say anything.
If those 95% issues were all edge cases, does it really matters?
If 50% of that 95% was something like "in some cases the interface is rendered slightly incorrectly" does it really matter?
I am much more worried by the 0,1% of them that end up in an arbitrary code execution vulnerability or worse.
> The reality is that whatever data you want is pointless
Then why even bother?
If it's pointless, why are you even arguing with me?
You're right by design, I'm quite sure I am not.
> Anyone who knows what they're talking about should be able to very easily conclude that Rust will have fewer memory safety issues than C
Doesn't mean anything.
If you put people in bunkers alone you'll see a drop in homicide cases.
Doesn't mean it's better.
That's all I'm saying.
I'm not a zealot, not a fan, don't have a political agenda and not trying to convince anybody.
We don't have the data, that's all, if you have data then show it to me or you have to agree with me that we don't have any.
I guess you put Linus Torvalds in the group of people who don't know what they are talking about
Sorry if I trust him more than you.
---
And the *reality* is that there are no absolute guarantees. Ever. The "Rust is safe" is not some kind of absolute guarantee of code safety.
Never has been. Anybody who believes that should probably re-take their kindergarten year, and stop believing in the Easter bunny and Santa Claus.
I... just explained. You can't control for the variables.
> If it's pointless, why are you even arguing with me?
I'm not arguing with you. I made one comment to explain that the data you're asking for doesn't exist and if it can exist it is extremely expensive to generate. Generating expensive data like that to show something obvious is not something most companies care about.
> We don't have the data, that's all, if you have data then show it to me or you have to agree with me that we don't have any.
Yes, I'm saying that there is no good data.
> I guess you put Linus Torvalds in the group of people who don't know what they are talking about
Yes, I think Linus Torvalds is incompetent. That said, I think you're actually misunderstanding his statement there.
I’d like to get involved with contributing to the prossimo project like the blog suggested, however there doesn’t seem to be any more information anywhere on memorysafety.org to do so.
And the reality is that there are no absolute guarantees. Ever. The "Rust is safe" is not some kind of absolute guarantee of code safety. Never has been. Anybody who believes that should probably re-take their kindergarten year, and stop believing in the Easter bunny and Santa Claus.
A bad rewrite from an unsafe to a safe language would mean safety issues traded for logical errors in most cases. Which sounds like a win if you ask me.
So even the "rewrite it in Rust, badly" has a decent ring to it tbh (although I'm not arguing there should be a rush to so).
IMHO the entire Linux kernel should be rewritten as a microkernel in Rust. Another option would be to use the seL4 kernel and salvage parts of Linux to become device drivers and services.
This comment reminded me of Redox (rust microkernel), which I haven’t looked at in a while. It’s an impressive project, but it was funny to see that in their top news post, one of the items is about tracking down memory-corruption/use-after-free bugs:
> “After having thoroughly debugged the orbital/orblogin memory corruption bug with little success, I decided to go as far as phase out the old paging code (ActivePageTable/InactivePageTable/Mapper etc.) in favor of RMM (Redox Memory Manager). Surprisingly, this fixed the bug entirely in the process, and it turns out the issue was simply that parent page tables were not properly unmapped (causing use-after-free), most likely due to the coexistence of RMM and the old paging code, which did not agree on how the number of page table entries were counted.”
This project surely uses rust more thoroughly and idiomatically than the Linux kernel ever will. And yet here we are with memory corruption and use after free bugs. And the text indicates the bug was so hard to track down that they basically gave up and just replaced the old code.
Rust may prove to be beneficial to Linux, but there is too much over-promising hype at this point.
When you write an operating system you eventually will have to go down into the boiler room and write assembly and such. This is most likely where the bugs occur.
Also, you need unsafe() blocks once in a while to interoperate with the extremely low-level assembler parts.
So I'm not in the least surprised there are still memory corruption errors in Redox.
Mind you the bug occurred in the memory paging code and was eventually fixed.
You literally said in another comment that rust is a "magic bullet" that will "put an end" to memory and thread bugs. That is clearly too much hype, when you can turn around and say you're not surprised that a rust microkernel still has memory corruption errors.
Whether it's an unsafe() block, or that in a kernel a logic-bug can also be a memory-corrupting bug (and apparently a use-after-free bug), the fact remains: there's no magic bullet here. Just hopefully an overall improvement. We'll see.
Go ahead, then, and RiiR. (Rewrite it in Rust.) It's not really a novel thought that X thing might be better leveraging Rust's features. The novel thing is actually doing it.
Yep. The wasm don't even have a primitive to access to its own executable. Let alone modification and cause RCE. Bound checking definitely have overheads so you wouldn't expect it to suit all workloads, but for most workload the trade-off would be probably acceptable. And it would probably enable a universal linux driver that runs independent to cpu arch.
The whole point of eBPF is that it's a limited subset of an execution environment that not only provides a memory safe environment, but just as crucially all eBPF programs are guaranteed to terminate.
It's not a general purpose computation environment in a strict sense.
afaik the eBPF vm used by the linux kernel can run programs that never complete, those programs are representable in eBPF bytecode just like they are in WASM bytecode. To prevent running eBPF programs that never terminate the linux kernel runs static analysis over the eBPF bytecode when its loaded, I would think similar analysis could be run over WASM bytecode to ensure it terminates.
You need to realize that
(a) reality trumps fantasy
(b) kernel needs trump any Rust needs
And the reality is that there are no absolute guarantees. Ever. The "Rust is safe" is not some kind of absolute guarantee of code safety. Never has been. Anybody who believes that should probably re-take their kindergarten year, and stop believing in the Easter bunny and Santa Claus.
> The "Rust is safe" is not some kind of absolute guarantee of code safety
Exactly. Some people act like we don't have the whole branch of "formal proofs" in CS. Memory safety is just once aspect of program safety.
Like, IMO, programs written in Coq, F* or even C programs verified by Frama-C are much more "safe" than Rust programs that advertise their "safety" on the mere fact that they are written in Rust.
The reality is that people are adding critical code to the kernel and surrounding infrastructure (OpenSSL) on a Friday night after a long weeks work and never bother to look at it again.
We absolutely need something like Rust to cover our backs!
The idea that Rust can solve this problem is ridiculous to me. The types of bugs that sleep-deprived contributors writing fire-and-forget code will make will just shift to something that the borrow checker doesn't help with.
The parent comment implied that this meant that there would be fewer bugs. That is definitely not what happens.
The factor that actually generates the bugs is the tired person writing code they will never read again or use. The borrow checker won't help with that.
I write code with different types of bugs in C, Go, Rust, Javascript, and Verilog, for example. I rarely write code with no bugs, especially when I have no real connection to the code.
GP comment implied there would be fewer exploitable bugs. That is definitely what happens.
If you think there's the same amount of severe exploit from software written in Go/Java/Javascript and software written in C/C++, you are just factually wrong.
70% of exploitable bugs from large company products (M$, Apple, Google) ARE memory safety bugs.
I do not agree with you, and I think it's a pretty strong claim to make that Rust code has fewer exploitable bugs than other code without evidence. The fact that 70% of "exploitable bugs from large company products" are memory safety bugs does not imply that those products will be any harder to exploit when re-written in Rust, just that they won't have certain types of memory safety bugs - which happen to be 70% of the known exploitable bugs that have emerged.
One big reason why we have so many CVEs for memory safety bugs is that they are very easy to find with analyzers and easy to programmatically test. We currently live in a world where a lot of deployed code has not had the benefit of those analyses, but the attackers do. Hence the huge number of CVEs. Rust closes that asymmetry, which is significant.
It does not mean that we won't move on to a new class of exploitable bugs that show up due to a new class of analyzers.
Also, exploitation means a lot of things to a lot of people. The fact that it's really easy to crash a Rust program could also be considered an exploit (as a number of CVEs do).
Just using Rust does not save you from exploits. Using Rust well makes it easier to be safer.
1. You acknowledge others' reports that 70% of exploitable bugs are rooted in memory safety problems.
2. You acknowledge that Rust helps reduce the number of memory safety bugs.
3. You resist any conclusion that Rust therefore reduces the number of exploitable bugs.
4. The stated reason for such resistance is "but but but they might exist and you might not know about them and something something something about how analyzers have gotten better."
1+2 alone seem like a pretty clear open & shut case to me. Your (4) looks like grasping at straw to me. You complain about "without evidence," but 1+2 looks like pretty compelling evidence to me.
One also has to wonder what kind of evidence would meet your standard. What evidence would convince you? And is that evidence even obtainable?
(1) is wrong. I said that 70% of reported exploitable bugs are rooted in memory safety problems. Not 70% of exploitable bugs. There is a big difference. In other words, I am suggesting that we have found a lot more of the exploitable memory safety bugs than other classes of bugs, which skews the number high, and that there are a tremendous number of latent exploitable bugs that are not related to memory safety that we haven't found out how to find yet (in a systematic way). I am also asserting that the Rust borrow checker likely won't help with those latent bugs.
The evidence that would convince me is ~10 years of a notable reduction in both total CVEs and total monetary value of exploits of that software (or a comparable piece of software). There is almost nothing that would convince me today that Rust is inherently more secure than C or C++ (particularly modern C++), except in the small class of applications that rely solely on memory safety for security and cannot use a garbage collector.
By the way, I do have an application running in production today that fits that requirement, and I wrote it in Rust.
Total CVEs is a poor metric given that we (Rust programmers) tend to file CVEs far more liberally than C or C++ programmers. More to the point, the evidence you claim to require is just that: reported exploitable bugs. Which seems to have the same problems as the evidence that has already been presented to you.
> I am also asserting that the Rust borrow checker likely won't help with those latent bugs.
Kind of a silly assertion, no? Particularly given you've failed to characterize these "latent bugs" other than the fact that they aren't related to memory safety. You've also failed to provide any compelling commentary regarding whether these "latent bugs" are present in C or C++ programs. If you believe they are, then Rust still makes the situation better by reducing the number of exploitable bugs by reducing the number of memory safety bugs.
Methinks you are suffering to an appeal to ridicule. Your comments are written as if someone is saying "Rust will eliminate exploitable bugs." Nobody has said that in this thread. More to the point, I'd be willing to wager that nobody with any modicum of credibility has ever said that.
Wait, so reporting bias in CVEs makes my proposed experiment bad, but your assertion about 70% of CVEs okay? Surely all the memory safety bugs that show up in the next 10 years will make this no contest...
Onto latent bugs: part of the idea of latent bugs is that they are latent, as in we don't know what they are yet. I am just pretty darn sure that we haven't found all the bugs in computer software, or even all the possible types of bugs. Spectre didn't show up until 2018, and it was a totally new type of bug.
I am pretty convinced, after working on huge-scale systems that get fuzzed really well by their clients, that we have found less than half of the exploitable bugs in Linux (and other similar systems). I'm not suggesting that Rust will hurt here, just that there's no evidence that it will. They will probably show up in C and C++ code too, but you never know.
By the way, one class of vulnerability that Rust code tends to introduce when compared to C++ code is supply chain attacks. Cargo/NPM/Pip are attack surfaces. So far, the worst version of this that I have heard about in Cargo was that several packages started printing some harmless politically-motivated text on startup.
Also, let's get this straight: I am saying that the claim "Rust reduces exploitable bugs" has not been proven yet. Let's stick to that, shall we?
> Also, let's get this straight: I am saying that the claim "Rust reduces exploitable bugs" has not been proven yet. Let's stick to that, shall we?
I don't know how one "proves" that claim. But it definitely has enough supporting evidence to be a very reasonable belief. I certainly believe it.
I just find your entire approach here to be so strange. On the one hand, you're demanding concrete evidence, but on the other, you're waving your hands about latent bugs and quantifying the number of known bugs with zero supporting evidence.
I think this is one of those things that's common sense and you're overthinking it.
From experience, no. At least cppcheck, clang tidy, and coverity together still miss aome fairly simple use-after-free on the stack. Asan or valgrind can catch it, as long as you have a unit test that would cause it, which might require 100% code and branch coverage. In more complicated cases where it somehow dependsnon inputs, even that might not cut it.
Speaking about tools like Frama-C, it is important to note that while there is an overhead during development of Rust programs because of the type system, proving the absence of runtime errors in industrial size programs using Frama-C is not something easy, and it remains quite costly (and to be fair, far more costly than making Rust programs type). However, it is true that you can catch some errors that are not caught by the Rust type system, say for example, integer overflows. But I would not bet that all problems caugth thanks to the type system of Rust can be caught using Frama-C.
Now, if we focus on functional properties (proving that the code is correct), one terribly hard problem when dealing with real world programs is handling the shape of the memory. That can make some proofs awful and really hard to complete. In a language like Rust, you can get a lot of information about the shape of the memory and the memory separation for free thanks to the type system. That would make proofs really easier (this is for example what is done, but with far less precision than what the Rust type system could provide, in the different memory models configuration in Frama-C/WP and it can already dramatically improve proof performance).
It probably does not justify rewrite everything, nor changing verification tools chains that are in use in some critical domains. However, I would definitely love working on and working with a Frama-Rust tool ;)
The idea that people will just shift to other kinds is ludicrous. There isn't a fixed quota of bugs per developer-hour. In my personal experience, Rust code absolutely has fewer bugs than most other languages.
Several large surveys have found that approximately 70% of bugs in C and C++ projects are memory safety issues.
I will say that I have written a fair amount of Rust, and never had a bug in a sub-100-line Rust program, which is a huge difference compared to C.
For more complex things, arguing with the borrow checker has often led me to weird solutions that seem to work, but are unlikely to be 100% bug-free.
I would also like to point out that the surveys are looking at known bugs, and memory safety bugs are now very easy to find, thanks to the large number of memory safety analyzers that exist.
The analyzers exist because memory safety problems are significant, but the fact that they are 70% of known bugs does not imply that Rust code will have 30% of the bugs that you would find in a C equivalent. In my experience, if the C equivalent is short, Rust code usually has 0% of the bugs! If the C equivalent is long and complex, it could be a lot higher.
It's not ridiculous, it's a proven fact! Rust obviously won't stop logical errors, but it will put an end to the almost unending cue of memory and thread related bugs.
Mind you that Firefox, for example, has been around for 17 years. Every month I get security updates fixing multiple memory holes in the code each of which could potentially allow anyone to take over my machine. Seventeen years!! They must have fixed hundreds if not thousands of such bugs by now, and every month more are repaired by updates.
We'd have none of those had it been written in Rust.
Also mind the time saved by developers not having to hunt for such (hard to track down) bugs!
> We'd have none of those had it been written in Rust.
Except for memory issues in JIT-generated code from Javascript? Not all browser vulnerabilities are caused by memory safety issues in the code generated by the Javascript JIT, but several of them are (particularly "type confusion" vulnerabilities). Rust might help avoid vulnerabilities in the code generator, but not in the generated code.
FWIW, Walter Bright have been, for years, proposing the C standard to fix the billion dollar mistake in a backwards compatible way. Stroustrup is the head of the C standards committee, just saying.
Many of the Rust "evangelists" thinks/behaves like Rust's guarantees are absolute and leads to absolutely unbreakable software by default, and advocate that the language is the silver bullet combining abilities of C, C++ (depending on application) without any of their downsides.
When you hit a limitation you really need to implement in Rust, they say "Hey, there's unsafe{}, use that". Also, they advocate that unsafe{} is equal to C/C++ in programming freedom, which is again not.
When they're reminded that reality is not like that, they get upset and defensive. This comment is a nice flag to remind this reality.
I congratulate Rust for being what it is, but it's not a silver bullet and it's not the next C or C++. It's just a very nice programming language for various applications.
Being all shiny-eyed doesn't work in CS or programming in general, and also hardware doesn't work like that (a deterministic, perfectly good behaving, spec-obeying magic box with some included smoke for higher performance).
> Many of the Rust "evangelists" thinks/behaves like Rust's guarantees are absolute and leads to absolutely unbreakable software by default
Can you point to (high-profile) evangelists that actually push this view? I think the people you refer to are a loud minority of developers who possibly don't even write professionally in Rust. I've never read or heard this position from experts.
While the people I talk with are not high profile evangelists, all of them are using Rust in their professional life for work.
Maybe the messaging should be clear, and hype should be better controlled from top to bottom, because I never talked with anyone who doesn't casts stones to C & C++ and badmouths it while saying that Rust is the one, and only, and the last savior we need.
BTW, I'm not against Rust, but I don't use LLVM. I'm waiting gccrs to dive into the language.
> I never talked with anyone who doesn't casts stones to C & C++ and badmouths it while saying that Rust is the one, and only, and the last savior we need.
So here is one, Ada was already that saviour in 1983, and in every use case where using a GC is an option, there are already plenty of options besides Rust.
Also until Rust compilers get fully botstraped, knowing C++ is a requirement to contribute to the compiler's backend.
Ada is cool, but as far as I understand it doesn't give you memory safety in the presence of dynamic allocations? Unless you use recent improvements to spark? It's hardly a superset of the safety features rust has.
You are not supposed to call Ada.Unchecked_Deallocation() directly, rather from Ada's version of "Drop".
Then SPARK allows for formal proofs that one actually does the right thing, integrated into the language as of Ada 2012.
The cherry on top of the cake is that the language is also getting affine types on top of the already battle tested features in 40 years of production deployment into high integrity systems.
Who said anything about RAII? Having RAII doesn't make C++ memory safe. If you can take a reference or pointer to some RAII-created vector, and access it after the vector is gone… then you're not memory safe?
Yes, SPARK exists, and is very cool. I think there's work on a similar system for rust (or ferrocene, anyway, which is being co-developed by AdaCore: https://blog.adacore.com/adacore-and-ferrous-systems-joining...). It also seems that SPARK now has memory ownership and aliasing support, but only since ~2019 (https://blog.adacore.com/using-pointers-in-spark), and with clear inspiration from rust. It seems to me that this addition to SPARK was felt necessary by the AdaCore people, meaning that rust had something Ada did not support (or did not support well).
Has Ada ever been the most loved language on the Stack Overflow developer survey for seven years in a row?
There are plenty of options besides Rust, but none that have & and &mut which eliminates many classes of bugs in both multithreaded and single-threaded code.
> because I never talked with anyone who doesn't casts stones to C & C++ and badmouths it while saying that Rust is the one, and only, and the last savior we need.
I do definitely cast stones on C/++, especially considering that a C project I've rewritten in Rust uncovered several memory safety issues from the very first run. Another C project I've approached also showed C-specific issues from the very beginning.
On the other hand, I don't define Rust and the savior and so on; to be specific, memory safety is a very serious issue, but not the only one, and memory safe languages solve a very serious issue, but not all the issues. Additionally, I think Rust is a niche language; other memory safe languages may be more productive for the majority of the use cases ("webcrap", like a famous software engineer described :)).
I'm a big GPL advocate, and publish I everything I can publish under GPLv3. Also, I want the code I publish to be able to be built with openly available tools. In other words, I want my software to be free and can be easily reproduced/built. This is the first aspect.
Second aspect is I don't like the behavior of LLVM ecosystem which is trying to subtly EEE gcc toolchain.
Lastly, I don't desire to be able to build a project I developed, or cloned to be only can be built with "clang/llvm/20201024+somecompanyClosedGitBuild20210514+bp1" which is available in binary form for a single distribution for a specific architecture. I have experienced SDKs and other software like that, and I don't want to go through again, or put anyone through that hoops.
>Many of the Rust "evangelists" thinks/behaves like Rust's guarantees are absolute and leads to absolutely unbreakable software by default, and advocate that the language is the silver bullet combining abilities of C, C++ (depending on application) without any of their downsides.
Where are these people? I'm not doubting that they exist, but I've never come across one and I've been in the rust community for several years now.
All memory-safe languages in existence have safe abstractions built around unsafe code. For example, most JavaScript runtimes are written in C++. The point of unsafe Rust is to be able to use the same language to write both safe and unsafe code.
On the flip side, almost all C and C++ is unsafe code. The point of unsafe Rust is to be able to reserve brainpower for small subsets of code while having a relaxed posture towards most of it.
> When you hit a limitation you really need to implement in Rust, they say "Hey, there's unsafe{}, use that". Also, they advocate that unsafe{} is equal to C/C++ in programming freedom, which is again not.
I'm interested. How does rust unsafe give you less freedom than let's say c or cpp?
It absolutely is written as a threat though, likely intentionally (probably out of spite against anyone who isn't a rust evangelist) and I'm taking it as one.
The Kernel and say Chromium, don't use crates.io. They (will) vendor what they need, which they can update when they need to and when they've reviewed the dependencies.
Unless that 0-day comes from some other software, it seems unlikely that we'll get such a worldwide supply chain issue.
Firefox, on the other hand, seems to download a ton of Rust packages during the build as opposed to vendoring. (Debian maintains a bunch of hacks to allow vendoring all the Rust components, but this isn't the default or the approach taken by other distros, e.g. Arch Linux.)
No, Firefox vendors everything it uses. Debian has no patches wrt vendoring of Rust code in Firefox. Source: I work for Mozilla and maintain the Debian Firefox package.
Thank you, I appreciate the correction. Did this change at some point in the past? I seem to remember the Arch Linux package downloading a ton of Rust stuff at one point.
No, it has always used vendored crates. Well, technically, it wasn't using vendored crates until https://bugzilla.mozilla.org/show_bug.cgi?id=1298422 , but before that, there were only a limited number of crates in use, and their only dependencies were local, so practically, that's the same thing.
They obviously didn't miss this while reviewing the patch, but just wondering: are there any performance/resource implications to making KSYM_NAME_LEN 512 instead of the previous 128 or 256?
Java would be devoured by C# and others if it were that bad. I guess that it isn’t bad, at a pragmatic level. It definitely ain’t about developer joy though. When I first used it in 99 it seemed magical though. Notepad + javac = gui program. Compare that to VisualC++ or VB!
Just because you write unsafe it's not out of jail free card.
Point of unsafe is to say these things _can_ break. Not that these things _will_ break. Calling into unsafe still has to maintain all invariants, so that safe fn wrapping unsafe fn is safe for all possible safe inputs.
Point of safe is unless someone fucked in unsafe, these things will never break.
There hasn't been a convincing argument so far that Rust is a net negative for the Rust kernel from a security perspective. Sloppy programming practices and say sloppy review practices will exist in any language. What we're hoping for is fewer "oops, I used that thing after it no longer existed".
"Complicates code unnecessarily" can be met with a counter that it's necessary for the memory safety of the future millions of devices out there.
If Microsoft and the Linux Kernel release security updates periodically, and people's research says that around 70% of those updates are addressing memory safety issues, "unnecessarily" starts to sound more like a necessity.
We have to get to a point where resistance for the sake of resistance becomes unproductive.
Rust does prevent a lot of cases of "sloppy" code. In the safe subset sloppy use of pointers won't compile. Destructors run automatically, so even sloppy code is unlikely to leak. Optional and Result types make it harder to be sloppy with error handling. The type system won't let you handwave immutability or thread-safety.
I always tend to think: "C is merely high-level assembly" with all the warts and bumps that come with it.
C is a poor choice for large software projects, because of its fragility (high-level assembly, remember).
The real problem lies in the fact that some obstinate developers refuse to trade even one iota of performance for security. Without that we wouldn't have the mess we're in today! It's relatively easy to develop a programming language that's memory and thread safe, but at the cost of some performance.
That's why Rust was developed: to get the same performance as C without the drawbacks. It does this by simply disallowing you to write dangerous code. Underneath it's simply C code, if you will.
I want to be able to actually compile my software if I wish so. This is becoming increasingly difficult. Rust is adding to the problem.