return to table of content

The first stable release of a memory safe sudo implementation

coggs
70 replies
1d3h

As one of the original creators of sudo (https://en.wikipedia.org/wiki/Sudo) I've witnessed it getting nearly totally rewritten and then incrementally bug-fixed over the last 43 years. It must take the prize for the UNIX command most highly-scrutinized for security flaws. Flaws which have been identified and fixed.

Thousands of developers and security experts have gone over it. So part of me wonders - how is it possible for a single dev team to totally reimplement it without unknowingly introducing at least a bug or two? Is there something to this Rust language which magically eliminates all chances of any bug being introduced?

nolok
23 replies
1d3h

In memory safety ? Yes, the language is much better at being safe by default. But it does nothing for logics bugs.

The thing is, replacing from C (sudo or anything else), the number of exploit due to null pointer or buffer abuse or ... represent easily 50% of it.

timschmidt
10 replies
1d2h

Enums, Option and Result types, absence of null, not to mention that the type system, borrow checker, and static everything by default, rewards encoding application state and state transitions using all these mechanics, such that they can be verified at compile time. I'd say the language does quite a lot to address logic bugs as well as memory safety. It can't protect a determined developer from themselves, but it provides incredibly useful tools to anyone who can work out how to use them.

ajuc
5 replies
1d2h

Static-everything is such a gimmick in my opinion. It sounds great until you try to do something useful with your code. It's almost never the case that people actually want to hard-code stuff in the source code.

Almost always you read configuration files at run-time (like sudo does) and change your behavior depending on run-time information - so you will have run-time errors.

kstrauser
4 replies
1d1h

“Static” here means that variables are const by default, and you can’t modify one without explicitly marking it as mutable.

In your case, a config object would be mutable inside the function that loads it from disk into memory, then read-only everywhere else by default.

ajuc
1 replies
1d

I use rust, and it does have static by default in many places (for example it's hard to do the traditional OOP virtual polymorphism or to keep objects of various types in one container) and it makes it pretty hard for me to write "nice" looking code.

It usually devolves into a lot of nested if-else and switch (match) instructions.

kstrauser
0 replies
23h29m

I haven't run into that so much myself. What I have run into is trying to write C-but-in-Rust, for which the compiler yells at me to please knock it off. It got way easier when I gave up and committed to doing things the Rust way.

Not saying you haven't done that, just sharing my personal experience with it.

GTP
1 replies
23h56m

If your program doesn't have a way of reloading its configuration at runtime, then even that first object created by reading the configuration from file can be immutable.

kstrauser
0 replies
23h31m

Yep! What I mean, though, is that the loading function itself will need to mutate the object as it reads settings from disk and updates the in-memory data structure. Once that's done, you can pass that around as a read-only object.

cyber_kinetist
3 replies
1d2h

Even if I don't like the design of Rust's borrow checker I still do appreciate how Enums/Option/Result types and pattern matching can make your code more robust. Really wish I can bring some of them to C++... I frequently use a poor-man's version of Result types with a `TRY()` preprocessor macro, but I'm often jealous of what Rust has in its toolbelt.

antoinealb
2 replies
1d1h

Isn't Rust's result type basically the same as Abseil's Status, or am I missing something ? https://abseil.io/docs/cpp/guides/status

steveklabnik
0 replies
1d1h

Generally the same idea, yes. Your parent mentioned a key difference though: "and pattern matching." enums in Rust have much stronger language support.

But there are also differences, for example, errors must be absl::StatusCode, whereas enums in Rust allow for arbitrary error payloads.

Also don't discount ecosystem usage: everyone uses Result in Rust, abeseil isn't used by most things, and std::expected has its own issues (though I can appreciate how tough making those calls is) and only landed in C++23, so it's not as widely used as Result either.

adastra22
0 replies
23h9m

Sibling comment mentioned pattern matching, but didn’t point out the important point that the rustc compiler makes sure all patterns matches are exhaustive.

To use a C example, if you add a new definition/variant to an enum, suddenly all switch statements over that enum will fail to compile (unless there is a default: branch).

This does eliminate a large swatch of logic errors, though by no means all.

lionkor
4 replies
1d3h

Is that because theyre easy to find, or because theyre the worst?

tialaramex
2 replies
1d2h

A lot of the most serious security vulnerabilities are memory safety because e.g. remote code execution is very often along the lines of "LOL, I smash buffer with machine code, it gets executed" and that's a memory safety problem.

For sudo you have potential for some very serious logic bugs, where the program does exactly what the programmer wrote, but what they wrote was not what they intended.

Rust's type safety makes it less vulnerable to these mistakes than some languages, but there is no magic. In C obviously a UID, a PID, a duration, an inode number, a file descriptor, a counter are all just integers. In Rust you could make all those distinct types (the "New type idiom"), and out of the box the Duration and the File Descriptor are in fact provided as distinct types. So, some improvement.

Someone
1 replies
1d1h

In C obviously a UID, a PID, a duration, an inode number, a file descriptor, a counter are all just integers. In Rust you could make all those distinct types

For various kinds of IDs you can do that in C, too:

  struct UID {
    int value;
  };
A C compiler can pass these in registers to functions (https://wintermade.it/blog/posts/value-struct.html). So, performance impact should be zero.

It may be not as nice as other languages, but it isn’t bad, either. If you use C++, it can be made a bit nicer, and you could also have such structs that you can calculate with.

elteto
0 replies
21h1m

You can technically do this but then you have to write wrapper functions for all relevant syscalls or libc functions to unpack the structure and call the actual thing. Lots of work.

yakubin
0 replies
1d2h

They’re easy to make.

bunderbunder
4 replies
1d2h

This gets said a lot, but I am coming to believe that the case is overstated. For two reasons:

1. Valgrind exists. It's not perfect, but it does arguably do a pretty good job as long as you're writing modern C. The biggest gap I'm aware of is that it can't really help you with global pre-allocated buffers. But I don't think that any language or tool can effectively protect you from information leakage if you're doing that sort of thing, not even Rust.

2. Memory-safe is not the same thing as secure. Programs written in memory-safe languages are rotten with security vulnerabilities, too. Rust's happening to be a memory-safe language that doesn't use garbage collection does not render it immune to this situation. It has some protections around concurrent usage of data that do add additional safety under certain circumstances (assuming you don't switch them off), but I doubt it's a panacea. I worry, though, that the Rust community's tendency to pitch this stuff as a security panacea could breed a culture of complacency that negates the advantages that Rust does bring to the table for systems programming languages. People tend to take unnecessary risks when they believe they're invincible.

shakow
0 replies
1d2h

Valgrind exists

You may be right on an infinite frictionless plane, but unfortunately that does not work in real life, cf. e.g. https://msrc.microsoft.com/blog/2019/07/why-rust-for-safe-sy...

Memory-safe is not the same thing as secure.

And safety belts do not help you if your car is on fire, still it's better to wear it.

elteto
0 replies
21h4m

Many vulnerabilities rely on crafting very particular inputs that trigger memory corruption in programs. Unless you happen to have fed that same input to your program when running it under Valgrind then Valgrind is useless for this case.

chlorion
0 replies
22h14m

It's true that it doesn't eliminate all bugs in general, but it can completely eliminate buffer overflows for example.

There is no excuse to not at least have bounds checking. This is one of the most basic memory safety problems and it's trivial to prevent.

Just preventing this small issue will prevent a non-trivial fraction of bugs. I don't have sudo's bug list on hand but I wouldn't be surprised if 25% or more are caused by buffer overflows.

So even if it doesn't prevent all logic bugs, it cuts out a pretty big chunk of the bug list.

assuming you don't switch them off

You can't switch them off.

Rust community's tendency to pitch this stuff as a security panacea

I've not seen anyone claim this so far.

adgjlsfhk1
0 replies
1d

The fundamental problem with valgrind is it only looks at what happened, not what could happen. Valgrind is great at making sure you don't have memory safety issues for "normal" inputs, but is basically useless at making sure your code doesn't have memory safety vulnerabilities when fed atypical inputs.

jerf
1 replies
1d2h

"But it does nothing for logics bugs."

"Nothing" is too strong. It does not solve logic bugs, but type systems stronger than C can solve some logic bugs too.

Even something as simple as having some concept of "private" and "public" and some boundaries between them can help. I'm writing some code right now in Go, hardly a super strong type system, but I've still put some basic barriers in place like, you can have a read-only view of the global state, but the only way to write to it is to a per-user view of that state, and the only way to witness the changes to the underlying value is through one of those per-user write handles. This eliminates a large class of logic errors in which one accidentally reads the original global state when you should be using the per-user modified state or vice versa. This is a rewrite of some older code, and this error is so rampant in that code as to be almost invisible and probably in practice unfixable in the original code. (Which was solved in practice by only every dealing with one user at a time, and if there was multiple users, it simply ran the process completely from scratch once per user. It tried to cache its way out of repetition of the most expensive stuff, but, the cache keys had some of the same conceptual underlying problems, so it just wasn't as good as it should be.)

You can't solve everything this way. Rust's stronger type system offers more options, but you can't solve everything with that either. But with good use of types, there are still classes of mistakes you can eliminate, and classes of other mistakes you can inhibit.

(There are some tradeoffs, though; with bad types you can alse mandate incorrect usage. But I think in the case of something like a sudo replacement we can reasonably assume fairly high skill developers and that there will be a lot of high skill oversight, as evidenced by the fact they've already sought out a third-party security review.)

ndriscoll
0 replies
20h14m

C does have some notion of visibility: put private declarations into the .c file instead of the .h file and declare static linkage. You could have a function that returns a pointer to const for read only data. Obviously they can cast that away, but other languages have unsafe escape hatches too. C also has static analyzers to help with some classes of bugs.

Cowboy code might be common, but you don't have to do that. If using something C-like, C++ definitely gives you a lot more tools to write safe code (or hang yourself, up to you) though.

tptacek
14 replies
1d2h

Whatever else happened in those 43 years, we had a widely-exploitable memory corruption vulnerability (Baron Samedit) as recently as 2021.

ndr
13 replies
1d1h

And it looks like it was a buffer overflow:

https://blog.qualys.com/vulnerabilities-threat-research/2021...

Would Rust prevent this?

jvanderbot
4 replies
1d1h

Yes buffer overflows are one of the explicitly addressed vulnerabilities of Rust's bounds checker, which is always on, if memory serves. I haven't touched Rust in a year.

adastra22
3 replies
23h13m

You can get around the bounds checker with unsafe code. But yes, by default an overflow should result in a panic and program termination.

qerti
1 replies
20h30m

This comment reminds me of “What you're referring to as Linux, is in fact, GNU/Linux, or as I've recently taken to calling it…”

adastra22
0 replies
20h21m

Look into the crates you use and you’ll find tons of unsafe code, especially around custom data structures doing buffer pointer arithmetic and stuff. If it’s wrapped in a safe interface, you’d never know.

Filligree
0 replies
21h17m

You can, but unsafe code is discouraged in general, even given a slight performance cost.

For performance-insensitive, security-critical code, there really shouldn't be any such code in the entire program—and it would be easy to verify that with a presubmit.

Hedepig
4 replies
1d1h

Yes it would be prevented by the borrow checker.

chlorion
2 replies
22h49m

The borrow checker does not prevent out of bounds access of arrays (or vectors or whatever you want to call them).

The borrow checker is intended to protect against "temporal memory unsafety". It can tell you that you are using something that has already been freed, or something that could be freed while you are using it for example.

Bounds checking is a "spatial memory unsafety" problem, it has nothing to do with borrowing and exclusive references.

Bounds checking is a trivial problem, for an array that has N length, like a char[N], something tried to access a value past the end of the array (like char[11] if N=10).

Rust doesn't really do anything special here and protecting against buffer overflows does not require any novel technology.

An implementation of bounds checking is as simple as an "assert(I >= 0 && I < N)", where I is the index and N is the length of the array.

In C this is difficult to do because arrays or are just pointers (or decay to) and pointers do not carry any information about the length. Keeping a separate variable containing the length around but this apparently is too unergonomic since virtually all C software does not check every array access in all parts of the program.

In Rust, its very rare to use raw pointers to work with "arrays". Instead there is a "slice" type that models the concept of a contiguous sequence of values in memory. The important part is that the slice type is a "fat pointer", and the fat pointer contains the length or the array. The slice type is able to check every access in all parts of program.

So all slice accesses are checked by default. and you can't "turn it off". If you really want to disable bounds checking for some reason, there is an unsafe "get_unchecked" function.

There are some sequence types other than slices, arrays for example (array is a specific type here). They are still checked but they don't have to store the length information because it's encoded into it's type.

The Vec type is another one. It is a resizable "array", and it stores 3 things, a pointer to the allocation, the capacity and the length. That's mostly not relevant here though. It checks every access like the other types.

Bounds checking is a very easily preventable error. It should not be happening in $CURRENT_YEAR.

Hedepig
1 replies
22h32m

Does it not provide some protection against a buffer overflow?

Filligree
0 replies
21h16m

Indirectly, e.g. by ensuring that you can't modify an array while iterating over it. That sort of thing.

SpaghettiCthulu
0 replies
1d

Not by the borrow checker. It would be prevented by bounds checking on slices, arrays, strings, etc.

steveklabnik
0 replies
1d1h

Would Rust prevent this?

This is often hard to say.

In a very literal sense, you could write this same code, in unsafe Rust, so one could argue that Rust does not prevent it.

Some may argue that if this program was written in Rust in the first place, "concatenate all command line arguments into one big string for processing" wouldn't be the way you'd go about escaping command line arguments. The issue here is about misplacing a null terminator, Rust strongly prefers a "start + length" style of representing strings instead of null terminators, so you'd never really end up in this situation in Rust in the first place.

I'm sure there's other ways to evaluate the situation as well. Which one you find compelling is up to you.

slashdev
0 replies
23h55m

Yes, unless you use unsafe code.

jwilk
0 replies
1d1h

Discussed on HN:

https://news.ycombinator.com/item?id=25919235 (321 comments)

noahjk
8 replies
1d3h

On the surface, sudo seems fairly straightforward, so it’s interesting to hear how much work has gone into it! Do you have any interesting facts or anecdotes you’d care to share?

nolok
3 replies
1d3h

The key is in "on the surface". While the common usage of sudo is fairly straightforward, you me and most people use like 5% of it. The trick is in all the side shows.

yesimahuman
2 replies
1d2h

Makes you wonder then why it does so much, if those rarely used features increase the surface area of possible exploits? This is just a question I’ve had about *nix utilities in general, since sudo is hardly the only tool with obscure flags and features

yjftsjthsd-h
0 replies
1d2h

Because the long tail of features is useful to someone. Mind, I like doas for this reason, but having the more feature rich option available makes sense.

__turbobrew__
0 replies
1d

This is part of what the openbsd ‘doas’ was trying to solve. They drastically reduced the functionality to reduce the attack surface.

folmar
1 replies
1d2h

sudo seems fairly straightforward

`su` is straightforward, `sudo` is a very powerful piece of software and the configuration has a lot of edge cases.

SoftTalker
0 replies
1d1h

Yes, have a read of the sudoers man page and marvel at the complexity of the configuration, and wonder about your chances of getting it right if you are not well-experienced. This is the config file with the infamous paragraph:

The sudoers grammar will be described below in Extended Backus-Naur Form (EBNF). Don’t despair if you are unfamiliar with EBNF; it is fairly simple, and the definitions below are annotated.

OpenBSD replaced sudo with their own "doas" command a few years ago; the doas.conf manual page is about 100 lines; sudoers is over 2,000.

coggs
1 replies
1d3h

Hackaday interviewed me about the origin story - https://www.youtube.com/watch?v=LaAwl3HN5ds&ab_channel=HACKA...

ralgozino
0 replies
1d

great story! also, TIL that I've been pronouncing `sudo` wrong, I was 100% sure that it was supposed to be like pseudo, but I guess that is a myth :)

It's so great to be able to listen and learn from the people that invented these important building blocks themselves, I feel lucky. Thanks for sharing.

sgerenser
3 replies
1d

It can eliminate many bugs, but it certainly wouldn’t eliminate all bugs. During implementation they realized they were not implementing sudo’s (undocumented) feature of failing to run if the sudoers file is world-writable: https://ferrous-systems.com/blog/testing-sudo-rs/.

Of course they did find and fix the bug, but in general Rust isn’t going to protect you from bugs like this that are essentially logic errors.

Calzifer
2 replies
23h43m

That is documented. Since the mercurial web interface isn't very nice to use I picked a random version. sudo 1.8.6 from 2012 writes in the man page "The sudoers file must not be world-writable,".

https://www.sudo.ws/repos/sudo/file/SUDO_1_8_6/doc/sudoers.m...

This is also a very common behaviour for security sensitive applications to check config file permissions. Another example I remember are ssh private keys.

I might be to harsh but it is not so trustworthy they still made this error and still miss the documentation.

sgerenser
0 replies
23h8m

Interesting, the posting I linked to indicated this behavior wasn’t documented. It’s certainly not surprising and as you mentioned, it’s equivalent to openssh requiring specific permissions on private key files.

jrmg
0 replies
23h34m

I’m not sure why people are downvoting you. I suspect they may be clicking the link and thinking ‘that’s not documentation it’s source code’, not realizing it actually _is_ documentation.

The language it’s in is ‘mdoc’ - a markup format for man pages: https://man.freebsd.org/cgi/man.cgi?mdoc

It’s the source code for the man page, which is about as documentationey as you can get.

kristopolous
1 replies
22h25m

So let's settle this. Does sudo rhyme with judo or voodoo?

jjgreen
0 replies
20h46m

su(peruser) do, so soodoo

stefs
0 replies
1d3h

Is there something to this Rust language which magically eliminates all chances of any bug being introduced?

no, altough it has features that prevent or reduce the probability of some types of bugs - one example of this being memory safety bugs. rust can't prevent logic bugs.

the rust reimplementation probably has more bugs than the original, but a theoretically better chance to achieve fewer bugs in the long run.

is rewriting mature linux infrastructure in rust a good idea? many people agree that no, it's probably not a good idea outside of special use cases.

rnijveld
0 replies
22h31m

I can only thank you for the work you've done in creating sudo, I think it's an invaluable tool in the general day to day use for so many people. As someone working on sudo-rs, our goal with creating it never was to invalidate any of the work previously done, and we are very much aware that our implementation will not be bug free, especially not at the start.

For me personally, creating this Rust version allowed me to work on something that I would normally not be able to work on, given how I would not rate my confidence in writing relatively safe C code very high. If nothing else, at least we already found a few bugs in the original sudo because of this work. Despite the 43 years of bugfixing, such a piece of software is unlikely to ever be free of bugs, even if just for the changing surroundings.

Other than that, having some alternatives can never hurt, as long as we keep cooperating and trying to learn from each others work (and from each others mistakes).

pohl
0 replies
1d2h

I think a better question might be whether it prevents categories of bugs that are more likely to be exploitable than, say, the logic errors that no language could ever prevent?

Also, it sounds like your seasoned eyes would be valuable in reviewing this code.

narinxas
0 replies
1d3h

Is there something to this Rust language which magically eliminates all chances of any bug being introduced?

apperently, yes... and its the type system, but granted

it's only 'memory safety' bugs... the kind of error that C languages are really suceptible to.

lionkor
0 replies
1d3h

No, but maybe it feels better to know memory bugs aren't there (but all others are, and worse than in sudo)

larodi
0 replies
20h11m

Of course it's not. But hubris is possible and does not take years to master. And honestly statements like my overnight-rust-sudo is better than some poor peoples 40 years of work... well they don't really help Rust becoming more popular, but actually contribute to everything rust becoming even more irritating. Most rust tools are released with this pathos of "we fix what oldies couldn't get right with C". Not a great attitude to approach giants whose shoulders we're standing on indeed.

knorker
0 replies
19h58m

how is it possible for a single dev team to totally reimplement it without unknowingly introducing at least a bug or two?

As someone with over three decades of C programming experience (so not as much as you), maintaining widely used stuff written in C for decades, that has recently switched from C and C++ as main languages for systems programming to Rust, I'd instead ask this: How is it possible, even given 43 years of working the problem, to create a program in C that does what it's supposed to, and only what it's supposed to?

But also, one of the answers from the article is "Leaving out less commonly used features so as to reduce attack surface". Most security bugs in sudo are in features I don't use.

Rust isn't just memory safe. It's also orders of magnitude harder to accidentally make other mistakes, such as race conditions.

khimaros
0 replies
1d1h

i wonder what fraction of these fixes came with automated texts to prevent regressions (and to aid new implementations from making the same mistakes).

jchw
0 replies
1d3h

Advanced type systems and borrow checking/memory safe languages DO go a long way, but obviously, No. The best developers can do pulling a RiiR is try to follow best practices and learn from past mistakes. We've certainly come a long way in 43 years. Ditching C string handling eliminates a ton of bugs before you factor in the memory safety. Heck, you have to admit: someone setting out to make a secure sudo replacement could do a lot better nowadays even using just C. The OpenBSD project does a pretty good job demonstrating this imo. If you make a programming language that doesn't have many of the sharp edges OpenBSD code avoids, you could probably get yourself a head start, but clearly it also is going to take plenty of care and experience too, and a programming language can't really grant you that.

I think it's at least worth humoring. It probably shouldn't be shipping as a default any time soon, though...

hoherd
0 replies
1d2h

Rust aside, one thing to consider is that a reimplementation of an existing piece of software does offer the benefit of being able to test the old version and the new version side by side for consistent behavior. You could have an entire class of test cases that is just "do X with the old version, and then do X with the new version, and just make sure the result is the same." There is also the entire bug history of the old version that can be investigated during reimplementation. If the old version has specific tests for each resolved bug, those can also be run against the new version to ensure it has consistent behavior.

In this case though, it's only a partial reimplementation: "Leaving out less commonly used features so as to reduce attack surface", which would complicate that approach.

grayhatter
0 replies
1d

Thank you for working to create one of the tools which is obviously on the list of the most valuable and beneficial to computer security. Perhaps only second to netfilter.

And I'm really sorry so many people have decided they're going to imply something is wrong or broken with it for their own clout. Or because they've bought into the lie that no code written in C can be safe or correct.

For what it's worth, I and all the engineers I willingly associate with (read: the ones who I respect) all have said the exact same thing. Switching to rust here, just 'cause, isn't going to meaningfully increase anyone's security. But what are you gonna do. Other than ask people to be honest?

Annoying fanboys aside... again, *thank you*! The computer security world is meaningfully better because of your work, and that's something the RIIR fad will never be able to replace :)

godelski
0 replies
23h45m

You gotta start somewhere right? I mean its not like you got it right the first time. Don't everyone go switching over just yet, but people can't scrutinize something that doesn't exist.

amai
0 replies
22h44m

How is it possible for a single dev team to totally reimplement it without unknowingly introducing at least a bug or two

This is possible if every bug fixed has an associated test. If they use this battery of tests to test their new implementation it should be as good as the original implementation.

alkonaut
0 replies
22h18m

I’m sure there is a logic bug or two in the new implementation. Whether you want to take the risk of new logic bugs for the benefit of removing several whole categories of bugs (both known and unknown!) is the question and tradeoff in each case like this. This too requires scrutiny, but I’d be a lot more comfortable running a Rust program with 2 years of scrutiny than any C program with 40.

WesolyKubeczek
0 replies
1d2h

While I don't negate your experience and I genuinely anticipate that this project is going to rediscover some pain, there's something to be said about the fact that we don't have to replicate the life work of Newton, Leibniz, Maxwell, etc to really "get" classical physics. It fits now into the high school curriculum, and if you pass it, you can be fairly decent at it; with a little additional effort, you can get real freaking good at what took those people their whole freaking lifetimes.

This is because we can stand on those giants' shoulders and have the benefit of hindsight and not have to also repeat each and every of their blunders, and have better technology and learning methodology to boot.

So I presume if you yourself wanted to rewrite sudo from the first principles, you, with all your experience and knowledge already there, would spend a lot less time doing it, and it would be way cleaner and simpler.

So while I'm not dunking on your effort and experience, I'm just pointing out that it's not impossible to take your experience and turn it into something better over a smaller timespan.

AndyKelley
0 replies
20h19m

By making it simpler and not having a ton of rarely used features, and by using a programming language that makes it more difficult to write bugs.

garblegarble
62 replies
1d5h

I'm assuming this project's aim is to replace sudo, in which case hand-waving away "Leaving out less commonly used features" is a bit worrying. What are these features? How uncommonly are they used? In which way will it fail if a configuration uses those features?

Edit: Looks like their github readme outlines some of these limitations, https://github.com/memorysafety/sudo-rs#differences-from-ori...

hpb42
19 replies
1d4h

One of those left out features is `sudoedit` or `sudo -e`. I use this a lot when editing files in /etc or any file that my user does not have permissions. The flag first copies the file to a temporary location with permissions for my user to edit, then opens my text editor (defined via $SUDO_EDITOR env var) as _my user_, without any sudo permissions. After I close the editor, the file is copied back with the original permissions only if there were any changes.

The cool thing is running the editor via my user, which loads my user's configuration/plugins, instead of the root user's.

josephg
10 replies
1d4h

This would be a great use case for a capability security model. Essentially what you really want is the sudo command to acquire a temporary capability token to edit that specific file. Then run your editor and pass it the capability. (And revoke the capability when the editor process closes).

It’s a pity this isn’t more straight forward to implement on Linux.

quotemstr
7 replies
1d3h

Essentially what you really want is the sudo command to acquire a temporary capability token to edit that specific file.

This should be doable with an XDG portal model, right?

yakubin
6 replies
1d2h

It's doable by opening the file in a privileged process (sudo) and passing the file descriptor to a non-privileged process.

Maybe one could make a sudoedit that opens a file in sudo process and then spawns a non-privileged editor process which inherits the file descriptor and is given the /dev/fd/ path on the command line, so it stays none the wiser about the whole process.

vlovich123
5 replies
1d

Sounds like a bit of recipe for accidentally handing access to an unintended privileged fd through inheritance (ignoring the /dev/fd one) such that a compromised unprivileged SUDO_EDITOR value gives you sudo access. Maybe not likely, but I’d really be hesitant about any feature that relies on implicit fd inheritance…

yakubin
3 replies
22h42m

Close all other fds between fork and exec then (you can look at the code of base::LaunchProcess in Chromium for an example). It’s a minuscule amount of code to audit compared to XDG portals. And it’s backwards-compatible with decades of unix programs.

For a more complicated solution: spawn a zygote process early with a unix socket which you’ll use to send the fd later. Zygote at start drops provileges. When it receives the fd, it closes the socket and execs the editor.

vlovich123
2 replies
22h19m

I’m not saying it’s not possible to do correctly. But do you not agree that the first is hard to correctly (can overlook an fd) while the latter is a lot of complexity?

There is the CLOEXEC flag which is the intended way to manage this but it’s not the default and you have to be diligent about setting it which again carries its own set of challenges.

What you’d really want is CLOEXEC implicitly on all fds and having to explicitly opt in for fd inheritance.

yakubin
0 replies
21h46m

That would be ideal, but we'd need a new syscall for that.

sophacles
0 replies
21h14m

Rust stdlib opens all fds with CLOEXEC set. You have to explicitly disable it when you want the child to inhert the fd.

kelnos
0 replies
20h26m

Another option could be to open a UNIX socket in the privileged sudo process, spawn an unprivileged child process 'shim' that connects to that socket, and then the sudo process can pass the file descriptor over the socket. Since the child shim is 'clean', it should have nothing more than stdin/out/err open, plus now this passed FD. Then the shim can spawn the target program and allow it to inherit just the passed FD.

I think the larger issue is that I doubt many (if any?) editors allow opening a file via an inherited file descriptor! I guess some will read stdin (the shim could close stdin and then dup2() it into its place), but then there's no way to save the file back when finished.

arijun
1 replies
21h47m

Are there no overwrite/seek bugs in Unix that could be exploited in that case? It seems to me like only using sudo for a cp command would reduce the attack surface.

josephg
0 replies
9h4m

I’d certainly hope not. A capability based security system in an OS is only secure if it doesn’t have bugs. Just like most security-critical software.

However, I’m not sure that Linux is capable of masquerading as a general purpose capability based operating system. I think it’s missing a bunch of APIs.

tambourine_man
2 replies
1d4h

In Vim:

:w !sudo tee %

Which I map to :w!!

Of course, if you’re not using Vim, you’re doing it wrong :)

phanimahesh
1 replies
1d3h

It is a little less useful if the file is not readable by your user, and once you authenticate anything within your vim can also silently run other sudo commands since on most distros sudo remembers the autnentication for a while.

Now that I think of it, not sure how sudoedit behaves wrt this cached auth.

KMnO4
0 replies
1d2h

I think you can use the sudo -k flag to clear the cached auth

Zardoz84
2 replies
1d4h

I usully use "sudo -E EDITOR_OF_MY_CHOICE"

liftm
0 replies
1d4h

Many editors can execute shell commands, so this isn't the same at all.

Denvercoder9
0 replies
1d3h

That makes your editor run as root, which is a bad idea for many reasons (aside from security, any mistake now has the potential mess with the whole system).

lucideer
0 replies
1d3h

One of those left out features

They indicate that many omittted features are by design, but this particular one is implied to be planned:

Some functionality is not yet supported; in particular sudoedit
aumerle
0 replies
1d

So now any program that's running as your user, even your browser, can edit any file you edit with sudo. It just has to watch for your editor to quit and win a race with sudo to modify the file before sudo reads it.

dtx1
18 replies
1d4h

Having so many different feeatures in one of the most basic unix tools is much more of a red flag.

garblegarble
17 replies
1d4h

For sure! But that mistake has already been made, and has been in the wild for years, so removing those features (and proposing yourself as a replacement for the original) is now a breaking change

mprovost
15 replies
1d4h

OpenBSD replaced sudo with doas (with a vastly reduced feature set) several years ago, and without breaking everything. Sure there are use cases where you absolutely need some feature of sudo, but you can always install it.

garblegarble
6 replies
1d4h

That seems like the Right Way to do it...

As annoying as it is to have to update every sudo reference -> doas, it forces you to think about everywhere you're using it, rather than waiting to see what breaks and then trying to fix it.

codetrotter
5 replies
1d3h

As annoying as it is to have to update every sudo reference -> doas, it forces you to think about everywhere you're using it, rather than waiting to see what breaks and then trying to fix it.

In my scripts I never call sudo or doas. Instead, if the script needs to do something as root, I write the whole script so that it expects to itself be run as root.

And then when I want to run my script, I run it as root

    doas ./somescript.zsh
PrimeMcFly
3 replies
1d2h

That's a much worse approach from a security pov.

codetrotter
2 replies
1d2h

No. That’s a blanket statement on your part that you cannot make because you don’t know what my scripts look like, or what commands they call.

xyzzy_plugh
0 replies
1d2h

No, it's never better to run whole scripts as root when root is only required for part of it. Unless every expression in your script requires root, the blanket statement holds.

In my experience, and in my own scripts, it is better to explicitly check if you are being run as root, advise against it and exit (with maybe some break glass flags) and invoke sudo when escalated privileges are required.

PrimeMcFly
0 replies
1d2h

Yes, it's a blanket statement, better it's an absolute statement because it's absolutely true.

You're taking a shortcut due to convenience and it's bad security practice.

It's that simple.

josefx
0 replies
1d2h

I just constantly run as root since there is always a chance that I might need root permissions for something. /s

samus
2 replies
1d4h

OpenBSD is much more open (pun not intended!) about breaking parts of userspace to push through beneficial changes. After all, they control their own userspace and can fix up most things before they even become an issue. Linux is only the kernel.

cpach
1 replies
1d3h

In that case, shouldn’t Linux distros be even more free to break things…? In theory they can bundle any userland tools they want.

AFAIK sudo isn’t really tightly coupled to the kernel itself.

samus
0 replies
1d2h

They could, but their users really won't like that. They have their workflows that they got used to. In practice it's gonna be GNU Coreutils and Glibc and the other usual suspects. If they bundle something more exotic, it better be for a very good reason. For example musl on Alpine or what Android does.

PrimeMcFly
2 replies
1d2h

OpenBSD is mainly used by hobbyists and not sysadmins, which is why there are not complaints about the missing functionality.

kristjank
1 replies
1d1h

OpenBSD is mainly used where other Unices can be used, and provides widely used software like OpenSSH, OpenBGPD and OpenSMTPD. To say that it's a hobby project strikes me as very ignorant. That said, it is not very easy to convince the developers that a function is missing because it's a pretty opinionated project, and they might not share the user's definition of needed functionality. Thankfully, they're nowhere near ebassi levels of functionality deletion disorder.

PrimeMcFly
0 replies
1d

OpenBSD is mainly used where other Unices can be used,

That's a pretty general statement, and I'd say to that not really. It's very much a hobbyist OS. A few people use it at home as firewalls, a few small businesses maybe, but it's mostly hobbyists and developers.

To say that it's a hobby project strikes me as very ignorant.

I mean, I've been familiar with the project for over 20 years, so I don't think I'm ignorant at all. The developers primarily make the OS for themselves and people with the same ideas and priorities.

That said, it is not very easy to convince the developers that a function is missing because it's a pretty opinionated project, and they might not share the user's definition of needed functionality.

Right, the devs prioritize their own needs, and can do so because it's a hobbyist OS.

xorcist
0 replies
1d3h

without breaking everything

Except all exiting use of sudo ...

It's such an entrenched tool that I'm sure there a compatible replacement could be useful.

Personally I would appreciate someone to take on the mess that is PAM. It was much too complex from the start and it hasn't become better over the years.

Fnoord
0 replies
1d3h

OpenBSD uses BSD_Auth instead of PAM. So you cannot use your YubiKey with doas via PAM on the Linux ports. At least not in the same way, as they do not support caching it seems.

speed_spread
0 replies
1d4h

Priorities. If a fundamental security tool's design limits it's trustworthiness, it greatly reduces it's usefulness and "breaking" it's interface is thus warranted.

quotemstr
6 replies
1d3h

There's a gulf between being 99% compatible with something and being a 100% drop-in. If the author of program B wants to replace A, he should go the extra mile and implement every feature of A so as to erase technical excuses for stasis. B needs to put aside his ego, swallow his pride, and implement all the features of A, even the ones her personally dislikes, because the effect of doing otherwise will be that B doesn't replace A. We have to work backwards from out desired outcomes.

marcus0x62
4 replies
1d2h

Perhaps, but if the goal is security of a critical tool, losing some attack surface (features) if they aren’t widely used is a win. Other projects, like ntpsec[0] have taken this approach with good results. Although, I agree with another commenter in this thread[1] that this effort would have been better directed at something with an inherently small attack surface like doas.

0 - https://www.ntpsec.org/accomplishments.html

1 - https://news.ycombinator.com/item?id=38161016#38162736

godshatter
3 replies
1d1h

The features they are leaving out were presumably added for a reason. If someone is on a system that is using sudo-rs as a drop-in replacement (not under their control) and they need to use one of those less widely-used features, how secure is the work-around they have to use instead? I'm hoping this factored in to their analysis.

Sometimes reimplementing something and leaving out lesser-used features to "reduce the attack surface" can sound an awful lot like "let them pound sand".

marcus0x62
1 replies
21h39m

Sure, and those people are free to continue to use the C-based implementation of sudo, implement the features themselves and submit patches to the maintainers of the rust sudo implementation, etc. But, the idea that a feature, once implemented, is sacrosanct and can never be deprecated is insane, especially for a piece of critical security infrastructure.

infamouscow
0 replies
20h45m

Having disdain for real-world business requirements is probably why Rust sees so little use in the real world.

nucleardog
0 replies
23h7m

Did you know you can set up an OpenVPN tunnel with no encryption or authentication?

I'm sure for someone out there that's a make-or-break feature, but for the vast majority trying to use OpenVPN it's a massive, insecure footgun. (Hell, how many bugs have protocol negotiation led to in OpenVPN/SSL/etc?)

Compare that to Wireguard that just says... it's encrypted. Full stop. Carry on.

A lot of this tooling and technology was developed in a different era with different priorities. Security, and especially network security, was not such a huge focus 30-40 years ago. Priorities have shifted. The operating environment is a lot more homogeneous (when's the last time you dealt with a layer 2 protocol besides ethernet?), while the risk of poor security has grown immensely.

It's absolutely fair to critically evaluate these features and determine which can be removed to simplify and improve the products for the vast majority of users. If a small fraction of users stay on sudo, but the majority are able to move to a more secure option... that's a win. This is exactly what Wireguard provides versus OpenVPN.

db48x
0 replies
1d2h

It’s actually mostly just a matter of time and money. They implemented the most commonly–used features first, because those are the most important ones. The majority of people could probably swap sudo-rs in for their existing sudo implementation today with nothing lost. Others will need one of those “enterprise features” and so they should either wait or pitch in.

gary_0
5 replies
1d4h

One feature they didn't mention they left out was the ability to run `make me a sandwich` (https://github.com/sudo-project/sudo/blob/main/Makefile.in#L...)

queuebert
4 replies
1d3h

Is that a Slashdot reference?

tecleandor
3 replies
1d3h

Old XKCD joke (maybe coming from an older joke)...

https://xkcd.com/149/

gary_0
2 replies
1d3h

That XKCD joke was all over the Internet in 2006. Now get off my lawn.

tecleandor
0 replies
1d3h

Well, that comic is from 2006 so not that far away :P ;)

kelnos
0 replies
20h23m

Huh, it took 6 years for the joke to get added: https://github.com/sudo-project/sudo/commit/c1d6e86d67aa60d7...

SonOfLilit
5 replies
1d4h

I've lived through the transition to systemd. I'm sure sysadmins will be able to manage this one. And I'm sure great technical documentation exists, this was a PR release, not where I'd look for a list of missing features.

jacquesm
4 replies
1d4h

I still run into trouble on a fairly regular basis on account of systemd. Especially the log files continue to cause all kinds of issues.

happymellon
2 replies
1d4h

What issues do you run into with the log files?

I have plenty of ideological problems with the design of the logs, but not actually ran into problems in the real world.

djbusby
1 replies
1d4h

I'm still mad I can't just `tail -f`

eptcyka
0 replies
1d4h

journalctl -f?

abofh
0 replies
1d3h

Have you tried reading them? They're often helpful

fermuch
1 replies
1d4h

It seems like those changes are noted here: https://github.com/memorysafety/sudo-rs#differences-from-ori...

garblegarble
0 replies
1d4h

The text seems to imply that's not a list of features not implemented, it's a list of features not implemented that don't output a clear error

sigio
0 replies
1d3h

One of the features I use in some (larger) environments, which isn't on the roadmap or implemented is LDAP support in sudo-rs. Using the regular sudo, this allows you to manage the sudo permissions for the entire network from the central LDAP configuration, and even make rules that are time/host/user/command limited in a central location with no chance of simple syntax-errors wiping out your entire configuration, just that single rule is being ignored in this case.

emporas
0 replies
15h59m

So, statically link the new sudo with the old sudo, and when the user tries to use less commonly used features fallback to the older version in C.

The binary executable will be bigger, but disk space is a lot cheaper nowadays, compared to 43 years back.

I mean, is there any time where one more level of indirection failed to make everyone happy?

fdsfsdfdsffgg
23 replies
1d4h

Apache-2.0+MIT vs GPL-2.0

So, you may get a memory-safe su/sudo-rs, but those who distribute it in a binary form won't be obliged to show you the source code it was built from (potentially including some modifications).

wiz21c
9 replies
1d4h

Moving away from the GPL is a very bad idea for such critical component. Exactly for the reason you give.

(this post is just here to insist on the issue)

mhh__
7 replies
1d4h

In general a lot of "[GNU tool] but in rust" projects do seem to come very close to violating the GPL, especially in spirit.

tsimionescu
6 replies
1d3h

In what sense? It is completely in the spirit of the GPL to reimplement a GPL tool from scratch with the same behavior and a different license. After all, that's how the free Unixes came about (though admittedly those were BSD licensed typically).

zorked
2 replies
1d3h

Kinda? Historically there were indeed concerns about reimplementation and copyright. One of the ways that the GNU Project tried to fight claims was to reimplement the tools using dynamically-allocated memory (instead of Unix's traditional fixed-size buffers) to make sure the implementation was sufficiently different. Other ways were making the implementation Posixly correct, adding internationalization or trying to pick different approaches (like using more modern algorithms for sorting). The GNU tools were better, not just direct ports, and that's why it was common to install them in systems like Solaris or HP-UX.

mustache_kimono
0 replies
1d

Kinda? Historically there were indeed concerns about reimplementation and copyright.

Free software projects should welcome multiple implementations and interoperability, because these are the mother's milk of free software. It's frankly incoherent, given values of free software, that a reimplementation of, for example, Unix coreutils (GNU) would find fault with a reimplementation of itself (uutils).

Notwithstanding how philosophically incoherent it is, a desire, now that Linux and free software have some market power, to be a bully back, to grasp for monopoly power, to play AT&T, is really distasteful. What's exciting about free software is not the artifact, Linux or coreutils or sudo, but that anyone can create new and interesting alternatives. That users get to make choices about which implementation to use. The existence of FreeBSD does not make Linux worse. It makes it better! The "solution" to an MIT licensed coreutils is a GNU licensed fork which is 10x better. Instead, we get complaints which amount to a kind of free software entitlement, an endless pissing and moaning about how other people won't do new things your way.

This is a major problem in the way that most normies view the GNU and the GPL. In the past, I may not have chosen the GPL for my own projects, but I'd be pleased to contribute to a GPL project. Now, I'd have a hard contributing to a GPL project, because of just how toxic this attitude (no other license matters but ours) is.

iudqnolq
0 replies
1d2h

Arguably writing in Rust will force a similar magnitude difference to those examples. For example, you'll probably replace that modern sorting algorithm with a call to .sort

oynqr
2 replies
1d3h

Pretty sure you'd have to clean room the whole thing. Which these Rust implementation might not have. This is not legal advice.

mhh__
1 replies
1d1h

I can't remember enough to name names but one obviously didn't to the point that it mentioned what the GNU code does in comments.

mustache_kimono
0 replies
1d

I'm really not certain this is enough to be a copyright problem.

For instance, GNU and POSIX both publish their specs for the coreutils. If a coder were to take a look at the actual GNU code (which BTW is published for everyone to see), copyright law has a well trodden distinction between the idea and the expression -- that is, ideas are not copyrightable. If the "idea" simply amounts to what would be a more a detailed specification, I'm not sure there is a problem, like ... GNU uses this kernel facility for X. The problem would be vast amounts of "expression", especially "creative expression", directly copied and reimplemented in Rust. If the code is meat and potatoes, not 10xer galaxy brain fare ("I wrote a custom allocator which is suspiciously like the custom allocator implemented by GNU"), there shouldn't be an issue.

Think about what copyright to a play, or a novel, or a screenplay is. Now imagine a comment in the text/source: "This is how Toni Morrison did her characterizations in Beloved". This obviously isn't a copyright violation, unless you're copying the actual expression or a translation of the actual expression found in Beloved.

nindalf
0 replies
1d2h

But it wasn’t GPL to begin with - https://www.sudo.ws/about/license/

zigzag312
3 replies
1d4h

Is that really bad? You are free to not use such distributions.

Regarding security, malicious actor could show you a different source code from what he distributes in a binary form. GPL or no GPL.

pbmonster
1 replies
1d3h

Regarding security, malicious actor could show you a different source code from what he distributes in a binary form.

That's why hashes are published by distributors and checked by package managers, right?

zigzag312
0 replies
1d2h

That only checks that binaries are the same as what is published by distributors.

It doesn't help against a malicious distributor, unless package managers also do a deterministic build themselves and verify that checksum from self-build binary matches the checksum published by a distributor.

EspressoGPT
0 replies
1d4h

Is that really bad? You are free to not use such distributions.

It's not really bad but it kinda defeats the purpose.

pjmlp
2 replies
1d4h

For better or worse the use of GPL is going away, even the future of Linux kernel is not guaranteed.

In the realm of IoT FOSS UNIX like operating systems, all the contendants are using a mix of Apache, MIT and BSD licenses, including the ZephyrOS sponsored by the Linux Foundation.

When the GPL generation is gone from the face of the Earth, it won't last long that UNIX-like OSes get another steward alternative to the Linux kernel, with a more appealing license to big corps.

NegativeK
1 replies
1d

How would they be able to drop the GPL from the Linux kernel?

pjmlp
0 replies
1d

By replacing it with something else, duh.

Linux kernel isn't the first nor the last UNIX clone.

alwayslikethis
2 replies
1d4h

I wanted to write this comment too, as I have a serious concern that the effort to displace GPL tools with Rust rewrites in MIT/Apache will one day lead to a proprietary Linux, but the original sudo is not in GPL. It's in an ISC/MIT style license [1].

1. https://www.sudo.ws/about/license/

pjmlp
0 replies
1d3h

Look at Android, the only GPL thing left is exactly the Linux kernel, and it hasn't been yet replaced by Zirkon because reasons.

Look at the FOSS UNIX like RTOS, none of them is GPL.

fdsfsdfdsffgg
0 replies
1d4h

There are su and runuser in util-linux (GPL-2.0) [1].

[1]: https://github.com/util-linux/util-linux/tree/master/login-u...

Nullabillity
2 replies
1d4h

Sudo is ISC-ish[0] (very permissive), not GPL. Su does indeed seem to be GPL though.

[0]: https://www.sudo.ws/about/license/

ksherlock
0 replies
1d4h

The GNU ~~coreutils~~ util-linux version of su would be GPL but su is from Unix V1 (1971) so there are AT&T implementations, BSD implementiations, etc.

fdsfsdfdsffgg
0 replies
1d4h

There are su and runuser in util-linux (GPL-2.0) [1].

[1]: https://github.com/util-linux/util-linux/tree/master/login-u...

slacka
6 replies
1d3h

Would be interesting to see a a Debian derivative that combines this with the Rust Implementation Of GNU Coreutils.[1] Could be a big win for memory safety and performance.

[1] https://github.com/uutils/coreutils

guerrilla
5 replies
1d2h

I wonder how we are from a Rust UNIX userland. At least we wouldn't have to implement a C compiler!

nonameiguess
2 replies
1d

I looked into this a few years back when I was making my own toy Linux distro, and this is the list of packages provided by a typical GNU system that meet POSIX requirements for a userspace:

* `bash`

* `bc`

* `binutils`

* `bison`

* `Coreutils`

* `Diffutils`

* `file`

* `Findutils`

* `flex`

* `gawk`

* `glibc`

* `grep`

* `tar`

* `gzip`

* `M4`

* `make`

* `man-db`

* `man-pages`

* `procps-ng`

* `psmisc`

* `sed`

That's a reasonable start, but you also need, minimally, something to replace `pciutils`, `IPRoute2`, a bootloader, and an init system. For a close to expected experience, add in `TexInfo`, `XZ`, `ZStd`, and `bzip2`, plus `shadow` if you don't want passwords stored in plaintext.

POSIX doesn't dictate an editor, but you probably want something that can run in a terminal. Usually `cURL` and either `openssl` or `GnuTLS`, plus `bind-utils`, `ldns`, or something equivalent are there for actually using the network, something to replicate `gpg` functionality if you're going to install signed packages, and of course the package manager itself. Cargo is fine for Rust app developers, but can't replace an installer of system packages. You likely need an `ssh` implementation to replace `OpenSSH`.

I'm sure there's more I'm missing, but this is pretty close to what you'd get in a minimal server image.

If you're looking to fully get rid of C and not need a C compiler, though, Linux itself is a hurdle. You don't necessarily need a kernel quite as fully-featured, but you need something that at least implements the POSIX system calls. Just about every Linux distro I'm aware of seems to also provide Python and Perl these days as a whole lot of system utilities and build scripts use them. Presumably, rewriting all of Perl and Python in Rust is not feasible, so you either need some other interpreted scripting language good for system scripting that is written in Rust, or somehow make your shell a superset of POSIX but also much closer to a real programming language.

Don't underestimate the lift of replacing `libc`, either. It's not just the C standard library and interface to system calls. It also provides the linking loader that makes it possible to even run other programs, all of the locales and time zones, the system's name server, profiler, memory dumper. A whole lot of stuff.

mprovost
1 replies
22h36m

POSIX doesn't dictate an editor

ed is the standard text editor!

yjftsjthsd-h
1 replies
1d1h

A Linux distro is going to need to see compiler to self-host regardless of the user land. If you can live without Linux, there's redox ( https://redox-os.org/ )

guerrilla
0 replies
1d

Well, I guess if the build system uses that distro or if it's a sourve distro.

jackmott
6 replies
1d5h

I remember a couple of years ago a root exploit in Sudo that was the result of failing to check for a sentinel value, thinking “that is a bug that wouldn’t happen in Rust, even though it isn’t related to memory safety!”

Rust enums are sum types, and imho are one of the few unambiguously good language feature ideas. I miss them any time I use a language where they are not built in. F# is another nice language where they are first class and where I first got familiar with them

Karellen
5 replies
1d4h

Rust enums are sum types,

I wouldn't mind so much if they just called them "sum types" or "tagged unions", or even some other new name. Reusing the existing name "enum" from other languages, but differently from the way all those other languages have used it for 45 gorram years, is freaking maddening.

n_plus_1_acc
2 replies
1d3h

That's inherited from OCaml I think.

https://www.ocamlwiki.com/wiki/Enum

ode
0 replies
1d2h

Nobody in the OCaml community commonly refers to them as Enum's today or any time recently (maybe they were at the time Rust was created though? IDK).

They're usually called 'variants'.

debugnik
0 replies
1d2h

I don't think so, OCaml consistently calls them "variant types". I don't know who wrote that page, but that wiki didn't even exist before September and it isn't endorsed by ocaml.org, so I suggest you don't consider it authoritative.

cyber_kinetist
1 replies
1d3h

Swift and Scala also uses the enum keyword to define sum types, and their history goes earlier than Rust, so now you have multiple languages to yell at!

Karellen
0 replies
20h13m

Are you sure about Scala? I'm not familiar with it, but looking at the documentation it seems that an enum is a set of values, not a set of types?

https://docs.scala-lang.org/scala3/reference/enums/enums.htm...

badrabbit
4 replies
1d4h

IIRC, all the recent sudo vulns are logic errors, not memory safety. I mean, rewrite away but let's not pretend that there couldn't be some new bug introduced due to a misunderstanding of how something works or just a plain old mistake.

latexr
1 replies
1d2h

let's not pretend that there couldn't be some new bug introduced due to a misunderstanding of how something works or just a plain old mistake.

Is anyone doing that? I see a lot of claims of memory safety, but as far as I can see the project isn’t saying other types of bugs are for sure eliminated.

badrabbit
0 replies
22h10m

That's fair and i support that but it does not address historical bug patterns that may be a design issue.

alpaca128
0 replies
1d3h

In the same way a new memory bug could be introduced to the original sudo. Shrinking the attack surface with static checks seems like a better deal in the long run.

lynx23
3 replies
1d5h

doas is 43184 bytes, and does everything I need. That sudo exploit was a wakeup call. If you haven't moved away from it yet, give opendoas (Debian package) a try.

hannob
2 replies
1d4h

Do you use doas on Linux? It is not protected against tty pushback attack: https://github.com/Duncaen/OpenDoas/issues/106

That's a pretty severe unsolved security issue.

zokier
1 replies
1d1h

It's solved; TIOCSTI is disabled by default since Linux 6.2 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...

hannob
0 replies
23h4m

The thing you linked says "default y" to "Allow legacy TIOCSTI usage". So yeah, you can disable it, no, it's not the default.

There's also a related issue with TIOCLINUX and the paste functionality. (That will however be solved in an upcoming kernel version. I wrote the patch for it :-)

charcircuit
2 replies
1d1h

Having sudo itself makes an OS less secure since malware can use it to easily get root. Sure a rust version may be more secure, but even better would be deleting it entirely.

AnonC
1 replies
23h20m

How else would you do things as root or superuser without exposing everything? If your sudo configuration is ALL = ALL (or is a variant of this), then sudo opens everything up for use/abuse. But if you carefully construct the configuration to allow only certain commands, it’s much better than just giving out the root password to users.

charcircuit
0 replies
21h23m

How else would you do things as root

Nothing a user is supposed to do should require elevating to root to do.

it’s much better than just giving out the root password to users.

This is even worse. Access control should be set up properly instead of having users assume the identity of other accounts.

lambdaone
1 replies
1d1h

This is good work, and I'm not quite sure why people are complaining about it; there clearly won't be any replacement of the traditional C sudo by this unless it's driven by distros and the community making it happen.

Multiple implementations make it much easier to do fuzzing and generate automatic test suites that may be used to improve all the versions of this critical utility.

thiht
0 replies
1d

As they say in the article, their test suite was even able to uncover 2 bugs in the original sudo. That's definitely a win.

brundolf
1 replies
1d1h

By now we've gotten several projects that re-implement a core unix util in a safe language, often also with better performance due to concurrency, better standard primitives, etc

Have any of these ever been adopted by a distro as the default implementation? Is that something that might happen? I.e. I would never bother to upgrade my sudo command or my grep command, but getting better defaults would be better

Obviously they would have to be perfect drop-in equivalents, which some of these projects don't try to be, but others of them do

steveklabnik
0 replies
1d1h

In 2021, uutils was far enough along and compatible enough to boot debian. I haven't heard of anyone actually moving to them fully yet.

oh_sigh
0 replies
19h45m

Why do we need a memory safe re-implementation? Is there no way to wrap a binary and have it blow up if any attempts at memory unsafe accesses are detected?

markhahn
0 replies
23h43m

Polishing a turd?

Seriously, better reimplementations are great. But weren't you shocked to read about all those weird sudo features? I mean, the normal stuff is very weird, subtle, and therefore fragile.

Anyone who uses sudo "deeply" should probably think about whether there are other ways.

kelnos
0 replies
20h36m

Leaving out less commonly used features so as to reduce attack surface

In principle I think this is a great idea, but when it comes to encouraging adoption, I think this might be a mistake. I would love to use this, but I'm not going to install it myself and make sure it stays updated. Realistically, I'm only going to use it if Debian decides to replace their sudo-c package with sudo-rs. And I just don't see Debian (known for being fairly conservative with changes and updates) doing that when sudo-rs doesn't implement sudo-c's full feature set.

feldrim
0 replies
1d2h

I'd love to see a verification / validation parameter/flag/tool that allows the user to dry-run the current sudo configuration and print out the parts unsupported by sudo-rs.

Portability helpers for projects like these enable a frictionless change.

declan_roberts
0 replies
23h8m

I don't know why anyone is enamored with a rewrite of something as critical as sudo in a memory safe language, as if memory-safety somehow magically makes all of the other types of bugs disappear.

No thanks. Keep this far away from all of my systems.

datadeft
0 replies
21h30m

Doas is a much simpler tool for the same thing. I am not sure why it is not used more.

dang
0 replies
21h10m

Recent and related:

Sudo-rs' first security audit - https://news.ycombinator.com/item?id=38131442 - Nov 2023 (58 comments)

cyber_kinetist
0 replies
1d2h

I think the two bullet points they listed for their project (other than using Rust) are often overlooked:

- Leaving out less commonly used features so as to reduce attack surface

- Developing an extensive test suite which even managed to find bugs in the original sudo

Which are the most important aspects when writing any safety-critical code, even moreso than rewriting in Rust!