Good plan. Reimplementing in Rust using a carefully planned milestone-based approach should result in feature parity with fewer security vulnerabilities.
There is zero guarantee about that. The result could have fewer vulnerabilities, but it's not an easy thing to do. I'd say there definitely are some vulnerabilities left in sudo code, but over the years all the obvious bugs have already been eliminated and rewriting it in a new language can reintroduce a lot of those. Now, if the people doing this are competent and have time and money in their hands, rust enables doing some things better and basically lets you forget about basic and advanced memory bugs, so the final product may well be a good (better) one.
But just using another language to reimplement something in order to make it "safer" in some abstract manner does not guarantee anything. Good coding practices combined with "elementary" and highly-portable language like C can also result in victory that can't really be challenged. We'll see.
I don't know. But if its a drop-in replacement, which aims compatibility, then the same name seems OK. And for most use-cases, this will be a drop-in replacement. Except for obscure configs. But I think that's OK. If your goal is world domination, you aim for the low hanging fruit first.
My concern is that while re-implementing sudo in rust would solve bugs due to memory safety and off by one errors, it is a complex piece of software where logic errors can create serious security issues.
This isn't how people seriously approach memory safety.
Memory safety is a critical starting point, because without it you can no longer trust the logic you wrote in your program to behave in any particular bounded way. Memory safety bugs undermine everything else.
“Free-after-use” is not a vulnerability class; it’s “use-after-free.” And Rust’s borrow checker provides temporal memory safety; you could even say that it primarily exists to prevent temporal vulnerability classes like UAFs.
Rust protects against most memory safety vulnerabilities: use-after-free, out-of-bounds accesses, returning dangling pointers. Probably the memory safety vulnerability it's the least protective against is using uninitialized memory. And recall that memory safety vulnerabilities are the vast majority of software vulnerabilities--somewhere in the 70+% range.
But Rust doesn't only touch memory safety, it also has some measure of protection for other vulnerabilities. It's somewhat stricter on integer overflow vulnerabilities. Newtypes can be used to provide protection against validation vulnerabilities (e.g., SQL injection). Send and Sync traits can provide some measure of protection against data races: it takes a little bit of effort to use an object on a different thread if it's not able to be used from multiple threads. You don't hear as much about these protection efforts because, quite frankly, memory safety is so important that it alone is sufficient to drive many decisions.
You are not wrong, but logic errors are a pervasive concept that applies to all code bases. Logic errors in the existing codebase, as you've demonstrated, can also cause issues. The pro-Rust argument here would be "letting the compiler handle memory safety for you frees up your attention to focus on those logic errors even more."
That's not really responsive to the concern. The issue is that we've already had decades of experience with the existing sudo codebase looking for logic vulnerabilities. And, in fact, that's what the overwhelming majority of sudo vulnerabilities are; they're not generally memory safety bugs. So rewriting in a new language to get rid of memory safety vulnerabilities is not, in fact, an obviously good tradeoff.
I don't directly disagree with what you're saying here either. All of these things need to be weighed against each other. I am not familiar with sudo's codebase, and so I can't speak to if I personally agree with Prossimo or you here.
What I will say is that I certainly agree that memory safety on its own would be a weaker justification for the reasons you cite. But this analysis doesn't take into account the relative usefulness of various language features for preventing logic errors. For example, I find that enums really help catch edge cases that are easy to forget about, causing bugs. Tagged unions are obviously a thing in C codebases but aren't as easy to use nor integrated into the language in useful ways, like exhaustiveness checking. You're absolutely right that, at the moment, the sudo codebase is more well understood, but one could make the argument that C's various weaknesses in areas like the typesystem means that as this codebase matures, and becomes well known itself, logic errors become more tractable.
One could also make an argument that a new codebase is a good idea, even disregarding the C vs Rust factors. For example, they're not going for "100% drop-in replacement for sudo," they're going for "a drop in replacement for common cases." Sudo has users who I assume would be upset at removing features they rely on, whereas this project has no userbase, and therefore, can do whatever they'd like. Removing a bunch of code can also help reduce logic errors, as it's impossible to have logic errors in code that doesn't exist, obviously. Of course, this article focuses on the memory safety aspects and not the others, maybe that's a marketing mis-step. Then again, what's important here is the engineering, not the marketing.
So yeah. It's not obviously a slam dunk either way, it really depends on how one personally weighs all sorts of factors. As I said above, time will tell.
While I appreciate Rust's correctness features and dearly miss `match` statements, as a software security professional with (I think I can say) a lot of experience looking for the kinds of vulnerabilities we're talking about here: I do not buy this theory of Rust's security advantage, like, at all. People have been saying things like this about strongly typed languages of varying sorts (Haskell was once a favorite) for over a decade, and it hasn't panned out. I think you'll find, if you look at the last (say) 10 meaningful sudo vulnerabilities, that there isn't a clear story about how enums would have steered you away from the problem.
Certainly, if there's an appetite for a reduced-fat version of sudo that caters to the 80-90% use case, I'm all for a Go, Rust, or whatever version of that thing. But then, C programmers were making the same argument 15 years ago, and nobody was able to sell the reduced-fat sudo (or, for the matter, the reduced-fat ssh, which we're all still dealing with). If it works out, great.
If it ends up gradually becoming a 1:1 equivalent to sudo, wartfeatures, and all, that's less great.
> I do not buy this theory of Rust's security advantage, like, at all.
Don't worry, you've made that overwhelmingly clear.
(I also know that I am not a security engineer, and respect your overall expertise here tremendously.)
> that there isn't a clear story about how enums would have steered you away from the problem.
Yeah man, I picked an example solely based on something that's done in both languages, but differently, because I thought it would be illustrative of the general idea. I am not claiming that enums will magically fix CVEs in sudo, that would be ridiculous. I'm saying "if we're saying memory safety is irrelevant, and logic errors are what matters, you should compare the tools that let you model your problem." Maybe Rust's features are truly irrelevant here, but as you say, I dearly miss match statements when I'm working in a language without them, so I suspect they do help in the general case of this argument, even if they don't for this one specific codebase.
> People have been saying things like this about strongly typed languages of varying sorts (Haskell was once a favorite) for over a decade, and it hasn't panned out.
I actually agree with this, but I don't think that the typesystem aspects are the cause here. Programming language adoption is weird, complex, organic, and really hard to see the future of. I think it's taken decades to "productize" more advanced type systems, and it's really only relatively recently (like, I'm not gonna try and pin down an exact moment, but like, let's say "the last ten years" but I suspect even that may not be far enough back) that we've seen larger adoption of this stuff. I don't even personally consider static typing to be strictly better than dynamic typing!
Oh and, if we're gonna nitpick examples, Haskell was never going to be a language to do that, one that expressly doesn't try to pursue popularity and broad usage. Those people (and I remember them too) were wrong then, and wrong now. But that's not (only) the fault of the type system.
That said, while I agree with the description of the history, I don't see how the trend points to this being impossible, but rather than we're now living in the time of truly being able to answer the question one way or the other. And the only way you do it is by putting in the work.
I'm aware that there is more to Rust than enums, and that you were using that as an example of a correctness feature that is part of a gestalt of correctness features. My point is that people have been arguing that more expressive languages with stronger type systems will be better able to model problems and thus avoid logic vulnerabilities, and that hasn't panned out at all.
Since I don't think there's any evidence to support your point that's a Google query away from you, I guess something you could present that would weaken my argument is an example of a recent meaningful sudo vulnerability where idiomatic Rust, written in the manner that a typical Rust programmer would use to solve the relevant problem, would have foreclosed on that vulnerability. Obviously: we pre-agree about memory corruption vulnerabilities here.
To be honest, on these issues, I'm not invested in winning an argument about it. I can see good arguments for why this would be beneficial, and I think they make sense. But I also know there's good arguments for why this would not be, and I can think they make sense too. I want to see both sides represented here, because I think it's interesting, and seeing both sides is good. That's good enough for me.
If in five years (or whatever) no distros use this new tool, it's had zero impact on things, I'll go "damn, tptacek was right," and that's an outcome I am totally fine with.
> And, in fact, that's what the overwhelming majority of sudo vulnerabilities are; they're not generally memory safety bugs.
Only if you count all vulnerabilities as equal. There have been lots of sudo vulnerabilities over the years, but most of them either only affected configurations that allow users to run specific commands (unlike most configurations which are all-or-nothing), or had even more unusual requirements. I think the only sudo vulnerability in a long time that affected the default configuration is CVE-2021-3156 – and that was a memory safety bug.
Sure. That was the vulnerability I was thinking about too. I think the biggest knock I've heard against what Prossimo is doing --- and I respect & admire the people working on that project! --- from exploit-dev types is, they're picking targets that nobody thinks are likely to cough up more meaningful memory corruption vulnerabilities. I agree: 2021-3156 is a good argument for memory safety. Memory safety is a good argument! But if you're ranking "next things to make memory safe", sudo is, maybe counterintuitively, a little unattractive.
What's your ranking for "next things to make memory safe"? I'm going to guess the TLS stack would be #1, considering fly.io's sponsorship of rustls. Eager to hear the rest of the list.
Actually, there's a point: doas is already smaller and safer, so it would probably be easier to port to a new language as well as having less attack surface in the first place. Of course, it's still necessary to work with sudo as well because it genuinely supports a lot more features and some of them are even useful, but if you want the low hanging fruit...
>> it is a complex piece of software where logic errors can create serious security issues.
I know many unix commands have a lot of capabilities I never use, sudo? Not much logic other than "run this as root if user has permission" is there? OTOH I never thought about how a cli app can escalate privilige without already having it....
The escalating privileges part is easy: the file /usr/bin/sudo is owned by root and has the setuid flag set, meaning it gets executed with the permissions of the file owner instead of those of the caller.
The complexity has more to do with the fact that it has 28 command line flags, plus a fairly complex config file to configure who is allowed to do what, impersonating which user, and whether they need a password to do so. All of that dealing with security critical stuff like what exactly should carry over and what should be reset (all configurable ofc).
su is very simple by comparison (and you can do `sudo -s` anyways to get the same result as calling su without parameters).
I’m one of the people working on this. While I do think that the memory safety aspect is an important one, I think that one thing where we can win even more is that Rust has a type system that is much more robust than what C offers. If set up right, we can prevent lots of these kinds of bugs right from the start. We can also simplify things in lots of cases by removing unnecessary details no longer relevant in a modern implementation.
There is also 'doas' from the OpenBSD project. It's a replacement for 'sudo' with fewer features and a smaller codebase, with the aim of a smaller attack surface.
Though written in C for no apparent reason. It's ironic to me how security focused OpenBSD is while at the same time looking down on any other language besides C.
Note that when they say support, they mean that it's fully supported and actually works well, including that OpenBSD is fully self-hosting on that platform (read: "oops, the compiler OOMs on 32-bit" is a no-go).
Now, here's the list of targets that rust supports:
Notice that all the OpenBSD targets are tier 3, and it's a strict subset of OpenBSD's platoforms. Even if we ignore everything else - a questionable choice - rust is unsuitable for writing core parts of OpenBSD because it can't actually build for all the systems that OpenBSD supports.
The point GP was (probably) trying to make is that OpenBSD's vision of security is at odds with its insistence on C, a notoriously unsafe and insecure language. There's no reason that the replacement language has to be Rust; it could be Nim or Zig or C# or Java or Vala or OpenBSD Custom Memory-Safe Language.
What it takes for OpenBSD to choose to support whichever language it wants to is primarily a commitment to actually spend its resources to support said language. That the OpenBSD targets for Rust are tier 3 is a sign of its unwillingness to consider moving away from C: what it takes to move from tier 3 to tier 2 is a set of maintainers who have a commitment to be responsive to patches, and an automated CI solution.
(Also note that OpenBSD is the largest Unix "stuck" in tier 3 for Rust. Solaris/Illumos, FreeBSD, and NetBSD all manage to have tier 2 builders. Even Fuchsia and Redox have tier 2 support!)
OpenBSD doesn't have a Rust compiler in their core system. Having a core utility written in a language that isn't buildable with tools in their core system is a non-starter.
Once they have their own Rust compiler, or are able to import a Rust compiler that supports OpenBSD to the point where bugs on that platform are release-blockers for that compiler, and which is suitably licensed, they should be able to start (re-)writing core tools in Rust.
Another way to look at that is "SQlite has had these bugs in the past, and our standards are unlikely to be that high". It does deal with a quite complex problem domain, but is still a strong warning re. vulnerabilities in C.
1.5M lines of Rust in Android and not a single memory vulnerability found, including in their unsafe Rust code. They also observe that the number of memory vulnerabilities decreases almost exactly inline with the decreasing use of memory unsafe language in Android.
The Android Rust code is also showing to have less bugs in general than the C/++ code.
I'm guessing there aren't many rustaceans in the ranks of the various Military organisations of the world, outside of those planting vulnerabilities ofc...
Recently learned that it doesn't implement using a new pty, which makes it vulnerable to TIOCSTI and TIOCLINUX ioctl attacks. Which doesn't matter on OpenBSD, because OpenBSD does not have these features. But Linux does, so not ideal.
https://github.com/Duncaen/OpenDoas/issues/106
I’m on the team that is implementing sudo-rs, and we are definitely aware of doas and other similar utilities. Doas does definitely have its usages, especially with the ‘just let me run this as root’ use case in mind. That said, there is also something to say for the more extensive configurability of sudo, and doas does sometimes have an execution model that might be a little too simple. And having another alternative is never a bad thing in my mind.
This sounds good, however, I hope they don't try to replicate all of sudo.
sudo fails a basic security principle on Unix systems, and that is that suid binaries should be simple. Their developers have a tendency to add all kinds of stuff that barely anyone ever uses, but that bloats its size.
> Our current target is to build a drop-in replacement for most basic use cases of sudo. ...
> Some parts of the original sudo are explicitly not in scope. Sudo has a large and rich history and some of the features available in the original sudo implementation are largely unused or only available for legacy platforms. In order to determine which features make it we both consider whether the feature is relevant for modern systems, and whether it will receive at very least decent usage. Finally of course a feature should not compromise the safety of the whole program.
So seems like they're on the same wavelength as you are.
Definitely one of the things that is on our radar! Lots of features in sudo are just basically legacy features, remnants from the 90s or 00s that are no longer necessary in a modern setup, but nevertheless exist because in past times they used to be the default or only option. We are particularly aware of how much power a suid binary has, so we do try to be cautious!
Correct me if I am wrong, but isn’t Rust unsafe only when explicitly using unsafe? Provided this project does not do that, it would be memory safe, no?
Anything more than hello world is full of unsafe blocks. You need it. In any case, Ada/SPARK would be the most ideal choice for a "safe" language, not Rust. So tiring.
Is my statement considered hate? Is it not the truth, though? Any projects I pick, including Rust's standard library, there are unsafe blocks everywhere, and as a Rust developer has said, those blocks do affect code outside of it.
Rust has a lot of unsafeties. First their stdlib is mostly unsafe. Also their varargs may overflow. That's why they have tons of stack overflow bugs in their issues. They use unbounded stack allocation, alloca is nice but dangerous. To overcome their segvs they just lie and signal sigabrt instead.
They cannot free cycles.
They need to use mutexes for concurrency, which is a big no-no, deadlocking. Their FFI is unsafer than lisp ffi's.
I don't see a safe of dialect of rust, you could trust. Their new safe pragma doesn't help with all of these. There also tons of CVE's.
I think your expectations are too high. During our initial exploration we actually managed to talk to Todd Miller, the maintainer of sudo. In our (brief) interactions with him he did not sound cavalier like this at all. Instead I think that a lot of the issues with sudo are more about it being a thirty+ year old program and codebase, and sometimes features turn into bugs and security issues all on their own in such time periods. But then again, C just cannot offer the kinds of protections that Rust can, and mistakes will be made eventually by every human, better to have some protection from your mistakes than none at all.
This so-called memory safety is looking like a buzzword engineered to be extremely appealing to a type of mildly technical but mostly illiterate about computer security kind of people.
This has been said before, this has been tried before, OOP was also seen as silver bullet at some point, like several others.
Computer security is a deeply complex and dirty field, switching programming language won’t help much if programmers are expecting the work to be done for them by the compiler.
If you want robust code : hire experts in the field
and pay the price.
Rewriting sudo is almost certainly going to be painful and to increase the vulnerabilities potential.
I’m on the team that is creating sudo-rs. I agree that just assuming that memory safety will get rid of all the bugs is just plain wrong, it will prevent some particular classes of bugs, but that is all it does.
But we do think that sudo in particular suffers from being a really old codebase, and that especially on that point we can make progress. Sudo has lots of features no longer relevant. It has a plugin interface, but that interface uses almost exclusively strings in `key=value` format, and the plugin boundaries aren’t perfect either. It has behaviors that probably almost nobody relies on and yet add complexity and increase the attack surface. If we wanted to do something about that it would mean rewriting large parts of sudo. So if we’re re-implementing sudo anyway, why not start at the basics and build it a little better.
Aside from the memory safety I think that is one of our main goals: make a simpler sudo that still has lots of the expressiveness. I hope you agree that cleaning up sudo is a good thing, and if we are doing that, we might as well take some memory safety along for the ride.
I'm pretty sure this is just trying to stir people up, but we have lots of evidence that memory unsafety is the cause of the majority of vulnerabilities in widely deployed systems that are written in unsafe languages, and these vulnerabilities are often much more severe.
Refusing to accept or acknowledge scientific evidence is something that I would not expect from a security expert (or any expert).
Another tool getting reimplemented in Rust under a weak license.
Do people want to ruin the Linux Eco system or what? It only takes on distro to close its modified source(backports, bugfixes etc) for the entire Eco system to start to crack.
Indeed. This Why Not Rewrite It In Rust (RIIR) is absurd. I question their competency with regarding to C. I suppose they are just regurgitating each other's sentences without actually looking much into C and related tooling. That, or Ada/SPARK.
Ada/SPARK has fallen behind on the rich library ecosystem. I've vetted it once about 7 months ago.
I don't dig the syntax but that's 98% irrelevant; professionals shouldn't care about it. However, the lack of stuff I take for granted when working with several other languages, Rust included, drove me away. Nobody is paying me to enrich an ecosystem (even though I'd gladly take the opportunity to do so for a few languages I hold dear).
---
On the regurgitating part, I feel obliged to point out that you're doing exactly the same as those you accuse of doing it.
Rust is making strides and extremely serious engineers and decision makers are using and recommending it: part of the Linux kernel community, France's intelligence agency, Google's Android and Fuchsia projects, a lot of Fintech companies, and many others.
You and others being eternally skeptical and feeling the need to insult adopters sounds like you just want people off your lawn without an objective analysis. And without taking feedback from companies who successfully adopted Rust and wrote good blog posts with both pros and cons.
I'd question your competence if you think you know better than Google, Linux kernel devs and GCHQ.
It's your right to echo-chamber yourself, the world keeps moving though.
According to your other answers, you have already concluded that opposing RIIR is due to a hatred for Rust. I doubt there will be any convincing of you, I did attempt it when I replied to one of your comments.
> I'd question your competence if you think you know better than Google, Linux kernel devs and GCHQ.
Could I not say the same though? Ada is used in avionics, air traffic control, railways, banking, military and space technology, i.e. critical software. Are they wrong but they do not know it yet? Should they switch to Rust? Either way, I find your conclusions questionable.
> According to your other answers, you have already concluded that opposing RIIR is due to a hatred for Rust.
I refuse to discuss castles in the sky so let's get one thing straight: there is no such thing as "RIIR". It does not exist and never did. That's just a coined term by the detractors so they can have a boogeyman to shake their head at and pretend they are smarter and know best -- which is pretty rich when it comes from C/C++ devs, I have to say; not a month goes by without us getting news that the "just don't write bugs, duh!" crowd has produced yet another privilege escalation bug that, surprise surprise, comes from lack of memory safety (lol). And people still argue Rust doesn't help even in this thread, when memory safety is Rust's one of the top value-adds.
Now it's my turn to shake my head. Right back at you.
Tradeoffs exist, you are aware of that I am sure. Some people evaluate Rust and find it a good fit, others don't. Both are 100% fine. You seem to have a problem with the former though.
I never said Ada is not good btw, don't straw-man me, that's not arguing in good faith (though I took the obvious bait because that much was pretty clear already). I said that Ada was not good for the projects I evaluated, nothing else. For whoever it works well then by all means, keep using it! We don't exist to evangelize technology, we exist to get stuff done. If tech X or Y makes that easier, cheaper, more reliable etc. then we should swallow (ideally, destroy) our bias and use the right tool for the job. Can you do that? I know I can, I have my doubts about you however.
You seem to be under the illusion that there are hordes of imaginary zealots out there going around telling people EVERYTHING should be in Rust. Go touch some grass because that's not true.
(And let me blow your mind: every community has its bad apples. If you chose to judge Rust's viability based on a few loonies then that says bad things about your judgement.)
Since your shtick seems to be "I'll make it look you're the prejudiced guy" then you might as well not bother replying, I just wanted to make the above clear for future readers, not for you. You seem to have made up your mind already, long ago.
> You seem to be under the illusion that there are hordes of imaginary zealots out there going around telling people EVERYTHING should be in Rust. Go touch some grass because that's not true.
> (And let me blow your mind: every community has its bad apples. If you chose to judge Rust's viability based on a few loonies then that says bad things about your judgement.)
For the readers, too. You did blow my mind though.
Little more seriously, people do use analysis tools and memory safety bugs still creep in. There was an interesting blog post here on HN several months ago about it.
And yes it helps, but doesn't eliminate everything still.
Which ironically is exactly the argument for using Rust: it will not eliminate all bugs of course, but it will eliminate a whole class of them just because your program compiled successfully.
Part of the programmers resisting Rust is quite hilarious to watch. All reasoning and evidence presented is ignored and it all devolves to "kids these days can't code".
- doas(1) - portable version has about 500 lines of code
- doas(1) man pages - 157 lines long
- doas(1) had 2 CVEs
sudo(8)
- sudo(8) - about 120,000 lines of code (100x more)
- sudo(8) man pages - 10 000 lines long
- sudo(8) had 140 CVEs
The CVEs comparison is from 'all time' and as sudo(8) has longer history then doas(1) - it will (at least statistically) have more of these ... I expect doas(1) to have about 5-10 CVEs when they would have the same life span.
Yes, the ecosystem definitely needs more attraction.
"People do not use it because the ecosystem sucks, and the ecosystem sucks because people do not use it."
That said, it is more than enough for many use-cases that are related to critical software.
Either way, what you should focus on is the cyber-security aspect of Ada/SPARK. It is actually the language and programming environment for secure/crticial software.
92 comments
[ 3.2 ms ] story [ 267 ms ] threadBut just using another language to reimplement something in order to make it "safer" in some abstract manner does not guarantee anything. Good coding practices combined with "elementary" and highly-portable language like C can also result in victory that can't really be challenged. We'll see.
rsu, rsudo
surs, sudors (and then /etc/sudorsers as the cherry on top)
I don't know. But if its a drop-in replacement, which aims compatibility, then the same name seems OK. And for most use-cases, this will be a drop-in replacement. Except for obscure configs. But I think that's OK. If your goal is world domination, you aim for the low hanging fruit first.
[1] https://en.wikipedia.org/wiki/Doas
The reality is that all programmers are insecure programmers. The ones arrogant enough to think they are not insecure are the most dangerous.
To be fair, I think the OpenBSD people have demonstrated they're pretty capable at writing decently secure software in C.
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-2280...
Memory safety is a critical starting point, because without it you can no longer trust the logic you wrote in your program to behave in any particular bounded way. Memory safety bugs undermine everything else.
But Rust doesn't only touch memory safety, it also has some measure of protection for other vulnerabilities. It's somewhat stricter on integer overflow vulnerabilities. Newtypes can be used to provide protection against validation vulnerabilities (e.g., SQL injection). Send and Sync traits can provide some measure of protection against data races: it takes a little bit of effort to use an object on a different thread if it's not able to be used from multiple threads. You don't hear as much about these protection efforts because, quite frankly, memory safety is so important that it alone is sufficient to drive many decisions.
Imagine not using seatbelts because they don't help if someone shoots you in the face.
Time will tell!
What I will say is that I certainly agree that memory safety on its own would be a weaker justification for the reasons you cite. But this analysis doesn't take into account the relative usefulness of various language features for preventing logic errors. For example, I find that enums really help catch edge cases that are easy to forget about, causing bugs. Tagged unions are obviously a thing in C codebases but aren't as easy to use nor integrated into the language in useful ways, like exhaustiveness checking. You're absolutely right that, at the moment, the sudo codebase is more well understood, but one could make the argument that C's various weaknesses in areas like the typesystem means that as this codebase matures, and becomes well known itself, logic errors become more tractable.
One could also make an argument that a new codebase is a good idea, even disregarding the C vs Rust factors. For example, they're not going for "100% drop-in replacement for sudo," they're going for "a drop in replacement for common cases." Sudo has users who I assume would be upset at removing features they rely on, whereas this project has no userbase, and therefore, can do whatever they'd like. Removing a bunch of code can also help reduce logic errors, as it's impossible to have logic errors in code that doesn't exist, obviously. Of course, this article focuses on the memory safety aspects and not the others, maybe that's a marketing mis-step. Then again, what's important here is the engineering, not the marketing.
So yeah. It's not obviously a slam dunk either way, it really depends on how one personally weighs all sorts of factors. As I said above, time will tell.
Certainly, if there's an appetite for a reduced-fat version of sudo that caters to the 80-90% use case, I'm all for a Go, Rust, or whatever version of that thing. But then, C programmers were making the same argument 15 years ago, and nobody was able to sell the reduced-fat sudo (or, for the matter, the reduced-fat ssh, which we're all still dealing with). If it works out, great.
If it ends up gradually becoming a 1:1 equivalent to sudo, wartfeatures, and all, that's less great.
Don't worry, you've made that overwhelmingly clear.
(I also know that I am not a security engineer, and respect your overall expertise here tremendously.)
> that there isn't a clear story about how enums would have steered you away from the problem.
Yeah man, I picked an example solely based on something that's done in both languages, but differently, because I thought it would be illustrative of the general idea. I am not claiming that enums will magically fix CVEs in sudo, that would be ridiculous. I'm saying "if we're saying memory safety is irrelevant, and logic errors are what matters, you should compare the tools that let you model your problem." Maybe Rust's features are truly irrelevant here, but as you say, I dearly miss match statements when I'm working in a language without them, so I suspect they do help in the general case of this argument, even if they don't for this one specific codebase.
> People have been saying things like this about strongly typed languages of varying sorts (Haskell was once a favorite) for over a decade, and it hasn't panned out.
I actually agree with this, but I don't think that the typesystem aspects are the cause here. Programming language adoption is weird, complex, organic, and really hard to see the future of. I think it's taken decades to "productize" more advanced type systems, and it's really only relatively recently (like, I'm not gonna try and pin down an exact moment, but like, let's say "the last ten years" but I suspect even that may not be far enough back) that we've seen larger adoption of this stuff. I don't even personally consider static typing to be strictly better than dynamic typing!
Oh and, if we're gonna nitpick examples, Haskell was never going to be a language to do that, one that expressly doesn't try to pursue popularity and broad usage. Those people (and I remember them too) were wrong then, and wrong now. But that's not (only) the fault of the type system.
That said, while I agree with the description of the history, I don't see how the trend points to this being impossible, but rather than we're now living in the time of truly being able to answer the question one way or the other. And the only way you do it is by putting in the work.
Since I don't think there's any evidence to support your point that's a Google query away from you, I guess something you could present that would weaken my argument is an example of a recent meaningful sudo vulnerability where idiomatic Rust, written in the manner that a typical Rust programmer would use to solve the relevant problem, would have foreclosed on that vulnerability. Obviously: we pre-agree about memory corruption vulnerabilities here.
If in five years (or whatever) no distros use this new tool, it's had zero impact on things, I'll go "damn, tptacek was right," and that's an outcome I am totally fine with.
Only if you count all vulnerabilities as equal. There have been lots of sudo vulnerabilities over the years, but most of them either only affected configurations that allow users to run specific commands (unlike most configurations which are all-or-nothing), or had even more unusual requirements. I think the only sudo vulnerability in a long time that affected the default configuration is CVE-2021-3156 – and that was a memory safety bug.
That's the problem. It shouldn't be. I hope the sudo-rs variant does better.
I know many unix commands have a lot of capabilities I never use, sudo? Not much logic other than "run this as root if user has permission" is there? OTOH I never thought about how a cli app can escalate privilige without already having it....
The complexity has more to do with the fact that it has 28 command line flags, plus a fairly complex config file to configure who is allowed to do what, impersonating which user, and whether they need a password to do so. All of that dealing with security critical stuff like what exactly should carry over and what should be reset (all configurable ofc).
su is very simple by comparison (and you can do `sudo -s` anyways to get the same result as calling su without parameters).
https://en.m.wikipedia.org/wiki/Doas
Here's the list of hardware platforms that OpenBSD supports:
https://www.openbsd.org/plat.html
Note that when they say support, they mean that it's fully supported and actually works well, including that OpenBSD is fully self-hosting on that platform (read: "oops, the compiler OOMs on 32-bit" is a no-go).
Now, here's the list of targets that rust supports:
https://doc.rust-lang.org/beta/rustc/platform-support.html
Notice that all the OpenBSD targets are tier 3, and it's a strict subset of OpenBSD's platoforms. Even if we ignore everything else - a questionable choice - rust is unsuitable for writing core parts of OpenBSD because it can't actually build for all the systems that OpenBSD supports.
What it takes for OpenBSD to choose to support whichever language it wants to is primarily a commitment to actually spend its resources to support said language. That the OpenBSD targets for Rust are tier 3 is a sign of its unwillingness to consider moving away from C: what it takes to move from tier 3 to tier 2 is a set of maintainers who have a commitment to be responsive to patches, and an automated CI solution.
(Also note that OpenBSD is the largest Unix "stuck" in tier 3 for Rust. Solaris/Illumos, FreeBSD, and NetBSD all manage to have tier 2 builders. Even Fuchsia and Redox have tier 2 support!)
Their idea of security honestly seems very narrowly scoped on fixing a particular set of issues.
Once they have their own Rust compiler, or are able to import a Rust compiler that supports OpenBSD to the point where bugs on that platform are release-blockers for that compiler, and which is suitably licensed, they should be able to start (re-)writing core tools in Rust.
Another way to look at that is "SQlite has had these bugs in the past, and our standards are unlikely to be that high". It does deal with a quite complex problem domain, but is still a strong warning re. vulnerabilities in C.
As for now, less exposure means less CVE. So the numbers are biased.
As usually, time will tell.
1.5M lines of Rust in Android and not a single memory vulnerability found, including in their unsafe Rust code. They also observe that the number of memory vulnerabilities decreases almost exactly inline with the decreasing use of memory unsafe language in Android.
The Android Rust code is also showing to have less bugs in general than the C/++ code.
Recently learned that it doesn't implement using a new pty, which makes it vulnerable to TIOCSTI and TIOCLINUX ioctl attacks. Which doesn't matter on OpenBSD, because OpenBSD does not have these features. But Linux does, so not ideal. https://github.com/Duncaen/OpenDoas/issues/106
sudo fails a basic security principle on Unix systems, and that is that suid binaries should be simple. Their developers have a tendency to add all kinds of stuff that barely anyone ever uses, but that bloats its size.
> Our current target is to build a drop-in replacement for most basic use cases of sudo. ...
> Some parts of the original sudo are explicitly not in scope. Sudo has a large and rich history and some of the features available in the original sudo implementation are largely unused or only available for legacy platforms. In order to determine which features make it we both consider whether the feature is relevant for modern systems, and whether it will receive at very least decent usage. Finally of course a feature should not compromise the safety of the whole program.
So seems like they're on the same wavelength as you are.
Consider not caring. I'll try to do the same.
Or because it's not been developed with enough care?
I for one think that there is no unsafe language, only careless programmers.
The pilot would be the sysadmin, maybe?
Perhaps you didn't intend it this way, but that implies that there is no difference in safety between languages. This is a patently absurd idea.
C is clearly less safe than many languages that don't allow unsafe memory practices.
This has been said before, this has been tried before, OOP was also seen as silver bullet at some point, like several others.
Computer security is a deeply complex and dirty field, switching programming language won’t help much if programmers are expecting the work to be done for them by the compiler.
If you want robust code : hire experts in the field and pay the price.
Rewriting sudo is almost certainly going to be painful and to increase the vulnerabilities potential.
The experts in the field are right over there, getting paid to rewrite it in rust.
But we do think that sudo in particular suffers from being a really old codebase, and that especially on that point we can make progress. Sudo has lots of features no longer relevant. It has a plugin interface, but that interface uses almost exclusively strings in `key=value` format, and the plugin boundaries aren’t perfect either. It has behaviors that probably almost nobody relies on and yet add complexity and increase the attack surface. If we wanted to do something about that it would mean rewriting large parts of sudo. So if we’re re-implementing sudo anyway, why not start at the basics and build it a little better.
Aside from the memory safety I think that is one of our main goals: make a simpler sudo that still has lots of the expressiveness. I hope you agree that cleaning up sudo is a good thing, and if we are doing that, we might as well take some memory safety along for the ride.
Is it really broken though?
Improving the codebase could be simpler and safer, but less marketable maybe…
Refusing to accept or acknowledge scientific evidence is something that I would not expect from a security expert (or any expert).
Do people want to ruin the Linux Eco system or what? It only takes on distro to close its modified source(backports, bugfixes etc) for the entire Eco system to start to crack.
It seems any program that meets the four criteria would better served by rigorous analysis of the existing code.
I don't dig the syntax but that's 98% irrelevant; professionals shouldn't care about it. However, the lack of stuff I take for granted when working with several other languages, Rust included, drove me away. Nobody is paying me to enrich an ecosystem (even though I'd gladly take the opportunity to do so for a few languages I hold dear).
---
On the regurgitating part, I feel obliged to point out that you're doing exactly the same as those you accuse of doing it.
Rust is making strides and extremely serious engineers and decision makers are using and recommending it: part of the Linux kernel community, France's intelligence agency, Google's Android and Fuchsia projects, a lot of Fintech companies, and many others.
You and others being eternally skeptical and feeling the need to insult adopters sounds like you just want people off your lawn without an objective analysis. And without taking feedback from companies who successfully adopted Rust and wrote good blog posts with both pros and cons.
I'd question your competence if you think you know better than Google, Linux kernel devs and GCHQ.
It's your right to echo-chamber yourself, the world keeps moving though.
> I'd question your competence if you think you know better than Google, Linux kernel devs and GCHQ.
Could I not say the same though? Ada is used in avionics, air traffic control, railways, banking, military and space technology, i.e. critical software. Are they wrong but they do not know it yet? Should they switch to Rust? Either way, I find your conclusions questionable.
I refuse to discuss castles in the sky so let's get one thing straight: there is no such thing as "RIIR". It does not exist and never did. That's just a coined term by the detractors so they can have a boogeyman to shake their head at and pretend they are smarter and know best -- which is pretty rich when it comes from C/C++ devs, I have to say; not a month goes by without us getting news that the "just don't write bugs, duh!" crowd has produced yet another privilege escalation bug that, surprise surprise, comes from lack of memory safety (lol). And people still argue Rust doesn't help even in this thread, when memory safety is Rust's one of the top value-adds.
Now it's my turn to shake my head. Right back at you.
Tradeoffs exist, you are aware of that I am sure. Some people evaluate Rust and find it a good fit, others don't. Both are 100% fine. You seem to have a problem with the former though.
I never said Ada is not good btw, don't straw-man me, that's not arguing in good faith (though I took the obvious bait because that much was pretty clear already). I said that Ada was not good for the projects I evaluated, nothing else. For whoever it works well then by all means, keep using it! We don't exist to evangelize technology, we exist to get stuff done. If tech X or Y makes that easier, cheaper, more reliable etc. then we should swallow (ideally, destroy) our bias and use the right tool for the job. Can you do that? I know I can, I have my doubts about you however.
You seem to be under the illusion that there are hordes of imaginary zealots out there going around telling people EVERYTHING should be in Rust. Go touch some grass because that's not true.
(And let me blow your mind: every community has its bad apples. If you chose to judge Rust's viability based on a few loonies then that says bad things about your judgement.)
Since your shtick seems to be "I'll make it look you're the prejudiced guy" then you might as well not bother replying, I just wanted to make the above clear for future readers, not for you. You seem to have made up your mind already, long ago.
> (And let me blow your mind: every community has its bad apples. If you chose to judge Rust's viability based on a few loonies then that says bad things about your judgement.)
For the readers, too. You did blow my mind though.
Little more seriously, people do use analysis tools and memory safety bugs still creep in. There was an interesting blog post here on HN several months ago about it.
And yes it helps, but doesn't eliminate everything still.
Which ironically is exactly the argument for using Rust: it will not eliminate all bugs of course, but it will eliminate a whole class of them just because your program compiled successfully.
Part of the programmers resisting Rust is quite hilarious to watch. All reasoning and evidence presented is ignored and it all devolves to "kids these days can't code".
doas(1)
- doas(1) - portable version has about 500 lines of code
- doas(1) man pages - 157 lines long
- doas(1) had 2 CVEs
sudo(8)
- sudo(8) - about 120,000 lines of code (100x more)
- sudo(8) man pages - 10 000 lines long
- sudo(8) had 140 CVEs
The CVEs comparison is from 'all time' and as sudo(8) has longer history then doas(1) - it will (at least statistically) have more of these ... I expect doas(1) to have about 5-10 CVEs when they would have the same life span.
Regards,
vermaden
Granted I'm not a systems programmer. Just giving you one random programmer's reason to skip it.
"People do not use it because the ecosystem sucks, and the ecosystem sucks because people do not use it."
That said, it is more than enough for many use-cases that are related to critical software.
Either way, what you should focus on is the cyber-security aspect of Ada/SPARK. It is actually the language and programming environment for secure/crticial software.
Says you. It wasn't enough for the work I wanted to do for a fintech company.
¯\_(ツ)_/¯