-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stop using absolute rpaths #11746
Comments
For an example of why an absolute path is bad, consider building a library in a home directory or perhaps It's true that this is also possible with relative ( Linux distributions usually lint for insecure rpaths, rather than all rpaths. So, an |
Accepted for 1.0, P-backcompat-lang. |
No, relative |
Sure, but having no absolute rpaths is better than having both |
I don't know if you can avoid all absolute rpaths if you configure with a custom BINDIR and LIBDIR. It should be possible if you only change PREFIX, or only change BINDIR and LIBDIR within prefix (i.e. ${PREFIX}/lib64). Think especially about the relatively common case where a rust package is installed by a user in ${HOME}. This absolutely needs an rpath ... and in the case there BINDIR= In fact, now that I think about it, my ~/bin is a symlink anyway, so relative rpaths wouldn't work. As far as I understand it, rpaths are only a security problem when running executables with a set*id bit or setcap bits. Oh, and about the "install multiple deps when you can't write to root" - the solution to that sounds like a sysroot (which == DESTDIR). So: |
That's not when rpaths are meant to be used. A user can set @o11c: It is not just a security issue with setuid binaries. Rust binaries will have rpaths based on their build directory opening up the ability for non-root users to inject code when other users run the binary, like root. Rust won't be included in Fedora or Debian if it's making this kind of security faux pas - rpaths should be opt-in. |
Well, what I always heard about LD_LIBRARY_PATH was "don't use it; use rpath instead". Particularly, asking users to set LD_LIBRARY_PATH globally just to be able to install rust packages as user is wrong. When installed as user, absolute rpaths should definitely be used. Yes, it's wrong to have an rpath pointing to the build directory, but that's not the same as it being wrong to have an absolute rpath at all. For the virtualbox $ORIGIN attack, I would hope that root can be trusted not to accidentally run someone else's hard link to the binary. Therefore, it should be secure to have two rpaths: an absolute one to the install directory (where bindir and libdir may have no relation), and a relative one to the build directory (where the equivalent of bindir and libdir are known) for testing. |
I don't understand why you would say this. It's totally fine to set I am obviously not suggesting that it be done globally. The
It's insecure to add an absolute rpath by default. I don't know of any other compiler doing this. I doubt that the Ubuntu PPA is removing this insecure rpath, for example.
I'm not talking about hard links. Adding rpaths by default with the compiler means files installed to root are going to accidentally end up with insecure rpaths. Other compilers are not doing this by default, so it makes Rust's behaviour very surprising. There's no such thing as an rpath on Windows so Rust can never provide a consistent, predictable behaviour if it uses this hack. |
Rust won't be allowed in Fedora and Debian until this issue is fixed, and their policies are not going to change. At most, they'll patch this out of the compiler and Windows won't be the only platform behaving differently. |
My understanding is Debian is likely to make at least temporary exceptions for Rust's remaining infidelities, but we should still keep trying to work toward a model that doesn't use rpath. |
Static linking is already used by default and the build process no longer needs rpaths. There's nothing blocking stripping it all out today and having users set them manually if they want them, as other languages do. It's not a technical issue anymore. |
There is absolutely nothing insecure about an rpath that is writable by the same set of users (i.e. just root) who can write to the binary itself (barring the set_id thing). There is *nothing_ fundamentally wrong with rpath. Just don't use it wrong. Neither Debian nor Fedora has an absolute ban on rpath, and Rust fits quite neatly into the explicitly permitted case. And there are very real cases where static linking simply cannot be used. One particular case I hit recently: when you need to link to an internal C shared library that is not in the default library path. I have to compile my rust library as crate type dylib and add the rpath myself. But anybody linking to my rust library shouldn't have to know about internals - they only need the rpath to my library, which rustc currently happily provides. Everything should Just Work. If rpath isn't added by rust itself (which can be done securely), you'll just end up with a bunch of ad-hoc scripts adding it in all the packages, which is infinitely harder to make secure. |
Rust adds rpaths pointing to the build directory, and these are often insecure when the binary is packaged and installed to a system directory. A package is usually build in a clean
There are correct use cases for rpaths, but adding an absolute and relative path to the build directory is not correct in many cases. It's a significant security risk. It's implicit, so "don't use it wrong" isn't an excuse. The defaults should be secure, and potentially risky options should be opt-in. You can't blame people for doing it wrong if Rust is doing it implicitly without letting them know. No other compiler seems to do this - it's a surprising default.
They don't permit what Rust is doing. Fedora is certainly not going to add Rust to the repositories as long as it's implicitly adding rpaths which are not always safe. They've kept Chromium out of the repositories for smaller issues.
The default is static linking, and it works. Perhaps you're missing that Windows doesn't have this feature, so using it provides an inconsistent experience across platforms regardless of how it's done. Most packages work fine without using any rpaths, as they just make use of the regular system libraries or are a system library themselves. |
I'm not sure what you mean by an ad-hoc script though. You can ask for an rpath by passing The Ubuntu PPA is a good example of this - it builds in a directory, then ships the binaries and libraries as a package. However, these binaries/libraries have rpaths set outside of the system directories. |
I completely agree that rust should not use absolute rpaths to the build directory. But the other cases - relative rpath to build directory and absolute rpath to install directory - are both secure and essential. |
A relative path to libraries used while building is still a security issue. An absolute path to the location where libraries are installed is not, but |
Can you give an example of that? The VirtualBox case doesn't count, because that relies on hard-links to set_id, and if you're using set_id it's your own responsibility to take care of things. |
Adding a package-specific path like
|
Uh, it looks like I ignited this discussion, so I think I should make a couple of clearer comments:
In summary I'd say: in the grand final plan, rpaths are not ok and I don't plan to ship any packaged binaries with them. However, they are mostly used to ease the setup of user-level playgrounds. (Probably) this should be handled together by rust and rustpkg2 and requires a bit of careful design in the latter. I'm still far from coming up with a proper proposal for this, but I surely would contribute to rustpkg2 plans. |
Every exploit I am aware of involves one of:
Just stop doing those things and you'll be fine. Also note that not using rpath means shipping 50 different hashed versions of libstd-*.so in /usr/lib itself, which frankly is more likely to upset distros than leaving them under /usr/lib/rust. |
It doesn't need to be a world-writable directory, it just has to be writable by an unprivileged user. Since Rust is setting paths relative to the build directory without any knowledge about the final destination, I don't think it is unrealistic for insecure rpaths to be created.
It's Rust setting the rpath, not the programmer. Insecure defaults are not the fault of the programmer or package. It's not a matter of having people "stop doing those things" as I stated in a previous reply.
There's no reason Rust would have to do this. One shared object and one archive are required to support dynamic linking, link-time optimization and static linking - that's two files for each library, not fifty. Any other copies will be for cross-compilation and don't need to be available on the host itself. New directories can be added to the system's library search path by a package via |
For one version of a library. But consider, once rust gets out of the "recompile every day" stage: At the API level, each library can reasonably be expected to have 3 "live" versions: oldstable, stable, and testing. There is no correlation between which level of a package is used in any particular installation. So if: Ideally, for a full build of a single package containing both foo and bar, the process is:
If foo and bar are separate packages, the process is much simplified; you can reasonably expect libfoo to be completely installed to the system before libbar begins.
Finally, while user-level playground is indeed a completely different story, I am worried that attempts to curb the use of rpath for system-level problems will lead to completely breaking it for user-level. Far better to have one solution that works for both system and user, with a small set of changes for a few rare setuid programs, than to have to maintain two completely different and incompatible solutions, one for system installs and one for user ones. |
Static linking is already the default, and I don't really see why dynamic linking is useful at a user level. It's simply a non-issue in my opinion. Dynamic linking with Rust is only useful as a way to reduce duplication between packages. There's no ABI compatibility at all right now (std::reflect) and there won't be for idiomatic libraries that aren't doing contortions to support it. |
Because static linking doesn't work for my crate, which has moderately nasty C dependencies, unless I force all the complexity out to every single caller.
Nope. It's also a form of encapsulating away internal dependencies. Unless rust's #[link] becomes able to execute arbitrary scripts, rlib just can't do it. |
Concerns have been raised about using absolute rpaths in rust-lang#11746, and this is the first step towards not relying on rpaths at all. The only current use case for an absolute rpath is when a non-installed rust builds an executable that then moves from is built location. The relative rpath back to libstd and absolute rpath to the installation directory still remain (CFG_PREFIX). Closes rust-lang#11746 Rebasing of rust-lang#12754
Hi guys, I am pretty new using rust. I am wrapping a C library to rust in Linux64 bit. I am trying to set the rpath like in gcc -Wl,-rpath,the path. But in rust there is not a clear documentation about that, the -C rpath option is doing nothing. I have different versions for the library so I need the rpath variable and LD_LIBRARY_PATH is not an option because I have several executables and th shared objects are in different path. I don't use cargo either because my software runs over CMake so I am using rustc directly. |
Followup to #5219. Per that issue rpaths are frowned on by linux distros. Absolute rpaths are supposed to be worse than relative rpaths (I'm not clear on why at the moment), and they are probably relatively easy to get rid of. Nominating.
The text was updated successfully, but these errors were encountered: