Re: [PATCH] elf: Fix ld.so SIGSEGV in trace mode with unresolved TLS symbols (BZ 34532)
Adhemerval Zanella Netto <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.alpha |
|---|---|
| Organization | Linaro |
| Message-ID | <[email protected]> |
Oops, I forgot to update it. Fixed locally.
On 20/08/26 06:56, mengqinggang wrote:
> The bug ID in elf/tst-trace-tls.c appears to be a placeholder (XXXXX).
>
>
> 在 2026/8/17 22:21, Adhemerval Zanella 写道:
>> On loongarch and hppa, running ld.so in trace mode on an object with
>> dynamic relocations against undefined TLS symbols crashes with SIGSEGV.
>>
>> Add the same NULL guards used by all other targets.
>>
>> Checked on loongarch64-linux-gnu-lp64d and hppa-linux-gnu.
>> ---
>> elf/Makefile | 5 +++
>> elf/tst-trace-tls-mod.c | 41 +++++++++++++++++
>> elf/tst-trace-tls.c | 82 ++++++++++++++++++++++++++++++++++
>> sysdeps/hppa/dl-machine.h | 4 +-
>> sysdeps/loongarch/dl-machine.h | 14 ++++--
>> 5 files changed, 141 insertions(+), 5 deletions(-)
>> create mode 100644 elf/tst-trace-tls-mod.c
>> create mode 100644 elf/tst-trace-tls.c
>>
>> diff --git a/elf/Makefile b/elf/Makefile
>> index dbc6cfec7fe..d9abbad1cf7 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>> @@ -529,6 +529,7 @@ tests += \
>> tst-tlsalign \
>> tst-tlsalign-extern \
>> tst-tlsgap \
>> + tst-trace-tls \
>> tst-unique1 \
>> tst-unique2 \
>> tst-unwind-ctor \
>> @@ -1108,6 +1109,7 @@ modules-names += \
>> tst-tlsmod7 \
>> tst-tlsmod8 \
>> tst-tlsmod9 \
>> + tst-trace-tls-mod \
>> tst-unique1mod1 \
>> tst-unique1mod2 \
>> tst-unique2mod1 \
>> @@ -3544,6 +3546,9 @@ $(objpfx)tst-nodeps2-mod.so: $(common-objpfx)libc.so \
>> $(objpfx)tst-nodeps2.out: \
>> $(objpfx)tst-nodeps1-mod.so $(objpfx)tst-nodeps2-mod.so
>> +$(objpfx)tst-trace-tls.out: $(objpfx)tst-trace-tls-mod.so $(objpfx)ld.so
>> +tst-trace-tls-mod.so-no-z-defs = yes
>> +
>> $(objpfx)tst-tlsgap: $(shared-thread-library)
>> $(objpfx)tst-tlsgap.out: \
>> $(objpfx)tst-tlsgap-mod0.so \
>> diff --git a/elf/tst-trace-tls-mod.c b/elf/tst-trace-tls-mod.c
>> new file mode 100644
>> index 00000000000..7b855fd814c
>> --- /dev/null
>> +++ b/elf/tst-trace-tls-mod.c
>> @@ -0,0 +1,41 @@
>> +/* Shared object with relocations against undefined TLS symbols.
>> + Copyright (C) 2026 Free Software Foundation, Inc.
>> + This file is part of the GNU C Library.
>> +
>> + The GNU C Library is free software; you can redistribute it and/or
>> + modify it under the terms of the GNU Lesser General Public
>> + License as published by the Free Software Foundation; either
>> + version 2.1 of the License, or (at your option) any later version.
>> +
>> + The GNU C Library is distributed in the hope that it will be useful,
>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + Lesser General Public License for more details.
>> +
>> + You should have received a copy of the GNU Lesser General Public
>> + License along with the GNU C Library; if not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +extern __thread int missing_tls_gd
>> + __attribute__ ((tls_model ("global-dynamic")));
>> +extern __thread int missing_tls_ie
>> + __attribute__ ((tls_model ("initial-exec")));
>> +extern int missing_data;
>> +
>> +int
>> +access_tls_gd (void)
>> +{
>> + return missing_tls_gd;
>> +}
>> +
>> +int
>> +access_tls_ie (void)
>> +{
>> + return missing_tls_ie;
>> +}
>> +
>> +int
>> +access_data (void)
>> +{
>> + return missing_data;
>> +}
>> diff --git a/elf/tst-trace-tls.c b/elf/tst-trace-tls.c
>> new file mode 100644
>> index 00000000000..2d541b1a519
>> --- /dev/null
>> +++ b/elf/tst-trace-tls.c
>> @@ -0,0 +1,82 @@
>> +/* Check that trace mode handles unresolved TLS symbols (bug XXXXX).
>> + Copyright (C) 2026 Free Software Foundation, Inc.
>> + This file is part of the GNU C Library.
>> +
>> + The GNU C Library is free software; you can redistribute it and/or
>> + modify it under the terms of the GNU Lesser General Public
>> + License as published by the Free Software Foundation; either
>> + version 2.1 of the License, or (at your option) any later version.
>> +
>> + The GNU C Library is distributed in the hope that it will be useful,
>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + Lesser General Public License for more details.
>> +
>> + You should have received a copy of the GNU Lesser General Public
>> + License along with the GNU C Library; if not, see
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +#include <support/capture_subprocess.h>
>> +#include <support/check.h>
>> +#include <support/support.h>
>> +
>> +/* Check if unresolved TLS symbol in trace mode (LD_TRACE_LOADED_OBJECTS)
>> + is correctly reported. */
>> +
>> +static char *mod;
>> +
>> +static struct support_capture_subprocess
>> +run_ldso (const char *env1, const char *env2)
>> +{
>> + char *const argv[] =
>> + { (char *) support_objdir_elf_ldso, (char *) mod, NULL };
>> + char *const envp[] =
>> + { (char *) "LD_TRACE_LOADED_OBJECTS=1", (char *) env1, (char *) env2,
>> + NULL };
>> +
>> + struct support_capture_subprocess result
>> + = support_capture_subprogram (argv[0], argv, envp);
>> + support_capture_subprocess_check (&result, "tst-trace-tls", 0,
>> + sc_allow_stdout | sc_allow_stderr);
>> + return result;
>> +}
>> +
>> +static void
>> +run_trace (const char *title, const char *env1, const char *env2,
>> + bool check_undefined)
>> +{
>> + printf ("info: checking %s\n", title);
>> +
>> + struct support_capture_subprocess result = run_ldso (env1, env2);
>> +
>> + if (check_undefined)
>> + {
>> + TEST_VERIFY (strstr (result.err.buffer,
>> + "undefined symbol: missing_tls_gd") != NULL);
>> + TEST_VERIFY (strstr (result.err.buffer,
>> + "undefined symbol: missing_tls_ie") != NULL);
>> + TEST_VERIFY (strstr (result.err.buffer,
>> + "undefined symbol: missing_data") != NULL);
>> + }
>> +
>> + support_capture_subprocess_free (&result);
>> +}
>> +
>> +static int
>> +do_test (void)
>> +{
>> + mod = xasprintf ("%s/elf/tst-trace-tls-mod.so", support_objdir_root);
>> +
>> + run_trace ("ldd -d", "LD_WARN=yes", NULL, true);
>> + run_trace ("ldd -r", "LD_WARN=yes", "LD_BIND_NOW=1", true);
>> + run_trace ("ldd -u", "LD_DEBUG=unused", NULL, false);
>> +
>> + free (mod);
>> +
>> + return 0;
>> +}
>> +
>> +#include <support/test-driver.c>
>> diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h
>> index 9bdbd85b6b3..ba2e4123c6e 100644
>> --- a/sysdeps/hppa/dl-machine.h
>> +++ b/sysdeps/hppa/dl-machine.h
>> @@ -700,7 +700,9 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
>> #if !defined RTLD_BOOTSTRAP
>> case R_PARISC_TLS_DTPMOD32:
>> - value = sym_map->l_tls_modid;
>> + /* The sym_map may be NULL in trace mode (LD_TRACE_LOADED_OBJECTS). */
>> + if (sym_map != NULL)
>> + value = sym_map->l_tls_modid;
>> break;
>> case R_PARISC_TLS_DTPOFF32:
>> diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
>> index ae295264ae9..1fb2635f92e 100644
>> --- a/sysdeps/loongarch/dl-machine.h
>> +++ b/sysdeps/loongarch/dl-machine.h
>> @@ -197,16 +197,22 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
>> #ifndef RTLD_BOOTSTRAP
>> case __WORDSIZE == 64 ? R_LARCH_TLS_DTPMOD64 : R_LARCH_TLS_DTPMOD32:
>> - *addr_field = sym_map->l_tls_modid;
>> + /* The sym_map may be NULL in trace mode (LD_TRACE_LOADED_OBJECTS). */
>> + if (sym_map != NULL)
>> + *addr_field = sym_map->l_tls_modid;
>> break;
>> case __WORDSIZE == 64 ? R_LARCH_TLS_DTPREL64 : R_LARCH_TLS_DTPREL32:
>> - *addr_field = TLS_DTPREL_VALUE (sym) + reloc->r_addend;
>> + if (sym != NULL)
>> + *addr_field = TLS_DTPREL_VALUE (sym) + reloc->r_addend;
>> break;
>> case __WORDSIZE == 64 ? R_LARCH_TLS_TPREL64 : R_LARCH_TLS_TPREL32:
>> - CHECK_STATIC_TLS (map, sym_map, sym);
>> - *addr_field = TLS_TPREL_VALUE (sym_map, sym) + reloc->r_addend;
>> + if (sym != NULL)
>> + {
>> + CHECK_STATIC_TLS (map, sym_map, sym);
>> + *addr_field = TLS_TPREL_VALUE (sym_map, sym) + reloc->r_addend;
>> + }
>> break;
>> case __WORDSIZE == 64 ? R_LARCH_TLS_DESC64 : R_LARCH_TLS_DESC32:
>