mesonbuild / meson

The Meson Build System
http://mesonbuild.com
Apache License 2.0
5.51k stars 1.6k forks source link

Meson RPATH munging can yield libraries that break ldconfig on Linux #4685

Open pkgw opened 5 years ago

pkgw commented 5 years ago

(This issue is inspired by conda-forge/glib-feedstock#40; see also NixOS/patchelf#44.)

I have found that in a corner case, Meson's ELF RPATH munging code can lead to installed shared libraries that are legal but confuse some tools that are not so smart about the ELF standard. Unfortunately one of those tools is ldconfig, and the breakage can lead it to create junk files that confuse other tools.

The problem occurs when a shared library is installed on Linux and its install_rpath setting is the empty string (which appears to be the default). This triggers a codepath that removes the RPATH entry altogether. Unfortunately, as best I can take away from NixOS/patchelf#44, the way it does this rearranges the ELF file that confuses certain naive tools. For instance, chrpath is one of these, and you can get a binary for which readelf -d reports a good RPATH but chrpath -l reports, essentially, garbage.

Unfortunately, another one of these naive tools is ldconfig. It reads the SONAME string from ELF libraries to figure out what symlink name to create, and I ran into an example where ldconfig decided to create a file named /usr/lib/\n, containing a newline character. Unsurprisingly, the existence of such a file breaks all sorts of stuff.

This is really ldconfig's fault, but the failure mode can be very hard to track down. Based on what I've seen, I think maybe Meson should look into alternative ways to implement remove_rpath_entry that keep ldconfig happy. Reading that file, it seems as if there are other corner cases that have caused problems in the past, so a larger-bore solution might be worth considering too.

pkgw commented 5 years ago

If you want an example, the shared libraries in this conda package demonstrate the net effect:

$ readelf -d libglib-2.0.so |grep RPATH
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/.]

$ chrpath -l libglib-2.0.so
libglib-2.0.so: RPATH=scaped

$ ldconfig -n $(pwd)
ldconfig: file /home/peter/sw/conda/glib-feedstock/tmp2/lib/libgthread-2.0.so.0 is truncated
ldconfig: file /home/peter/sw/conda/glib-feedstock/tmp2/lib/libgthread-2.0.so.0.5800.2 is truncated
ldconfig: file /home/peter/sw/conda/glib-feedstock/tmp2/lib/libgthread-2.0.so is truncated
ldconfig: /home/peter/sw/conda/glib-feedstock/tmp2/lib/ is not a symbolic link

$ ls -l
total 4116
lrwxrwxrwx. 1 peter peter      22 Dec 28 21:10 ''$'\n' -> libgio-2.0.so.0.5800.2
[...]
jpakkane commented 5 years ago

Originally we did not remove the rpath entry but just left it empty. This is against distro packaging standards where rpath entries, even if empty, are forbidden. Any use of rpath must be documented and it can only be used for specific things (accessing internal libraries with an unstable ABI).

Thus any change or fix done to this must preserve the removing behaviour.

pkgw commented 5 years ago

@jpakkane Relatedly ... it's surprising to me that this problem doesn't crop up more frequently. As I currently understand things, the changes that happen when RPATHs are removed can very easily lead to ldconfig problems, which you would think would be quite noticeable. Maybe I'm just too used to the Conda world, where everything is built with rpaths. In most use cases, do those RPATH entries never get added in the first place?

jpakkane commented 5 years ago

Rpath is not added if the ELF file in question does not link to any built shared libraries. As far as these things go, we have not had any bugs filed about broken rpaths like these and Meson is used by a fair chunk of the core infrastructure so one would imagine they would show up fairly quickly.