From 6b1ce0df404b9d1908f768b733a9dfcd17d39050 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Tue, 11 Oct 2022 16:15:26 +0200 Subject: [PATCH] Import glibc-2.34-47.fc35 from f35 * Tue Oct 11 2022 Florian Weimer - 2.34-47 - Simplify the glibc system call profile (#2117712) * Tue Oct 11 2022 Florian Weimer - 2.34-46 - DSO dependency sort must put new map first even if in cycle (#2128615) * Tue Oct 11 2022 Florian Weimer - 2.34-45 - Run tst-audit-tlsdesc{,-dlopen} on all architectures (#2118666) Resolves: RHELX-69 Resolves: #2118666 Resolves: #2128615 --- glibc-rh2117712-1.patch | 154 +++++++++++++++++++++++++++++++++++++ glibc-rh2117712-2.patch | 45 +++++++++++ glibc-rh2117712-3.patch | 164 ++++++++++++++++++++++++++++++++++++++++ glibc-rh2117712-4.patch | 22 ++++++ glibc-rh2117712-5.patch | 69 +++++++++++++++++ glibc-rh2117712-6.patch | 35 +++++++++ glibc-rh2118666.patch | 94 +++++++++++++++++++++++ glibc-rh2128615-1.patch | 37 +++++++++ glibc-rh2128615-2.patch | 79 +++++++++++++++++++ glibc-rh2128615-3.patch | 90 ++++++++++++++++++++++ glibc.spec | 21 ++++- 11 files changed, 809 insertions(+), 1 deletion(-) create mode 100644 glibc-rh2117712-1.patch create mode 100644 glibc-rh2117712-2.patch create mode 100644 glibc-rh2117712-3.patch create mode 100644 glibc-rh2117712-4.patch create mode 100644 glibc-rh2117712-5.patch create mode 100644 glibc-rh2117712-6.patch create mode 100644 glibc-rh2118666.patch create mode 100644 glibc-rh2128615-1.patch create mode 100644 glibc-rh2128615-2.patch create mode 100644 glibc-rh2128615-3.patch diff --git a/glibc-rh2117712-1.patch b/glibc-rh2117712-1.patch new file mode 100644 index 0000000..e154365 --- /dev/null +++ b/glibc-rh2117712-1.patch @@ -0,0 +1,154 @@ +commit cca9684f2d7a74fc0b28bfb1859955e0e28d7b4b +Author: Florian Weimer +Date: Wed Aug 3 11:41:53 2022 +0200 + + stdio: Clean up __libc_message after unconditional abort + + Since commit ec2c1fcefb200c6cb7e09553f3c6af8815013d83 ("malloc: + Abort on heap corruption, without a backtrace [BZ #21754]"), + __libc_message always terminates the process. Since commit + a289ea09ea843ced6e5277c2f2e63c357bc7f9a3 ("Do not print backtraces + on fatal glibc errors"), the backtrace facility has been removed. + Therefore, remove enum __libc_message_action and the action + argument of __libc_message, and mark __libc_message as _No_return. + + Reviewed-by: Adhemerval Zanella + +diff --git a/debug/fortify_fail.c b/debug/fortify_fail.c +index 9fa07af4867c2bd1..1b490d9da78b8d0d 100644 +--- a/debug/fortify_fail.c ++++ b/debug/fortify_fail.c +@@ -21,8 +21,6 @@ void + __attribute__ ((noreturn)) + __fortify_fail (const char *msg) + { +- /* The loop is added only to keep gcc happy. */ +- while (1) +- __libc_message (do_abort, "*** %s ***: terminated\n", msg); ++ __libc_message ("*** %s ***: terminated\n", msg); + } + libc_hidden_def (__fortify_fail) +diff --git a/include/stdio.h b/include/stdio.h +index 23b7fd288cdaba66..3d4544575318a934 100644 +--- a/include/stdio.h ++++ b/include/stdio.h +@@ -143,18 +143,11 @@ extern int __gen_tempname (char *__tmpl, int __suffixlen, int __flags, + # define __GT_DIR 1 /* create a directory */ + # define __GT_NOCREATE 2 /* just find a name not currently in use */ + +-enum __libc_message_action +-{ +- do_message = 0, /* Print message. */ +- do_abort = 1 << 0, /* Abort. */ +-}; +- + /* Print out MESSAGE (which should end with a newline) on the error output + and abort. */ + extern void __libc_fatal (const char *__message) + __attribute__ ((__noreturn__)); +-extern void __libc_message (enum __libc_message_action action, +- const char *__fnt, ...) attribute_hidden; ++_Noreturn void __libc_message (const char *__fnt, ...) attribute_hidden; + extern void __fortify_fail (const char *msg) __attribute__ ((__noreturn__)); + libc_hidden_proto (__fortify_fail) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index d31e985ecce968fe..918e7936f1983437 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -298,8 +298,7 @@ _Noreturn static void + __malloc_assert (const char *assertion, const char *file, unsigned int line, + const char *function) + { +- __libc_message (do_abort, "\ +-Fatal glibc error: malloc assertion failure in %s: %s\n", ++ __libc_message ("Fatal glibc error: malloc assertion failure in %s: %s\n", + function, assertion); + __builtin_unreachable (); + } +@@ -5528,7 +5527,7 @@ static void + malloc_printerr (const char *str) + { + #if IS_IN (libc) +- __libc_message (do_abort, "%s\n", str); ++ __libc_message ("%s\n", str); + #else + __libc_fatal (str); + #endif +diff --git a/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c +index 6d24bee6134856d1..1feacfbeba765035 100644 +--- a/sysdeps/posix/libc_fatal.c ++++ b/sysdeps/posix/libc_fatal.c +@@ -54,7 +54,7 @@ struct str_list + + /* Abort with an error message. */ + void +-__libc_message (enum __libc_message_action action, const char *fmt, ...) ++__libc_message (const char *fmt, ...) + { + va_list ap; + int fd = -1; +@@ -123,36 +123,31 @@ __libc_message (enum __libc_message_action action, const char *fmt, ...) + + WRITEV_FOR_FATAL (fd, iov, nlist, total); + +- if ((action & do_abort)) ++ total = (total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1); ++ struct abort_msg_s *buf = __mmap (NULL, total, ++ PROT_READ | PROT_WRITE, ++ MAP_ANON | MAP_PRIVATE, -1, 0); ++ if (__glibc_likely (buf != MAP_FAILED)) + { +- total = ((total + 1 + GLRO(dl_pagesize) - 1) +- & ~(GLRO(dl_pagesize) - 1)); +- struct abort_msg_s *buf = __mmap (NULL, total, +- PROT_READ | PROT_WRITE, +- MAP_ANON | MAP_PRIVATE, -1, 0); +- if (__glibc_likely (buf != MAP_FAILED)) +- { +- buf->size = total; +- char *wp = buf->msg; +- for (int cnt = 0; cnt < nlist; ++cnt) +- wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); +- *wp = '\0'; +- +- /* We have to free the old buffer since the application might +- catch the SIGABRT signal. */ +- struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg, +- buf); +- if (old != NULL) +- __munmap (old, old->size); +- } ++ buf->size = total; ++ char *wp = buf->msg; ++ for (int cnt = 0; cnt < nlist; ++cnt) ++ wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len); ++ *wp = '\0'; ++ ++ /* We have to free the old buffer since the application might ++ catch the SIGABRT signal. */ ++ struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg, ++ buf); ++ if (old != NULL) ++ __munmap (old, old->size); + } + } + + va_end (ap); + +- if ((action & do_abort)) +- /* Kill the application. */ +- abort (); ++ /* Kill the application. */ ++ abort (); + } + + +@@ -161,6 +156,6 @@ __libc_fatal (const char *message) + { + /* The loop is added only to keep gcc happy. */ + while (1) +- __libc_message (do_abort, "%s", message); ++ __libc_message ("%s", message); + } + libc_hidden_def (__libc_fatal) diff --git a/glibc-rh2117712-2.patch b/glibc-rh2117712-2.patch new file mode 100644 index 0000000..0a55182 --- /dev/null +++ b/glibc-rh2117712-2.patch @@ -0,0 +1,45 @@ +commit 68e036f27f31c3378201702e182246504fb00f87 +Author: Florian Weimer +Date: Wed Aug 3 11:41:53 2022 +0200 + + nptl: Remove uses of assert_perror + + __pthread_sigmask cannot actually fail with valid pointer arguments + (it would need a really broken seccomp filter), and we do not check + for errors elsewhere. + + Reviewed-by: Adhemerval Zanella + +diff --git a/sysdeps/nptl/gai_misc.h b/sysdeps/nptl/gai_misc.h +index 261e24dae62d7871..700fd5c46b4b7c82 100644 +--- a/sysdeps/nptl/gai_misc.h ++++ b/sysdeps/nptl/gai_misc.h +@@ -81,9 +81,7 @@ __gai_start_notify_thread (void) + { + sigset_t ss; + sigemptyset (&ss); +- int sigerr __attribute__ ((unused)); +- sigerr = __pthread_sigmask (SIG_SETMASK, &ss, NULL); +- assert_perror (sigerr); ++ (void) __pthread_sigmask (SIG_SETMASK, &ss, NULL); + } + + extern inline int +@@ -106,15 +104,12 @@ __gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), + sigset_t ss; + sigset_t oss; + sigfillset (&ss); +- int sigerr __attribute__ ((unused)); +- sigerr = __pthread_sigmask (SIG_SETMASK, &ss, &oss); +- assert_perror (sigerr); ++ (void) __pthread_sigmask (SIG_SETMASK, &ss, &oss); + + int ret = __pthread_create (threadp, &attr, tf, arg); + + /* Restore the signal mask. */ +- sigerr = __pthread_sigmask (SIG_SETMASK, &oss, NULL); +- assert_perror (sigerr); ++ (void) __pthread_sigmask (SIG_SETMASK, &oss, NULL); + + (void) __pthread_attr_destroy (&attr); + return ret; diff --git a/glibc-rh2117712-3.patch b/glibc-rh2117712-3.patch new file mode 100644 index 0000000..e3cf26e --- /dev/null +++ b/glibc-rh2117712-3.patch @@ -0,0 +1,164 @@ +commit 9001cb1102cddba54f0e84e147dfbb0356067356 +Author: Florian Weimer +Date: Wed Aug 3 11:41:53 2022 +0200 + + assert: Do not use stderr in libc-internal assert + + Redirect internal assertion failures to __libc_assert_fail, based on + based on __libc_message, which writes directly to STDERR_FILENO + and calls abort. Also disable message translation and reword the + error message slightly (adjusting stdlib/tst-bz20544 accordingly). + + As a result of these changes, malloc no longer needs its own + redefinition of __assert_fail. + + __libc_assert_fail needs to be stubbed out during rtld dependency + analysis because the rtld rebuilds turn __libc_assert_fail into + __assert_fail, which is unconditionally provided by elf/dl-minimal.c. + + This change is not possible for the public assert macro and its + __assert_fail function because POSIX requires that the diagnostic + is written to stderr. + + Reviewed-by: Adhemerval Zanella + +diff --git a/assert/Makefile b/assert/Makefile +index 0008de34cb484a13..2bc9e2214e3e9a8b 100644 +--- a/assert/Makefile ++++ b/assert/Makefile +@@ -24,7 +24,12 @@ include ../Makeconfig + + headers := assert.h + +-routines := assert assert-perr __assert ++routines := \ ++ __assert \ ++ __libc_assert_fail \ ++ assert \ ++ assert-perr \ ++ # routines + tests := test-assert test-assert-perr tst-assert-c++ tst-assert-g++ + + ifeq ($(have-cxx-thread_local),yes) +diff --git a/assert/__libc_assert_fail.c b/assert/__libc_assert_fail.c +new file mode 100644 +index 0000000000000000..149d5feae12f4af8 +--- /dev/null ++++ b/assert/__libc_assert_fail.c +@@ -0,0 +1,33 @@ ++/* libc-internal assert that calls __libc_message. ++ 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 <_itoa.h> ++#include ++#include ++#include ++ ++void ++__libc_assert_fail (const char *assertion, const char *file, unsigned int line, ++ const char *function) ++{ ++ char linebuf[INT_BUFSIZE_BOUND (unsigned int)]; ++ array_end (linebuf)[-1] = '\0'; ++ char *linestr = _itoa_word (line, array_end (linebuf) - 1, 10, 0); ++ __libc_message ("Fatal glibc error: %s:%s (%s): assertion failed: %s\n", ++ file, linestr, function, assertion); ++} +diff --git a/assert/assert.c b/assert/assert.c +index 8a277dce008b3495..989126c7e5b6b265 100644 +--- a/assert/assert.c ++++ b/assert/assert.c +@@ -101,4 +101,3 @@ __assert_fail (const char *assertion, const char *file, unsigned int line, + __assert_fail_base (_("%s%s%s:%u: %s%sAssertion `%s' failed.\n%n"), + assertion, file, line, function); + } +-hidden_def(__assert_fail) +diff --git a/elf/Makefile b/elf/Makefile +index 613d244e7781d479..2b547d5b58f1759b 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -1158,6 +1158,7 @@ $(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os) + rtld-stubbed-symbols = \ + __GI___pthread_disable_asynccancel \ + __GI___pthread_enable_asynccancel \ ++ __libc_assert_fail \ + __pthread_disable_asynccancel \ + __pthread_enable_asynccancel \ + calloc \ +diff --git a/include/assert.h b/include/assert.h +index 61cc8aa22ff4b913..c812808f9b767964 100644 +--- a/include/assert.h ++++ b/include/assert.h +@@ -20,8 +20,14 @@ extern void __assert_fail_base (const char *fmt, const char *assertion, + const char *function) + __THROW __attribute__ ((__noreturn__)) attribute_hidden; + +-# if IS_IN (libc) || (IS_IN (rtld) && !defined NO_RTLD_HIDDEN) +-hidden_proto (__assert_fail) +-hidden_proto (__assert_perror_fail) ++rtld_hidden_proto (__assert_fail) ++rtld_hidden_proto (__assert_perror_fail) ++libc_hidden_proto (__assert_perror_fail) ++ ++ ++# if IS_IN (libc) ++/* Redirect to the internal version which does not use stderr. */ ++extern _Noreturn __typeof (__assert_fail) __libc_assert_fail attribute_hidden; ++# define __assert_fail __libc_assert_fail + # endif + #endif +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 918e7936f1983437..2edb469d5dbf1203 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -289,22 +289,6 @@ + #define MALLOC_DEBUG 0 + #endif + +-#if IS_IN (libc) +-#ifndef NDEBUG +-# define __assert_fail(assertion, file, line, function) \ +- __malloc_assert(assertion, file, line, function) +- +-_Noreturn static void +-__malloc_assert (const char *assertion, const char *file, unsigned int line, +- const char *function) +-{ +- __libc_message ("Fatal glibc error: malloc assertion failure in %s: %s\n", +- function, assertion); +- __builtin_unreachable (); +-} +-#endif +-#endif +- + #if USE_TCACHE + /* We want 64 entries. This is an arbitrary limit, which tunables can reduce. */ + # define TCACHE_MAX_BINS 64 +diff --git a/stdlib/tst-bz20544.c b/stdlib/tst-bz20544.c +index 4aa5793b8994d1f6..1337a3952c30e517 100644 +--- a/stdlib/tst-bz20544.c ++++ b/stdlib/tst-bz20544.c +@@ -78,7 +78,7 @@ test_bz20544_cxa_at_quick_exit (void *closure) + static void + test_one_fn (void (*test_fn) (void *)) + { +- const char expected_error[] = "Assertion `func != NULL' failed.\n"; ++ const char expected_error[] = "assertion failed: func != NULL\n"; + struct support_capture_subprocess result; + result = support_capture_subprocess (test_fn, NULL); + support_capture_subprocess_check (&result, "bz20544", -SIGABRT, diff --git a/glibc-rh2117712-4.patch b/glibc-rh2117712-4.patch new file mode 100644 index 0000000..1d0a420 --- /dev/null +++ b/glibc-rh2117712-4.patch @@ -0,0 +1,22 @@ +commit 8fabe0e632bd441c760f878d1022c378f04f8497 +Author: Florian Weimer +Date: Thu Aug 4 06:17:50 2022 +0200 + + Linux: Remove exit system call from _exit + + exit only terminates the current thread, not the whole process, so it + is the wrong fallback system call in this context. All supported + Linux versions implement the exit_group system call anyway. + +diff --git a/sysdeps/unix/sysv/linux/_exit.c b/sysdeps/unix/sysv/linux/_exit.c +index 2f0ec35459f25314..cd1270ac9b2b5b2b 100644 +--- a/sysdeps/unix/sysv/linux/_exit.c ++++ b/sysdeps/unix/sysv/linux/_exit.c +@@ -28,7 +28,6 @@ _exit (int status) + while (1) + { + INLINE_SYSCALL (exit_group, 1, status); +- INLINE_SYSCALL (exit, 1, status); + + #ifdef ABORT_INSTRUCTION + ABORT_INSTRUCTION; diff --git a/glibc-rh2117712-5.patch b/glibc-rh2117712-5.patch new file mode 100644 index 0000000..e147fa2 --- /dev/null +++ b/glibc-rh2117712-5.patch @@ -0,0 +1,69 @@ +Very limited backport of the following upstream commit, to obtain +the definition of __getrandom_nocancel. + +commit 6f4e0fcfa2d2b0915816a3a3a1d48b4763a7dee2 +Author: Adhemerval Zanella Netto +Date: Thu Jul 21 10:04:59 2022 -0300 + + stdlib: Add arc4random, arc4random_buf, and arc4random_uniform (BZ #4417) + +With the INTERNAL_SYSCALL_CALL change from this patch already applied: + +commit 609c9d0951da387cd523b5db42a82d38dabc37c4 +Author: Adhemerval Zanella +Date: Thu Sep 29 16:18:06 2022 -0300 + + malloc: Do not clobber errno on __getrandom_nocancel (BZ #29624) + + Use INTERNAL_SYSCALL_CALL instead of INLINE_SYSCALL_CALL. This + requires emulate the semantic for hurd call (so __arc4random_buf + uses the fallback). + + Checked on x86_64-linux-gnu. + + Reviewed-by: Wilco Dijkstra + +diff --git a/sysdeps/generic/not-cancel.h b/sysdeps/generic/not-cancel.h +index 8a3772a1fe66271e..14188041c2c0ad57 100644 +--- a/sysdeps/generic/not-cancel.h ++++ b/sysdeps/generic/not-cancel.h +@@ -49,5 +49,7 @@ + (void) __writev (fd, iov, n) + #define __fcntl64_nocancel(fd, cmd, ...) \ + __fcntl64 (fd, cmd, __VA_ARGS__) ++#define __getrandom_nocancel(buf, size, flags) \ ++ __getrandom (buf, size, flags) + + #endif /* NOT_CANCEL_H */ +diff --git a/sysdeps/mach/hurd/not-cancel.h b/sysdeps/mach/hurd/not-cancel.h +index cd320cb721e6ff7e..7a3d2cc3532cf866 100644 +--- a/sysdeps/mach/hurd/not-cancel.h ++++ b/sysdeps/mach/hurd/not-cancel.h +@@ -75,6 +75,9 @@ __typeof (__fcntl) __fcntl_nocancel; + #define __fcntl64_nocancel(...) \ + __fcntl_nocancel (__VA_ARGS__) + ++#define __getrandom_nocancel(buf, size, flags) \ ++ __getrandom (buf, size, flags) ++ + #if IS_IN (libc) + hidden_proto (__close_nocancel) + hidden_proto (__close_nocancel_nostatus) +diff --git a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/linux/not-cancel.h +index f06d57426a40227e..d2bb59acddbcfee0 100644 +--- a/sysdeps/unix/sysv/linux/not-cancel.h ++++ b/sysdeps/unix/sysv/linux/not-cancel.h +@@ -68,6 +68,13 @@ __writev_nocancel_nostatus (int fd, const struct iovec *iov, int iovcnt) + INTERNAL_SYSCALL_CALL (writev, fd, iov, iovcnt); + } + ++static inline int ++__getrandom_nocancel (void *buf, size_t buflen, unsigned int flags) ++{ ++ return INTERNAL_SYSCALL_CALL (getrandom, buf, buflen, flags); ++} ++ ++ + /* Uncancelable fcntl. */ + __typeof (__fcntl) __fcntl64_nocancel; + diff --git a/glibc-rh2117712-6.patch b/glibc-rh2117712-6.patch new file mode 100644 index 0000000..33766ff --- /dev/null +++ b/glibc-rh2117712-6.patch @@ -0,0 +1,35 @@ +commit 7187efd0aa270c83c428ea6cd0e1cffc34b41a74 +Author: Florian Weimer +Date: Mon Aug 1 15:49:07 2022 +0200 + + malloc: Use __getrandom_nocancel during tcache initiailization + + Cancellation currently cannot happen at this point because dlopen + as used by the unwind link always performs additional allocations + for libgcc_s.so.1, even if it has been loaded already as a dependency + of the main executable. But it seems prudent not to rely on this + quirk. + + Reviewed-by: Adhemerval Zanella + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 2edb469d5dbf1203..375f50f5db13e234 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -256,6 +256,7 @@ + /* For tcache double-free check. */ + #include + #include ++#include + + /* + Debugging: +@@ -3025,7 +3026,7 @@ static uintptr_t tcache_key; + static void + tcache_key_initialize (void) + { +- if (__getrandom (&tcache_key, sizeof(tcache_key), GRND_NONBLOCK) ++ if (__getrandom_nocancel (&tcache_key, sizeof(tcache_key), GRND_NONBLOCK) + != sizeof (tcache_key)) + { + tcache_key = random_bits (); diff --git a/glibc-rh2118666.patch b/glibc-rh2118666.patch new file mode 100644 index 0000000..86750f6 --- /dev/null +++ b/glibc-rh2118666.patch @@ -0,0 +1,94 @@ +commit dd2315a866a4ac2b838ea1cb10c5ea1c35d51a2f +Author: Florian Weimer +Date: Tue Aug 16 08:27:50 2022 +0200 + + elf: Run tst-audit-tlsdesc, tst-audit-tlsdesc-dlopen everywhere + + The test is valid for all TLS models, but we want to make a reasonable + effort to test the GNU2 model specifically. For example, aarch64 + defaults to GNU2, but does not have -mtls-dialect=gnu2, and the test + was not run there. + + Suggested-by: Martin Coufal + +Conflicts: + elf/Makefile + (missing tst-align3 test downstream) + +diff --git a/elf/Makefile b/elf/Makefile +index ea1512549be3f628..613d244e7781d479 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -361,6 +361,8 @@ tests += \ + tst-addr1 \ + tst-align \ + tst-align2 \ ++ tst-audit-tlsdesc \ ++ tst-audit-tlsdesc-dlopen \ + tst-audit1 \ + tst-audit2 \ + tst-audit8 \ +@@ -679,6 +681,8 @@ modules-names = \ + tst-alignmod2 \ + tst-array2dep \ + tst-array5dep \ ++ tst-audit-tlsdesc-mod1 \ ++ tst-audit-tlsdesc-mod2 \ + tst-audit11mod1 \ + tst-audit11mod2 \ + tst-audit12mod1 \ +@@ -712,6 +716,7 @@ modules-names = \ + tst-auditmanymod7 \ + tst-auditmanymod8 \ + tst-auditmanymod9 \ ++ tst-auditmod-tlsdesc \ + tst-auditmod1 \ + tst-auditmod9a \ + tst-auditmod9b \ +@@ -889,23 +894,8 @@ modules-names += tst-gnu2-tls1mod + $(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so + tst-gnu2-tls1mod.so-no-z-defs = yes + CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2 ++endif # $(have-mtls-dialect-gnu2) + +-tests += tst-audit-tlsdesc tst-audit-tlsdesc-dlopen +-modules-names += tst-audit-tlsdesc-mod1 tst-audit-tlsdesc-mod2 tst-auditmod-tlsdesc +-$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \ +- $(objpfx)tst-audit-tlsdesc-mod2.so \ +- $(shared-thread-library) +-CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2 +-CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2 +-$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library) +-$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \ +- $(objpfx)tst-audit-tlsdesc-mod2.so +-$(objpfx)tst-audit-tlsdesc-mod1.so: $(objpfx)tst-audit-tlsdesc-mod2.so +-$(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so +-tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so +-$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so +-tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so +-endif + ifeq (yes,$(have-protected-data)) + modules-names += tst-protected1moda tst-protected1modb + tests += tst-protected1a tst-protected1b +@@ -2656,3 +2646,21 @@ $(objpfx)tst-tls-allocation-failure-static-patched.out: \ + grep -q '^Fatal glibc error: Cannot allocate TLS block$$' $@ \ + && grep -q '^status: 127$$' $@; \ + $(evaluate-test) ++ ++$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \ ++ $(objpfx)tst-audit-tlsdesc-mod2.so \ ++ $(shared-thread-library) ++ifeq (yes,$(have-mtls-dialect-gnu2)) ++# The test is valid for all TLS types, but we want to exercise GNU2 ++# TLS if possible. ++CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2 ++CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2 ++endif ++$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library) ++$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \ ++ $(objpfx)tst-audit-tlsdesc-mod2.so ++$(objpfx)tst-audit-tlsdesc-mod1.so: $(objpfx)tst-audit-tlsdesc-mod2.so ++$(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so ++tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so ++$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so ++tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so diff --git a/glibc-rh2128615-1.patch b/glibc-rh2128615-1.patch new file mode 100644 index 0000000..b4783d8 --- /dev/null +++ b/glibc-rh2128615-1.patch @@ -0,0 +1,37 @@ +commit 183d99737298bb3200f0610fdcd1c7549c8ed560 +Author: Florian Weimer +Date: Tue Sep 6 07:38:10 2022 +0200 + + scripts/dso-ordering-test.py: Generate program run-time dependencies + + The main program needs to depend on all shared objects, even objects + that have link-time dependencies among shared objects. Filtering + out shared objects that already have an link-time dependencies is not + necessary here; make will do this automatically. + + Reviewed-by: Adhemerval Zanella + +diff --git a/scripts/dso-ordering-test.py b/scripts/dso-ordering-test.py +index bde0406be9da14fc..4ffcff6136145ef1 100644 +--- a/scripts/dso-ordering-test.py ++++ b/scripts/dso-ordering-test.py +@@ -707,13 +707,12 @@ def process_testcase(t): + "\t$(compile.c) $(OUTPUT_OPTION)\n") + makefile.write (rule) + +- not_depended_objs = find_objs_not_depended_on(test_descr) +- if not_depended_objs: +- depstr = "" +- for dep in not_depended_objs: +- depstr += (" $(objpfx)" + test_subdir + "/" +- + test_name + "-" + dep + ".so") +- makefile.write("$(objpfx)%s.out:%s\n" % (base_test_name, depstr)) ++ # Ensure that all shared objects are built before running the ++ # test, whether there link-time dependencies or not. ++ depobjs = ["$(objpfx){}/{}-{}.so".format(test_subdir, test_name, dep) ++ for dep in test_descr.objs] ++ makefile.write("$(objpfx){}.out: {}\n".format( ++ base_test_name, " ".join(depobjs))) + + # Add main executable to test-srcs + makefile.write("test-srcs += %s/%s\n" % (test_subdir, test_name)) diff --git a/glibc-rh2128615-2.patch b/glibc-rh2128615-2.patch new file mode 100644 index 0000000..2d8d4ac --- /dev/null +++ b/glibc-rh2128615-2.patch @@ -0,0 +1,79 @@ +commit dbb75513f5cf9285c77c9e55777c5c35b653f890 +Author: Florian Weimer +Date: Tue Sep 6 07:38:10 2022 +0200 + + elf: Rename _dl_sort_maps parameter from skip to force_first + + The new implementation will not be able to skip an arbitrary number + of objects. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c +index 72f4ff0e6eda3377..7c614bca5d8115c6 100644 +--- a/elf/dl-sort-maps.c ++++ b/elf/dl-sort-maps.c +@@ -27,12 +27,12 @@ + If FOR_FINI is true, this is called for finishing an object. */ + static void + _dl_sort_maps_original (struct link_map **maps, unsigned int nmaps, +- unsigned int skip, bool for_fini) ++ bool force_first, bool for_fini) + { + /* Allows caller to do the common optimization of skipping the first map, + usually the main binary. */ +- maps += skip; +- nmaps -= skip; ++ maps += force_first; ++ nmaps -= force_first; + + /* A list of one element need not be sorted. */ + if (nmaps <= 1) +@@ -182,7 +182,7 @@ dfs_traversal (struct link_map ***rpo, struct link_map *map, + + static void + _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps, +- unsigned int skip __attribute__ ((unused)), bool for_fini) ++ bool force_first __attribute__ ((unused)), bool for_fini) + { + for (int i = nmaps - 1; i >= 0; i--) + maps[i]->l_visited = 0; +@@ -286,7 +286,7 @@ _dl_sort_maps_init (void) + + void + _dl_sort_maps (struct link_map **maps, unsigned int nmaps, +- unsigned int skip, bool for_fini) ++ bool force_first, bool for_fini) + { + /* It can be tempting to use a static function pointer to store and call + the current selected sorting algorithm routine, but experimentation +@@ -296,9 +296,9 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps, + input cases. A simple if-case with direct function calls appears to + be the fastest. */ + if (__glibc_likely (GLRO(dl_dso_sort_algo) == dso_sort_algorithm_original)) +- _dl_sort_maps_original (maps, nmaps, skip, for_fini); ++ _dl_sort_maps_original (maps, nmaps, force_first, for_fini); + else +- _dl_sort_maps_dfs (maps, nmaps, skip, for_fini); ++ _dl_sort_maps_dfs (maps, nmaps, force_first, for_fini); + } + + #endif /* HAVE_TUNABLES. */ +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 87ad2f3f4d89eb7d..8c0fe98f69a88f1e 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1106,9 +1106,11 @@ extern void _dl_init (struct link_map *main_map, int argc, char **argv, + initializer functions have completed. */ + extern void _dl_fini (void) attribute_hidden; + +-/* Sort array MAPS according to dependencies of the contained objects. */ ++/* Sort array MAPS according to dependencies of the contained objects. ++ If FORCE_FIRST, MAPS[0] keeps its place even if the dependencies ++ say otherwise. */ + extern void _dl_sort_maps (struct link_map **maps, unsigned int nmaps, +- unsigned int skip, bool for_fini) attribute_hidden; ++ bool force_first, bool for_fini) attribute_hidden; + + /* The dynamic linker calls this function before and having changing + any shared object mappings. The `r_state' member of `struct r_debug' diff --git a/glibc-rh2128615-3.patch b/glibc-rh2128615-3.patch new file mode 100644 index 0000000..bf8a9a4 --- /dev/null +++ b/glibc-rh2128615-3.patch @@ -0,0 +1,90 @@ +commit 1df71d32fe5f5905ffd5d100e5e9ca8ad6210891 +Author: Florian Weimer +Date: Tue Sep 20 11:00:42 2022 +0200 + + elf: Implement force_first handling in _dl_sort_maps_dfs (bug 28937) + + The implementation in _dl_close_worker requires that the first + element of l_initfini is always this very map (“We are always the + zeroth entry, and since we don't include ourselves in the + dependency analysis start at 1.”). Rather than fixing that + assumption, this commit adds an implementation of the force_first + argument to the new dependency sorting algorithm. This also means + that the directly dlopen'ed shared object is always initialized last, + which is the least surprising behavior in the presence of cycles. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c +index 7c614bca5d8115c6..e8ef5e8b3588ab53 100644 +--- a/elf/dl-sort-maps.c ++++ b/elf/dl-sort-maps.c +@@ -182,8 +182,9 @@ dfs_traversal (struct link_map ***rpo, struct link_map *map, + + static void + _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps, +- bool force_first __attribute__ ((unused)), bool for_fini) ++ bool force_first, bool for_fini) + { ++ struct link_map *first_map = maps[0]; + for (int i = nmaps - 1; i >= 0; i--) + maps[i]->l_visited = 0; + +@@ -208,14 +209,6 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps, + Adjusting the order so that maps[0] is last traversed naturally avoids + this problem. + +- Further, the old "optimization" of skipping the main object at maps[0] +- from the call-site (i.e. _dl_sort_maps(maps+1,nmaps-1)) is in general +- no longer valid, since traversing along object dependency-links +- may "find" the main object even when it is not included in the initial +- order (e.g. a dlopen()'ed shared object can have circular dependencies +- linked back to itself). In such a case, traversing N-1 objects will +- create a N-object result, and raise problems. +- + To summarize, just passing in the full list, and iterating from back + to front makes things much more straightforward. */ + +@@ -274,6 +267,27 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps, + } + + memcpy (maps, rpo, sizeof (struct link_map *) * nmaps); ++ ++ /* Skipping the first object at maps[0] is not valid in general, ++ since traversing along object dependency-links may "find" that ++ first object even when it is not included in the initial order ++ (e.g., a dlopen'ed shared object can have circular dependencies ++ linked back to itself). In such a case, traversing N-1 objects ++ will create a N-object result, and raise problems. Instead, ++ force the object back into first place after sorting. This naive ++ approach may introduce further dependency ordering violations ++ compared to rotating the cycle until the first map is again in ++ the first position, but as there is a cycle, at least one ++ violation is already present. */ ++ if (force_first && maps[0] != first_map) ++ { ++ int i; ++ for (i = 0; maps[i] != first_map; ++i) ++ ; ++ assert (i < nmaps); ++ memmove (&maps[1], maps, i * sizeof (maps[0])); ++ maps[0] = first_map; ++ } + } + + void +diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def +index 5f7f18ef270bc12d..4bf9052db16fb352 100644 +--- a/elf/dso-sort-tests-1.def ++++ b/elf/dso-sort-tests-1.def +@@ -64,3 +64,10 @@ output: b>a>{}b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c + output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[a1;a->a2;a2->a;b->b1;c->a1;c=>a1 ++output(glibc.rtld.dynamic_sort=1): {+a[a2>a1>a>];+b[b1>b>];-b[];%c(a1());}a1>a>];+b[b1>b>];-b[];%c(a1());} - 2.34-47 +- Simplify the glibc system call profile (#2117712) + +* Tue Oct 11 2022 Florian Weimer - 2.34-46 +- DSO dependency sort must put new map first even if in cycle (#2128615) + +* Tue Oct 11 2022 Florian Weimer - 2.34-45 +- Run tst-audit-tlsdesc{,-dlopen} on all architectures (#2118666) + * Thu Oct 06 2022 Arjun Shankar - 2.34-44 - wrap-find-debuginfo.sh: Use nm --format=posix instead of --format=just-symbols