7 ms·
Security vulnerability in Rust standard library
- crispyalmond 5y agoIt's admiring how quickly they fix these. Kudos to the Rust team. But I worry about older software compiled with an older version of Rust which does not have this fixed.
- caaqil 5y ago> It's admiring how quickly they fix these This is a weird comment, especially on this fix. The bug was reported back in 2018. From the linked blog post: We also want to thank Florian Weimer for reviewing the UNIX-like fix and for reporting the same issue back in 2018, even though the Security Response WG didn't realize the severity of the issue at the time. See: https://github.com/rust-lang/rust/issues/48504 https://github.com/rust-lang/rust/issues/48504
- dralley 5y agoIt wasn't known to be a security vulnerability as time.
- dundarious 5y agoFailing to recognize it as such is not a hugely different kind of failure. Symlink attacks have been known about for a long time. I'm not castigating the devs/teams here (I don't even think the underlying security risk is that high) but any credit for speedy response should carry caaqil's significant caveat.
- jasonpeacock 5y ago> But I worry about older software compiled with an older version of Rust which does not have this fixed That's true for everything, right? Anyone running older versions of Java, Python, Ruby, Go, C++ (gcc/llvm), etc. that don't update all are exposed to unpatched security vulnerabilities, in both their 3P library dependencies, stdlib, and compilers/interpreters. I don't see how Rust can force people to update any more than any other language.
- masklinn 5y agoTbf in python or java you can update the runtime without having to touch the program.
- vbrandl 5y agoMaybe by releasing often (every 6 weeks or out of band for bug fixes like this), they make it easier to use a current version of the compiler, in comparison to the old Java release cycle of multiple years. Also testing the compiler against the whole ecosystem on crates.io before releasing a new version helps building trust in the backwards compatibility of new compiler versions. So they are doing something to establish a culture where updating your compiler regularly is encouraged. I don't have actual numbers and I don't know how enterprise Rust shops handle their compiler versions, but they are doing things to encourage (not force) users to keep their compilers up to date.
- nonameiguess 5y agoVirtually every other language has a stable ABI and dynamically links the standard library, so if you have a vulnerability in the standard library, update it and you're good to go. With Rust, you need to also recompile every program and other library on the system that uses std, which is likely all of them.
- watermelon0 5y agoGolang, which is most used system language in the last few years, also bundles stdlib. Additionally, quite a lot of software seems to be distributed in self-contained format; for example many Java apps (even those intended to be installed on a server) come bundled with JRE, and Linux GUI apps and games are usually distributed in Flatpak/Snap/AppImage. Of course let's not forget about distributing software as Docker images, which is probably the most common way software is installed in many server environments.
- josephcsible 5y agoIn general, programs should never operate on the same file name more than once. If there's more than one thing you need to do with a file, open it and then operate on the FD instead.
- nindalf 5y agoThis issue seems like it would be common across languages, or at least those languages that have filesystem APIs in the stdlib. My understanding is that it is fixed in Python 3.3, while in C++ concurrent file system access is considered UB and therefore this isn’t a bug. Do people know the state in other languages?
- piyh 5y agoUB?
- spoiler 5y agoIt stands for "Undefined Behaviour" It's commonly used in C/C++ communities (elsewhere too, but not as often).
- tyleo 5y agoUndefined behavior: https://en.m.wikipedia.org/wiki/Undefined_behavior https://en.m.wikipedia.org/wiki/Undefined_behavior
- milliams 5y agoUndefined behaviour -- https://en.wikipedia.org/wiki/Undefined_behavior https://en.wikipedia.org/wiki/Undefined_behavior
- tyleo 5y agoIt appears the race was on for commenters to jump in and define undefined behavior. Your comment is similar to my own. I feel like this sort of thing can be utilized as some sort of dev honeypot.
- remram 5y agoIt's easy enough to delete your comment if you see older ones after you've replied. With the amount of discussion around distributed system design on here, it's pretty egregious that we can't get the simplest transactional behavior right.
- deleted 5y ago[deleted]
- cyber_kinetist 5y agoThis relates to the fact that there's some talk going on in the Rust community to extend lifetime checks to domains outside of memory safety (like filesystems). Here's an RFC that tries to extend lifetimes to file handles: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md https://github.com/rust-lang/rfcs/blob/master/text/3128-io-s...
- milliams 5y agoInteresting RFC. I'm interested in how something like `OwnedFd` can work. In what sense is it "owned"? What's stopping the OS from deleting/changing the file underneath it? Do OS's provide some API to this end, or will the Rust std library do some checks before allowing operations on it?
- voxic11 5y agoFile Descriptors are not files. They are unique per process so the rust compiler should be able to completely track their ownership.
- hn_go_brrrrr 5y agoNo they're not. Other processes can pass you an fd at startup, you can send/receive fds across a Unix domain socket, and there are even syscalls for copying another process's fds.
- estebank 5y agoBut another process wouldn't be passing an OwnedFd in that case, and sending an OwnedFd away would pass the underlying FD and drop the wrapping OwnedFd. The process receiving the FD would have to take care (as today in any C program) to determine whether they are responsible dispose of the FD or not.
- brandmeyer 5y agoThe receiving process gets a copy of the file descriptor. Both processes must close(2) it.
- vessenes 5y agoThis doesn’t go with my mental model of unix filesystem permissions, can someone explain it to me? The vulnerability mentions a userspace compromise aimed at a system directory, not another sensitive user directory. In my mind, a user trying to delete say /usr/bin on a POSIX system is going to be slapped down immediately unless they are root, or have the proper group access, and this is not the responsibility of any standard library, it’s the responsibility of the fs layer and kernel. So, what am I misunderstanding? Opening up a link to /usr/bin doesn’t ever give me permissions on /usr/bin over what I have.
- ivanbakel 5y agoTo quote the post: > If std::fs::remove_dir_all followed symbolic links, they could find a privileged program that removes a directory they have access to (called temp/), create a symlink from temp/foo to sensitive/, and wait for the privileged program to delete foo/ This is a classic confused deputy exploit - the attacker doesn't need access to the system directory, they just need to be able to point the deputy at that directory. The race condition on checking if the directory is a link means it's possible to trick the privileged program into misusing its privileges.
- perlgeek 5y agoIf I remember correctly, rust compiles to static binaries by default, meaning they include a copy of all used parts of both libraries and standard library in the executable. Does that mean that any Rust program compiled with any affected version of the standard library is affected? How would I even find those? Statically linked binary make deployments really easy, but this one scenario where they have real downsides.
- kam 5y ago> Does that mean that any Rust program compiled with any affected version of the standard library is affected? Most programs don't use `remove_dir_all`, and a smaller fraction of those use it on a directory that untrusted actors can write to. But yes, tracking down those that do is a challenge.
- pornel 5y agoThe bug exists in all versions of libstd before today's, so in this case finding possibly affected Rust programs is easy: all of them. As for other situations: when Rust programs are built with Cargo, it creates a Cargo.lock file, which is a machine-readable record of all dependencies and their checksums used in the build. Distros could archive it and later use it track all affected dependencies. Unfortunately, libstd is a magical compiler built-in, not a regular dependency, so it doesn't get recorded that way.
- perlgeek 5y agoHow do I find out if an executable was built with rust? (Assuming it's not my code...)
- PeterCorless 5y agoTokio users: this string occurs here: https://github.com/tokio-rs/tokio/blob/b42f21ec3e212ace25331d0c13889a45769e6006/tokio/src/fs/remove_dir_all.rs https://github.com/tokio-rs/tokio/blob/b42f21ec3e212ace25331...
- vlmutolo 5y ago> Note that the following targets don't have usable APIs to properly mitigate the attack, and are thus still vulnerable even with a patched toolchain: > - macOS before version 10.10 (Yosemite) > - REDOX It's funny to me that they chose to include RedoxOS in this security advisory. For those of you serving your customers over RedoxOS in production, beware.