Re: [PATCH] elf: Fix ld.so SIGSEGV in trace mode with unresolved TLS symbols (BZ 34532)
mengqinggang <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.alpha |
|---|---|
| Message-ID | <[email protected]> |
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: