Commit Graph

788 Commits

Author SHA1 Message Date
Sam James a2bd5008a9
Pass -Wl,--no-error-execstack for tests where -Wl,-z,execstack is used [PR32717]
When GNU Binutils is configured with --enable-error-execstack=yes, a handful
of our tests which rely on -Wl,-z,execstack fail. Pass --Wl,--no-error-execstack
to override the behaviour and get a warning instead.

Bug: https://sourceware.org/PR32717
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-03-04 20:08:50 +00:00
Florian Weimer aa3d7bd529 elf: Keep using minimal malloc after early DTV resize (bug 32412)
If an auditor loads many TLS-using modules during startup, it is
possible to trigger DTV resizing.  Previously, the DTV was marked
as allocated by the main malloc afterwards, even if the minimal
malloc was still in use.  With this change, _dl_resize_dtv marks
the resized DTV as allocated with the minimal malloc.

The new test reuses TLS-using modules from other auditing tests.

Reviewed-by: DJ Delorie <dj@redhat.com>
2025-02-13 21:56:52 +01:00
Florian Weimer 96429bcc91 elf: Do not add a copy of _dl_find_object to libc.so
This reduces code size and dependencies on ld.so internals from
libc.so.

Fixes commit f4c142bb9f
("arm: Use _dl_find_object on __gnu_Unwind_Find_exidx (BZ 31405)").

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2025-02-01 12:37:58 +01:00
Florian Weimer d1da011118 elf: Always define TLS_TP_OFFSET
This will be needed to compute __rseq_offset outside of the TLS
relocation machinery.

Reviewed-by: Michael Jeanson <mjeanson@efficios.com>
2025-01-09 19:30:44 +01:00
Florian Weimer 39183f47d8 elf: Minimize library dependencies of tst-nolink-libc.c
On 32-bit Arm, -fasynchronous-unwind-tables creates a reference
to the symbol __aeabi_unwind_cpp_pr0.  Compile the tests without
this flag even if it is passed as part of CC, to avoid linker
failures.
2025-01-08 16:55:31 +01:00
Florian Weimer 706209867f elf: Second ld.so relocation only if libc.so has been loaded
Commit 8f8dd904c4 (“elf:
rtld_multiple_ref is always true”) removed some code that happened
to enable compatibility with programs that do not link against
libc.so.  Such programs cannot call dlopen or any dynamic linker
functions (except __tls_get_addr), so this is not really useful.
Still ld.so should not crash with a null-pointer dereference
or undefined symbol reference in these cases.

In the main relocation loop, call _dl_relocate_object unconditionally
because it already checks if the object has been relocated.

If libc.so was loaded, self-relocate ld.so against it and call
__rtld_mutex_init and __rtld_malloc_init_real to activate the full
implementations.  Those are available only if libc.so is there,
so skip these initialization steps if libc.so is absent.  Without
libc.so, the global scope can be completely empty.  This can cause
ld.so self-relocation to fail because if it uses symbol-based
relocations, which is why the second ld.so self-relocation is not
performed if libc.so is missing.

The previous concern regarding GOT updates through self-relocation
no longer applies because function pointers are updated
explicitly through __rtld_mutex_init and __rtld_malloc_init_real,
and not through relocation.  However, the second ld.so self-relocation
is still delayed, in case there are other symbols being used.

Fixes commit 8f8dd904c4 (“elf:
rtld_multiple_ref is always true”).

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2025-01-07 09:19:01 +01:00
H.J. Lu 1294926da3 Rename have-mtls-descriptor to have-test-mtls-descriptor
Since have-mtls-descriptor is only used for glibc testing, rename it to
have-test-mtls-descriptor.  Also enable tst-gnu2-tls2-amx only if
$(have-test-mtls-descriptor) == gnu2.

Tested with GCC 14 and Clang 19/18/17 on x86-64.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
2025-01-04 04:51:21 +08:00
Paul Eggert 2642002380 Update copyright dates with scripts/update-copyrights 2025-01-01 11:22:09 -08:00
Adhemerval Zanella 58272284b6 elf: Add glibc.rtld.execstack
The new tunable can be used to control whether executable stacks are
allowed from either the main program or dependencies.  The default is
to allow executable stacks.

The executable stacks default permission is checked agains the one
provided by the PT_GNU_STACK from program headers (if present).  The
tunable also disables the stack permission change if any dependency
requires an executable stack at loading time.

Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
2024-12-31 09:04:20 -03:00
Adhemerval Zanella c9540704ac elf: Add tst-execstack-prog-static
Similar to tst-execstack-prog, check if executable stacks works for
statically linked programs.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
2024-12-31 09:04:20 -03:00
H.J. Lu 8d25b9f2c8 elf: Enable tst-dlopen-nodelete-reloc if TEST_CXX supports STB_GNU_UNIQUE
tst-dlopen-nodelete-reloc requires STB_GNU_UNIQUE support so that NODELETE
is propagated by do_lookup_unique.  Enable it only if TEST_CXX supports
STB_GNU_UNIQUE,

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
2024-12-22 17:20:15 +08:00
H.J. Lu 03feea74dc elf: Compile test modules with -fsemantic-interposition
Compiler may default to -fno-semantic-interposition. But some elf test
modules must be compiled with -fsemantic-interposition to function properly.
Add a TEST_CC check for -fsemantic-interposition and use it on elf test
modules.  This fixed

FAIL: elf/tst-dlclose-lazy
FAIL: elf/tst-pie1
FAIL: elf/tst-plt-rewrite1
FAIL: elf/unload4

when Clang 19 is used to test glibc.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
2024-12-22 13:15:43 +08:00
H.J. Lu d9d30f6cb5 Enable execstack tests only if compiler supports trampoline
Since trampoline is required to test execstack, enable execstack tests
only if compiler supports trampoline.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
2024-12-22 12:55:50 +08:00
Joseph Myers d7f587398c Add further DSO dependency sorting tests
The current DSO dependency sorting tests are for a limited number of
specific cases, including some from particular bug reports.

Add tests that systematically cover all possible DAGs for an
executable and the shared libraries it depends on, directly or
indirectly, up to four objects (an executable and three shared
libraries).  (For this kind of DAG - ones with a single source vertex
from which all others are reachable, and an ordering on the edges from
each vertex - there are 57 DAGs on four vertices, 3399 on five
vertices and 1026944 on six vertices; see
https://arxiv.org/pdf/2303.14710 for more details on this enumeration.
I've tested that the 3399 cases with five vertices do all pass if
enabled.)

These tests are replicating the sorting logic from the dynamic linker
(thereby, for example, asserting that it doesn't accidentally change);
I'm not claiming that the logic in the dynamic linker is in some
abstract sense optimal.  Note that these tests do illustrate how in
some cases the two sorting algorithms produce different results for a
DAG (I think all the existing tests for such differences are ones
involving cycles, and the motivation for the new algorithm was also to
improve the handling of cycles):

  tst-dso-ordering-all4-44: a->[bc];{}->[cba]
  output(glibc.rtld.dynamic_sort=1): c>b>a>{}<a<b<c
  output(glibc.rtld.dynamic_sort=2): b>c>a>{}<a<c<b

They also illustrate that sometimes the sorting algorithms do not
follow the order in which dependencies are listed in DT_NEEDED even
though there is a valid topological sort that does follow that, which
might be counterintuitive considering that the DT_NEEDED ordering is
followed in the simplest cases:

  tst-dso-ordering-all4-56: {}->[abc]
  output: c>b>a>{}<a<b<c

shows such a simple case following DT_NEEDED order for destructor
execution (the reverse of it for constructor execution), but

  tst-dso-ordering-all4-41: a->[cb];{}->[cba]
  output: c>b>a>{}<a<b<c

shows that c and b are in the opposite order to what might be expected
from the simplest case, though there is no dependency requiring such
an opposite order to be used.

(I'm not asserting that either of those things is a problem, simply
observing them as less obvious properties of the sorting algorithms
shown up by these tests.)

Tested for x86_64.
2024-12-19 18:56:04 +00:00
Joseph Myers 062257c5d9 Fix typo in elf/Makefile:postclean-generated
The postclean-generated setting in elf/Makefile lists
$(objpfx)/dso-sort-tests-2.generated-makefile twice and
$(objpfx)/dso-sort-tests-1.generated-makefile not at all, which looks
like a typo; fix it to list each once.

Tested for x86_64.
2024-12-05 21:40:57 +00:00
Joseph Myers 9b5f2eb9fc Add further test of TLS
Add an additional test of TLS variables, with different alignment,
accessed from different modules.  The idea of the alignment test is
similar to tst-tlsalign and the same code is shared for setting up
test variables, but unlike the tst-tlsalign code, there are multiple
threads and variables are accessed from multiple objects to verify
that they get a consistent notion of the address of an object within a
thread.  Threads are repeatedly created and shut down to verify proper
initialization in each new thread.  The test is also repeated with TLS
descriptors when supported.  (However, only initial-exec TLS is
covered in this test.)

Tested for x86_64.
2024-12-05 09:53:47 +00:00
Joseph Myers 6ae9836ed2 Add test of ELF hash collisions
Add tests that the dynamic linker works correctly with symbol names
involving hash collisions, for both choices of hash style (and
--hash-style=both as well).  I note that there weren't actually any
previous tests using --hash-style (so tests would only cover the
default linker configuration in that regard).  Also test symbol
versions involving hash collisions.

Tested for x86_64.
2024-11-29 16:43:56 +00:00
H.J. Lu e7b5532721 elf: Handle static PIE with non-zero load address [BZ #31799]
For a static PIE with non-zero load address, its PT_DYNAMIC segment
entries contain the relocated values for the load address in static PIE.
Since static PIE usually doesn't have PT_PHDR segment, use p_vaddr of
the PT_LOAD segment with offset == 0 as the load address in static PIE
and adjust the entries of PT_DYNAMIC segment in static PIE by properly
setting the l_addr field for static PIE.  This fixes BZ #31799.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
2024-11-22 06:22:13 +08:00
Florian Weimer c1560f3f75 elf: Switch to main malloc after final ld.so self-relocation
Before commit ee1ada1bdb
("elf: Rework exception handling in the dynamic loader
[BZ #25486]"), the previous order called the main calloc
to allocate a shadow GOT/PLT array for auditing support.
This happened before libc.so.6 ELF constructors were run, so
a user malloc could run without libc.so.6 having been
initialized fully.  One observable effect was that
environ was NULL at this point.

It does not seem to be possible at present to trigger such
an allocation, but it seems more robust to delay switching
to main malloc after ld.so self-relocation is complete.
The elf/tst-rtld-no-malloc-audit test case fails with a
2.34-era glibc that does not have this fix.

Reviewed-by: DJ Delorie <dj@redhat.com>
2024-11-06 10:33:44 +01:00
Florian Weimer 95129e6b8f Revert "elf: Run constructors on cyclic recursive dlopen (bug 31986)"
This reverts commit 9897ced8e7.

Adjust the test expectations in elf/tst-dlopen-auditdup-auditmod.c
accordingly.
2024-10-28 14:45:30 +01:00
Florian Weimer 43db5e2c06 elf: Signal RT_CONSISTENT after relocation processing in dlopen (bug 31986)
Previously, a la_activity audit event was generated before
relocation processing completed.  This does did not match what
happened during initial startup in elf/rtld.c (towards the end
of dl_main).  It also caused various problems if an auditor
tried to open the same shared object again using dlmopen:
If it was the directly loaded object, it had a search scope
associated with it, so the early exit in dl_open_worker_begin
was taken even though the object was unrelocated.  This caused
the r_state == RT_CONSISTENT assert to fail.  Avoidance of the
assert also depends on reversing the order of r_state update
and auditor event (already implemented in a previous commit).

At the later point, args->map can be NULL due to failure,
so use the assigned namespace ID instead if that is available.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2024-10-25 16:54:22 +02:00
Florian Weimer 9897ced8e7 elf: Run constructors on cyclic recursive dlopen (bug 31986)
This is conceptually similar to the reported bug, but does not
depend on auditing.  The fix is simple: just complete execution
of the constructors.  This exposed the fact that the link map
for statically linked executables does not have l_init_called
set, even though constructors have run.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2024-10-25 16:50:10 +02:00
Aaron Merey 83fd4149ff Test that errno is set to 0 at program startup
Add new testcase elf/tst-startup-errno.c which tests that errno is set
to 0 at first ELF constructor execution and at the start of the
program's main function.

Tested for x86_64

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2024-09-20 15:49:36 -04:00
Florian Weimer e82a7cb162 elf: Fix tst-dlopen-tlsreinit1.out test dependency
Fixes commit 5097cd344f
("elf: Avoid re-initializing already allocated TLS in dlopen
(bug 31717)").

Reported-by: Patsy Griffin <patsy@redhat.com>
Reviewed-by: Patsy Griffin <patsy@redhat.com>
2024-09-09 21:10:23 +02:00
Adhemerval Zanella 89b53077d2 nptl: Fix Race conditions in pthread cancellation [BZ#12683]
The current racy approach is to enable asynchronous cancellation
before making the syscall and restore the previous cancellation
type once the syscall returns, and check if cancellation has happen
during the cancellation entrypoint.

As described in BZ#12683, this approach shows 2 problems:

  1. Cancellation can act after the syscall has returned from the
     kernel, but before userspace saves the return value.  It might
     result in a resource leak if the syscall allocated a resource or a
     side effect (partial read/write), and there is no way to program
     handle it with cancellation handlers.

  2. If a signal is handled while the thread is blocked at a cancellable
     syscall, the entire signal handler runs with asynchronous
     cancellation enabled.  This can lead to issues if the signal
     handler call functions which are async-signal-safe but not
     async-cancel-safe.

For the cancellation to work correctly, there are 5 points at which the
cancellation signal could arrive:

	[ ... )[ ... )[ syscall ]( ...
	   1      2        3    4   5

  1. Before initial testcancel, e.g. [*... testcancel)
  2. Between testcancel and syscall start, e.g. [testcancel...syscall start)
  3. While syscall is blocked and no side effects have yet taken
     place, e.g. [ syscall ]
  4. Same as 3 but with side-effects having occurred (e.g. a partial
     read or write).
  5. After syscall end e.g. (syscall end...*]

And libc wants to act on cancellation in cases 1, 2, and 3 but not
in cases 4 or 5.  For the 4 and 5 cases, the cancellation will eventually
happen in the next cancellable entrypoint without any further external
event.

The proposed solution for each case is:

  1. Do a conditional branch based on whether the thread has received
     a cancellation request;

  2. It can be caught by the signal handler determining that the saved
     program counter (from the ucontext_t) is in some address range
     beginning just before the "testcancel" and ending with the
     syscall instruction.

  3. SIGCANCEL can be caught by the signal handler and determine that
     the saved program counter (from the ucontext_t) is in the address
     range beginning just before "testcancel" and ending with the first
     uninterruptable (via a signal) syscall instruction that enters the
      kernel.

  4. In this case, except for certain syscalls that ALWAYS fail with
     EINTR even for non-interrupting signals, the kernel will reset
     the program counter to point at the syscall instruction during
     signal handling, so that the syscall is restarted when the signal
     handler returns.  So, from the signal handler's standpoint, this
     looks the same as case 2, and thus it's taken care of.

  5. For syscalls with side-effects, the kernel cannot restart the
     syscall; when it's interrupted by a signal, the kernel must cause
     the syscall to return with whatever partial result is obtained
     (e.g. partial read or write).

  6. The saved program counter points just after the syscall
     instruction, so the signal handler won't act on cancellation.
     This is similar to 4. since the program counter is past the syscall
     instruction.

So The proposed fixes are:

  1. Remove the enable_asynccancel/disable_asynccancel function usage in
     cancellable syscall definition and instead make them call a common
     symbol that will check if cancellation is enabled (__syscall_cancel
     at nptl/cancellation.c), call the arch-specific cancellable
     entry-point (__syscall_cancel_arch), and cancel the thread when
     required.

  2. Provide an arch-specific generic system call wrapper function
     that contains global markers.  These markers will be used in
     SIGCANCEL signal handler to check if the interruption has been
     called in a valid syscall and if the syscalls has side-effects.

     A reference implementation sysdeps/unix/sysv/linux/syscall_cancel.c
     is provided.  However, the markers may not be set on correct
     expected places depending on how INTERNAL_SYSCALL_NCS is
     implemented by the architecture.  It is expected that all
     architectures add an arch-specific implementation.

  3. Rewrite SIGCANCEL asynchronous handler to check for both canceling
     type and if current IP from signal handler falls between the global
     markers and act accordingly.

  4. Adjust libc code to replace LIBC_CANCEL_ASYNC/LIBC_CANCEL_RESET to
     use the appropriate cancelable syscalls.

  5. Adjust 'lowlevellock-futex.h' arch-specific implementations to
     provide cancelable futex calls.

Some architectures require specific support on syscall handling:

  * On i386 the syscall cancel bridge needs to use the old int80
    instruction because the optimized vDSO symbol the resulting PC value
    for an interrupted syscall points to an address outside the expected
    markers in __syscall_cancel_arch.  It has been discussed in LKML [1]
    on how kernel could help userland to accomplish it, but afaik
    discussion has stalled.

    Also, sysenter should not be used directly by libc since its calling
    convention is set by the kernel depending of the underlying x86 chip
    (check kernel commit 30bfa7b3488bfb1bb75c9f50a5fcac1832970c60).

  * mips o32 is the only kABI that requires 7 argument syscall, and to
    avoid add a requirement on all architectures to support it, mips
    support is added with extra internal defines.

Checked on aarch64-linux-gnu, arm-linux-gnueabihf, powerpc-linux-gnu,
powerpc64-linux-gnu, powerpc64le-linux-gnu, i686-linux-gnu, and
x86_64-linux-gnu.

[1] https://lkml.org/lkml/2016/3/8/1105
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2024-08-23 14:27:43 -03:00
Henrik Lindström bd1719aca5 rtld: Add test case for '--' option
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2024-08-06 10:53:24 -03:00
Florian Weimer 5097cd344f elf: Avoid re-initializing already allocated TLS in dlopen (bug 31717)
The old code used l_init_called as an indicator for whether TLS
initialization was complete.  However, it is possible that
TLS for an object is initialized, written to, and then dlopen
for this object is called again, and l_init_called is not true at
this point.  Previously, this resulted in TLS being initialized
twice, discarding any interim writes (technically introducing a
use-after-free bug even).

This commit introduces an explicit per-object flag, l_tls_in_slotinfo.
It indicates whether _dl_add_to_slotinfo has been called for this
object.  This flag is used to avoid double-initialization of TLS.
In update_tls_slotinfo, the first_static_tls micro-optimization
is removed because preserving the initalization flag for subsequent
use by the second loop for static TLS is a bit complicated, and
another per-object flag does not seem to be worth it.  Furthermore,
the l_init_called flag is dropped from the second loop (for static
TLS initialization) because l_need_tls_init on its own prevents
double-initialization.

The remaining l_init_called usage in resize_scopes and update_scopes
is just an optimization due to the use of scope_has_map, so it is
not changed in this commit.

The isupper check ensures that libc.so.6 is TLS is not reverted.
Such a revert happens if l_need_tls_init is not cleared in
_dl_allocate_tls_init for the main_thread case, now that
l_init_called is not checked anymore in update_tls_slotinfo
in elf/dl-open.c.

Reported-by: Jonathon Anderson <janderson@rice.edu>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2024-08-05 18:26:52 +02:00
Adhemerval Zanella 9fc639f654 elf: Make dl-rseq-symbols Linux only
And avoid a Hurd build failures.

Checked on x86_64-linux-gnu.
2024-07-04 10:09:07 -03:00
Michael Jeanson 2b92982e23 nptl: fix potential merge of __rseq_* relro symbols
While working on a patch to add support for the extensible rseq ABI, we
came across an issue where a new 'const' variable would be merged with
the existing '__rseq_size' variable. We tracked this to the use of
'-fmerge-all-constants' which allows the compiler to merge identical
constant variables. This means that all 'const' variables in a compile
unit that are of the same size and are initialized to the same value can
be merged.

In this specific case, on 32 bit systems 'unsigned int' and 'ptrdiff_t'
are both 4 bytes and initialized to 0 which should trigger the merge.
However for reasons we haven't delved into when the attribute 'section
(".data.rel.ro")' is added to the mix, only variables of the same exact
types are merged. As far as we know this behavior is not specified
anywhere and could change with a new compiler version, hence this patch.

Move the definitions of these variables into an assembler file and add
hidden writable aliases for internal use. This has the added bonus of
removing the asm workaround to set the values on rseq registration.

Tested on Debian 12 with GCC 12.2.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
2024-07-03 21:40:30 +02:00
Stefan Liebler d2f6ceaccb elf/rtld: Fix auxiliary vector for enable_secure
Starting with commit
59974938fe
elf/rtld: Count skipped environment variables for enable_secure

The new testcase elf/tst-tunables-enable_secure-env segfaults on s390 (31bit).
There _start parses the auxiliary vector for some additional checks.

Therefore it skips over the zeros after the environment variables ...
0x7fffac20:     0x7fffbd17      0x7fffbd32      0x7fffbd69      0x00000000
------------------------------------------------^^^last environment variable

... and then it parses the auxiliary vector and stops at AT_NULL.
0x7fffac30:     0x00000000      0x00000021      0x00000000      0x00000000
--------------------------------^^^AT_SYSINFO_EHDR--------------^^^AT_NULL
----------------^^^newp-----------------------------------------^^^oldp
Afterwards it tries to access AT_PHDR which points to somewhere and segfaults.

Due to not incorporating the skip_env variable in the computation of oldp
when shuffling down the auxv in rtld.c, it just copies one entry with AT_NULL
and value 0x00000021 and stops the loop.  In reality we have skipped
GLIBC_TUNABLES environment variable (=> skip_env=1). Thus we should copy from
here:
0x7fffac40:     0x00000021      0x7ffff000      0x00000010      0x007fffff
----------------^^^fixed-oldp

This patch fixes the computation of oldp when shuffling down auxiliary vector.
It also adds some checks in the testcase.  Those checks also fail on
s390x (64bit) and x86_64 without the fix.

Co-authored-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2024-07-03 13:01:44 +02:00
Florian Weimer 018f0fc3b8 elf: Support recursive use of dynamic TLS in interposed malloc
It turns out that quite a few applications use bundled mallocs that
have been built to use global-dynamic TLS (instead of the recommended
initial-exec TLS).  The previous workaround from
commit afe42e935b ("elf: Avoid some
free (NULL) calls in _dl_update_slotinfo") does not fix all
encountered cases unfortunatelly.

This change avoids the TLS generation update for recursive use
of TLS from a malloc that was called during a TLS update.  This
is possible because an interposed malloc has a fixed module ID and
TLS slot.  (It cannot be unloaded.)  If an initially-loaded module ID
is encountered in __tls_get_addr and the dynamic linker is already
in the middle of a TLS update, use the outdated DTV, thus avoiding
another call into malloc.  It's still necessary to update the
DTV to the most recent generation, to get out of the slow path,
which is why the check for recursion is needed.

The bookkeeping is done using a global counter instead of per-thread
flag because TLS access in the dynamic linker is tricky.

All this will go away once the dynamic linker stops using malloc
for TLS, likely as part of a change that pre-allocates all TLS
during pthread_create/dlopen.

Fixes commit d2123d6827 ("elf: Fix slow
tls access after dlopen [BZ #19924]").

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
2024-07-01 19:02:11 +02:00
Carlos O'Donell a7fe3e805d
Fix conditionals on mtrace-based tests (bug 31892)
The conditionals for several mtrace-based tests in catgets, elf, libio,
malloc, misc, nptl, posix, and stdio-common were incorrect leading to
test failures when bootstrapping glibc without perl.

The correct conditional for mtrace-based tests requires three checks:
first checking for run-built-tests, then build-shared, and lastly that
PERL is not equal to "no" (missing perl).
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2024-07-01 17:20:30 +02:00
H.J. Lu 0b7f7842f8 elf: Change module-names to modules-names in comments
module-names should be modules-names.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
2024-06-14 13:29:21 -07:00
H.J. Lu ab46c6ba6c elf/Makefile: Split and sort PIE tests
Put each item on a separate line and sort PIE tests.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
2024-05-25 14:53:30 -07:00
H.J. Lu 049b7684c9 elf: Also compile dl-misc.os with $(rtld-early-cflags)
Also compile dl-misc.os with $(rtld-early-cflags) to avoid

Program received signal SIGILL, Illegal instruction.
0x00007ffff7fd36ea in _dl_strtoul (nptr=nptr@entry=0x7fffffffe2c9 "2",
    endptr=endptr@entry=0x7fffffffd728) at dl-misc.c:156
156	  bool positive = true;
(gdb) bt
 #0  0x00007ffff7fd36ea in _dl_strtoul (nptr=nptr@entry=0x7fffffffe2c9 "2",
    endptr=endptr@entry=0x7fffffffd728) at dl-misc.c:156
 #1  0x00007ffff7fdb1a9 in tunable_initialize (
    cur=cur@entry=0x7ffff7ffbc00 <tunable_list+2176>,
    strval=strval@entry=0x7fffffffe2c9 "2", len=len@entry=1)
    at dl-tunables.c:131
 #2  0x00007ffff7fdb3a2 in parse_tunables (valstring=<optimized out>)
    at dl-tunables.c:258
 #3  0x00007ffff7fdb5d9 in __GI___tunables_init (envp=0x7fffffffdd58)
    at dl-tunables.c:288
 #4  0x00007ffff7fe44c3 in _dl_sysdep_start (
    start_argptr=start_argptr@entry=0x7fffffffdcb0,
    dl_main=dl_main@entry=0x7ffff7fe5f80 <dl_main>)
    at ../sysdeps/unix/sysv/linux/dl-sysdep.c:110
 #5  0x00007ffff7fe5cae in _dl_start_final (arg=0x7fffffffdcb0) at rtld.c:494
 #6  _dl_start (arg=0x7fffffffdcb0) at rtld.c:581
 #7  0x00007ffff7fe4b38 in _start ()
(gdb)

when setting GLIBC_TUNABLES in glibc compiled with APX.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
2024-04-25 08:09:49 -07:00
Joe Simmons-Talbott 59974938fe elf/rtld: Count skipped environment variables for enable_secure
When using the glibc.rtld.enable_secure tunable we need to keep track of
the count of environment variables we skip due to __libc_enable_secure
being set and adjust the auxv section of the stack.  This fixes an
assertion when running ld.so directly with glibc.rtld.enable_secure set.
Add a testcase that ensures the assert is not hit.

elf/rtld.c:1324   assert (auxv == sp + 1);

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2024-04-16 20:32:10 +00:00
Florian Weimer aea52e3d2b Revert "x86_64: Suppress false positive valgrind error"
This reverts commit a1735e0aa8.

The test failure is a real valgrind bug that needs to be fixed before
valgrind is usable with a glibc that has been built with
CC="gcc -march=x86-64-v3".  The proposed valgrind patch teaches
valgrind to replace ld.so strcmp with an unoptimized scalar
implementation, thus avoiding any AVX2-related problems.

Valgrind bug: <https://bugs.kde.org/show_bug.cgi?id=485487>

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
2024-04-13 17:42:13 +02:00
Florian Weimer ae7468a7b0 elf: Add ld.so test with non-existing program name
None of the existing tests seem to cover the case where
_dl_signal_error is called without an active error handler.
The new elf/tst-rtld-does-not-exist test triggers such a
_dl_signal_error call from _dl_map_object.

Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
2024-04-08 19:19:09 +02:00
Adhemerval Zanella 3d53d18fc7 elf: Enable TLS descriptor tests on aarch64
The aarch64 uses 'trad' for traditional tls and 'desc' for tls
descriptors, but unlike other targets it defaults to 'desc'.  The
gnutls2 configure check does not set aarch64 as an ABI that uses
TLS descriptors, which then disable somes stests.

Also rename the internal machinery fron gnu2 to tls descriptors.

Checked on aarch64-linux-gnu.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
2024-03-19 14:53:30 -03:00
Adhemerval Zanella 64c7e34428 arm: Update _dl_tlsdesc_dynamic to preserve caller-saved registers (BZ 31372)
ARM _dl_tlsdesc_dynamic slow path has two issues:

  * The ip/r12 is defined by AAPCS as a scratch register, and gcc is
    used to save the stack pointer before on some function calls.  So it
    should also be saved/restored as well.  It fixes the tst-gnu2-tls2.

  * None of the possible VFP registers are saved/restored.  ARM has the
    additional complexity to have different VFP bank sizes (depending of
    VFP support by the chip).

The tst-gnu2-tls2 test is extended to check for VFP registers, although
only for hardfp builds.  Different than setcontext, _dl_tlsdesc_dynamic
does not have  HWCAP_ARM_IWMMXT (I don't have a way to properly test
it and it is almost a decade since newer hardware was released).

With this patch there is no need to mark tst-gnu2-tls2 as XFAIL.

Checked on arm-linux-gnueabihf.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
2024-03-19 14:53:30 -03:00
Joe Simmons-Talbott 71648e8004 rtld: Add glibc.rtld.enable_secure tunable.
Add a tunable for setting __libc_enable_secure to 1.  Do not set
__libc_enable_secure to 0 if the tunable is set to 0.  Ignore all
tunables if glib.rtld.enable_secure is set.  One use-case for this
addition is to enable testing code paths that depend on
__libc_enable_secure being set without the need to use setxid binaries.

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
2024-02-29 19:55:58 +00:00
H.J. Lu a1735e0aa8 x86_64: Suppress false positive valgrind error
When strcmp-avx2.S is used as the default, elf/tst-valgrind-smoke fails
with

==1272761== Conditional jump or move depends on uninitialised value(s)
==1272761==    at 0x4022C98: strcmp (strcmp-avx2.S:462)
==1272761==    by 0x400B05B: _dl_name_match_p (dl-misc.c:75)
==1272761==    by 0x40085F3: _dl_map_object (dl-load.c:1966)
==1272761==    by 0x401AEA4: map_doit (rtld.c:644)
==1272761==    by 0x4001488: _dl_catch_exception (dl-catch.c:237)
==1272761==    by 0x40015AE: _dl_catch_error (dl-catch.c:256)
==1272761==    by 0x401B38F: do_preload (rtld.c:816)
==1272761==    by 0x401C116: handle_preload_list (rtld.c:892)
==1272761==    by 0x401EDF5: dl_main (rtld.c:1842)
==1272761==    by 0x401A79E: _dl_sysdep_start (dl-sysdep.c:140)
==1272761==    by 0x401BEEE: _dl_start_final (rtld.c:494)
==1272761==    by 0x401BEEE: _dl_start (rtld.c:581)
==1272761==    by 0x401AD87: ??? (in */elf/ld.so)

The assembly codes are:

   0x0000000004022c80 <+144>:	vmovdqu 0x20(%rdi),%ymm0
   0x0000000004022c85 <+149>:	vpcmpeqb 0x20(%rsi),%ymm0,%ymm1
   0x0000000004022c8a <+154>:	vpcmpeqb %ymm0,%ymm15,%ymm2
   0x0000000004022c8e <+158>:	vpandn %ymm1,%ymm2,%ymm1
   0x0000000004022c92 <+162>:	vpmovmskb %ymm1,%ecx
   0x0000000004022c96 <+166>:	inc    %ecx
=> 0x0000000004022c98 <+168>:	jne    0x4022c32 <strcmp+66>

strcmp-avx2.S has 32-byte vector loads of strings which are shorter than
32 bytes:

(gdb) p (char *) ($rdi + 0x20)
$6 = 0x1ffeffea20 "memcheck-amd64-linux.so"
(gdb) p (char *) ($rsi + 0x20)
$7 = 0x4832640 "core-amd64-linux.so"
(gdb) call (int) strlen ((char *) ($rsi + 0x20))
$8 = 19
(gdb) call (int) strlen ((char *) ($rdi + 0x20))
$9 = 23
(gdb)

It triggers the valgrind error.  The above code is safe since the loads
don't cross the page boundary.  Update tst-valgrind-smoke.sh to accept
an optional suppression file and pass a suppression file to valgrind when
strcmp-avx2.S is the default implementation of strcmp.
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
2024-02-28 13:40:55 -08:00
H.J. Lu 0aac205a81 x86: Update _dl_tlsdesc_dynamic to preserve caller-saved registers
Compiler generates the following instruction sequence for GNU2 dynamic
TLS access:

	leaq	tls_var@TLSDESC(%rip), %rax
	call	*tls_var@TLSCALL(%rax)

or

	leal	tls_var@TLSDESC(%ebx), %eax
	call	*tls_var@TLSCALL(%eax)

CALL instruction is transparent to compiler which assumes all registers,
except for EFLAGS and RAX/EAX, are unchanged after CALL.  When
_dl_tlsdesc_dynamic is called, it calls __tls_get_addr on the slow
path.  __tls_get_addr is a normal function which doesn't preserve any
caller-saved registers.  _dl_tlsdesc_dynamic saved and restored integer
caller-saved registers, but didn't preserve any other caller-saved
registers.  Add _dl_tlsdesc_dynamic IFUNC functions for FNSAVE, FXSAVE,
XSAVE and XSAVEC to save and restore all caller-saved registers.  This
fixes BZ #31372.

Add GLRO(dl_x86_64_runtime_resolve) with GLRO(dl_x86_tlsdesc_dynamic)
to optimize elf_machine_runtime_setup.
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
2024-02-28 09:02:56 -08:00
Adhemerval Zanella f4c142bb9f arm: Use _dl_find_object on __gnu_Unwind_Find_exidx (BZ 31405)
Instead of __dl_iterate_phdr. On ARM dlfo_eh_frame/dlfo_eh_count
maps to PT_ARM_EXIDX vaddr start / length.

On a Neoverse N1 machine with 160 cores, the following program:

  $ cat test.c
  #include <stdlib.h>
  #include <pthread.h>
  #include <assert.h>

  enum {
    niter = 1024,
    ntimes = 128,
  };

  static void *
  tf (void *arg)
  {
    int a = (int) arg;

    for (int i = 0; i < niter; i++)
      {
        void *p[ntimes];
        for (int j = 0; j < ntimes; j++)
  	p[j] = malloc (a * 128);
        for (int j = 0; j < ntimes; j++)
  	free (p[j]);
      }

    return NULL;
  }

  int main (int argc, char *argv[])
  {
    enum { nthreads = 16 };
    pthread_t t[nthreads];

    for (int i = 0; i < nthreads; i ++)
      assert (pthread_create (&t[i], NULL, tf, (void *) i) == 0);

    for (int i = 0; i < nthreads; i++)
      {
        void *r;
        assert (pthread_join (t[i], &r) == 0);
        assert (r == NULL);
      }

    return 0;
  }
  $ arm-linux-gnueabihf-gcc -fsanitize=address test.c -o test

Improves from ~15s to 0.5s.

Checked on arm-linux-gnueabihf.
2024-02-23 08:50:00 -03:00
Carlos O'Donell 94aa256a47 elf: Fix tst-nodeps2 test failure.
After 78ca44da01
("elf: Relocate libc.so early during startup and dlmopen (bug 31083)")
we start seeing tst-nodeps2 failures when building the testsuite with
--enable-hard-coded-path-in-tests.

When building the testsuite with --enable-hard-coded-path-in-tests
the tst-nodeps2-mod.so is not built with the required DT_RUNPATH
values and the test escapes the test framework and loads the system
libraries and aborts. The fix is to use the existing
$(link-test-modules-rpath-link) variable to set DT_RUNPATH correctly.

No regressions on x86_64.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
2024-01-10 14:08:26 -05:00
Paul Eggert dff8da6b3e Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
Szabolcs Nagy 980450f126 elf: Add TLS modid reuse test for bug 29039
This is a minimal regression test for bug 29039 which only affects
targets with TLSDESC and a reproducer requires that

1) Have modid gaps (closed modules) with old generation.
2) Update a DTV to a newer generation (needs a newer dlopen).
3) But do not update the closed gap entry in that DTV.
4) Reuse the modid gap for a new module (another dlopen).
5) Use dynamic TLSDESC in that new module with old generation (bug).
6) Access TLS via this TLSDESC and the now outdated DTV.

However step (3) in practice rarely happens: during DTV update the
entries for closed modids are initialized to "unallocated" and then
dynamic TLSDESC calls __tls_get_addr independently of its generation.
The only exception to this is DTV setup at thread creation (gaps are
initialized to NULL instead of unallocated) or DTV resize where the
gap entries are outside the previous DTV array (again NULL instead
of unallocated, and this requires loading > DTV_SURPLUS modules).

So the bug can only cause NULL (+ offset) dereference, not use after
free. And the easiest way to get (3) is via thread creation.

Note that step (5) requires that the newly loaded module has larger
TLS than the remaining optional static TLS. And for (6) there cannot
be other TLS access or dlopen in the thread that updates the DTV.

Tested on aarch64-linux-gnu.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2023-12-20 08:45:48 +00:00
Stefan Liebler 3150cc0c90 Fix elf/tst-env-setuid[-static] if test needs to be rerun.
If /tmp is mounted nosuid and make xcheck is run,
then tst-env-setuid fails UNSUPPORTED with "SGID failed: GID and EGID match"
and /var/tmp/tst-sonamemove-runmod1.so.profile is created.

If you then try to rerun the test with a suid mounted test-dir
(the SGID binary is created in test-dir which defaults to /tmp)
with something like that:
make tst-env-setuid-ENV="TMPDIR=..." t=elf/tst-env-setuid test
the test fails as the LD_PROFILE output file is still available
from the previous run.

Thus this patch removes the LD_PROFILE output file in parent
before spawning the SGID binary.

Even if LD_PROFILE is not supported anymore in static binaries,
use a different library and thus output file for tst-env-setuid
and tst-env-setuid-static in order to not interfere if both
tests are run in parallel.

Furthermore the checks in test_child are now more verbose.
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2023-12-20 08:41:06 +01:00
Florian Weimer 78ca44da01 elf: Relocate libc.so early during startup and dlmopen (bug 31083)
This makes it more likely that objects without dependencies can
use IFUNC resolvers in libc.so.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2023-11-27 11:28:13 +01:00
Adhemerval Zanella 55f41ef8de elf: Remove LD_PROFILE for static binaries
The _dl_non_dynamic_init does not parse LD_PROFILE, which does not
enable profile for dlopen objects.  Since dlopen is deprecated for
static objects, it is better to remove the support.

It also allows to trim down libc.a of profile support.

Checked on x86_64-linux-gnu.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
2023-11-21 16:15:42 -03:00