Bringing Memory Safety to sudo and su
memorysafety.org
memorysafety.org
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-2280...
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).
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
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).
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.
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.
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
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.
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.
¯\_(ツ)_/¯
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.
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.
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.
Consider not caring. I'll try to do the same.