Reputation: 1325
I'm trying to dynamically load a library from within a chroot. The said library depends on glibc and its version is different from my host (host has 2.26, chroot has 2.23).
Is there a way to achieve that?
Here is what I tried:
$ curl http://cdimage.ubuntu.com/ubuntu-base/releases/16.04/release/ubuntu-base-16.04-core-amd64.tar.gz | tar -C ubuntu -xz
#include <unistd.h>
#include <dlfcn.h>
int main(int argc, char *argv[])
{
chdir("ubuntu");
chroot(".");
// 1. This will fail
dlopen("libpthread.so.0", RTLD_NOW);
// 2. This will crash
dlmopen(LM_ID_NEWLM, "libpthread.so.0", RTLD_NOW);
return 0;
}
Obviously fails because there is a glibc mismatch:
/lib/x86_64-linux-gnu/libpthread.so.0: symbol __libc_dl_error_tsd, version GLIBC_PRIVATE not defined in file libc.so.6 with link time reference
Crashes with the following output from valgrind:
==19923== Process terminating with default action of signal 4 (SIGILL): dumping core
==19923== Illegal opcode at address 0x401D41C
==19923== at 0x401D41C: ??? (in /usr/lib/ld-2.26.so)
==19923== by 0x4013932: dl_open_worker (in /usr/lib/ld-2.26.so)
==19923== by 0x516EB63: _dl_catch_error (in /usr/lib/libc-2.26.so)
==19923== by 0x4013279: _dl_open (in /usr/lib/ld-2.26.so)
==19923== by 0x4E3A8CF: ??? (in /usr/lib/libdl-2.26.so)
==19923== by 0x516EB63: _dl_catch_error (in /usr/lib/libc-2.26.so)
==19923== by 0x4E3A586: ??? (in /usr/lib/libdl-2.26.so)
==19923== by 0x4E3A9B6: dlmopen (in /usr/lib/libdl-2.26.so)
Upvotes: 0
Views: 1839
Reputation: 213937
You are trying to bring two separate versions of GLIBC into a single process.
The reasons this does not work are explained here:
you need to know that glibc consists of many pieces (200+ shared libraries) which all must match. One of the pieces is
ld-linux.so.2
, and it must matchlibc.so.6
, or you'll see the errors you are seeing.
In your case the mismatch is between /usr/lib/ld-2.26.so
(symlinked from ld-linux-x86-64.so.2
and loaded into the process by the kernel before your program executes a single instruction of its own) and ubuntu/libpthread.so.0
.
If you fully statically link your test program with gcc -static ...
, it will likely work. But that is not a mode of operation that GLIBC developers test or support, and is unlikely to work for any non-trivial program.
To fix this, you would need to re-execve
the program inside chroot
. If you can't copy the binary into your chroot, you may be able to escape from that difficulty with fexecve or using /proc/self/exe
(both of these appear to require that /proc
is mounted inside the chroot).
P.S.
The said library depends on glibc and its version is different from my host (host has 2.26, chroot has 2.23).
Due to libc backward compatibility, any library linked against GLIBC-2.23 should continue to work just fine against GLIBC-2.26.
So maybe you don't have a problem to solve in the first place?
Upvotes: 1