about summary refs log tree commit diff
path: root/elf
Commit message (Collapse)AuthorAgeFilesLines
* elf: Avoid re-initializing already allocated TLS in dlopen (bug 31717)Florian Weimer2024-09-0910-37/+307
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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> (cherry picked from commit 5097cd344fd243fb8deb6dec96e8073753f962f9)
* elf: Clarify and invert second argument of _dl_allocate_tls_initFlorian Weimer2024-09-092-5/+10
| | | | | | | | Also remove an outdated comment: _dl_allocate_tls_init is called as part of pthread_create. Reviewed-by: Carlos O'Donell <carlos@redhat.com> (cherry picked from commit fe06fb313bddf7e4530056897d4a706606e49377)
* elf: Support recursive use of dynamic TLS in interposed mallocFlorian Weimer2024-09-096-9/+266
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 afe42e935b3ee97bac9a7064157587777259c60e ("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 d2123d68275acc0f061e73d5f86ca504e0d5a344 ("elf: Fix slow tls access after dlopen [BZ #19924]"). Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> (cherry picked from commit 018f0fc3b818d4d1460a4e2384c24802504b1d20)
* elf: Make dl-rseq-symbols Linux onlyAdhemerval Zanella2024-07-162-65/+0
| | | | | | | | And avoid a Hurd build failures. Checked on x86_64-linux-gnu. (cherry picked from commit 9fc639f654dc004736836613be703e6bed0c36a8)
* nptl: fix potential merge of __rseq_* relro symbolsMichael Jeanson2024-07-162-0/+65
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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> (cherry picked from commit 2b92982e2369d292560793bee8e730f695f48ff3)
* elf: Avoid some free (NULL) calls in _dl_update_slotinfoFlorian Weimer2024-06-031-1/+8
| | | | | | | | | | | | | | | | | | | | This has been confirmed to work around some interposed mallocs. Here is a discussion of the impact test ust/libc-wrapper/test_libc-wrapper in lttng-tools: New TLS usage in libgcc_s.so.1, compatibility impact <https://inbox.sourceware.org/libc-alpha/8734v1ieke.fsf@oldenburg.str.redhat.com/> Reportedly, this patch also papers over a similar issue when tcmalloc 2.9.1 is not compiled with -ftls-model=initial-exec. Of course the goal really should be to compile mallocs with the initial-exec TLS model, but this commit appears to be a useful interim workaround. Fixes commit d2123d68275acc0f061e73d5f86ca504e0d5a344 ("elf: Fix slow tls access after dlopen [BZ #19924]"). Reviewed-by: Carlos O'Donell <carlos@redhat.com> (cherry picked from commit afe42e935b3ee97bac9a7064157587777259c60e)
* elf: Only process multiple tunable once (BZ 31686)Adhemerval Zanella2024-05-072-12/+77
| | | | | | | | | | | | | | | | | | | | | | | | | The 680c597e9c3 commit made loader reject ill-formatted strings by first tracking all set tunables and then applying them. However, it does not take into consideration if the same tunable is set multiple times, where parse_tunables_string appends the found tunable without checking if it was already in the list. It leads to a stack-based buffer overflow if the tunable is specified more than the total number of tunables. For instance: GLIBC_TUNABLES=glibc.malloc.check=2:... (repeat over the number of total support for different tunable). Instead, use the index of the tunable list to get the expected tunable entry. Since now the initial list is zero-initialized, the compiler might emit an extra memset and this requires some minor adjustment on some ports. Checked on x86_64-linux-gnu and aarch64-linux-gnu. Reported-by: Yuto Maeda <maeda@cyberdefense.jp> Reported-by: Yutaro Shimizu <shimizu@cyberdefense.jp> Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> (cherry picked from commit bcae44ea8536b30a7119c0986ff5692bddacb672)
* elf: Also compile dl-misc.os with $(rtld-early-cflags)H.J. Lu2024-04-251-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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> (cherry picked from commit 049b7684c912dd32b67b1b15b0f43bf07d5f512e)
* elf: Enable TLS descriptor tests on aarch64Adhemerval Zanella2024-04-011-13/+13
| | | | | | | | | | | | | | 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> (cherry picked from commit 3d53d18fc71c5d9ef4773b8bce04d54b80181926)
* arm: Update _dl_tlsdesc_dynamic to preserve caller-saved registers (BZ 31372)Adhemerval Zanella2024-04-015-7/+10
| | | | | | | | | | | | | | | | | | | | | | | | 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> (cherry picked from commit 64c7e344289ed085517c2227d8e3b06388242c13)
* x86: Update _dl_tlsdesc_dynamic to preserve caller-saved registersH.J. Lu2024-04-016-0/+269
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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> (cherry picked from commit 0aac205a814a8511e98d02b91a8dc908f1c53cde)
* powerpc: Add HWCAP3/HWCAP4 data to TCB for Power Architecture.Manjunath Matti2024-03-203-0/+8
| | | | | | | | | | | | This patch adds a new feature for powerpc. In order to get faster access to the HWCAP3/HWCAP4 masks, similar to HWCAP/HWCAP2 (i.e. for implementing __builtin_cpu_supports() in GCC) without the overhead of reading them from the auxiliary vector, we now reserve space for them in the TCB. Suggested-by: Peter Bergner <bergner@linux.ibm.com> Reviewed-by: Peter Bergner <bergner@linux.ibm.com> (cherry picked from commit 3ab9b88e2ac91062b6d493fe32bd101a55006c6a)
* elf: correct relocation statistics for !ELF_MACHINE_START_ADDRESSAndreas Schwab2024-01-291-4/+3
| | | | Fixes: 6628c742b2 ("elf: Remove prelink support")
* elf: Fix tst-nodeps2 test failure.Carlos O'Donell2024-01-101-1/+4
| | | | | | | | | | | | | | | | | After 78ca44da0160a0b442f0ca1f253e3360f044b2ec ("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>
* Remove ia64-linux-gnuAdhemerval Zanella2024-01-081-3/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Linux 6.7 removed ia64 from the official tree [1], following the general principle that a glibc port needs upstream support for the architecture in all the components it depends on (binutils, GCC, and the Linux kernel). Apart from the removal of sysdeps/ia64 and sysdeps/unix/sysv/linux/ia64, there are updates to various comments referencing ia64 for which removal of those references seemed appropriate. The configuration is removed from README and build-many-glibcs.py. The CONTRIBUTED-BY, elf/elf.h, manual/contrib.texi (the porting mention), *.po files, config.guess, and longlong.h are not changed. For Linux it allows cleanup some clone2 support on multiple files. The following bug can be closed as WONTFIX: BZ 22634 [2], BZ 14250 [3], BZ 21634 [4], BZ 10163 [5], BZ 16401 [6], and BZ 11585 [7]. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=43ff221426d33db909f7159fdf620c3b052e2d1c [2] https://sourceware.org/bugzilla/show_bug.cgi?id=22634 [3] https://sourceware.org/bugzilla/show_bug.cgi?id=14250 [4] https://sourceware.org/bugzilla/show_bug.cgi?id=21634 [5] https://sourceware.org/bugzilla/show_bug.cgi?id=10163 [6] https://sourceware.org/bugzilla/show_bug.cgi?id=16401 [7] https://sourceware.org/bugzilla/show_bug.cgi?id=11585 Reviewed-by: Carlos O'Donell <carlos@redhat.com>
* elf: Add ELF_DYNAMIC_AFTER_RELOC to rewrite PLTH.J. Lu2024-01-053-0/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add ELF_DYNAMIC_AFTER_RELOC to allow target specific processing after relocation. For x86-64, add #define DT_X86_64_PLT (DT_LOPROC + 0) #define DT_X86_64_PLTSZ (DT_LOPROC + 1) #define DT_X86_64_PLTENT (DT_LOPROC + 3) 1. DT_X86_64_PLT: The address of the procedure linkage table. 2. DT_X86_64_PLTSZ: The total size, in bytes, of the procedure linkage table. 3. DT_X86_64_PLTENT: The size, in bytes, of a procedure linkage table entry. With the r_addend field of the R_X86_64_JUMP_SLOT relocation set to the memory offset of the indirect branch instruction. Define ELF_DYNAMIC_AFTER_RELOC for x86-64 to rewrite the PLT section with direct branch after relocation when the lazy binding is disabled. PLT rewrite is disabled by default since SELinux may disallow modifying code pages and ld.so can't detect it in all cases. Use $ export GLIBC_TUNABLES=glibc.cpu.plt_rewrite=1 to enable PLT rewrite with 32-bit direct jump at run-time or $ export GLIBC_TUNABLES=glibc.cpu.plt_rewrite=2 to enable PLT rewrite with 32-bit direct jump and on APX processors with 64-bit absolute jump at run-time. Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
* Update copyright dates not handled by scripts/update-copyrightsPaul Eggert2024-01-015-5/+5
| | | | | | I've updated copyright dates in glibc for 2024. This is the patch for the changes not generated by scripts/update-copyrights and subsequent build / regeneration of generated files.
* Update copyright dates with scripts/update-copyrightsPaul Eggert2024-01-01395-396/+396
|
* elf: Always provide _dl_get_dl_main_map in libc.aH.J. Lu2024-01-011-2/+0
| | | | | Always provide _dl_get_dl_main_map in libc.a. It will be used by x86 to process PT_GNU_PROPERTY segment.
* elf: Add TLS modid reuse test for bug 29039Szabolcs Nagy2023-12-205-0/+113
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* Fix elf/tst-env-setuid[-static] if test needs to be rerun.Stefan Liebler2023-12-203-6/+42
| | | | | | | | | | | | | | | | | | | | | | | | 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>
* elf: Do not set invalid tunables valuesAdhemerval Zanella2023-12-193-6/+68
| | | | | | | | | The loader now warns for invalid and out-of-range tunable values. The patch also fixes the parsing of size_t maximum values, where _dl_strtoul was failing for large values close to SIZE_MAX. Checked on x86_64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Do not duplicate the GLIBC_TUNABLES stringAdhemerval Zanella2023-12-193-53/+99
| | | | | | | | | | | | | | | | | | | | | The tunable parsing duplicates the tunable environment variable so it null-terminates each one since it simplifies the later parsing. It has the drawback of adding another point of failure (__minimal_malloc failing), and the memory copy requires tuning the compiler to avoid mem operations calls. The parsing now tracks the tunable start and its size. The dl-tunable-parse.h adds helper functions to help parsing, like a strcmp that also checks for size and an iterator for suboptions that are comma-separated (used on hwcap parsing by x86, powerpc, and s390x). Since the environment variable is allocated on the stack by the kernel, it is safe to keep the references to the suboptions for later parsing of string tunables (as done by set_hwcaps by multiple architectures). Checked on x86_64-linux-gnu, powerpc64le-linux-gnu, and aarch64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Initialize GLRO(dl_lazy) before relocating libc in dynamic startupFlorian Weimer2023-12-081-3/+3
| | | | | | | | | | | GLRO(dl_lazy) is used to set the parameters for the early _dl_relocate_object call, so the consider_profiling setting has to be applied before the call. Fixes commit 78ca44da0160a0b442f0ca1f253e3360f044b2ec ("elf: Relocate libc.so early during startup and dlmopen (bug 31083)"). Reviewed-by: Carlos O'Donell <carlos@redhat.com>
* elf: Fix wrong break removal from 8ee878592cAdhemerval Zanella2023-12-071-0/+1
| | | | Reported-by: Alexander Monakov <amonakov@ispras.ru>
* elf: Refactor process_envvarsAdhemerval Zanella2023-12-051-48/+84
| | | | | | | | | | It splits between process_envvars_secure and process_envvars_default, with the former used to process arguments for __libc_enable_secure. It does not have any semantic change, just simplify the code so there is no need to handle __libc_enable_secure on each len switch. Checked on x86_64-linux-gnu and aarch64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Ignore LD_BIND_NOW and LD_BIND_NOT for setuid binariesAdhemerval Zanella2023-12-052-4/+8
| | | | | | | | To avoid any environment variable to change setuid binaries semantics. Checked on x86_64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Ignore loader debug env vars for setuidAdhemerval Zanella2023-12-052-8/+18
| | | | | | | | | | | | | Loader already ignores LD_DEBUG, LD_DEBUG_OUTPUT, and LD_TRACE_LOADED_OBJECTS. Both LD_WARN and LD_VERBOSE are similar to LD_DEBUG, in the sense they enable additional checks and debug information, so it makes sense to disable them. Also add both LD_VERBOSE and LD_WARN on filtered environment variables for setuid binaries. Checked on x86_64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Add a way to check if tunable is set (BZ 27069)Adhemerval Zanella2023-11-295-0/+71
| | | | | | | | | | | The patch adds two new macros, TUNABLE_GET_DEFAULT and TUNABLE_IS_INITIALIZED, here the former get the default value with a signature similar to TUNABLE_GET, while the later returns whether the tunable was set by the environment variable. Checked on x86_64-linux-gnu. Reviewed-by: DJ Delorie <dj@redhat.com> Tested-by: Zhangfei Gao <zhangfei.gao@linaro.org>
* elf: Fix TLS modid reuse generation assignment (BZ 29039)Hector Martin2023-11-281-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | _dl_assign_tls_modid() assigns a slotinfo entry for a new module, but does *not* do anything to the generation counter. The first time this happens, the generation is zero and map_generation() returns the current generation to be used during relocation processing. However, if a slotinfo entry is later reused, it will already have a generation assigned. If this generation has fallen behind the current global max generation, then this causes an obsolete generation to be assigned during relocation processing, as map_generation() returns this generation if nonzero. _dl_add_to_slotinfo() eventually resets the generation, but by then it is too late. This causes DTV updates to be skipped, leading to NULL or broken TLS slot pointers and segfaults. Fix this by resetting the generation to zero in _dl_assign_tls_modid(), so it behaves the same as the first time a slot is assigned. _dl_add_to_slotinfo() will still assign the correct static generation later during module load, but relocation processing will no longer use an obsolete generation. Note that slotinfo entry (aka modid) reuse typically happens after a dlclose and only TLS access via dynamic tlsdesc is affected. Because tlsdesc is optimized to use the optional part of static TLS, dynamic tlsdesc can be avoided by increasing the glibc.rtld.optional_static_tls tunable to a large enough value, or by LD_PRELOAD-ing the affected modules. Fixes bug 29039. Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
* elf: Relocate libc.so early during startup and dlmopen (bug 31083)Florian Weimer2023-11-277-2/+118
| | | | | | | This makes it more likely that objects without dependencies can use IFUNC resolvers in libc.so. Reviewed-by: Carlos O'Donell <carlos@redhat.com>
* elf: Introduce the _dl_open_relocate_one_object functionFlorian Weimer2023-11-271-39/+47
| | | | | | It is extracted from dl_open_worker_begin. Reviewed-by: Carlos O'Donell <carlos@redhat.com>
* elf: In _dl_relocate_object, skip processing if object is relocatedFlorian Weimer2023-11-271-3/+3
| | | | | | | This is just a minor optimization. It also makes it more obvious that _dl_relocate_object can be called multiple times. Reviewed-by: Carlos O'Donell <carlos@redhat.com>
* elf: Add comments on how LD_AUDIT and LD_PRELOAD handle __libc_enable_secureAdhemerval Zanella2023-11-211-1/+8
| | | | | To make explicit why __libc_enable_secure is not checked. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Ignore LD_LIBRARY_PATH and debug env var for setuid for staticAdhemerval Zanella2023-11-211-16/+16
| | | | | | | It mimics the ld.so behavior. Checked on x86_64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Remove any_debug from dl_main_stateAdhemerval Zanella2023-11-212-6/+1
| | | | | Its usage can be implied by the GLRO(dl_debug_mask). Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Remove LD_PROFILE for static binariesAdhemerval Zanella2023-11-215-25/+16
| | | | | | | | | | | 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>
* elf: Ignore LD_PROFILE for setuid binariesAdhemerval Zanella2023-11-213-6/+17
| | | | | | | | | | | | | | | | | | Loader does not ignore LD_PROFILE in secure-execution mode (different than man-page states [1]), rather it uses a different path (/var/profile) and ignore LD_PROFILE_OUTPUT. Allowing secure-execution profiling is already a non good security boundary, since it enables different code paths and extra OS access by the process. But by ignoring LD_PROFILE_OUTPUT, the resulting profile file might also be acceded in a racy manner since the file name does not use any process-specific information (such as pid, timing, etc.). Another side-effect is it forces lazy binding even on libraries that might be with DF_BIND_NOW. [1] https://man7.org/linux/man-pages/man8/ld.so.8.html Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Emit warning if tunable is ill-formattedAdhemerval Zanella2023-11-211-0/+6
| | | | | | | So caller knows that the tunable will be ignored. Checked on x86_64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Fix _dl_debug_vdprintf to work before self-relocationAdhemerval Zanella2023-11-211-2/+14
| | | | | | | | | | | | | The strlen might trigger and invalid GOT entry if it used before the process is self-relocated (for instance on dl-tunables if any error occurs). For i386, _dl_writev with PIE requires to use the old 'int $0x80' syscall mode because the calling the TLS register (gs) is not yet initialized. Checked on x86_64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Do not parse ill-formatted stringsAdhemerval Zanella2023-11-212-16/+45
| | | | | | | | | | | Instead of ignoring ill-formatted tunable strings, first, check all the tunable definitions are correct and then set each tunable value. It means that partially invalid strings, like "key1=value1:key2=key2=value' or 'key1=value':key2=value2=value2' do not enable 'key1=value1'. It avoids possible user-defined errors in tunable definitions. Checked on x86_64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Do not process invalid tunable formatAdhemerval Zanella2023-11-212-7/+21
| | | | | | | | | | | Tunable definitions with more than one '=' on are parsed and enabled, and any subsequent '=' are ignored. It means that tunables in the form 'tunable=tunable=value' or 'tunable=value=value' are handled as 'tunable=value'. These inputs are likely user input errors, which should not be accepted. Checked on x86_64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Add all malloc tunable to unsecvarsAdhemerval Zanella2023-11-213-58/+79
| | | | | | | | | | | | | | | | | | | | | | | | Some environment variables allow alteration of allocator behavior across setuid boundaries, where a setuid program may ignore the tunable, but its non-setuid child can read it and adjust the memory allocator behavior accordingly. Most library behavior tunings is limited to the current process and does not bleed in scope; so it is unclear how pratical this misfeature is. If behavior change across privilege boundaries is desirable, it would be better done with a wrapper program around the non-setuid child that sets these envvars, instead of using the setuid process as the messenger. The patch as fixes tst-env-setuid, where it fail if any unsecvars is set. It also adds a dynamic test, although it requires --enable-hardcoded-path-in-tests so kernel correctly sets the setuid bit (using the loader command directly would require to set the setuid bit on the loader itself, which is not a usual deployment). Co-authored-by: Siddhesh Poyarekar <siddhesh@sourceware.org> Checked on x86_64-linux-gnu. Reviewed-by: DJ Delorie <dj@redhat.com>
* elf: Ignore GLIBC_TUNABLES for setuid/setgid binariesAdhemerval Zanella2023-11-216-135/+297
| | | | | | | | | | | | | | | | | | | | The tunable privilege levels were a retrofit to try and keep the malloc tunable environment variables' behavior unchanged across security boundaries. However, CVE-2023-4911 shows how tricky can be tunable parsing in a security-sensitive environment. Not only parsing, but the malloc tunable essentially changes some semantics on setuid/setgid processes. Although it is not a direct security issue, allowing users to change setuid/setgid semantics is not a good security practice, and requires extra code and analysis to check if each tunable is safe to use on all security boundaries. It also means that security opt-in features, like aarch64 MTE, would need to be explicit enabled by an administrator with a wrapper script or with a possible future system-wide tunable setting. Co-authored-by: Siddhesh Poyarekar <siddhesh@sourceware.org> Reviewed-by: DJ Delorie <dj@redhat.com>
* elf: Add GLIBC_TUNABLES to unsecvarsAdhemerval Zanella2023-11-211-28/+4
| | | | | | | | | | | | setuid/setgid process now ignores any glibc tunables, and filters out all environment variables that might changes its behavior. This patch also adds GLIBC_TUNABLES, so any spawned process by setuid/setgid processes should set tunable explicitly. Checked on x86_64-linux-gnu. Reviewed-by: Florian Weimer <fweimer@redhat.com> Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf: Remove /etc/suid-debug supportAdhemerval Zanella2023-11-212-18/+1
| | | | | | | | | | | | | | | | Since malloc debug support moved to a different library (libc_malloc_debug.so), the glibc.malloc.check requires preloading the debug library to enable it. It means that suid-debug support has not been working since 2.34. To restore its support, it would require to add additional information and parsing to where to find libc_malloc_debug.so. It is one thing less that might change AT_SECURE binaries' behavior due to environment configurations. Checked on x86_64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
* ldconfig: Fixes for skipping temporary files.Florian Weimer2023-11-201-4/+15
| | | | | | | | | | | Arguments to a memchr call were swapped, causing incorrect skipping of files. Files related to dpkg have different names: they actually end in .dpkg-new and .dpkg-tmp, not .tmp as I mistakenly assumed. Fixes commit 2aa0974d2573441bffd59 ("elf: ldconfig should skip temporary files created by package managers").
* nptl: Rename tst-execstack to tst-execstack-threadsFlorian Weimer2023-11-201-1/+6
| | | | | | | So that the test is harder to confuse with elf/tst-execstack (although the tests are supposed to be the same). Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
* elf: Fix force_first handling in dlclose (bug 30981)Florian Weimer2023-11-163-13/+29
| | | | | | | | | | | | | The force_first parameter was ineffective because the dlclose'd object was not necessarily the first in the maps array. Also enable force_first handling unconditionally, regardless of namespace. The initial object in a namespace should be destructed first, too. The _dl_sort_maps_dfs function had early returns for relocation dependency processing which broke force_first handling, too, and this is fixed in this change as well. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
* elf: Handle non-directory name in search path (BZ 31035)Adhemerval Zanella2023-11-165-3/+103
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The open_path stops if a relative path in search path contains a component that is a non directory (for instance, if the component is an existing file). For instance: $ cat > lib.c <<EOF > void foo (void) {} > EOF $ gcc -shared -fPIC -o lib.so lib.c $ cat > main.c <<EOF extern void foo (); int main () { foo (); return 0; } EOF $ gcc -o main main.c lib.so $ LD_LIBRARY_PATH=. ./main $ LD_LIBRARY_PATH=non-existing/path:. ./main $ LD_LIBRARY_PATH=$(pwd)/main:. ./main $ LD_LIBRARY_PATH=./main:. ./main ./main: error while loading shared libraries: lib.so: cannot open shared object file: No such file or directory The invalid './main' should be ignored as a non-existent one, instead as a valid but non accessible file. Absolute paths do not trigger this issue because their status are initialized as 'unknown' and open_path check if this is a directory. Checked on x86_64-linux-gnu. Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>