JonathonReinhart / staticx

Create static executable from dynamic executable
https://staticx.readthedocs.io/
Other
345 stars 37 forks source link

libnssfix fails to build under Ubuntu 22.04 #245

Closed JonathonReinhart closed 1 year ago

JonathonReinhart commented 1 year ago

Noted here: https://github.com/JonathonReinhart/staticx/pull/194#issuecomment-1624289769

gcc -o scons_build/debug/libnssfix/libnssfix.so -Wl,--fatal-warnings -Wl,--no-as-needed -nostdlib -Wl,--no-undefined -shared scons_build/debug/libnssfix/nssfix.os -Lscons_build/debug/lib scons_build/debug/libnssfix/libc.so.6 -lnss_dns -lnss_files
/bin/ld: cannot find -lnss_dns: No such file or directory
/bin/ld: cannot find -lnss_files: No such file or directory
JonathonReinhart commented 1 year ago

The problem is missing symlinks:

In ubuntu 22:04, there is no libnss_files.so symlink 😦

jreinhart@cbc4e6bb2b96:~/gitrepos/staticx$ ls -l /usr/lib/x86_64-linux-gnu/libnss*
lrwxrwxrwx 1 root root    40 Jul  6  2022 /usr/lib/x86_64-linux-gnu/libnss_compat.so -> /lib/x86_64-linux-gnu/libnss_compat.so.2
-rw-r--r-- 1 root root 44024 Jul  6  2022 /usr/lib/x86_64-linux-gnu/libnss_compat.so.2
-rw-r--r-- 1 root root 14352 Jul  6  2022 /usr/lib/x86_64-linux-gnu/libnss_dns.so.2
-rw-r--r-- 1 root root 14352 Jul  6  2022 /usr/lib/x86_64-linux-gnu/libnss_files.so.2
lrwxrwxrwx 1 root root    40 Jul  6  2022 /usr/lib/x86_64-linux-gnu/libnss_hesiod.so -> /lib/x86_64-linux-gnu/libnss_hesiod.so.2
-rw-r--r-- 1 root root 27160 Jul  6  2022 /usr/lib/x86_64-linux-gnu/libnss_hesiod.so.2

Note that there is no libnss_dns.so or libnss_files.so symlink. Hmm.

It's also a little suspicious that both libnss_dns.so.2 and libnss_files.so.2 are exactly the same size:

-rw-r--r-- 1 root root 14352 Jul  6  2022 /usr/lib/x86_64-linux-gnu/libnss_dns.so.2
-rw-r--r-- 1 root root 14352 Jul  6  2022 /usr/lib/x86_64-linux-gnu/libnss_files.so.2
JonathonReinhart commented 1 year ago

As I suspected, it appears that libnss_dns.so.2 and libnss_files.so.2 are stubs (export no symbols). The real implementation is moved into libc as of GLIBC 2.34.

Relevant changes:

Initial thoughts

If libnss_files/libnss_dns are built into libc, we can just leave these out of the link.

How do we detect this?

JonathonReinhart commented 1 year ago

Reopening as #255 is incomplete. See https://github.com/JonathonReinhart/staticx/pull/255#issuecomment-1630120893.

It needs to provide runtime libnssfix detection, not just build-time.

JonathonReinhart commented 1 year ago

I'm yanking staticx 0.14.0 from PyPI, because what's there (libnssfix.so not linking against libnss_files, causing dlopen of system lib) is arguably worse (odd app runtime behavior / crash) than 0.13.9 (which works on glibc>=2.34 because libnssfix.so has NEEDED of the soname libnss_files.so.2), so the dependencies are picked up.

We just can't build staticx on glibc>=2.34 (as the title ostensibly states).

JonathonReinhart commented 1 year ago

My initial thought was:

It needs to provide runtime libnssfix detection, not just build-time.

Meaning, when staticx is run, it needs to determine if the glibc (against which the given app was linked) has nss_files and nss_dns builtin -- not the GLIBC used to build staticx.


But based on my test (staticx 0.13.9 works on ubuntu 22.04):

$ ldd /usr/local/lib/python3.10/dist-packages/staticx/assets/release/libnssfix.so
        linux-vdso.so.1 (0x00007ffec95a9000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f982aa84000)
        libnss_files.so.2 => /lib/x86_64-linux-gnu/libnss_files.so.2 (0x00007f982aa7f000)
        libnss_dns.so.2 => /lib/x86_64-linux-gnu/libnss_dns.so.2 (0x00007f982aa7a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f982acb6000)

the stubs are present and don't hurt anything.

We just need to get the NEEDED tags on libnssfix.so with the SONAME (including .2), like they always were:

$ readelf --dynamic /usr/local/lib/python3.10/dist-packages/staticx/assets/release/libnssfix.so | grep '(NEEDED)'
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libnss_files.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libnss_dns.so.2]

How do we best achieve this in our scons build system? (Keep in mind that -lnss_files does not work because of the missing symlinks).

Ideas: