Patchelf use in Nix/NixOS

Hello,

Today, I encountered some criticism about Nix, specifically concerning its reliance on patchelf.

My personal understanding is that patchelf is generally used with pre-built software that is designed for a traditional Linux Filesystem Hierarchy Standard (FHS) setup. However, Nix operates differently, as each package is isolated within its own /nix/store/... directory.

patchelf is used in many places in Nix. It’s very difficult to estimate how much since it’s used at the same time in pkgs but also by builders in pkgs/build-support.

I’m initiating this discussion to clarify two points: Firstly, is my understanding of patchelf’s role in the Nix ecosystem correct? Secondly, I’m curious whether patchelf is employed for other purposes within Nix environments.

Could you please share some insights?

Thanks.

2 Likes

I think patchelf --shrink-rpath is done in every fixupPhase unless disabled, right?

To quote patchelf(1):

   --shrink-rpath
         Remove from the DT_RUNPATH or DT_RPATH all directories that do not contain a library referenced by DT_NEEDED fields of the executable or library.

         For instance, if an executable references one library libfoo.so, has an RPATH "/lib:/usr/lib:/foo/lib", and libfoo.so can only be found in /foo/lib, then the new RPATH will be "/foo/lib".

(Relevant code is in pkgs/development/tools/misc/patchelf/setup-hook.sh).

It’s worth noting that patchelf isn’t blindly modifying binaries. It’s just rewriting some metadata, namely rpath and the path to the dynamic linker.

It’s actually common for other distros to use patchelf in their packages too. People are just much less aware of it. That’s because even among FHS distros, authors of different software make different assumptions about paths. Here’s a search result for “patchelf” in the Debian repositories, for example.

https://codesearch.debian.net/search?q=patchelf&literal=1

Personally, I’m not aware of any downside to using patchelf. Patched binaries work just fine. It’s a common criticism, but it might be a knee-jerk reaction.

It might contribute to store bloat, if the store contains an unpatched downloaded binary and the patched binary.

It could also make things difficult for software integrity checks, either for applications that verify their own code or for external audits.

The biggest current problem of patchelf is that it’s unmaintained, and its state is quite problematic.

A rewrite in Rust using a proper ELF Rust library seems an appropriate side project for someone too bored (or I will take care of it once I exhaust my current list).

Thank you all for your information. Greatly appreciated.

I agree that patchelf’s use on source-based packages is a sign of a workaround in nixpkgs.

The worst part of it is that it patches binaries after they are built. Sometimes that breaks the binaries. The breakages are never easy to debug (and nixpkgs is already different enough from FHS distributions). That’s one of the reasons why nixpkgs does not use the latest version of patchelf.

--shrink-rpath is a good example of a workaround that should belong somewhere else. Ideally the linker (like ld) should provide an equivalent of RPATH shrinking (just like --as-needed shrinks libraries) to build the binaries in a way you expect them to be.