Skip to content
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

Ignore the case where a library symlink has the same basename as its target #225

Merged
merged 3 commits into from
Aug 7, 2022

Conversation

JonathonReinhart
Copy link
Owner

@JonathonReinhart JonathonReinhart commented Aug 6, 2022

Fixes #223

Thanks @liujin1993 for helping to track this down.

Background:
The archive contains a flat collection of all dependent libraries.
We also add symlinks as necessary for library versions
(e.g. libfoo.so.1 -> libfoo.so.1.2 -> libfoo.so.1.2.3).

Problem:
The code assumed that a library symlink would only ever point to a
library (or another symlink) with a different basename.  It did not
consider the case where a symlink would point to a library with the
same name (but in a different directory). If we would add such a
symlink in our flat archive directory, it would be self-referential.
The actual crash was a check in the staticx python code, which prevented
ELOOP (Too many levels of symbolic links) at runtime.

Solution:
Skip the creation of any symlinks with the same name as their target, as
those are pointless in our flat directory.
@JonathonReinhart
Copy link
Owner Author

JonathonReinhart commented Aug 6, 2022

Unfortunately this is crashing on Ubuntu:22.04 (the environment referenced in #223), although I think for an unrelated reason:

$ scuba --root --image ubuntu:22.04
# apt update && apt install -y python3-pip patchelf pyelftools

Building:

# python3 -m staticx --debug $(which date) date.sx
INFO:root:Running StaticX version 0.13.6
INFO:root:Libraries:
INFO:root:  elftools: 0.28
DEBUG:root:External tools:
INFO:root:  ldd: /usr/bin/ldd: ldd (Ubuntu GLIBC 2.35-0ubuntu3) 2.35
INFO:root:  objcopy: /usr/bin/objcopy: GNU objcopy (GNU Binutils for Ubuntu) 2.38
INFO:root:  strip: /usr/bin/strip: GNU strip (GNU Binutils for Ubuntu) 2.38
INFO:root:  patchelf: /usr/bin/patchelf: patchelf 0.14.3
DEBUG:root:Arguments:
DEBUG:root:  prog:      '/usr/bin/date'
DEBUG:root:  output:    'date.sx'
DEBUG:root:  libs:      None
DEBUG:root:  strip:     False
DEBUG:root:  compress:  True
DEBUG:root:  debug:     True
INFO:root:Using XZ BCJ filter FILTER_X86
DEBUG:root:Bootloader: bootloader version <unknown> compiled Mar  2 2022 at 00:49:56 by gcc version 10.2.1 20210110
INFO:root:Program interpreter: /lib64/ld-linux-x86-64.so.2
DEBUG:root:Running ['patchelf', '--remove-rpath', '/tmp/staticx-prog-tvonkngm']
DEBUG:root:Running ['patchelf', '--set-interpreter', 'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii', '--set-rpath', 'rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr', '--force-rpath', '/tmp/staticx-prog-tvonkngm']
DEBUG:root:Running ['patchelf', '--no-default-lib', '/tmp/staticx-prog-tvonkngm']
DEBUG:root:Program linked with GLIBC: Found libc.so.6 GLIBC_2.14
DEBUG:root:Running ['patchelf', '--add-needed', 'libnssfix.so', '/tmp/staticx-prog-tvonkngm']
INFO:root:Adding libnssfix.so
DEBUG:root:Running ['ldd', '/tmp/libnssfix-u8hn6pgh.so']
DEBUG:root:Ignoring synthetic library: linux-vdso.so.1
INFO:root:Processing library libc.so.6 (/lib/x86_64-linux-gnu/libc.so.6)
INFO:root:Adding /lib/x86_64-linux-gnu/libc.so.6 as libc.so.6
INFO:root:Processing library libnss_dns.so.2 (/lib/x86_64-linux-gnu/libnss_dns.so.2)
INFO:root:Adding /lib/x86_64-linux-gnu/libnss_dns.so.2 as libnss_dns.so.2
INFO:root:Processing library libnss_files.so.2 (/lib/x86_64-linux-gnu/libnss_files.so.2)
INFO:root:Adding /lib/x86_64-linux-gnu/libnss_files.so.2 as libnss_files.so.2
INFO:root:Processing library ld-linux-x86-64.so.2 (/lib64/ld-linux-x86-64.so.2)
INFO:root:Adding /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 as ld-linux-x86-64.so.2
INFO:root:Adding /tmp/staticx-prog-tvonkngm as date
DEBUG:root:Running ['ldd', '/usr/bin/date']
DEBUG:root:Ignoring synthetic library: linux-vdso.so.1
DEBUG:root:Running ['objcopy', '--add-section', '.staticx.archive=/tmp/staticx-archive-dfdk486k.tar', '/tmp/staticx-output-e6daig41']

Running:

# ./date.sx 
STATICX [4854]: bootloader version <unknown>
STATICX [4854]: compiled Mar  2 2022 at 00:49:56 by gcc version 10.2.1 20210110
STATICX [4854]: Temporary bundle dir: /tmp/staticx-6xnm6e
STATICX [4854]: Found archive at offset 0xF5F51 (852976 bytes)
STATICX [4854]: Archive is XZ-compressed
STATICX [4854]: Extracting tar archive to /tmp/staticx-6xnm6e
Segmentation fault (core dumped)

Inspecting

# file date.sx 
date.sx: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=49bce3675fdefe26776f3ffc9c075eedacfa4056, for GNU/Linux 3.2.0, with debug_info, not stripped

Running under GDB:

# gdb --args ./date.sx
GNU gdb (Ubuntu 12.0.90-0ubuntu1) 12.0.90
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./date.sx...
(gdb) r
Starting program: /home/jreinhart/gitrepos/staticx/date.sx 
warning: Error disabling address space randomization: Operation not permitted
STATICX [4865]: bootloader version <unknown>
STATICX [4865]: compiled Mar  2 2022 at 00:49:56 by gcc version 10.2.1 20210110
STATICX [4865]: Temporary bundle dir: /tmp/staticx-aivT11
STATICX [4865]: Found archive at offset 0xF5F51 (852976 bytes)
STATICX [4865]: Archive is XZ-compressed
STATICX [4865]: Extracting tar archive to /tmp/staticx-aivT11
warning: File "/usr/lib/x86_64-linux-gnu/libthread_db.so.1" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
	add-auto-load-safe-path /usr/lib/x86_64-linux-gnu/libthread_db.so.1
line to your configuration file "/root/.config/gdb/gdbinit".
To completely disable this security protection add
	set auto-load safe-path /
line to your configuration file "/root/.config/gdb/gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual.  E.g., run from the shell:
	info "(gdb)Auto-loading safe path"
warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.

Program received signal SIGSEGV, Segmentation fault.
0x00007f02c4473ef4 in __GI___nss_readline (poffset=<optimized out>, len=<optimized out>, buf=<optimized out>, fp=<optimized out>) at ../include/ctype.h:41
41	../include/ctype.h: No such file or directory.
(gdb) bt
#0  0x00007f02c4473ef4 in __GI___nss_readline (poffset=<optimized out>, len=<optimized out>, buf=<optimized out>, fp=<optimized out>) at ../include/ctype.h:41
#1  __GI___nss_readline (fp=fp@entry=0x7f02c41e32a0, buf=buf@entry=0x751dd0 "root:x:0:0:root:/root:/bin/bash\n", len=len@entry=1024, poffset=poffset@entry=0x7ffcbf6a4240) at ./nss/nss_readline.c:26
#2  0x00007f02c4479a05 in internal_getent (errnop=<optimized out>, buflen=<optimized out>, buffer=<optimized out>, result=<optimized out>, stream=<optimized out>) at nss_files/files-XXX.c:124
#3  __GI__nss_files_getpwnam_r (name=0x751cc1 "root", result=0x4e8a60 <resbuf>, buffer=0x751dd0 "root:x:0:0:root:/root:/bin/bash\n", buflen=1024, errnop=0x7492c0) at nss_files/files-pwd.c:33
#4  0x000000000045d833 in getpwnam_r ()
#5  0x000000000045d414 in getpwnam ()
#6  0x0000000000405a23 in th_get_uid (t=0x751ba0) at libtar/decode.c:49
#7  0x0000000000404a01 in th_print_long_ls (t=0x751ba0, f=0x4e5160 <_IO_2_1_stderr_>) at libtar/output.c:51
#8  0x00000000004047e8 in tar_extract_all (t=0x751ba0, prefix=0x74a670 "/tmp/staticx-aivT11") at libtar/extract.c:552
#9  0x00000000004027ea in extract_archive (dest_path=0x74a670 "/tmp/staticx-aivT11") at bootloader/extract.c:229
#10 0x0000000000403722 in main (argc=1, argv=0x7ffcbf6a5648) at bootloader/main.c:449
(gdb) info proc  
all       cmdline   cwd       exe       files     mappings  stat      status    
(gdb) info proc mappings 
process 4865
Mapped address spaces:

          Start Addr           End Addr       Size     Offset  Perms  objfile
            0x400000           0x401000     0x1000        0x0  r--p   /home/jreinhart/gitrepos/staticx/date.sx
            0x401000           0x4b5000    0xb4000     0x1000  r-xp   /home/jreinhart/gitrepos/staticx/date.sx
            0x4b5000           0x4e1000    0x2c000    0xb5000  r--p   /home/jreinhart/gitrepos/staticx/date.sx
            0x4e1000           0x4e5000     0x4000    0xe0000  r--p   /home/jreinhart/gitrepos/staticx/date.sx
            0x4e5000           0x4e8000     0x3000    0xe4000  rw-p   /home/jreinhart/gitrepos/staticx/date.sx
            0x4e8000           0x4ea000     0x2000        0x0  rw-p   
            0x748000           0x76b000    0x23000        0x0  rw-p   [heap]
      0x7f02c41e3000     0x7f02c42e3000   0x100000        0x0  rw-p   
      0x7f02c42e3000     0x7f02c42e5000     0x2000        0x0  r--p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7f02c42e5000     0x7f02c430f000    0x2a000     0x2000  r-xp   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7f02c430f000     0x7f02c431a000     0xb000    0x2c000  r--p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7f02c431a000     0x7f02c431b000     0x1000    0x37000  ---p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7f02c431b000     0x7f02c431d000     0x2000    0x37000  r--p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7f02c431d000     0x7f02c431f000     0x2000    0x39000  rw-p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7f02c431f000     0x7f02c4347000    0x28000        0x0  r--p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7f02c4347000     0x7f02c44dc000   0x195000    0x28000  r-xp   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7f02c44dc000     0x7f02c4534000    0x58000   0x1bd000  r--p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7f02c4534000     0x7f02c4538000     0x4000   0x214000  r--p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7f02c4538000     0x7f02c453a000     0x2000   0x218000  rw-p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7f02c453a000     0x7f02c4547000     0xd000        0x0  rw-p   
      0x7f02c4547000     0x7f02c4548000     0x1000        0x0  r--p   /usr/lib/x86_64-linux-gnu/libnss_files.so.2
      0x7f02c4548000     0x7f02c4549000     0x1000     0x1000  r-xp   /usr/lib/x86_64-linux-gnu/libnss_files.so.2
      0x7f02c4549000     0x7f02c454a000     0x1000     0x2000  r--p   /usr/lib/x86_64-linux-gnu/libnss_files.so.2
      0x7f02c454a000     0x7f02c454b000     0x1000     0x2000  r--p   /usr/lib/x86_64-linux-gnu/libnss_files.so.2
      0x7f02c454b000     0x7f02c454c000     0x1000     0x3000  rw-p   /usr/lib/x86_64-linux-gnu/libnss_files.so.2
      0x7f02c454f000     0x7f02c4d50000   0x801000        0x0  rw-p   
      0x7f02c4d50000     0x7f02c4f2e000   0x1de000        0x0  r--s   /home/jreinhart/gitrepos/staticx/date.sx
      0x7ffcbf686000     0x7ffcbf6a7000    0x21000        0x0  rw-p   [stack]
      0x7ffcbf6f0000     0x7ffcbf6f4000     0x4000        0x0  r--p   [vvar]
      0x7ffcbf6f4000     0x7ffcbf6f6000     0x2000        0x0  r-xp   [vdso]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0  r-xp   [vsyscall]

Analysis:

  • Everything went find until getpwnam_r() (0x45d833 in static libc) called __GI__nss_files_getpwnam_r (0x7f02c4479980) - That function should not be called:
    • It is in /usr/lib/x86_64-linux-gnu/libc.so.6 (host library ⚠️)
    • The bootloader should be static!
    • Its name includes NSS which should not be involved in this static bootloader

Conclusions:

  • I think this bootloader was statically-linked with glibc, not musl
  • Even though the bootloader is statically linked, it still dynamically loads NSS libraries (which depend on libc.so)
    • So now we have two libcs loaded!

Should pay more attention to this warning:

/bin/ld: scons_build/release/lib/libtar.a(decode.o): in function `th_get_uid':
decode.c:(.text+0x88): warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

So what does this mean? Options:

  • Forbid glibc -- require staticx
  • Remove calls to getgrgid, getgrnam, getpwnam, getgwuid in libtar
    • Can we turn this warning into an error?

@JonathonReinhart
Copy link
Owner Author

After rebuilding the bootloader with musl, The test was successful.

This proves that the new crash is unrelated to this fix. I will move the new crash to its own issue.

@JonathonReinhart JonathonReinhart changed the title WIP Fix library self-referential symlink Fix library self-referential symlink Aug 7, 2022
@JonathonReinhart JonathonReinhart changed the title Fix library self-referential symlink Ignore the case where a library symlink has the same basename as its target Aug 7, 2022
@JonathonReinhart JonathonReinhart merged commit cbec08b into master Aug 7, 2022
@JonathonReinhart JonathonReinhart deleted the 223-libname-symlink branch August 7, 2022 04:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

InternalError with Python 3.10: libname absent from _added_libs but library is present
1 participant