Live data from Hacker News

Bugs Rust won't catch

corrode.dev

181–190 of 395 posts

Re: Bugs Rust won't catch

#181

> The trap is that get_user_by_name ends up loading shared libraries from the new root filesystem to resolve the username. That's kind of horrifying. Is there a reliable list somewhere of all the functions that do that? Is that list considered stable?

Nope! But basically, expect anything that resolves usernames, or host names, to be done in the userspace by NSS. Sun engineers Thomas Maslen and Sanjay Dani were the first to design and implement the Name Service Switch. They fulfilled Solaris requirements with the nsswitch.conf file specification and the implementation choice to load database access modules as dynamically loaded libraries, which Sun was also the fir…

This is precisely why I don't link with glibc anymore.

Re: Bugs Rust won't catch

#182
post #115

Earlier quoted context omitted.

Indeed, and it doesn't need to be deprecated, because it's an API explicitly designed to give you low-level control where you need it, and because it is appropriately defined as an `unsafe` function with documented safety invariants that must be manually upheld in order for usage to be memory-safe. The documentation also suggests several other (safe) functions that should be used instead when possible, and provides c…

> and because it is appropriately defined as an `unsafe` function with documented safety invariants that must be manually upheld in order for usage to be memory-safe. Didn't we learn from c, and the entire raison detre for rust, is that coders cannot be trusted to follow rules like this? If coders could "(document) safety invariants that must be manually upheld in order for usage to be memory-safe." there's be no nee…

No, this is mistaken. Rust provides `unsafe` functions for operations where memory-safety invariants must be manually upheld, and then forces callers to use `unsafe` blocks in order to call those functions, and then provides tooling for auditing unsafe blocks. Want to keep unsafe code out of your codebase? Then add `#![forbid(unsafe_code)]` to your crate root, and all unsafe code becomes a compiler error. Or you could add a check in your CI that prevents anyone from merging code that touches an unsafe block without sign-off from a senior maintainer. And/or you can add unit tests for any code that uses unsafe blocks and then run those tests under Miri, which will loudly complain if you perform any memory-unsafe operations. And you can add the `undocumented_unsafe_comment` lint in Clippy so that you'll never forget to document an unsafe block. Rust's culture is that unsafe blocks should be reserved for leaf nodes in the call graph, wrapped in safe APIs whose usage does not impose manual invariant management to downstream callers. Internally, those APIs represent a relatively miniscule portion of the codebase upon which all your verification can be focused. So you don't need to "trust" that coders will remember not to call unsafe functions needlessly, because the tooling is there to have your back.

Re: Bugs Rust won't catch

#183

Earlier quoted context omitted.

> caused by programmer error, not anything inherent to Rust Your argument does not work as a praise for Rust because the bugs in any program are caused by programmer errors, except the very rare cases when there are bugs in the compiler tool chain, which are caused by errors of other programmers. The bugs in a C or C++ program are also caused by programmer errors, they are not inherent to C/C++. It is rather trivial…

I'm neither praising or admonishing rust. Did you read the parent comment or its parents' comment I was responding to at all? (grandparent comment): "Cloudflare crashed a chunk of the internet with a rust app a month or so ago" The actual bug had nothing to do with rust, yet rust is specifically brought up here. (grandparent comment): "Rust isn’t a panacea, it’s a programming language. It’s ok that it’s flawed, all l…

The cloudflare bug was the equivalent of an uncaught exception caused by a malformed config file. There's no recovery from a malformed config file - the software couldn't possibly have done its job. What's salient is that they were using an alternative to exceptions, because people were told exceptions were error-prone, and using this thing instead would make it easier to write bug-free code. But don't do the equivalent of not catching them!

And then, it turned out to not really be any better than exceptions.

Most Rust evangelism is like this. "In Rust you do X and this makes your code have fewer bugs!" Well no it doesn't. Manually propagating exceptions still makes the program crash and requires more typing, and doesn't emit a stack trace.

Re: Bugs Rust won't catch

#184
post #141

Earlier quoted context omitted.

> The root cause is not thinking: Why is root chrooting into a directory they do not control? Because you can't call chroot(2) unless you're root. And "control a directory" is weasel words; root technically controls everything in one sense of the word. It can also gain full control (in a slightly different sense of the word) over a directory: kill every single process that's owned by the owner of that directory, then…

> And "control a directory" is weasel words; I did not choose the term to confuse you, that's from the definition document linked to the CVE: https://cwe.mitre.org/data/definitions/426.html The CVE itself uses the language "If the NEWROOT is writable by an attacker" which could refer to a shared library (as indicated in the report), or even a passwd file as would have been true since the origin of chroot() > root tec…

> Well you can[1],

No, you can't, it's an entirely different syscall that does something vaguely similar. IMHO there are a bit too many root-restricted operations that should not have been; but they are, so we're stuck with setuid-enabled "confused deputies" — arguably, it's the root that should be prohibited from calling chroot(2).

> Now: Which database should be used to map a username to a userid? If you're the author of the code in-question, you chose the latter

That's the problem: the choice is implicit. If the author moved setuid/setgid calls way up in the call order, the implicit choice would've also been the safe one but it was literally impossible.

> unshare(CLONE_USERNS|CLONE_FS) can be used

Wait, CLONE_USERNS? That's not a real flag. Did you mean CLONE_NEWUSER?

Re: Bugs Rust won't catch

#186
post #140

Earlier quoted context omitted.

Nobody disputes that Rust is one of the programming languages that prevent several classes of frequent bugs, which is a valuable feature when compared with C/C++, even if that is a very low bar. What many do not accept among the claims of the Rust fans is that rewriting a mature and very big codebase from another language into Rust is likely to reduce the number of bugs of that codebase. For some buggier codebases, a…

As other people have mentioned, the goal of uutils was not "let's reduce bugs in coreutils by rewriting it in Rust", it was "it's 2013 and here's a pre-1.0 language that looks neat and claims to be a credible replacement for C, let's test that hypothesis by porting coreutils, giving us an excuse to learn and play with a new language in the process". It seems worth emphasizing that its creation was neither ideological…

But are the current uutils developers the same as the 2013 developers? At least based on GitHub's graphs, that's not the case (it looks fairly bimodal to me), and so it wouldn't be unreasonable to treat the 2013-era project differently to the 2020-era project. So judging the 2020-era project for its current and ongoing failures does not seem unreasonable.

Similarly, sudo-rs dropping "legacy" features leaves a bad taste in my mind, there are multiple privilege escalation tools that exist (doas being the first that comes to mind), and doing something better and not claiming "sudo" (and rather providing a compat mode ala podman for docker) would to me seem a better long term path than causing more breakage (and as shown by uutils, breakage on "core" utils can very easily lead to security issue).

I personally find uutils lack of care to be concerning because I've been writing (as a very low priority side project) a network utility in rust, and while it not aiming to be a drop in rewrite for anything, I would much rather not attract the same drama.

Re: Bugs Rust won't catch

#187
post #2

> What’s notable is that all of these bugs landed in a production Rust codebase, written by people who knew what they were doing They knew how to write Rust, but clearly weren't sufficiently experienced with Unix APIs, semantics, and pitfalls. Most of those mistakes are exceedingly amateur from the perspective of long-time GNU coreutils (or BSD or Solaris base) developers, issues that were identified and largely hash…

> They knew how to write Rust, but clearly weren't sufficiently experienced with Unix APIs, semantics, and pitfalls.

The point of Rust is that you shouldn't have to worry about the biggest, easiest to fall in pitfalls.

I think the author's point of this article, is that a proper file system API should do the same.

Re: Bugs Rust won't catch

#188
post #141

Earlier quoted context omitted.

> And "control a directory" is weasel words; I did not choose the term to confuse you, that's from the definition document linked to the CVE: https://cwe.mitre.org/data/definitions/426.html The CVE itself uses the language "If the NEWROOT is writable by an attacker" which could refer to a shared library (as indicated in the report), or even a passwd file as would have been true since the origin of chroot() > root tec…

> Well you can[1], No, you can't, it's an entirely different syscall that does something vaguely similar. IMHO there are a bit too many root-restricted operations that should not have been; but they are, so we're stuck with setuid-enabled "confused deputies" — arguably, it's the root that should be prohibited from calling chroot(2). > Now: Which database should be used to map a username to a userid? If you're the aut…

> Did you mean CLONE_NEWUSER? [~] it's an entirely different syscall that does something vaguely similar

Yes. And I agree, but it also enables chroot(2) to work without being root, which was the syscall we are talking about, and which I still maintain is not as important as reading.

> arguably, it's the root that should be prohibited from calling chroot(2).

> IMHO there are a bit too many root-restricted operations that should not have been

It's a popular opinion. It's also cheap. So what?

> so we're stuck with setuid-enabled "confused deputies"

chroot(8) is not setuid-enabled. This has nothing to do with anything.

> That's the problem: the choice is implicit. If the author moved setuid/setgid calls way up in the call order, the implicit choice would've also been the safe one but it was literally impossible.

False. The setuid/setgid calls are in the right place. The lookup of the database mapping usernames to userids is in the wrong place.

If the rust programmer just read what they wrote they would see this.

If you just read what they wrote you would see this.

Re: Bugs Rust won't catch

#189
post #156

Earlier quoted context omitted.

If you don't want Canonical's packages, you should probably just be using Debian rather than Ubuntu. It's not 2008 anymore, stock Debian is quite user-friendly.

Or use a sane distribution like Arch or Gentoo instead of Ubuntu based systems.

[deleted]

Re: Bugs Rust won't catch

#190

I find it interesting how people will criticise Rust for not preventing all bugs, when the alternative languages don't prevent those same bugs nor the bugs rust does catch . If you're comparing Rust to a perfect language that doesn't exist, you should probably also compare your alternative to that perfect language as well right? I'd be interested in a comparison with the amount of bugs and CVE's in GNU coreutils at t…

"The alternative languages" - in this case you're talking about C, 99% of the time.

So let's talk about that. Well written C code, especially for the purpose of writing and continuing to maintain mature GNU coreutils, is not a big risk in terms of CVE. Between having an inexperienced Rust developer and an extremely experienced C developer (who's been through all the motions), I'd say the latter is likely the safer option.

Post reply on HN