From fad7629617707e631c552f11aa9b776d76982cae Mon Sep 17 00:00:00 2001 From: xujing Date: Tue, 10 May 2022 11:14:32 +0800 Subject: [PATCH] elf: Fix initial-exec TLS access on audit modules (BZ #28096) --- ...exec-TLS-access-on-audit-modules-BZ-.patch | 313 ++++++++++++++++++ glibc.spec | 24 +- 2 files changed, 327 insertions(+), 10 deletions(-) create mode 100644 backport-elf-Fix-initial-exec-TLS-access-on-audit-modules-BZ-.patch diff --git a/backport-elf-Fix-initial-exec-TLS-access-on-audit-modules-BZ-.patch b/backport-elf-Fix-initial-exec-TLS-access-on-audit-modules-BZ-.patch new file mode 100644 index 0000000..1b28528 --- /dev/null +++ b/backport-elf-Fix-initial-exec-TLS-access-on-audit-modules-BZ-.patch @@ -0,0 +1,313 @@ +From ad8f9584a76a6fc9426e9dd0ba8cd7be46f3d931 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Mon, 24 Jan 2022 10:46:16 -0300 +Subject: [PATCH] elf: Fix initial-exec TLS access on audit modules (BZ #28096) + +For audit modules and dependencies with initial-exec TLS, we can not +set the initial TLS image on default loader initialization because it +would already be set by the audit setup. However, subsequent thread +creation would need to follow the default behaviour. + +This patch fixes it by setting l_auditing link_map field not only +for the audit modules, but also for all its dependencies. This is +used on _dl_allocate_tls_init to avoid the static TLS initialization +at load time. + +Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + +Reviewed-by: Carlos O'Donell +Tested-by: Carlos O'Donell +--- + elf/Makefile | 8 +++- + elf/dl-tls.c | 17 ++++++-- + elf/rtld.c | 2 +- + elf/tst-audit21.c | 42 ++++++++++++++++++++ + elf/tst-auditmod21a.c | 80 ++++++++++++++++++++++++++++++++++++++ + elf/tst-auditmod21b.c | 22 +++++++++++ + nptl/allocatestack.c | 2 +- + sysdeps/generic/ldsodefs.h | 2 +- + 8 files changed, 168 insertions(+), 7 deletions(-) + create mode 100644 elf/tst-audit21.c + create mode 100644 elf/tst-auditmod21a.c + create mode 100644 elf/tst-auditmod21b.c + +diff --git a/elf/Makefile b/elf/Makefile +index 302ce378..cb91b7e2 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -187,7 +187,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-dlmodcount tst-dlopenrpath tst-deep1 \ + tst-dlmopen1 tst-dlmopen3 \ + unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ +- tst-audit1 tst-audit2 tst-audit8 tst-audit9 \ ++ tst-audit1 tst-audit2 tst-audit8 tst-audit9 tst-audit21\ + tst-addr1 tst-thrlock \ + tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \ + tst-nodelete) \ +@@ -268,6 +268,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-unique1mod1 tst-unique1mod2 \ + tst-unique2mod1 tst-unique2mod2 \ + tst-auditmod9a tst-auditmod9b \ ++ tst-auditmod21a tst-auditmod21b \ + $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \ + tst-nodelete-uniquemod tst-nodelete-rtldmod \ + tst-nodelete-zmod) \ +@@ -1219,6 +1220,11 @@ $(objpfx)tst-audit8: $(libm) + $(objpfx)tst-audit8.out: $(objpfx)tst-auditmod1.so + tst-audit8-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so + ++$(objpfx)tst-audit21: $(shared-thread-library) ++$(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21a.so ++$(objpfx)tst-auditmod21a.so: $(objpfx)tst-auditmod21b.so ++tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21a.so ++ + $(objpfx)tst-global1: $(libdl) + $(objpfx)tst-global1.out: $(objpfx)testobj6.so $(objpfx)testobj2.so + +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index bb03f458..d9860c56 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -432,8 +432,12 @@ _dl_resize_dtv (dtv_t *dtv) + } + + ++/* Allocate initial TLS. RESULT should be a non-NULL pointer to storage ++ for the TLS space. The DTV may be resized, and so this function may ++ call malloc to allocate that space. The loader's GL(dl_load_tls_lock) ++ is taken when manipulating global TLS-related data in the loader. */ + void * +-_dl_allocate_tls_init (void *result) ++_dl_allocate_tls_init (void *result, bool init_tls) + { + if (result == NULL) + /* The memory allocation failed. */ +@@ -504,7 +508,14 @@ _dl_allocate_tls_init (void *result) + some platforms use in static programs requires it. */ + dtv[map->l_tls_modid].pointer.val = dest; + +- /* Copy the initialization image and clear the BSS part. */ ++ /* Copy the initialization image and clear the BSS part. For ++ audit modules or dependencies with initial-exec TLS, we can not ++ set the initial TLS image on default loader initialization ++ because it would already be set by the audit setup. However, ++ subsequent thread creation would need to follow the default ++ behaviour. */ ++ if (map->l_ns != LM_ID_BASE && !init_tls) ++ continue; + memset (__mempcpy (dest, map->l_tls_initimage, + map->l_tls_initimage_size), '\0', + map->l_tls_blocksize - map->l_tls_initimage_size); +@@ -534,7 +545,7 @@ _dl_allocate_tls (void *mem) + { + return _dl_allocate_tls_init (mem == NULL + ? _dl_allocate_tls_storage () +- : allocate_dtv (mem)); ++ : allocate_dtv (mem), true); + } + rtld_hidden_def (_dl_allocate_tls) + +diff --git a/elf/rtld.c b/elf/rtld.c +index 4abc6dd4..b069ca2c 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2219,7 +2219,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + into the main thread's TLS area, which we allocated above. + Note: thread-local variables must only be accessed after completing + the next step. */ +- _dl_allocate_tls_init (tcbp); ++ _dl_allocate_tls_init (tcbp, false); + + /* And finally install it for the main thread. */ + if (! tls_init_tp_called) +diff --git a/elf/tst-audit21.c b/elf/tst-audit21.c +new file mode 100644 +index 00000000..3a47ab64 +--- /dev/null ++++ b/elf/tst-audit21.c +@@ -0,0 +1,42 @@ ++/* Check LD_AUDIT with static TLS. ++ Copyright (C) 2022 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 ++ . */ ++ ++#include ++#include ++#include ++ ++static volatile __thread int out __attribute__ ((tls_model ("initial-exec"))); ++ ++static void * ++tf (void *arg) ++{ ++ TEST_COMPARE (out, 0); ++ out = isspace (' '); ++ return NULL; ++} ++ ++int main (int argc, char *argv[]) ++{ ++ TEST_COMPARE (out, 0); ++ out = isspace (' '); ++ ++ pthread_t t = xpthread_create (NULL, tf, NULL); ++ xpthread_join (t); ++ ++ return 0; ++} +diff --git a/elf/tst-auditmod21a.c b/elf/tst-auditmod21a.c +new file mode 100644 +index 00000000..f6d51b5c +--- /dev/null ++++ b/elf/tst-auditmod21a.c +@@ -0,0 +1,80 @@ ++/* Check LD_AUDIT with static TLS. ++ Copyright (C) 2022 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 ++ . */ ++ ++#include ++#include ++#include ++ ++#define tls_ie __attribute__ ((tls_model ("initial-exec"))) ++ ++__thread int tls_var0 tls_ie; ++__thread int tls_var1 tls_ie = 0x10; ++ ++/* Defined at tst-auditmod21b.so */ ++extern __thread int tls_var2; ++extern __thread int tls_var3; ++ ++static volatile int out; ++ ++static void ++call_libc (void) ++{ ++ /* isspace accesses the initial-exec glibc TLS variables, which are ++ setup in glibc initialization. */ ++ out = isspace (' '); ++} ++ ++unsigned int ++la_version (unsigned int v) ++{ ++ tls_var0 = 0x1; ++ if (tls_var1 != 0x10) ++ abort (); ++ tls_var1 = 0x20; ++ ++ tls_var2 = 0x2; ++ if (tls_var3 != 0x20) ++ abort (); ++ tls_var3 = 0x40; ++ ++ call_libc (); ++ ++ return LAV_CURRENT; ++} ++ ++unsigned int ++la_objopen (struct link_map* map, Lmid_t lmid, uintptr_t* cookie) ++{ ++ call_libc (); ++ *cookie = (uintptr_t) map; ++ return 0; ++} ++ ++void ++la_activity (uintptr_t* cookie, unsigned int flag) ++{ ++ if (tls_var0 != 0x1 || tls_var1 != 0x20) ++ abort (); ++ call_libc (); ++} ++ ++void ++la_preinit (uintptr_t* cookie) ++{ ++ call_libc (); ++} +diff --git a/elf/tst-auditmod21b.c b/elf/tst-auditmod21b.c +new file mode 100644 +index 00000000..6ba5335b +--- /dev/null ++++ b/elf/tst-auditmod21b.c +@@ -0,0 +1,22 @@ ++/* Check LD_AUDIT with static TLS. ++ Copyright (C) 2022 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 ++ . */ ++ ++#define tls_ie __attribute__ ((tls_model ("initial-exec"))) ++ ++__thread int tls_var2 tls_ie; ++__thread int tls_var3 tls_ie = 0x20; +diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c +index d0971a97..88fa41d5 100644 +--- a/nptl/allocatestack.c ++++ b/nptl/allocatestack.c +@@ -244,7 +244,7 @@ get_cached_stack (size_t *sizep, void **memp) + memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t)); + + /* Re-initialize the TLS. */ +- _dl_allocate_tls_init (TLS_TPADJ (result)); ++ _dl_allocate_tls_init (TLS_TPADJ (result), true); + + return result; + } +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 4e956593..495b37ed 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1095,7 +1095,7 @@ extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden; + /* These are internal entry points to the two halves of _dl_allocate_tls, + only used within rtld.c itself at startup time. */ + extern void *_dl_allocate_tls_storage (void) attribute_hidden; +-extern void *_dl_allocate_tls_init (void *); ++extern void *_dl_allocate_tls_init (void *, bool); + rtld_hidden_proto (_dl_allocate_tls_init) + + /* Deallocate memory allocated with _dl_allocate_tls. */ +-- +2.27.0 + diff --git a/glibc.spec b/glibc.spec index 7ab7ec9..9a1878f 100644 --- a/glibc.spec +++ b/glibc.spec @@ -59,7 +59,7 @@ ############################################################################## Name: glibc Version: 2.28 -Release: 88 +Release: 89 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -141,15 +141,16 @@ Patch57: backport-gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch Patch58: backport-nss-make-sure-startp_initialized-do-first.patch Patch59: backport-glibc-fix-CVE-2019-1010023.patch Patch60: backport-fix-pthread_create-and-dlopen-racing.patch -Patch61: revert-Add-miss-brackets.patch -Patch62: Rewrite-iconv-option-parsing-BZ-19519.patch -Patch63: intl-Handle-translation-output-codesets-with-suffixes-BZ-26383.patch -Patch64: socket-Add-the-__sockaddr_un_set-function.patch -Patch65: CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch -Patch66: sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch -Patch67: CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch -Patch68: getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch -Patch69: x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch +Patch61: backport-elf-Fix-initial-exec-TLS-access-on-audit-modules-BZ-.patch +Patch62: revert-Add-miss-brackets.patch +Patch63: Rewrite-iconv-option-parsing-BZ-19519.patch +Patch64: intl-Handle-translation-output-codesets-with-suffixes-BZ-26383.patch +Patch65: socket-Add-the-__sockaddr_un_set-function.patch +Patch66: CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch +Patch67: sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch +Patch68: CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch +Patch69: getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch +Patch70: x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) @@ -1174,6 +1175,9 @@ fi %doc hesiod/README.hesiod %changelog +* Tue May 10 2022 xujing - 2.28-89 +- elf: Fix initial-exec TLS access on audit modules (BZ #28096) + * Fri Jan 28 2022 Qingqing Li - 2.28-88 - Fix __cscncmp_avx2 in strcmp-avx2.S [BZ#28755] -- Gitee