[PATCH 1/1] elf: Canonicalize $ORIGIN in an explicit ld.so invocation [BZ #25263]

Geoffrey Thomas geofft@ldpreload.com
Fri Feb 28 19:02:00 GMT 2025


On Thu, Feb 27, 2025, at 3:26 PM, Adhemerval Zanella Netto wrote:
> Although this change solves the LD_TRACE_LOADED_OBJECTS=1 (ldd) issue, I
> think it still misses the underlying issue for the case user want to also 
> run the binary with a direct loader invocation (as Florian has hinted on 
> comment #4).
>
> For instance, with this testcase (similar to what electron is doing from
> the bug report):
>
> $ cat test/main.c
> int main (int argc, char *argv[]) { return 0; }
> $ cat test/lib1.c
> int foo (void) { return 42; }
> tst-bz25263 $ mkdir test && cd test
> test $ gcc -Wall -shared -Wl,-soname,lib1.so lib1.c -o lib1.so
> test $ gcc -no-pie -Wall main.c -o main -Wl,-rpath,\$ORIGIN -L`pwd` 
> -Wl,-no-as-needed -l1
> test $ gcc -no-pie -Wall main.c -o main-hcp 
> -Wl,-rpath,\$ORIGIN:$GLIBCBUILDDIR 
> -Wl,-dynamic-linker,$GLIBCBUILDDIR/elf/ld.so -L`pwd` -Wl,-no-as-needed 
> -l1
> main $ cd ..
> $ ln -s test/main main
> $ ln -s test/main-hcp main-hcp
>
> So 'main' is a binary without just one RUNPATH with $ORIGIN, while 'main-hcp'
> is binary that will use a built glibc (along with the RUNPATH).
>
> Checking the library path resolution for both cases:
>
> $ LD_DEBUG=libs ./main-hcp
>    3151277:     find library=lib1.so [0]; searching
>    3151277:      search 
> path=$GLIBCBUILDDIR/tst-bz25263/test/glibc-hwcaps/x86-64-v3:/home/azanella/Projects/glibc/build/
> x86_64-linux-gnu-work/tst-bz25263/test/glibc-hwcaps/x86-64-v2:$GLIBCBUILDDIR/tst-bz25263/test:$GLIBCBUILDDIR/glibc-hwcaps/x86-64-v3:$GLIBCBUILDDIR/glibc-hwcaps/x86-64-v2:$GLIBCBUILDDIR 
>          (RUNPATH from file ./main-hcp)
>    3151277:       trying 
> file=$GLIBCBUILDDIR/tst-bz25263/test/glibc-hwcaps/x86-64-v3/lib1.so
>    3151277:       trying 
> file=$GLIBCBUILDDIR/tst-bz25263/test/glibc-hwcaps/x86-64-v2/lib1.so
>    3151277:       trying file=$GLIBCBUILDDIR/tst-bz25263/test/lib1.so
>
> LD_DEBUG=libs $GLIBCBUILDDIR/elf/ld.so --library-path $GLIBCBUILDDIR 
> ./main
>    3151286:	find library=lib1.so [0]; searching
>    3151286:	 search 
> path=$GLIBCBUILDDIR/glibc-hwcaps/x86-64-v3:$GLIBCBUILDDIR/glibc-hwcaps/x86-64-v2:$GLIBCBUILDDIR		(--library-path)
>    3151286:	  trying file=$GLIBCBUILDDIR/glibc-hwcaps/x86-64-v3/lib1.so
>    3151286:	  trying file=$GLIBCBUILDDIR/glibc-hwcaps/x86-64-v2/lib1.so
>    3151286:	  trying file=$GLIBCBUILDDIR/lib1.so
>    3151286:	 search 
> path=$GLIBCBUILDDIR/tst-bz25263/./glibc-hwcaps/x86-64-v3:$GLIBCBUILDDIR/tst-bz25263/./glibc-hwcaps/x86-64-v2:$GLIBCBUILDDIR/tst-bz25263/.		(RUNPATH 
> from file ./main)
>    3151286:	  trying 
> file=$GLIBCBUILDDIR/tst-bz25263/./glibc-hwcaps/x86-64-v3/lib1.so
>    3151286:	  trying 
> file=$GLIBCBUILDDIR/tst-bz25263/./glibc-hwcaps/x86-64-v2/lib1.so
>    3151286:	  trying file=$GLIBCBUILDDIR/tst-bz25263/./lib1.so
>    3151286:	 search cache=/etc/ld.so.cache
>    3151286:	 search 
> path=/lib64/glibc-hwcaps/x86-64-v3:/lib64/glibc-hwcaps/x86-64-v2:/lib64:/usr/lib64/glibc-hwcaps/x86-64-v3:/usr/lib64/glibc-hwcaps/x86-64-v2:/usr/lib64		(system 
> search path)
>    3151286:	  trying file=/lib64/glibc-hwcaps/x86-64-v3/lib1.so
>    3151286:	  trying file=/lib64/glibc-hwcaps/x86-64-v2/lib1.so
>    3151286:	  trying file=/lib64/lib1.so
>    3151286:	  trying file=/usr/lib64/glibc-hwcaps/x86-64-v3/lib1.so
>    3151286:	  trying file=/usr/lib64/glibc-hwcaps/x86-64-v2/lib1.so
>    3151286:	  trying file=/usr/lib64/lib1.so
>
> You can see that if the binary is not issued directly by the loader 
> (main-hcp),
> it will have the full realpath on the search path 
> (GLIBCBUILDDIR/tst-bz25263/test);
> different that binary issued by the loader which is has the current 
> directory
> (GLIBCBUILDDIR/tst-bz25263).

This is with my patch? Directly on top of glibc-2.41 (commit db71c940
from github.com/geofft/glibc), with a checkout at /glibc and so
GLIBCBUILDDIR=/glibc/build, I get

[root@nixos:/glibc/build/tst-bz25263]# ls -l
total 0
lrwxr-xr-x 1 root root   9 Feb 28 13:37 main -> test/main
lrwxr-xr-x 1 root root  13 Feb 28 13:37 main-hcp -> test/main-hcp
drwxr-xr-x 7 root root 224 Feb 28 13:37 test
[root@nixos:/glibc/build/tst-bz25263]# readelf -d main | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [lib1.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
[root@nixos:/glibc/build/tst-bz25263]# LD_DEBUG=libs /glibc/build/elf/ld.so --library-path /glibc/build ./main
     49044:     find library=lib1.so [0]; searching
     49044:      search path=/glibc/build               (--library-path)
     49044:       trying file=/glibc/build/lib1.so
     49044:      search path=/glibc/build/tst-bz25263/test:/nix/store/6j2qcdi8axcl91v08blc3vjn39y117z3-shell/lib:/nix/store/q6kvdfhlp251n8rx183lg1n245kwg6m8-glibc-2.39-52/lib:/nix/store/fxh2cg0sfgygfya6qjr11gzj4sbjx0h9-gcc-13.2.0-lib/lib         (RUNPATH from file ./main)
     49044:       trying file=/glibc/build/tst-bz25263/test/lib1.so
     49044:
     49044:     find library=libc.so.6 [0]; searching
     49044:      search path=/glibc/build               (--library-path)
     49044:       trying file=/glibc/build/libc.so.6
[...]

which, if I'm following correctly, is the fixed behavior.

As expected it does not work with a copy instead of a symlink:

[root@nixos:/glibc/build/tst-bz25263]# cp test/main maincopy
[root@nixos:/glibc/build/tst-bz25263]# LD_DEBUG=libs /glibc/build/elf/ld.so --library-path /glibc/build ./maincopy
     49073:     find library=lib1.so [0]; searching
     49073:      search path=/glibc/build               (--library-path)
     49073:       trying file=/glibc/build/lib1.so
     49073:      search path=/glibc/build/tst-bz25263:/nix/store/6j2qcdi8axcl91v08blc3vjn39y117z3-shell/lib:/nix/store/q6kvdfhlp251n8rx183lg1n245kwg6m8-glibc-2.39-52/lib:/nix/store/fxh2cg0sfgygfya6qjr11gzj4sbjx0h9-gcc-13.2.0-lib/lib              (RUNPATH from file ./maincopy)
     49073:       trying file=/glibc/build/tst-bz25263/lib1.so
     49073:       trying file=/nix/store/6j2qcdi8axcl91v08blc3vjn39y117z3-shell/lib/lib1.so
     49073:       trying file=/nix/store/q6kvdfhlp251n8rx183lg1n245kwg6m8-glibc-2.39-52/lib/lib1.so
     49073:       trying file=/nix/store/fxh2cg0sfgygfya6qjr11gzj4sbjx0h9-gcc-13.2.0-lib/lib/lib1.so
     49073:      search cache=/root/etc/ld.so.cache
     49073:      search path=/root/lib          (system search path)
     49073:       trying file=/root/lib/lib1.so
     49073:
./maincopy: error while loading shared libraries: lib1.so: cannot open shared object file: No such file or directory

What commit and OS and arch are you on? (It's possible I'm confusing 
myself by using NixOS, maybe.)

-- 
Geoffrey Thomas
geofft@ldpreload.com


More information about the Libc-alpha mailing list