On Sat, Jun 01, 2019 at 06:35:23PM +0200, Yann Sionneau wrote:
Hello Luca,
I am not sure whether dlopen'ing an executable (and not a shared lib) is
a supported feature of uClibc-ng...
Man page of dlopen says it is for opening "shared lib".
There has been a discussion on glibc bug tracker to widen the scope of
dlopen and allow it to open executables ... but it seems Ulrich Drepper
refused it, and then the discussion was revived and it still does not
seem to hold a strong consensus. See
https://sourceware.org/bugzilla/show_bug.cgi?id=11754
I didn't try, but I am guessing here that if it works, it is by accident.
opening and mapping an ET_EXEC is needed indeed in the case of
"standalone" (dynamic loader run as an executable and loading another
executable given as argument).
And the function used to do this, is also the one used by dlopen() to
map the shared libs.
I guess you are refering to
https://elixir.bootlin.com/uclibc-ng/latest/source/ldso/ldso/dl-elf.c#L596
_dl_load_elf_shared_library is indeed used to load the ET_EXEC in the
"ld.so used as an executable" from there:
https://elixir.bootlin.com/uclibc-ng/latest/source/ldso/ldso/ldso.c#L601
And it is also called from
https://elixir.bootlin.com/uclibc-ng/latest/source/ldso/ldso/dl-elf.c#L200
Which is itself called from dlopen:
https://elixir.bootlin.com/uclibc-ng/latest/source/ldso/libdl/libdl.c#L372
So it seems the same function is used in 2 different contexts and that
leads to the support of ET_EXEC which is valid in one context ... but
I'm not sure it is valid in the other one (directly loading an ET_EXEC
with dlopen).
I hope this is clear.
Maybe someone else can give a hint whether my guess is correct or not?
Rich ? Waldemar ?
I don't think dlopen of an ET_EXEC can be made safe/consistent. aside
from the issue with whether the address space range is available,
which could just be imposed as a constraint, you also have matters of
interposition and TLS model.
When producing an executable, whether ET_EXEC or ET_DYN (PIE), the
linker will bind address references to external function and data
symbols to PLT slots of copy relocations in the main executable. But
the rest of the program (into which it's loaded via dlopen) will be
using different addresses for these functions and objects. That
*might* not matter, if you don't care about function pointer equality
and don't use global variables.
For TLS, it's even worse. All access to thread-local objects from an
executable will use the local-exec model -- the offset of the object
from the thread pointer is hard-coded at link time. The offsets used
by the dlopened program will overlap with offsets used by the program
it's loaded into, or its shared libraries, and major memory corruption
will occur if they're ever accessed. There is no way to patch this up.
Rich