Age | Commit message (Collapse) | Author | Files | Lines |
|
this is the modern way, and the only way that makes any sense. glibc
has this complicated mechanism with RPATH and RUNPATH that controls
whether RPATH is processed before or after LD_LIBRARY_PATH, presumably
to support legacy binaries, but there is no compelling reason to
support this, and better behavior is obtained by just fixing the
search order.
|
|
this fixes an oversight in the previous commit.
|
|
previously, errno could be meaningless when the caller wrote it to the
dlerror string or stderr. try to make it meaningful. also, fix
incorrect check for over-long program headers and instead actually
support them by allocating memory if needed.
|
|
this can only happen for invalid library files, but they were not
detected reliably because the variable was uninitialized.
|
|
one of the arguments to memcmp may be shorter than the length l-3, and
memcmp is under no obligation not to access past the first byte that
differs. instead use strncmp which conveys the correct semantics. the
performance difference is negligible here and since the code is only
use for shared libc, both functions are already linked anyway.
|
|
the dev/inode for the main app and the dynamic linker ("interpreter")
are not available, so the subsequent checks don't work. in general we
don't want to make exact string matches to existing libraries prevent
loading new ones, since this breaks loading upgraded modules in
module-loading systems. so instead, special-case it.
the motivation for this fix is that calling dlopen on the names
returned by dl_iterate_phdr or walking the link map (obtained by
dlinfo) seem to be the only methods available to an application to
actually get a list of open dso handles.
|
|
reject elf files which are not ET_EXEC/ET_DYN type as bad exec format,
and reject ET_EXEC files when they cannot be loaded at the correct
address, since they are not relocatable at runtime. the main practical
benefit of this is to make dlopen of the main program fail rather than
producing an unsafe-to-use handle.
|
|
|
|
it's not clear to me why the linker even outputs these headers if they
are null, but apparently it does so. with the default startfiles, they
will never be null anyway, but this patch allows eliminating crti,
crtn, crtbegin, and crtend (leaving only crt1) if the toolchain is
using init_array/fini_array (or for a C-only, no-ctor environment).
|
|
|
|
|
|
entry point was wrong for PIE. e_entry was being treated as an
absolute value, whereas it's actually relative to the load address
(which is zero for non-PIE).
phdr pointer was wrong for non-PIE. e_phoff was being treated as
load-address-relative, whereas it's actually a file offset in the ELF
file. in any case, map_library was already computing it correctly, and
the incorrect code in __dynlink was overwriting it with junk.
|
|
these are needed for some C++ library binaries including most builds
of libstdc++. I'm not entirely clear on the rationale. this patch does
not implement any special semantics for them, but as far as I can
tell, no special treatment is needed in correctly-linked programs;
this binding seems to exist only for catching incorrectly-linked
programs.
|
|
this more than compensates for the size increase of jmp_buf, and
greatly reduces bss/data size on archs with huge jmp_buf.
|
|
since the old, poorly-thought-out musl approach to init/fini arrays on
ARM (when it was the only arch that needed them) was to put the code
in crti/crtn and have the legacy _init/_fini code run the arrays,
adding proper init/fini array support caused the arrays to get
processed twice on ARM. I'm not sure skipping legacy init/fini
processing is the best solution to the problem, but it works, and it
shouldn't break anything since the legacy init/fini system was never
used for ARM EABI.
|
|
modern (4.7.x and later) gcc uses init/fini arrays, rather than the
legacy _init/_fini function pasting and crtbegin/crtend ctors/dtors
system, on most or all archs. some archs had already switched a long
time ago. without following this change, global ctors/dtors will cease
to work under musl when building with new gcc versions.
the most surprising part of this patch is that it actually reduces the
size of the init code, for both static and shared libc. this is
achieved by (1) unifying the handling main program and shared
libraries in the dynamic linker, and (2) eliminating the
glibc-inspired rube goldberg machine for passing around init and fini
function pointers. to clarify, some background:
the function signature for __libc_start_main was based on glibc, as
part of the original goal of being able to run some glibc-linked
binaries. it worked by having the crt1 code, which is linked into
every application, static or dynamic, obtain and pass pointers to the
init and fini functions, which __libc_start_main is then responsible
for using and recording for later use, as necessary. however, in
neither the static-linked nor dynamic-linked case do we actually need
crt1.o's help. with dynamic linking, all the pointers are available in
the _DYNAMIC block. with static linking, it's safe to simply access
the _init/_fini and __init_array_start, etc. symbols directly.
obviously changing the __libc_start_main function signature in an
incompatible way would break both old musl-linked programs and
glibc-linked programs, so let's not do that. instead, the function can
just ignore the information it doesn't need. new archs need not even
provide the useless args in their versions of crt1.o. existing archs
should continue to provide it as long as there is an interest in
having newly-linked applications be able to run on old versions of
musl; at some point in the future, this support can be removed.
|
|
|
|
|
|
prior to this change, using a non-default syslibdir was impractical on
systems where the ordinary library paths contain musl-incompatible
library files. the file containing search paths was always taken from
/etc, which would either correspond to a system-wide musl
installation, or fail to exist at all, resulting in searching of the
default library path.
the new search strategy is safe even for suid programs because the
pathname used comes from the PT_INTERP header of the program being
run, rather than any external input.
as part of this change, I have also begun differentiating the names of
arch variants that differ by endianness or floating point calling
convention. the corresponding changes in the build system and and gcc
wrapper script (to use an alternate dynamic linker name) for these
configurations have not yet been made.
|
|
map_library was saving pointers to an automatic-storage buffer rather
than pointers into the mapping. this should be a fairly simple fix,
but the patch here is slightly complicated by two issues:
1. supporting gratuitously obfuscated ELF files where the program
headers are not right at the beginning of the file.
2. cleaning up the map_library function so that data isn't clobbered
by the time we need it.
|
|
|
|
this change is needed to correctly handle the case where a constructor
creates a new thread which calls dlopen. previously, the lock was not
held in this case. the reason for the complex logic to avoid locking
whenever possible is that, since the mutex is recursive, it will need
to inspect the thread pointer to get the current thread's tid, and
this requires initializing the thread pointer. we do not want
non-multi-threaded programs to attempt to access the thread pointer
unnecessarily; doing so could make them crash on ancient kernels that
don't support threads but which may otherwise be capable of running
the program.
|
|
|
|
previously, the path string was being used despite being invalid. with
this change, empty path file or error reading the path file is treated
as an empty path. this is preferable to falling back to a default
path, so that attacks to prevent reading of the path file could not
result in loading incorrect and possibly dangerous (outdated or
mismatching ABI) libraries from.
the code to strip the final newline has also been removed; now that
newline is accepted as a delimiter, it's harmless to leave it in
place.
|
|
apparently the original commit was never tested properly, since
getline was only ever reading one line. the intent was to read the
entire file, so use getdelim with the null byte as delimiter as a
cheap way to read a whole file into memory.
|
|
|
|
this allows /etc/ld-musl-$(ARCH).path to contain one path per line,
which is much more convenient for users than the :-delimited format,
which was a source of repeated and unnecessary confusion. for
simplicity, \n is also accepted in environment variables, though it
should probably not be used there.
at the same time, issues with overly long paths invoking UB or getting
truncated have been fixed. such issues should not have arisen with the
environment (which is size-limited) but could have been generated by a
path file larger than 2**31 bytes in length.
|
|
this bug seems to have been introduced when the map_library signatures
was changed to return the mapping in a temp dso structure instead of
into separate variables.
|
|
based on patch by Pierre Carrier <pierre@gcarrier.fr> that just added
the flag constant, but with minimal additional code so that it
actually works as documented. this is a nonstandard option but some
major software (reportedly, Firefox) uses it and it was easy to add
anyway.
|
|
|
|
struct dso was not defined in this case, and it's not needed in the
code that was using it anyway; void pointers work just as well.
|
|
|
|
this is wasteful and useless from a standpoint of sane programs, but
it is required by the standard, and the current requirements were
upheld with the closure of Austin Group issue #639:
http://austingroupbugs.net/view.php?id=639
|
|
|
|
previously, shared library constructors were being called before
important internal things like the environment (extern char **environ)
and hwcap flags (needed for sjlj to work right with float on arm) were
initialized in __libc_start_main. rather than trying to have to
dynamic linker make sure this stuff all gets initialized right, I've
opted to just defer calling shared library constructors until after
the main program's entry point is reached. this also fixes the order
of ctors to be the exact reverse of dtors, which is a desirable
property and possibly even mandated by some languages.
the main practical effect of this change is that shared libraries
calling getenv from ctors will no longer fail.
|
|
actually, the hard-coded name should be eliminated too, and replaced
by a search for the soname in the headers, but that can be done
separately later.
|
|
fortunately the memory corruption could not hurt anything, but it
prevented clearing the final newline and thus prevented the last path
element from working.
|
|
this allows using the dynamic linker as a command to load programs.
|
|
incomplete but at least partly working. requires all files to be
compiled in the new "secure" plt model, not the old one that put plt
code in the data segment. TLS is untested but may work. invoking the
dynamic linker explicitly to load a program does not yet handle argv
correctly.
|
|
|
|
|
|
|
|
|
|
|
|
this change was originally intended just to avoid repeated attempts to
open a nonexistant /etc/ls-musl-$(ARCH).path file, but I realized it
also prevents the default paths from being searched when such a path
file exists. despite the potential to break existing usage, I believe
the new behavior is the right behavior, and it's better to fix it
sooner rather than later. with the old behavior, it was impossible to
inhibit search of default paths which might contain musl-incompatible
libs (or even libs from a different cpu arch, on multi-arch machines).
|
|
saving the return address from the delay slot is not valid -- by the
time the instruction executes, the return address has already been
replaced.
|
|
|
|
some of these were coming from stdio functions locking files without
unlocking them. I believe it's useful for this to throw a warning, so
I added a new macro that's self-documenting that the file will never
be unlocked to avoid the warning in the few places where it's wrong.
|
|
patches by Alex Caudill (npx). the dynamic-linked version is almost
identical to the final submitted patch; I just added a couple missing
lines for saving the phdr address when the dynamic linker is invoked
directly to run a program, and removed a couple to avoid introducing
another unnecessary type. the static-linked version is based on npx's
draft. it could use some improvements which are contingent on the
startup code saving some additional information for later use.
|
|
|