Import glibc-2.34-47.fc35 from f35

* Tue Oct 11 2022 Florian Weimer <fweimer@redhat.com> - 2.34-47
- Simplify the glibc system call profile (#2117712)

* Tue Oct 11 2022 Florian Weimer <fweimer@redhat.com> - 2.34-46
- DSO dependency sort must put new map first even if in cycle (#2128615)

* Tue Oct 11 2022 Florian Weimer <fweimer@redhat.com> - 2.34-45
- Run tst-audit-tlsdesc{,-dlopen} on all architectures (#2118666)

Resolves: RHELX-69
Resolves: #2118666
Resolves: #2128615
This commit is contained in:
Florian Weimer 2022-10-11 16:15:26 +02:00
parent 591bb6da2e
commit 6b1ce0df40
11 changed files with 809 additions and 1 deletions

154
glibc-rh2117712-1.patch Normal file
View File

@ -0,0 +1,154 @@
commit cca9684f2d7a74fc0b28bfb1859955e0e28d7b4b
Author: Florian Weimer <fweimer@redhat.com>
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 <adhemerval.zanella@linaro.org>
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)

45
glibc-rh2117712-2.patch Normal file
View File

@ -0,0 +1,45 @@
commit 68e036f27f31c3378201702e182246504fb00f87
Author: Florian Weimer <fweimer@redhat.com>
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 <adhemerval.zanella@linaro.org>
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;

164
glibc-rh2117712-3.patch Normal file
View File

@ -0,0 +1,164 @@
commit 9001cb1102cddba54f0e84e147dfbb0356067356
Author: Florian Weimer <fweimer@redhat.com>
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 <adhemerval.zanella@linaro.org>
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <_itoa.h>
+#include <array_length.h>
+#include <intprops.h>
+#include <stdio.h>
+
+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,

22
glibc-rh2117712-4.patch Normal file
View File

@ -0,0 +1,22 @@
commit 8fabe0e632bd441c760f878d1022c378f04f8497
Author: Florian Weimer <fweimer@redhat.com>
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;

69
glibc-rh2117712-5.patch Normal file
View File

@ -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 <adhemerval.zanella@linaro.org>
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 <adhemerval.zanella@linaro.org>
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 <Wilco.Dijkstra@arm.com>
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;

35
glibc-rh2117712-6.patch Normal file
View File

@ -0,0 +1,35 @@
commit 7187efd0aa270c83c428ea6cd0e1cffc34b41a74
Author: Florian Weimer <fweimer@redhat.com>
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 <adhemerval.zanella@linaro.org>
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 <random-bits.h>
#include <sys/random.h>
+#include <not-cancel.h>
/*
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 ();

94
glibc-rh2118666.patch Normal file
View File

@ -0,0 +1,94 @@
commit dd2315a866a4ac2b838ea1cb10c5ea1c35d51a2f
Author: Florian Weimer <fweimer@redhat.com>
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 <mcoufal@redhat.com>
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

37
glibc-rh2128615-1.patch Normal file
View File

@ -0,0 +1,37 @@
commit 183d99737298bb3200f0610fdcd1c7549c8ed560
Author: Florian Weimer <fweimer@redhat.com>
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 <adhemerval.zanella@linaro.org>
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))

79
glibc-rh2128615-2.patch Normal file
View File

@ -0,0 +1,79 @@
commit dbb75513f5cf9285c77c9e55777c5c35b653f890
Author: Florian Weimer <fweimer@redhat.com>
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 <adhemerval.zanella@linaro.org>
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'

90
glibc-rh2128615-3.patch Normal file
View File

@ -0,0 +1,90 @@
commit 1df71d32fe5f5905ffd5d100e5e9ca8ad6210891
Author: Florian Weimer <fweimer@redhat.com>
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 <adhemerval.zanella@linaro.org>
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>{}<a<b
tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};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[<a<c<d<g<f<b<e];}
output(glibc.rtld.dynamic_sort=2): {+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[<g<f<a<b<c<d<e];}
+
+# Test that even in the presence of dependency loops involving dlopen'ed
+# object, that object is initialized last (and not unloaded prematurely).
+# Final destructor order is indeterminate due to the cycle.
+tst-bz28937: {+a;+b;-b;+c;%c};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[<b<b1];+c[c>];%c(a1());}<a<a2<c<a1
+output(glibc.rtld.dynamic_sort=2): {+a[a2>a1>a>];+b[b1>b>];-b[<b<b1];+c[c>];%c(a1());}<a2<a<c<a1

View File

@ -148,7 +148,7 @@ end \
Summary: The GNU libc libraries
Name: glibc
Version: %{glibcversion}
Release: 44%{?dist}
Release: 47%{?dist}
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
# libraries.
@ -585,6 +585,16 @@ Patch377: glibc-upstream-2.34-305.patch
Patch378: glibc-upstream-2.34-306.patch
Patch379: glibc-upstream-2.34-307.patch
Patch380: glibc-upstream-2.34-308.patch
Patch381: glibc-rh2118666.patch
Patch382: glibc-rh2128615-1.patch
Patch383: glibc-rh2128615-2.patch
Patch384: glibc-rh2128615-3.patch
Patch385: glibc-rh2117712-1.patch
Patch386: glibc-rh2117712-2.patch
Patch387: glibc-rh2117712-3.patch
Patch388: glibc-rh2117712-4.patch
Patch389: glibc-rh2117712-5.patch
Patch390: glibc-rh2117712-6.patch
##############################################################################
# Continued list of core "glibc" package information:
@ -2641,6 +2651,15 @@ fi
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
%changelog
* Tue Oct 11 2022 Florian Weimer <fweimer@redhat.com> - 2.34-47
- Simplify the glibc system call profile (#2117712)
* Tue Oct 11 2022 Florian Weimer <fweimer@redhat.com> - 2.34-46
- DSO dependency sort must put new map first even if in cycle (#2128615)
* Tue Oct 11 2022 Florian Weimer <fweimer@redhat.com> - 2.34-45
- Run tst-audit-tlsdesc{,-dlopen} on all architectures (#2118666)
* Thu Oct 06 2022 Arjun Shankar <arjun@redhat.com> - 2.34-44
- wrap-find-debuginfo.sh: Use nm --format=posix instead of --format=just-symbols