diff --git a/SOURCES/glibc-rh2117712-1.patch b/SOURCES/glibc-rh2117712-1.patch new file mode 100644 index 0000000..e154365 --- /dev/null +++ b/SOURCES/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/SOURCES/glibc-rh2117712-2.patch b/SOURCES/glibc-rh2117712-2.patch new file mode 100644 index 0000000..0a55182 --- /dev/null +++ b/SOURCES/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/SOURCES/glibc-rh2117712-3.patch b/SOURCES/glibc-rh2117712-3.patch new file mode 100644 index 0000000..e3cf26e --- /dev/null +++ b/SOURCES/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/SOURCES/glibc-rh2117712-4.patch b/SOURCES/glibc-rh2117712-4.patch new file mode 100644 index 0000000..1d0a420 --- /dev/null +++ b/SOURCES/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/SOURCES/glibc-rh2117712-5.patch b/SOURCES/glibc-rh2117712-5.patch new file mode 100644 index 0000000..e147fa2 --- /dev/null +++ b/SOURCES/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/SOURCES/glibc-rh2117712-6.patch b/SOURCES/glibc-rh2117712-6.patch new file mode 100644 index 0000000..33766ff --- /dev/null +++ b/SOURCES/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/SOURCES/glibc-rh2118666.patch b/SOURCES/glibc-rh2118666.patch new file mode 100644 index 0000000..86750f6 --- /dev/null +++ b/SOURCES/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/SOURCES/glibc-rh2128615-1.patch b/SOURCES/glibc-rh2128615-1.patch new file mode 100644 index 0000000..b4783d8 --- /dev/null +++ b/SOURCES/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/SOURCES/glibc-rh2128615-2.patch b/SOURCES/glibc-rh2128615-2.patch new file mode 100644 index 0000000..2d8d4ac --- /dev/null +++ b/SOURCES/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/SOURCES/glibc-rh2128615-3.patch b/SOURCES/glibc-rh2128615-3.patch new file mode 100644 index 0000000..bf8a9a4 --- /dev/null +++ b/SOURCES/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());} +Date: Tue Aug 30 10:02:49 2022 +0200 + + nss_dns: Rewrite _nss_dns_gethostbyname4_r using current interfaces + + Introduce struct alloc_buffer to this function, and use it and + struct ns_rr_cursor in gaih_getanswer_slice. Adjust gaih_getanswer + and gaih_getanswer_noaaaa accordingly. + + Reviewed-by: Siddhesh Poyarekar + +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index 1cb3be71f04d98eb..36789965c06757d0 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -101,13 +101,6 @@ + #endif + #define MAXHOSTNAMELEN 256 + +-/* We need this time later. */ +-typedef union querybuf +-{ +- HEADER hdr; +- u_char buf[MAXPACKET]; +-} querybuf; +- + /* For historic reasons, pointers to IP addresses are char *, so use a + single list type for addresses and host names. */ + #define DYNARRAY_STRUCT ptrlist +@@ -126,18 +119,18 @@ static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen, + char **hnamep, int *errnop, + int *h_errnop, int32_t *ttlp); + +-static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1, +- const querybuf *answer2, int anslen2, +- const char *qname, ++static enum nss_status gaih_getanswer (unsigned char *packet1, ++ size_t packet1len, ++ unsigned char *packet2, ++ size_t packet2len, ++ struct alloc_buffer *abuf, + struct gaih_addrtuple **pat, +- char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp); +-static enum nss_status gaih_getanswer_noaaaa (const querybuf *answer1, +- int anslen1, +- const char *qname, ++static enum nss_status gaih_getanswer_noaaaa (unsigned char *packet, ++ size_t packetlen, ++ struct alloc_buffer *abuf, + struct gaih_addrtuple **pat, +- char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp); + +@@ -409,17 +402,13 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + name = cp; + } + +- union +- { +- querybuf *buf; +- u_char *ptr; +- } host_buffer; +- querybuf *orig_host_buffer; +- host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048); ++ unsigned char dns_packet_buffer[2048]; ++ unsigned char *alt_dns_packet_buffer = dns_packet_buffer; + u_char *ans2p = NULL; + int nans2p = 0; + int resplen2 = 0; + int ans2p_malloced = 0; ++ struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen); + + + int olderr = errno; +@@ -428,22 +417,21 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + if ((ctx->resp->options & RES_NOAAAA) == 0) + { + n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, +- host_buffer.buf->buf, 2048, &host_buffer.ptr, +- &ans2p, &nans2p, &resplen2, &ans2p_malloced); ++ dns_packet_buffer, sizeof (dns_packet_buffer), ++ &alt_dns_packet_buffer, &ans2p, &nans2p, ++ &resplen2, &ans2p_malloced); + if (n >= 0) +- status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p, +- resplen2, name, pat, buffer, buflen, +- errnop, herrnop, ttlp); ++ status = gaih_getanswer (alt_dns_packet_buffer, n, ans2p, resplen2, ++ &abuf, pat, errnop, herrnop, ttlp); + } + else + { + n = __res_context_search (ctx, name, C_IN, T_A, +- host_buffer.buf->buf, 2048, NULL, +- NULL, NULL, NULL, NULL); ++ dns_packet_buffer, sizeof (dns_packet_buffer), ++ NULL, NULL, NULL, NULL, NULL); + if (n >= 0) +- status = gaih_getanswer_noaaaa (host_buffer.buf, n, +- name, pat, buffer, buflen, +- errnop, herrnop, ttlp); ++ status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n, ++ &abuf, pat, errnop, herrnop, ttlp); + } + if (n < 0) + { +@@ -474,12 +462,20 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + __set_errno (olderr); + } + ++ /* Implement the buffer resizing protocol. */ ++ if (alloc_buffer_has_failed (&abuf)) ++ { ++ *errnop = ERANGE; ++ *herrnop = NETDB_INTERNAL; ++ status = NSS_STATUS_TRYAGAIN; ++ } ++ + /* Check whether ans2p was separately allocated. */ + if (ans2p_malloced) + free (ans2p); + +- if (host_buffer.buf != orig_host_buffer) +- free (host_buffer.buf); ++ if (alt_dns_packet_buffer != dns_packet_buffer) ++ free (alt_dns_packet_buffer); + + __resolv_context_put (ctx); + return status; +@@ -893,259 +889,152 @@ getanswer_ptr (unsigned char *packet, size_t packetlen, + return NSS_STATUS_TRYAGAIN; + } + ++/* Parses DNS data found in PACKETLEN bytes at PACKET in struct ++ gaih_addrtuple address tuples. The new address tuples are linked ++ from **TAILP, with backing store allocated from ABUF, and *TAILP is ++ updated to point where the next tuple pointer should be stored. If ++ TTLP is not null, *TTLP is updated to reflect the minimum TTL. If ++ STORE_CANON is true, the canonical name is stored as part of the ++ first address tuple being written. */ + static enum nss_status +-gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, +- struct gaih_addrtuple ***patp, +- char **bufferp, size_t *buflenp, +- int *errnop, int *h_errnop, int32_t *ttlp, int *firstp) ++gaih_getanswer_slice (unsigned char *packet, size_t packetlen, ++ struct alloc_buffer *abuf, ++ struct gaih_addrtuple ***tailp, ++ int *errnop, int *h_errnop, int32_t *ttlp, ++ bool store_canon) + { +- char *buffer = *bufferp; +- size_t buflen = *buflenp; +- +- struct gaih_addrtuple **pat = *patp; +- const HEADER *hp = &answer->hdr; +- int ancount = ntohs (hp->ancount); +- int qdcount = ntohs (hp->qdcount); +- const u_char *cp = answer->buf + HFIXEDSZ; +- const u_char *end_of_message = answer->buf + anslen; +- if (__glibc_unlikely (qdcount != 1)) +- { +- *h_errnop = NO_RECOVERY; +- return NSS_STATUS_UNAVAIL; +- } +- +- u_char packtmp[NS_MAXCDNAME]; +- int n = __ns_name_unpack (answer->buf, end_of_message, cp, +- packtmp, sizeof packtmp); +- /* We unpack the name to check it for validity. But we do not need +- it later. */ +- if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1) +- { +- if (__glibc_unlikely (errno == EMSGSIZE)) +- { +- too_small: +- *errnop = ERANGE; +- *h_errnop = NETDB_INTERNAL; +- return NSS_STATUS_TRYAGAIN; +- } +- +- n = -1; +- } +- +- if (__glibc_unlikely (n < 0)) +- { +- *errnop = errno; +- *h_errnop = NO_RECOVERY; +- return NSS_STATUS_UNAVAIL; +- } +- if (__glibc_unlikely (__libc_res_hnok (buffer) == 0)) ++ struct ns_rr_cursor c; ++ if (!__ns_rr_cursor_init (&c, packet, packetlen)) + { +- errno = EBADMSG; +- *errnop = EBADMSG; ++ /* This should not happen because __res_context_query already ++ perfroms response validation. */ + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + } +- cp += n + QFIXEDSZ; ++ bool haveanswer = false; /* Set to true if at least one address. */ ++ uint16_t qtype = ns_rr_cursor_qtype (&c); ++ int ancount = ns_rr_cursor_ancount (&c); ++ const unsigned char *expected_name = ns_rr_cursor_qname (&c); ++ /* expected_name may be updated to point into this buffer. */ ++ unsigned char name_buffer[NS_MAXCDNAME]; + +- int haveanswer = 0; +- int had_error = 0; +- char *canon = NULL; +- char *h_name = NULL; +- int h_namelen = 0; ++ /* This is a pointer to a possibly-compressed name in the packet. ++ Eventually it is equivalent to the canonical name. If needed, it ++ is uncompressed and translated to text form when the first ++ address tuple is encountered. */ ++ const unsigned char *compressed_alias_name = expected_name; + +- if (ancount == 0) ++ if (ancount == 0 || !__res_binary_hnok (compressed_alias_name)) + { + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } + +- while (ancount-- > 0 && cp < end_of_message && had_error == 0) ++ for (; ancount > -0; --ancount) + { +- n = __ns_name_unpack (answer->buf, end_of_message, cp, +- packtmp, sizeof packtmp); +- if (n != -1 && +- (h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1) +- { +- if (__glibc_unlikely (errno == EMSGSIZE)) +- goto too_small; +- +- n = -1; +- } +- if (__glibc_unlikely (n < 0)) +- { +- ++had_error; +- continue; +- } +- if (*firstp && canon == NULL && __libc_res_hnok (buffer)) +- { +- h_name = buffer; +- buffer += h_namelen; +- buflen -= h_namelen; +- } +- +- cp += n; /* name */ +- +- if (__glibc_unlikely (cp + 10 > end_of_message)) +- { +- ++had_error; +- continue; +- } +- +- uint16_t type; +- NS_GET16 (type, cp); +- uint16_t class; +- NS_GET16 (class, cp); +- int32_t ttl; +- NS_GET32 (ttl, cp); +- NS_GET16 (n, cp); /* RDATA length. */ +- +- if (end_of_message - cp < n) ++ struct ns_rr_wire rr; ++ if (!__ns_rr_cursor_next (&c, &rr)) + { +- /* RDATA extends beyond the end of the packet. */ +- ++had_error; +- continue; ++ *h_errnop = NO_RECOVERY; ++ return NSS_STATUS_UNAVAIL; + } + +- if (class != C_IN) +- { +- cp += n; +- continue; +- } ++ /* Update TTL for known record types. */ ++ if ((rr.rtype == T_CNAME || rr.rtype == qtype) ++ && ttlp != NULL && *ttlp > rr.ttl) ++ *ttlp = rr.ttl; + +- if (type == T_CNAME) ++ if (rr.rtype == T_CNAME) + { +- char tbuf[MAXDNAME]; +- +- /* A CNAME could also have a TTL entry. */ +- if (ttlp != NULL && ttl < *ttlp) +- *ttlp = ttl; +- +- n = __libc_dn_expand (answer->buf, end_of_message, cp, +- tbuf, sizeof tbuf); +- if (__glibc_unlikely (n < 0)) +- { +- ++had_error; +- continue; +- } +- cp += n; +- +- if (*firstp && __libc_res_hnok (tbuf)) ++ /* NB: No check for owner name match, based on historic ++ precedent. Record the CNAME target as the new expected ++ name. */ ++ int n = __ns_name_unpack (c.begin, c.end, rr.rdata, ++ name_buffer, sizeof (name_buffer)); ++ if (n < 0) + { +- /* Reclaim buffer space. */ +- if (h_name + h_namelen == buffer) +- { +- buffer = h_name; +- buflen += h_namelen; +- } +- +- n = strlen (tbuf) + 1; +- if (__glibc_unlikely (n > buflen)) +- goto too_small; +- if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) +- { +- ++had_error; +- continue; +- } +- +- canon = buffer; +- buffer = __mempcpy (buffer, tbuf, n); +- buflen -= n; +- h_namelen = 0; ++ *h_errnop = NO_RECOVERY; ++ return NSS_STATUS_UNAVAIL; + } +- continue; ++ expected_name = name_buffer; ++ if (store_canon && __res_binary_hnok (name_buffer)) ++ /* This name can be used as a canonical name. Do not ++ translate to text form here to conserve buffer space. ++ Point to the compressed name because name_buffer can be ++ overwritten with an unusable name later. */ ++ compressed_alias_name = rr.rdata; + } +- +- /* Stop parsing if we encounter a record with incorrect RDATA +- length. */ +- if (type == T_A || type == T_AAAA) ++ else if (rr.rtype == qtype ++ && __ns_samebinaryname (rr.rname, expected_name) ++ && rr.rdlength == rrtype_to_rdata_length (qtype)) + { +- if (n != rrtype_to_rdata_length (type)) ++ struct gaih_addrtuple *ntup ++ = alloc_buffer_alloc (abuf, struct gaih_addrtuple); ++ /* Delay error reporting to the callers (they implement the ++ ERANGE buffer resizing handshake). */ ++ if (ntup != NULL) + { +- ++had_error; +- continue; ++ ntup->next = NULL; ++ if (store_canon && compressed_alias_name != NULL) ++ { ++ /* This assumes that all the CNAME records come ++ first. Use MAXHOSTNAMELEN instead of ++ NS_MAXCDNAME for additional length checking. ++ However, these checks are not expected to fail ++ because all size NS_MAXCDNAME names should into ++ the hname buffer because no escaping is ++ needed. */ ++ char unsigned nbuf[NS_MAXCDNAME]; ++ char hname[MAXHOSTNAMELEN + 1]; ++ if (__ns_name_unpack (c.begin, c.end, ++ compressed_alias_name, ++ nbuf, sizeof (nbuf)) >= 0 ++ && __ns_name_ntop (nbuf, hname, sizeof (hname)) >= 0) ++ /* Space checking is performed by the callers. */ ++ ntup->name = alloc_buffer_copy_string (abuf, hname); ++ store_canon = false; ++ } ++ else ++ ntup->name = NULL; ++ if (rr.rdlength == 4) ++ ntup->family = AF_INET; ++ else ++ ntup->family = AF_INET6; ++ memcpy (ntup->addr, rr.rdata, rr.rdlength); ++ ntup->scopeid = 0; ++ ++ /* Link in the new tuple, and update the tail pointer to ++ point to its next field. */ ++ **tailp = ntup; ++ *tailp = &ntup->next; ++ ++ haveanswer = true; + } + } +- else +- { +- /* Skip unknown records. */ +- cp += n; +- continue; +- } +- +- assert (type == T_A || type == T_AAAA); +- if (*pat == NULL) +- { +- uintptr_t pad = (-(uintptr_t) buffer +- % __alignof__ (struct gaih_addrtuple)); +- buffer += pad; +- buflen = buflen > pad ? buflen - pad : 0; +- +- if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple))) +- goto too_small; +- +- *pat = (struct gaih_addrtuple *) buffer; +- buffer += sizeof (struct gaih_addrtuple); +- buflen -= sizeof (struct gaih_addrtuple); +- } +- +- (*pat)->name = NULL; +- (*pat)->next = NULL; +- +- if (*firstp) +- { +- /* We compose a single hostent out of the entire chain of +- entries, so the TTL of the hostent is essentially the lowest +- TTL in the chain. */ +- if (ttlp != NULL && ttl < *ttlp) +- *ttlp = ttl; +- +- (*pat)->name = canon ?: h_name; +- +- *firstp = 0; +- } +- +- (*pat)->family = type == T_A ? AF_INET : AF_INET6; +- memcpy ((*pat)->addr, cp, n); +- cp += n; +- (*pat)->scopeid = 0; +- +- pat = &((*pat)->next); +- +- haveanswer = 1; + } + + if (haveanswer) + { +- *patp = pat; +- *bufferp = buffer; +- *buflenp = buflen; +- + *h_errnop = NETDB_SUCCESS; + return NSS_STATUS_SUCCESS; + } +- +- /* Special case here: if the resolver sent a result but it only +- contains a CNAME while we are looking for a T_A or T_AAAA record, +- we fail with NOTFOUND instead of TRYAGAIN. */ +- if (canon != NULL) ++ else + { ++ /* Special case here: if the resolver sent a result but it only ++ contains a CNAME while we are looking for a T_A or T_AAAA ++ record, we fail with NOTFOUND. */ + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } +- +- *h_errnop = NETDB_INTERNAL; +- return NSS_STATUS_TRYAGAIN; + } + + + static enum nss_status +-gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, +- int anslen2, const char *qname, +- struct gaih_addrtuple **pat, char *buffer, size_t buflen, ++gaih_getanswer (unsigned char *packet1, size_t packet1len, ++ unsigned char *packet2, size_t packet2len, ++ struct alloc_buffer *abuf, struct gaih_addrtuple **pat, + int *errnop, int *h_errnop, int32_t *ttlp) + { +- int first = 1; +- + enum nss_status status = NSS_STATUS_NOTFOUND; + + /* Combining the NSS status of two distinct queries requires some +@@ -1157,7 +1046,10 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, + between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable). + A recoverable TRYAGAIN is almost always due to buffer size issues + and returns ERANGE in errno and the caller is expected to retry +- with a larger buffer. ++ with a larger buffer. (The caller, _nss_dns_gethostbyname4_r, ++ ignores the return status if it detects that the result buffer ++ has been exhausted and generates a TRYAGAIN failure with an ++ ERANGE code.) + + Lastly, you may be tempted to make significant changes to the + conditions in this code to bring about symmetry between responses. +@@ -1237,36 +1129,30 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, + is a recoverable error we now return TRYAGIN even if the first + response was SUCCESS. */ + +- if (anslen1 > 0) +- status = gaih_getanswer_slice(answer1, anslen1, qname, +- &pat, &buffer, &buflen, +- errnop, h_errnop, ttlp, +- &first); +- +- if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND +- || (status == NSS_STATUS_TRYAGAIN +- /* We want to look at the second answer in case of an +- NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e. +- *h_errnop is NO_RECOVERY. If not, and if the failure was due to +- an insufficient buffer (ERANGE), then we need to drop the results +- and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can +- repeat the query with a larger buffer. */ +- && (*errnop != ERANGE || *h_errnop == NO_RECOVERY))) +- && answer2 != NULL && anslen2 > 0) ++ if (packet1len > 0) + { +- enum nss_status status2 = gaih_getanswer_slice(answer2, anslen2, qname, +- &pat, &buffer, &buflen, +- errnop, h_errnop, ttlp, +- &first); ++ status = gaih_getanswer_slice (packet1, packet1len, ++ abuf, &pat, errnop, h_errnop, ttlp, true); ++ if (alloc_buffer_has_failed (abuf)) ++ /* Do not try parsing the second packet if a larger result ++ buffer is needed. The caller implements the resizing ++ protocol because *abuf has been exhausted. */ ++ return NSS_STATUS_TRYAGAIN; /* Ignored by the caller. */ ++ } ++ ++ if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND) ++ && packet2 != NULL && packet2len > 0) ++ { ++ enum nss_status status2 ++ = gaih_getanswer_slice (packet2, packet2len, ++ abuf, &pat, errnop, h_errnop, ttlp, ++ /* Success means that data with a ++ canonical name has already been ++ stored. Do not store the name again. */ ++ status != NSS_STATUS_SUCCESS); + /* Use the second response status in some cases. */ + if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND) + status = status2; +- /* Do not return a truncated second response (unless it was +- unavoidable e.g. unrecoverable TRYAGAIN). */ +- if (status == NSS_STATUS_SUCCESS +- && (status2 == NSS_STATUS_TRYAGAIN +- && *errnop == ERANGE && *h_errnop != NO_RECOVERY)) +- status = NSS_STATUS_TRYAGAIN; + } + + return status; +@@ -1274,18 +1160,13 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, + + /* Variant of gaih_getanswer without a second (AAAA) response. */ + static enum nss_status +-gaih_getanswer_noaaaa (const querybuf *answer1, int anslen1, const char *qname, +- struct gaih_addrtuple **pat, +- char *buffer, size_t buflen, ++gaih_getanswer_noaaaa (unsigned char *packet, size_t packetlen, ++ struct alloc_buffer *abuf, struct gaih_addrtuple **pat, + int *errnop, int *h_errnop, int32_t *ttlp) + { +- int first = 1; +- + enum nss_status status = NSS_STATUS_NOTFOUND; +- if (anslen1 > 0) +- status = gaih_getanswer_slice (answer1, anslen1, qname, +- &pat, &buffer, &buflen, +- errnop, h_errnop, ttlp, +- &first); ++ if (packetlen > 0) ++ status = gaih_getanswer_slice (packet, packetlen, ++ abuf, &pat, errnop, h_errnop, ttlp, true); + return status; + } diff --git a/SOURCES/glibc-rh2149102.patch b/SOURCES/glibc-rh2149102.patch new file mode 100644 index 0000000..6516cc0 --- /dev/null +++ b/SOURCES/glibc-rh2149102.patch @@ -0,0 +1,19 @@ +commit b8c6166b1b75036ab3e4127a1c0aacf52ca93651 +Author: Florian Weimer +Date: Mon Sep 6 19:43:37 2021 +0200 + + locale: Add missing second argument to _Static_assert in C-collate-seq.c + +diff --git a/locale/C-collate-seq.c b/locale/C-collate-seq.c +index 4fb82cb8357936b6..40b17f4f90313144 100644 +--- a/locale/C-collate-seq.c ++++ b/locale/C-collate-seq.c +@@ -55,7 +55,7 @@ static const char collseqmb[] = + + /* This table must be 256 bytes in size. We index bytes into the + table to find the collation sequence. */ +-_Static_assert (sizeof (collseqmb) == 256); ++_Static_assert (sizeof (collseqmb) == 256, "sizeof (collseqmb)"); + + static const uint32_t collseqwc[] = + { diff --git a/SOURCES/glibc-rh2162962.patch b/SOURCES/glibc-rh2162962.patch new file mode 100644 index 0000000..718d38c --- /dev/null +++ b/SOURCES/glibc-rh2162962.patch @@ -0,0 +1,306 @@ +Maintain an explicit order of tunables, so that the tunable_list +array and the tunable_id_t constant can remain consistent over time. + +Related to this upstream bug: + + Internal tunables ABI depends on awk array iteration order + + +The new dl-tunables.list files are already on the sysdeps search +path, which is why the existing Makeconfig rule picks them up. +The files for RHEL 9.1z were created by applying the gen-tunables.awk +part of this patch to RHEL 9.1.0 (glibc-2.34-40.el9_2.1, to be +precise). The sysdeps/unix/sysv/linux/**/dl-tunables.list files were +created based on the generated error message during the RHEL 9.1.z +build. + +Going forward, new tunables will have to be added manually to the end +of those files. Existing tunables should not be deleted. For +deletion, the script would have to be extended to be able to create +gaps in the tunable_list array. + +diff --git a/scripts/gen-tunables.awk b/scripts/gen-tunables.awk +index fa63e86d1a51fe61..c5445e95f9fc36e7 100644 +--- a/scripts/gen-tunables.awk ++++ b/scripts/gen-tunables.awk +@@ -14,6 +14,7 @@ BEGIN { + top_ns="" + max_name_len=0 + max_alias_len=0 ++ tunable_order_count = 0 + } + + # Skip over blank lines and comments. +@@ -83,6 +84,37 @@ $1 == "}" { + next + } + ++$1 == "@order" { ++ if (top_ns != "") { ++ printf("%s:%d: error: invalid @order directive inside namespace %s\n", ++ FILENAME, FNR, top_ns) > "/dev/stderr" ++ exit 1 ++ } ++ if (NF != 2) { ++ printf("%s:%d: error: invalid argument count in @order directive\n", ++ FILENAME, FNR) > "/dev/stderr" ++ exit 1 ++ } ++ order_arg = $2 ++ if (split(order_arg, indices, /\./) != 3) { ++ printf("%s:%d: error: invalid tunable syntax in @order directive\n", ++ FILENAME, FNR) > "/dev/stderr" ++ exit 1 ++ } ++ t = indices[1] ++ n = indices[2] ++ m = indices[3] ++ if ((t, n, m) in tunable_order) { ++ printf("%s:%d: error: duplicate\"@order %s\"\n" \ ++ FILENAME, FNR, order_arg) > "/dev/stderr" ++ exit 1 ++ } ++ ++tunable_order_count ++ tunable_order[t,n,m] = tunable_order_count ++ tunable_order_list[tunable_order_count] = t SUBSEP n SUBSEP m ++ next ++} ++ + # Everything else, which could either be a tunable without any attributes or a + # tunable attribute. + { +@@ -145,6 +177,31 @@ END { + exit 1 + } + ++ missing_order = 0 ++ for (tnm in types) { ++ if (!(tnm in tunable_order)) { ++ if (!missing_order) { ++ print "error: Missing @order directives:" > "/dev/stderr" ++ missing_order = 1 ++ } ++ split(tnm, indices, SUBSEP) ++ printf("@order %s.%s.%s\n", indices[1], indices[2], indices[3]) \ ++ > "/dev/stderr" ++ } ++ } ++ for (i = 1; i <= tunable_order_count; ++i) { ++ tnm = tunable_order_list[i] ++ if (!(tnm in types)) { ++ split(tnm, indices, SUBSEP) ++ printf("error: tunable in \"@order %s.%s.%s\" not known\n", \ ++ indices[1], indices[2], indices[3]) > "/dev/stderr" ++ missing_order = 1 ++ } ++ } ++ if (missing_order) { ++ exit 1 ++ } ++ + print "/* AUTOGENERATED by gen-tunables.awk. */" + print "#ifndef _TUNABLES_H_" + print "# error \"Do not include this file directly.\"" +@@ -155,7 +212,8 @@ END { + # Now, the enum names + print "\ntypedef enum" + print "{" +- for (tnm in types) { ++ for (i = 1; i <= tunable_order_count; ++i) { ++ tnm = tunable_order_list[i] + split (tnm, indices, SUBSEP); + t = indices[1]; + n = indices[2]; +@@ -171,7 +229,8 @@ END { + print "# include \"dl-tunable-types.h\"" + # Finally, the tunable list. + print "static tunable_t tunable_list[] attribute_relro = {" +- for (tnm in types) { ++ for (i = 1; i <= tunable_order_count; ++i) { ++ tnm = tunable_order_list[i] + split (tnm, indices, SUBSEP); + t = indices[1]; + n = indices[2]; +diff --git a/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list b/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list +new file mode 100644 +index 0000000000000000..d9d62499be4d67cb +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list +@@ -0,0 +1,28 @@ ++# Order of tunables in RHEL 9.1.z. ++@order glibc.rtld.nns ++@order glibc.elision.skip_lock_after_retries ++@order glibc.malloc.trim_threshold ++@order glibc.malloc.perturb ++@order glibc.pthread.rseq ++@order glibc.cpu.name ++@order glibc.mem.tagging ++@order glibc.elision.tries ++@order glibc.elision.enable ++@order glibc.malloc.mxfast ++@order glibc.rtld.dynamic_sort ++@order glibc.elision.skip_lock_busy ++@order glibc.malloc.top_pad ++@order glibc.pthread.stack_cache_size ++@order glibc.cpu.hwcap_mask ++@order glibc.malloc.mmap_max ++@order glibc.elision.skip_trylock_internal_abort ++@order glibc.malloc.tcache_unsorted_limit ++@order glibc.elision.skip_lock_internal_abort ++@order glibc.malloc.arena_max ++@order glibc.malloc.mmap_threshold ++@order glibc.malloc.tcache_count ++@order glibc.malloc.arena_test ++@order glibc.pthread.mutex_spin_count ++@order glibc.rtld.optional_static_tls ++@order glibc.malloc.tcache_max ++@order glibc.malloc.check +diff --git a/sysdeps/unix/sysv/linux/i386/dl-tunables.list b/sysdeps/unix/sysv/linux/i386/dl-tunables.list +new file mode 100644 +index 0000000000000000..e83962ec3af11691 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/i386/dl-tunables.list +@@ -0,0 +1,35 @@ ++# Order of tunables in RHEL 9.1.z. ++@order glibc.rtld.nns ++@order glibc.elision.skip_lock_after_retries ++@order glibc.malloc.trim_threshold ++@order glibc.malloc.perturb ++@order glibc.cpu.x86_shared_cache_size ++@order glibc.pthread.rseq ++@order glibc.mem.tagging ++@order glibc.elision.tries ++@order glibc.elision.enable ++@order glibc.cpu.x86_rep_movsb_threshold ++@order glibc.malloc.mxfast ++@order glibc.rtld.dynamic_sort ++@order glibc.elision.skip_lock_busy ++@order glibc.malloc.top_pad ++@order glibc.cpu.x86_rep_stosb_threshold ++@order glibc.cpu.x86_non_temporal_threshold ++@order glibc.cpu.x86_shstk ++@order glibc.pthread.stack_cache_size ++@order glibc.cpu.hwcap_mask ++@order glibc.malloc.mmap_max ++@order glibc.elision.skip_trylock_internal_abort ++@order glibc.malloc.tcache_unsorted_limit ++@order glibc.cpu.x86_ibt ++@order glibc.cpu.hwcaps ++@order glibc.elision.skip_lock_internal_abort ++@order glibc.malloc.arena_max ++@order glibc.malloc.mmap_threshold ++@order glibc.cpu.x86_data_cache_size ++@order glibc.malloc.tcache_count ++@order glibc.malloc.arena_test ++@order glibc.pthread.mutex_spin_count ++@order glibc.rtld.optional_static_tls ++@order glibc.malloc.tcache_max ++@order glibc.malloc.check +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list +new file mode 100644 +index 0000000000000000..8f01840ef57874e7 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list +@@ -0,0 +1,28 @@ ++# Order of tunables in RHEL 9.1.z. ++@order glibc.rtld.nns ++@order glibc.elision.skip_lock_after_retries ++@order glibc.malloc.trim_threshold ++@order glibc.malloc.perturb ++@order glibc.pthread.rseq ++@order glibc.mem.tagging ++@order glibc.elision.tries ++@order glibc.elision.enable ++@order glibc.malloc.mxfast ++@order glibc.rtld.dynamic_sort ++@order glibc.elision.skip_lock_busy ++@order glibc.malloc.top_pad ++@order glibc.pthread.stack_cache_size ++@order glibc.cpu.hwcap_mask ++@order glibc.malloc.mmap_max ++@order glibc.elision.skip_trylock_internal_abort ++@order glibc.malloc.tcache_unsorted_limit ++@order glibc.elision.skip_lock_internal_abort ++@order glibc.malloc.arena_max ++@order glibc.malloc.mmap_threshold ++@order glibc.cpu.cached_memopt ++@order glibc.malloc.tcache_count ++@order glibc.malloc.arena_test ++@order glibc.pthread.mutex_spin_count ++@order glibc.rtld.optional_static_tls ++@order glibc.malloc.tcache_max ++@order glibc.malloc.check +diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list b/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list +new file mode 100644 +index 0000000000000000..c3bc83f33910af22 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list +@@ -0,0 +1,27 @@ ++# Order of tunables in RHEL 9.1.z. ++@order glibc.rtld.nns ++@order glibc.elision.skip_lock_after_retries ++@order glibc.malloc.trim_threshold ++@order glibc.malloc.perturb ++@order glibc.pthread.rseq ++@order glibc.mem.tagging ++@order glibc.elision.tries ++@order glibc.elision.enable ++@order glibc.malloc.mxfast ++@order glibc.rtld.dynamic_sort ++@order glibc.elision.skip_lock_busy ++@order glibc.malloc.top_pad ++@order glibc.pthread.stack_cache_size ++@order glibc.cpu.hwcap_mask ++@order glibc.malloc.mmap_max ++@order glibc.elision.skip_trylock_internal_abort ++@order glibc.malloc.tcache_unsorted_limit ++@order glibc.elision.skip_lock_internal_abort ++@order glibc.malloc.arena_max ++@order glibc.malloc.mmap_threshold ++@order glibc.malloc.tcache_count ++@order glibc.malloc.arena_test ++@order glibc.pthread.mutex_spin_count ++@order glibc.rtld.optional_static_tls ++@order glibc.malloc.tcache_max ++@order glibc.malloc.check +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list +new file mode 100644 +index 0000000000000000..e83962ec3af11691 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list +@@ -0,0 +1,35 @@ ++# Order of tunables in RHEL 9.1.z. ++@order glibc.rtld.nns ++@order glibc.elision.skip_lock_after_retries ++@order glibc.malloc.trim_threshold ++@order glibc.malloc.perturb ++@order glibc.cpu.x86_shared_cache_size ++@order glibc.pthread.rseq ++@order glibc.mem.tagging ++@order glibc.elision.tries ++@order glibc.elision.enable ++@order glibc.cpu.x86_rep_movsb_threshold ++@order glibc.malloc.mxfast ++@order glibc.rtld.dynamic_sort ++@order glibc.elision.skip_lock_busy ++@order glibc.malloc.top_pad ++@order glibc.cpu.x86_rep_stosb_threshold ++@order glibc.cpu.x86_non_temporal_threshold ++@order glibc.cpu.x86_shstk ++@order glibc.pthread.stack_cache_size ++@order glibc.cpu.hwcap_mask ++@order glibc.malloc.mmap_max ++@order glibc.elision.skip_trylock_internal_abort ++@order glibc.malloc.tcache_unsorted_limit ++@order glibc.cpu.x86_ibt ++@order glibc.cpu.hwcaps ++@order glibc.elision.skip_lock_internal_abort ++@order glibc.malloc.arena_max ++@order glibc.malloc.mmap_threshold ++@order glibc.cpu.x86_data_cache_size ++@order glibc.malloc.tcache_count ++@order glibc.malloc.arena_test ++@order glibc.pthread.mutex_spin_count ++@order glibc.rtld.optional_static_tls ++@order glibc.malloc.tcache_max ++@order glibc.malloc.check diff --git a/SOURCES/glibc-upstream-2.34-303.patch b/SOURCES/glibc-upstream-2.34-303.patch new file mode 100644 index 0000000..d7c929f --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-303.patch @@ -0,0 +1,24 @@ +commit 875b2414cd68df64aeead651a9b05ae9bc3d88ef +Author: Florian Weimer +Date: Thu Aug 4 17:54:48 2022 +0200 + + dlfcn: Pass caller pointer to static dlopen implementation (bug 29446) + + Fixes commit 0c1c3a771eceec46e66ce1183cf988e2303bd373 ("dlfcn: Move + dlopen into libc"). + + (cherry picked from commit ed0185e4129130cbe081c221efb758fb400623ce) + +diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c +index 9c59c751c4eaf7a7..739d17baafe928cc 100644 +--- a/dlfcn/dlopen.c ++++ b/dlfcn/dlopen.c +@@ -90,7 +90,7 @@ compat_symbol (libdl, ___dlopen, dlopen, GLIBC_2_1); + void * + __dlopen (const char *file, int mode, void *dl_caller) + { +- return dlopen_implementation (file, mode, RETURN_ADDRESS (0)); ++ return dlopen_implementation (file, mode, dl_caller); + } + + void * diff --git a/SOURCES/glibc-upstream-2.34-304.patch b/SOURCES/glibc-upstream-2.34-304.patch new file mode 100644 index 0000000..f67a835 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-304.patch @@ -0,0 +1,54 @@ +commit 4ab59ce4e5195f98b01748127248fed2b2b77b21 +Author: Joseph Myers +Date: Tue Aug 2 21:05:07 2022 +0000 + + Update syscall lists for Linux 5.19 + + Linux 5.19 has no new syscalls, but enables memfd_secret in the uapi + headers for RISC-V. Update the version number in syscall-names.list + to reflect that it is still current for 5.19 and regenerate the + arch-syscall.h headers with build-many-glibcs.py update-syscalls. + + Tested with build-many-glibcs.py. + + (cherry picked from commit fccadcdf5bed7ee67a6cef4714e0b477d6c8472c) + +diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h +index bf4be80f8d380963..202520ee254ec02f 100644 +--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h +@@ -122,6 +122,7 @@ + #define __NR_mbind 235 + #define __NR_membarrier 283 + #define __NR_memfd_create 279 ++#define __NR_memfd_secret 447 + #define __NR_migrate_pages 238 + #define __NR_mincore 232 + #define __NR_mkdirat 34 +diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h +index d656aedcc2be6009..4e65f337d486de1f 100644 +--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h +@@ -127,6 +127,7 @@ + #define __NR_mbind 235 + #define __NR_membarrier 283 + #define __NR_memfd_create 279 ++#define __NR_memfd_secret 447 + #define __NR_migrate_pages 238 + #define __NR_mincore 232 + #define __NR_mkdirat 34 +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 95370e2ec5dbc4a7..9b285d898db9ab9e 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.18. +-kernel 5.18 ++# The list of system calls is current as of Linux 5.19. ++kernel 5.19 + + FAST_atomic_update + FAST_cmpxchg diff --git a/SOURCES/glibc-upstream-2.34-305.patch b/SOURCES/glibc-upstream-2.34-305.patch new file mode 100644 index 0000000..8a70f75 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-305.patch @@ -0,0 +1,85 @@ +commit a88f07f71f051021339682328103a8c75559fc5f +Author: Noah Goldstein +Date: Wed Jun 22 08:24:21 2022 -0700 + + stdlib: Remove attr_write from mbstows if dst is NULL [BZ: 29265] + + mbstows is defined if dst is NULL and is defined to special cased if + dst is NULL so the fortify objsize check if incorrect in that case. + + Tested on x86-64 linux. + Reviewed-by: Siddhesh Poyarekar + + (cherry picked from commit 464d189b9622932a75302290625de84931656ec0) + +diff --git a/stdlib/Makefile b/stdlib/Makefile +index a4ac30d1f6359561..e13f1ee33c410ae6 100644 +--- a/stdlib/Makefile ++++ b/stdlib/Makefile +@@ -217,6 +217,9 @@ CFLAGS-tst-qsort.c += $(stack-align-test-flags) + CFLAGS-tst-makecontext.c += -funwind-tables + CFLAGS-tst-makecontext2.c += $(stack-align-test-flags) + ++CFLAGS-testmb.c += -D_FORTIFY_SOURCE=2 -Wall -Werror ++ ++ + # Run a test on the header files we use. + tests-special += $(objpfx)isomac.out + +diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h +index ccacbdf76a08225a..f0918d5d798a6ac4 100644 +--- a/stdlib/bits/stdlib.h ++++ b/stdlib/bits/stdlib.h +@@ -96,6 +96,11 @@ extern size_t __mbstowcs_chk (wchar_t *__restrict __dst, + const char *__restrict __src, + size_t __len, size_t __dstlen) __THROW + __attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2)); ++extern size_t __REDIRECT_NTH (__mbstowcs_chk_nulldst, ++ (wchar_t *__restrict __dst, ++ const char *__restrict __src, ++ size_t __len), mbstowcs_chk) ++ __attr_access ((__read_only__, 2)); + extern size_t __REDIRECT_NTH (__mbstowcs_alias, + (wchar_t *__restrict __dst, + const char *__restrict __src, +@@ -108,16 +113,17 @@ extern size_t __REDIRECT_NTH (__mbstowcs_chk_warn, + __warnattr ("mbstowcs called with dst buffer smaller than len " + "* sizeof (wchar_t)"); + +-__fortify_function size_t ++__always_inline __fortify_function size_t + __NTH (mbstowcs (wchar_t *__restrict __dst, const char *__restrict __src, + size_t __len)) + { +- return __glibc_fortify_n (mbstowcs, __len, sizeof (wchar_t), +- __glibc_objsize (__dst), +- __dst, __src, __len); ++ if (__builtin_constant_p (__dst == NULL) && __dst == NULL) ++ return __mbstowcs_chk_nulldst (__dst, __src, __len); ++ else ++ return __glibc_fortify_n (mbstowcs, __len, sizeof (wchar_t), ++ __glibc_objsize (__dst), __dst, __src, __len); + } + +- + extern size_t __wcstombs_chk (char *__restrict __dst, + const wchar_t *__restrict __src, + size_t __len, size_t __dstlen) __THROW +diff --git a/stdlib/testmb.c b/stdlib/testmb.c +index 45dae7db61fb3e7b..6ac4dfd21d2d33b8 100644 +--- a/stdlib/testmb.c ++++ b/stdlib/testmb.c +@@ -16,6 +16,13 @@ main (int argc, char *argv[]) + lose = 1; + } + ++ i = mbstowcs (NULL, "bar", 4); ++ if (!(i == 3 && w[1] == 'a')) ++ { ++ puts ("mbstowcs FAILED2!"); ++ lose = 1; ++ } ++ + mbstowcs (w, "blah", 5); + i = wcstombs (c, w, 10); + if (i != 4) diff --git a/SOURCES/glibc-upstream-2.34-306.patch b/SOURCES/glibc-upstream-2.34-306.patch new file mode 100644 index 0000000..b031a56 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-306.patch @@ -0,0 +1,54 @@ +commit 4bc889c01ce68475ce36f9c67b9a445a6c0218d9 +Author: Noah Goldstein +Date: Wed Jun 22 16:34:42 2022 -0700 + + stdlib: Fixup mbstowcs NULL __dst handling. [BZ #29279] + + commit 464d189b9622932a75302290625de84931656ec0 (origin/master, origin/HEAD) + Author: Noah Goldstein + Date: Wed Jun 22 08:24:21 2022 -0700 + + stdlib: Remove attr_write from mbstows if dst is NULL [BZ: 29265] + + Incorrectly called `__mbstowcs_chk` in the NULL __dst case which is + incorrect as in the NULL __dst case we are explicitly skipping + the objsize checks. + + As well, remove the `__always_inline` attribute which exists in + `__fortify_function`. + Reviewed-by: Siddhesh Poyarekar + + (cherry picked from commit 220b83d83d32aa9e6f5659e2fa2a63a0024c3e4a) + +diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h +index f0918d5d798a6ac4..ac9badc81f3990c5 100644 +--- a/stdlib/bits/stdlib.h ++++ b/stdlib/bits/stdlib.h +@@ -96,10 +96,10 @@ extern size_t __mbstowcs_chk (wchar_t *__restrict __dst, + const char *__restrict __src, + size_t __len, size_t __dstlen) __THROW + __attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2)); +-extern size_t __REDIRECT_NTH (__mbstowcs_chk_nulldst, ++extern size_t __REDIRECT_NTH (__mbstowcs_nulldst, + (wchar_t *__restrict __dst, + const char *__restrict __src, +- size_t __len), mbstowcs_chk) ++ size_t __len), mbstowcs) + __attr_access ((__read_only__, 2)); + extern size_t __REDIRECT_NTH (__mbstowcs_alias, + (wchar_t *__restrict __dst, +@@ -113,12 +113,12 @@ extern size_t __REDIRECT_NTH (__mbstowcs_chk_warn, + __warnattr ("mbstowcs called with dst buffer smaller than len " + "* sizeof (wchar_t)"); + +-__always_inline __fortify_function size_t ++__fortify_function size_t + __NTH (mbstowcs (wchar_t *__restrict __dst, const char *__restrict __src, + size_t __len)) + { + if (__builtin_constant_p (__dst == NULL) && __dst == NULL) +- return __mbstowcs_chk_nulldst (__dst, __src, __len); ++ return __mbstowcs_nulldst (__dst, __src, __len); + else + return __glibc_fortify_n (mbstowcs, __len, sizeof (wchar_t), + __glibc_objsize (__dst), __dst, __src, __len); diff --git a/SOURCES/glibc-upstream-2.34-307.patch b/SOURCES/glibc-upstream-2.34-307.patch new file mode 100644 index 0000000..8e5493b --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-307.patch @@ -0,0 +1,30 @@ +commit 1fcc7bfee22a07064508b6729cdaa6289851a2b4 +Author: Florian Weimer +Date: Mon Aug 22 11:04:47 2022 +0200 + + alpha: Fix generic brk system call emulation in __brk_call (bug 29490) + + The kernel special-cases the zero argument for alpha brk, and we can + use that to restore the generic Linux error handling behavior. + + Fixes commit b57ab258c1140bc45464b4b9908713e3e0ee35aa ("Linux: + Introduce __brk_call for invoking the brk system call"). + + (cherry picked from commit e7ad26ee3cb74e61d0637c888f24dd478d77af58) + +diff --git a/sysdeps/unix/sysv/linux/alpha/brk_call.h b/sysdeps/unix/sysv/linux/alpha/brk_call.h +index b8088cf13f938c88..0b851b6c8664e8d5 100644 +--- a/sysdeps/unix/sysv/linux/alpha/brk_call.h ++++ b/sysdeps/unix/sysv/linux/alpha/brk_call.h +@@ -21,8 +21,7 @@ __brk_call (void *addr) + { + unsigned long int result = INTERNAL_SYSCALL_CALL (brk, addr); + if (result == -ENOMEM) +- /* Mimic the default error reporting behavior. */ +- return addr; +- else +- return (void *) result; ++ /* Mimic the generic error reporting behavior. */ ++ result = INTERNAL_SYSCALL_CALL (brk, 0); ++ return (void *) result; + } diff --git a/SOURCES/glibc-upstream-2.34-308.patch b/SOURCES/glibc-upstream-2.34-308.patch new file mode 100644 index 0000000..4726bf0 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-308.patch @@ -0,0 +1,435 @@ +commit 68507377f249d165f1f35502d96e9365edb07d9a +Author: Arjun Shankar +Date: Tue Aug 2 11:10:25 2022 +0200 + + socket: Check lengths before advancing pointer in CMSG_NXTHDR + + The inline and library functions that the CMSG_NXTHDR macro may expand + to increment the pointer to the header before checking the stride of + the increment against available space. Since C only allows incrementing + pointers to one past the end of an array, the increment must be done + after a length check. This commit fixes that and includes a regression + test for CMSG_FIRSTHDR and CMSG_NXTHDR. + + The Linux, Hurd, and generic headers are all changed. + + Tested on Linux on armv7hl, i686, x86_64, aarch64, ppc64le, and s390x. + + [BZ #28846] + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 9c443ac4559a47ed99859bd80d14dc4b6dd220a1) + +diff --git a/bits/socket.h b/bits/socket.h +index 05ac0249c7da7218..781b1b2d1e0632a8 100644 +--- a/bits/socket.h ++++ b/bits/socket.h +@@ -245,6 +245,12 @@ struct cmsghdr + + CMSG_ALIGN (sizeof (struct cmsghdr))) + #define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) + ++/* Given a length, return the additional padding necessary such that ++ len + __CMSG_PADDING(len) == CMSG_ALIGN (len). */ ++#define __CMSG_PADDING(len) ((sizeof (size_t) \ ++ - ((len) & (sizeof (size_t) - 1))) \ ++ & (sizeof (size_t) - 1)) ++ + extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + struct cmsghdr *__cmsg) __THROW; + #ifdef __USE_EXTERN_INLINES +@@ -254,18 +260,38 @@ extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + _EXTERN_INLINE struct cmsghdr * + __NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg)) + { ++ /* We may safely assume that __cmsg lies between __mhdr->msg_control and ++ __mhdr->msg_controllen because the user is required to obtain the first ++ cmsg via CMSG_FIRSTHDR, set its length, then obtain subsequent cmsgs ++ via CMSG_NXTHDR, setting lengths along the way. However, we don't yet ++ trust the value of __cmsg->cmsg_len and therefore do not use it in any ++ pointer arithmetic until we check its value. */ ++ ++ unsigned char * __msg_control_ptr = (unsigned char *) __mhdr->msg_control; ++ unsigned char * __cmsg_ptr = (unsigned char *) __cmsg; ++ ++ size_t __size_needed = sizeof (struct cmsghdr) ++ + __CMSG_PADDING (__cmsg->cmsg_len); ++ ++ /* The current header is malformed, too small to be a full header. */ + if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr)) +- /* The kernel header does this so there may be a reason. */ + return (struct cmsghdr *) 0; + ++ /* There isn't enough space between __cmsg and the end of the buffer to ++ hold the current cmsg *and* the next one. */ ++ if (((size_t) ++ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr) ++ < __size_needed) ++ || ((size_t) ++ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr ++ - __size_needed) ++ < __cmsg->cmsg_len)) ++ ++ return (struct cmsghdr *) 0; ++ ++ /* Now, we trust cmsg_len and can use it to find the next header. */ + __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg + + CMSG_ALIGN (__cmsg->cmsg_len)); +- if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control +- + __mhdr->msg_controllen) +- || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len) +- > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen))) +- /* No more entries. */ +- return (struct cmsghdr *) 0; + return __cmsg; + } + #endif /* Use `extern inline'. */ +diff --git a/socket/Makefile b/socket/Makefile +index c2de11d73ca1e324..2fdf441bb44bf142 100644 +--- a/socket/Makefile ++++ b/socket/Makefile +@@ -34,6 +34,7 @@ routines := accept bind connect getpeername getsockname getsockopt \ + tests := \ + tst-accept4 \ + tst-sockopt \ ++ tst-cmsghdr \ + # tests + + tests-internal := \ +diff --git a/socket/tst-cmsghdr-skeleton.c b/socket/tst-cmsghdr-skeleton.c +new file mode 100644 +index 0000000000000000..7accfa6e54708e2a +--- /dev/null ++++ b/socket/tst-cmsghdr-skeleton.c +@@ -0,0 +1,93 @@ ++/* Test ancillary data header creation. ++ 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 ++ . */ ++ ++/* We use the preprocessor to generate the function/macro tests instead of ++ using indirection because having all the macro expansions alongside ++ each other lets the compiler warn us about suspicious pointer ++ arithmetic across subsequent CMSG_{FIRST,NXT}HDR expansions. */ ++ ++#include ++#include ++ ++#define RUN_TEST_CONCAT(suffix) run_test_##suffix ++#define RUN_TEST_FUNCNAME(suffix) RUN_TEST_CONCAT (suffix) ++ ++static void ++RUN_TEST_FUNCNAME (CMSG_NXTHDR_IMPL) (void) ++{ ++ struct msghdr m = {0}; ++ struct cmsghdr *cmsg; ++ char cmsgbuf[3 * CMSG_SPACE (sizeof (PAYLOAD))] = {0}; ++ ++ m.msg_control = cmsgbuf; ++ m.msg_controllen = sizeof (cmsgbuf); ++ ++ /* First header should point to the start of the buffer. */ ++ cmsg = CMSG_FIRSTHDR (&m); ++ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf); ++ ++ /* If the first header length consumes the entire buffer, there is no ++ space remaining for additional headers. */ ++ cmsg->cmsg_len = sizeof (cmsgbuf); ++ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg); ++ TEST_VERIFY_EXIT (cmsg == NULL); ++ ++ /* The first header length is so big, using it would cause an overflow. */ ++ cmsg = CMSG_FIRSTHDR (&m); ++ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf); ++ cmsg->cmsg_len = SIZE_MAX; ++ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg); ++ TEST_VERIFY_EXIT (cmsg == NULL); ++ ++ /* The first header leaves just enough space to hold another header. */ ++ cmsg = CMSG_FIRSTHDR (&m); ++ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf); ++ cmsg->cmsg_len = sizeof (cmsgbuf) - sizeof (struct cmsghdr); ++ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg); ++ TEST_VERIFY_EXIT (cmsg != NULL); ++ ++ /* The first header leaves space but not enough for another header. */ ++ cmsg = CMSG_FIRSTHDR (&m); ++ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf); ++ cmsg->cmsg_len ++; ++ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg); ++ TEST_VERIFY_EXIT (cmsg == NULL); ++ ++ /* The second header leaves just enough space to hold another header. */ ++ cmsg = CMSG_FIRSTHDR (&m); ++ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf); ++ cmsg->cmsg_len = CMSG_LEN (sizeof (PAYLOAD)); ++ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg); ++ TEST_VERIFY_EXIT (cmsg != NULL); ++ cmsg->cmsg_len = sizeof (cmsgbuf) ++ - CMSG_SPACE (sizeof (PAYLOAD)) /* First header. */ ++ - sizeof (struct cmsghdr); ++ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg); ++ TEST_VERIFY_EXIT (cmsg != NULL); ++ ++ /* The second header leaves space but not enough for another header. */ ++ cmsg = CMSG_FIRSTHDR (&m); ++ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf); ++ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg); ++ TEST_VERIFY_EXIT (cmsg != NULL); ++ cmsg->cmsg_len ++; ++ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg); ++ TEST_VERIFY_EXIT (cmsg == NULL); ++ ++ return; ++} +diff --git a/socket/tst-cmsghdr.c b/socket/tst-cmsghdr.c +new file mode 100644 +index 0000000000000000..68c96d3c9dd2bce8 +--- /dev/null ++++ b/socket/tst-cmsghdr.c +@@ -0,0 +1,56 @@ ++/* Test ancillary data header creation. ++ 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 ++#include ++ ++#define PAYLOAD "Hello, World!" ++ ++/* CMSG_NXTHDR is a macro that calls an inline function defined in ++ bits/socket.h. In case the function cannot be inlined, libc.so carries ++ a copy. Both versions need to be tested. */ ++ ++#define CMSG_NXTHDR_IMPL CMSG_NXTHDR ++#include "tst-cmsghdr-skeleton.c" ++#undef CMSG_NXTHDR_IMPL ++ ++static struct cmsghdr * (* cmsg_nxthdr) (struct msghdr *, struct cmsghdr *); ++ ++#define CMSG_NXTHDR_IMPL cmsg_nxthdr ++#include "tst-cmsghdr-skeleton.c" ++#undef CMSG_NXTHDR_IMPL ++ ++static int ++do_test (void) ++{ ++ static void *handle; ++ ++ run_test_CMSG_NXTHDR (); ++ ++ handle = xdlopen (LIBC_SO, RTLD_LAZY); ++ cmsg_nxthdr = (struct cmsghdr * (*) (struct msghdr *, struct cmsghdr *)) ++ xdlsym (handle, "__cmsg_nxthdr"); ++ ++ run_test_cmsg_nxthdr (); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/mach/hurd/bits/socket.h b/sysdeps/mach/hurd/bits/socket.h +index 5210a7b44950e957..423eb2df09c3eef9 100644 +--- a/sysdeps/mach/hurd/bits/socket.h ++++ b/sysdeps/mach/hurd/bits/socket.h +@@ -249,6 +249,12 @@ struct cmsghdr + + CMSG_ALIGN (sizeof (struct cmsghdr))) + #define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) + ++/* Given a length, return the additional padding necessary such that ++ len + __CMSG_PADDING(len) == CMSG_ALIGN (len). */ ++#define __CMSG_PADDING(len) ((sizeof (size_t) \ ++ - ((len) & (sizeof (size_t) - 1))) \ ++ & (sizeof (size_t) - 1)) ++ + extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + struct cmsghdr *__cmsg) __THROW; + #ifdef __USE_EXTERN_INLINES +@@ -258,18 +264,38 @@ extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + _EXTERN_INLINE struct cmsghdr * + __NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg)) + { ++ /* We may safely assume that __cmsg lies between __mhdr->msg_control and ++ __mhdr->msg_controllen because the user is required to obtain the first ++ cmsg via CMSG_FIRSTHDR, set its length, then obtain subsequent cmsgs ++ via CMSG_NXTHDR, setting lengths along the way. However, we don't yet ++ trust the value of __cmsg->cmsg_len and therefore do not use it in any ++ pointer arithmetic until we check its value. */ ++ ++ unsigned char * __msg_control_ptr = (unsigned char *) __mhdr->msg_control; ++ unsigned char * __cmsg_ptr = (unsigned char *) __cmsg; ++ ++ size_t __size_needed = sizeof (struct cmsghdr) ++ + __CMSG_PADDING (__cmsg->cmsg_len); ++ ++ /* The current header is malformed, too small to be a full header. */ + if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr)) +- /* The kernel header does this so there may be a reason. */ + return (struct cmsghdr *) 0; + ++ /* There isn't enough space between __cmsg and the end of the buffer to ++ hold the current cmsg *and* the next one. */ ++ if (((size_t) ++ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr) ++ < __size_needed) ++ || ((size_t) ++ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr ++ - __size_needed) ++ < __cmsg->cmsg_len)) ++ ++ return (struct cmsghdr *) 0; ++ ++ /* Now, we trust cmsg_len and can use it to find the next header. */ + __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg + + CMSG_ALIGN (__cmsg->cmsg_len)); +- if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control +- + __mhdr->msg_controllen) +- || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len) +- > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen))) +- /* No more entries. */ +- return (struct cmsghdr *) 0; + return __cmsg; + } + #endif /* Use `extern inline'. */ +diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h +index c81fab840918924e..7d56f877e0a73acb 100644 +--- a/sysdeps/unix/sysv/linux/bits/socket.h ++++ b/sysdeps/unix/sysv/linux/bits/socket.h +@@ -306,6 +306,12 @@ struct cmsghdr + + CMSG_ALIGN (sizeof (struct cmsghdr))) + #define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) + ++/* Given a length, return the additional padding necessary such that ++ len + __CMSG_PADDING(len) == CMSG_ALIGN (len). */ ++#define __CMSG_PADDING(len) ((sizeof (size_t) \ ++ - ((len) & (sizeof (size_t) - 1))) \ ++ & (sizeof (size_t) - 1)) ++ + extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + struct cmsghdr *__cmsg) __THROW; + #ifdef __USE_EXTERN_INLINES +@@ -315,18 +321,38 @@ extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + _EXTERN_INLINE struct cmsghdr * + __NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg)) + { ++ /* We may safely assume that __cmsg lies between __mhdr->msg_control and ++ __mhdr->msg_controllen because the user is required to obtain the first ++ cmsg via CMSG_FIRSTHDR, set its length, then obtain subsequent cmsgs ++ via CMSG_NXTHDR, setting lengths along the way. However, we don't yet ++ trust the value of __cmsg->cmsg_len and therefore do not use it in any ++ pointer arithmetic until we check its value. */ ++ ++ unsigned char * __msg_control_ptr = (unsigned char *) __mhdr->msg_control; ++ unsigned char * __cmsg_ptr = (unsigned char *) __cmsg; ++ ++ size_t __size_needed = sizeof (struct cmsghdr) ++ + __CMSG_PADDING (__cmsg->cmsg_len); ++ ++ /* The current header is malformed, too small to be a full header. */ + if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr)) +- /* The kernel header does this so there may be a reason. */ + return (struct cmsghdr *) 0; + ++ /* There isn't enough space between __cmsg and the end of the buffer to ++ hold the current cmsg *and* the next one. */ ++ if (((size_t) ++ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr) ++ < __size_needed) ++ || ((size_t) ++ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr ++ - __size_needed) ++ < __cmsg->cmsg_len)) ++ ++ return (struct cmsghdr *) 0; ++ ++ /* Now, we trust cmsg_len and can use it to find the next header. */ + __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg + + CMSG_ALIGN (__cmsg->cmsg_len)); +- if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control +- + __mhdr->msg_controllen) +- || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len) +- > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen))) +- /* No more entries. */ +- return (struct cmsghdr *) 0; + return __cmsg; + } + #endif /* Use `extern inline'. */ +diff --git a/sysdeps/unix/sysv/linux/cmsg_nxthdr.c b/sysdeps/unix/sysv/linux/cmsg_nxthdr.c +index a0fe49f28563d030..535d22e9a037b9a9 100644 +--- a/sysdeps/unix/sysv/linux/cmsg_nxthdr.c ++++ b/sysdeps/unix/sysv/linux/cmsg_nxthdr.c +@@ -23,18 +23,38 @@ + struct cmsghdr * + __cmsg_nxthdr (struct msghdr *mhdr, struct cmsghdr *cmsg) + { ++ /* We may safely assume that cmsg lies between mhdr->msg_control and ++ mhdr->msg_controllen because the user is required to obtain the first ++ cmsg via CMSG_FIRSTHDR, set its length, then obtain subsequent cmsgs ++ via CMSG_NXTHDR, setting lengths along the way. However, we don't yet ++ trust the value of cmsg->cmsg_len and therefore do not use it in any ++ pointer arithmetic until we check its value. */ ++ ++ unsigned char * msg_control_ptr = (unsigned char *) mhdr->msg_control; ++ unsigned char * cmsg_ptr = (unsigned char *) cmsg; ++ ++ size_t size_needed = sizeof (struct cmsghdr) ++ + __CMSG_PADDING (cmsg->cmsg_len); ++ ++ /* The current header is malformed, too small to be a full header. */ + if ((size_t) cmsg->cmsg_len < sizeof (struct cmsghdr)) +- /* The kernel header does this so there may be a reason. */ +- return NULL; ++ return (struct cmsghdr *) 0; ++ ++ /* There isn't enough space between cmsg and the end of the buffer to ++ hold the current cmsg *and* the next one. */ ++ if (((size_t) ++ (msg_control_ptr + mhdr->msg_controllen - cmsg_ptr) ++ < size_needed) ++ || ((size_t) ++ (msg_control_ptr + mhdr->msg_controllen - cmsg_ptr ++ - size_needed) ++ < cmsg->cmsg_len)) ++ ++ return (struct cmsghdr *) 0; + ++ /* Now, we trust cmsg_len and can use it to find the next header. */ + cmsg = (struct cmsghdr *) ((unsigned char *) cmsg + + CMSG_ALIGN (cmsg->cmsg_len)); +- if ((unsigned char *) (cmsg + 1) > ((unsigned char *) mhdr->msg_control +- + mhdr->msg_controllen) +- || ((unsigned char *) cmsg + CMSG_ALIGN (cmsg->cmsg_len) +- > ((unsigned char *) mhdr->msg_control + mhdr->msg_controllen))) +- /* No more entries. */ +- return NULL; + return cmsg; + } + libc_hidden_def (__cmsg_nxthdr) diff --git a/SOURCES/glibc-upstream-2.34-309.patch b/SOURCES/glibc-upstream-2.34-309.patch new file mode 100644 index 0000000..1c34dc0 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-309.patch @@ -0,0 +1,212 @@ +commit 536ddc5c02f1ee82483319863a893ccb381beece +Author: Florian Weimer +Date: Fri Aug 26 21:15:43 2022 +0200 + + elf: Call __libc_early_init for reused namespaces (bug 29528) + + libc_map is never reset to NULL, neither during dlclose nor on a + dlopen call which reuses the namespace structure. As a result, if a + namespace is reused, its libc is not initialized properly. The most + visible result is a crash in the functions. + + To prevent similar bugs on namespace reuse from surfacing, + unconditionally initialize the chosen namespace to zero using memset. + + (cherry picked from commit d0e357ff45a75553dee3b17ed7d303bfa544f6fe) + +Conflicts: + elf/Makefile + (usual test differences) + +diff --git a/elf/Makefile b/elf/Makefile +index 2b547d5b58f1759b..feec365e4e5fe9b3 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -399,6 +399,7 @@ tests += \ + tst-dlmopen3 \ + tst-dlmopen-dlerror \ + tst-dlmopen-gethostbyname \ ++ tst-dlmopen-twice \ + tst-dlopenfail \ + tst-dlopenfail-2 \ + tst-dlopenrpath \ +@@ -744,6 +745,8 @@ modules-names = \ + tst-dlmopen1mod \ + tst-dlmopen-dlerror-mod \ + tst-dlmopen-gethostbyname-mod \ ++ tst-dlmopen-twice-mod1 \ ++ tst-dlmopen-twice-mod2 \ + tst-dlopenfaillinkmod \ + tst-dlopenfailmod1 \ + tst-dlopenfailmod2 \ +@@ -2665,3 +2668,7 @@ $(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 ++ ++$(objpfx)tst-dlmopen-twice.out: \ ++ $(objpfx)tst-dlmopen-twice-mod1.so \ ++ $(objpfx)tst-dlmopen-twice-mod2.so +diff --git a/elf/dl-open.c b/elf/dl-open.c +index bc6872632880634e..1ab3c7b5ac2fbc45 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -839,11 +839,14 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid, + _dl_signal_error (EINVAL, file, NULL, N_("\ + no more namespaces available for dlmopen()")); + } +- else if (nsid == GL(dl_nns)) +- { +- __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock); +- ++GL(dl_nns); +- } ++ ++ if (nsid == GL(dl_nns)) ++ ++GL(dl_nns); ++ ++ /* Initialize the new namespace. Most members are ++ zero-initialized, only the lock needs special treatment. */ ++ memset (&GL(dl_ns)[nsid], 0, sizeof (GL(dl_ns)[nsid])); ++ __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock); + + _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT; + } +diff --git a/elf/tst-dlmopen-twice-mod1.c b/elf/tst-dlmopen-twice-mod1.c +new file mode 100644 +index 0000000000000000..0eaf04948ce5263e +--- /dev/null ++++ b/elf/tst-dlmopen-twice-mod1.c +@@ -0,0 +1,37 @@ ++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 1. ++ 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 ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ puts ("info: tst-dlmopen-twice-mod1.so loaded"); ++ fflush (stdout); ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ puts ("info: tst-dlmopen-twice-mod1.so about to be unloaded"); ++ fflush (stdout); ++} ++ ++/* Large allocation. The second module does not have this, so it ++ should load libc at a different address. */ ++char large_allocate[16 * 1024 * 1024]; +diff --git a/elf/tst-dlmopen-twice-mod2.c b/elf/tst-dlmopen-twice-mod2.c +new file mode 100644 +index 0000000000000000..40c6c01f9625e188 +--- /dev/null ++++ b/elf/tst-dlmopen-twice-mod2.c +@@ -0,0 +1,50 @@ ++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 2. ++ 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 ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ puts ("info: tst-dlmopen-twice-mod2.so loaded"); ++ fflush (stdout); ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ puts ("info: tst-dlmopen-twice-mod2.so about to be unloaded"); ++ fflush (stdout); ++} ++ ++int ++run_check (void) ++{ ++ puts ("info: about to call isalpha"); ++ fflush (stdout); ++ ++ volatile char ch = 'a'; ++ if (!isalpha (ch)) ++ { ++ puts ("error: isalpha ('a') is not true"); ++ fflush (stdout); ++ return 1; ++ } ++ return 0; ++} +diff --git a/elf/tst-dlmopen-twice.c b/elf/tst-dlmopen-twice.c +new file mode 100644 +index 0000000000000000..449f3c8fa9f2aa01 +--- /dev/null ++++ b/elf/tst-dlmopen-twice.c +@@ -0,0 +1,34 @@ ++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Main. ++ 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 ++ ++static int ++do_test (void) ++{ ++ void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so", RTLD_NOW); ++ xdlclose (handle); ++ handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod2.so", RTLD_NOW); ++ int (*run_check) (void) = xdlsym (handle, "run_check"); ++ TEST_COMPARE (run_check (), 0); ++ xdlclose (handle); ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-upstream-2.34-310.patch b/SOURCES/glibc-upstream-2.34-310.patch new file mode 100644 index 0000000..7f949a0 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-310.patch @@ -0,0 +1,334 @@ +commit 2a44960cbc78713c6a2721683a4319d50e71a01f +Author: Tulio Magno Quites Machado Filho +Date: Thu Jul 7 18:12:58 2022 -0300 + + Apply asm redirections in stdio.h before first use [BZ #27087] + + Compilers may not be able to apply asm redirections to functions after + these functions are used for the first time, e.g. clang 13. + Fix [BZ #27087] by applying all long double-related asm redirections + before using functions in bits/stdio.h. + However, as these asm redirections depend on the declarations provided + by libio/bits/stdio2.h, this header was split in 2: + + - libio/bits/stdio2-decl.h contains all function declarations; + - libio/bits/stdio2.h remains with the remaining contents, including + redirections. + + This also adds the access attribute to __vsnprintf_chk that was missing. + + Tested with build-many-glibcs.py. + + Reviewed-by: Paul E. Murphy + (cherry picked from commit d0fa09a7701956036ff36f8ca188e9fff81553d8) + +diff --git a/include/bits/stdio2-decl.h b/include/bits/stdio2-decl.h +new file mode 100644 +index 0000000000000000..bbb052f192218219 +--- /dev/null ++++ b/include/bits/stdio2-decl.h +@@ -0,0 +1 @@ ++#include +diff --git a/libio/Makefile b/libio/Makefile +index 5336b7d59584927f..981c876940f67fbf 100644 +--- a/libio/Makefile ++++ b/libio/Makefile +@@ -23,7 +23,7 @@ subdir := libio + include ../Makeconfig + + headers := stdio.h \ +- bits/stdio.h bits/stdio2.h bits/stdio-ldbl.h \ ++ bits/stdio.h bits/stdio2.h bits/stdio2-decl.h bits/stdio-ldbl.h \ + bits/types/FILE.h bits/types/__FILE.h bits/types/struct_FILE.h \ + bits/types/__fpos_t.h bits/types/__fpos64_t.h \ + bits/types/cookie_io_functions_t.h +diff --git a/libio/bits/stdio2-decl.h b/libio/bits/stdio2-decl.h +new file mode 100644 +index 0000000000000000..e398f7182b98e4d7 +--- /dev/null ++++ b/libio/bits/stdio2-decl.h +@@ -0,0 +1,111 @@ ++/* Checking macros for stdio functions. Declarations only. ++ Copyright (C) 2004-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 ++ . */ ++ ++#ifndef _BITS_STDIO2_DEC_H ++#define _BITS_STDIO2_DEC_H 1 ++ ++#ifndef _STDIO_H ++# error "Never include directly; use instead." ++#endif ++ ++extern int __sprintf_chk (char *__restrict __s, int __flag, size_t __slen, ++ const char *__restrict __format, ...) __THROW ++ __attr_access ((__write_only__, 1, 3)); ++extern int __vsprintf_chk (char *__restrict __s, int __flag, size_t __slen, ++ const char *__restrict __format, ++ __gnuc_va_list __ap) __THROW ++ __attr_access ((__write_only__, 1, 3)); ++ ++#if defined __USE_ISOC99 || defined __USE_UNIX98 ++ ++extern int __snprintf_chk (char *__restrict __s, size_t __n, int __flag, ++ size_t __slen, const char *__restrict __format, ++ ...) __THROW ++ __attr_access ((__write_only__, 1, 2)); ++extern int __vsnprintf_chk (char *__restrict __s, size_t __n, int __flag, ++ size_t __slen, const char *__restrict __format, ++ __gnuc_va_list __ap) __THROW ++ __attr_access ((__write_only__, 1, 2)); ++ ++#endif ++ ++#if __USE_FORTIFY_LEVEL > 1 ++ ++extern int __fprintf_chk (FILE *__restrict __stream, int __flag, ++ const char *__restrict __format, ...); ++extern int __printf_chk (int __flag, const char *__restrict __format, ...); ++extern int __vfprintf_chk (FILE *__restrict __stream, int __flag, ++ const char *__restrict __format, __gnuc_va_list __ap); ++extern int __vprintf_chk (int __flag, const char *__restrict __format, ++ __gnuc_va_list __ap); ++ ++# ifdef __USE_XOPEN2K8 ++extern int __dprintf_chk (int __fd, int __flag, const char *__restrict __fmt, ++ ...) __attribute__ ((__format__ (__printf__, 3, 4))); ++extern int __vdprintf_chk (int __fd, int __flag, ++ const char *__restrict __fmt, __gnuc_va_list __arg) ++ __attribute__ ((__format__ (__printf__, 3, 0))); ++# endif ++ ++# ifdef __USE_GNU ++ ++extern int __asprintf_chk (char **__restrict __ptr, int __flag, ++ const char *__restrict __fmt, ...) ++ __THROW __attribute__ ((__format__ (__printf__, 3, 4))) __wur; ++extern int __vasprintf_chk (char **__restrict __ptr, int __flag, ++ const char *__restrict __fmt, __gnuc_va_list __arg) ++ __THROW __attribute__ ((__format__ (__printf__, 3, 0))) __wur; ++extern int __obstack_printf_chk (struct obstack *__restrict __obstack, ++ int __flag, const char *__restrict __format, ++ ...) ++ __THROW __attribute__ ((__format__ (__printf__, 3, 4))); ++extern int __obstack_vprintf_chk (struct obstack *__restrict __obstack, ++ int __flag, ++ const char *__restrict __format, ++ __gnuc_va_list __args) ++ __THROW __attribute__ ((__format__ (__printf__, 3, 0))); ++ ++# endif ++#endif ++ ++#if __GLIBC_USE (DEPRECATED_GETS) ++extern char *__gets_chk (char *__str, size_t) __wur; ++#endif ++ ++extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n, ++ FILE *__restrict __stream) ++ __wur __attr_access ((__write_only__, 1, 3)); ++ ++extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen, ++ size_t __size, size_t __n, ++ FILE *__restrict __stream) __wur; ++ ++#ifdef __USE_GNU ++extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size, ++ int __n, FILE *__restrict __stream) ++ __wur __attr_access ((__write_only__, 1, 3)); ++#endif ++ ++#ifdef __USE_MISC ++# undef fread_unlocked ++extern size_t __fread_unlocked_chk (void *__restrict __ptr, size_t __ptrlen, ++ size_t __size, size_t __n, ++ FILE *__restrict __stream) __wur; ++#endif ++ ++#endif /* bits/stdio2-decl.h. */ +diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h +index 40ff16b01b4f4876..4570f86a4496c1ee 100644 +--- a/libio/bits/stdio2.h ++++ b/libio/bits/stdio2.h +@@ -23,14 +23,6 @@ + # error "Never include directly; use instead." + #endif + +-extern int __sprintf_chk (char *__restrict __s, int __flag, size_t __slen, +- const char *__restrict __format, ...) __THROW +- __attr_access ((__write_only__, 1, 3)); +-extern int __vsprintf_chk (char *__restrict __s, int __flag, size_t __slen, +- const char *__restrict __format, +- __gnuc_va_list __ap) __THROW +- __attr_access ((__write_only__, 1, 3)); +- + #ifdef __va_arg_pack + __fortify_function int + __NTH (sprintf (char *__restrict __s, const char *__restrict __fmt, ...)) +@@ -54,15 +46,6 @@ __NTH (vsprintf (char *__restrict __s, const char *__restrict __fmt, + } + + #if defined __USE_ISOC99 || defined __USE_UNIX98 +- +-extern int __snprintf_chk (char *__restrict __s, size_t __n, int __flag, +- size_t __slen, const char *__restrict __format, +- ...) __THROW +- __attr_access ((__write_only__, 1, 2)); +-extern int __vsnprintf_chk (char *__restrict __s, size_t __n, int __flag, +- size_t __slen, const char *__restrict __format, +- __gnuc_va_list __ap) __THROW; +- + # ifdef __va_arg_pack + __fortify_function int + __NTH (snprintf (char *__restrict __s, size_t __n, +@@ -89,15 +72,6 @@ __NTH (vsnprintf (char *__restrict __s, size_t __n, + #endif + + #if __USE_FORTIFY_LEVEL > 1 +- +-extern int __fprintf_chk (FILE *__restrict __stream, int __flag, +- const char *__restrict __format, ...); +-extern int __printf_chk (int __flag, const char *__restrict __format, ...); +-extern int __vfprintf_chk (FILE *__restrict __stream, int __flag, +- const char *__restrict __format, __gnuc_va_list __ap); +-extern int __vprintf_chk (int __flag, const char *__restrict __format, +- __gnuc_va_list __ap); +- + # ifdef __va_arg_pack + __fortify_function int + fprintf (FILE *__restrict __stream, const char *__restrict __fmt, ...) +@@ -136,12 +110,6 @@ vfprintf (FILE *__restrict __stream, + } + + # ifdef __USE_XOPEN2K8 +-extern int __dprintf_chk (int __fd, int __flag, const char *__restrict __fmt, +- ...) __attribute__ ((__format__ (__printf__, 3, 4))); +-extern int __vdprintf_chk (int __fd, int __flag, +- const char *__restrict __fmt, __gnuc_va_list __arg) +- __attribute__ ((__format__ (__printf__, 3, 0))); +- + # ifdef __va_arg_pack + __fortify_function int + dprintf (int __fd, const char *__restrict __fmt, ...) +@@ -162,23 +130,6 @@ vdprintf (int __fd, const char *__restrict __fmt, __gnuc_va_list __ap) + # endif + + # ifdef __USE_GNU +- +-extern int __asprintf_chk (char **__restrict __ptr, int __flag, +- const char *__restrict __fmt, ...) +- __THROW __attribute__ ((__format__ (__printf__, 3, 4))) __wur; +-extern int __vasprintf_chk (char **__restrict __ptr, int __flag, +- const char *__restrict __fmt, __gnuc_va_list __arg) +- __THROW __attribute__ ((__format__ (__printf__, 3, 0))) __wur; +-extern int __obstack_printf_chk (struct obstack *__restrict __obstack, +- int __flag, const char *__restrict __format, +- ...) +- __THROW __attribute__ ((__format__ (__printf__, 3, 4))); +-extern int __obstack_vprintf_chk (struct obstack *__restrict __obstack, +- int __flag, +- const char *__restrict __format, +- __gnuc_va_list __args) +- __THROW __attribute__ ((__format__ (__printf__, 3, 0))); +- + # ifdef __va_arg_pack + __fortify_function int + __NTH (asprintf (char **__restrict __ptr, const char *__restrict __fmt, ...)) +@@ -231,7 +182,6 @@ __NTH (obstack_vprintf (struct obstack *__restrict __obstack, + #endif + + #if __GLIBC_USE (DEPRECATED_GETS) +-extern char *__gets_chk (char *__str, size_t) __wur; + extern char *__REDIRECT (__gets_warn, (char *__str), gets) + __wur __warnattr ("please use fgets or getline instead, gets can't " + "specify buffer size"); +@@ -245,9 +195,6 @@ gets (char *__str) + } + #endif + +-extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n, +- FILE *__restrict __stream) +- __wur __attr_access ((__write_only__, 1, 3)); + extern char *__REDIRECT (__fgets_alias, + (char *__restrict __s, int __n, + FILE *__restrict __stream), fgets) +@@ -269,9 +216,6 @@ fgets (char *__restrict __s, int __n, FILE *__restrict __stream) + return __fgets_chk (__s, sz, __n, __stream); + } + +-extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen, +- size_t __size, size_t __n, +- FILE *__restrict __stream) __wur; + extern size_t __REDIRECT (__fread_alias, + (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream), +@@ -297,9 +241,6 @@ fread (void *__restrict __ptr, size_t __size, size_t __n, + } + + #ifdef __USE_GNU +-extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size, +- int __n, FILE *__restrict __stream) +- __wur __attr_access ((__write_only__, 1, 3)); + extern char *__REDIRECT (__fgets_unlocked_alias, + (char *__restrict __s, int __n, + FILE *__restrict __stream), fgets_unlocked) +@@ -324,9 +265,6 @@ fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream) + + #ifdef __USE_MISC + # undef fread_unlocked +-extern size_t __fread_unlocked_chk (void *__restrict __ptr, size_t __ptrlen, +- size_t __size, size_t __n, +- FILE *__restrict __stream) __wur; + extern size_t __REDIRECT (__fread_unlocked_alias, + (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream), +diff --git a/libio/stdio.h b/libio/stdio.h +index abefe640e52d18d5..d36e61c56bbb3117 100644 +--- a/libio/stdio.h ++++ b/libio/stdio.h +@@ -879,20 +879,27 @@ extern void funlockfile (FILE *__stream) __THROW; + extern int __uflow (FILE *); + extern int __overflow (FILE *, int); + ++#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function ++/* Declare all functions from bits/stdio2-decl.h first. */ ++# include ++#endif ++ ++/* The following headers provide asm redirections. These redirections must ++ appear before the first usage of these functions, e.g. in bits/stdio.h. */ ++#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 ++# include ++#endif ++ + /* If we are compiling with optimizing read this file. It contains + several optimizing inline functions and macros. */ + #ifdef __USE_EXTERN_INLINES + # include + #endif + #if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function ++/* Now include the function definitions and redirects too. */ + # include + #endif + +-#include +-#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 +-# include +-#endif +- + __END_DECLS + + #endif /* included. */ diff --git a/SOURCES/glibc-upstream-2.34-311.patch b/SOURCES/glibc-upstream-2.34-311.patch new file mode 100644 index 0000000..2307c0c --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-311.patch @@ -0,0 +1,414 @@ +commit b41c535f46e7e7bbd8ff2ac68b94c2348e2f66e4 +Author: Raphael Moreira Zinsly +Date: Wed Aug 24 11:43:37 2022 -0300 + + Apply asm redirections in wchar.h before first use + + Similar to d0fa09a770, but for wchar.h. Fixes [BZ #27087] by applying + all long double related asm redirections before using functions in + bits/wchar2.h. + Moves the function declarations from wcsmbs/bits/wchar2.h to a new file + wcsmbs/bits/wchar2-decl.h that will be included first in wcsmbs/wchar.h. + + Tested with build-many-glibcs.py. + Reviewed-by: Adhemerval Zanella + + (cherry picked from commit c7509d49c4e8fa494120c5ead21338559dad16f5) + +diff --git a/include/bits/wchar2-decl.h b/include/bits/wchar2-decl.h +new file mode 100644 +index 0000000000000000..00b1b93342ef28ff +--- /dev/null ++++ b/include/bits/wchar2-decl.h +@@ -0,0 +1 @@ ++#include +diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile +index f38eb5cfe16fd3d7..5fe755e65df6c621 100644 +--- a/wcsmbs/Makefile ++++ b/wcsmbs/Makefile +@@ -22,8 +22,9 @@ subdir := wcsmbs + + include ../Makeconfig + +-headers := wchar.h bits/wchar.h bits/wchar2.h bits/wchar-ldbl.h uchar.h \ +- bits/types/__mbstate_t.h bits/types/mbstate_t.h bits/types/wint_t.h ++headers := wchar.h bits/wchar.h bits/wchar2.h bits/wchar2-decl.h \ ++ bits/wchar-ldbl.h uchar.h bits/types/__mbstate_t.h \ ++ bits/types/mbstate_t.h bits/types/wint_t.h + + routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \ + wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \ +diff --git a/wcsmbs/bits/wchar2-decl.h b/wcsmbs/bits/wchar2-decl.h +new file mode 100644 +index 0000000000000000..8e1735c33b7f7e78 +--- /dev/null ++++ b/wcsmbs/bits/wchar2-decl.h +@@ -0,0 +1,124 @@ ++/* Checking macros for wchar functions. Declarations only. ++ Copyright (C) 2004-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 ++ . */ ++ ++#ifndef _BITS_WCHAR2_DECL_H ++#define _BITS_WCHAR2_DECL_H 1 ++ ++#ifndef _WCHAR_H ++# error "Never include directly; use instead." ++#endif ++ ++ ++extern wchar_t *__wmemcpy_chk (wchar_t *__restrict __s1, ++ const wchar_t *__restrict __s2, size_t __n, ++ size_t __ns1) __THROW; ++extern wchar_t *__wmemmove_chk (wchar_t *__s1, const wchar_t *__s2, ++ size_t __n, size_t __ns1) __THROW; ++ ++ ++#ifdef __USE_GNU ++ ++extern wchar_t *__wmempcpy_chk (wchar_t *__restrict __s1, ++ const wchar_t *__restrict __s2, size_t __n, ++ size_t __ns1) __THROW; ++ ++#endif ++ ++ ++extern wchar_t *__wmemset_chk (wchar_t *__s, wchar_t __c, size_t __n, ++ size_t __ns) __THROW; ++extern wchar_t *__wcscpy_chk (wchar_t *__restrict __dest, ++ const wchar_t *__restrict __src, ++ size_t __n) __THROW; ++extern wchar_t *__wcpcpy_chk (wchar_t *__restrict __dest, ++ const wchar_t *__restrict __src, ++ size_t __destlen) __THROW; ++extern wchar_t *__wcsncpy_chk (wchar_t *__restrict __dest, ++ const wchar_t *__restrict __src, size_t __n, ++ size_t __destlen) __THROW; ++extern wchar_t *__wcpncpy_chk (wchar_t *__restrict __dest, ++ const wchar_t *__restrict __src, size_t __n, ++ size_t __destlen) __THROW; ++extern wchar_t *__wcscat_chk (wchar_t *__restrict __dest, ++ const wchar_t *__restrict __src, ++ size_t __destlen) __THROW; ++extern wchar_t *__wcsncat_chk (wchar_t *__restrict __dest, ++ const wchar_t *__restrict __src, ++ size_t __n, size_t __destlen) __THROW; ++extern int __swprintf_chk (wchar_t *__restrict __s, size_t __n, ++ int __flag, size_t __s_len, ++ const wchar_t *__restrict __format, ...) ++ __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 6))) */; ++extern int __vswprintf_chk (wchar_t *__restrict __s, size_t __n, ++ int __flag, size_t __s_len, ++ const wchar_t *__restrict __format, ++ __gnuc_va_list __arg) ++ __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 0))) */; ++ ++#if __USE_FORTIFY_LEVEL > 1 ++ ++extern int __fwprintf_chk (__FILE *__restrict __stream, int __flag, ++ const wchar_t *__restrict __format, ...); ++extern int __wprintf_chk (int __flag, const wchar_t *__restrict __format, ++ ...); ++extern int __vfwprintf_chk (__FILE *__restrict __stream, int __flag, ++ const wchar_t *__restrict __format, ++ __gnuc_va_list __ap); ++extern int __vwprintf_chk (int __flag, const wchar_t *__restrict __format, ++ __gnuc_va_list __ap); ++ ++#endif ++ ++extern wchar_t *__fgetws_chk (wchar_t *__restrict __s, size_t __size, int __n, ++ __FILE *__restrict __stream) __wur; ++ ++#ifdef __USE_GNU ++ ++extern wchar_t *__fgetws_unlocked_chk (wchar_t *__restrict __s, size_t __size, ++ int __n, __FILE *__restrict __stream) ++ __wur; ++ ++#endif ++ ++extern size_t __wcrtomb_chk (char *__restrict __s, wchar_t __wchar, ++ mbstate_t *__restrict __p, ++ size_t __buflen) __THROW __wur; ++extern size_t __mbsrtowcs_chk (wchar_t *__restrict __dst, ++ const char **__restrict __src, ++ size_t __len, mbstate_t *__restrict __ps, ++ size_t __dstlen) __THROW; ++extern size_t __wcsrtombs_chk (char *__restrict __dst, ++ const wchar_t **__restrict __src, ++ size_t __len, mbstate_t *__restrict __ps, ++ size_t __dstlen) __THROW; ++ ++#ifdef __USE_XOPEN2K8 ++ ++extern size_t __mbsnrtowcs_chk (wchar_t *__restrict __dst, ++ const char **__restrict __src, size_t __nmc, ++ size_t __len, mbstate_t *__restrict __ps, ++ size_t __dstlen) __THROW; ++extern size_t __wcsnrtombs_chk (char *__restrict __dst, ++ const wchar_t **__restrict __src, ++ size_t __nwc, size_t __len, ++ mbstate_t *__restrict __ps, size_t __dstlen) ++ __THROW; ++ ++#endif ++ ++#endif /* bits/wchar2-decl.h. */ +diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h +index 88c1fdfcd34292f4..50151b424d85a032 100644 +--- a/wcsmbs/bits/wchar2.h ++++ b/wcsmbs/bits/wchar2.h +@@ -21,9 +21,6 @@ + #endif + + +-extern wchar_t *__wmemcpy_chk (wchar_t *__restrict __s1, +- const wchar_t *__restrict __s2, size_t __n, +- size_t __ns1) __THROW; + extern wchar_t *__REDIRECT_NTH (__wmemcpy_alias, + (wchar_t *__restrict __s1, + const wchar_t *__restrict __s2, size_t __n), +@@ -45,8 +42,6 @@ __NTH (wmemcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2, + } + + +-extern wchar_t *__wmemmove_chk (wchar_t *__s1, const wchar_t *__s2, +- size_t __n, size_t __ns1) __THROW; + extern wchar_t *__REDIRECT_NTH (__wmemmove_alias, (wchar_t *__s1, + const wchar_t *__s2, + size_t __n), wmemmove); +@@ -66,9 +61,6 @@ __NTH (wmemmove (wchar_t *__s1, const wchar_t *__s2, size_t __n)) + + + #ifdef __USE_GNU +-extern wchar_t *__wmempcpy_chk (wchar_t *__restrict __s1, +- const wchar_t *__restrict __s2, size_t __n, +- size_t __ns1) __THROW; + extern wchar_t *__REDIRECT_NTH (__wmempcpy_alias, + (wchar_t *__restrict __s1, + const wchar_t *__restrict __s2, +@@ -91,8 +83,6 @@ __NTH (wmempcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2, + #endif + + +-extern wchar_t *__wmemset_chk (wchar_t *__s, wchar_t __c, size_t __n, +- size_t __ns) __THROW; + extern wchar_t *__REDIRECT_NTH (__wmemset_alias, (wchar_t *__s, wchar_t __c, + size_t __n), wmemset); + extern wchar_t *__REDIRECT_NTH (__wmemset_chk_warn, +@@ -110,9 +100,6 @@ __NTH (wmemset (wchar_t *__s, wchar_t __c, size_t __n)) + } + + +-extern wchar_t *__wcscpy_chk (wchar_t *__restrict __dest, +- const wchar_t *__restrict __src, +- size_t __n) __THROW; + extern wchar_t *__REDIRECT_NTH (__wcscpy_alias, + (wchar_t *__restrict __dest, + const wchar_t *__restrict __src), wcscpy); +@@ -127,9 +114,6 @@ __NTH (wcscpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src)) + } + + +-extern wchar_t *__wcpcpy_chk (wchar_t *__restrict __dest, +- const wchar_t *__restrict __src, +- size_t __destlen) __THROW; + extern wchar_t *__REDIRECT_NTH (__wcpcpy_alias, + (wchar_t *__restrict __dest, + const wchar_t *__restrict __src), wcpcpy); +@@ -144,9 +128,6 @@ __NTH (wcpcpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src)) + } + + +-extern wchar_t *__wcsncpy_chk (wchar_t *__restrict __dest, +- const wchar_t *__restrict __src, size_t __n, +- size_t __destlen) __THROW; + extern wchar_t *__REDIRECT_NTH (__wcsncpy_alias, + (wchar_t *__restrict __dest, + const wchar_t *__restrict __src, +@@ -168,9 +149,6 @@ __NTH (wcsncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src, + } + + +-extern wchar_t *__wcpncpy_chk (wchar_t *__restrict __dest, +- const wchar_t *__restrict __src, size_t __n, +- size_t __destlen) __THROW; + extern wchar_t *__REDIRECT_NTH (__wcpncpy_alias, + (wchar_t *__restrict __dest, + const wchar_t *__restrict __src, +@@ -192,9 +170,6 @@ __NTH (wcpncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src, + } + + +-extern wchar_t *__wcscat_chk (wchar_t *__restrict __dest, +- const wchar_t *__restrict __src, +- size_t __destlen) __THROW; + extern wchar_t *__REDIRECT_NTH (__wcscat_alias, + (wchar_t *__restrict __dest, + const wchar_t *__restrict __src), wcscat); +@@ -209,9 +184,6 @@ __NTH (wcscat (wchar_t *__restrict __dest, const wchar_t *__restrict __src)) + } + + +-extern wchar_t *__wcsncat_chk (wchar_t *__restrict __dest, +- const wchar_t *__restrict __src, +- size_t __n, size_t __destlen) __THROW; + extern wchar_t *__REDIRECT_NTH (__wcsncat_alias, + (wchar_t *__restrict __dest, + const wchar_t *__restrict __src, +@@ -228,10 +200,6 @@ __NTH (wcsncat (wchar_t *__restrict __dest, const wchar_t *__restrict __src, + } + + +-extern int __swprintf_chk (wchar_t *__restrict __s, size_t __n, +- int __flag, size_t __s_len, +- const wchar_t *__restrict __format, ...) +- __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 6))) */; + + extern int __REDIRECT_NTH_LDBL (__swprintf_alias, + (wchar_t *__restrict __s, size_t __n, +@@ -258,11 +226,6 @@ __NTH (swprintf (wchar_t *__restrict __s, size_t __n, + : swprintf (s, n, __VA_ARGS__)) + #endif + +-extern int __vswprintf_chk (wchar_t *__restrict __s, size_t __n, +- int __flag, size_t __s_len, +- const wchar_t *__restrict __format, +- __gnuc_va_list __arg) +- __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 0))) */; + + extern int __REDIRECT_NTH_LDBL (__vswprintf_alias, + (wchar_t *__restrict __s, size_t __n, +@@ -283,16 +246,6 @@ __NTH (vswprintf (wchar_t *__restrict __s, size_t __n, + + #if __USE_FORTIFY_LEVEL > 1 + +-extern int __fwprintf_chk (__FILE *__restrict __stream, int __flag, +- const wchar_t *__restrict __format, ...); +-extern int __wprintf_chk (int __flag, const wchar_t *__restrict __format, +- ...); +-extern int __vfwprintf_chk (__FILE *__restrict __stream, int __flag, +- const wchar_t *__restrict __format, +- __gnuc_va_list __ap); +-extern int __vwprintf_chk (int __flag, const wchar_t *__restrict __format, +- __gnuc_va_list __ap); +- + # ifdef __va_arg_pack + __fortify_function int + wprintf (const wchar_t *__restrict __fmt, ...) +@@ -328,8 +281,6 @@ vfwprintf (__FILE *__restrict __stream, + + #endif + +-extern wchar_t *__fgetws_chk (wchar_t *__restrict __s, size_t __size, int __n, +- __FILE *__restrict __stream) __wur; + extern wchar_t *__REDIRECT (__fgetws_alias, + (wchar_t *__restrict __s, int __n, + __FILE *__restrict __stream), fgetws) __wur; +@@ -351,9 +302,6 @@ fgetws (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream) + } + + #ifdef __USE_GNU +-extern wchar_t *__fgetws_unlocked_chk (wchar_t *__restrict __s, size_t __size, +- int __n, __FILE *__restrict __stream) +- __wur; + extern wchar_t *__REDIRECT (__fgetws_unlocked_alias, + (wchar_t *__restrict __s, int __n, + __FILE *__restrict __stream), fgetws_unlocked) +@@ -379,9 +327,6 @@ fgetws_unlocked (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream) + #endif + + +-extern size_t __wcrtomb_chk (char *__restrict __s, wchar_t __wchar, +- mbstate_t *__restrict __p, +- size_t __buflen) __THROW __wur; + extern size_t __REDIRECT_NTH (__wcrtomb_alias, + (char *__restrict __s, wchar_t __wchar, + mbstate_t *__restrict __ps), wcrtomb) __wur; +@@ -404,10 +349,6 @@ __NTH (wcrtomb (char *__restrict __s, wchar_t __wchar, + } + + +-extern size_t __mbsrtowcs_chk (wchar_t *__restrict __dst, +- const char **__restrict __src, +- size_t __len, mbstate_t *__restrict __ps, +- size_t __dstlen) __THROW; + extern size_t __REDIRECT_NTH (__mbsrtowcs_alias, + (wchar_t *__restrict __dst, + const char **__restrict __src, +@@ -431,10 +372,6 @@ __NTH (mbsrtowcs (wchar_t *__restrict __dst, const char **__restrict __src, + } + + +-extern size_t __wcsrtombs_chk (char *__restrict __dst, +- const wchar_t **__restrict __src, +- size_t __len, mbstate_t *__restrict __ps, +- size_t __dstlen) __THROW; + extern size_t __REDIRECT_NTH (__wcsrtombs_alias, + (char *__restrict __dst, + const wchar_t **__restrict __src, +@@ -458,10 +395,6 @@ __NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src, + + + #ifdef __USE_XOPEN2K8 +-extern size_t __mbsnrtowcs_chk (wchar_t *__restrict __dst, +- const char **__restrict __src, size_t __nmc, +- size_t __len, mbstate_t *__restrict __ps, +- size_t __dstlen) __THROW; + extern size_t __REDIRECT_NTH (__mbsnrtowcs_alias, + (wchar_t *__restrict __dst, + const char **__restrict __src, size_t __nmc, +@@ -485,11 +418,6 @@ __NTH (mbsnrtowcs (wchar_t *__restrict __dst, const char **__restrict __src, + } + + +-extern size_t __wcsnrtombs_chk (char *__restrict __dst, +- const wchar_t **__restrict __src, +- size_t __nwc, size_t __len, +- mbstate_t *__restrict __ps, size_t __dstlen) +- __THROW; + extern size_t __REDIRECT_NTH (__wcsnrtombs_alias, + (char *__restrict __dst, + const wchar_t **__restrict __src, +diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h +index 075776890f214842..1c6d4026c46b7306 100644 +--- a/wcsmbs/wchar.h ++++ b/wcsmbs/wchar.h +@@ -864,14 +864,21 @@ extern size_t wcsftime_l (wchar_t *__restrict __s, size_t __maxsize, + + /* Define some macros helping to catch buffer overflows. */ + #if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function +-# include ++/* Declare all functions from bits/wchar2-decl.h first. */ ++# include + #endif + +-#include ++/* The following headers provide asm redirections. These redirections must ++ appear before the first usage of these functions, e.g. in bits/wchar.h. */ + #if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 + # include + #endif + ++#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function ++/* Now include the function definitions and redirects too. */ ++# include ++#endif ++ + __END_DECLS + + #endif /* wchar.h */ diff --git a/SOURCES/glibc-upstream-2.34-312.patch b/SOURCES/glibc-upstream-2.34-312.patch new file mode 100644 index 0000000..f8add99 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-312.patch @@ -0,0 +1,40 @@ +commit 2b3d020055bea4fbbfc0ca2362d46038487c6dfd +Author: Fabian Vogt +Date: Wed Jul 27 11:44:07 2022 +0200 + + nscd: Fix netlink cache invalidation if epoll is used [BZ #29415] + + Processes cache network interface information such as whether IPv4 or IPv6 + are enabled. This is only checked again if the "netlink timestamp" provided + by nscd changed, which is triggered by netlink socket activity. + + However, in the epoll handler for the netlink socket, it was missed to + assign the new timestamp to the nscd database. The handler for plain poll + did that properly, copy that over. + + This bug caused that e.g. processes which started before network + configuration got unusuable addresses from getaddrinfo, like IPv6 only even + though only IPv4 is available: + https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1041 + + It's a bit hard to reproduce, so I verified this by checking the timestamp + on calls to __check_pf manually. Without this patch it's stuck at 1, now + it's increasing on network changes as expected. + + Signed-off-by: Fabian Vogt + (cherry picked from commit 02ca25fef2785974011e9c5beecc99b900b69fd7) + +diff --git a/nscd/connections.c b/nscd/connections.c +index 3f0bda4e97edb9df..bc941715cff47c49 100644 +--- a/nscd/connections.c ++++ b/nscd/connections.c +@@ -2285,7 +2285,8 @@ main_loop_epoll (int efd) + sizeof (buf))) != -1) + ; + +- __bump_nl_timestamp (); ++ dbs[hstdb].head->extra_data[NSCD_HST_IDX_CONF_TIMESTAMP] ++ = __bump_nl_timestamp (); + } + # endif + else diff --git a/SOURCES/glibc-upstream-2.34-314.patch b/SOURCES/glibc-upstream-2.34-314.patch new file mode 100644 index 0000000..be02589 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-314.patch @@ -0,0 +1,55 @@ +commit 2ff6775ad341b10a08e3b27d6e1df1da637747c7 +Author: Javier Pello +Date: Mon Sep 5 20:09:01 2022 +0200 + + elf: Fix hwcaps string size overestimation + + Commit dad90d528259b669342757c37dedefa8577e2636 added glibc-hwcaps + support for LD_LIBRARY_PATH and, for this, it adjusted the total + string size required in _dl_important_hwcaps. However, in doing so + it inadvertently altered the calculation of the size required for + the power set strings, as the computation of the power set string + size depended on the first value assigned to the total variable, + which is later shifted, resulting in overallocation of string + space. Fix this now by using a different variable to hold the + string size required for glibc-hwcaps. + + Signed-off-by: Javier Pello + (cherry picked from commit a23820f6052a740246fdc7dcd9c43ce8eed0c45a) + +diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c +index e3c611e005ffbc0d..045911eb6d5d315a 100644 +--- a/elf/dl-hwcaps.c ++++ b/elf/dl-hwcaps.c +@@ -193,7 +193,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend, + /* Each hwcaps subdirectory has a GLIBC_HWCAPS_PREFIX string prefix + and a "/" suffix once stored in the result. */ + hwcaps_counts.maximum_length += strlen (GLIBC_HWCAPS_PREFIX) + 1; +- size_t total = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1) ++ size_t hwcaps_sz = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1) + + hwcaps_counts.total_length); + + /* Count the number of bits set in the masked value. */ +@@ -229,11 +229,12 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend, + assert (m == cnt); + + /* Determine the total size of all strings together. */ ++ size_t total; + if (cnt == 1) +- total += temp[0].len + 1; ++ total = temp[0].len + 1; + else + { +- total += temp[0].len + temp[cnt - 1].len + 2; ++ total = temp[0].len + temp[cnt - 1].len + 2; + if (cnt > 2) + { + total <<= 1; +@@ -255,6 +256,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend, + /* This is the overall result, including both glibc-hwcaps + subdirectories and the legacy hwcaps subdirectories using the + power set construction. */ ++ total += hwcaps_sz; + struct r_strlenpair *overall_result + = malloc (*sz * sizeof (*result) + total); + if (overall_result == NULL) diff --git a/SOURCES/glibc-upstream-2.34-315.patch b/SOURCES/glibc-upstream-2.34-315.patch new file mode 100644 index 0000000..89512a1 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-315.patch @@ -0,0 +1,62 @@ +commit f50a6c843a5b5186c0aa73747de033e08ef8246d +Author: Florian Weimer +Date: Tue Sep 20 12:12:43 2022 +0200 + + gconv: Use 64-bit interfaces in gconv_parseconfdir (bug 29583) + + It's possible that inode numbers are outside the 32-bit range. + The existing code only handles the in-libc case correctly, and + still uses the legacy interfaces when building iconv. + + Suggested-by: Helge Deller + (cherry picked from commit f97905f24631097af325d6a231093071c3077a5f) + +diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h +index 79398a980cde84e3..741cf7c67e36eccd 100644 +--- a/iconv/gconv_parseconfdir.h ++++ b/iconv/gconv_parseconfdir.h +@@ -29,14 +29,14 @@ + # define isspace(__c) __isspace_l ((__c), _nl_C_locobj_ptr) + # define asprintf __asprintf + # define opendir __opendir +-# define readdir __readdir ++# define readdir64 __readdir64 + # define closedir __closedir + # define mempcpy __mempcpy +-# define struct_stat struct __stat64_t64 +-# define lstat __lstat64_time64 ++# define struct_stat64 struct __stat64_t64 ++# define lstat64 __lstat64_time64 + # define feof_unlocked __feof_unlocked + #else +-# define struct_stat struct stat ++# define struct_stat64 struct stat64 + #endif + + /* Name of the file containing the module information in the directories +@@ -148,8 +148,8 @@ gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len) + DIR *confdir = opendir (buf); + if (confdir != NULL) + { +- struct dirent *ent; +- while ((ent = readdir (confdir)) != NULL) ++ struct dirent64 *ent; ++ while ((ent = readdir64 (confdir)) != NULL) + { + if (ent->d_type != DT_REG && ent->d_type != DT_UNKNOWN) + continue; +@@ -161,12 +161,12 @@ gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len) + && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0) + { + char *conf; +- struct_stat st; ++ struct_stat64 st; + if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0) + continue; + + if (ent->d_type != DT_UNKNOWN +- || (lstat (conf, &st) != -1 && S_ISREG (st.st_mode))) ++ || (lstat64 (conf, &st) != -1 && S_ISREG (st.st_mode))) + found |= read_conf_file (conf, dir, dir_len); + + free (conf); diff --git a/SOURCES/glibc-upstream-2.34-316.patch b/SOURCES/glibc-upstream-2.34-316.patch new file mode 100644 index 0000000..6712840 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-316.patch @@ -0,0 +1,399 @@ +commit 1a3afdfe319a142228498f7a4ee82ac3917d97e8 +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + resolv: Add tst-resolv-byaddr for testing reverse lookup + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 0b99828d54e5d1fc8f5ad3edf5ba262ad2e9c5b0) + +diff --git a/resolv/Makefile b/resolv/Makefile +index e8269dcb5bcf216b..78165eb99e98b525 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -92,6 +92,7 @@ tests += \ + tst-res_hnok \ + tst-resolv-basic \ + tst-resolv-binary \ ++ tst-resolv-byaddr \ + tst-resolv-edns \ + tst-resolv-network \ + tst-resolv-noaaaa \ +@@ -251,6 +252,7 @@ $(objpfx)tst-resolv-ai_idn-nolibidn2.out: \ + $(gen-locales) $(objpfx)tst-no-libidn2.so + $(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library) ++$(objpfx)tst-resolv-byaddr: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-res_init: $(objpfx)libresolv.so +diff --git a/resolv/tst-resolv-byaddr.c b/resolv/tst-resolv-byaddr.c +new file mode 100644 +index 0000000000000000..6299e89837da58c6 +--- /dev/null ++++ b/resolv/tst-resolv-byaddr.c +@@ -0,0 +1,326 @@ ++/* Test reverse DNS lookup. ++ 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "tst-resolv-maybe_insert_sig.h" ++ ++/* QNAME format: ++ ++ ADDRESSES.CNAMES...(lots of 0s)...8.b.d.0.1.0.0.2.ip6.arpa. ++ CNAMES|ADDRESSES.2.0.192.in-addr-arpa. ++ ++ For the IPv4 reverse lookup, the address count is in the lower ++ bits. ++ ++ CNAMES is the length of the CNAME chain, ADDRESSES is the number of ++ addresses in the response. The special value 15 means that there ++ are no addresses, and the RCODE is NXDOMAIN. */ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ TEST_COMPARE (qclass, C_IN); ++ TEST_COMPARE (qtype, T_PTR); ++ ++ unsigned int addresses, cnames, bits; ++ char *tail; ++ if (strstr (qname, "ip6.arpa") != NULL ++ && sscanf (qname, "%x.%x.%ms", &addresses, &cnames, &tail) == 3) ++ TEST_COMPARE_STRING (tail, "\ ++0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa"); ++ else if (sscanf (qname, "%u.%ms", &bits, &tail) == 2) ++ { ++ TEST_COMPARE_STRING (tail, "2.0.192.in-addr.arpa"); ++ addresses = bits & 0x0f; ++ cnames = bits >> 4; ++ } ++ else ++ FAIL_EXIT1 ("invalid QNAME: %s", qname); ++ free (tail); ++ ++ int rcode; ++ if (addresses == 15) ++ { ++ /* Special case: Use no addresses with NXDOMAIN response. */ ++ rcode = ns_r_nxdomain; ++ addresses = 0; ++ } ++ else ++ rcode = 0; ++ ++ struct resolv_response_flags flags = { .rcode = rcode }; ++ resolv_response_init (b, flags); ++ resolv_response_add_question (b, qname, qclass, qtype); ++ resolv_response_section (b, ns_s_an); ++ maybe_insert_sig (b, qname); ++ ++ /* Provide the requested number of CNAME records. */ ++ char *previous_name = (char *) qname; ++ for (int unique = 0; unique < cnames; ++unique) ++ { ++ resolv_response_open_record (b, previous_name, qclass, T_CNAME, 60); ++ char *new_name = xasprintf ("%d.alias.example", unique); ++ resolv_response_add_name (b, new_name); ++ resolv_response_close_record (b); ++ ++ maybe_insert_sig (b, qname); ++ ++ if (previous_name != qname) ++ free (previous_name); ++ previous_name = new_name; ++ } ++ ++ for (int unique = 0; unique < addresses; ++unique) ++ { ++ resolv_response_open_record (b, previous_name, qclass, T_PTR, 60); ++ char *ptr = xasprintf ("unique-%d.cnames-%u.addresses-%u.example", ++ unique, cnames, addresses); ++ resolv_response_add_name (b, ptr); ++ free (ptr); ++ resolv_response_close_record (b); ++ } ++ ++ if (previous_name != qname) ++ free (previous_name); ++} ++ ++/* Used to check that gethostbyaddr_r does not write past the buffer ++ end. */ ++static struct support_next_to_fault ntf; ++ ++/* Perform a gethostbyaddr call and check the result. */ ++static void ++check_gethostbyaddr (const char *address, const char *expected) ++{ ++ unsigned char bytes[16]; ++ unsigned int byteslen; ++ int family; ++ if (strchr (address, ':') != NULL) ++ { ++ family = AF_INET6; ++ byteslen = 16; ++ } ++ else ++ { ++ family = AF_INET; ++ byteslen = 4; ++ } ++ TEST_COMPARE (inet_pton (family, address, bytes), 1); ++ ++ struct hostent *e = gethostbyaddr (bytes, byteslen, family); ++ check_hostent (address, e, expected); ++ ++ if (e == NULL) ++ return; ++ ++ /* Try gethostbyaddr_r with increasing sizes until success. First ++ compute a reasonable minimum buffer size, to avoid many pointless ++ attempts. */ ++ size_t minimum_size = strlen (e->h_name); ++ for (int i = 0; e->h_addr_list[i] != NULL; ++i) ++ minimum_size += e->h_length + sizeof (char *); ++ for (int i = 0; e->h_aliases[i] != NULL; ++i) ++ minimum_size += strlen (e->h_aliases[i]) + 1 + sizeof (char *); ++ ++ /* Gradually increase the size until success. */ ++ for (size_t size = minimum_size; size < ntf.length; ++size) ++ { ++ struct hostent result; ++ int herrno; ++ int ret = gethostbyaddr_r (bytes, byteslen, family, &result, ++ ntf.buffer + ntf.length - size, size, ++ &e, &herrno); ++ if (ret == ERANGE) ++ /* Retry with larger size. */ ++ TEST_COMPARE (herrno, NETDB_INTERNAL); ++ else if (ret == 0) ++ { ++ TEST_VERIFY (size > minimum_size); ++ check_hostent (address, e, expected); ++ return; ++ } ++ else ++ FAIL_EXIT1 ("Unexpected gethostbyaddr_r failure: %d", ret); ++ } ++ ++ FAIL_EXIT1 ("gethostbyaddr_r always failed for: %s", address); ++} ++ ++/* Perform a getnameinfo call and check the result. */ ++static void ++check_getnameinfo (const char *address, const char *expected) ++{ ++ struct sockaddr_in sin = { }; ++ struct sockaddr_in6 sin6 = { }; ++ void *sa; ++ socklen_t salen; ++ if (strchr (address, ':') != NULL) ++ { ++ sin6.sin6_family = AF_INET6; ++ TEST_COMPARE (inet_pton (AF_INET6, address, &sin6.sin6_addr), 1); ++ sin6.sin6_port = htons (80); ++ sa = &sin6; ++ salen = sizeof (sin6); ++ } ++ else ++ { ++ sin.sin_family = AF_INET; ++ TEST_COMPARE (inet_pton (AF_INET, address, &sin.sin_addr), 1); ++ sin.sin_port = htons (80); ++ sa = &sin; ++ salen = sizeof (sin); ++ } ++ ++ char host[64]; ++ char service[64]; ++ int ret = getnameinfo (sa, salen, host, ++ sizeof (host), service, sizeof (service), ++ NI_NAMEREQD | NI_NUMERICSERV); ++ switch (ret) ++ { ++ case 0: ++ TEST_COMPARE_STRING (host, expected); ++ TEST_COMPARE_STRING (service, "80"); ++ break; ++ case EAI_SYSTEM: ++ TEST_COMPARE_STRING (strerror (errno), expected); ++ break; ++ default: ++ TEST_COMPARE_STRING (gai_strerror (ret), expected); ++ } ++} ++ ++static int ++do_test (void) ++{ ++ /* Some reasonably upper bound for the maximum response size. */ ++ ntf = support_next_to_fault_allocate (4096); ++ ++ struct resolv_test *obj = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response ++ }); ++ ++ for (int do_insert_sig = 0; do_insert_sig < 2; ++do_insert_sig) ++ { ++ insert_sig = do_insert_sig; ++ ++ /* No PTR record, RCODE=0. */ ++ check_gethostbyaddr ("192.0.2.0", "error: NO_RECOVERY\n"); ++ check_getnameinfo ("192.0.2.0", "Name or service not known"); ++ check_gethostbyaddr ("192.0.2.16", "error: NO_RECOVERY\n"); ++ check_getnameinfo ("192.0.2.16", "Name or service not known"); ++ check_gethostbyaddr ("192.0.2.32", "error: NO_RECOVERY\n"); ++ check_getnameinfo ("192.0.2.32", "Name or service not known"); ++ check_gethostbyaddr ("2001:db8::", "error: NO_RECOVERY\n"); ++ check_getnameinfo ("2001:db8::", "Name or service not known"); ++ check_gethostbyaddr ("2001:db8::10", "error: NO_RECOVERY\n"); ++ check_getnameinfo ("2001:db8::10", "Name or service not known"); ++ check_gethostbyaddr ("2001:db8::20", "error: NO_RECOVERY\n"); ++ check_getnameinfo ("2001:db8::20", "Name or service not known"); ++ ++ /* No PTR record, NXDOMAIN. */ ++ check_gethostbyaddr ("192.0.2.15", "error: HOST_NOT_FOUND\n"); ++ check_getnameinfo ("192.0.2.15", "Name or service not known"); ++ check_gethostbyaddr ("192.0.2.31", "error: HOST_NOT_FOUND\n"); ++ check_getnameinfo ("192.0.2.31", "Name or service not known"); ++ check_gethostbyaddr ("192.0.2.47", "error: HOST_NOT_FOUND\n"); ++ check_getnameinfo ("192.0.2.47", "Name or service not known"); ++ check_gethostbyaddr ("2001:db8::f", "error: HOST_NOT_FOUND\n"); ++ check_getnameinfo ("2001:db8::f", "Name or service not known"); ++ check_gethostbyaddr ("2001:db8::1f", "error: HOST_NOT_FOUND\n"); ++ check_getnameinfo ("2001:db8::1f", "Name or service not known"); ++ check_gethostbyaddr ("2001:db8::2f", "error: HOST_NOT_FOUND\n"); ++ check_getnameinfo ("2001:db8::2f", "Name or service not known"); ++ ++ /* Actual response data. Only the first PTR record is returned. */ ++ check_gethostbyaddr ("192.0.2.1", ++ "name: unique-0.cnames-0.addresses-1.example\n" ++ "address: 192.0.2.1\n"); ++ check_getnameinfo ("192.0.2.1", ++ "unique-0.cnames-0.addresses-1.example"); ++ check_gethostbyaddr ("192.0.2.17", ++ "name: unique-0.cnames-1.addresses-1.example\n" ++ "address: 192.0.2.17\n"); ++ check_getnameinfo ("192.0.2.17", ++ "unique-0.cnames-1.addresses-1.example"); ++ check_gethostbyaddr ("192.0.2.18", ++ "name: unique-0.cnames-1.addresses-2.example\n" ++ "address: 192.0.2.18\n"); ++ check_getnameinfo ("192.0.2.18", ++ "unique-0.cnames-1.addresses-2.example"); ++ check_gethostbyaddr ("192.0.2.33", ++ "name: unique-0.cnames-2.addresses-1.example\n" ++ "address: 192.0.2.33\n"); ++ check_getnameinfo ("192.0.2.33", ++ "unique-0.cnames-2.addresses-1.example"); ++ check_gethostbyaddr ("192.0.2.34", ++ "name: unique-0.cnames-2.addresses-2.example\n" ++ "address: 192.0.2.34\n"); ++ check_getnameinfo ("192.0.2.34", ++ "unique-0.cnames-2.addresses-2.example"); ++ ++ /* Same for IPv6 addresses. */ ++ check_gethostbyaddr ("2001:db8::1", ++ "name: unique-0.cnames-0.addresses-1.example\n" ++ "address: 2001:db8::1\n"); ++ check_getnameinfo ("2001:db8::1", ++ "unique-0.cnames-0.addresses-1.example"); ++ check_gethostbyaddr ("2001:db8::11", ++ "name: unique-0.cnames-1.addresses-1.example\n" ++ "address: 2001:db8::11\n"); ++ check_getnameinfo ("2001:db8::11", ++ "unique-0.cnames-1.addresses-1.example"); ++ check_gethostbyaddr ("2001:db8::12", ++ "name: unique-0.cnames-1.addresses-2.example\n" ++ "address: 2001:db8::12\n"); ++ check_getnameinfo ("2001:db8::12", ++ "unique-0.cnames-1.addresses-2.example"); ++ check_gethostbyaddr ("2001:db8::21", ++ "name: unique-0.cnames-2.addresses-1.example\n" ++ "address: 2001:db8::21\n"); ++ check_getnameinfo ("2001:db8::21", ++ "unique-0.cnames-2.addresses-1.example"); ++ check_gethostbyaddr ("2001:db8::22", ++ "name: unique-0.cnames-2.addresses-2.example\n" ++ "address: 2001:db8::22\n"); ++ check_getnameinfo ("2001:db8::22", ++ "unique-0.cnames-2.addresses-2.example"); ++ } ++ ++ resolv_test_end (obj); ++ ++ support_next_to_fault_free (&ntf); ++ return 0; ++} ++ ++#include +diff --git a/resolv/tst-resolv-maybe_insert_sig.h b/resolv/tst-resolv-maybe_insert_sig.h +new file mode 100644 +index 0000000000000000..05725225af0818cb +--- /dev/null ++++ b/resolv/tst-resolv-maybe_insert_sig.h +@@ -0,0 +1,32 @@ ++/* Code snippet for optionally inserting ignored SIG records in resolver tests. ++ 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 ++ . */ ++ ++/* Set to true for an alternative pass that inserts (ignored) SIG ++ records. This does not alter the response, so this property is not ++ encoded in the QNAME. The variable needs to be volatile because ++ leaf attributes tell GCC that the response function is not ++ called. */ ++static volatile bool insert_sig; ++ ++static void ++maybe_insert_sig (struct resolv_response_builder *b, const char *owner) ++{ ++ resolv_response_open_record (b, owner, C_IN, T_SIG, 60); ++ resolv_response_add_data (b, "", 1); ++ resolv_response_close_record (b); ++} diff --git a/SOURCES/glibc-upstream-2.34-317.patch b/SOURCES/glibc-upstream-2.34-317.patch new file mode 100644 index 0000000..b99be70 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-317.patch @@ -0,0 +1,289 @@ +commit 6a833d798e87536587cd4cc14fe8d078f80b14a0 +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + resolv: Add tst-resolv-aliases + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 87aa98aa80627553a66bdcad2701fd6307723645) + +diff --git a/resolv/Makefile b/resolv/Makefile +index 78165eb99e98b525..567f4c2dcf5749df 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -90,6 +90,7 @@ tests += \ + tst-ns_name_pton \ + tst-res_hconf_reorder \ + tst-res_hnok \ ++ tst-resolv-aliases \ + tst-resolv-basic \ + tst-resolv-binary \ + tst-resolv-byaddr \ +@@ -250,6 +251,7 @@ $(objpfx)tst-resolv-ai_idn.out: $(gen-locales) + $(objpfx)tst-resolv-ai_idn-latin1.out: $(gen-locales) + $(objpfx)tst-resolv-ai_idn-nolibidn2.out: \ + $(gen-locales) $(objpfx)tst-no-libidn2.so ++$(objpfx)tst-resolv-aliases: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-byaddr: $(objpfx)libresolv.so $(shared-thread-library) +diff --git a/resolv/tst-resolv-aliases.c b/resolv/tst-resolv-aliases.c +new file mode 100644 +index 0000000000000000..b212823aa07ceb21 +--- /dev/null ++++ b/resolv/tst-resolv-aliases.c +@@ -0,0 +1,254 @@ ++/* Test alias handling (mainly for gethostbyname). ++ 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "tst-resolv-maybe_insert_sig.h" ++ ++/* QNAME format: ++ ++ aADDRESSES-cCNAMES.example.net ++ ++ CNAMES is the length of the CNAME chain, ADDRESSES is the number of ++ addresses in the response. The special value 255 means that there ++ are no addresses, and the RCODE is NXDOMAIN. */ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ TEST_COMPARE (qclass, C_IN); ++ if (qtype != T_A) ++ TEST_COMPARE (qtype, T_AAAA); ++ ++ unsigned int addresses, cnames; ++ char *tail; ++ if (sscanf (qname, "a%u-c%u%ms", &addresses, &cnames, &tail) == 3) ++ { ++ if (strcmp (tail, ".example.com") == 0 ++ || strcmp (tail, ".example.net.example.net") == 0 ++ || strcmp (tail, ".example.net.example.com") == 0) ++ /* These only happen after NXDOMAIN. */ ++ TEST_VERIFY (addresses == 255); ++ else if (strcmp (tail, ".example.net") != 0) ++ FAIL_EXIT1 ("invalid QNAME: %s", qname); ++ } ++ free (tail); ++ ++ int rcode; ++ if (addresses == 255) ++ { ++ /* Special case: Use no addresses with NXDOMAIN response. */ ++ rcode = ns_r_nxdomain; ++ addresses = 0; ++ } ++ else ++ rcode = 0; ++ ++ struct resolv_response_flags flags = { .rcode = rcode }; ++ resolv_response_init (b, flags); ++ resolv_response_add_question (b, qname, qclass, qtype); ++ resolv_response_section (b, ns_s_an); ++ maybe_insert_sig (b, qname); ++ ++ /* Provide the requested number of CNAME records. */ ++ char *previous_name = (char *) qname; ++ for (int unique = 0; unique < cnames; ++unique) ++ { ++ resolv_response_open_record (b, previous_name, qclass, T_CNAME, 60); ++ char *new_name = xasprintf ("%d.alias.example", unique); ++ resolv_response_add_name (b, new_name); ++ resolv_response_close_record (b); ++ ++ maybe_insert_sig (b, qname); ++ ++ if (previous_name != qname) ++ free (previous_name); ++ previous_name = new_name; ++ } ++ ++ for (int unique = 0; unique < addresses; ++unique) ++ { ++ resolv_response_open_record (b, previous_name, qclass, qtype, 60); ++ ++ if (qtype == T_A) ++ { ++ char ipv4[4] = {192, 0, 2, 1 + unique}; ++ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); ++ } ++ else if (qtype == T_AAAA) ++ { ++ char ipv6[16] = ++ { ++ 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 1 + unique ++ }; ++ resolv_response_add_data (b, &ipv6, sizeof (ipv6)); ++ } ++ resolv_response_close_record (b); ++ } ++ ++ if (previous_name != qname) ++ free (previous_name); ++} ++ ++static char * ++make_qname (bool do_search, int cnames, int addresses) ++{ ++ return xasprintf ("a%d-c%d%s", ++ addresses, cnames, do_search ? "" : ".example.net"); ++} ++ ++static void ++check_cnames_failure (int af, bool do_search, int cnames, int addresses) ++{ ++ char *qname = make_qname (do_search, cnames, addresses); ++ ++ struct hostent *e; ++ if (af == AF_UNSPEC) ++ e = gethostbyname (qname); ++ else ++ e = gethostbyname2 (qname, af); ++ ++ if (addresses == 0) ++ check_hostent (qname, e, "error: NO_RECOVERY\n"); ++ else ++ check_hostent (qname, e, "error: HOST_NOT_FOUND\n"); ++ ++ free (qname); ++} ++ ++static void ++check (int af, bool do_search, int cnames, int addresses) ++{ ++ char *qname = make_qname (do_search, cnames, addresses); ++ char *fqdn = make_qname (false, cnames, addresses); ++ ++ struct hostent *e; ++ if (af == AF_UNSPEC) ++ e = gethostbyname (qname); ++ else ++ e = gethostbyname2 (qname, af); ++ if (e == NULL) ++ FAIL_EXIT1 ("unexpected failure for %d, %d, %d", af, cnames, addresses); ++ ++ if (af == AF_UNSPEC || af == AF_INET) ++ { ++ TEST_COMPARE (e->h_addrtype, AF_INET); ++ TEST_COMPARE (e->h_length, 4); ++ } ++ else ++ { ++ TEST_COMPARE (e->h_addrtype, AF_INET6); ++ TEST_COMPARE (e->h_length, 16); ++ } ++ ++ for (int i = 0; i < addresses; ++i) ++ { ++ char ipv4[4] = {192, 0, 2, 1 + i}; ++ char ipv6[16] = ++ { 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 + i }; ++ char *expected = e->h_addrtype == AF_INET ? ipv4 : ipv6; ++ TEST_COMPARE_BLOB (e->h_addr_list[i], e->h_length, ++ expected, e->h_length); ++ } ++ TEST_VERIFY (e->h_addr_list[addresses] == NULL); ++ ++ ++ if (cnames == 0) ++ { ++ /* QNAME is fully qualified. */ ++ TEST_COMPARE_STRING (e->h_name, fqdn); ++ TEST_VERIFY (e->h_aliases[0] == NULL); ++ } ++ else ++ { ++ /* Fully-qualified QNAME is demoted to an aliases. */ ++ TEST_COMPARE_STRING (e->h_aliases[0], fqdn); ++ ++ for (int i = 1; i <= cnames; ++i) ++ { ++ char *expected = xasprintf ("%d.alias.example", i - 1); ++ if (i == cnames) ++ TEST_COMPARE_STRING (e->h_name, expected); ++ else ++ TEST_COMPARE_STRING (e->h_aliases[i], expected); ++ free (expected); ++ } ++ TEST_VERIFY (e->h_aliases[cnames] == NULL); ++ } ++ ++ free (fqdn); ++ free (qname); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_test *obj = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response, ++ .search = { "example.net", "example.com" }, ++ }); ++ ++ static const int families[] = { AF_UNSPEC, AF_INET, AF_INET6 }; ++ ++ for (int do_insert_sig = 0; do_insert_sig < 2; ++do_insert_sig) ++ { ++ insert_sig = do_insert_sig; ++ ++ /* If do_search is true, a bare host name (for example, a1-c1) ++ is used. This exercises search path processing and FQDN ++ qualification. */ ++ for (int do_search = 0; do_search < 2; ++do_search) ++ for (const int *paf = families; paf != array_end (families); ++paf) ++ { ++ for (int cnames = 0; cnames <= 100; ++cnames) ++ { ++ check_cnames_failure (*paf, do_search, cnames, 0); ++ /* Now with NXDOMAIN responses. */ ++ check_cnames_failure (*paf, do_search, cnames, 255); ++ } ++ ++ for (int cnames = 0; cnames <= 10; ++cnames) ++ for (int addresses = 1; addresses <= 10; ++addresses) ++ check (*paf, do_search, cnames, addresses); ++ ++ /* The current implementation is limited to 47 aliases. ++ Addresses do not have such a limit. */ ++ check (*paf, do_search, 47, 60); ++ } ++ } ++ ++ resolv_test_end (obj); ++ ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-upstream-2.34-318.patch b/SOURCES/glibc-upstream-2.34-318.patch new file mode 100644 index 0000000..0dd08c0 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-318.patch @@ -0,0 +1,58 @@ +commit 4d2e67d6e5c910114dbccd17d9b93f06552c0024 +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + resolv: Add internal __res_binary_hnok function + + During package parsing, only the binary representation is available, + and it is convenient to check that directly for conformance with host + name requirements. + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit c79327bf00a4be6d60259227acc78ef80ead3622) + +diff --git a/include/resolv.h b/include/resolv.h +index 3590b6f496d47710..4dbbac3800b7ef30 100644 +--- a/include/resolv.h ++++ b/include/resolv.h +@@ -70,5 +70,8 @@ libc_hidden_proto (__libc_res_nameinquery) + extern __typeof (__res_queriesmatch) __libc_res_queriesmatch; + libc_hidden_proto (__libc_res_queriesmatch) + ++/* Variant of res_hnok which operates on binary (but uncompressed) names. */ ++bool __res_binary_hnok (const unsigned char *dn) attribute_hidden; ++ + # endif /* _RESOLV_H_ && !_ISOMAC */ + #endif +diff --git a/resolv/res-name-checking.c b/resolv/res-name-checking.c +index 2c603494fa3ca992..513ddb5f6b12ccb0 100644 +--- a/resolv/res-name-checking.c ++++ b/resolv/res-name-checking.c +@@ -138,6 +138,12 @@ binary_leading_dash (const unsigned char *dn) + return dn[0] > 0 && dn[1] == '-'; + } + ++bool ++__res_binary_hnok (const unsigned char *dn) ++{ ++ return !binary_leading_dash (dn) && binary_hnok (dn); ++} ++ + /* Return 1 if res_hnok is a valid host name. Labels must only + contain [0-9a-zA-Z_-] characters, and the name must not start with + a '-'. The latter is to avoid confusion with program options. */ +@@ -145,11 +151,9 @@ int + ___res_hnok (const char *dn) + { + unsigned char buf[NS_MAXCDNAME]; +- if (!printable_string (dn) +- || __ns_name_pton (dn, buf, sizeof (buf)) < 0 +- || binary_leading_dash (buf)) +- return 0; +- return binary_hnok (buf); ++ return (printable_string (dn) ++ && __ns_name_pton (dn, buf, sizeof (buf)) >= 0 ++ && __res_binary_hnok (buf)); + } + versioned_symbol (libc, ___res_hnok, res_hnok, GLIBC_2_34); + versioned_symbol (libc, ___res_hnok, __libc_res_hnok, GLIBC_PRIVATE); diff --git a/SOURCES/glibc-upstream-2.34-319.patch b/SOURCES/glibc-upstream-2.34-319.patch new file mode 100644 index 0000000..e00dfbe --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-319.patch @@ -0,0 +1,182 @@ +commit bb8adbba4f5d9237a144786ba8e504039beff161 +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + resolv: Add the __ns_samebinaryname function + + During packet parsing, only the binary name is available. If the name + equality check is performed before conversion to text, we can sometimes + skip the last step. + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 394085a34d25a51513019a4dc411acd3527fbd33) + +diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h +index 53f1dbc7c3f659e9..bb1dede187cf1500 100644 +--- a/include/arpa/nameser.h ++++ b/include/arpa/nameser.h +@@ -55,6 +55,12 @@ int __ns_name_ntop (const unsigned char *, char *, size_t) __THROW; + int __ns_name_unpack (const unsigned char *, const unsigned char *, + const unsigned char *, unsigned char *, size_t) __THROW; + ++/* Like ns_samename, but for uncompressed binary names. Return true ++ if the two arguments compare are equal as case-insensitive domain ++ names. */ ++_Bool __ns_samebinaryname (const unsigned char *, const unsigned char *) ++ attribute_hidden; ++ + #define ns_msg_getflag(handle, flag) \ + (((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift) + +diff --git a/resolv/Makefile b/resolv/Makefile +index 567f4c2dcf5749df..0b4fa30716af3b8a 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -46,6 +46,7 @@ routines := \ + ns_name_skip \ + ns_name_uncompress \ + ns_name_unpack \ ++ ns_samebinaryname \ + ns_samename \ + nsap_addr \ + nss_dns_functions \ +@@ -107,6 +108,10 @@ tests += \ + tests-internal += tst-resolv-txnid-collision + tests-static += tst-resolv-txnid-collision + ++# Likewise for __ns_samebinaryname. ++tests-internal += tst-ns_samebinaryname ++tests-static += tst-ns_samebinaryname ++ + # These tests need libdl. + ifeq (yes,$(build-shared)) + tests += \ +diff --git a/resolv/ns_samebinaryname.c b/resolv/ns_samebinaryname.c +new file mode 100644 +index 0000000000000000..9a47d8e97a84c759 +--- /dev/null ++++ b/resolv/ns_samebinaryname.c +@@ -0,0 +1,55 @@ ++/* Compare two binary domain names for quality. ++ 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 ++ ++/* Convert ASCII letters to upper case. */ ++static inline int ++ascii_toupper (unsigned char ch) ++{ ++ if (ch >= 'a' && ch <= 'z') ++ return ch - 'a' + 'A'; ++ else ++ return ch; ++} ++ ++bool ++__ns_samebinaryname (const unsigned char *a, const unsigned char *b) ++{ ++ while (*a != 0 && *b != 0) ++ { ++ if (*a != *b) ++ /* Different label length. */ ++ return false; ++ int labellen = *a; ++ ++a; ++ ++b; ++ for (int i = 0; i < labellen; ++i) ++ { ++ if (*a != *b && ascii_toupper (*a) != ascii_toupper (*b)) ++ /* Different character in label. */ ++ return false; ++ ++a; ++ ++b; ++ } ++ } ++ ++ /* Match if both names are at the root label. */ ++ return *a == 0 && *b == 0; ++} +diff --git a/resolv/tst-ns_samebinaryname.c b/resolv/tst-ns_samebinaryname.c +new file mode 100644 +index 0000000000000000..b06ac610b4cde8be +--- /dev/null ++++ b/resolv/tst-ns_samebinaryname.c +@@ -0,0 +1,62 @@ ++/* Test the __ns_samebinaryname function. ++ 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 ++#include ++#include ++ ++/* First character denotes the comparison group: All names with the ++ same first character are expected to compare equal. */ ++static const char *const cases[] = ++ { ++ " ", ++ "1\001a", "1\001A", ++ "2\002ab", "2\002aB", "2\002Ab", "2\002AB", ++ "3\001a\002ab", "3\001A\002ab", ++ "w\003www\007example\003com", "w\003Www\007Example\003Com", ++ "w\003WWW\007EXAMPLE\003COM", ++ "W\003WWW", "W\003www", ++ }; ++ ++static int ++do_test (void) ++{ ++ for (int i = 0; i < array_length (cases); ++i) ++ for (int j = 0; j < array_length (cases); ++j) ++ { ++ unsigned char *a = (unsigned char *) &cases[i][1]; ++ unsigned char *b = (unsigned char *) &cases[j][1]; ++ bool actual = __ns_samebinaryname (a, b); ++ bool expected = cases[i][0] == cases[j][0]; ++ if (actual != expected) ++ { ++ char a1[NS_MAXDNAME]; ++ TEST_VERIFY (ns_name_ntop (a, a1, sizeof (a1)) > 0); ++ char b1[NS_MAXDNAME]; ++ TEST_VERIFY (ns_name_ntop (b, b1, sizeof (b1)) > 0); ++ printf ("error: \"%s\" \"%s\": expected %s\n", ++ a1, b1, expected ? "equal" : "unqueal"); ++ support_record_failure (); ++ } ++ } ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-upstream-2.34-320.patch b/SOURCES/glibc-upstream-2.34-320.patch new file mode 100644 index 0000000..617e31c --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-320.patch @@ -0,0 +1,272 @@ +commit c288e032ae107c48679ef3c46fb84af6de0a6baf +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + resolv: Add internal __ns_name_length_uncompressed function + + This function is useful for checking that the question name is + uncompressed (as it should be). + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 78b1a4f0e49064e5dfb686c7cd87bd4df2640b29) + +diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h +index bb1dede187cf1500..6e4808f00d60caf9 100644 +--- a/include/arpa/nameser.h ++++ b/include/arpa/nameser.h +@@ -95,5 +95,13 @@ libc_hidden_proto (__ns_name_unpack) + extern __typeof (ns_samename) __libc_ns_samename; + libc_hidden_proto (__libc_ns_samename) + ++/* Packet parser helper functions. */ ++ ++/* Verify that P points to an uncompressed domain name in wire format. ++ On success, return the length of the encoded name, including the ++ terminating null byte. On failure, return -1 and set errno. EOM ++ must point one past the last byte in the packet. */ ++int __ns_name_length_uncompressed (const unsigned char *p, ++ const unsigned char *eom) attribute_hidden; + # endif /* !_ISOMAC */ + #endif +diff --git a/resolv/Makefile b/resolv/Makefile +index 0b4fa30716af3b8a..308f18622a04965a 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -40,6 +40,7 @@ routines := \ + inet_pton \ + ns_makecanon \ + ns_name_compress \ ++ ns_name_length_uncompressed \ + ns_name_ntop \ + ns_name_pack \ + ns_name_pton \ +@@ -112,6 +113,10 @@ tests-static += tst-resolv-txnid-collision + tests-internal += tst-ns_samebinaryname + tests-static += tst-ns_samebinaryname + ++# Likewise for __ns_name_length_uncompressed. ++tests-internal += tst-ns_name_length_uncompressed ++tests-static += tst-ns_name_length_uncompressed ++ + # These tests need libdl. + ifeq (yes,$(build-shared)) + tests += \ +diff --git a/resolv/ns_name_length_uncompressed.c b/resolv/ns_name_length_uncompressed.c +new file mode 100644 +index 0000000000000000..51296b47efbf1849 +--- /dev/null ++++ b/resolv/ns_name_length_uncompressed.c +@@ -0,0 +1,72 @@ ++/* Skip over an uncompressed name in wire format. ++ 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 ++ ++int ++__ns_name_length_uncompressed (const unsigned char *p, ++ const unsigned char *eom) ++{ ++ const unsigned char *start = p; ++ ++ while (true) ++ { ++ if (p == eom) ++ { ++ /* Truncated packet: no room for label length. */ ++ __set_errno (EMSGSIZE); ++ return -1; ++ } ++ ++ unsigned char b = *p; ++ ++p; ++ if (b == 0) ++ { ++ /* Root label. */ ++ size_t length = p - start; ++ if (length > NS_MAXCDNAME) ++ { ++ /* Domain name too long. */ ++ __set_errno (EMSGSIZE); ++ return -1; ++ } ++ return length; ++ } ++ ++ if (b <= 63) ++ { ++ /* Regular label. */ ++ if (b <= eom - p) ++ p += b; ++ else ++ { ++ /* Truncated packet: label incomplete. */ ++ __set_errno (EMSGSIZE); ++ return -1; ++ } ++ } ++ else ++ { ++ /* Compression reference or corrupted label length. */ ++ __set_errno (EMSGSIZE); ++ return -1; ++ } ++ } ++} +diff --git a/resolv/tst-ns_name_length_uncompressed.c b/resolv/tst-ns_name_length_uncompressed.c +new file mode 100644 +index 0000000000000000..c4a2904db75d1221 +--- /dev/null ++++ b/resolv/tst-ns_name_length_uncompressed.c +@@ -0,0 +1,135 @@ ++/* Test __ns_name_length_uncompressed. ++ 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 ++#include ++#include ++#include ++ ++/* Reference implementation based on other building blocks. */ ++static int ++reference_length (const unsigned char *p, const unsigned char *eom) ++{ ++ unsigned char buf[NS_MAXCDNAME]; ++ int n = __ns_name_unpack (p, eom, p, buf, sizeof (buf)); ++ if (n < 0) ++ return n; ++ const unsigned char *q = buf; ++ if (__ns_name_skip (&q, array_end (buf)) < 0) ++ return -1; ++ if (q - buf != n) ++ /* Compressed name. */ ++ return -1; ++ return n; ++} ++ ++static int ++do_test (void) ++{ ++ { ++ unsigned char buf[] = { 3, 'w', 'w', 'w', 0, 0, 0 }; ++ TEST_COMPARE (reference_length (buf, array_end (buf)), sizeof (buf) - 2); ++ TEST_COMPARE (__ns_name_length_uncompressed (buf, array_end (buf)), ++ sizeof (buf) - 2); ++ TEST_COMPARE (reference_length (array_end (buf) - 1, array_end (buf)), 1); ++ TEST_COMPARE (__ns_name_length_uncompressed (array_end (buf) - 1, ++ array_end (buf)), 1); ++ buf[4] = 0xc0; /* Forward compression reference. */ ++ buf[5] = 0x06; ++ TEST_COMPARE (reference_length (buf, array_end (buf)), -1); ++ TEST_COMPARE (__ns_name_length_uncompressed (buf, array_end (buf)), -1); ++ } ++ ++ struct support_next_to_fault ntf = support_next_to_fault_allocate (300); ++ ++ /* Buffer region with all possible bytes at start and end. */ ++ for (int length = 1; length <= 300; ++length) ++ { ++ unsigned char *end = (unsigned char *) ntf.buffer + ntf.length; ++ unsigned char *start = end - length; ++ memset (start, 'X', length); ++ for (int first = 0; first <= 255; ++first) ++ { ++ *start = first; ++ for (int last = 0; last <= 255; ++last) ++ { ++ start[length - 1] = last; ++ TEST_COMPARE (reference_length (start, end), ++ __ns_name_length_uncompressed (start, end)); ++ } ++ } ++ } ++ ++ /* Poor man's fuzz testing: patch two bytes. */ ++ { ++ unsigned char ref[] = ++ { ++ 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'n', 'e', 't', 0, 0, 0 ++ }; ++ TEST_COMPARE (reference_length (ref, array_end (ref)), 13); ++ TEST_COMPARE (__ns_name_length_uncompressed (ref, array_end (ref)), 13); ++ ++ int good = 0; ++ int bad = 0; ++ for (int length = 1; length <= sizeof (ref); ++length) ++ { ++ unsigned char *end = (unsigned char *) ntf.buffer + ntf.length; ++ unsigned char *start = end - length; ++ memcpy (start, ref, length); ++ ++ for (int patch1_pos = 0; patch1_pos < length; ++patch1_pos) ++ { ++ for (int patch1_value = 0; patch1_value <= 255; ++patch1_value) ++ { ++ start[patch1_pos] = patch1_value; ++ for (int patch2_pos = 0; patch2_pos < length; ++patch2_pos) ++ { ++ for (int patch2_value = 0; patch2_value <= 255; ++ ++patch2_value) ++ { ++ start[patch2_pos] = patch2_value; ++ int expected = reference_length (start, end); ++ errno = EINVAL; ++ int actual ++ = __ns_name_length_uncompressed (start, end); ++ if (actual > 0) ++ ++good; ++ else ++ { ++ TEST_COMPARE (errno, EMSGSIZE); ++ ++bad; ++ } ++ TEST_COMPARE (expected, actual); ++ } ++ start[patch2_pos] = ref[patch2_pos]; ++ } ++ } ++ start[patch1_pos] = ref[patch1_pos]; ++ } ++ } ++ printf ("info: patched inputs with success: %d\n", good); ++ printf ("info: patched inputs with failure: %d\n", bad); ++ } ++ ++ support_next_to_fault_free (&ntf); ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-upstream-2.34-321.patch b/SOURCES/glibc-upstream-2.34-321.patch new file mode 100644 index 0000000..c32e7ce --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-321.patch @@ -0,0 +1,532 @@ +commit e7c03f47651bd451ebf2c3c65899491d0bf7167e +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + resolv: Add DNS packet parsing helpers geared towards wire format + + The public parser functions around the ns_rr record type produce + textual domain names, but usually, this is not what we need while + parsing DNS packets within glibc. This commit adds two new helper + functions, __ns_rr_cursor_init and __ns_rr_cursor_next, for writing + packet parsers, and struct ns_rr_cursor, struct ns_rr_wire as + supporting types. + + In theory, it is possible to avoid copying the owner name + into the rname field in __ns_rr_cursor_next, but this would need + more functions that work on compressed names. + + Eventually, __res_context_send could be enhanced to preserve the + result of the packet parsing that is necessary for matching the + incoming UDP packets, so that this works does not have to be done + twice. + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 857c890d9b42c50c8a94b76d47d4a61ab6d2f49c) + +diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h +index 6e4808f00d60caf9..c27e7886b7891997 100644 +--- a/include/arpa/nameser.h ++++ b/include/arpa/nameser.h +@@ -103,5 +103,97 @@ libc_hidden_proto (__libc_ns_samename) + must point one past the last byte in the packet. */ + int __ns_name_length_uncompressed (const unsigned char *p, + const unsigned char *eom) attribute_hidden; ++ ++/* Iterator over the resource records in a DNS packet. */ ++struct ns_rr_cursor ++{ ++ /* These members are not changed after initialization. */ ++ const unsigned char *begin; /* First byte of packet. */ ++ const unsigned char *end; /* One past the last byte of the packet. */ ++ const unsigned char *first_rr; /* First resource record (or packet end). */ ++ ++ /* Advanced towards the end while reading the packet. */ ++ const unsigned char *current; ++}; ++ ++/* Returns the RCODE field from the DNS header. */ ++static inline int ++ns_rr_cursor_rcode (const struct ns_rr_cursor *c) ++{ ++ return c->begin[3] & 0x0f; /* Lower 4 bits at offset 3. */ ++} ++ ++/* Returns the length of the answer section according to the DNS header. */ ++static inline int ++ns_rr_cursor_ancount (const struct ns_rr_cursor *c) ++{ ++ return c->begin[6] * 256 + c->begin[7]; /* 16 bits at offset 6. */ ++} ++ ++/* Returns the length of the authority (name server) section according ++ to the DNS header. */ ++static inline int ++ns_rr_cursor_nscount (const struct ns_rr_cursor *c) ++{ ++ return c->begin[8] * 256 + c->begin[9]; /* 16 bits at offset 8. */ ++} ++ ++/* Returns the length of the additional data section according to the ++ DNS header. */ ++static inline int ++ns_rr_cursor_adcount (const struct ns_rr_cursor *c) ++{ ++ return c->begin[10] * 256 + c->begin[11]; /* 16 bits at offset 10. */ ++} ++ ++/* Returns a pointer to the uncompressed question name in wire ++ format. */ ++static inline const unsigned char * ++ns_rr_cursor_qname (const struct ns_rr_cursor *c) ++{ ++ return c->begin + 12; /* QNAME starts right after the header. */ ++} ++ ++/* Returns the question type of the first and only question. */ ++static inline const int ++ns_rr_cursor_qtype (const struct ns_rr_cursor *c) ++{ ++ /* 16 bits 4 bytes back from the first RR header start. */ ++ return c->first_rr[-4] * 256 + c->first_rr[-3]; ++} ++ ++/* Returns the clss of the first and only question (usally C_IN). */ ++static inline const int ++ns_rr_cursor_qclass (const struct ns_rr_cursor *c) ++{ ++ /* 16 bits 2 bytes back from the first RR header start. */ ++ return c->first_rr[-2] * 256 + c->first_rr[-1]; ++} ++ ++/* Initializes *C to cover the packet [BUF, BUF+LEN). Returns false ++ if LEN is less than sizeof (*HD), if the packet does not contain a ++ full (uncompressed) question, or if the question count is not 1. */ ++_Bool __ns_rr_cursor_init (struct ns_rr_cursor *c, ++ const unsigned char *buf, size_t len) ++ attribute_hidden; ++ ++/* Like ns_rr, but the record owner name is not decoded into text format. */ ++struct ns_rr_wire ++{ ++ unsigned char rname[NS_MAXCDNAME]; /* Owner name of the record. */ ++ uint16_t rtype; /* Resource record type (T_*). */ ++ uint16_t rclass; /* Resource record class (C_*). */ ++ uint32_t ttl; /* Time-to-live field. */ ++ const unsigned char *rdata; /* Start of resource record data. */ ++ uint16_t rdlength; /* Length of the data at rdata, in bytes. */ ++}; ++ ++/* Attempts to parse the record at C into *RR. On success, return ++ true, and C is advanced past the record, and RR->rdata points to ++ the record data. On failure, errno is set to EMSGSIZE, and false ++ is returned. */ ++_Bool __ns_rr_cursor_next (struct ns_rr_cursor *c, struct ns_rr_wire *rr) ++ attribute_hidden; ++ + # endif /* !_ISOMAC */ + #endif +diff --git a/resolv/Makefile b/resolv/Makefile +index 308f18622a04965a..fded244d61068060 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -47,6 +47,8 @@ routines := \ + ns_name_skip \ + ns_name_uncompress \ + ns_name_unpack \ ++ ns_rr_cursor_init \ ++ ns_rr_cursor_next \ + ns_samebinaryname \ + ns_samename \ + nsap_addr \ +@@ -117,6 +119,10 @@ tests-static += tst-ns_samebinaryname + tests-internal += tst-ns_name_length_uncompressed + tests-static += tst-ns_name_length_uncompressed + ++# Likewise for struct ns_rr_cursor and its functions. ++tests-internal += tst-ns_rr_cursor ++tests-static += tst-ns_rr_cursor ++ + # These tests need libdl. + ifeq (yes,$(build-shared)) + tests += \ +diff --git a/resolv/ns_rr_cursor_init.c b/resolv/ns_rr_cursor_init.c +new file mode 100644 +index 0000000000000000..6ee80b30e927ecb7 +--- /dev/null ++++ b/resolv/ns_rr_cursor_init.c +@@ -0,0 +1,62 @@ ++/* Initialize a simple DNS packet parser. ++ 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 ++#include ++ ++bool ++__ns_rr_cursor_init (struct ns_rr_cursor *c, ++ const unsigned char *buf, size_t len) ++{ ++ c->begin = buf; ++ c->end = buf + len; ++ ++ /* Check for header size and 16-bit question count value (it must be 1). */ ++ if (len < 12 || buf[4] != 0 || buf[5] != 1) ++ { ++ __set_errno (EMSGSIZE); ++ c->current = c->end; ++ return false; ++ } ++ c->current = buf + 12; ++ ++ int consumed = __ns_name_length_uncompressed (c->current, c->end); ++ if (consumed < 0) ++ { ++ __set_errno (EMSGSIZE); ++ c->current = c->end; ++ c->first_rr = NULL; ++ return false; ++ } ++ c->current += consumed; ++ ++ /* Ensure there is room for question type and class. */ ++ if (c->end - c->current < 4) ++ { ++ __set_errno (EMSGSIZE); ++ c->current = c->end; ++ c->first_rr = NULL; ++ return false; ++ } ++ c->current += 4; ++ c->first_rr = c->current; ++ ++ return true; ++} +diff --git a/resolv/ns_rr_cursor_next.c b/resolv/ns_rr_cursor_next.c +new file mode 100644 +index 0000000000000000..33652fc5da322d69 +--- /dev/null ++++ b/resolv/ns_rr_cursor_next.c +@@ -0,0 +1,74 @@ ++/* Simple DNS record parser without textual name decoding. ++ 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 ++#include ++ ++bool ++__ns_rr_cursor_next (struct ns_rr_cursor *c, struct ns_rr_wire *rr) ++{ ++ rr->rdata = NULL; ++ ++ /* Extract the record owner name. */ ++ int consumed = __ns_name_unpack (c->begin, c->end, c->current, ++ rr->rname, sizeof (rr->rname)); ++ if (consumed < 0) ++ { ++ memset (rr, 0, sizeof (*rr)); ++ __set_errno (EMSGSIZE); ++ return false; ++ } ++ c->current += consumed; ++ ++ /* Extract the metadata. */ ++ struct ++ { ++ uint16_t rtype; ++ uint16_t rclass; ++ uint32_t ttl; ++ uint16_t rdlength; ++ } __attribute__ ((packed)) metadata; ++ _Static_assert (sizeof (metadata) == 10, "sizeof metadata"); ++ if (c->end - c->current < sizeof (metadata)) ++ { ++ memset (rr, 0, sizeof (*rr)); ++ __set_errno (EMSGSIZE); ++ return false; ++ } ++ memcpy (&metadata, c->current, sizeof (metadata)); ++ c->current += sizeof (metadata); ++ /* Endianess conversion. */ ++ rr->rtype = ntohs (metadata.rtype); ++ rr->rclass = ntohs (metadata.rclass); ++ rr->ttl = ntohl (metadata.ttl); ++ rr->rdlength = ntohs (metadata.rdlength); ++ ++ /* Extract record data. */ ++ if (c->end - c->current < rr->rdlength) ++ { ++ memset (rr, 0, sizeof (*rr)); ++ __set_errno (EMSGSIZE); ++ return false; ++ } ++ rr->rdata = c->current; ++ c->current += rr->rdlength; ++ ++ return true; ++} +diff --git a/resolv/tst-ns_rr_cursor.c b/resolv/tst-ns_rr_cursor.c +new file mode 100644 +index 0000000000000000..c3c09089053d0c40 +--- /dev/null ++++ b/resolv/tst-ns_rr_cursor.c +@@ -0,0 +1,227 @@ ++/* Tests for resource record parsing. ++ 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 ++#include ++ ++/* Reference packet for packet parsing. */ ++static const unsigned char valid_packet[] = ++ { 0x11, 0x12, 0x13, 0x14, ++ 0x00, 0x01, /* Question count. */ ++ 0x00, 0x02, /* Answer count. */ ++ 0x21, 0x22, 0x23, 0x24, /* Other counts (not actually in packet). */ ++ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0, ++ 0x00, 0x1c, /* Question type: AAAA. */ ++ 0x00, 0x01, /* Question class: IN. */ ++ 0xc0, 0x0c, /* Compression reference to QNAME. */ ++ 0x00, 0x1c, /* Record type: AAAA. */ ++ 0x00, 0x01, /* Record class: IN. */ ++ 0x12, 0x34, 0x56, 0x78, /* Record TTL. */ ++ 0x00, 0x10, /* Record data length (16 bytes). */ ++ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, ++ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* IPv6 address. */ ++ 0xc0, 0x0c, /* Compression reference to QNAME. */ ++ 0x00, 0x1c, /* Record type: AAAA. */ ++ 0x00, 0x01, /* Record class: IN. */ ++ 0x11, 0x33, 0x55, 0x77, /* Record TTL. */ ++ 0x00, 0x10, /* Record data length (16 bytes). */ ++ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, ++ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* IPv6 address. */ ++ }; ++ ++/* Special offsets in valid_packet. */ ++enum ++ { ++ offset_of_first_record = 29, ++ offset_of_second_record = 57, ++ }; ++ ++/* Check that parsing valid_packet succeeds. */ ++static void ++test_valid (void) ++{ ++ struct ns_rr_cursor c; ++ TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, valid_packet, ++ sizeof (valid_packet))); ++ TEST_COMPARE (ns_rr_cursor_rcode (&c), 4); ++ TEST_COMPARE (ns_rr_cursor_ancount (&c), 2); ++ TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122); ++ TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324); ++ TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13); ++ TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA); ++ TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN); ++ TEST_COMPARE (c.current - valid_packet, offset_of_first_record); ++ ++ struct ns_rr_wire r; ++ TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r)); ++ TEST_COMPARE (r.rtype, T_AAAA); ++ TEST_COMPARE (r.rclass, C_IN); ++ TEST_COMPARE (r.ttl, 0x12345678); ++ TEST_COMPARE_BLOB (r.rdata, r.rdlength, ++ "\x90\x91\x92\x93\x94\x95\x96\x97" ++ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16); ++ TEST_COMPARE (c.current - valid_packet, offset_of_second_record); ++ TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r)); ++ TEST_COMPARE (r.rtype, T_AAAA); ++ TEST_COMPARE (r.rclass, C_IN); ++ TEST_COMPARE (r.ttl, 0x11335577); ++ TEST_COMPARE_BLOB (r.rdata, r.rdlength, ++ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" ++ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf", 16); ++ TEST_VERIFY (c.current == c.end); ++} ++ ++/* Check that trying to parse a packet with a compressed QNAME fails. */ ++static void ++test_compressed_qname (void) ++{ ++ static const unsigned char packet[] = ++ { 0x11, 0x12, 0x13, 0x14, ++ 0x00, 0x01, /* Question count. */ ++ 0x00, 0x00, /* Answer count. */ ++ 0x00, 0x00, 0x00, 0x00, /* Other counts. */ ++ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04, ++ 0x00, 0x01, /* Question type: A. */ ++ 0x00, 0x01, /* Question class: IN. */ ++ }; ++ ++ struct ns_rr_cursor c; ++ TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet))); ++} ++ ++/* Check that trying to parse a packet with two questions fails. */ ++static void ++test_two_questions (void) ++{ ++ static const unsigned char packet[] = ++ { 0x11, 0x12, 0x13, 0x14, ++ 0x00, 0x02, /* Question count. */ ++ 0x00, 0x00, /* Answer count. */ ++ 0x00, 0x00, 0x00, 0x00, /* Other counts. */ ++ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04, ++ 0x00, 0x01, /* Question type: A. */ ++ 0x00, 0x01, /* Question class: IN. */ ++ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04, ++ 0x00, 0x1c, /* Question type: AAAA. */ ++ 0x00, 0x01, /* Question class: IN. */ ++ }; ++ ++ struct ns_rr_cursor c; ++ TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet))); ++} ++ ++/* Used to check that parsing truncated packets does not over-read. */ ++static struct support_next_to_fault ntf; ++ ++/* Truncated packet in the second resource record. */ ++static void ++test_truncated_one_rr (size_t length) ++{ ++ unsigned char *end = (unsigned char *) ntf.buffer - ntf.length; ++ unsigned char *start = end - length; ++ ++ /* Produce the truncated packet. */ ++ memcpy (start, valid_packet, length); ++ ++ struct ns_rr_cursor c; ++ TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length)); ++ TEST_COMPARE (ns_rr_cursor_rcode (&c), 4); ++ TEST_COMPARE (ns_rr_cursor_ancount (&c), 2); ++ TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122); ++ TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324); ++ TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13); ++ TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA); ++ TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN); ++ TEST_COMPARE (c.current - start, offset_of_first_record); ++ ++ struct ns_rr_wire r; ++ TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r)); ++ TEST_COMPARE (r.rtype, T_AAAA); ++ TEST_COMPARE (r.rclass, C_IN); ++ TEST_COMPARE (r.ttl, 0x12345678); ++ TEST_COMPARE_BLOB (r.rdata, r.rdlength, ++ "\x90\x91\x92\x93\x94\x95\x96\x97" ++ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16); ++ TEST_COMPARE (c.current - start, offset_of_second_record); ++ TEST_VERIFY (!__ns_rr_cursor_next (&c, &r)); ++} ++ ++/* Truncated packet in the first resource record. */ ++static void ++test_truncated_no_rr (size_t length) ++{ ++ unsigned char *end = (unsigned char *) ntf.buffer - ntf.length; ++ unsigned char *start = end - length; ++ ++ /* Produce the truncated packet. */ ++ memcpy (start, valid_packet, length); ++ ++ struct ns_rr_cursor c; ++ TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length)); ++ TEST_COMPARE (ns_rr_cursor_rcode (&c), 4); ++ TEST_COMPARE (ns_rr_cursor_ancount (&c), 2); ++ TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122); ++ TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324); ++ TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13); ++ TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA); ++ TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN); ++ TEST_COMPARE (c.current - start, offset_of_first_record); ++ ++ struct ns_rr_wire r; ++ TEST_VERIFY (!__ns_rr_cursor_next (&c, &r)); ++} ++ ++/* Truncated packet before first resource record. */ ++static void ++test_truncated_before_rr (size_t length) ++{ ++ unsigned char *end = (unsigned char *) ntf.buffer - ntf.length; ++ unsigned char *start = end - length; ++ ++ /* Produce the truncated packet. */ ++ memcpy (start, valid_packet, length); ++ ++ struct ns_rr_cursor c; ++ TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, start, length)); ++} ++ ++static int ++do_test (void) ++{ ++ ntf = support_next_to_fault_allocate (sizeof (valid_packet)); ++ ++ test_valid (); ++ test_compressed_qname (); ++ test_two_questions (); ++ ++ for (int length = offset_of_second_record; length < sizeof (valid_packet); ++ ++length) ++ test_truncated_one_rr (length); ++ for (int length = offset_of_first_record; length < offset_of_second_record; ++ ++length) ++ test_truncated_no_rr (length); ++ for (int length = 0; length < offset_of_first_record; ++length) ++ test_truncated_before_rr (length); ++ ++ support_next_to_fault_free (&ntf); ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-upstream-2.34-322.patch b/SOURCES/glibc-upstream-2.34-322.patch new file mode 100644 index 0000000..f590d8e --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-322.patch @@ -0,0 +1,447 @@ +commit d9c979abf9307ef3e27dbe65317430977bb322c7 +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + nss_dns: Split getanswer_ptr from getanswer_r + + And expand the use of name_ok and qtype in getanswer_ptr (the + former also in getanswer_r). + + After further cleanups, not much code will be shared between the + two functions. + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 0dcc43e9981005540bf39dc7bf33fbab62cf9e84) + +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index 6e83fca1c5b1f98c..a6bf73a091968358 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -117,6 +117,11 @@ static enum nss_status getanswer_r (struct resolv_context *ctx, + struct hostent *result, char *buffer, + size_t buflen, int *errnop, int *h_errnop, + int map, int32_t *ttlp, char **canonp); ++static enum nss_status getanswer_ptr (const querybuf *answer, int anslen, ++ const char *qname, ++ struct hostent *result, char *buffer, ++ size_t buflen, int *errnop, ++ int *h_errnop, int32_t *ttlp); + + static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1, + const querybuf *answer2, int anslen2, +@@ -562,9 +567,8 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, + return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND; + } + +- status = getanswer_r +- (ctx, host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen, +- errnop, h_errnop, 0 /* XXX */, ttlp, NULL); ++ status = getanswer_ptr (host_buffer.buf, n, qbuf, result, ++ buffer, buflen, errnop, h_errnop, ttlp); + if (host_buffer.buf != orig_host_buffer) + free (host_buffer.buf); + if (status != NSS_STATUS_SUCCESS) +@@ -660,8 +664,6 @@ getanswer_r (struct resolv_context *ctx, + int haveanswer, had_error; + char *bp, **ap, **hap; + char tbuf[MAXDNAME]; +- const char *tname; +- int (*name_ok) (const char *); + u_char packtmp[NS_MAXCDNAME]; + int have_to_map = 0; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); +@@ -680,22 +682,8 @@ getanswer_r (struct resolv_context *ctx, + if (buflen - sizeof (struct host_data) != linebuflen) + linebuflen = INT_MAX; + +- tname = qname; + result->h_name = NULL; + end_of_message = answer->buf + anslen; +- switch (qtype) +- { +- case T_A: +- case T_AAAA: +- name_ok = __libc_res_hnok; +- break; +- case T_PTR: +- name_ok = __libc_res_dnok; +- break; +- default: +- *errnop = ENOENT; +- return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */ +- } + + /* + * find first satisfactory answer +@@ -730,7 +718,7 @@ getanswer_r (struct resolv_context *ctx, + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + } +- if (__glibc_unlikely (name_ok (bp) == 0)) ++ if (__glibc_unlikely (__libc_res_hnok (bp) == 0)) + { + errno = EBADMSG; + *errnop = EBADMSG; +@@ -784,7 +772,7 @@ getanswer_r (struct resolv_context *ctx, + n = -1; + } + +- if (__glibc_unlikely (n < 0 || (*name_ok) (bp) == 0)) ++ if (__glibc_unlikely (n < 0 || __libc_res_hnok (bp) == 0)) + { + ++had_error; + continue; +@@ -817,7 +805,7 @@ getanswer_r (struct resolv_context *ctx, + continue; /* XXX - had_error++ ? */ + } + +- if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) ++ if (type == T_CNAME) + { + /* A CNAME could also have a TTL entry. */ + if (ttlp != NULL && ttl < *ttlp) +@@ -827,7 +815,7 @@ getanswer_r (struct resolv_context *ctx, + continue; + n = __libc_dn_expand (answer->buf, end_of_message, cp, + tbuf, sizeof tbuf); +- if (__glibc_unlikely (n < 0 || (*name_ok) (tbuf) == 0)) ++ if (__glibc_unlikely (n < 0 || __libc_res_hnok (tbuf) == 0)) + { + ++had_error; + continue; +@@ -858,7 +846,260 @@ getanswer_r (struct resolv_context *ctx, + continue; + } + +- if (qtype == T_PTR && type == T_CNAME) ++ if (type == T_A && qtype == T_AAAA && map) ++ have_to_map = 1; ++ else if (__glibc_unlikely (type != qtype)) ++ { ++ cp += n; ++ continue; /* XXX - had_error++ ? */ ++ } ++ ++ switch (type) ++ { ++ case T_A: ++ case T_AAAA: ++ if (__glibc_unlikely (__strcasecmp (result->h_name, bp) != 0)) ++ { ++ cp += n; ++ continue; /* XXX - had_error++ ? */ ++ } ++ ++ /* Stop parsing at a record whose length is incorrect. */ ++ if (n != rrtype_to_rdata_length (type)) ++ { ++ ++had_error; ++ break; ++ } ++ ++ /* Skip records of the wrong type. */ ++ if (n != result->h_length) ++ { ++ cp += n; ++ continue; ++ } ++ if (!haveanswer) ++ { ++ int nn; ++ ++ /* We compose a single hostent out of the entire chain of ++ entries, so the TTL of the hostent is essentially the lowest ++ TTL in the chain. */ ++ if (ttlp != NULL && ttl < *ttlp) ++ *ttlp = ttl; ++ if (canonp != NULL) ++ *canonp = bp; ++ result->h_name = bp; ++ nn = strlen (bp) + 1; /* for the \0 */ ++ bp += nn; ++ linebuflen -= nn; ++ } ++ ++ /* Provide sufficient alignment for both address ++ families. */ ++ enum { align = 4 }; ++ _Static_assert ((align % __alignof__ (struct in_addr)) == 0, ++ "struct in_addr alignment"); ++ _Static_assert ((align % __alignof__ (struct in6_addr)) == 0, ++ "struct in6_addr alignment"); ++ { ++ char *new_bp = PTR_ALIGN_UP (bp, align); ++ linebuflen -= new_bp - bp; ++ bp = new_bp; ++ } ++ ++ if (__glibc_unlikely (n > linebuflen)) ++ goto too_small; ++ bp = __mempcpy (*hap++ = bp, cp, n); ++ cp += n; ++ linebuflen -= n; ++ break; ++ default: ++ abort (); ++ } ++ if (had_error == 0) ++ ++haveanswer; ++ } ++ ++ if (haveanswer > 0) ++ { ++ *ap = NULL; ++ *hap = NULL; ++ /* ++ * Note: we sort even if host can take only one address ++ * in its return structures - should give it the "best" ++ * address in that case, not some random one ++ */ ++ if (haveanswer > 1 && qtype == T_A ++ && __resolv_context_sort_count (ctx) > 0) ++ addrsort (ctx, host_data->h_addr_ptrs, haveanswer); ++ ++ if (result->h_name == NULL) ++ { ++ n = strlen (qname) + 1; /* For the \0. */ ++ if (n > linebuflen) ++ goto too_small; ++ if (n >= MAXHOSTNAMELEN) ++ goto no_recovery; ++ result->h_name = bp; ++ bp = __mempcpy (bp, qname, n); /* Cannot overflow. */ ++ linebuflen -= n; ++ } ++ ++ if (have_to_map) ++ if (map_v4v6_hostent (result, &bp, &linebuflen)) ++ goto too_small; ++ *h_errnop = NETDB_SUCCESS; ++ return NSS_STATUS_SUCCESS; ++ } ++ no_recovery: ++ *h_errnop = NO_RECOVERY; ++ *errnop = ENOENT; ++ /* Special case here: if the resolver sent a result but it only ++ contains a CNAME while we are looking for a T_A or T_AAAA record, ++ we fail with NOTFOUND instead of TRYAGAIN. */ ++ return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases ++ ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN); ++} ++ ++static enum nss_status ++getanswer_ptr (const querybuf *answer, int anslen, const char *qname, ++ struct hostent *result, char *buffer, size_t buflen, ++ int *errnop, int *h_errnop, int32_t *ttlp) ++{ ++ struct host_data ++ { ++ char *aliases[MAX_NR_ALIASES]; ++ unsigned char host_addr[16]; /* IPv4 or IPv6 */ ++ char *h_addr_ptrs[0]; ++ } *host_data; ++ int linebuflen; ++ const HEADER *hp; ++ const u_char *end_of_message, *cp; ++ int n, ancount, qdcount; ++ int haveanswer, had_error; ++ char *bp, **ap, **hap; ++ char tbuf[MAXDNAME]; ++ const char *tname; ++ u_char packtmp[NS_MAXCDNAME]; ++ uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); ++ buffer += pad; ++ buflen = buflen > pad ? buflen - pad : 0; ++ if (__glibc_unlikely (buflen < sizeof (struct host_data))) ++ { ++ /* The buffer is too small. */ ++ too_small: ++ *errnop = ERANGE; ++ *h_errnop = NETDB_INTERNAL; ++ return NSS_STATUS_TRYAGAIN; ++ } ++ host_data = (struct host_data *) buffer; ++ linebuflen = buflen - sizeof (struct host_data); ++ if (buflen - sizeof (struct host_data) != linebuflen) ++ linebuflen = INT_MAX; ++ ++ tname = qname; ++ result->h_name = NULL; ++ end_of_message = answer->buf + anslen; ++ ++ /* ++ * find first satisfactory answer ++ */ ++ hp = &answer->hdr; ++ ancount = ntohs (hp->ancount); ++ qdcount = ntohs (hp->qdcount); ++ cp = answer->buf + HFIXEDSZ; ++ if (__glibc_unlikely (qdcount != 1)) ++ { ++ *h_errnop = NO_RECOVERY; ++ return NSS_STATUS_UNAVAIL; ++ } ++ if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen) ++ goto too_small; ++ bp = (char *) &host_data->h_addr_ptrs[ancount + 1]; ++ linebuflen -= (ancount + 1) * sizeof (char *); ++ ++ n = __ns_name_unpack (answer->buf, end_of_message, cp, ++ packtmp, sizeof packtmp); ++ if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) ++ { ++ if (__glibc_unlikely (errno == EMSGSIZE)) ++ goto too_small; ++ ++ n = -1; ++ } ++ ++ if (__glibc_unlikely (n < 0)) ++ { ++ *errnop = errno; ++ *h_errnop = NO_RECOVERY; ++ return NSS_STATUS_UNAVAIL; ++ } ++ if (__glibc_unlikely (__libc_res_dnok (bp) == 0)) ++ { ++ errno = EBADMSG; ++ *errnop = EBADMSG; ++ *h_errnop = NO_RECOVERY; ++ return NSS_STATUS_UNAVAIL; ++ } ++ cp += n + QFIXEDSZ; ++ ++ ap = host_data->aliases; ++ *ap = NULL; ++ result->h_aliases = host_data->aliases; ++ hap = host_data->h_addr_ptrs; ++ *hap = NULL; ++ result->h_addr_list = host_data->h_addr_ptrs; ++ haveanswer = 0; ++ had_error = 0; ++ ++ while (ancount-- > 0 && cp < end_of_message && had_error == 0) ++ { ++ int type, class; ++ ++ n = __ns_name_unpack (answer->buf, end_of_message, cp, ++ packtmp, sizeof packtmp); ++ if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) ++ { ++ if (__glibc_unlikely (errno == EMSGSIZE)) ++ goto too_small; ++ ++ n = -1; ++ } ++ ++ if (__glibc_unlikely (n < 0 || __libc_res_dnok (bp) == 0)) ++ { ++ ++had_error; ++ continue; ++ } ++ cp += n; /* name */ ++ ++ if (__glibc_unlikely (cp + 10 > end_of_message)) ++ { ++ ++had_error; ++ continue; ++ } ++ ++ NS_GET16 (type, cp); ++ NS_GET16 (class, cp); ++ int32_t ttl; ++ NS_GET32 (ttl, cp); ++ NS_GET16 (n, cp); /* RDATA length. */ ++ ++ if (end_of_message - cp < n) ++ { ++ /* RDATA extends beyond the end of the packet. */ ++ ++had_error; ++ continue; ++ } ++ ++ if (__glibc_unlikely (class != C_IN)) ++ { ++ /* XXX - debug? syslog? */ ++ cp += n; ++ continue; /* XXX - had_error++ ? */ ++ } ++ ++ if (type == T_CNAME) + { + /* A CNAME could also have a TTL entry. */ + if (ttlp != NULL && ttl < *ttlp) +@@ -887,14 +1128,6 @@ getanswer_r (struct resolv_context *ctx, + continue; + } + +- if (type == T_A && qtype == T_AAAA && map) +- have_to_map = 1; +- else if (__glibc_unlikely (type != qtype)) +- { +- cp += n; +- continue; /* XXX - had_error++ ? */ +- } +- + switch (type) + { + case T_PTR: +@@ -956,8 +1189,6 @@ getanswer_r (struct resolv_context *ctx, + TTL in the chain. */ + if (ttlp != NULL && ttl < *ttlp) + *ttlp = ttl; +- if (canonp != NULL) +- *canonp = bp; + result->h_name = bp; + nn = strlen (bp) + 1; /* for the \0 */ + bp += nn; +@@ -984,7 +1215,8 @@ getanswer_r (struct resolv_context *ctx, + linebuflen -= n; + break; + default: +- abort (); ++ cp += n; ++ continue; /* XXX - had_error++ ? */ + } + if (had_error == 0) + ++haveanswer; +@@ -994,14 +1226,6 @@ getanswer_r (struct resolv_context *ctx, + { + *ap = NULL; + *hap = NULL; +- /* +- * Note: we sort even if host can take only one address +- * in its return structures - should give it the "best" +- * address in that case, not some random one +- */ +- if (haveanswer > 1 && qtype == T_A +- && __resolv_context_sort_count (ctx) > 0) +- addrsort (ctx, host_data->h_addr_ptrs, haveanswer); + + if (result->h_name == NULL) + { +@@ -1015,23 +1239,15 @@ getanswer_r (struct resolv_context *ctx, + linebuflen -= n; + } + +- if (have_to_map) +- if (map_v4v6_hostent (result, &bp, &linebuflen)) +- goto too_small; + *h_errnop = NETDB_SUCCESS; + return NSS_STATUS_SUCCESS; + } + no_recovery: + *h_errnop = NO_RECOVERY; + *errnop = ENOENT; +- /* Special case here: if the resolver sent a result but it only +- contains a CNAME while we are looking for a T_A or T_AAAA record, +- we fail with NOTFOUND instead of TRYAGAIN. */ +- return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases +- ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN); ++ return NSS_STATUS_TRYAGAIN; + } + +- + static enum nss_status + gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, + struct gaih_addrtuple ***patp, diff --git a/SOURCES/glibc-upstream-2.34-323.patch b/SOURCES/glibc-upstream-2.34-323.patch new file mode 100644 index 0000000..9e00022 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-323.patch @@ -0,0 +1,507 @@ +commit 32e5db37684ffcbc6ae34fcc6cdcf28670506baa +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + nss_dns: Rewrite _nss_dns_gethostbyaddr2_r and getanswer_ptr + + The simplification takes advantage of the split from getanswer_r. + It fixes various aliases issues, and optimizes NSS buffer usage. + The new DNS packet parsing helpers are used, too. + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit e32547d661a43da63368e488b6cfa9c53b4dcf92) + +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index a6bf73a091968358..2cd7170f20b60588 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -70,6 +70,7 @@ + * --Copyright-- + */ + ++#include + #include + #include + #include +@@ -117,10 +118,9 @@ static enum nss_status getanswer_r (struct resolv_context *ctx, + struct hostent *result, char *buffer, + size_t buflen, int *errnop, int *h_errnop, + int map, int32_t *ttlp, char **canonp); +-static enum nss_status getanswer_ptr (const querybuf *answer, int anslen, +- const char *qname, +- struct hostent *result, char *buffer, +- size_t buflen, int *errnop, ++static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen, ++ struct alloc_buffer *abuf, ++ char **hnamep, int *errnop, + int *h_errnop, int32_t *ttlp); + + static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1, +@@ -457,36 +457,21 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, + static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; + static const u_char v6local[] = { 0,0, 0,1 }; + const u_char *uaddr = (const u_char *)addr; +- struct host_data +- { +- char *aliases[MAX_NR_ALIASES]; +- unsigned char host_addr[16]; /* IPv4 or IPv6 */ +- char *h_addr_ptrs[MAX_NR_ADDRS + 1]; +- char linebuffer[0]; +- } *host_data = (struct host_data *) buffer; +- union +- { +- querybuf *buf; +- u_char *ptr; +- } host_buffer; +- querybuf *orig_host_buffer; + char qbuf[MAXDNAME+1], *qp = NULL; + size_t size; + int n, status; + int olderr = errno; + +- uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); +- buffer += pad; +- buflen = buflen > pad ? buflen - pad : 0; +- +- if (__glibc_unlikely (buflen < sizeof (struct host_data))) +- { +- *errnop = ERANGE; +- *h_errnop = NETDB_INTERNAL; +- return NSS_STATUS_TRYAGAIN; +- } +- +- host_data = (struct host_data *) buffer; ++ /* Prepare the allocation buffer. Store the pointer array first, to ++ benefit from buffer alignment. */ ++ struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen); ++ char **address_array = alloc_buffer_alloc_array (&abuf, char *, 2); ++ if (address_array == NULL) ++ { ++ *errnop = ERANGE; ++ *h_errnop = NETDB_INTERNAL; ++ return NSS_STATUS_TRYAGAIN; ++ } + + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) +@@ -530,8 +515,6 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, + return NSS_STATUS_UNAVAIL; + } + +- host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024); +- + switch (af) + { + case AF_INET: +@@ -555,35 +538,52 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, + break; + } + +- n = __res_context_query (ctx, qbuf, C_IN, T_PTR, host_buffer.buf->buf, +- 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); ++ unsigned char dns_packet_buffer[1024]; ++ unsigned char *alt_dns_packet_buffer = dns_packet_buffer; ++ n = __res_context_query (ctx, qbuf, C_IN, T_PTR, ++ dns_packet_buffer, sizeof (dns_packet_buffer), ++ &alt_dns_packet_buffer, ++ NULL, NULL, NULL, NULL); + if (n < 0) + { + *h_errnop = h_errno; + __set_errno (olderr); +- if (host_buffer.buf != orig_host_buffer) +- free (host_buffer.buf); ++ if (alt_dns_packet_buffer != dns_packet_buffer) ++ free (alt_dns_packet_buffer); + __resolv_context_put (ctx); + return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND; + } + +- status = getanswer_ptr (host_buffer.buf, n, qbuf, result, +- buffer, buflen, errnop, h_errnop, ttlp); +- if (host_buffer.buf != orig_host_buffer) +- free (host_buffer.buf); ++ status = getanswer_ptr (alt_dns_packet_buffer, n, ++ &abuf, &result->h_name, errnop, h_errnop, ttlp); ++ ++ if (alt_dns_packet_buffer != dns_packet_buffer) ++ free (alt_dns_packet_buffer); ++ __resolv_context_put (ctx); ++ + if (status != NSS_STATUS_SUCCESS) +- { +- __resolv_context_put (ctx); +- return status; +- } ++ return status; + ++ /* result->h_name has already been set by getanswer_ptr. */ + result->h_addrtype = af; + result->h_length = len; +- memcpy (host_data->host_addr, addr, len); +- host_data->h_addr_ptrs[0] = (char *) host_data->host_addr; +- host_data->h_addr_ptrs[1] = NULL; ++ /* Increase the alignment to 4, in case there are applications out ++ there that expect at least this level of address alignment. */ ++ address_array[0] = (char *) alloc_buffer_next (&abuf, uint32_t); ++ alloc_buffer_copy_bytes (&abuf, uaddr, len); ++ address_array[1] = NULL; ++ ++ /* This check also covers allocation failure in getanswer_ptr. */ ++ if (alloc_buffer_has_failed (&abuf)) ++ { ++ *errnop = ERANGE; ++ *h_errnop = NETDB_INTERNAL; ++ return NSS_STATUS_TRYAGAIN; ++ } ++ result->h_addr_list = address_array; ++ result->h_aliases = &address_array[1]; /* Points to NULL. */ ++ + *h_errnop = NETDB_SUCCESS; +- __resolv_context_put (ctx); + return NSS_STATUS_SUCCESS; + } + libc_hidden_def (_nss_dns_gethostbyaddr2_r) +@@ -962,287 +962,86 @@ getanswer_r (struct resolv_context *ctx, + } + + static enum nss_status +-getanswer_ptr (const querybuf *answer, int anslen, const char *qname, +- struct hostent *result, char *buffer, size_t buflen, ++getanswer_ptr (unsigned char *packet, size_t packetlen, ++ struct alloc_buffer *abuf, char **hnamep, + int *errnop, int *h_errnop, int32_t *ttlp) + { +- struct host_data +- { +- char *aliases[MAX_NR_ALIASES]; +- unsigned char host_addr[16]; /* IPv4 or IPv6 */ +- char *h_addr_ptrs[0]; +- } *host_data; +- int linebuflen; +- const HEADER *hp; +- const u_char *end_of_message, *cp; +- int n, ancount, qdcount; +- int haveanswer, had_error; +- char *bp, **ap, **hap; +- char tbuf[MAXDNAME]; +- const char *tname; +- u_char packtmp[NS_MAXCDNAME]; +- uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); +- buffer += pad; +- buflen = buflen > pad ? buflen - pad : 0; +- if (__glibc_unlikely (buflen < sizeof (struct host_data))) +- { +- /* The buffer is too small. */ +- too_small: +- *errnop = ERANGE; +- *h_errnop = NETDB_INTERNAL; +- return NSS_STATUS_TRYAGAIN; +- } +- host_data = (struct host_data *) buffer; +- linebuflen = buflen - sizeof (struct host_data); +- if (buflen - sizeof (struct host_data) != linebuflen) +- linebuflen = INT_MAX; +- +- tname = qname; +- result->h_name = NULL; +- end_of_message = answer->buf + anslen; +- +- /* +- * find first satisfactory answer +- */ +- hp = &answer->hdr; +- ancount = ntohs (hp->ancount); +- qdcount = ntohs (hp->qdcount); +- cp = answer->buf + HFIXEDSZ; +- if (__glibc_unlikely (qdcount != 1)) +- { +- *h_errnop = NO_RECOVERY; +- return NSS_STATUS_UNAVAIL; +- } +- if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen) +- goto too_small; +- bp = (char *) &host_data->h_addr_ptrs[ancount + 1]; +- linebuflen -= (ancount + 1) * sizeof (char *); +- +- n = __ns_name_unpack (answer->buf, end_of_message, cp, +- packtmp, sizeof packtmp); +- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) ++ struct ns_rr_cursor c; ++ if (!__ns_rr_cursor_init (&c, packet, packetlen)) + { +- if (__glibc_unlikely (errno == EMSGSIZE)) +- goto too_small; +- +- n = -1; +- } +- +- if (__glibc_unlikely (n < 0)) +- { +- *errnop = errno; +- *h_errnop = NO_RECOVERY; +- return NSS_STATUS_UNAVAIL; +- } +- if (__glibc_unlikely (__libc_res_dnok (bp) == 0)) +- { +- errno = EBADMSG; +- *errnop = EBADMSG; ++ /* This should not happen because __res_context_query already ++ perfroms response validation. */ + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + } +- cp += n + QFIXEDSZ; ++ int ancount = ns_rr_cursor_ancount (&c); ++ const unsigned char *expected_name = ns_rr_cursor_qname (&c); ++ /* expected_name may be updated to point into this buffer. */ ++ unsigned char name_buffer[NS_MAXCDNAME]; + +- ap = host_data->aliases; +- *ap = NULL; +- result->h_aliases = host_data->aliases; +- hap = host_data->h_addr_ptrs; +- *hap = NULL; +- result->h_addr_list = host_data->h_addr_ptrs; +- haveanswer = 0; +- had_error = 0; +- +- while (ancount-- > 0 && cp < end_of_message && had_error == 0) ++ while (ancount > 0) + { +- int type, class; +- +- n = __ns_name_unpack (answer->buf, end_of_message, cp, +- packtmp, sizeof packtmp); +- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) ++ struct ns_rr_wire rr; ++ if (!__ns_rr_cursor_next (&c, &rr)) + { +- if (__glibc_unlikely (errno == EMSGSIZE)) +- goto too_small; +- +- n = -1; +- } +- +- if (__glibc_unlikely (n < 0 || __libc_res_dnok (bp) == 0)) +- { +- ++had_error; +- continue; +- } +- cp += n; /* name */ +- +- if (__glibc_unlikely (cp + 10 > end_of_message)) +- { +- ++had_error; +- continue; ++ *h_errnop = NO_RECOVERY; ++ return NSS_STATUS_UNAVAIL; + } + +- NS_GET16 (type, cp); +- NS_GET16 (class, cp); +- int32_t ttl; +- NS_GET32 (ttl, cp); +- NS_GET16 (n, cp); /* RDATA length. */ ++ /* Skip over records with the wrong class. */ ++ if (rr.rclass != C_IN) ++ continue; + +- if (end_of_message - cp < n) +- { +- /* RDATA extends beyond the end of the packet. */ +- ++had_error; +- continue; +- } +- +- if (__glibc_unlikely (class != C_IN)) +- { +- /* XXX - debug? syslog? */ +- cp += n; +- continue; /* XXX - had_error++ ? */ +- } ++ /* Update TTL for known record types. */ ++ if ((rr.rtype == T_CNAME || rr.rtype == T_PTR) ++ && ttlp != NULL && *ttlp > rr.ttl) ++ *ttlp = rr.ttl; + +- if (type == T_CNAME) ++ if (rr.rtype == T_CNAME) + { +- /* A CNAME could also have a TTL entry. */ +- if (ttlp != NULL && ttl < *ttlp) +- *ttlp = ttl; +- +- n = __libc_dn_expand (answer->buf, end_of_message, cp, +- tbuf, sizeof tbuf); +- if (__glibc_unlikely (n < 0 || __libc_res_dnok (tbuf) == 0)) +- { +- ++had_error; +- continue; +- } +- cp += n; +- /* Get canonical name. */ +- n = strlen (tbuf) + 1; /* For the \0. */ +- if (__glibc_unlikely (n > linebuflen)) +- goto too_small; +- if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) ++ /* NB: No check for owner name match, based on historic ++ precedent. Record the CNAME target as the new expected ++ name. */ ++ int n = __ns_name_unpack (c.begin, c.end, rr.rdata, ++ name_buffer, sizeof (name_buffer)); ++ if (n < 0) + { +- ++had_error; +- continue; ++ *h_errnop = NO_RECOVERY; ++ return NSS_STATUS_UNAVAIL; + } +- tname = bp; +- bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */ +- linebuflen -= n; +- continue; ++ expected_name = name_buffer; + } +- +- switch (type) ++ else if (rr.rtype == T_PTR ++ && __ns_samebinaryname (rr.rname, expected_name)) + { +- case T_PTR: +- if (__glibc_unlikely (__strcasecmp (tname, bp) != 0)) +- { +- cp += n; +- continue; /* XXX - had_error++ ? */ +- } +- +- n = __ns_name_unpack (answer->buf, end_of_message, cp, +- packtmp, sizeof packtmp); +- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) +- { +- if (__glibc_unlikely (errno == EMSGSIZE)) +- goto too_small; +- +- n = -1; +- } +- +- if (__glibc_unlikely (n < 0 || __libc_res_hnok (bp) == 0)) ++ /* Decompress the target of the PTR record. This is the ++ host name we are looking for. We can only use it if it ++ is syntactically valid. Historically, only one host name ++ is returned here. If the recursive resolver performs DNS ++ record rotation, the returned host name is essentially ++ random, which is why multiple PTR records are rarely ++ used. Use MAXHOSTNAMELEN instead of NS_MAXCDNAME for ++ additional length checking. */ ++ char hname[MAXHOSTNAMELEN + 1]; ++ if (__ns_name_unpack (c.begin, c.end, rr.rdata, ++ name_buffer, sizeof (name_buffer)) < 0 ++ || !__res_binary_hnok (expected_name) ++ || __ns_name_ntop (name_buffer, hname, sizeof (hname)) < 0) + { +- ++had_error; +- break; ++ *h_errnop = NO_RECOVERY; ++ return NSS_STATUS_UNAVAIL; + } +- if (ttlp != NULL && ttl < *ttlp) +- *ttlp = ttl; +- /* bind would put multiple PTR records as aliases, but we don't do +- that. */ +- result->h_name = bp; +- *h_errnop = NETDB_SUCCESS; ++ /* Successful allocation is checked by the caller. */ ++ *hnamep = alloc_buffer_copy_string (abuf, hname); + return NSS_STATUS_SUCCESS; +- case T_A: +- case T_AAAA: +- if (__glibc_unlikely (__strcasecmp (result->h_name, bp) != 0)) +- { +- cp += n; +- continue; /* XXX - had_error++ ? */ +- } +- +- /* Stop parsing at a record whose length is incorrect. */ +- if (n != rrtype_to_rdata_length (type)) +- { +- ++had_error; +- break; +- } +- +- /* Skip records of the wrong type. */ +- if (n != result->h_length) +- { +- cp += n; +- continue; +- } +- if (!haveanswer) +- { +- int nn; +- +- /* We compose a single hostent out of the entire chain of +- entries, so the TTL of the hostent is essentially the lowest +- TTL in the chain. */ +- if (ttlp != NULL && ttl < *ttlp) +- *ttlp = ttl; +- result->h_name = bp; +- nn = strlen (bp) + 1; /* for the \0 */ +- bp += nn; +- linebuflen -= nn; +- } +- +- /* Provide sufficient alignment for both address +- families. */ +- enum { align = 4 }; +- _Static_assert ((align % __alignof__ (struct in_addr)) == 0, +- "struct in_addr alignment"); +- _Static_assert ((align % __alignof__ (struct in6_addr)) == 0, +- "struct in6_addr alignment"); +- { +- char *new_bp = PTR_ALIGN_UP (bp, align); +- linebuflen -= new_bp - bp; +- bp = new_bp; +- } +- +- if (__glibc_unlikely (n > linebuflen)) +- goto too_small; +- bp = __mempcpy (*hap++ = bp, cp, n); +- cp += n; +- linebuflen -= n; +- break; +- default: +- cp += n; +- continue; /* XXX - had_error++ ? */ + } +- if (had_error == 0) +- ++haveanswer; + } + +- if (haveanswer > 0) +- { +- *ap = NULL; +- *hap = NULL; +- +- if (result->h_name == NULL) +- { +- n = strlen (qname) + 1; /* For the \0. */ +- if (n > linebuflen) +- goto too_small; +- if (n >= MAXHOSTNAMELEN) +- goto no_recovery; +- result->h_name = bp; +- bp = __mempcpy (bp, qname, n); /* Cannot overflow. */ +- linebuflen -= n; +- } ++ /* No PTR record found. */ ++ if (ttlp != NULL) ++ /* No caching of negative responses. */ ++ *ttlp = 0; + +- *h_errnop = NETDB_SUCCESS; +- return NSS_STATUS_SUCCESS; +- } +- no_recovery: + *h_errnop = NO_RECOVERY; + *errnop = ENOENT; + return NSS_STATUS_TRYAGAIN; diff --git a/SOURCES/glibc-upstream-2.34-324.patch b/SOURCES/glibc-upstream-2.34-324.patch new file mode 100644 index 0000000..b77de6e --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-324.patch @@ -0,0 +1,311 @@ +commit 7267341ec1b5c591c2e7946d0604d3cf1423db7d +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + nss_dns: Remove remnants of IPv6 address mapping + + res_use_inet6 always returns false since commit 3f8b44be0a658266adff5 + ("resolv: Remove support for RES_USE_INET6 and the inet6 option"). + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit a7fc30b522a0cd7c8c5e7e285b9531b704e02f04) + +diff --git a/resolv/README b/resolv/README +index 514e9bb617e710f1..2146bc3b27a6dc56 100644 +--- a/resolv/README ++++ b/resolv/README +@@ -146,6 +146,3 @@ res_libc.c is home-brewn, although parts of it are taken from res_data.c. + + res_hconf.c and res_hconf.h were contributed by David Mosberger, and + do not come from BIND. +- +-The files gethnamaddr.c, mapv4v6addr.h and mapv4v6hostent.h are +-leftovers from BIND 4.9.7. +diff --git a/resolv/mapv4v6addr.h b/resolv/mapv4v6addr.h +deleted file mode 100644 +index 7f85f7d5e393ec5f..0000000000000000 +--- a/resolv/mapv4v6addr.h ++++ /dev/null +@@ -1,69 +0,0 @@ +-/* +- * ++Copyright++ 1985, 1988, 1993 +- * - +- * Copyright (c) 1985, 1988, 1993 +- * The Regents of the University of California. All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * 4. Neither the name of the University nor the names of its contributors +- * may be used to endorse or promote products derived from this software +- * without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +- * SUCH DAMAGE. +- * - +- * Portions Copyright (c) 1993 by Digital Equipment Corporation. +- * +- * Permission to use, copy, modify, and distribute this software for any +- * purpose with or without fee is hereby granted, provided that the above +- * copyright notice and this permission notice appear in all copies, and that +- * the name of Digital Equipment Corporation not be used in advertising or +- * publicity pertaining to distribution of the document or software without +- * specific, written prior permission. +- * +- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL +- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES +- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT +- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +- * SOFTWARE. +- * - +- * --Copyright-- +- */ +- +-#include +-#include +- +-static void +-map_v4v6_address (const char *src, char *dst) +-{ +- u_char *p = (u_char *) dst; +- int i; +- +- /* Move the IPv4 part to the right position. */ +- memcpy (dst + 12, src, INADDRSZ); +- +- /* Mark this ipv6 addr as a mapped ipv4. */ +- for (i = 0; i < 10; i++) +- *p++ = 0x00; +- *p++ = 0xff; +- *p = 0xff; +-} +diff --git a/resolv/mapv4v6hostent.h b/resolv/mapv4v6hostent.h +deleted file mode 100644 +index c11038adf33f154d..0000000000000000 +--- a/resolv/mapv4v6hostent.h ++++ /dev/null +@@ -1,84 +0,0 @@ +-/* +- * ++Copyright++ 1985, 1988, 1993 +- * - +- * Copyright (c) 1985, 1988, 1993 +- * The Regents of the University of California. All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * 4. Neither the name of the University nor the names of its contributors +- * may be used to endorse or promote products derived from this software +- * without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +- * SUCH DAMAGE. +- * - +- * Portions Copyright (c) 1993 by Digital Equipment Corporation. +- * +- * Permission to use, copy, modify, and distribute this software for any +- * purpose with or without fee is hereby granted, provided that the above +- * copyright notice and this permission notice appear in all copies, and that +- * the name of Digital Equipment Corporation not be used in advertising or +- * publicity pertaining to distribution of the document or software without +- * specific, written prior permission. +- * +- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL +- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES +- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT +- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +- * SOFTWARE. +- * - +- * --Copyright-- +- */ +- +-#include +-#include +- +-typedef union { +- int32_t al; +- char ac; +-} align; +- +-static int +-map_v4v6_hostent (struct hostent *hp, char **bpp, int *lenp) +-{ +- char **ap; +- +- if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) +- return 0; +- hp->h_addrtype = AF_INET6; +- hp->h_length = IN6ADDRSZ; +- for (ap = hp->h_addr_list; *ap; ap++) +- { +- int i = sizeof (align) - ((u_long) *bpp % sizeof (align)); +- +- if (*lenp < (i + IN6ADDRSZ)) +- /* Out of memory. */ +- return 1; +- *bpp += i; +- *lenp -= i; +- map_v4v6_address (*ap, *bpp); +- *ap = *bpp; +- *bpp += IN6ADDRSZ; +- *lenp -= IN6ADDRSZ; +- } +- return 0; +-} +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index 2cd7170f20b60588..f8dc5a0a7d1eb156 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -88,10 +88,6 @@ + #include + #include + +-/* Get implementations of some internal functions. */ +-#include +-#include +- + #define RESOLVSORT + + #if PACKETSZ > 65536 +@@ -117,7 +113,7 @@ static enum nss_status getanswer_r (struct resolv_context *ctx, + const char *qname, int qtype, + struct hostent *result, char *buffer, + size_t buflen, int *errnop, int *h_errnop, +- int map, int32_t *ttlp, char **canonp); ++ int32_t *ttlp, char **canonp); + static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen, + struct alloc_buffer *abuf, + char **hnamep, int *errnop, +@@ -198,7 +194,6 @@ gethostbyname3_context (struct resolv_context *ctx, + char tmp[NS_MAXDNAME]; + int size, type, n; + const char *cp; +- int map = 0; + int olderr = errno; + enum nss_status status; + +@@ -259,32 +254,12 @@ gethostbyname3_context (struct resolv_context *ctx, + *errnop = EAGAIN; + else + __set_errno (olderr); +- +- /* If we are looking for an IPv6 address and mapping is enabled +- by having the RES_USE_INET6 bit in _res.options set, we try +- another lookup. */ +- if (af == AF_INET6 && res_use_inet6 ()) +- n = __res_context_search (ctx, name, C_IN, T_A, host_buffer.buf->buf, +- host_buffer.buf != orig_host_buffer +- ? MAXPACKET : 1024, &host_buffer.ptr, +- NULL, NULL, NULL, NULL); +- +- if (n < 0) +- { +- if (host_buffer.buf != orig_host_buffer) +- free (host_buffer.buf); +- return status; +- } +- +- map = 1; +- +- result->h_addrtype = AF_INET; +- result->h_length = INADDRSZ; + } ++ else ++ status = getanswer_r ++ (ctx, host_buffer.buf, n, name, type, result, buffer, buflen, ++ errnop, h_errnop, ttlp, canonp); + +- status = getanswer_r +- (ctx, host_buffer.buf, n, name, type, result, buffer, buflen, +- errnop, h_errnop, map, ttlp, canonp); + if (host_buffer.buf != orig_host_buffer) + free (host_buffer.buf); + return status; +@@ -330,13 +305,8 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result, + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } +- status = NSS_STATUS_NOTFOUND; +- if (res_use_inet6 ()) +- status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer, +- buflen, errnop, h_errnop, NULL, NULL); +- if (status == NSS_STATUS_NOTFOUND) +- status = gethostbyname3_context (ctx, name, AF_INET, result, buffer, +- buflen, errnop, h_errnop, NULL, NULL); ++ status = gethostbyname3_context (ctx, name, AF_INET, result, buffer, ++ buflen, errnop, h_errnop, NULL, NULL); + __resolv_context_put (ctx); + return status; + } +@@ -649,7 +619,7 @@ static enum nss_status + getanswer_r (struct resolv_context *ctx, + const querybuf *answer, int anslen, const char *qname, int qtype, + struct hostent *result, char *buffer, size_t buflen, +- int *errnop, int *h_errnop, int map, int32_t *ttlp, char **canonp) ++ int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) + { + struct host_data + { +@@ -665,7 +635,6 @@ getanswer_r (struct resolv_context *ctx, + char *bp, **ap, **hap; + char tbuf[MAXDNAME]; + u_char packtmp[NS_MAXCDNAME]; +- int have_to_map = 0; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); + buffer += pad; + buflen = buflen > pad ? buflen - pad : 0; +@@ -846,9 +815,7 @@ getanswer_r (struct resolv_context *ctx, + continue; + } + +- if (type == T_A && qtype == T_AAAA && map) +- have_to_map = 1; +- else if (__glibc_unlikely (type != qtype)) ++ if (__glibc_unlikely (type != qtype)) + { + cp += n; + continue; /* XXX - had_error++ ? */ +@@ -945,9 +912,6 @@ getanswer_r (struct resolv_context *ctx, + linebuflen -= n; + } + +- if (have_to_map) +- if (map_v4v6_hostent (result, &bp, &linebuflen)) +- goto too_small; + *h_errnop = NETDB_SUCCESS; + return NSS_STATUS_SUCCESS; + } diff --git a/SOURCES/glibc-upstream-2.34-325.patch b/SOURCES/glibc-upstream-2.34-325.patch new file mode 100644 index 0000000..7a282c5 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-325.patch @@ -0,0 +1,565 @@ +commit 9abc40d9b514fc51cd1a052d32d092a827c6e21a +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + nss_dns: Rewrite getanswer_r to match getanswer_ptr (bug 12154, bug 29305) + + Allocate the pointer arrays only at the end, when their sizes + are known. This addresses bug 29305. + + Skip over invalid names instead of failing lookups. This partially + fixes bug 12154 (for gethostbyname, fixing getaddrinfo requires + different changes). + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit d101d836e7e4bd1d4e4972b0e0bd0a55c9b650fa) + +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index f8dc5a0a7d1eb156..10c21e1e827cde12 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -108,12 +108,19 @@ typedef union querybuf + u_char buf[MAXPACKET]; + } querybuf; + +-static enum nss_status getanswer_r (struct resolv_context *ctx, +- const querybuf *answer, int anslen, +- const char *qname, int qtype, +- struct hostent *result, char *buffer, +- size_t buflen, int *errnop, int *h_errnop, +- int32_t *ttlp, char **canonp); ++/* For historic reasons, pointers to IP addresses are char *, so use a ++ single list type for addresses and host names. */ ++#define DYNARRAY_STRUCT ptrlist ++#define DYNARRAY_ELEMENT char * ++#define DYNARRAY_PREFIX ptrlist_ ++#include ++ ++static enum nss_status getanswer_r (unsigned char *packet, size_t packetlen, ++ uint16_t qtype, struct alloc_buffer *abuf, ++ struct ptrlist *addresses, ++ struct ptrlist *aliases, ++ int *errnop, int *h_errnop, int32_t *ttlp); ++static void addrsort (struct resolv_context *ctx, char **ap, int num); + static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen, + struct alloc_buffer *abuf, + char **hnamep, int *errnop, +@@ -185,12 +192,6 @@ gethostbyname3_context (struct resolv_context *ctx, + char *buffer, size_t buflen, int *errnop, + int *h_errnop, int32_t *ttlp, char **canonp) + { +- union +- { +- querybuf *buf; +- u_char *ptr; +- } host_buffer; +- querybuf *orig_host_buffer; + char tmp[NS_MAXDNAME]; + int size, type, n; + const char *cp; +@@ -224,10 +225,12 @@ gethostbyname3_context (struct resolv_context *ctx, + && (cp = __res_context_hostalias (ctx, name, tmp, sizeof (tmp))) != NULL) + name = cp; + +- host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024); ++ unsigned char dns_packet_buffer[1024]; ++ unsigned char *alt_dns_packet_buffer = dns_packet_buffer; + +- n = __res_context_search (ctx, name, C_IN, type, host_buffer.buf->buf, +- 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); ++ n = __res_context_search (ctx, name, C_IN, type, ++ dns_packet_buffer, sizeof (dns_packet_buffer), ++ &alt_dns_packet_buffer, NULL, NULL, NULL, NULL); + if (n < 0) + { + switch (errno) +@@ -256,12 +259,77 @@ gethostbyname3_context (struct resolv_context *ctx, + __set_errno (olderr); + } + else +- status = getanswer_r +- (ctx, host_buffer.buf, n, name, type, result, buffer, buflen, +- errnop, h_errnop, ttlp, canonp); ++ { ++ struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen); + +- if (host_buffer.buf != orig_host_buffer) +- free (host_buffer.buf); ++ struct ptrlist addresses; ++ ptrlist_init (&addresses); ++ struct ptrlist aliases; ++ ptrlist_init (&aliases); ++ ++ status = getanswer_r (alt_dns_packet_buffer, n, type, ++ &abuf, &addresses, &aliases, ++ errnop, h_errnop, ttlp); ++ if (status == NSS_STATUS_SUCCESS) ++ { ++ if (ptrlist_has_failed (&addresses) ++ || ptrlist_has_failed (&aliases)) ++ { ++ /* malloc failure. Do not retry using the ERANGE protocol. */ ++ *errnop = ENOMEM; ++ *h_errnop = NETDB_INTERNAL; ++ status = NSS_STATUS_UNAVAIL; ++ } ++ ++ /* Reserve the address and alias arrays in the result ++ buffer. Both are NULL-terminated, but the first element ++ of the alias array is stored in h_name, so no extra space ++ for the NULL terminator is needed there. */ ++ result->h_addr_list ++ = alloc_buffer_alloc_array (&abuf, char *, ++ ptrlist_size (&addresses) + 1); ++ result->h_aliases ++ = alloc_buffer_alloc_array (&abuf, char *, ++ ptrlist_size (&aliases)); ++ if (alloc_buffer_has_failed (&abuf)) ++ { ++ /* Retry using the ERANGE protocol. */ ++ *errnop = ERANGE; ++ *h_errnop = NETDB_INTERNAL; ++ status = NSS_STATUS_TRYAGAIN; ++ } ++ else ++ { ++ /* Copy the address list and NULL-terminate it. */ ++ memcpy (result->h_addr_list, ptrlist_begin (&addresses), ++ ptrlist_size (&addresses) * sizeof (char *)); ++ result->h_addr_list[ptrlist_size (&addresses)] = NULL; ++ ++ /* Sort the address list if requested. */ ++ if (type == T_A && __resolv_context_sort_count (ctx) > 0) ++ addrsort (ctx, result->h_addr_list, ptrlist_size (&addresses)); ++ ++ /* Copy the aliases, excluding the last one. */ ++ memcpy (result->h_aliases, ptrlist_begin (&aliases), ++ (ptrlist_size (&aliases) - 1) * sizeof (char *)); ++ result->h_aliases[ptrlist_size (&aliases) - 1] = NULL; ++ ++ /* The last alias goes into h_name. */ ++ assert (ptrlist_size (&aliases) >= 1); ++ result->h_name = ptrlist_end (&aliases)[-1]; ++ ++ /* This is also the canonical name. */ ++ if (canonp != NULL) ++ *canonp = result->h_name; ++ } ++ } ++ ++ ptrlist_free (&aliases); ++ ptrlist_free (&addresses); ++ } ++ ++ if (alt_dns_packet_buffer != dns_packet_buffer) ++ free (alt_dns_packet_buffer); + return status; + } + +@@ -615,314 +683,128 @@ addrsort (struct resolv_context *ctx, char **ap, int num) + break; + } + +-static enum nss_status +-getanswer_r (struct resolv_context *ctx, +- const querybuf *answer, int anslen, const char *qname, int qtype, +- struct hostent *result, char *buffer, size_t buflen, +- int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) ++/* Convert the uncompressed, binary domain name CDNAME into its ++ textual representation and add it to the end of ALIASES, allocating ++ space for a copy of the name from ABUF. Skip adding the name if it ++ is not a valid host name, and return false in that case, otherwise ++ true. */ ++static bool ++getanswer_r_store_alias (const unsigned char *cdname, ++ struct alloc_buffer *abuf, ++ struct ptrlist *aliases) + { +- struct host_data +- { +- char *aliases[MAX_NR_ALIASES]; +- unsigned char host_addr[16]; /* IPv4 or IPv6 */ +- char *h_addr_ptrs[0]; +- } *host_data; +- int linebuflen; +- const HEADER *hp; +- const u_char *end_of_message, *cp; +- int n, ancount, qdcount; +- int haveanswer, had_error; +- char *bp, **ap, **hap; +- char tbuf[MAXDNAME]; +- u_char packtmp[NS_MAXCDNAME]; +- uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); +- buffer += pad; +- buflen = buflen > pad ? buflen - pad : 0; +- if (__glibc_unlikely (buflen < sizeof (struct host_data))) +- { +- /* The buffer is too small. */ +- too_small: +- *errnop = ERANGE; +- *h_errnop = NETDB_INTERNAL; +- return NSS_STATUS_TRYAGAIN; +- } +- host_data = (struct host_data *) buffer; +- linebuflen = buflen - sizeof (struct host_data); +- if (buflen - sizeof (struct host_data) != linebuflen) +- linebuflen = INT_MAX; +- +- result->h_name = NULL; +- end_of_message = answer->buf + anslen; +- +- /* +- * find first satisfactory answer +- */ +- hp = &answer->hdr; +- ancount = ntohs (hp->ancount); +- qdcount = ntohs (hp->qdcount); +- cp = answer->buf + HFIXEDSZ; +- if (__glibc_unlikely (qdcount != 1)) +- { +- *h_errnop = NO_RECOVERY; +- return NSS_STATUS_UNAVAIL; +- } +- if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen) +- goto too_small; +- bp = (char *) &host_data->h_addr_ptrs[ancount + 1]; +- linebuflen -= (ancount + 1) * sizeof (char *); +- +- n = __ns_name_unpack (answer->buf, end_of_message, cp, +- packtmp, sizeof packtmp); +- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) +- { +- if (__glibc_unlikely (errno == EMSGSIZE)) +- goto too_small; +- +- n = -1; +- } ++ /* Filter out domain names that are not host names. */ ++ if (!__res_binary_hnok (cdname)) ++ return false; ++ ++ /* Note: Not NS_MAXCDNAME, so that __ns_name_ntop implicitly checks ++ for length. */ ++ char dname[MAXHOSTNAMELEN + 1]; ++ if (__ns_name_ntop (cdname, dname, sizeof (dname)) < 0) ++ return false; ++ /* Do not report an error on allocation failure, instead store NULL ++ or do nothing. getanswer_r's caller will see NSS_STATUS_SUCCESS ++ and detect the memory allocation failure or buffer space ++ exhaustion, and report it accordingly. */ ++ ptrlist_add (aliases, alloc_buffer_copy_string (abuf, dname)); ++ return true; ++} + +- if (__glibc_unlikely (n < 0)) +- { +- *errnop = errno; +- *h_errnop = NO_RECOVERY; +- return NSS_STATUS_UNAVAIL; +- } +- if (__glibc_unlikely (__libc_res_hnok (bp) == 0)) ++static enum nss_status __attribute__ ((noinline)) ++getanswer_r (unsigned char *packet, size_t packetlen, uint16_t qtype, ++ struct alloc_buffer *abuf, ++ struct ptrlist *addresses, struct ptrlist *aliases, ++ int *errnop, int *h_errnop, int32_t *ttlp) ++{ ++ struct ns_rr_cursor c; ++ if (!__ns_rr_cursor_init (&c, packet, packetlen)) + { +- errno = EBADMSG; +- *errnop = EBADMSG; ++ /* This should not happen because __res_context_query already ++ perfroms response validation. */ + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + } +- cp += n + QFIXEDSZ; + +- if (qtype == T_A || qtype == T_AAAA) ++ /* Treat the QNAME just like an alias. Error out if it is not a ++ valid host name. */ ++ if (ns_rr_cursor_rcode (&c) == NXDOMAIN ++ || !getanswer_r_store_alias (ns_rr_cursor_qname (&c), abuf, aliases)) + { +- /* res_send() has already verified that the query name is the +- * same as the one we sent; this just gets the expanded name +- * (i.e., with the succeeding search-domain tacked on). +- */ +- n = strlen (bp) + 1; /* for the \0 */ +- if (n >= MAXHOSTNAMELEN) +- { +- *h_errnop = NO_RECOVERY; +- *errnop = ENOENT; +- return NSS_STATUS_TRYAGAIN; +- } +- result->h_name = bp; +- bp += n; +- linebuflen -= n; +- if (linebuflen < 0) +- goto too_small; +- /* The qname can be abbreviated, but h_name is now absolute. */ +- qname = result->h_name; ++ if (ttlp != NULL) ++ /* No negative caching. */ ++ *ttlp = 0; ++ *h_errnop = HOST_NOT_FOUND; ++ *errnop = ENOENT; ++ return NSS_STATUS_NOTFOUND; + } + +- ap = host_data->aliases; +- *ap = NULL; +- result->h_aliases = host_data->aliases; +- hap = host_data->h_addr_ptrs; +- *hap = NULL; +- result->h_addr_list = host_data->h_addr_ptrs; +- haveanswer = 0; +- had_error = 0; ++ int ancount = ns_rr_cursor_ancount (&c); ++ const unsigned char *expected_name = ns_rr_cursor_qname (&c); ++ /* expected_name may be updated to point into this buffer. */ ++ unsigned char name_buffer[NS_MAXCDNAME]; + +- while (ancount-- > 0 && cp < end_of_message && had_error == 0) ++ for (; ancount > 0; --ancount) + { +- int type, class; +- +- n = __ns_name_unpack (answer->buf, end_of_message, cp, +- packtmp, sizeof packtmp); +- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) +- { +- if (__glibc_unlikely (errno == EMSGSIZE)) +- goto too_small; +- +- n = -1; +- } +- +- if (__glibc_unlikely (n < 0 || __libc_res_hnok (bp) == 0)) +- { +- ++had_error; +- continue; +- } +- cp += n; /* name */ +- +- if (__glibc_unlikely (cp + 10 > end_of_message)) ++ struct ns_rr_wire rr; ++ if (!__ns_rr_cursor_next (&c, &rr)) + { +- ++had_error; +- continue; ++ *h_errnop = NO_RECOVERY; ++ return NSS_STATUS_UNAVAIL; + } + +- NS_GET16 (type, cp); +- NS_GET16 (class, cp); +- int32_t ttl; +- NS_GET32 (ttl, cp); +- NS_GET16 (n, cp); /* RDATA length. */ +- +- if (end_of_message - cp < n) +- { +- /* RDATA extends beyond the end of the packet. */ +- ++had_error; +- continue; +- } ++ /* Skip over records with the wrong class. */ ++ if (rr.rclass != C_IN) ++ continue; + +- if (__glibc_unlikely (class != C_IN)) +- { +- /* XXX - debug? syslog? */ +- cp += n; +- continue; /* XXX - had_error++ ? */ +- } ++ /* Update TTL for recognized record types. */ ++ if ((rr.rtype == T_CNAME || rr.rtype == qtype) ++ && ttlp != NULL && *ttlp > rr.ttl) ++ *ttlp = rr.ttl; + +- if (type == T_CNAME) ++ if (rr.rtype == T_CNAME) + { +- /* A CNAME could also have a TTL entry. */ +- if (ttlp != NULL && ttl < *ttlp) +- *ttlp = ttl; +- +- if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1]) +- continue; +- n = __libc_dn_expand (answer->buf, end_of_message, cp, +- tbuf, sizeof tbuf); +- if (__glibc_unlikely (n < 0 || __libc_res_hnok (tbuf) == 0)) +- { +- ++had_error; +- continue; +- } +- cp += n; +- /* Store alias. */ +- *ap++ = bp; +- n = strlen (bp) + 1; /* For the \0. */ +- if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) +- { +- ++had_error; +- continue; +- } +- bp += n; +- linebuflen -= n; +- /* Get canonical name. */ +- n = strlen (tbuf) + 1; /* For the \0. */ +- if (__glibc_unlikely (n > linebuflen)) +- goto too_small; +- if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) ++ /* NB: No check for owner name match, based on historic ++ precedent. Record the CNAME target as the new expected ++ name. */ ++ int n = __ns_name_unpack (c.begin, c.end, rr.rdata, ++ name_buffer, sizeof (name_buffer)); ++ if (n < 0) + { +- ++had_error; +- continue; ++ *h_errnop = NO_RECOVERY; ++ return NSS_STATUS_UNAVAIL; + } +- result->h_name = bp; +- bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */ +- linebuflen -= n; +- continue; ++ /* And store the new name as an alias. */ ++ getanswer_r_store_alias (name_buffer, abuf, aliases); ++ expected_name = name_buffer; + } +- +- if (__glibc_unlikely (type != qtype)) ++ else if (rr.rtype == qtype ++ && __ns_samebinaryname (rr.rname, expected_name) ++ && rr.rdlength == rrtype_to_rdata_length (qtype)) + { +- cp += n; +- continue; /* XXX - had_error++ ? */ ++ /* Make a copy of the address and store it. Increase the ++ alignment to 4, in case there are applications out there ++ that expect at least this level of address alignment. */ ++ ptrlist_add (addresses, (char *) alloc_buffer_next (abuf, uint32_t)); ++ alloc_buffer_copy_bytes (abuf, rr.rdata, rr.rdlength); + } +- +- switch (type) +- { +- case T_A: +- case T_AAAA: +- if (__glibc_unlikely (__strcasecmp (result->h_name, bp) != 0)) +- { +- cp += n; +- continue; /* XXX - had_error++ ? */ +- } +- +- /* Stop parsing at a record whose length is incorrect. */ +- if (n != rrtype_to_rdata_length (type)) +- { +- ++had_error; +- break; +- } +- +- /* Skip records of the wrong type. */ +- if (n != result->h_length) +- { +- cp += n; +- continue; +- } +- if (!haveanswer) +- { +- int nn; +- +- /* We compose a single hostent out of the entire chain of +- entries, so the TTL of the hostent is essentially the lowest +- TTL in the chain. */ +- if (ttlp != NULL && ttl < *ttlp) +- *ttlp = ttl; +- if (canonp != NULL) +- *canonp = bp; +- result->h_name = bp; +- nn = strlen (bp) + 1; /* for the \0 */ +- bp += nn; +- linebuflen -= nn; +- } +- +- /* Provide sufficient alignment for both address +- families. */ +- enum { align = 4 }; +- _Static_assert ((align % __alignof__ (struct in_addr)) == 0, +- "struct in_addr alignment"); +- _Static_assert ((align % __alignof__ (struct in6_addr)) == 0, +- "struct in6_addr alignment"); +- { +- char *new_bp = PTR_ALIGN_UP (bp, align); +- linebuflen -= new_bp - bp; +- bp = new_bp; +- } +- +- if (__glibc_unlikely (n > linebuflen)) +- goto too_small; +- bp = __mempcpy (*hap++ = bp, cp, n); +- cp += n; +- linebuflen -= n; +- break; +- default: +- abort (); +- } +- if (had_error == 0) +- ++haveanswer; + } + +- if (haveanswer > 0) ++ if (ptrlist_size (addresses) == 0) + { +- *ap = NULL; +- *hap = NULL; +- /* +- * Note: we sort even if host can take only one address +- * in its return structures - should give it the "best" +- * address in that case, not some random one +- */ +- if (haveanswer > 1 && qtype == T_A +- && __resolv_context_sort_count (ctx) > 0) +- addrsort (ctx, host_data->h_addr_ptrs, haveanswer); +- +- if (result->h_name == NULL) +- { +- n = strlen (qname) + 1; /* For the \0. */ +- if (n > linebuflen) +- goto too_small; +- if (n >= MAXHOSTNAMELEN) +- goto no_recovery; +- result->h_name = bp; +- bp = __mempcpy (bp, qname, n); /* Cannot overflow. */ +- linebuflen -= n; +- } ++ /* No address record found. */ ++ if (ttlp != NULL) ++ /* No caching of negative responses. */ ++ *ttlp = 0; + ++ *h_errnop = NO_RECOVERY; ++ *errnop = ENOENT; ++ return NSS_STATUS_TRYAGAIN; ++ } ++ else ++ { + *h_errnop = NETDB_SUCCESS; + return NSS_STATUS_SUCCESS; + } +- no_recovery: +- *h_errnop = NO_RECOVERY; +- *errnop = ENOENT; +- /* Special case here: if the resolver sent a result but it only +- contains a CNAME while we are looking for a T_A or T_AAAA record, +- we fail with NOTFOUND instead of TRYAGAIN. */ +- return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases +- ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN); + } + + static enum nss_status diff --git a/SOURCES/glibc-upstream-2.34-326.patch b/SOURCES/glibc-upstream-2.34-326.patch new file mode 100644 index 0000000..3784a3e --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-326.patch @@ -0,0 +1,51 @@ +commit c36e7cca3571b0c92b09409c1df86a142596c210 +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + nss_dns: In gaih_getanswer_slice, skip strange aliases (bug 12154) + + If the name is not a host name, skip adding it to the result, instead + of reporting query failure. This fixes bug 12154 for getaddrinfo. + + This commit still keeps the old parsing code, and only adjusts when + a host name is copied. + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 32b599ac8c21c4c332cc3900a792a1395bca79c7) + +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index 10c21e1e827cde12..1cb3be71f04d98eb 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -971,12 +971,12 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, + + n = -1; + } +- if (__glibc_unlikely (n < 0 || __libc_res_hnok (buffer) == 0)) ++ if (__glibc_unlikely (n < 0)) + { + ++had_error; + continue; + } +- if (*firstp && canon == NULL) ++ if (*firstp && canon == NULL && __libc_res_hnok (buffer)) + { + h_name = buffer; + buffer += h_namelen; +@@ -1022,14 +1022,14 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, + + n = __libc_dn_expand (answer->buf, end_of_message, cp, + tbuf, sizeof tbuf); +- if (__glibc_unlikely (n < 0 || __libc_res_hnok (tbuf) == 0)) ++ if (__glibc_unlikely (n < 0)) + { + ++had_error; + continue; + } + cp += n; + +- if (*firstp) ++ if (*firstp && __libc_res_hnok (tbuf)) + { + /* Reclaim buffer space. */ + if (h_name + h_namelen == buffer) diff --git a/SOURCES/glibc-upstream-2.34-327.patch b/SOURCES/glibc-upstream-2.34-327.patch new file mode 100644 index 0000000..8019ca3 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-327.patch @@ -0,0 +1,449 @@ +commit 480c820493add16e8dda6f3189d834223e1f4f39 +Author: Florian Weimer +Date: Tue Aug 30 10:02:49 2022 +0200 + + resolv: Add new tst-resolv-invalid-cname + + This test checks resolution through CNAME chains that do not contain + host names (bug 12154). + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 9caf782276ecea4bc86fc94fbb52779736f3106d) + +Conflicts: + resolv/Makefile + (usual test differences) + +diff --git a/resolv/Makefile b/resolv/Makefile +index fded244d61068060..ea1518ec2da860c1 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -99,6 +99,7 @@ tests += \ + tst-resolv-binary \ + tst-resolv-byaddr \ + tst-resolv-edns \ ++ tst-resolv-invalid-cname \ + tst-resolv-network \ + tst-resolv-noaaaa \ + tst-resolv-nondecimal \ +@@ -279,6 +280,8 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \ + $(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \ + $(shared-thread-library) + $(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library) ++$(objpfx)tst-resolv-invalid-cname: $(objpfx)libresolv.so \ ++ $(shared-thread-library) + $(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library) +diff --git a/resolv/tst-resolv-invalid-cname.c b/resolv/tst-resolv-invalid-cname.c +new file mode 100644 +index 0000000000000000..ae2d4419b1978c02 +--- /dev/null ++++ b/resolv/tst-resolv-invalid-cname.c +@@ -0,0 +1,406 @@ ++/* Test handling of CNAMEs with non-host domain names (bug 12154). ++ 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Query strings describe the CNAME chain in the response. They have ++ the format "bitsBITS.countCOUNT.example.", where BITS and COUNT are ++ replaced by unsigned decimal numbers. COUNT is the number of CNAME ++ records in the response. BITS has two bits for each CNAME record, ++ describing a special prefix that is added to that CNAME. ++ ++ 0: No special leading label. ++ 1: Starting with "*.". ++ 2: Starting with "-x.". ++ 3: Starting with "star.*.". ++ ++ The first CNAME in the response using the two least significant ++ bits. ++ ++ For PTR queries, the QNAME format is different, it is either ++ COUNT.BITS.168.192.in-addr.arpa. (with BITS and COUNT still ++ decimal), or: ++ ++COUNT.BITS0.BITS1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. ++ ++ where BITS and COUNT are hexadecimal. */ ++ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ TEST_COMPARE (qclass, C_IN); ++ ++ /* The only other query type besides A is PTR. */ ++ if (qtype != T_A && qtype != T_AAAA) ++ TEST_COMPARE (qtype, T_PTR); ++ ++ unsigned int bits, bits1, count; ++ char *tail = NULL; ++ if (sscanf (qname, "bits%u.count%u.%ms", &bits, &count, &tail) == 3) ++ TEST_COMPARE_STRING (tail, "example"); ++ else if (strstr (qname, "in-addr.arpa") != NULL ++ && sscanf (qname, "%u.%u.%ms", &bits, &count, &tail) == 3) ++ TEST_COMPARE_STRING (tail, "168.192.in-addr.arpa"); ++ else if (sscanf (qname, "%x.%x.%x.%ms", &bits, &bits1, &count, &tail) == 4) ++ { ++ TEST_COMPARE_STRING (tail, "\ ++0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa"); ++ bits |= bits1 << 4; ++ } ++ else ++ FAIL_EXIT1 ("invalid QNAME: %s\n", qname); ++ free (tail); ++ ++ struct resolv_response_flags flags = {}; ++ resolv_response_init (b, flags); ++ resolv_response_add_question (b, qname, qclass, qtype); ++ resolv_response_section (b, ns_s_an); ++ ++ /* Provide the requested number of CNAME records. */ ++ char *previous_name = (char *) qname; ++ unsigned int original_bits = bits; ++ for (int unique = 0; unique < count; ++unique) ++ { ++ resolv_response_open_record (b, previous_name, qclass, T_CNAME, 60); ++ ++ static const char bits_to_prefix[4][8] = { "", "*.", "-x.", "star.*." }; ++ char *new_name = xasprintf ("%sunique%d.example", ++ bits_to_prefix[bits & 3], unique); ++ bits >>= 2; ++ resolv_response_add_name (b, new_name); ++ resolv_response_close_record (b); ++ ++ if (previous_name != qname) ++ free (previous_name); ++ previous_name = new_name; ++ } ++ ++ /* Actual answer record. */ ++ resolv_response_open_record (b, previous_name, qclass, qtype, 60); ++ switch (qtype) ++ { ++ case T_A: ++ { ++ char ipv4[4] = {192, 168, count, original_bits}; ++ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); ++ } ++ break; ++ case T_AAAA: ++ { ++ char ipv6[16] = ++ { ++ 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ count, original_bits ++ }; ++ resolv_response_add_data (b, &ipv6, sizeof (ipv6)); ++ } ++ break; ++ ++ case T_PTR: ++ { ++ char *name = xasprintf ("bits%u.count%u.example", ++ original_bits, count); ++ resolv_response_add_name (b, name); ++ free (name); ++ } ++ break; ++ } ++ resolv_response_close_record (b); ++ ++ if (previous_name != qname) ++ free (previous_name); ++} ++ ++/* Controls which name resolution function is invoked. */ ++enum test_mode ++ { ++ byname, /* gethostbyname. */ ++ byname2, /* gethostbyname2. */ ++ gai, /* getaddrinfo without AI_CANONNAME. */ ++ gai_canon, /* getaddrinfo with AI_CANONNAME. */ ++ ++ test_mode_num /* Number of enum values. */ ++ }; ++ ++static const char * ++test_mode_to_string (enum test_mode mode) ++{ ++ switch (mode) ++ { ++ case byname: ++ return "byname"; ++ case byname2: ++ return "byname2"; ++ case gai: ++ return "gai"; ++ case gai_canon: ++ return "gai_canon"; ++ case test_mode_num: ++ /* Report error below. */ ++ } ++ FAIL_EXIT1 ("invalid test_mode: %d", mode); ++} ++ ++/* Append the name and aliases to OUT. */ ++static void ++append_names (FILE *out, const char *qname, int bits, int count, ++ enum test_mode mode) ++{ ++ /* Largest valid index which has a corresponding zero in bits ++ (meaning a syntactically valid CNAME). */ ++ int last_valid_cname = -1; ++ ++ for (int i = 0; i < count; ++i) ++ if ((bits & (3 << (i * 2))) == 0) ++ last_valid_cname = i; ++ ++ if (mode != gai) ++ { ++ const char *label; ++ if (mode == gai_canon) ++ label = "canonname"; ++ else ++ label = "name"; ++ if (last_valid_cname >= 0) ++ fprintf (out, "%s: unique%d.example\n", label, last_valid_cname); ++ else ++ fprintf (out, "%s: %s\n", label, qname); ++ } ++ ++ if (mode == byname || mode == byname2) ++ { ++ if (last_valid_cname >= 0) ++ fprintf (out, "alias: %s\n", qname); ++ for (int i = 0; i < count; ++i) ++ { ++ if ((bits & (3 << (i * 2))) == 0 && i != last_valid_cname) ++ fprintf (out, "alias: unique%d.example\n", i); ++ } ++ } ++} ++ ++/* Append the address information to OUT. */ ++static void ++append_addresses (FILE *out, int af, int bits, int count, enum test_mode mode) ++{ ++ int last = count * 256 + bits; ++ if (mode == gai || mode == gai_canon) ++ { ++ if (af == AF_INET || af == AF_UNSPEC) ++ fprintf (out, "address: STREAM/TCP 192.168.%d.%d 80\n", count, bits); ++ if (af == AF_INET6 || af == AF_UNSPEC) ++ { ++ if (last == 0) ++ fprintf (out, "address: STREAM/TCP 2001:db8:: 80\n"); ++ else ++ fprintf (out, "address: STREAM/TCP 2001:db8::%x 80\n", last); ++ } ++ } ++ else ++ { ++ TEST_VERIFY (af != AF_UNSPEC); ++ if (af == AF_INET) ++ fprintf (out, "address: 192.168.%d.%d\n", count, bits); ++ if (af == AF_INET6) ++ { ++ if (last == 0) ++ fprintf (out, "address: 2001:db8::\n"); ++ else ++ fprintf (out, "address: 2001:db8::%x\n", last); ++ } ++ } ++} ++ ++/* Perform one test using a forward lookup. */ ++static void ++check_forward (int af, int bits, int count, enum test_mode mode) ++{ ++ char *qname = xasprintf ("bits%d.count%d.example", bits, count); ++ char *label = xasprintf ("af=%d bits=%d count=%d mode=%s qname=%s", ++ af, bits, count, test_mode_to_string (mode), qname); ++ ++ struct xmemstream expected; ++ xopen_memstream (&expected); ++ if (mode == gai_canon) ++ fprintf (expected.out, "flags: AI_CANONNAME\n"); ++ append_names (expected.out, qname, bits, count, mode); ++ append_addresses (expected.out, af, bits, count, mode); ++ xfclose_memstream (&expected); ++ ++ if (mode == gai || mode == gai_canon) ++ { ++ struct addrinfo *ai; ++ struct addrinfo hints = ++ { ++ .ai_family = af, ++ .ai_socktype = SOCK_STREAM, ++ }; ++ if (mode == gai_canon) ++ hints.ai_flags |= AI_CANONNAME; ++ int ret = getaddrinfo (qname, "80", &hints, &ai); ++ check_addrinfo (label, ai, ret, expected.buffer); ++ if (ret == 0) ++ freeaddrinfo (ai); ++ } ++ else ++ { ++ struct hostent *e; ++ if (mode == gai) ++ { ++ TEST_COMPARE (af, AF_INET); ++ e = gethostbyname (qname); ++ } ++ else ++ { ++ if (af != AF_INET) ++ TEST_COMPARE (af, AF_INET6); ++ e = gethostbyname2 (qname, af); ++ } ++ check_hostent (label, e, expected.buffer); ++ } ++ ++ free (expected.buffer); ++ free (label); ++ free (qname); ++} ++ ++/* Perform one check using a reverse lookup. */ ++ ++static void ++check_reverse (int af, int bits, int count) ++{ ++ TEST_VERIFY (af == AF_INET || af == AF_INET6); ++ ++ char *label = xasprintf ("af=%d bits=%d count=%d", af, bits, count); ++ char *fqdn = xasprintf ("bits%d.count%d.example", bits, count); ++ ++ struct xmemstream expected; ++ xopen_memstream (&expected); ++ fprintf (expected.out, "name: %s\n", fqdn); ++ append_addresses (expected.out, af, bits, count, byname); ++ xfclose_memstream (&expected); ++ ++ char addr[16] = { 0 }; ++ socklen_t addrlen; ++ if (af == AF_INET) ++ { ++ addr[0] = 192; ++ addr[1] = 168; ++ addr[2] = count; ++ addr[3] = bits; ++ addrlen = 4; ++ } ++ else ++ { ++ addr[0] = 0x20; ++ addr[1] = 0x01; ++ addr[2] = 0x0d; ++ addr[3] = 0xb8; ++ addr[14] = count; ++ addr[15] = bits; ++ addrlen = 16; ++ } ++ ++ struct hostent *e = gethostbyaddr (addr, addrlen, af); ++ check_hostent (label, e, expected.buffer); ++ ++ /* getnameinfo check is different. There is no generic check_* ++ function for it. */ ++ { ++ struct sockaddr_in sin = { }; ++ struct sockaddr_in6 sin6 = { }; ++ void *sa; ++ socklen_t salen; ++ if (af == AF_INET) ++ { ++ sin.sin_family = AF_INET; ++ memcpy (&sin.sin_addr, addr, addrlen); ++ sin.sin_port = htons (80); ++ sa = &sin; ++ salen = sizeof (sin); ++ } ++ else ++ { ++ sin6.sin6_family = AF_INET6; ++ memcpy (&sin6.sin6_addr, addr, addrlen); ++ sin6.sin6_port = htons (80); ++ sa = &sin6; ++ salen = sizeof (sin6); ++ } ++ ++ char host[64]; ++ char service[64]; ++ int ret = getnameinfo (sa, salen, host, ++ sizeof (host), service, sizeof (service), ++ NI_NAMEREQD | NI_NUMERICSERV); ++ TEST_COMPARE (ret, 0); ++ TEST_COMPARE_STRING (host, fqdn); ++ TEST_COMPARE_STRING (service, "80"); ++ } ++ ++ free (expected.buffer); ++ free (fqdn); ++ free (label); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_test *obj = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response ++ }); ++ ++ for (int count = 0; count <= 3; ++count) ++ for (int bits = 0; bits <= 1 << (count * 2); ++bits) ++ { ++ if (count > 0 && bits == count) ++ /* The last bits value is only checked if count == 0. */ ++ continue; ++ ++ for (enum test_mode mode = 0; mode < test_mode_num; ++mode) ++ { ++ check_forward (AF_INET, bits, count, mode); ++ if (mode != byname) ++ check_forward (AF_INET6, bits, count, mode); ++ if (mode == gai || mode == gai_canon) ++ check_forward (AF_UNSPEC, bits, count, mode); ++ } ++ ++ check_reverse (AF_INET, bits, count); ++ check_reverse (AF_INET6, bits, count); ++ } ++ ++ resolv_test_end (obj); ++ ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-upstream-2.34-329.patch b/SOURCES/glibc-upstream-2.34-329.patch new file mode 100644 index 0000000..d718c5f --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-329.patch @@ -0,0 +1,31 @@ +commit 044755e2faeeca13bb77b2e9e638a45e6e90a5fa +Author: Florian Weimer +Date: Tue Aug 30 13:30:03 2022 +0200 + + resolv: Fix building tst-resolv-invalid-cname for earlier C standards + + This fixes this compiler error: + + tst-resolv-invalid-cname.c: In function ‘test_mode_to_string’: + tst-resolv-invalid-cname.c:164:10: error: label at end of compound statement + case test_mode_num: + ^~~~~~~~~~~~~ + + Fixes commit 9caf782276ecea4bc86fc94fbb52779736f3106d + ("resolv: Add new tst-resolv-invalid-cname"). + + (cherry picked from commit d09aa4a17229bcaa2ec7642006b12612498582e7) + +diff --git a/resolv/tst-resolv-invalid-cname.c b/resolv/tst-resolv-invalid-cname.c +index ae2d4419b1978c02..63dac90e02d6cbc7 100644 +--- a/resolv/tst-resolv-invalid-cname.c ++++ b/resolv/tst-resolv-invalid-cname.c +@@ -162,7 +162,7 @@ test_mode_to_string (enum test_mode mode) + case gai_canon: + return "gai_canon"; + case test_mode_num: +- /* Report error below. */ ++ break; /* Report error below. */ + } + FAIL_EXIT1 ("invalid test_mode: %d", mode); + } diff --git a/SOURCES/glibc-upstream-2.34-330.patch b/SOURCES/glibc-upstream-2.34-330.patch new file mode 100644 index 0000000..4fb22ef --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-330.patch @@ -0,0 +1,33 @@ +commit a2e259014f8a0e5f3ff938314f3087b74255804d +Author: H.J. Lu +Date: Thu Nov 11 06:31:51 2021 -0800 + + Avoid extra load with CAS in __pthread_mutex_lock_full [BZ #28537] + + Replace boolean CAS with value CAS to avoid the extra load. + + Reviewed-by: Szabolcs Nagy + (cherry picked from commit 0b82747dc48d5bf0871bdc6da8cb6eec1256355f) + +diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c +index da624f322d06d0ee..a04e0158451c8fff 100644 +--- a/nptl/pthread_mutex_lock.c ++++ b/nptl/pthread_mutex_lock.c +@@ -298,12 +298,12 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) + meantime. */ + if ((oldval & FUTEX_WAITERS) == 0) + { +- if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock, +- oldval | FUTEX_WAITERS, +- oldval) +- != 0) ++ int val; ++ if ((val = atomic_compare_and_exchange_val_acq ++ (&mutex->__data.__lock, oldval | FUTEX_WAITERS, ++ oldval)) != oldval) + { +- oldval = mutex->__data.__lock; ++ oldval = val; + continue; + } + oldval |= FUTEX_WAITERS; diff --git a/SOURCES/glibc-upstream-2.34-331.patch b/SOURCES/glibc-upstream-2.34-331.patch new file mode 100644 index 0000000..59c359f --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-331.patch @@ -0,0 +1,33 @@ +commit ed8300c054cae4aeb0bbfa043f5fccc91a4adbf5 +Author: H.J. Lu +Date: Thu Nov 11 06:54:01 2021 -0800 + + Avoid extra load with CAS in __pthread_mutex_clocklock_common [BZ #28537] + + Replace boolean CAS with value CAS to avoid the extra load. + + Reviewed-by: Szabolcs Nagy + (cherry picked from commit 49302b8fdf9103b6fc0a398678668a22fa19574c) + +diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c +index 11ad7005d07afc6e..90cede9446e33fcf 100644 +--- a/nptl/pthread_mutex_timedlock.c ++++ b/nptl/pthread_mutex_timedlock.c +@@ -234,12 +234,12 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex, + meantime. */ + if ((oldval & FUTEX_WAITERS) == 0) + { +- if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock, +- oldval | FUTEX_WAITERS, +- oldval) +- != 0) ++ int val; ++ if ((val = atomic_compare_and_exchange_val_acq ++ (&mutex->__data.__lock, oldval | FUTEX_WAITERS, ++ oldval)) != oldval) + { +- oldval = mutex->__data.__lock; ++ oldval = val; + continue; + } + oldval |= FUTEX_WAITERS; diff --git a/SOURCES/glibc-upstream-2.34-332.patch b/SOURCES/glibc-upstream-2.34-332.patch new file mode 100644 index 0000000..2a8d15a --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-332.patch @@ -0,0 +1,46 @@ +commit a6b81f605dfba8650ea1f80122f41eb8e6c73dc7 +Author: H.J. Lu +Date: Tue Nov 2 18:33:07 2021 -0700 + + Add LLL_MUTEX_READ_LOCK [BZ #28537] + + CAS instruction is expensive. From the x86 CPU's point of view, getting + a cache line for writing is more expensive than reading. See Appendix + A.2 Spinlock in: + + https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/xeon-lock-scaling-analysis-paper.pdf + + The full compare and swap will grab the cache line exclusive and cause + excessive cache line bouncing. + + Add LLL_MUTEX_READ_LOCK to do an atomic load and skip CAS in spinlock + loop if compare may fail to reduce cache line bouncing on contended locks. + + Reviewed-by: Szabolcs Nagy + (cherry picked from commit d672a98a1af106bd68deb15576710cd61363f7a6) + +diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c +index a04e0158451c8fff..9f40928cc6b9a067 100644 +--- a/nptl/pthread_mutex_lock.c ++++ b/nptl/pthread_mutex_lock.c +@@ -65,6 +65,11 @@ lll_mutex_lock_optimized (pthread_mutex_t *mutex) + # define PTHREAD_MUTEX_VERSIONS 1 + #endif + ++#ifndef LLL_MUTEX_READ_LOCK ++# define LLL_MUTEX_READ_LOCK(mutex) \ ++ atomic_load_relaxed (&(mutex)->__data.__lock) ++#endif ++ + static int __pthread_mutex_lock_full (pthread_mutex_t *mutex) + __attribute_noinline__; + +@@ -142,6 +147,8 @@ PTHREAD_MUTEX_LOCK (pthread_mutex_t *mutex) + break; + } + atomic_spin_nop (); ++ if (LLL_MUTEX_READ_LOCK (mutex) != 0) ++ continue; + } + while (LLL_MUTEX_TRYLOCK (mutex) != 0); + diff --git a/SOURCES/glibc-upstream-2.34-333.patch b/SOURCES/glibc-upstream-2.34-333.patch new file mode 100644 index 0000000..71f9e2a --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-333.patch @@ -0,0 +1,66 @@ +commit 6bcfbee7277e4faa4b693bd965931f0d1883005d +Author: H.J. Lu +Date: Fri Nov 12 11:47:42 2021 -0800 + + Move assignment out of the CAS condition + + Update + + commit 49302b8fdf9103b6fc0a398678668a22fa19574c + Author: H.J. Lu + Date: Thu Nov 11 06:54:01 2021 -0800 + + Avoid extra load with CAS in __pthread_mutex_clocklock_common [BZ #28537] + + Replace boolean CAS with value CAS to avoid the extra load. + + and + + commit 0b82747dc48d5bf0871bdc6da8cb6eec1256355f + Author: H.J. Lu + Date: Thu Nov 11 06:31:51 2021 -0800 + + Avoid extra load with CAS in __pthread_mutex_lock_full [BZ #28537] + + Replace boolean CAS with value CAS to avoid the extra load. + + by moving assignment out of the CAS condition. + + (cherry picked from commit 120ac6d238825452e8024e2f627da33b2508dfd3) + +diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c +index 9f40928cc6b9a067..49901ffa0a96d659 100644 +--- a/nptl/pthread_mutex_lock.c ++++ b/nptl/pthread_mutex_lock.c +@@ -305,10 +305,9 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) + meantime. */ + if ((oldval & FUTEX_WAITERS) == 0) + { +- int val; +- if ((val = atomic_compare_and_exchange_val_acq +- (&mutex->__data.__lock, oldval | FUTEX_WAITERS, +- oldval)) != oldval) ++ int val = atomic_compare_and_exchange_val_acq ++ (&mutex->__data.__lock, oldval | FUTEX_WAITERS, oldval); ++ if (val != oldval) + { + oldval = val; + continue; +diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c +index 90cede9446e33fcf..2e5506db06ccb1ec 100644 +--- a/nptl/pthread_mutex_timedlock.c ++++ b/nptl/pthread_mutex_timedlock.c +@@ -234,10 +234,9 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex, + meantime. */ + if ((oldval & FUTEX_WAITERS) == 0) + { +- int val; +- if ((val = atomic_compare_and_exchange_val_acq +- (&mutex->__data.__lock, oldval | FUTEX_WAITERS, +- oldval)) != oldval) ++ int val = atomic_compare_and_exchange_val_acq ++ (&mutex->__data.__lock, oldval | FUTEX_WAITERS, oldval); ++ if (val != oldval) + { + oldval = val; + continue; diff --git a/SOURCES/glibc-upstream-2.34-334.patch b/SOURCES/glibc-upstream-2.34-334.patch new file mode 100644 index 0000000..1138256 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-334.patch @@ -0,0 +1,38 @@ +commit 43760d33d78f9ea8c8af942b570112ee801b99df +Author: Jangwoong Kim <6812skiii@gmail.com> +Date: Tue Dec 14 21:30:51 2021 +0900 + + nptl: Effectively skip CAS in spinlock loop + + The commit: + "Add LLL_MUTEX_READ_LOCK [BZ #28537]" + SHA1: d672a98a1af106bd68deb15576710cd61363f7a6 + + introduced LLL_MUTEX_READ_LOCK, to skip CAS in spinlock loop + if atomic load fails. But, "continue" inside of do-while loop + does not skip the evaluation of escape expression, thus CAS + is not skipped. + + Replace do-while with while and skip LLL_MUTEX_TRYLOCK if + LLL_MUTEX_READ_LOCK fails. + + Reviewed-by: H.J. Lu + (cherry picked from commit 6b8dbbd03ac88f169b65b5c7d7278576a11d2e44) + +diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c +index 49901ffa0a96d659..bbe754a272b97d91 100644 +--- a/nptl/pthread_mutex_lock.c ++++ b/nptl/pthread_mutex_lock.c +@@ -147,10 +147,9 @@ PTHREAD_MUTEX_LOCK (pthread_mutex_t *mutex) + break; + } + atomic_spin_nop (); +- if (LLL_MUTEX_READ_LOCK (mutex) != 0) +- continue; + } +- while (LLL_MUTEX_TRYLOCK (mutex) != 0); ++ while (LLL_MUTEX_READ_LOCK (mutex) != 0 ++ || LLL_MUTEX_TRYLOCK (mutex) != 0); + + mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8; + } diff --git a/SOURCES/glibc-upstream-2.34-335.patch b/SOURCES/glibc-upstream-2.34-335.patch new file mode 100644 index 0000000..fdf1241 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-335.patch @@ -0,0 +1,68 @@ +commit 04efdcfac405723c23b25d124817bcfc1697e2d8 +Author: Noah Goldstein +Date: Wed Apr 27 15:13:02 2022 -0500 + + sysdeps: Add 'get_fast_jitter' interace in fast-jitter.h + + 'get_fast_jitter' is meant to be used purely for performance + purposes. In all cases it's used it should be acceptable to get no + randomness (see default case). An example use case is in setting + jitter for retries between threads at a lock. There is a + performance benefit to having jitter, but only if the jitter can + be generated very quickly and ultimately there is no serious issue + if no jitter is generated. + + The implementation generally uses 'HP_TIMING_NOW' iff it is + inlined (avoid any potential syscall paths). + Reviewed-by: H.J. Lu + + (cherry picked from commit 911c63a51c690dd1a97dfc587097277029baf00f) + +diff --git a/sysdeps/generic/fast-jitter.h b/sysdeps/generic/fast-jitter.h +new file mode 100644 +index 0000000000000000..4dd53e3475c3dfe6 +--- /dev/null ++++ b/sysdeps/generic/fast-jitter.h +@@ -0,0 +1,42 @@ ++/* Fallback for fast jitter just return 0. ++ Copyright (C) 2019-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 ++ . */ ++ ++#ifndef _FAST_JITTER_H ++# define _FAST_JITTER_H ++ ++# include ++# include ++ ++/* Baseline just return 0. We could create jitter using a clock or ++ 'random_bits' but that may imply a syscall and the goal of ++ 'get_fast_jitter' is minimal overhead "randomness" when such ++ randomness helps performance. Adding high overhead the function ++ defeats the purpose. */ ++static inline uint32_t ++get_fast_jitter (void) ++{ ++# if HP_TIMING_INLINE ++ hp_timing_t jitter; ++ HP_TIMING_NOW (jitter); ++ return (uint32_t) jitter; ++# else ++ return 0; ++# endif ++} ++ ++#endif diff --git a/SOURCES/glibc-upstream-2.34-336.patch b/SOURCES/glibc-upstream-2.34-336.patch new file mode 100644 index 0000000..94b39f2 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-336.patch @@ -0,0 +1,209 @@ +commit ea69248445fb9b80da02ee0c7261cba4b1a5532e +Author: Wangyang Guo +Date: Fri May 6 01:50:10 2022 +0000 + + nptl: Add backoff mechanism to spinlock loop + + When mutiple threads waiting for lock at the same time, once lock owner + releases the lock, waiters will see lock available and all try to lock, + which may cause an expensive CAS storm. + + Binary exponential backoff with random jitter is introduced. As try-lock + attempt increases, there is more likely that a larger number threads + compete for adaptive mutex lock, so increase wait time in exponential. + A random jitter is also added to avoid synchronous try-lock from other + threads. + + v2: Remove read-check before try-lock for performance. + + v3: + 1. Restore read-check since it works well in some platform. + 2. Make backoff arch dependent, and enable it for x86_64. + 3. Limit max backoff to reduce latency in large critical section. + + v4: Fix strict-prototypes error in sysdeps/nptl/pthread_mutex_backoff.h + + v5: Commit log updated for regression in large critical section. + + Result of pthread-mutex-locks bench + + Test Platform: Xeon 8280L (2 socket, 112 CPUs in total) + First Row: thread number + First Col: critical section length + Values: backoff vs upstream, time based, low is better + + non-critical-length: 1 + 1 2 4 8 16 32 64 112 140 + 0 0.99 0.58 0.52 0.49 0.43 0.44 0.46 0.52 0.54 + 1 0.98 0.43 0.56 0.50 0.44 0.45 0.50 0.56 0.57 + 2 0.99 0.41 0.57 0.51 0.45 0.47 0.48 0.60 0.61 + 4 0.99 0.45 0.59 0.53 0.48 0.49 0.52 0.64 0.65 + 8 1.00 0.66 0.71 0.63 0.56 0.59 0.66 0.72 0.71 + 16 0.97 0.78 0.91 0.73 0.67 0.70 0.79 0.80 0.80 + 32 0.95 1.17 0.98 0.87 0.82 0.86 0.89 0.90 0.90 + 64 0.96 0.95 1.01 1.01 0.98 1.00 1.03 0.99 0.99 + 128 0.99 1.01 1.01 1.17 1.08 1.12 1.02 0.97 1.02 + + non-critical-length: 32 + 1 2 4 8 16 32 64 112 140 + 0 1.03 0.97 0.75 0.65 0.58 0.58 0.56 0.70 0.70 + 1 0.94 0.95 0.76 0.65 0.58 0.58 0.61 0.71 0.72 + 2 0.97 0.96 0.77 0.66 0.58 0.59 0.62 0.74 0.74 + 4 0.99 0.96 0.78 0.66 0.60 0.61 0.66 0.76 0.77 + 8 0.99 0.99 0.84 0.70 0.64 0.66 0.71 0.80 0.80 + 16 0.98 0.97 0.95 0.76 0.70 0.73 0.81 0.85 0.84 + 32 1.04 1.12 1.04 0.89 0.82 0.86 0.93 0.91 0.91 + 64 0.99 1.15 1.07 1.00 0.99 1.01 1.05 0.99 0.99 + 128 1.00 1.21 1.20 1.22 1.25 1.31 1.12 1.10 0.99 + + non-critical-length: 128 + 1 2 4 8 16 32 64 112 140 + 0 1.02 1.00 0.99 0.67 0.61 0.61 0.61 0.74 0.73 + 1 0.95 0.99 1.00 0.68 0.61 0.60 0.60 0.74 0.74 + 2 1.00 1.04 1.00 0.68 0.59 0.61 0.65 0.76 0.76 + 4 1.00 0.96 0.98 0.70 0.63 0.63 0.67 0.78 0.77 + 8 1.01 1.02 0.89 0.73 0.65 0.67 0.71 0.81 0.80 + 16 0.99 0.96 0.96 0.79 0.71 0.73 0.80 0.84 0.84 + 32 0.99 0.95 1.05 0.89 0.84 0.85 0.94 0.92 0.91 + 64 1.00 0.99 1.16 1.04 1.00 1.02 1.06 0.99 0.99 + 128 1.00 1.06 0.98 1.14 1.39 1.26 1.08 1.02 0.98 + + There is regression in large critical section. But adaptive mutex is + aimed for "quick" locks. Small critical section is more common when + users choose to use adaptive pthread_mutex. + + Signed-off-by: Wangyang Guo + Reviewed-by: H.J. Lu + (cherry picked from commit 8162147872491bb5b48e91543b19c49a29ae6b6d) + +diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c +index bbe754a272b97d91..8f3f687f2a151d16 100644 +--- a/nptl/pthread_mutex_lock.c ++++ b/nptl/pthread_mutex_lock.c +@@ -139,14 +139,26 @@ PTHREAD_MUTEX_LOCK (pthread_mutex_t *mutex) + int cnt = 0; + int max_cnt = MIN (max_adaptive_count (), + mutex->__data.__spins * 2 + 10); ++ int spin_count, exp_backoff = 1; ++ unsigned int jitter = get_jitter (); + do + { +- if (cnt++ >= max_cnt) ++ /* In each loop, spin count is exponential backoff plus ++ random jitter, random range is [0, exp_backoff-1]. */ ++ spin_count = exp_backoff + (jitter & (exp_backoff - 1)); ++ cnt += spin_count; ++ if (cnt >= max_cnt) + { ++ /* If cnt exceeds max spin count, just go to wait ++ queue. */ + LLL_MUTEX_LOCK (mutex); + break; + } +- atomic_spin_nop (); ++ do ++ atomic_spin_nop (); ++ while (--spin_count > 0); ++ /* Prepare for next loop. */ ++ exp_backoff = get_next_backoff (exp_backoff); + } + while (LLL_MUTEX_READ_LOCK (mutex) != 0 + || LLL_MUTEX_TRYLOCK (mutex) != 0); +diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h +index b968afc4c6b61b92..ed186ce3df1fde0c 100644 +--- a/sysdeps/nptl/pthreadP.h ++++ b/sysdeps/nptl/pthreadP.h +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include "pthread_mutex_conf.h" + + +diff --git a/sysdeps/nptl/pthread_mutex_backoff.h b/sysdeps/nptl/pthread_mutex_backoff.h +new file mode 100644 +index 0000000000000000..5b26c22ac789f54f +--- /dev/null ++++ b/sysdeps/nptl/pthread_mutex_backoff.h +@@ -0,0 +1,35 @@ ++/* Pthread mutex backoff configuration. ++ 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 ++ . */ ++#ifndef _PTHREAD_MUTEX_BACKOFF_H ++#define _PTHREAD_MUTEX_BACKOFF_H 1 ++ ++static inline unsigned int ++get_jitter (void) ++{ ++ /* Arch dependent random jitter, return 0 disables random. */ ++ return 0; ++} ++ ++static inline int ++get_next_backoff (int backoff) ++{ ++ /* Next backoff, return 1 disables mutex backoff. */ ++ return 1; ++} ++ ++#endif +diff --git a/sysdeps/x86_64/nptl/pthread_mutex_backoff.h b/sysdeps/x86_64/nptl/pthread_mutex_backoff.h +new file mode 100644 +index 0000000000000000..ec74c3d9db61864e +--- /dev/null ++++ b/sysdeps/x86_64/nptl/pthread_mutex_backoff.h +@@ -0,0 +1,39 @@ ++/* Pthread mutex backoff configuration. ++ 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 ++ . */ ++#ifndef _PTHREAD_MUTEX_BACKOFF_H ++#define _PTHREAD_MUTEX_BACKOFF_H 1 ++ ++#include ++ ++static inline unsigned int ++get_jitter (void) ++{ ++ return get_fast_jitter (); ++} ++ ++#define MAX_BACKOFF 16 ++ ++static inline int ++get_next_backoff (int backoff) ++{ ++ /* Binary expontial backoff. Limiting max backoff ++ can reduce latency in large critical section. */ ++ return (backoff < MAX_BACKOFF) ? backoff << 1 : backoff; ++} ++ ++#endif diff --git a/SOURCES/glibc-upstream-2.34-337.patch b/SOURCES/glibc-upstream-2.34-337.patch new file mode 100644 index 0000000..41aea50 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-337.patch @@ -0,0 +1,26 @@ +commit 95f5089d4a57cd1e738be908c7a628cb7d0ce512 +Author: Aurelien Jarno +Date: Mon Oct 3 23:16:46 2022 +0200 + + x86: include BMI1 and BMI2 in x86-64-v3 level + + The "System V Application Binary Interface AMD64 Architecture Processor + Supplement" mandates the BMI1 and BMI2 CPU features for the x86-64-v3 + level. + + Reviewed-by: Noah Goldstein + (cherry picked from commit b80f16adbd979831bf25ea491e1261e81885c2b6) + +diff --git a/sysdeps/x86/get-isa-level.h b/sysdeps/x86/get-isa-level.h +index aa80f56ca635e54b..785c25a835edf004 100644 +--- a/sysdeps/x86/get-isa-level.h ++++ b/sysdeps/x86/get-isa-level.h +@@ -47,6 +47,8 @@ get_isa_level (const struct cpu_features *cpu_features) + isa_level |= GNU_PROPERTY_X86_ISA_1_V2; + if (CPU_FEATURE_USABLE_P (cpu_features, AVX) + && CPU_FEATURE_USABLE_P (cpu_features, AVX2) ++ && CPU_FEATURE_USABLE_P (cpu_features, BMI1) ++ && CPU_FEATURE_USABLE_P (cpu_features, BMI2) + && CPU_FEATURE_USABLE_P (cpu_features, F16C) + && CPU_FEATURE_USABLE_P (cpu_features, FMA) + && CPU_FEATURE_USABLE_P (cpu_features, LZCNT) diff --git a/SOURCES/glibc-upstream-2.34-338.patch b/SOURCES/glibc-upstream-2.34-338.patch new file mode 100644 index 0000000..44dec62 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-338.patch @@ -0,0 +1,111 @@ +commit 414fc856ff4e011e62b88a21d30294637a152dc7 +Author: Aurelien Jarno +Date: Mon Oct 3 23:16:46 2022 +0200 + + x86-64: Require BMI2 for AVX2 str(n)casecmp implementations + + The AVX2 str(n)casecmp implementations use the 'bzhi' instruction, which + belongs to the BMI2 CPU feature. + + NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF + as BSF if the CPU doesn't support TZCNT, and produces the same result + for non-zero input. + + Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S") + Partially resolves: BZ #29611 + + Reviewed-by: Noah Goldstein + (cherry picked from commit 10f79d3670b036925da63dc532b122d27ce65ff8) + +diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +index 8d649e263eb24b8a..ca64b34c146a76f9 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +@@ -386,13 +386,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL (i, name, strcasecmp, + IFUNC_IMPL_ADD (array, i, strcasecmp, + (CPU_FEATURE_USABLE (AVX512VL) +- && CPU_FEATURE_USABLE (AVX512BW)), ++ && CPU_FEATURE_USABLE (AVX512BW) ++ && CPU_FEATURE_USABLE (BMI2)), + __strcasecmp_evex) + IFUNC_IMPL_ADD (array, i, strcasecmp, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2)), + __strcasecmp_avx2) + IFUNC_IMPL_ADD (array, i, strcasecmp, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __strcasecmp_avx2_rtm) + IFUNC_IMPL_ADD (array, i, strcasecmp, +@@ -407,13 +410,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL (i, name, strcasecmp_l, + IFUNC_IMPL_ADD (array, i, strcasecmp, + (CPU_FEATURE_USABLE (AVX512VL) +- && CPU_FEATURE_USABLE (AVX512BW)), ++ && CPU_FEATURE_USABLE (AVX512BW) ++ && CPU_FEATURE_USABLE (BMI2)), + __strcasecmp_l_evex) + IFUNC_IMPL_ADD (array, i, strcasecmp, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2)), + __strcasecmp_l_avx2) + IFUNC_IMPL_ADD (array, i, strcasecmp, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __strcasecmp_l_avx2_rtm) + IFUNC_IMPL_ADD (array, i, strcasecmp_l, +@@ -542,13 +548,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL (i, name, strncasecmp, + IFUNC_IMPL_ADD (array, i, strncasecmp, + (CPU_FEATURE_USABLE (AVX512VL) +- && CPU_FEATURE_USABLE (AVX512BW)), ++ && CPU_FEATURE_USABLE (AVX512BW) ++ && CPU_FEATURE_USABLE (BMI2)), + __strncasecmp_evex) + IFUNC_IMPL_ADD (array, i, strncasecmp, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2)), + __strncasecmp_avx2) + IFUNC_IMPL_ADD (array, i, strncasecmp, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __strncasecmp_avx2_rtm) + IFUNC_IMPL_ADD (array, i, strncasecmp, +@@ -564,13 +573,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL (i, name, strncasecmp_l, + IFUNC_IMPL_ADD (array, i, strncasecmp, + (CPU_FEATURE_USABLE (AVX512VL) +- && CPU_FEATURE_USABLE (AVX512BW)), ++ & CPU_FEATURE_USABLE (AVX512BW) ++ && CPU_FEATURE_USABLE (BMI2)), + __strncasecmp_l_evex) + IFUNC_IMPL_ADD (array, i, strncasecmp, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2)), + __strncasecmp_l_avx2) + IFUNC_IMPL_ADD (array, i, strncasecmp, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __strncasecmp_l_avx2_rtm) + IFUNC_IMPL_ADD (array, i, strncasecmp_l, +diff --git a/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h b/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h +index 40819caf5ab10337..e61d6e9497bce9d9 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h ++++ b/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h +@@ -32,6 +32,7 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (CPU_FEATURE_USABLE_P (cpu_features, AVX2) ++ && CPU_FEATURE_USABLE_P (cpu_features, BMI2) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + { + if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL) diff --git a/SOURCES/glibc-upstream-2.34-339.patch b/SOURCES/glibc-upstream-2.34-339.patch new file mode 100644 index 0000000..4820b0f --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-339.patch @@ -0,0 +1,55 @@ +commit e1561d8cf005a23bcaf514802854b493829a25b1 +Author: Aurelien Jarno +Date: Mon Oct 3 23:16:46 2022 +0200 + + x86-64: Require BMI2 for AVX2 strcmp implementation + + The AVX2 strcmp implementation uses the 'bzhi' instruction, which + belongs to the BMI2 CPU feature. + + NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF + as BSF if the CPU doesn't support TZCNT, and produces the same result + for non-zero input. + + Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S") + Partially resolves: BZ #29611 + + Reviewed-by: Noah Goldstein + (cherry picked from commit 4d64c6445735e9b34e2ac8e369312cbfc2f88e17) + +diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +index ca64b34c146a76f9..70931f15985334af 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +@@ -503,10 +503,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/strcmp.c. */ + IFUNC_IMPL (i, name, strcmp, + IFUNC_IMPL_ADD (array, i, strcmp, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2)), + __strcmp_avx2) + IFUNC_IMPL_ADD (array, i, strcmp, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __strcmp_avx2_rtm) + IFUNC_IMPL_ADD (array, i, strcmp, +diff --git a/sysdeps/x86_64/multiarch/strcmp.c b/sysdeps/x86_64/multiarch/strcmp.c +index b457fb4c150e4407..0c0cd20a03278a2b 100644 +--- a/sysdeps/x86_64/multiarch/strcmp.c ++++ b/sysdeps/x86_64/multiarch/strcmp.c +@@ -40,11 +40,11 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (CPU_FEATURE_USABLE_P (cpu_features, AVX2) ++ && CPU_FEATURE_USABLE_P (cpu_features, BMI2) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + { + if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL) +- && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW) +- && CPU_FEATURE_USABLE_P (cpu_features, BMI2)) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW)) + return OPTIMIZE (evex); + + if (CPU_FEATURE_USABLE_P (cpu_features, RTM)) diff --git a/SOURCES/glibc-upstream-2.34-340.patch b/SOURCES/glibc-upstream-2.34-340.patch new file mode 100644 index 0000000..077c288 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-340.patch @@ -0,0 +1,62 @@ +commit b9cbb8dd48b545f3b36b5d411481dc0bd118ee94 +Author: Aurelien Jarno +Date: Mon Oct 3 23:16:46 2022 +0200 + + x86-64: Require BMI2 for AVX2 strncmp implementation + + The AVX2 strncmp implementations uses the 'bzhi' instruction, which + belongs to the BMI2 CPU feature. + + NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF + as BSF if the CPU doesn't support TZCNT, and produces the same result + for non-zero input. + + Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S") + Partially resolves: BZ #29611 + + Reviewed-by: Noah Goldstein + (cherry picked from commit fc7de1d9b99ae1676bc626ddca422d7abee0eb48) + +diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +index 70931f15985334af..34d5f6efe5421014 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +@@ -1022,15 +1022,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/strncmp.c. */ + IFUNC_IMPL (i, name, strncmp, + IFUNC_IMPL_ADD (array, i, strncmp, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2)), + __strncmp_avx2) + IFUNC_IMPL_ADD (array, i, strncmp, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __strncmp_avx2_rtm) + IFUNC_IMPL_ADD (array, i, strncmp, + (CPU_FEATURE_USABLE (AVX512VL) +- && CPU_FEATURE_USABLE (AVX512BW)), ++ && CPU_FEATURE_USABLE (AVX512BW) ++ && CPU_FEATURE_USABLE (BMI2)), + __strncmp_evex) + IFUNC_IMPL_ADD (array, i, strncmp, CPU_FEATURE_USABLE (SSE4_2), + __strncmp_sse42) +diff --git a/sysdeps/x86_64/multiarch/strncmp.c b/sysdeps/x86_64/multiarch/strncmp.c +index f94a421784bfe923..7632d7b2dd4447aa 100644 +--- a/sysdeps/x86_64/multiarch/strncmp.c ++++ b/sysdeps/x86_64/multiarch/strncmp.c +@@ -39,11 +39,11 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (CPU_FEATURE_USABLE_P (cpu_features, AVX2) ++ && CPU_FEATURE_USABLE_P (cpu_features, BMI2) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + { + if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL) +- && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW) +- && CPU_FEATURE_USABLE_P (cpu_features, BMI2)) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW)) + return OPTIMIZE (evex); + + if (CPU_FEATURE_USABLE_P (cpu_features, RTM)) diff --git a/SOURCES/glibc-upstream-2.34-341.patch b/SOURCES/glibc-upstream-2.34-341.patch new file mode 100644 index 0000000..6e9814a --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-341.patch @@ -0,0 +1,51 @@ +commit 67e863742d98c990b3d3b814b80042c0fa0d50a5 +Author: Aurelien Jarno +Date: Mon Oct 3 23:16:46 2022 +0200 + + x86-64: Require BMI2 for AVX2 wcs(n)cmp implementations + + The AVX2 wcs(n)cmp implementations use the 'bzhi' instruction, which + belongs to the BMI2 CPU feature. + + NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF + as BSF if the CPU doesn't support TZCNT, and produces the same result + for non-zero input. + + Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S") + Partially resolves: BZ #29611 + + Reviewed-by: Noah Goldstein + (cherry picked from commit f31a5a884ed84bd37032729d4d1eb9d06c9f3c29) + +diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +index 34d5f6efe5421014..e76a991dc671c1a9 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +@@ -693,10 +693,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/wcscmp.c. */ + IFUNC_IMPL (i, name, wcscmp, + IFUNC_IMPL_ADD (array, i, wcscmp, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2)), + __wcscmp_avx2) + IFUNC_IMPL_ADD (array, i, wcscmp, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __wcscmp_avx2_rtm) + IFUNC_IMPL_ADD (array, i, wcscmp, +@@ -709,10 +711,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/wcsncmp.c. */ + IFUNC_IMPL (i, name, wcsncmp, + IFUNC_IMPL_ADD (array, i, wcsncmp, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2)), + __wcsncmp_avx2) + IFUNC_IMPL_ADD (array, i, wcsncmp, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __wcsncmp_avx2_rtm) + IFUNC_IMPL_ADD (array, i, wcsncmp, diff --git a/SOURCES/glibc-upstream-2.34-342.patch b/SOURCES/glibc-upstream-2.34-342.patch new file mode 100644 index 0000000..8750786 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-342.patch @@ -0,0 +1,61 @@ +commit 94b9c1b6409e34f3f0b2339f77d7ee78087422eb +Author: Aurelien Jarno +Date: Mon Oct 3 23:16:46 2022 +0200 + + x86-64: Require BMI2 for AVX2 (raw|w)memchr implementations + + The AVX2 memchr, rawmemchr and wmemchr implementations use the 'bzhi' + and 'sarx' instructions, which belongs to the BMI2 CPU feature. + + Fixes: acfd088a1963 ("x86: Optimize memchr-avx2.S") + Partially resolves: BZ #29611 + + Reviewed-by: Noah Goldstein + (cherry picked from commit e3e7fab7fe5186d18ca2046d99ba321c27db30ad) + +diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +index e76a991dc671c1a9..81640cf00664e3ed 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +@@ -41,10 +41,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/memchr.c. */ + IFUNC_IMPL (i, name, memchr, + IFUNC_IMPL_ADD (array, i, memchr, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2)), + __memchr_avx2) + IFUNC_IMPL_ADD (array, i, memchr, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __memchr_avx2_rtm) + IFUNC_IMPL_ADD (array, i, memchr, +@@ -283,10 +285,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/rawmemchr.c. */ + IFUNC_IMPL (i, name, rawmemchr, + IFUNC_IMPL_ADD (array, i, rawmemchr, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2)), + __rawmemchr_avx2) + IFUNC_IMPL_ADD (array, i, rawmemchr, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __rawmemchr_avx2_rtm) + IFUNC_IMPL_ADD (array, i, rawmemchr, +@@ -787,10 +791,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/wmemchr.c. */ + IFUNC_IMPL (i, name, wmemchr, + IFUNC_IMPL_ADD (array, i, wmemchr, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2)), + __wmemchr_avx2) + IFUNC_IMPL_ADD (array, i, wmemchr, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __wmemchr_avx2_rtm) + IFUNC_IMPL_ADD (array, i, wmemchr, diff --git a/SOURCES/glibc-upstream-2.34-343.patch b/SOURCES/glibc-upstream-2.34-343.patch new file mode 100644 index 0000000..dd9d4b8 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-343.patch @@ -0,0 +1,56 @@ +commit 36d6b9be3d7008a78e1f6e2e2db1947b76b206d8 +Author: Aurelien Jarno +Date: Mon Oct 3 23:16:46 2022 +0200 + + x86-64: Require BMI2 and LZCNT for AVX2 memrchr implementation + + The AVX2 memrchr implementation uses the 'shlxl' instruction, which + belongs to the BMI2 CPU feature and uses the 'lzcnt' instruction, which + belongs to the LZCNT CPU feature. + + Fixes: af5306a735eb ("x86: Optimize memrchr-avx2.S") + Partially resolves: BZ #29611 + + Reviewed-by: Noah Goldstein + (cherry picked from commit 3c0c78afabfed4b6fc161c159e628fbf14ff370b) + +diff --git a/sysdeps/x86_64/multiarch/ifunc-avx2.h b/sysdeps/x86_64/multiarch/ifunc-avx2.h +index 6de72f72724b81ba..52bd00ea5cab6b22 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-avx2.h ++++ b/sysdeps/x86_64/multiarch/ifunc-avx2.h +@@ -31,6 +31,7 @@ IFUNC_SELECTOR (void) + + if (CPU_FEATURE_USABLE_P (cpu_features, AVX2) + && CPU_FEATURE_USABLE_P (cpu_features, BMI2) ++ && CPU_FEATURE_USABLE_P (cpu_features, LZCNT) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + { + if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL) +diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +index 81640cf00664e3ed..d1fc1e75d6706413 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +@@ -174,15 +174,21 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/memrchr.c. */ + IFUNC_IMPL (i, name, memrchr, + IFUNC_IMPL_ADD (array, i, memrchr, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) ++ && CPU_FEATURE_USABLE (LZCNT)), + __memrchr_avx2) + IFUNC_IMPL_ADD (array, i, memrchr, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI2) ++ && CPU_FEATURE_USABLE (LZCNT) + && CPU_FEATURE_USABLE (RTM)), + __memrchr_avx2_rtm) + IFUNC_IMPL_ADD (array, i, memrchr, + (CPU_FEATURE_USABLE (AVX512VL) +- && CPU_FEATURE_USABLE (AVX512BW)), ++ && CPU_FEATURE_USABLE (AVX512BW) ++ && CPU_FEATURE_USABLE (BMI2) ++ && CPU_FEATURE_USABLE (LZCNT)), + __memrchr_evex) + + IFUNC_IMPL_ADD (array, i, memrchr, 1, __memrchr_sse2)) diff --git a/SOURCES/glibc-upstream-2.34-344.patch b/SOURCES/glibc-upstream-2.34-344.patch new file mode 100644 index 0000000..754168f --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-344.patch @@ -0,0 +1,78 @@ +commit e570b865b53f33453d97160791a7d97e38bcc6e8 +Author: Aurelien Jarno +Date: Mon Oct 3 23:16:46 2022 +0200 + + x86-64: Require BMI1/BMI2 for AVX2 strrchr and wcsrchr implementations + + The AVX2 strrchr and wcsrchr implementation uses the 'blsmsk' + instruction which belongs to the BMI1 CPU feature and the 'shrx' + instruction, which belongs to the BMI2 CPU feature. + + Fixes: df7e295d18ff ("x86: Optimize {str|wcs}rchr-avx2") + Partially resolves: BZ #29611 + + Reviewed-by: Noah Goldstein + (cherry picked from commit 7e8283170c5d6805b609a040801d819e362a6292) + +diff --git a/sysdeps/x86_64/multiarch/ifunc-avx2.h b/sysdeps/x86_64/multiarch/ifunc-avx2.h +index 52bd00ea5cab6b22..877f007dd6e38fe8 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-avx2.h ++++ b/sysdeps/x86_64/multiarch/ifunc-avx2.h +@@ -30,6 +30,7 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (CPU_FEATURE_USABLE_P (cpu_features, AVX2) ++ && CPU_FEATURE_USABLE_P (cpu_features, BMI1) + && CPU_FEATURE_USABLE_P (cpu_features, BMI2) + && CPU_FEATURE_USABLE_P (cpu_features, LZCNT) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) +diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +index d1fc1e75d6706413..84f9e73e2b7df816 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +@@ -498,15 +498,21 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/strrchr.c. */ + IFUNC_IMPL (i, name, strrchr, + IFUNC_IMPL_ADD (array, i, strrchr, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI1) ++ && CPU_FEATURE_USABLE (BMI2)), + __strrchr_avx2) + IFUNC_IMPL_ADD (array, i, strrchr, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI1) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __strrchr_avx2_rtm) + IFUNC_IMPL_ADD (array, i, strrchr, + (CPU_FEATURE_USABLE (AVX512VL) +- && CPU_FEATURE_USABLE (AVX512BW)), ++ && CPU_FEATURE_USABLE (AVX512BW) ++ && CPU_FEATURE_USABLE (BMI1) ++ && CPU_FEATURE_USABLE (BMI2)), + __strrchr_evex) + IFUNC_IMPL_ADD (array, i, strrchr, 1, __strrchr_sse2)) + +@@ -687,15 +693,20 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/wcsrchr.c. */ + IFUNC_IMPL (i, name, wcsrchr, + IFUNC_IMPL_ADD (array, i, wcsrchr, +- CPU_FEATURE_USABLE (AVX2), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI1) ++ && CPU_FEATURE_USABLE (BMI2)), + __wcsrchr_avx2) + IFUNC_IMPL_ADD (array, i, wcsrchr, + (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI1) ++ && CPU_FEATURE_USABLE (BMI2) + && CPU_FEATURE_USABLE (RTM)), + __wcsrchr_avx2_rtm) + IFUNC_IMPL_ADD (array, i, wcsrchr, + (CPU_FEATURE_USABLE (AVX512VL) + && CPU_FEATURE_USABLE (AVX512BW) ++ && CPU_FEATURE_USABLE (BMI1) + && CPU_FEATURE_USABLE (BMI2)), + __wcsrchr_evex) + IFUNC_IMPL_ADD (array, i, wcsrchr, 1, __wcsrchr_sse2)) diff --git a/SOURCES/glibc-upstream-2.34-345.patch b/SOURCES/glibc-upstream-2.34-345.patch new file mode 100644 index 0000000..c0028eb --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-345.patch @@ -0,0 +1,46 @@ +commit e3976287b22422787f3cc6fc9adda58304b55bd9 +Author: Siddhesh Poyarekar +Date: Tue Oct 4 18:40:25 2022 -0400 + + nscd: Drop local address tuple variable [BZ #29607] + + When a request needs to be resent (e.g. due to insufficient buffer + space), the references to subsequent tuples in the local variable are + stale and should not be used. This used to work by accident before, but + since 1d495912a it no longer does. Instead of trying to reset it, just + let gethostbyname4_r write into TUMPBUF6 for us, thus maintaining a + consistent state at all times. This is now consistent with what is done + in gaih_inet for getaddrinfo. + + Resolves: BZ #29607 + Reported-by: Holger Hoffstätte + Tested-by: Holger Hoffstätte + Reviewed-by: Carlos O'Donell + (cherry picked from commit 6e33e5c4b73cea7b8aa3de0947123db16200fb65) + +diff --git a/nscd/aicache.c b/nscd/aicache.c +index 737ace11cc276021..3b300ad9b7db2297 100644 +--- a/nscd/aicache.c ++++ b/nscd/aicache.c +@@ -111,11 +111,10 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, + "gethostbyname4_r"); + if (fct4 != NULL) + { +- struct gaih_addrtuple atmem; + struct gaih_addrtuple *at; + while (1) + { +- at = &atmem; ++ at = NULL; + rc6 = 0; + herrno = 0; + status[1] = DL_CALL_FCT (fct4, (key, &at, +@@ -138,7 +137,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, + goto next_nip; + + /* We found the data. Count the addresses and the size. */ +- for (const struct gaih_addrtuple *at2 = at = &atmem; at2 != NULL; ++ for (const struct gaih_addrtuple *at2 = at; at2 != NULL; + at2 = at2->next) + { + ++naddrs; diff --git a/SOURCES/glibc-upstream-2.34-346.patch b/SOURCES/glibc-upstream-2.34-346.patch new file mode 100644 index 0000000..a0fe300 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-346.patch @@ -0,0 +1,55 @@ +commit c95ef423d78d9a2ec0a8e4141c78165434685c6f +Author: Florian Weimer +Date: Tue Sep 13 16:10:20 2022 +0200 + + nss: Implement --no-addrconfig option for getent + + The ahosts, ahostsv4, ahostsv6 commands unconditionally pass + AI_ADDRCONFIG to getaddrinfo, which is not always desired. + + Reviewed-by: Carlos O'Donell + (cherry picked from commit a623f13adfac47c8634a7288e08f821a846bc650) + +diff --git a/nss/getent.c b/nss/getent.c +index ec48ba4bf1f5f788..0f4d549b05da73ac 100644 +--- a/nss/getent.c ++++ b/nss/getent.c +@@ -59,6 +59,8 @@ static const struct argp_option args_options[] = + { + { "service", 's', N_("CONFIG"), 0, N_("Service configuration to be used") }, + { "no-idn", 'i', NULL, 0, N_("disable IDN encoding") }, ++ { "no-addrconfig", 'A', NULL, 0, ++ N_("do not filter out unsupported IPv4/IPv6 addresses (with ahosts*)") }, + { NULL, 0, NULL, 0, NULL }, + }; + +@@ -80,6 +82,9 @@ static struct argp argp = + /* Additional getaddrinfo flags for IDN encoding. */ + static int idn_flags = AI_IDN | AI_CANONIDN; + ++/* Set to 0 by --no-addrconfig. */ ++static int addrconfig_flags = AI_ADDRCONFIG; ++ + /* Print the version information. */ + static void + print_version (FILE *stream, struct argp_state *state) +@@ -347,7 +352,7 @@ ahosts_keys_int (int af, int xflags, int number, char *key[]) + + struct addrinfo hint; + memset (&hint, '\0', sizeof (hint)); +- hint.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME ++ hint.ai_flags = (AI_V4MAPPED | addrconfig_flags | AI_CANONNAME + | idn_flags | xflags); + hint.ai_family = af; + +@@ -906,6 +911,10 @@ parse_option (int key, char *arg, struct argp_state *state) + idn_flags = 0; + break; + ++ case 'A': ++ addrconfig_flags = 0; ++ break; ++ + default: + return ARGP_ERR_UNKNOWN; + } diff --git a/SOURCES/glibc-upstream-2.34-347.patch b/SOURCES/glibc-upstream-2.34-347.patch new file mode 100644 index 0000000..408e38f --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-347.patch @@ -0,0 +1,38 @@ +commit 16c7ed6e68c13e5a5efd8ab464ebf9d07b4b0bb3 +Author: Florian Weimer +Date: Tue Sep 13 16:11:40 2022 +0200 + + nss: Fix tst-nss-files-hosts-long on single-stack hosts (bug 24816) + + getent implicitly passes AI_ADDRCONFIG to getaddrinfo by default. + Use --no-addrconfig to suppress that, so that both IPv4 and IPv6 + lookups succeed even if the address family is not supported by the + host. + + Reviewed-by: Carlos O'Donell + (cherry picked from commit c75d20b5b27b0a60f0678236f51a4d3b0b058c00) + +diff --git a/nss/tst-nss-files-hosts-long.c b/nss/tst-nss-files-hosts-long.c +index 00f8bea409e0b4cb..42676ba4056dbde2 100644 +--- a/nss/tst-nss-files-hosts-long.c ++++ b/nss/tst-nss-files-hosts-long.c +@@ -28,14 +28,15 @@ do_test (void) + { + int ret; + +- /* Run getent to fetch the IPv4 address for host test4. +- This forces /etc/hosts to be parsed. */ +- ret = system("getent ahostsv4 test4"); ++ /* Run getent to fetch the IPv4 address for host test4. This forces ++ /etc/hosts to be parsed. Use --no-addrconfig to return addresses ++ even in an IPv6-only environment. */ ++ ret = system("getent --no-addrconfig ahostsv4 test4"); + if (ret != 0) + FAIL_EXIT1("ahostsv4 failed"); + + /* Likewise for IPv6. */ +- ret = system("getent ahostsv6 test6"); ++ ret = system("getent --no-addrconfig ahostsv6 test6"); + if (ret != 0) + FAIL_EXIT1("ahostsv6 failed"); + diff --git a/SOURCES/glibc-upstream-2.34-348.patch b/SOURCES/glibc-upstream-2.34-348.patch new file mode 100644 index 0000000..c33b026 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-348.patch @@ -0,0 +1,47 @@ +commit d5313bcb7e56cd949ca920bb0c741a1d1d4093cf +Author: Florian Weimer +Date: Fri Sep 23 19:30:57 2022 +0200 + + nss: Use shared prefix in IPv4 address in tst-reload1 + + Otherwise, sorting based on the longest-matching prefix in + getaddrinfo can reorder the addresses in ways the test does not + expect, depending on the IPv4 address of the host. + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit c02e29a0ba47d636281e1a026444a1a0a254aa12) + +diff --git a/nss/tst-reload1.c b/nss/tst-reload1.c +index 27a18ed9c37607bb..844cfcddc5e0f638 100644 +--- a/nss/tst-reload1.c ++++ b/nss/tst-reload1.c +@@ -43,12 +43,12 @@ static struct passwd pwd_table_1[] = { + + static const char *hostaddr_5[] = + { +- "ABCD", "abcd", "1234", NULL ++ "ABCd", "ABCD", "ABC4", NULL + }; + + static const char *hostaddr_15[] = + { +- "4321", "ghij", NULL ++ "4321", "4322", NULL + }; + + static const char *hostaddr_25[] = +@@ -86,12 +86,12 @@ static const char *hostaddr_6[] = + + static const char *hostaddr_16[] = + { +- "7890", "a1b2", NULL ++ "7890", "7891", NULL + }; + + static const char *hostaddr_26[] = + { +- "qwer", "tyui", NULL ++ "qwer", "qweR", NULL + }; + + static struct hostent host_table_2[] = { diff --git a/SOURCES/glibc-upstream-2.34-349.patch b/SOURCES/glibc-upstream-2.34-349.patch new file mode 100644 index 0000000..0b05961 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-349.patch @@ -0,0 +1,92 @@ +commit 9f55d2e7c42e6ca862a25d3ee3eb2b367811c30d +Author: Florian Weimer +Date: Fri Oct 14 12:43:07 2022 +0200 + + elf: Do not completely clear reused namespace in dlmopen (bug 29600) + + The data in the _ns_debug member must be preserved, otherwise + _dl_debug_initialize enters an infinite loop. To be conservative, + only clear the libc_map member for now, to fix bug 29528. + + Fixes commit d0e357ff45a75553dee3b17ed7d303bfa544f6fe + ("elf: Call __libc_early_init for reused namespaces (bug 29528)"), + by reverting most of it. + + Reviewed-by: Carlos O'Donell + Tested-by: Carlos O'Donell + (cherry picked from commit 2c42257314536b94cc8d52edede86e94e98c1436) + (Conflict in elf/dl-open.c due to missing _r_debug namespace support.) + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 1ab3c7b5ac2fbc45..633b047ad2497296 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -839,15 +839,13 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid, + _dl_signal_error (EINVAL, file, NULL, N_("\ + no more namespaces available for dlmopen()")); + } ++ else if (nsid == GL(dl_nns)) ++ { ++ __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock); ++ ++GL(dl_nns); ++ } + +- if (nsid == GL(dl_nns)) +- ++GL(dl_nns); +- +- /* Initialize the new namespace. Most members are +- zero-initialized, only the lock needs special treatment. */ +- memset (&GL(dl_ns)[nsid], 0, sizeof (GL(dl_ns)[nsid])); +- __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock); +- ++ GL(dl_ns)[nsid].libc_map = NULL; + _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT; + } + /* Never allow loading a DSO in a namespace which is empty. Such +diff --git a/elf/tst-dlmopen-twice.c b/elf/tst-dlmopen-twice.c +index 449f3c8fa9f2aa01..70c71fe19c7d0bf9 100644 +--- a/elf/tst-dlmopen-twice.c ++++ b/elf/tst-dlmopen-twice.c +@@ -16,18 +16,38 @@ + License along with the GNU C Library; if not, see + . */ + +-#include ++#include + #include ++#include + +-static int +-do_test (void) ++/* Run the test multiple times, to check finding a new namespace while ++ another namespace is already in use. This used to trigger bug 29600. */ ++static void ++recurse (int depth) + { +- void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so", RTLD_NOW); ++ if (depth == 0) ++ return; ++ ++ printf ("info: running at depth %d\n", depth); ++ void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so", ++ RTLD_NOW); + xdlclose (handle); + handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod2.so", RTLD_NOW); + int (*run_check) (void) = xdlsym (handle, "run_check"); + TEST_COMPARE (run_check (), 0); ++ recurse (depth - 1); + xdlclose (handle); ++} ++ ++static int ++do_test (void) ++{ ++ /* First run the test without nesting. */ ++ recurse (1); ++ ++ /* Then with nesting. The constant needs to be less than the ++ internal DL_NNS namespace constant. */ ++ recurse (10); + return 0; + } + diff --git a/SOURCES/glibc-upstream-2.34-350.patch b/SOURCES/glibc-upstream-2.34-350.patch new file mode 100644 index 0000000..7ab515b --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-350.patch @@ -0,0 +1,861 @@ +commit ca5df795459b9242cd7d787ebf71a09be2244577 +Author: Adhemerval Zanella +Date: Wed Oct 19 19:14:04 2022 -0300 + + linux: Fix generic struct_stat for 64 bit time (BZ# 29657) + + The generic Linux struct_stat misses the conditionals to use + bits/struct_stat_time64_helper.h in the __USE_TIME_BITS64 for + architecture that uses __TIMESIZE == 32 (currently csky and nios2). + + Since newer ports should not support 32 bit time_t, the generic + implementation should be used as default. + + For arm, hppa, and sh a copy of default struct_stat is added, + while for csky and nios a new one based on generic is used, along + with conditionals to use bits/struct_stat_time64_helper.h. + + The default struct_stat is also replaced with the generic one. + + Checked on aarch64-linux-gnu and arm-linux-gnueabihf. + + (cherry picked from commit 7a6ca82f8007ddbd43e2b8fce806ba7101ee47f5) + +diff --git a/sysdeps/unix/sysv/linux/arm/bits/struct_stat.h b/sysdeps/unix/sysv/linux/arm/bits/struct_stat.h +new file mode 100644 +index 0000000000000000..30ee6279d2701242 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/arm/bits/struct_stat.h +@@ -0,0 +1,139 @@ ++/* Definition for struct stat. Linux/arm version. ++ Copyright (C) 2020-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 ++ . */ ++ ++#if !defined _SYS_STAT_H && !defined _FCNTL_H ++# error "Never include directly; use instead." ++#endif ++ ++#ifndef _BITS_STRUCT_STAT_H ++#define _BITS_STRUCT_STAT_H 1 ++ ++#include ++#include ++ ++struct stat ++ { ++#ifdef __USE_TIME_BITS64 ++# include ++#else ++ __dev_t st_dev; /* Device. */ ++ unsigned short int __pad1; ++# ifndef __USE_FILE_OFFSET64 ++ __ino_t st_ino; /* File serial number. */ ++# else ++ __ino_t __st_ino; /* 32bit file serial number. */ ++# endif ++ __mode_t st_mode; /* File mode. */ ++ __nlink_t st_nlink; /* Link count. */ ++ __uid_t st_uid; /* User ID of the file's owner. */ ++ __gid_t st_gid; /* Group ID of the file's group.*/ ++ __dev_t st_rdev; /* Device number, if device. */ ++ unsigned short int __pad2; ++# ifndef __USE_FILE_OFFSET64 ++ __off_t st_size; /* Size of file, in bytes. */ ++# else ++ __off64_t st_size; /* Size of file, in bytes. */ ++# endif ++ __blksize_t st_blksize; /* Optimal block size for I/O. */ ++ ++# ifndef __USE_FILE_OFFSET64 ++ __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ ++# else ++ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ ++# endif ++# ifdef __USE_XOPEN2K8 ++ /* Nanosecond resolution timestamps are stored in a format ++ equivalent to 'struct timespec'. This is the type used ++ whenever possible but the Unix namespace rules do not allow the ++ identifier 'timespec' to appear in the header. ++ Therefore we have to handle the use of this header in strictly ++ standard-compliant sources special. */ ++ struct timespec st_atim; /* Time of last access. */ ++ struct timespec st_mtim; /* Time of last modification. */ ++ struct timespec st_ctim; /* Time of last status change. */ ++# define st_atime st_atim.tv_sec /* Backward compatibility. */ ++# define st_mtime st_mtim.tv_sec ++# define st_ctime st_ctim.tv_sec ++# else ++ __time_t st_atime; /* Time of last access. */ ++ unsigned long int st_atimensec; /* Nscecs of last access. */ ++ __time_t st_mtime; /* Time of last modification. */ ++ unsigned long int st_mtimensec; /* Nsecs of last modification. */ ++ __time_t st_ctime; /* Time of last status change. */ ++ unsigned long int st_ctimensec; /* Nsecs of last status change. */ ++# endif ++# ifndef __USE_FILE_OFFSET64 ++ unsigned long int __glibc_reserved4; ++ unsigned long int __glibc_reserved5; ++# else ++ __ino64_t st_ino; /* File serial number. */ ++# endif ++#endif /* __USE_TIME_BITS64 */ ++ }; ++ ++#ifdef __USE_LARGEFILE64 ++struct stat64 ++ { ++# ifdef __USE_TIME_BITS64 ++# include ++# else ++ __dev_t st_dev; /* Device. */ ++ unsigned int __pad1; ++ ++ __ino_t __st_ino; /* 32bit file serial number. */ ++ __mode_t st_mode; /* File mode. */ ++ __nlink_t st_nlink; /* Link count. */ ++ __uid_t st_uid; /* User ID of the file's owner. */ ++ __gid_t st_gid; /* Group ID of the file's group.*/ ++ __dev_t st_rdev; /* Device number, if device. */ ++ unsigned int __pad2; ++ __off64_t st_size; /* Size of file, in bytes. */ ++ __blksize_t st_blksize; /* Optimal block size for I/O. */ ++ ++ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ ++# ifdef __USE_XOPEN2K8 ++ /* Nanosecond resolution timestamps are stored in a format ++ equivalent to 'struct timespec'. This is the type used ++ whenever possible but the Unix namespace rules do not allow the ++ identifier 'timespec' to appear in the header. ++ Therefore we have to handle the use of this header in strictly ++ standard-compliant sources special. */ ++ struct timespec st_atim; /* Time of last access. */ ++ struct timespec st_mtim; /* Time of last modification. */ ++ struct timespec st_ctim; /* Time of last status change. */ ++# else ++ __time_t st_atime; /* Time of last access. */ ++ unsigned long int st_atimensec; /* Nscecs of last access. */ ++ __time_t st_mtime; /* Time of last modification. */ ++ unsigned long int st_mtimensec; /* Nsecs of last modification. */ ++ __time_t st_ctime; /* Time of last status change. */ ++ unsigned long int st_ctimensec; /* Nsecs of last status change. */ ++# endif ++ __ino64_t st_ino; /* File serial number. */ ++# endif /* __USE_TIME_BITS64 */ ++ }; ++#endif ++ ++/* Tell code we have these members. */ ++#define _STATBUF_ST_BLKSIZE ++#define _STATBUF_ST_RDEV ++/* Nanosecond resolution time values are supported. */ ++#define _STATBUF_ST_NSEC ++ ++ ++#endif /* _BITS_STRUCT_STAT_H */ +diff --git a/sysdeps/unix/sysv/linux/bits/struct_stat.h b/sysdeps/unix/sysv/linux/bits/struct_stat.h +index 298418966f4d6e0b..32ef511ae5728276 100644 +--- a/sysdeps/unix/sysv/linux/bits/struct_stat.h ++++ b/sysdeps/unix/sysv/linux/bits/struct_stat.h +@@ -26,37 +26,36 @@ + #include + #include + +-struct stat +- { +-#ifdef __USE_TIME_BITS64 +-# include +-#else +- __dev_t st_dev; /* Device. */ +- unsigned short int __pad1; +-# ifndef __USE_FILE_OFFSET64 +- __ino_t st_ino; /* File serial number. */ +-# else +- __ino_t __st_ino; /* 32bit file serial number. */ ++#if defined __USE_FILE_OFFSET64 ++# define __field64(type, type64, name) type64 name ++#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T ++# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T ++# error "ino_t and off_t must both be the same type" + # endif +- __mode_t st_mode; /* File mode. */ +- __nlink_t st_nlink; /* Link count. */ +- __uid_t st_uid; /* User ID of the file's owner. */ +- __gid_t st_gid; /* Group ID of the file's group.*/ +- __dev_t st_rdev; /* Device number, if device. */ +- unsigned short int __pad2; +-# ifndef __USE_FILE_OFFSET64 +- __off_t st_size; /* Size of file, in bytes. */ +-# else +- __off64_t st_size; /* Size of file, in bytes. */ +-# endif +- __blksize_t st_blksize; /* Optimal block size for I/O. */ ++# define __field64(type, type64, name) type name ++#elif __BYTE_ORDER == __LITTLE_ENDIAN ++# define __field64(type, type64, name) \ ++ type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad ++#else ++# define __field64(type, type64, name) \ ++ int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name ++#endif + +-# ifndef __USE_FILE_OFFSET64 +- __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +-# else +- __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +-# endif +-# ifdef __USE_XOPEN2K8 ++struct stat ++ { ++ __dev_t st_dev; /* Device. */ ++ __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */ ++ __mode_t st_mode; /* File mode. */ ++ __nlink_t st_nlink; /* Link count. */ ++ __uid_t st_uid; /* User ID of the file's owner. */ ++ __gid_t st_gid; /* Group ID of the file's group.*/ ++ __dev_t st_rdev; /* Device number, if device. */ ++ __dev_t __pad1; ++ __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */ ++ __blksize_t st_blksize; /* Optimal block size for I/O. */ ++ int __pad2; ++ __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */ ++#ifdef __USE_XOPEN2K8 + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the +@@ -66,47 +65,38 @@ struct stat + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +-# define st_atime st_atim.tv_sec /* Backward compatibility. */ +-# define st_mtime st_mtim.tv_sec +-# define st_ctime st_ctim.tv_sec +-# else ++# define st_atime st_atim.tv_sec /* Backward compatibility. */ ++# define st_mtime st_mtim.tv_sec ++# define st_ctime st_ctim.tv_sec ++#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +-# endif +-# ifndef __USE_FILE_OFFSET64 +- unsigned long int __glibc_reserved4; +- unsigned long int __glibc_reserved5; +-# else +- __ino64_t st_ino; /* File serial number. */ +-# endif +-#endif /* __USE_TIME_BITS64 */ ++#endif ++ int __glibc_reserved[2]; + }; + ++#undef __field64 ++ + #ifdef __USE_LARGEFILE64 + struct stat64 + { +-# ifdef __USE_TIME_BITS64 +-# include +-# else +- __dev_t st_dev; /* Device. */ +- unsigned int __pad1; +- +- __ino_t __st_ino; /* 32bit file serial number. */ +- __mode_t st_mode; /* File mode. */ +- __nlink_t st_nlink; /* Link count. */ +- __uid_t st_uid; /* User ID of the file's owner. */ +- __gid_t st_gid; /* Group ID of the file's group.*/ +- __dev_t st_rdev; /* Device number, if device. */ +- unsigned int __pad2; +- __off64_t st_size; /* Size of file, in bytes. */ +- __blksize_t st_blksize; /* Optimal block size for I/O. */ +- +- __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +-# ifdef __USE_XOPEN2K8 ++ __dev_t st_dev; /* Device. */ ++ __ino64_t st_ino; /* File serial number. */ ++ __mode_t st_mode; /* File mode. */ ++ __nlink_t st_nlink; /* Link count. */ ++ __uid_t st_uid; /* User ID of the file's owner. */ ++ __gid_t st_gid; /* Group ID of the file's group.*/ ++ __dev_t st_rdev; /* Device number, if device. */ ++ __dev_t __pad1; ++ __off64_t st_size; /* Size of file, in bytes. */ ++ __blksize_t st_blksize; /* Optimal block size for I/O. */ ++ int __pad2; ++ __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ ++#ifdef __USE_XOPEN2K8 + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the +@@ -116,16 +106,15 @@ struct stat64 + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +-# else ++#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +-# endif +- __ino64_t st_ino; /* File serial number. */ +-# endif /* __USE_TIME_BITS64 */ ++#endif ++ int __glibc_reserved[2]; + }; + #endif + +@@ -135,5 +124,4 @@ struct stat64 + /* Nanosecond resolution time values are supported. */ + #define _STATBUF_ST_NSEC + +- + #endif /* _BITS_STRUCT_STAT_H */ +diff --git a/sysdeps/unix/sysv/linux/generic/bits/struct_stat.h b/sysdeps/unix/sysv/linux/csky/bits/struct_stat.h +similarity index 91% +rename from sysdeps/unix/sysv/linux/generic/bits/struct_stat.h +rename to sysdeps/unix/sysv/linux/csky/bits/struct_stat.h +index 32ef511ae5728276..f0ee455748d3ee41 100644 +--- a/sysdeps/unix/sysv/linux/generic/bits/struct_stat.h ++++ b/sysdeps/unix/sysv/linux/csky/bits/struct_stat.h +@@ -1,5 +1,5 @@ +-/* Definition for struct stat. +- Copyright (C) 2020-2021 Free Software Foundation, Inc. ++/* Definition for struct stat. Linux/csky version. ++ Copyright (C) 2020-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 +@@ -43,6 +43,9 @@ + + struct stat + { ++#ifdef __USE_TIME_BITS64 ++# include ++#else + __dev_t st_dev; /* Device. */ + __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */ + __mode_t st_mode; /* File mode. */ +@@ -55,7 +58,7 @@ struct stat + __blksize_t st_blksize; /* Optimal block size for I/O. */ + int __pad2; + __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */ +-#ifdef __USE_XOPEN2K8 ++# ifdef __USE_XOPEN2K8 + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the +@@ -65,18 +68,19 @@ struct stat + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +-# define st_atime st_atim.tv_sec /* Backward compatibility. */ +-# define st_mtime st_mtim.tv_sec +-# define st_ctime st_ctim.tv_sec +-#else ++# define st_atime st_atim.tv_sec /* Backward compatibility. */ ++# define st_mtime st_mtim.tv_sec ++# define st_ctime st_ctim.tv_sec ++# else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +-#endif ++# endif + int __glibc_reserved[2]; ++#endif + }; + + #undef __field64 +@@ -84,6 +88,9 @@ struct stat + #ifdef __USE_LARGEFILE64 + struct stat64 + { ++# ifdef __USE_TIME_BITS64 ++# include ++# else + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ +@@ -96,7 +103,7 @@ struct stat64 + __blksize_t st_blksize; /* Optimal block size for I/O. */ + int __pad2; + __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ +-#ifdef __USE_XOPEN2K8 ++# ifdef __USE_XOPEN2K8 + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the +@@ -106,15 +113,16 @@ struct stat64 + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +-#else ++# else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +-#endif ++# endif + int __glibc_reserved[2]; ++# endif + }; + #endif + +diff --git a/sysdeps/unix/sysv/linux/hppa/bits/struct_stat.h b/sysdeps/unix/sysv/linux/hppa/bits/struct_stat.h +new file mode 100644 +index 0000000000000000..38b6e13e68890c29 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/hppa/bits/struct_stat.h +@@ -0,0 +1,139 @@ ++/* Definition for struct stat. Linux/hppa version. ++ Copyright (C) 2020-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 ++ . */ ++ ++#if !defined _SYS_STAT_H && !defined _FCNTL_H ++# error "Never include directly; use instead." ++#endif ++ ++#ifndef _BITS_STRUCT_STAT_H ++#define _BITS_STRUCT_STAT_H 1 ++ ++#include ++#include ++ ++struct stat ++ { ++#ifdef __USE_TIME_BITS64 ++# include ++#else ++ __dev_t st_dev; /* Device. */ ++ unsigned short int __pad1; ++# ifndef __USE_FILE_OFFSET64 ++ __ino_t st_ino; /* File serial number. */ ++# else ++ __ino_t __st_ino; /* 32bit file serial number. */ ++# endif ++ __mode_t st_mode; /* File mode. */ ++ __nlink_t st_nlink; /* Link count. */ ++ __uid_t st_uid; /* User ID of the file's owner. */ ++ __gid_t st_gid; /* Group ID of the file's group.*/ ++ __dev_t st_rdev; /* Device number, if device. */ ++ unsigned short int __pad2; ++# ifndef __USE_FILE_OFFSET64 ++ __off_t st_size; /* Size of file, in bytes. */ ++# else ++ __off64_t st_size; /* Size of file, in bytes. */ ++# endif ++ __blksize_t st_blksize; /* Optimal block size for I/O. */ ++ ++# ifndef __USE_FILE_OFFSET64 ++ __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ ++# else ++ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ ++# endif ++# ifdef __USE_XOPEN2K8 ++ /* Nanosecond resolution timestamps are stored in a format ++ equivalent to 'struct timespec'. This is the type used ++ whenever possible but the Unix namespace rules do not allow the ++ identifier 'timespec' to appear in the header. ++ Therefore we have to handle the use of this header in strictly ++ standard-compliant sources special. */ ++ struct timespec st_atim; /* Time of last access. */ ++ struct timespec st_mtim; /* Time of last modification. */ ++ struct timespec st_ctim; /* Time of last status change. */ ++# define st_atime st_atim.tv_sec /* Backward compatibility. */ ++# define st_mtime st_mtim.tv_sec ++# define st_ctime st_ctim.tv_sec ++# else ++ __time_t st_atime; /* Time of last access. */ ++ unsigned long int st_atimensec; /* Nscecs of last access. */ ++ __time_t st_mtime; /* Time of last modification. */ ++ unsigned long int st_mtimensec; /* Nsecs of last modification. */ ++ __time_t st_ctime; /* Time of last status change. */ ++ unsigned long int st_ctimensec; /* Nsecs of last status change. */ ++# endif ++# ifndef __USE_FILE_OFFSET64 ++ unsigned long int __glibc_reserved4; ++ unsigned long int __glibc_reserved5; ++# else ++ __ino64_t st_ino; /* File serial number. */ ++# endif ++#endif /* __USE_TIME_BITS64 */ ++ }; ++ ++#ifdef __USE_LARGEFILE64 ++struct stat64 ++ { ++# ifdef __USE_TIME_BITS64 ++# include ++# else ++ __dev_t st_dev; /* Device. */ ++ unsigned int __pad1; ++ ++ __ino_t __st_ino; /* 32bit file serial number. */ ++ __mode_t st_mode; /* File mode. */ ++ __nlink_t st_nlink; /* Link count. */ ++ __uid_t st_uid; /* User ID of the file's owner. */ ++ __gid_t st_gid; /* Group ID of the file's group.*/ ++ __dev_t st_rdev; /* Device number, if device. */ ++ unsigned int __pad2; ++ __off64_t st_size; /* Size of file, in bytes. */ ++ __blksize_t st_blksize; /* Optimal block size for I/O. */ ++ ++ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ ++# ifdef __USE_XOPEN2K8 ++ /* Nanosecond resolution timestamps are stored in a format ++ equivalent to 'struct timespec'. This is the type used ++ whenever possible but the Unix namespace rules do not allow the ++ identifier 'timespec' to appear in the header. ++ Therefore we have to handle the use of this header in strictly ++ standard-compliant sources special. */ ++ struct timespec st_atim; /* Time of last access. */ ++ struct timespec st_mtim; /* Time of last modification. */ ++ struct timespec st_ctim; /* Time of last status change. */ ++# else ++ __time_t st_atime; /* Time of last access. */ ++ unsigned long int st_atimensec; /* Nscecs of last access. */ ++ __time_t st_mtime; /* Time of last modification. */ ++ unsigned long int st_mtimensec; /* Nsecs of last modification. */ ++ __time_t st_ctime; /* Time of last status change. */ ++ unsigned long int st_ctimensec; /* Nsecs of last status change. */ ++# endif ++ __ino64_t st_ino; /* File serial number. */ ++# endif /* __USE_TIME_BITS64 */ ++ }; ++#endif ++ ++/* Tell code we have these members. */ ++#define _STATBUF_ST_BLKSIZE ++#define _STATBUF_ST_RDEV ++/* Nanosecond resolution time values are supported. */ ++#define _STATBUF_ST_NSEC ++ ++ ++#endif /* _BITS_STRUCT_STAT_H */ +diff --git a/sysdeps/unix/sysv/linux/nios2/bits/struct_stat.h b/sysdeps/unix/sysv/linux/nios2/bits/struct_stat.h +new file mode 100644 +index 0000000000000000..e00e71173e184b48 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/nios2/bits/struct_stat.h +@@ -0,0 +1,135 @@ ++/* Definition for struct stat. Linux/nios2 version. ++ Copyright (C) 2020-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 ++ . */ ++ ++#if !defined _SYS_STAT_H && !defined _FCNTL_H ++# error "Never include directly; use instead." ++#endif ++ ++#ifndef _BITS_STRUCT_STAT_H ++#define _BITS_STRUCT_STAT_H 1 ++ ++#include ++#include ++ ++#if defined __USE_FILE_OFFSET64 ++# define __field64(type, type64, name) type64 name ++#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T ++# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T ++# error "ino_t and off_t must both be the same type" ++# endif ++# define __field64(type, type64, name) type name ++#elif __BYTE_ORDER == __LITTLE_ENDIAN ++# define __field64(type, type64, name) \ ++ type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad ++#else ++# define __field64(type, type64, name) \ ++ int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name ++#endif ++ ++struct stat ++ { ++#ifdef __USE_TIME_BITS64 ++# include ++#else ++ __dev_t st_dev; /* Device. */ ++ __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */ ++ __mode_t st_mode; /* File mode. */ ++ __nlink_t st_nlink; /* Link count. */ ++ __uid_t st_uid; /* User ID of the file's owner. */ ++ __gid_t st_gid; /* Group ID of the file's group.*/ ++ __dev_t st_rdev; /* Device number, if device. */ ++ __dev_t __pad1; ++ __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */ ++ __blksize_t st_blksize; /* Optimal block size for I/O. */ ++ int __pad2; ++ __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */ ++# ifdef __USE_XOPEN2K8 ++ /* Nanosecond resolution timestamps are stored in a format ++ equivalent to 'struct timespec'. This is the type used ++ whenever possible but the Unix namespace rules do not allow the ++ identifier 'timespec' to appear in the header. ++ Therefore we have to handle the use of this header in strictly ++ standard-compliant sources special. */ ++ struct timespec st_atim; /* Time of last access. */ ++ struct timespec st_mtim; /* Time of last modification. */ ++ struct timespec st_ctim; /* Time of last status change. */ ++# define st_atime st_atim.tv_sec /* Backward compatibility. */ ++# define st_mtime st_mtim.tv_sec ++# define st_ctime st_ctim.tv_sec ++# else ++ __time_t st_atime; /* Time of last access. */ ++ unsigned long int st_atimensec; /* Nscecs of last access. */ ++ __time_t st_mtime; /* Time of last modification. */ ++ unsigned long int st_mtimensec; /* Nsecs of last modification. */ ++ __time_t st_ctime; /* Time of last status change. */ ++ unsigned long int st_ctimensec; /* Nsecs of last status change. */ ++# endif ++ int __glibc_reserved[2]; ++#endif ++ }; ++ ++#undef __field64 ++ ++#ifdef __USE_LARGEFILE64 ++struct stat64 ++ { ++# ifdef __USE_TIME_BITS64 ++# include ++# else ++ __dev_t st_dev; /* Device. */ ++ __ino64_t st_ino; /* File serial number. */ ++ __mode_t st_mode; /* File mode. */ ++ __nlink_t st_nlink; /* Link count. */ ++ __uid_t st_uid; /* User ID of the file's owner. */ ++ __gid_t st_gid; /* Group ID of the file's group.*/ ++ __dev_t st_rdev; /* Device number, if device. */ ++ __dev_t __pad1; ++ __off64_t st_size; /* Size of file, in bytes. */ ++ __blksize_t st_blksize; /* Optimal block size for I/O. */ ++ int __pad2; ++ __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ ++# ifdef __USE_XOPEN2K8 ++ /* Nanosecond resolution timestamps are stored in a format ++ equivalent to 'struct timespec'. This is the type used ++ whenever possible but the Unix namespace rules do not allow the ++ identifier 'timespec' to appear in the header. ++ Therefore we have to handle the use of this header in strictly ++ standard-compliant sources special. */ ++ struct timespec st_atim; /* Time of last access. */ ++ struct timespec st_mtim; /* Time of last modification. */ ++ struct timespec st_ctim; /* Time of last status change. */ ++# else ++ __time_t st_atime; /* Time of last access. */ ++ unsigned long int st_atimensec; /* Nscecs of last access. */ ++ __time_t st_mtime; /* Time of last modification. */ ++ unsigned long int st_mtimensec; /* Nsecs of last modification. */ ++ __time_t st_ctime; /* Time of last status change. */ ++ unsigned long int st_ctimensec; /* Nsecs of last status change. */ ++# endif ++ int __glibc_reserved[2]; ++# endif ++ }; ++#endif ++ ++/* Tell code we have these members. */ ++#define _STATBUF_ST_BLKSIZE ++#define _STATBUF_ST_RDEV ++/* Nanosecond resolution time values are supported. */ ++#define _STATBUF_ST_NSEC ++ ++#endif /* _BITS_STRUCT_STAT_H */ +diff --git a/sysdeps/unix/sysv/linux/sh/bits/struct_stat.h b/sysdeps/unix/sysv/linux/sh/bits/struct_stat.h +new file mode 100644 +index 0000000000000000..0f7c9cdc89ebf686 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/sh/bits/struct_stat.h +@@ -0,0 +1,139 @@ ++/* Definition for struct stat. Linux/sh version. ++ Copyright (C) 2020-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 ++ . */ ++ ++#if !defined _SYS_STAT_H && !defined _FCNTL_H ++# error "Never include directly; use instead." ++#endif ++ ++#ifndef _BITS_STRUCT_STAT_H ++#define _BITS_STRUCT_STAT_H 1 ++ ++#include ++#include ++ ++struct stat ++ { ++#ifdef __USE_TIME_BITS64 ++# include ++#else ++ __dev_t st_dev; /* Device. */ ++ unsigned short int __pad1; ++# ifndef __USE_FILE_OFFSET64 ++ __ino_t st_ino; /* File serial number. */ ++# else ++ __ino_t __st_ino; /* 32bit file serial number. */ ++# endif ++ __mode_t st_mode; /* File mode. */ ++ __nlink_t st_nlink; /* Link count. */ ++ __uid_t st_uid; /* User ID of the file's owner. */ ++ __gid_t st_gid; /* Group ID of the file's group.*/ ++ __dev_t st_rdev; /* Device number, if device. */ ++ unsigned short int __pad2; ++# ifndef __USE_FILE_OFFSET64 ++ __off_t st_size; /* Size of file, in bytes. */ ++# else ++ __off64_t st_size; /* Size of file, in bytes. */ ++# endif ++ __blksize_t st_blksize; /* Optimal block size for I/O. */ ++ ++# ifndef __USE_FILE_OFFSET64 ++ __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ ++# else ++ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ ++# endif ++# ifdef __USE_XOPEN2K8 ++ /* Nanosecond resolution timestamps are stored in a format ++ equivalent to 'struct timespec'. This is the type used ++ whenever possible but the Unix namespace rules do not allow the ++ identifier 'timespec' to appear in the header. ++ Therefore we have to handle the use of this header in strictly ++ standard-compliant sources special. */ ++ struct timespec st_atim; /* Time of last access. */ ++ struct timespec st_mtim; /* Time of last modification. */ ++ struct timespec st_ctim; /* Time of last status change. */ ++# define st_atime st_atim.tv_sec /* Backward compatibility. */ ++# define st_mtime st_mtim.tv_sec ++# define st_ctime st_ctim.tv_sec ++# else ++ __time_t st_atime; /* Time of last access. */ ++ unsigned long int st_atimensec; /* Nscecs of last access. */ ++ __time_t st_mtime; /* Time of last modification. */ ++ unsigned long int st_mtimensec; /* Nsecs of last modification. */ ++ __time_t st_ctime; /* Time of last status change. */ ++ unsigned long int st_ctimensec; /* Nsecs of last status change. */ ++# endif ++# ifndef __USE_FILE_OFFSET64 ++ unsigned long int __glibc_reserved4; ++ unsigned long int __glibc_reserved5; ++# else ++ __ino64_t st_ino; /* File serial number. */ ++# endif ++#endif /* __USE_TIME_BITS64 */ ++ }; ++ ++#ifdef __USE_LARGEFILE64 ++struct stat64 ++ { ++# ifdef __USE_TIME_BITS64 ++# include ++# else ++ __dev_t st_dev; /* Device. */ ++ unsigned int __pad1; ++ ++ __ino_t __st_ino; /* 32bit file serial number. */ ++ __mode_t st_mode; /* File mode. */ ++ __nlink_t st_nlink; /* Link count. */ ++ __uid_t st_uid; /* User ID of the file's owner. */ ++ __gid_t st_gid; /* Group ID of the file's group.*/ ++ __dev_t st_rdev; /* Device number, if device. */ ++ unsigned int __pad2; ++ __off64_t st_size; /* Size of file, in bytes. */ ++ __blksize_t st_blksize; /* Optimal block size for I/O. */ ++ ++ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ ++# ifdef __USE_XOPEN2K8 ++ /* Nanosecond resolution timestamps are stored in a format ++ equivalent to 'struct timespec'. This is the type used ++ whenever possible but the Unix namespace rules do not allow the ++ identifier 'timespec' to appear in the header. ++ Therefore we have to handle the use of this header in strictly ++ standard-compliant sources special. */ ++ struct timespec st_atim; /* Time of last access. */ ++ struct timespec st_mtim; /* Time of last modification. */ ++ struct timespec st_ctim; /* Time of last status change. */ ++# else ++ __time_t st_atime; /* Time of last access. */ ++ unsigned long int st_atimensec; /* Nscecs of last access. */ ++ __time_t st_mtime; /* Time of last modification. */ ++ unsigned long int st_mtimensec; /* Nsecs of last modification. */ ++ __time_t st_ctime; /* Time of last status change. */ ++ unsigned long int st_ctimensec; /* Nsecs of last status change. */ ++# endif ++ __ino64_t st_ino; /* File serial number. */ ++# endif /* __USE_TIME_BITS64 */ ++ }; ++#endif ++ ++/* Tell code we have these members. */ ++#define _STATBUF_ST_BLKSIZE ++#define _STATBUF_ST_RDEV ++/* Nanosecond resolution time values are supported. */ ++#define _STATBUF_ST_NSEC ++ ++ ++#endif /* _BITS_STRUCT_STAT_H */ diff --git a/SOURCES/glibc-upstream-2.34-351.patch b/SOURCES/glibc-upstream-2.34-351.patch new file mode 100644 index 0000000..91141b0 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-351.patch @@ -0,0 +1,107 @@ +commit f42d871b22f7eb5330e77ed9bccbb447c44e7101 +Author: Sergei Trofimovich +Date: Tue Sep 13 13:39:13 2022 -0400 + + Makerules: fix MAKEFLAGS assignment for upcoming make-4.4 [BZ# 29564] + + make-4.4 will add long flags to MAKEFLAGS variable: + + * WARNING: Backward-incompatibility! + Previously only simple (one-letter) options were added to the MAKEFLAGS + variable that was visible while parsing makefiles. Now, all options + are available in MAKEFLAGS. + + This causes locale builds to fail when long options are used: + + $ make --shuffle + ... + make -C localedata install-locales + make: invalid shuffle mode: '1662724426r' + + The change fixes it by passing eash option via whitespace and dashes. + That way option is appended to both single-word form and whitespace + separated form. + + While at it fixed --silent mode detection in $(MAKEFLAGS) by filtering + out --long-options. Otherwise options like --shuffle flag enable silent + mode unintentionally. $(silent-make) variable consolidates the checks. + + Resolves: BZ# 29564 + + CC: Paul Smith + CC: Siddhesh Poyarekar + Signed-off-by: Sergei Trofimovich + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 2d7ed98add14f75041499ac189696c9bd3d757fe) + +diff --git a/Makeconfig b/Makeconfig +index 99898a632a64be91..4e04dafb76a1e1a1 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -43,6 +43,22 @@ else + $(error objdir must be defined by the build-directory Makefile) + endif + ++# Did we request 'make -s' run? "yes" or "no". ++# Starting from make-4.4 MAKEFLAGS now contains long ++# options like '--shuffle'. To detect presence of 's' ++# we pick first word with short options. Long options ++# are guaranteed to come after whitespace. We use '-' ++# prefix to always have a word before long options ++# even if no short options were passed. ++# Typical MAKEFLAGS values to watch for: ++# "rs --shuffle=42" (silent) ++# " --shuffle" (not silent) ++ifeq ($(findstring s, $(firstword -$(MAKEFLAGS))),) ++silent-make := no ++else ++silent-make := yes ++endif ++ + # Root of the sysdeps tree. + sysdep_dir := $(..)sysdeps + export sysdep_dir := $(sysdep_dir) +@@ -918,7 +934,7 @@ endif + # umpteen zillion filenames along with it (we use `...' instead) + # but we don't want this echoing done when the user has said + # he doesn't want to see commands echoed by using -s. +-ifneq "$(findstring s,$(MAKEFLAGS))" "" # if -s ++ifeq ($(silent-make),yes) # if -s + +cmdecho := echo >/dev/null + else # not -s + +cmdecho := echo +diff --git a/Makerules b/Makerules +index 7fbe85719aacc230..e5916f29fa0d4593 100644 +--- a/Makerules ++++ b/Makerules +@@ -810,7 +810,7 @@ endif + # Maximize efficiency by minimizing the number of rules. + .SUFFIXES: # Clear the suffix list. We don't use suffix rules. + # Don't define any builtin rules. +-MAKEFLAGS := $(MAKEFLAGS)r ++MAKEFLAGS := $(MAKEFLAGS) -r + + # Generic rule for making directories. + %/: +@@ -827,7 +827,7 @@ MAKEFLAGS := $(MAKEFLAGS)r + .PRECIOUS: $(foreach l,$(libtypes),$(patsubst %,$(common-objpfx)$l,c)) + + # Use the verbose option of ar and tar when not running silently. +-ifeq "$(findstring s,$(MAKEFLAGS))" "" # if not -s ++ifeq ($(silent-make),no) # if not -s + verbose := v + else # -s + verbose := +diff --git a/elf/rtld-Rules b/elf/rtld-Rules +index 10de81918c07670f..a452536d39b5c198 100644 +--- a/elf/rtld-Rules ++++ b/elf/rtld-Rules +@@ -52,7 +52,7 @@ $(objpfx)rtld-libc.a: $(foreach dir,$(rtld-subdirs),\ + mv -f $@T $@ + + # Use the verbose option of ar and tar when not running silently. +-ifeq "$(findstring s,$(MAKEFLAGS))" "" # if not -s ++ifeq ($(silent-make),no) # if not -s + verbose := v + else # -s + verbose := diff --git a/SOURCES/glibc-upstream-2.34-352.patch b/SOURCES/glibc-upstream-2.34-352.patch new file mode 100644 index 0000000..5c4006e --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-352.patch @@ -0,0 +1,73 @@ +commit 675ba1f361ea424626b48a40cfd24d113dfc1b65 +Author: Paul Eggert +Date: Thu Sep 8 20:08:32 2022 -0500 + + mktime: improve heuristic for ca-1986 Indiana DST + + This patch syncs mktime.c from Gnulib, fixing a + problem reported by Mark Krenz , + and it should fix BZ#29035 too. + * time/mktime.c (__mktime_internal): Be more generous about + accepting arguments with the wrong value of tm_isdst, by falling + back to a one-hour DST difference if we find no nearby DST that is + unusual. This fixes a problem where "1986-04-28 00:00 EDT" was + rejected when TZ="America/Indianapolis" because the nearest DST + timestamp occurred in 1970, a temporal distance too great for the + old heuristic. This also also narrows the search a bit, which + is a minor performance win. + + (cherry picked from commit 83859e1115269cf56d21669361d4ddbe2687831c) + +diff --git a/time/mktime.c b/time/mktime.c +index 8e78006eea7e693b..74d9bbaa5b375723 100644 +--- a/time/mktime.c ++++ b/time/mktime.c +@@ -429,8 +429,13 @@ __mktime_internal (struct tm *tp, + time with the right value, and use its UTC offset. + + Heuristic: probe the adjacent timestamps in both directions, +- looking for the desired isdst. This should work for all real +- time zone histories in the tz database. */ ++ looking for the desired isdst. If none is found within a ++ reasonable duration bound, assume a one-hour DST difference. ++ This should work for all real time zone histories in the tz ++ database. */ ++ ++ /* +1 if we wanted standard time but got DST, -1 if the reverse. */ ++ int dst_difference = (isdst == 0) - (tm.tm_isdst == 0); + + /* Distance between probes when looking for a DST boundary. In + tzdata2003a, the shortest period of DST is 601200 seconds +@@ -441,12 +446,14 @@ __mktime_internal (struct tm *tp, + periods when probing. */ + int stride = 601200; + +- /* The longest period of DST in tzdata2003a is 536454000 seconds +- (e.g., America/Jujuy starting 1946-10-01 01:00). The longest +- period of non-DST is much longer, but it makes no real sense +- to search for more than a year of non-DST, so use the DST +- max. */ +- int duration_max = 536454000; ++ /* In TZDB 2021e, the longest period of DST (or of non-DST), in ++ which the DST (or adjacent DST) difference is not one hour, ++ is 457243209 seconds: e.g., America/Cambridge_Bay with leap ++ seconds, starting 1965-10-31 00:00 in a switch from ++ double-daylight time (-05) to standard time (-07), and ++ continuing to 1980-04-27 02:00 in a switch from standard time ++ (-07) to daylight time (-06). */ ++ int duration_max = 457243209; + + /* Search in both directions, so the maximum distance is half + the duration; add the stride to avoid off-by-1 problems. */ +@@ -483,6 +490,11 @@ __mktime_internal (struct tm *tp, + } + } + ++ /* No unusual DST offset was found nearby. Assume one-hour DST. */ ++ t += 60 * 60 * dst_difference; ++ if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm)) ++ goto offset_found; ++ + __set_errno (EOVERFLOW); + return -1; + } diff --git a/SOURCES/glibc-upstream-2.34-353.patch b/SOURCES/glibc-upstream-2.34-353.patch new file mode 100644 index 0000000..2bf6250 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-353.patch @@ -0,0 +1,86 @@ +commit 6e8044e910600f71f4802dba2d105007af8428c3 +Author: Joseph Myers +Date: Mon Nov 8 19:11:51 2021 +0000 + + Fix memmove call in vfprintf-internal.c:group_number + + A recent GCC mainline change introduces errors of the form: + + vfprintf-internal.c: In function 'group_number': + vfprintf-internal.c:2093:15: error: 'memmove' specified bound between 9223372036854775808 and 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=] + 2093 | memmove (w, s, (front_ptr -s) * sizeof (CHAR_T)); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + This is a genuine bug in the glibc code: s > front_ptr is always true + at this point in the code, and the intent is clearly for the + subtraction to be the other way round. The other arguments to the + memmove call here also appear to be wrong; w and s point just *after* + the destination and source for copying the rest of the number, so the + size needs to be subtracted to get appropriate pointers for the + copying. Adjust the memmove call to conform to the apparent intent of + the code, so fixing the -Wstringop-overflow error. + + Now, if the original code were ever executed, a buffer overrun would + result. However, I believe this code (introduced in commit + edc1686af0c0fc2eb535f1d38cdf63c1a5a03675, "vfprintf: Reuse work_buffer + in group_number", so in glibc 2.26) is unreachable in prior glibc + releases (so there is no need for a bug in Bugzilla, no need to + consider any backports unless someone wants to build older glibc + releases with GCC 12 and no possibility of this buffer overrun + resulting in a security issue). + + work_buffer is 1000 bytes / 250 wide characters. This case is only + reachable if an initial part of the number, plus a grouped copy of the + rest of the number, fail to fit in that space; that is, if the grouped + number fails to fit in the space. In the wide character case, + grouping is always one wide character, so even with a locale (of which + there aren't any in glibc) grouping every digit, a number would need + to occupy at least 125 wide characters to overflow, and a 64-bit + integer occupies at most 23 characters in octal including a leading 0. + In the narrow character case, the multibyte encoding of the grouping + separator would need to be at least 42 bytes to overflow, again + supposing grouping every digit, but MB_LEN_MAX is 16. So even if we + admit the case of artificially constructed locales not shipped with + glibc, given that such a locale would need to use one of the character + sets supported by glibc, this code cannot be reached at present. (And + POSIX only actually specifies the ' flag for grouping for decimal + output, though glibc acts on it for other bases as well.) + + With binary output (if you consider use of grouping there to be + valid), you'd need a 15-byte multibyte character for overflow; I don't + know if any supported character set has such a character (if, again, + we admit constructed locales using grouping every digit and a grouping + separator chosen to have a multibyte encoding as long as possible, as + well as accepting use of grouping with binary), but given that we have + this code at all (clearly it's not *correct*, or in accordance with + the principle of avoiding arbitrary limits, to skip grouping on + running out of internal space like that), I don't think it should need + any further changes for binary printf support to go in. + + On the other hand, support for large sizes of _BitInt in printf (see + the N2858 proposal) *would* require something to be done about such + arbitrary limits (presumably using dynamic allocation in printf again, + for sufficiently large _BitInt arguments only - currently only + floating-point uses dynamic allocation, and, as previously discussed, + that could actually be replaced by bounded allocation given smarter + code). + + Tested with build-many-glibcs.py for aarch64-linux-gnu (GCC mainline). + Also tested natively for x86_64. + + (cherry picked from commit db6c4935fae6005d46af413b32aa92f4f6059dce) + +diff --git a/stdio-common/vfprintf-internal.c b/stdio-common/vfprintf-internal.c +index 3f3d1e148a8e7fda..53d93b2f07ecb261 100644 +--- a/stdio-common/vfprintf-internal.c ++++ b/stdio-common/vfprintf-internal.c +@@ -2154,7 +2154,8 @@ group_number (CHAR_T *front_ptr, CHAR_T *w, CHAR_T *rear_ptr, + copy_rest: + /* No further grouping to be done. Copy the rest of the + number. */ +- memmove (w, s, (front_ptr -s) * sizeof (CHAR_T)); ++ w -= s - front_ptr; ++ memmove (w, front_ptr, (s - front_ptr) * sizeof (CHAR_T)); + break; + } + else if (*grouping != '\0') diff --git a/SOURCES/glibc-upstream-2.34-354.patch b/SOURCES/glibc-upstream-2.34-354.patch new file mode 100644 index 0000000..0ac8827 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-354.patch @@ -0,0 +1,35 @@ +commit 291d4402067760edb7c0f339f9e451787a25e20a +Author: Joseph Myers +Date: Fri Aug 27 17:47:46 2021 +0000 + + Allow #pragma GCC in headers in conformtest + + No "#pragma GCC" pragma allows macro-expansion of its arguments, so no + namespace issues arise from use of such pragmas in installed headers. + Ignore them in conformtest tests of header namespace. + + Tested for x86_64, in conjunction with Paul's patch + + adding use of such pragmas to installed headers shared with gnulib. + + (cherry picked from commit 6090a4a1b32fd7859d0ad5b7e9b240bd5fa04b3f) + +diff --git a/conform/conformtest.py b/conform/conformtest.py +index 4898e16c9fb96503..164cf2917d464aa1 100644 +--- a/conform/conformtest.py ++++ b/conform/conformtest.py +@@ -631,6 +631,14 @@ class HeaderTests(object): + continue + if re.match(r'# [1-9]', line): + continue ++ if line.startswith('#pragma GCC '): ++ # No GCC pragma uses macro expansion, so no ++ # namespace issues arise from such pragmas. (Some ++ # pragmas not in the GCC namespace do macro-expand ++ # their arguments and so could be affected by ++ # macros defined by user code including the ++ # header.) ++ continue + match = re.match(r'#define (.*)', line) + if match: + self.check_token(bad_tokens, match.group(1)) diff --git a/SOURCES/glibc-upstream-2.34-355.patch b/SOURCES/glibc-upstream-2.34-355.patch new file mode 100644 index 0000000..4ba03a0 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-355.patch @@ -0,0 +1,629 @@ +commit 86a701a20479dfbc23540b3143fd5b28660a2447 +Author: Paul Eggert +Date: Tue Sep 21 07:47:45 2021 -0700 + + regex: copy back from Gnulib + + Copy regex-related files back from Gnulib, to fix a problem with + static checking of regex calls noted by Martin Sebor. This merges the + following changes: + + * New macro __attribute_nonnull__ in misc/sys/cdefs.h, for use later + when copying other files back from Gnulib. + + * Use __GNULIB_CDEFS instead of __GLIBC__ when deciding + whether to include bits/wordsize.h etc. + + * Avoid duplicate entries in epsilon closure table. + + * New regex.h macro _REGEX_NELTS to let regexec say that its pmatch + arg should contain nmatch elts. Use that for regexec, instead of + __attr_access (which is incorrect). + + * New regex.h macro _Attr_access_ which is like __attr_access except + portable to non-glibc platforms. + + * Add some DEBUG_ASSERTs to pacify gcc -fanalyzer and to catch + recently-fixed performance bugs if they recur. + + * Add Gnulib-specific stuff to port the dynarray- and lock-using parts + of regex code to non-glibc platforms. + + * Fix glibc bug 11053. + + * Avoid some undefined behavior when popping an empty fail stack. + + (cherry picked from commit 0b5ca7c3e551e5502f3be3b06453324fe8604e82) + +diff --git a/include/intprops.h b/include/intprops.h +index 967e32ea0cbedd56..9d10028a5966c1c6 100644 +--- a/include/intprops.h ++++ b/include/intprops.h +@@ -133,7 +133,8 @@ + operators might not yield numerically correct answers due to + arithmetic overflow. They do not rely on undefined or + implementation-defined behavior. Their implementations are simple +- and straightforward, but they are a bit harder to use than the ++ and straightforward, but they are harder to use and may be less ++ efficient than the INT__WRAPV, INT__OK, and + INT__OVERFLOW macros described below. + + Example usage: +@@ -158,6 +159,9 @@ + must have minimum value MIN and maximum MAX. Unsigned types should + use a zero MIN of the proper type. + ++ Because all arguments are subject to integer promotions, these ++ macros typically do not work on types narrower than 'int'. ++ + These macros are tuned for constant MIN and MAX. For commutative + operations such as A + B, they are also tuned for constant B. */ + +@@ -339,9 +343,15 @@ + arguments should not have side effects. + + The WRAPV macros are not constant expressions. They support only +- +, binary -, and *. Because the WRAPV macros convert the result, +- they report overflow in different circumstances than the OVERFLOW +- macros do. ++ +, binary -, and *. ++ ++ Because the WRAPV macros convert the result, they report overflow ++ in different circumstances than the OVERFLOW macros do. For ++ example, in the typical case with 16-bit 'short' and 32-bit 'int', ++ if A, B and R are all of type 'short' then INT_ADD_OVERFLOW (A, B) ++ returns false because the addition cannot overflow after A and B ++ are converted to 'int', whereas INT_ADD_WRAPV (A, B, &R) returns ++ true or false depending on whether the sum fits into 'short'. + + These macros are tuned for their last input argument being a constant. + +diff --git a/include/regex.h b/include/regex.h +index 24eca2c297bb6043..34fb67d85536bcb9 100644 +--- a/include/regex.h ++++ b/include/regex.h +@@ -37,7 +37,8 @@ extern int __regcomp (regex_t *__preg, const char *__pattern, int __cflags); + libc_hidden_proto (__regcomp) + + extern int __regexec (const regex_t *__preg, const char *__string, +- size_t __nmatch, regmatch_t __pmatch[], int __eflags); ++ size_t __nmatch, regmatch_t __pmatch[__nmatch], ++ int __eflags); + libc_hidden_proto (__regexec) + + extern size_t __regerror (int __errcode, const regex_t *__preg, +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index e0ecd9147ee3ce48..b166f3d209fe361f 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -366,16 +366,18 @@ + #endif + + /* The nonnull function attribute marks pointer parameters that +- must not be NULL. */ +-#ifndef __nonnull ++ must not be NULL. This has the name __nonnull in glibc, ++ and __attribute_nonnull__ in files shared with Gnulib to avoid ++ collision with a different __nonnull in DragonFlyBSD 5.9. */ ++#ifndef __attribute_nonnull__ + # if __GNUC_PREREQ (3,3) || __glibc_has_attribute (__nonnull__) +-# define __nonnull(params) __attribute__ ((__nonnull__ params)) ++# define __attribute_nonnull__(params) __attribute__ ((__nonnull__ params)) + # else +-# define __nonnull(params) ++# define __attribute_nonnull__(params) + # endif +-#elif !defined __GLIBC__ +-# undef __nonnull +-# define __nonnull(params) _GL_ATTRIBUTE_NONNULL (params) ++#endif ++#ifndef __nonnull ++# define __nonnull(params) __attribute_nonnull__ (params) + #endif + + /* The returns_nonnull function attribute marks the return type of the function +@@ -541,9 +543,9 @@ + [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })] + #endif + +-/* The #ifndef lets Gnulib avoid including these on non-glibc +- platforms, where the includes typically do not exist. */ +-#ifdef __GLIBC__ ++/* Gnulib avoids including these, as they don't work on non-glibc or ++ older glibc platforms. */ ++#ifndef __GNULIB_CDEFS + # include + # include + #endif +diff --git a/posix/regcomp.c b/posix/regcomp.c +index d93698ae78447b46..887e5b50684e22f5 100644 +--- a/posix/regcomp.c ++++ b/posix/regcomp.c +@@ -1695,12 +1695,14 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) + reg_errcode_t err; + Idx i; + re_node_set eclosure; +- bool ok; + bool incomplete = false; + err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + ++ /* An epsilon closure includes itself. */ ++ eclosure.elems[eclosure.nelem++] = node; ++ + /* This indicates that we are calculating this node now. + We reference this value to avoid infinite loop. */ + dfa->eclosures[node].nelem = -1; +@@ -1753,10 +1755,6 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) + } + } + +- /* An epsilon closure includes itself. */ +- ok = re_node_set_insert (&eclosure, node); +- if (__glibc_unlikely (! ok)) +- return REG_ESPACE; + if (incomplete && !root) + dfa->eclosures[node].nelem = 0; + else +diff --git a/posix/regex.c b/posix/regex.c +index 7296be0f08da88d8..d32863972c7bcdcf 100644 +--- a/posix/regex.c ++++ b/posix/regex.c +@@ -24,6 +24,7 @@ + + # if __GNUC_PREREQ (4, 6) + # pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" ++# pragma GCC diagnostic ignored "-Wvla" + # endif + # if __GNUC_PREREQ (4, 3) + # pragma GCC diagnostic ignored "-Wold-style-definition" +diff --git a/posix/regex.h b/posix/regex.h +index 14fb1d8364a11d29..adb69768ee520554 100644 +--- a/posix/regex.h ++++ b/posix/regex.h +@@ -522,6 +522,30 @@ typedef struct + + /* Declarations for routines. */ + ++#ifndef _REGEX_NELTS ++# if (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \ ++ && !defined __STDC_NO_VLA__) ++# define _REGEX_NELTS(n) n ++# else ++# define _REGEX_NELTS(n) ++# endif ++#endif ++ ++#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__) ++# pragma GCC diagnostic push ++# pragma GCC diagnostic ignored "-Wvla" ++#endif ++ ++#ifndef _Attr_access_ ++# ifdef __attr_access ++# define _Attr_access_(arg) __attr_access (arg) ++# elif defined __GNUC__ && 10 <= __GNUC__ ++# define _Attr_access_(x) __attribute__ ((__access__ x)) ++# else ++# define _Attr_access_(x) ++# endif ++#endif ++ + #ifdef __USE_GNU + /* Sets the current default syntax to SYNTAX, and return the old syntax. + You can also simply assign to the 're_syntax_options' variable. */ +@@ -537,7 +561,7 @@ extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); + 'regfree'. */ + extern const char *re_compile_pattern (const char *__pattern, size_t __length, + struct re_pattern_buffer *__buffer) +- __attr_access ((__read_only__, 1, 2)); ++ _Attr_access_ ((__read_only__, 1, 2)); + + + /* Compile a fastmap for the compiled pattern in BUFFER; used to +@@ -555,7 +579,7 @@ extern regoff_t re_search (struct re_pattern_buffer *__buffer, + const char *__String, regoff_t __length, + regoff_t __start, regoff_t __range, + struct re_registers *__regs) +- __attr_access ((__read_only__, 2, 3)); ++ _Attr_access_ ((__read_only__, 2, 3)); + + + /* Like 're_search', but search in the concatenation of STRING1 and +@@ -566,8 +590,8 @@ extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, + regoff_t __start, regoff_t __range, + struct re_registers *__regs, + regoff_t __stop) +- __attr_access ((__read_only__, 2, 3)) +- __attr_access ((__read_only__, 4, 5)); ++ _Attr_access_ ((__read_only__, 2, 3)) ++ _Attr_access_ ((__read_only__, 4, 5)); + + + /* Like 're_search', but return how many characters in STRING the regexp +@@ -575,7 +599,7 @@ extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, + extern regoff_t re_match (struct re_pattern_buffer *__buffer, + const char *__String, regoff_t __length, + regoff_t __start, struct re_registers *__regs) +- __attr_access ((__read_only__, 2, 3)); ++ _Attr_access_ ((__read_only__, 2, 3)); + + + /* Relates to 're_match' as 're_search_2' relates to 're_search'. */ +@@ -584,8 +608,8 @@ extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, + const char *__string2, regoff_t __length2, + regoff_t __start, struct re_registers *__regs, + regoff_t __stop) +- __attr_access ((__read_only__, 2, 3)) +- __attr_access ((__read_only__, 4, 5)); ++ _Attr_access_ ((__read_only__, 2, 3)) ++ _Attr_access_ ((__read_only__, 4, 5)); + + + /* Set REGS to hold NUM_REGS registers, storing them in STARTS and +@@ -654,16 +678,19 @@ extern int regcomp (regex_t *_Restrict_ __preg, + + extern int regexec (const regex_t *_Restrict_ __preg, + const char *_Restrict_ __String, size_t __nmatch, +- regmatch_t __pmatch[_Restrict_arr_], +- int __eflags) +- __attr_access ((__write_only__, 4, 3)); ++ regmatch_t __pmatch[_Restrict_arr_ ++ _REGEX_NELTS (__nmatch)], ++ int __eflags); + + extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg, + char *_Restrict_ __errbuf, size_t __errbuf_size) +- __attr_access ((__write_only__, 3, 4)); ++ _Attr_access_ ((__write_only__, 3, 4)); + + extern void regfree (regex_t *__preg); + ++#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__) ++# pragma GCC diagnostic pop ++#endif + + #ifdef __cplusplus + } +diff --git a/posix/regex_internal.c b/posix/regex_internal.c +index 9dd387ef85d64e62..aefcfa2f52e68c6a 100644 +--- a/posix/regex_internal.c ++++ b/posix/regex_internal.c +@@ -1211,6 +1211,10 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src) + + if (__glibc_unlikely (dest->nelem == 0)) + { ++ /* Although we already guaranteed above that dest->alloc != 0 and ++ therefore dest->elems != NULL, add a debug assertion to pacify ++ GCC 11.2.1's -fanalyzer. */ ++ DEBUG_ASSERT (dest->elems); + dest->nelem = src->nelem; + memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); + return REG_NOERROR; +@@ -1286,7 +1290,10 @@ re_node_set_insert (re_node_set *set, Idx elem) + + if (__glibc_unlikely (set->nelem) == 0) + { +- /* We already guaranteed above that set->alloc != 0. */ ++ /* Although we already guaranteed above that set->alloc != 0 and ++ therefore set->elems != NULL, add a debug assertion to pacify ++ GCC 11.2 -fanalyzer. */ ++ DEBUG_ASSERT (set->elems); + set->elems[0] = elem; + ++set->nelem; + return true; +@@ -1314,6 +1321,7 @@ re_node_set_insert (re_node_set *set, Idx elem) + { + for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) + set->elems[idx] = set->elems[idx - 1]; ++ DEBUG_ASSERT (set->elems[idx - 1] < elem); + } + + /* Insert the new element. */ +diff --git a/posix/regex_internal.h b/posix/regex_internal.h +index edcdc07e999694ac..1245e782ffc69086 100644 +--- a/posix/regex_internal.h ++++ b/posix/regex_internal.h +@@ -32,6 +32,10 @@ + #include + #include + ++#ifndef _LIBC ++# include ++#endif ++ + #include + #include + +@@ -49,14 +53,14 @@ + # define lock_fini(lock) ((void) 0) + # define lock_lock(lock) __libc_lock_lock (lock) + # define lock_unlock(lock) __libc_lock_unlock (lock) +-#elif defined GNULIB_LOCK && !defined USE_UNLOCKED_IO ++#elif defined GNULIB_LOCK && !defined GNULIB_REGEX_SINGLE_THREAD + # include "glthread/lock.h" + # define lock_define(name) gl_lock_define (, name) + # define lock_init(lock) glthread_lock_init (&(lock)) + # define lock_fini(lock) glthread_lock_destroy (&(lock)) + # define lock_lock(lock) glthread_lock_lock (&(lock)) + # define lock_unlock(lock) glthread_lock_unlock (&(lock)) +-#elif defined GNULIB_PTHREAD && !defined USE_UNLOCKED_IO ++#elif defined GNULIB_PTHREAD && !defined GNULIB_REGEX_SINGLE_THREAD + # include + # define lock_define(name) pthread_mutex_t name; + # define lock_init(lock) pthread_mutex_init (&(lock), 0) +diff --git a/posix/regexec.c b/posix/regexec.c +index f7b4f9cfc3f030df..83e9aaf8cad956a2 100644 +--- a/posix/regexec.c ++++ b/posix/regexec.c +@@ -59,7 +59,7 @@ static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, + Idx cur_idx, Idx nmatch); + static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, + Idx str_idx, Idx dest_node, Idx nregs, +- regmatch_t *regs, ++ regmatch_t *regs, regmatch_t *prevregs, + re_node_set *eps_via_nodes); + static reg_errcode_t set_regs (const regex_t *preg, + const re_match_context_t *mctx, +@@ -186,11 +186,12 @@ static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len); + REG_NOTBOL is set, then ^ does not match at the beginning of the + string; if REG_NOTEOL is set, then $ does not match at the end. + +- We return 0 if we find a match and REG_NOMATCH if not. */ ++ Return 0 if a match is found, REG_NOMATCH if not, REG_BADPAT if ++ EFLAGS is invalid. */ + + int + regexec (const regex_t *__restrict preg, const char *__restrict string, +- size_t nmatch, regmatch_t pmatch[], int eflags) ++ size_t nmatch, regmatch_t pmatch[_REGEX_NELTS (nmatch)], int eflags) + { + reg_errcode_t err; + Idx start, length; +@@ -234,7 +235,7 @@ int + attribute_compat_text_section + __compat_regexec (const regex_t *__restrict preg, + const char *__restrict string, size_t nmatch, +- regmatch_t pmatch[], int eflags) ++ regmatch_t pmatch[_REGEX_NELTS (nmatch)], int eflags) + { + return regexec (preg, string, nmatch, pmatch, + eflags & (REG_NOTBOL | REG_NOTEOL)); +@@ -269,8 +270,8 @@ compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); + strings.) + + On success, re_match* functions return the length of the match, re_search* +- return the position of the start of the match. Return value -1 means no +- match was found and -2 indicates an internal error. */ ++ return the position of the start of the match. They return -1 on ++ match failure, -2 on error. */ + + regoff_t + re_match (struct re_pattern_buffer *bufp, const char *string, Idx length, +@@ -1206,27 +1207,30 @@ check_halt_state_context (const re_match_context_t *mctx, + /* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA + corresponding to the DFA). + Return the destination node, and update EPS_VIA_NODES; +- return -1 in case of errors. */ ++ return -1 on match failure, -2 on error. */ + + static Idx + proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, ++ regmatch_t *prevregs, + Idx *pidx, Idx node, re_node_set *eps_via_nodes, + struct re_fail_stack_t *fs) + { + const re_dfa_t *const dfa = mctx->dfa; +- Idx i; +- bool ok; + if (IS_EPSILON_NODE (dfa->nodes[node].type)) + { + re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; + re_node_set *edests = &dfa->edests[node]; +- Idx dest_node; +- ok = re_node_set_insert (eps_via_nodes, node); +- if (__glibc_unlikely (! ok)) +- return -2; +- /* Pick up a valid destination, or return -1 if none +- is found. */ +- for (dest_node = -1, i = 0; i < edests->nelem; ++i) ++ ++ if (! re_node_set_contains (eps_via_nodes, node)) ++ { ++ bool ok = re_node_set_insert (eps_via_nodes, node); ++ if (__glibc_unlikely (! ok)) ++ return -2; ++ } ++ ++ /* Pick a valid destination, or return -1 if none is found. */ ++ Idx dest_node = -1; ++ for (Idx i = 0; i < edests->nelem; i++) + { + Idx candidate = edests->elems[i]; + if (!re_node_set_contains (cur_nodes, candidate)) +@@ -1244,7 +1248,7 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, + /* Otherwise, push the second epsilon-transition on the fail stack. */ + else if (fs != NULL + && push_fail_stack (fs, *pidx, candidate, nregs, regs, +- eps_via_nodes)) ++ prevregs, eps_via_nodes)) + return -2; + + /* We know we are going to exit. */ +@@ -1288,7 +1292,7 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, + if (naccepted == 0) + { + Idx dest_node; +- ok = re_node_set_insert (eps_via_nodes, node); ++ bool ok = re_node_set_insert (eps_via_nodes, node); + if (__glibc_unlikely (! ok)) + return -2; + dest_node = dfa->edests[node].elems[0]; +@@ -1317,7 +1321,8 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, + static reg_errcode_t + __attribute_warn_unused_result__ + push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node, +- Idx nregs, regmatch_t *regs, re_node_set *eps_via_nodes) ++ Idx nregs, regmatch_t *regs, regmatch_t *prevregs, ++ re_node_set *eps_via_nodes) + { + reg_errcode_t err; + Idx num = fs->num++; +@@ -1333,25 +1338,30 @@ push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node, + } + fs->stack[num].idx = str_idx; + fs->stack[num].node = dest_node; +- fs->stack[num].regs = re_malloc (regmatch_t, nregs); ++ fs->stack[num].regs = re_malloc (regmatch_t, 2 * nregs); + if (fs->stack[num].regs == NULL) + return REG_ESPACE; + memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); ++ memcpy (fs->stack[num].regs + nregs, prevregs, sizeof (regmatch_t) * nregs); + err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); + return err; + } + + static Idx + pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs, +- regmatch_t *regs, re_node_set *eps_via_nodes) ++ regmatch_t *regs, regmatch_t *prevregs, ++ re_node_set *eps_via_nodes) + { ++ if (fs == NULL || fs->num == 0) ++ return -1; + Idx num = --fs->num; +- DEBUG_ASSERT (num >= 0); + *pidx = fs->stack[num].idx; + memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); ++ memcpy (prevregs, fs->stack[num].regs + nregs, sizeof (regmatch_t) * nregs); + re_node_set_free (eps_via_nodes); + re_free (fs->stack[num].regs); + *eps_via_nodes = fs->stack[num].eps_via_nodes; ++ DEBUG_ASSERT (0 <= fs->stack[num].node); + return fs->stack[num].node; + } + +@@ -1407,33 +1417,32 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, + { + update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); + +- if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) ++ if ((idx == pmatch[0].rm_eo && cur_node == mctx->last_node) ++ || (fs && re_node_set_contains (&eps_via_nodes, cur_node))) + { + Idx reg_idx; ++ cur_node = -1; + if (fs) + { + for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) + if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) +- break; +- if (reg_idx == nmatch) +- { +- re_node_set_free (&eps_via_nodes); +- regmatch_list_free (&prev_match); +- return free_fail_stack_return (fs); +- } +- cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, +- &eps_via_nodes); ++ { ++ cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, ++ prev_idx_match, &eps_via_nodes); ++ break; ++ } + } +- else ++ if (cur_node < 0) + { + re_node_set_free (&eps_via_nodes); + regmatch_list_free (&prev_match); +- return REG_NOERROR; ++ return free_fail_stack_return (fs); + } + } + + /* Proceed to next node. */ +- cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node, ++ cur_node = proceed_next_node (mctx, nmatch, pmatch, prev_idx_match, ++ &idx, cur_node, + &eps_via_nodes, fs); + + if (__glibc_unlikely (cur_node < 0)) +@@ -1445,13 +1454,13 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, + free_fail_stack_return (fs); + return REG_ESPACE; + } +- if (fs) +- cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, +- &eps_via_nodes); +- else ++ cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, ++ prev_idx_match, &eps_via_nodes); ++ if (cur_node < 0) + { + re_node_set_free (&eps_via_nodes); + regmatch_list_free (&prev_match); ++ free_fail_stack_return (fs); + return REG_NOMATCH; + } + } +@@ -1495,10 +1504,10 @@ update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, + } + else if (type == OP_CLOSE_SUBEXP) + { ++ /* We are at the last node of this sub expression. */ + Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; + if (reg_num < nmatch) + { +- /* We are at the last node of this sub expression. */ + if (pmatch[reg_num].rm_so < cur_idx) + { + pmatch[reg_num].rm_eo = cur_idx; +@@ -2195,6 +2204,7 @@ sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, + + /* Return the next state to which the current state STATE will transit by + accepting the current input byte, and update STATE_LOG if necessary. ++ Return NULL on failure. + If STATE can accept a multibyte char/collating element/back reference + update the destination of STATE_LOG. */ + +@@ -2395,7 +2405,7 @@ check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, + + #if 0 + /* Return the next state to which the current state STATE will transit by +- accepting the current input byte. */ ++ accepting the current input byte. Return NULL on failure. */ + + static re_dfastate_t * + transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, +@@ -2817,7 +2827,8 @@ find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, + /* Check whether the node TOP_NODE at TOP_STR can arrive to the node + LAST_NODE at LAST_STR. We record the path onto PATH since it will be + heavily reused. +- Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ ++ Return REG_NOERROR if it can arrive, REG_NOMATCH if it cannot, ++ REG_ESPACE if memory is exhausted. */ + + static reg_errcode_t + __attribute_warn_unused_result__ +@@ -3433,7 +3444,8 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) + /* Group all nodes belonging to STATE into several destinations. + Then for all destinations, set the nodes belonging to the destination + to DESTS_NODE[i] and set the characters accepted by the destination +- to DEST_CH[i]. This function return the number of destinations. */ ++ to DEST_CH[i]. Return the number of destinations if successful, ++ -1 on internal error. */ + + static Idx + group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, +@@ -4211,7 +4223,8 @@ match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx) + } + + /* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches +- at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */ ++ at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. ++ Return the new entry if successful, NULL if memory is exhausted. */ + + static re_sub_match_last_t * + match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx) diff --git a/SOURCES/glibc-upstream-2.34-356.patch b/SOURCES/glibc-upstream-2.34-356.patch new file mode 100644 index 0000000..fcaa4ad --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-356.patch @@ -0,0 +1,30 @@ +commit fa5044f1e38f4f6515253449b6ca77fd14f53b8e +Author: Paul Eggert +Date: Wed Nov 24 14:16:09 2021 -0800 + + regex: fix buffer read overrun in search [BZ#28470] + + Problem reported by Benno Schulenberg in: + https://lists.gnu.org/r/bug-gnulib/2021-10/msg00035.html + * posix/regexec.c (re_search_internal): Use better bounds check. + + (cherry picked from commit c52ef24829f95a819965214eeae28e3289a91a61) + +diff --git a/posix/regexec.c b/posix/regexec.c +index 83e9aaf8cad956a2..6aeba3c0b4da23cc 100644 +--- a/posix/regexec.c ++++ b/posix/regexec.c +@@ -758,10 +758,9 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, + + offset = match_first - mctx.input.raw_mbs_idx; + } +- /* If MATCH_FIRST is out of the buffer, leave it as '\0'. +- Note that MATCH_FIRST must not be smaller than 0. */ +- ch = (match_first >= length +- ? 0 : re_string_byte_at (&mctx.input, offset)); ++ /* Use buffer byte if OFFSET is in buffer, otherwise '\0'. */ ++ ch = (offset < mctx.input.valid_len ++ ? re_string_byte_at (&mctx.input, offset) : 0); + if (fastmap[ch]) + break; + match_first += incr; diff --git a/SOURCES/glibc-upstream-2.34-357.patch b/SOURCES/glibc-upstream-2.34-357.patch new file mode 100644 index 0000000..732e8af --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-357.patch @@ -0,0 +1,203 @@ +commit 06afa5e09fbd984ed45ae6fc6ca050d544aba780 +Author: Adhemerval Zanella +Date: Wed Aug 25 11:17:06 2021 -0300 + + io: Fix ftw internal realloc buffer (BZ #28126) + + The 106ff08526d3ca did not take in consideration the buffer might be + reallocated if the total path is larger than PATH_MAX. The realloc + uses 'dirbuf', where 'dirstreams' is the allocated buffer. + + Checked on x86_64-linux-gnu. + + Reviewed-by: H.J. Lu + (cherry picked from commit 1836bb2ebf62bd9a3588f2ed2d851c8ae810097a) + +diff --git a/io/Makefile b/io/Makefile +index 01968b81042e01e4..5284a1282dd07e3d 100644 +--- a/io/Makefile ++++ b/io/Makefile +@@ -79,6 +79,7 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ + tst-futimens \ + tst-utimensat \ + tst-closefrom \ ++ tst-ftw-bz28126 + + tests-time64 := \ + tst-fcntl-time64 \ +diff --git a/io/ftw.c b/io/ftw.c +index ce1c6a14a306152a..cf08d9f101657df0 100644 +--- a/io/ftw.c ++++ b/io/ftw.c +@@ -204,6 +204,20 @@ struct ftw_data + void *known_objects; + }; + ++static bool ++ftw_allocate (struct ftw_data *data, size_t newsize) ++{ ++ void *newp = realloc (data->dirstreams, data->maxdir ++ * sizeof (struct dir_data *) ++ + newsize); ++ if (newp == NULL) ++ return false; ++ data->dirstreams = newp; ++ data->dirbufsize = newsize; ++ data->dirbuf = (char *) data->dirstreams ++ + data->maxdir * sizeof (struct dir_data *); ++ return true; ++} + + /* Internally we use the FTW_* constants used for `nftw'. When invoked + as `ftw', map each flag to the subset of values used by `ftw'. */ +@@ -389,17 +403,9 @@ process_entry (struct ftw_data *data, struct dir_data *dir, const char *name, + return 0; + + new_buflen = data->ftw.base + namlen + 2; +- if (data->dirbufsize < new_buflen) +- { +- /* Enlarge the buffer. */ +- char *newp; +- +- data->dirbufsize = 2 * new_buflen; +- newp = (char *) realloc (data->dirbuf, data->dirbufsize); +- if (newp == NULL) +- return -1; +- data->dirbuf = newp; +- } ++ if (data->dirbufsize < new_buflen ++ && !ftw_allocate (data, 2 * new_buflen)) ++ return -1; + + *((char *) __mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0'; + +@@ -629,7 +635,7 @@ __attribute ((noinline)) + ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, + int flags) + { +- struct ftw_data data; ++ struct ftw_data data = { .dirstreams = NULL }; + struct STRUCT_STAT st; + int result = 0; + int save_err; +@@ -647,16 +653,9 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, + data.maxdir = descriptors < 1 ? 1 : descriptors; + data.actdir = 0; + /* PATH_MAX is always defined when we get here. */ +- data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX); +- data.dirstreams = malloc (data.maxdir * sizeof (struct dir_data *) +- + data.dirbufsize); +- if (data.dirstreams == NULL) ++ if (!ftw_allocate (&data, MAX (2 * strlen (dir), PATH_MAX))) + return -1; +- + memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *)); +- +- data.dirbuf = (char *) data.dirstreams +- + data.maxdir * sizeof (struct dir_data *); + cp = __stpcpy (data.dirbuf, dir); + /* Strip trailing slashes. */ + while (cp > data.dirbuf + 1 && cp[-1] == '/') +diff --git a/io/tst-ftw-bz28126.c b/io/tst-ftw-bz28126.c +new file mode 100644 +index 0000000000000000..94044ab9d1d0275b +--- /dev/null ++++ b/io/tst-ftw-bz28126.c +@@ -0,0 +1,97 @@ ++/* Check if internal buffer reallocation work for large paths (BZ #28126) ++ Copyright (C) 2021 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++my_func (const char *file, const struct stat *sb, int flag) ++{ ++ return 0; ++} ++ ++static const char folder[NAME_MAX] = { [0 ... 253] = 'a', [254] = '\0' }; ++ ++#define NSUBFOLDERS 16 ++static int nsubfolders; ++ ++static void ++do_cleanup (void) ++{ ++ xchdir (".."); ++ for (int i = 0; i < nsubfolders; i++) ++ { ++ remove (folder); ++ xchdir (".."); ++ } ++ remove (folder); ++} ++#define CLEANUP_HANDLER do_cleanup ++ ++static void ++check_mkdir (const char *path) ++{ ++ int r = mkdir (path, 0777); ++ /* Some filesystem such as overlayfs does not support larger path required ++ to trigger the internal buffer reallocation. */ ++ if (r != 0) ++ { ++ if (errno == ENAMETOOLONG) ++ FAIL_UNSUPPORTED ("the filesystem does not support the required" ++ "large path"); ++ else ++ FAIL_EXIT1 ("mkdir (\"%s\", 0%o): %m", folder, 0777); ++ } ++} ++ ++static int ++do_test (void) ++{ ++ char *tempdir = support_create_temp_directory ("tst-bz28126"); ++ ++ /* Create path with various subfolders to force an internal buffer ++ reallocation within ntfw. */ ++ char *path = xasprintf ("%s/%s", tempdir, folder); ++ check_mkdir (path); ++ xchdir (path); ++ free (path); ++ for (int i = 0; i < NSUBFOLDERS - 1; i++) ++ { ++ check_mkdir (folder); ++ xchdir (folder); ++ nsubfolders++; ++ } ++ ++ TEST_COMPARE (ftw (tempdir, my_func, 20), 0); ++ ++ free (tempdir); ++ ++ do_cleanup (); ++ ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-upstream-2.34-358.patch b/SOURCES/glibc-upstream-2.34-358.patch new file mode 100644 index 0000000..fb4f91e --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-358.patch @@ -0,0 +1,25 @@ +commit deea6ab1bcb2696be514e579f3263c234ecc1683 +Author: Martin Sebor +Date: Tue Jan 25 17:39:02 2022 -0700 + + io: Fix use-after-free in ftw [BZ #26779] + + Reviewed-by: Carlos O'Donell + (cherry picked from commit ee52ab25ba875f458981fce22c54e3c04c7a17d3) + +diff --git a/io/ftw.c b/io/ftw.c +index cf08d9f101657df0..91a4e8e6de151ca1 100644 +--- a/io/ftw.c ++++ b/io/ftw.c +@@ -324,8 +324,9 @@ open_dir_stream (int *dfdp, struct ftw_data *data, struct dir_data *dirp) + buf[actsize++] = '\0'; + + /* Shrink the buffer to what we actually need. */ +- data->dirstreams[data->actdir]->content = realloc (buf, actsize); +- if (data->dirstreams[data->actdir]->content == NULL) ++ void *content = realloc (buf, actsize); ++ data->dirstreams[data->actdir]->content = content; ++ if (content == NULL) + { + int save_err = errno; + free (buf); diff --git a/SOURCES/glibc-upstream-2.34-359.patch b/SOURCES/glibc-upstream-2.34-359.patch new file mode 100644 index 0000000..25fdf9f --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-359.patch @@ -0,0 +1,221 @@ +commit d57cdc1b5a52b5468b9259c0b9a215e22a1fa1f6 +Author: Florian Weimer +Date: Tue Nov 8 14:15:02 2022 +0100 + + Linux: Support __IPC_64 in sysvctl *ctl command arguments (bug 29771) + + Old applications pass __IPC_64 as part of the command argument because + old glibc did not check for unknown commands, and passed through the + arguments directly to the kernel, without adding __IPC_64. + Applications need to continue doing that for old glibc compatibility, + so this commit enables this approach in current glibc. + + For msgctl and shmctl, if no translation is required, make + direct system calls, as we did before the time64 changes. If + translation is required, mask __IPC_64 from the command argument. + + For semctl, the union-in-vararg argument handling means that + translation is needed on all architectures. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 22a46dee24351fd5f4f188ad80554cad79c82524) + +diff --git a/sysdeps/unix/sysv/linux/ipc_priv.h b/sysdeps/unix/sysv/linux/ipc_priv.h +index f9852367a466cea9..d4efb9f3483daa9f 100644 +--- a/sysdeps/unix/sysv/linux/ipc_priv.h ++++ b/sysdeps/unix/sysv/linux/ipc_priv.h +@@ -63,4 +63,10 @@ struct __old_ipc_perm + # define __IPC_TIME64 0 + #endif + ++#if __IPC_TIME64 || defined __ASSUME_SYSVIPC_BROKEN_MODE_T ++# define IPC_CTL_NEED_TRANSLATION 1 ++#else ++# define IPC_CTL_NEED_TRANSLATION 0 ++#endif ++ + #include +diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c +index 9f38c06d53936390..ba7b94c22d17bc7f 100644 +--- a/sysdeps/unix/sysv/linux/msgctl.c ++++ b/sysdeps/unix/sysv/linux/msgctl.c +@@ -86,11 +86,19 @@ msgctl_syscall (int msqid, int cmd, msgctl_arg_t *buf) + int + __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf) + { +-#if __IPC_TIME64 ++#if IPC_CTL_NEED_TRANSLATION ++# if __IPC_TIME64 + struct kernel_msqid64_ds ksemid, *arg = NULL; +-#else ++# else + msgctl_arg_t *arg; +-#endif ++# endif ++ ++ /* Some applications pass the __IPC_64 flag in cmd, to invoke ++ previously unsupported commands back when there was no EINVAL ++ error checking in glibc. Mask the flag for the switch statements ++ below. msgctl_syscall adds back the __IPC_64 flag for the actual ++ system call. */ ++ cmd &= ~__IPC_64; + + switch (cmd) + { +@@ -102,19 +110,19 @@ __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf) + case IPC_STAT: + case MSG_STAT: + case MSG_STAT_ANY: +-#if __IPC_TIME64 ++# if __IPC_TIME64 + if (buf != NULL) + { + msqid64_to_kmsqid64 (buf, &ksemid); + arg = &ksemid; + } +-# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T ++# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T + if (cmd == IPC_SET) + arg->msg_perm.mode *= 0x10000U; +-# endif +-#else ++# endif ++# else + arg = buf; +-#endif ++# endif + break; + + case IPC_INFO: +@@ -138,21 +146,25 @@ __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf) + case IPC_STAT: + case MSG_STAT: + case MSG_STAT_ANY: +-#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T ++# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T + arg->msg_perm.mode >>= 16; +-#else ++# else + /* Old Linux kernel versions might not clear the mode padding. */ + if (sizeof ((struct msqid_ds){0}.msg_perm.mode) + != sizeof (__kernel_mode_t)) + arg->msg_perm.mode &= 0xFFFF; +-#endif ++# endif + +-#if __IPC_TIME64 ++# if __IPC_TIME64 + kmsqid64_to_msqid64 (arg, buf); +-#endif ++# endif + } + + return ret; ++ ++#else /* !IPC_CTL_NEED_TRANSLATION */ ++ return msgctl_syscall (msqid, cmd, buf); ++#endif + } + #if __TIMESIZE != 64 + libc_hidden_def (__msgctl64) +diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c +index bb2690d30f80bb22..97fa411547fdd81e 100644 +--- a/sysdeps/unix/sysv/linux/semctl.c ++++ b/sysdeps/unix/sysv/linux/semctl.c +@@ -141,6 +141,13 @@ __semctl64 (int semid, int semnum, int cmd, ...) + union semun64 arg64 = { 0 }; + va_list ap; + ++ /* Some applications pass the __IPC_64 flag in cmd, to invoke ++ previously unsupported commands back when there was no EINVAL ++ error checking in glibc. Mask the flag for the switch statements ++ below. semctl_syscall adds back the __IPC_64 flag for the actual ++ system call. */ ++ cmd &= ~__IPC_64; ++ + /* Get the argument only if required. */ + switch (cmd) + { +diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c +index f52018bfae4b3364..c44cbd6e4ac890a5 100644 +--- a/sysdeps/unix/sysv/linux/shmctl.c ++++ b/sysdeps/unix/sysv/linux/shmctl.c +@@ -86,11 +86,19 @@ shmctl_syscall (int shmid, int cmd, shmctl_arg_t *buf) + int + __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf) + { +-#if __IPC_TIME64 ++#if IPC_CTL_NEED_TRANSLATION ++# if __IPC_TIME64 + struct kernel_shmid64_ds kshmid, *arg = NULL; +-#else ++# else + shmctl_arg_t *arg; +-#endif ++# endif ++ ++ /* Some applications pass the __IPC_64 flag in cmd, to invoke ++ previously unsupported commands back when there was no EINVAL ++ error checking in glibc. Mask the flag for the switch statements ++ below. shmctl_syscall adds back the __IPC_64 flag for the actual ++ system call. */ ++ cmd &= ~__IPC_64; + + switch (cmd) + { +@@ -104,19 +112,19 @@ __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf) + case IPC_STAT: + case SHM_STAT: + case SHM_STAT_ANY: +-#if __IPC_TIME64 ++# if __IPC_TIME64 + if (buf != NULL) + { + shmid64_to_kshmid64 (buf, &kshmid); + arg = &kshmid; + } +-# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T ++# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T + if (cmd == IPC_SET) + arg->shm_perm.mode *= 0x10000U; +-# endif +-#else ++# endif ++# else + arg = buf; +-#endif ++# endif + break; + + case IPC_INFO: +@@ -141,21 +149,25 @@ __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf) + case IPC_STAT: + case SHM_STAT: + case SHM_STAT_ANY: +-#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T ++# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T + arg->shm_perm.mode >>= 16; +-#else ++# else + /* Old Linux kernel versions might not clear the mode padding. */ + if (sizeof ((struct shmid_ds){0}.shm_perm.mode) + != sizeof (__kernel_mode_t)) + arg->shm_perm.mode &= 0xFFFF; +-#endif ++# endif + +-#if __IPC_TIME64 ++# if __IPC_TIME64 + kshmid64_to_shmid64 (arg, buf); +-#endif ++# endif + } + + return ret; ++ ++#else /* !IPC_CTL_NEED_TRANSLATION */ ++ return shmctl_syscall (shmid, cmd, buf); ++#endif + } + #if __TIMESIZE != 64 + libc_hidden_def (__shmctl64) diff --git a/SOURCES/glibc-upstream-2.34-361.patch b/SOURCES/glibc-upstream-2.34-361.patch new file mode 100644 index 0000000..b6b86ca --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-361.patch @@ -0,0 +1,46 @@ +commit 691f70b84a1284f35c8cf9fbf3ef3b1cec41c234 +Author: Vladislav Khmelevsky +Date: Thu Nov 17 12:47:29 2022 +0400 + + elf: Fix rtld-audit trampoline for aarch64 + + This patch fixes two problems with audit: + + 1. The DL_OFFSET_RV_VPCS offset was mixed up with DL_OFFSET_RG_VPCS, + resulting in x2 register value nulling in RG structure. + + 2. We need to preserve the x8 register before function call, but + don't have to save it's new value and restore it before return. + + Anyway the final restore was using OFFSET_RV instead of OFFSET_RG value + which is wrong (althoug doesn't affect anything). + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit eb4181e9f4a512de37dad4ba623c921671584dea) + +diff --git a/sysdeps/aarch64/dl-trampoline.S b/sysdeps/aarch64/dl-trampoline.S +index 457570e7df5148c0..b84c53d1a544c1b1 100644 +--- a/sysdeps/aarch64/dl-trampoline.S ++++ b/sysdeps/aarch64/dl-trampoline.S +@@ -298,12 +298,11 @@ _dl_runtime_profile: + stp x2, x3, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*1] + stp x4, x5, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*2] + stp x6, x7, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*3] +- str x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4] + stp q0, q1, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0] + stp q2, q3, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1] + stp q4, q5, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*2] + stp q6, q7, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*3] +- str xzr, [X29, #OFFSET_RV + DL_OFFSET_RG_VPCS] ++ str xzr, [X29, #OFFSET_RV + DL_OFFSET_RV_VPCS] + + /* Setup call to pltexit */ + ldp x0, x1, [x29, #OFFSET_SAVED_CALL_X0] +@@ -315,7 +314,6 @@ _dl_runtime_profile: + ldp x2, x3, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*1] + ldp x4, x5, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*2] + ldp x6, x7, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*3] +- ldr x8, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*4] + ldp q0, q1, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0] + ldp q2, q3, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1] + ldp q4, q5, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*2] diff --git a/SOURCES/glibc-upstream-2.34-362.patch b/SOURCES/glibc-upstream-2.34-362.patch new file mode 100644 index 0000000..d7b4767 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-362.patch @@ -0,0 +1,128 @@ +commit e3255e7d2188d1731aad83ad0dc147513560aa1e +Author: Noah Goldstein +Date: Tue Sep 20 17:58:04 2022 -0700 + + x86: Fix wcsnlen-avx2 page cross length comparison [BZ #29591] + + Previous implementation was adjusting length (rsi) to match + bytes (eax), but since there is no bound to length this can cause + overflow. + + Fix is to just convert the byte-count (eax) to length by dividing by + sizeof (wchar_t) before the comparison. + + Full check passes on x86-64 and build succeeds w/ and w/o multiarch. + + (cherry picked from commit b0969fa53a28b4ab2159806bf6c99a98999502ee) + +diff --git a/string/test-strnlen.c b/string/test-strnlen.c +index bb5d9b5f04fa6586..eac84cd17526d5d9 100644 +--- a/string/test-strnlen.c ++++ b/string/test-strnlen.c +@@ -75,7 +75,7 @@ do_test (size_t align, size_t len, size_t maxlen, int max_char) + { + size_t i; + +- align &= 63; ++ align &= (getpagesize () / sizeof (CHAR) - 1); + if ((align + len) * sizeof (CHAR) >= page_size) + return; + +@@ -92,36 +92,50 @@ do_test (size_t align, size_t len, size_t maxlen, int max_char) + static void + do_overflow_tests (void) + { +- size_t i, j, len; ++ size_t i, j, al_idx, repeats, len; + const size_t one = 1; + uintptr_t buf_addr = (uintptr_t) buf1; ++ const size_t alignments[] = { 0, 1, 7, 9, 31, 33, 63, 65, 95, 97, 127, 129 }; + +- for (i = 0; i < 750; ++i) ++ for (al_idx = 0; al_idx < sizeof (alignments) / sizeof (alignments[0]); ++ al_idx++) + { +- do_test (0, i, SIZE_MAX - i, BIG_CHAR); +- do_test (0, i, i - buf_addr, BIG_CHAR); +- do_test (0, i, -buf_addr - i, BIG_CHAR); +- do_test (0, i, SIZE_MAX - buf_addr - i, BIG_CHAR); +- do_test (0, i, SIZE_MAX - buf_addr + i, BIG_CHAR); +- +- len = 0; +- for (j = 8 * sizeof(size_t) - 1; j ; --j) +- { +- len |= one << j; +- do_test (0, i, len - i, BIG_CHAR); +- do_test (0, i, len + i, BIG_CHAR); +- do_test (0, i, len - buf_addr - i, BIG_CHAR); +- do_test (0, i, len - buf_addr + i, BIG_CHAR); +- +- do_test (0, i, ~len - i, BIG_CHAR); +- do_test (0, i, ~len + i, BIG_CHAR); +- do_test (0, i, ~len - buf_addr - i, BIG_CHAR); +- do_test (0, i, ~len - buf_addr + i, BIG_CHAR); +- +- do_test (0, i, -buf_addr, BIG_CHAR); +- do_test (0, i, j - buf_addr, BIG_CHAR); +- do_test (0, i, -buf_addr - j, BIG_CHAR); +- } ++ for (repeats = 0; repeats < 2; ++repeats) ++ { ++ size_t align = repeats ? (getpagesize () - alignments[al_idx]) ++ : alignments[al_idx]; ++ align /= sizeof (CHAR); ++ for (i = 0; i < 750; ++i) ++ { ++ do_test (align, i, SIZE_MAX, BIG_CHAR); ++ ++ do_test (align, i, SIZE_MAX - i, BIG_CHAR); ++ do_test (align, i, i - buf_addr, BIG_CHAR); ++ do_test (align, i, -buf_addr - i, BIG_CHAR); ++ do_test (align, i, SIZE_MAX - buf_addr - i, BIG_CHAR); ++ do_test (align, i, SIZE_MAX - buf_addr + i, BIG_CHAR); ++ ++ len = 0; ++ for (j = 8 * sizeof (size_t) - 1; j; --j) ++ { ++ len |= one << j; ++ do_test (align, i, len, BIG_CHAR); ++ do_test (align, i, len - i, BIG_CHAR); ++ do_test (align, i, len + i, BIG_CHAR); ++ do_test (align, i, len - buf_addr - i, BIG_CHAR); ++ do_test (align, i, len - buf_addr + i, BIG_CHAR); ++ ++ do_test (align, i, ~len - i, BIG_CHAR); ++ do_test (align, i, ~len + i, BIG_CHAR); ++ do_test (align, i, ~len - buf_addr - i, BIG_CHAR); ++ do_test (align, i, ~len - buf_addr + i, BIG_CHAR); ++ ++ do_test (align, i, -buf_addr, BIG_CHAR); ++ do_test (align, i, j - buf_addr, BIG_CHAR); ++ do_test (align, i, -buf_addr - j, BIG_CHAR); ++ } ++ } ++ } + } + } + +diff --git a/sysdeps/x86_64/multiarch/strlen-avx2.S b/sysdeps/x86_64/multiarch/strlen-avx2.S +index b282a75613bf52ab..4d7d68396bcd4049 100644 +--- a/sysdeps/x86_64/multiarch/strlen-avx2.S ++++ b/sysdeps/x86_64/multiarch/strlen-avx2.S +@@ -542,14 +542,11 @@ L(return_vzeroupper): + L(cross_page_less_vec): + tzcntl %eax, %eax + # ifdef USE_AS_WCSLEN +- /* NB: Multiply length by 4 to get byte count. */ +- sall $2, %esi ++ /* NB: Divide by 4 to convert from byte-count to length. */ ++ shrl $2, %eax + # endif + cmpq %rax, %rsi + cmovb %esi, %eax +-# ifdef USE_AS_WCSLEN +- shrl $2, %eax +-# endif + VZEROUPPER_RETURN + # endif + diff --git a/SOURCES/glibc-upstream-2.34-363.patch b/SOURCES/glibc-upstream-2.34-363.patch new file mode 100644 index 0000000..4428f12 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-363.patch @@ -0,0 +1,26 @@ +commit 309c4708aca762f57263a66e5bea926fdbfd82eb +Author: Adhemerval Zanella +Date: Fri Mar 25 11:16:49 2022 -0300 + + elf: Fix wrong fscanf usage on tst-pldd + + To take in consideration the extra '\0'. + + Checked on x86_64-linux-gnu. + + (cherry picked from commit b2cd93fce666fdc8c9a5c64af2741a8a6940ac99) + +diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c +index 210ca4d24b8338ab..72b7a99b369a105d 100644 +--- a/elf/tst-pldd.c ++++ b/elf/tst-pldd.c +@@ -113,7 +113,8 @@ do_test (void) + TEST_VERIFY (out != NULL); + + /* First line is in the form of : */ +- TEST_COMPARE (fscanf (out, "%u: " STRINPUT (512), &pid, buffer), 2); ++ TEST_COMPARE (fscanf (out, "%u: " STRINPUT (sizeof (buffer) - 1), &pid, ++ buffer), 2); + + TEST_COMPARE (pid, *target_pid_ptr); + TEST_COMPARE (strcmp (basename (buffer), "tst-pldd"), 0); diff --git a/SOURCES/glibc-upstream-2.34-364.patch b/SOURCES/glibc-upstream-2.34-364.patch new file mode 100644 index 0000000..cf76f9b --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-364.patch @@ -0,0 +1,362 @@ +commit 42b9d7def8fd7d26f1926cbc801923aa2c8a386a +Author: DJ Delorie +Date: Mon Mar 28 23:53:33 2022 -0400 + + Allow for unpriviledged nested containers + + If the build itself is run in a container, we may not be able to + fully set up a nested container for test-container testing. + Notably is the mounting of /proc, since it's critical that it + be mounted from within the same PID namespace as its users, and + thus cannot be bind mounted from outside the container like other + mounts. + + This patch defaults to using the parent's PID namespace instead of + creating a new one, as this is more likely to be allowed. + + If the test needs an isolated PID namespace, it should add the "pidns" + command to its init script. + + Reviewed-by: Carlos O'Donell + (cherry picked from commit 2fe64148a81f0d78050c302f34a6853d21f7cae4) + +diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c +index 72b7a99b369a105d..6e4174cbf95b15c0 100644 +--- a/elf/tst-pldd.c ++++ b/elf/tst-pldd.c +@@ -85,6 +85,8 @@ in_str_list (const char *libname, const char *const strlist[]) + static int + do_test (void) + { ++ support_need_proc ("needs /proc/sys/kernel/yama/ptrace_scope and /proc/$child"); ++ + /* Check if our subprocess can be debugged with ptrace. */ + { + int ptrace_scope = support_ptrace_scope (); +diff --git a/nptl/tst-pthread-getattr.c b/nptl/tst-pthread-getattr.c +index 5f60cf9722b77a1a..6128402b2673c010 100644 +--- a/nptl/tst-pthread-getattr.c ++++ b/nptl/tst-pthread-getattr.c +@@ -28,6 +28,8 @@ + #include + #include + ++#include ++ + /* There is an obscure bug in the kernel due to which RLIMIT_STACK is sometimes + returned as unlimited when it is not, which may cause this test to fail. + There is also the other case where RLIMIT_STACK is intentionally set as +@@ -153,6 +155,8 @@ check_stack_top (void) + static int + do_test (void) + { ++ support_need_proc ("Reads /proc/self/maps to get stack size."); ++ + pagesize = sysconf (_SC_PAGESIZE); + return check_stack_top (); + } +diff --git a/nss/tst-reload2.c b/nss/tst-reload2.c +index 5ecb032e9fcd6868..a494145dd679099d 100644 +--- a/nss/tst-reload2.c ++++ b/nss/tst-reload2.c +@@ -95,6 +95,8 @@ do_test (void) + char buf1[PATH_MAX]; + char buf2[PATH_MAX]; + ++ support_need_proc ("Our xmkdirp fails if we can't map our uid, which requires /proc."); ++ + sprintf (buf1, "/subdir%s", support_slibdir_prefix); + xmkdirp (buf1, 0777); + +diff --git a/support/Makefile b/support/Makefile +index 6a5fc9faf2ca2e2d..0aa9d41c5a890087 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -63,6 +63,7 @@ libsupport-routines = \ + support_format_hostent \ + support_format_netent \ + support_isolate_in_subprocess \ ++ support_need_proc \ + support_path_support_time64 \ + support_process_state \ + support_ptrace \ +diff --git a/support/support.h b/support/support.h +index ecfc9a336d272a30..b69f588e2edce6be 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -90,6 +90,11 @@ char *support_quote_string (const char *); + regular file open for writing, and initially empty. */ + int support_descriptor_supports_holes (int fd); + ++/* Predicates that a test requires a working /proc filesystem. This ++ call will exit with UNSUPPORTED if /proc is not available, printing ++ WHY_MSG as part of the diagnostic. */ ++void support_need_proc (const char *why_msg); ++ + /* Error-checking wrapper functions which terminate the process on + error. */ + +diff --git a/support/support_need_proc.c b/support/support_need_proc.c +new file mode 100644 +index 0000000000000000..9b4eab7539b2d6c3 +--- /dev/null ++++ b/support/support_need_proc.c +@@ -0,0 +1,35 @@ ++/* Indicate that a test requires a working /proc. ++ 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 ++ ++/* We test for /proc/self/maps since that's one of the files that one ++ of our tests actually uses, but the general idea is if Linux's ++ /proc/ (procfs) filesystem is mounted. If not, the process exits ++ with an UNSUPPORTED result code. */ ++ ++void ++support_need_proc (const char *why_msg) ++{ ++#ifdef __linux__ ++ if (access ("/proc/self/maps", R_OK)) ++ FAIL_UNSUPPORTED ("/proc is not available, %s", why_msg); ++#endif ++} +diff --git a/support/test-container.c b/support/test-container.c +index 94498d39019a4776..7310335f7566b41e 100644 +--- a/support/test-container.c ++++ b/support/test-container.c +@@ -97,6 +97,7 @@ int verbose = 0; + * mytest.root/mytest.script has a list of "commands" to run: + syntax: + # comment ++ pidns + su + mv FILE FILE + cp FILE FILE +@@ -122,6 +123,8 @@ int verbose = 0; + + details: + - '#': A comment. ++ - 'pidns': Require a separate PID namespace, prints comment if it can't ++ (default is a shared pid namespace) + - 'su': Enables running test as root in the container. + - 'mv': A minimal move files command. + - 'cp': A minimal copy files command. +@@ -148,7 +151,7 @@ int verbose = 0; + * Simple, easy to review code (i.e. prefer simple naive code over + complex efficient code) + +- * The current implementation ist parallel-make-safe, but only in ++ * The current implementation is parallel-make-safe, but only in + that it uses a lock to prevent parallel access to the testroot. */ + + +@@ -227,11 +230,37 @@ concat (const char *str, ...) + return bufs[n]; + } + ++/* Like the above, but put spaces between words. Caller frees. */ ++static char * ++concat_words (char **words, int num_words) ++{ ++ int len = 0; ++ int i; ++ char *rv, *p; ++ ++ for (i = 0; i < num_words; i ++) ++ { ++ len += strlen (words[i]); ++ len ++; ++ } ++ ++ p = rv = (char *) xmalloc (len); ++ ++ for (i = 0; i < num_words; i ++) ++ { ++ if (i > 0) ++ p = stpcpy (p, " "); ++ p = stpcpy (p, words[i]); ++ } ++ ++ return rv; ++} ++ + /* Try to mount SRC onto DEST. */ + static void + trymount (const char *src, const char *dest) + { +- if (mount (src, dest, "", MS_BIND, NULL) < 0) ++ if (mount (src, dest, "", MS_BIND | MS_REC, NULL) < 0) + FAIL_EXIT1 ("can't mount %s onto %s\n", src, dest); + } + +@@ -726,6 +755,9 @@ main (int argc, char **argv) + gid_t original_gid; + /* If set, the test runs as root instead of the user running the testsuite. */ + int be_su = 0; ++ int require_pidns = 0; ++ const char *pidns_comment = NULL; ++ int do_proc_mounts = 0; + int UMAP; + int GMAP; + /* Used for "%lld %lld 1" so need not be large. */ +@@ -1011,6 +1043,12 @@ main (int argc, char **argv) + { + be_su = 1; + } ++ else if (nt >= 1 && strcmp (the_words[0], "pidns") == 0) ++ { ++ require_pidns = 1; ++ if (nt > 1) ++ pidns_comment = concat_words (the_words + 1, nt - 1); ++ } + else if (nt == 3 && strcmp (the_words[0], "mkdirp") == 0) + { + long int m; +@@ -1068,7 +1106,8 @@ main (int argc, char **argv) + + #ifdef CLONE_NEWNS + /* The unshare here gives us our own spaces and capabilities. */ +- if (unshare (CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNS) < 0) ++ if (unshare (CLONE_NEWUSER | CLONE_NEWNS ++ | (require_pidns ? CLONE_NEWPID : 0)) < 0) + { + /* Older kernels may not support all the options, or security + policy may block this call. */ +@@ -1079,6 +1118,11 @@ main (int argc, char **argv) + check_for_unshare_hints (); + FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (saved_errno)); + } ++ /* We're about to exit anyway, it's "safe" to call unshare again ++ just to see if the CLONE_NEWPID caused the error. */ ++ else if (require_pidns && unshare (CLONE_NEWUSER | CLONE_NEWNS) >= 0) ++ FAIL_EXIT1 ("unable to unshare pid ns: %s : %s", strerror (errno), ++ pidns_comment ? pidns_comment : "required by test"); + else + FAIL_EXIT1 ("unable to unshare user/fs: %s", strerror (errno)); + } +@@ -1094,6 +1138,15 @@ main (int argc, char **argv) + trymount (support_srcdir_root, new_srcdir_path); + trymount (support_objdir_root, new_objdir_path); + ++ /* It may not be possible to mount /proc directly. */ ++ if (! require_pidns) ++ { ++ char *new_proc = concat (new_root_path, "/proc", NULL); ++ xmkdirp (new_proc, 0755); ++ trymount ("/proc", new_proc); ++ do_proc_mounts = 1; ++ } ++ + xmkdirp (concat (new_root_path, "/dev", NULL), 0755); + devmount (new_root_path, "null"); + devmount (new_root_path, "zero"); +@@ -1163,42 +1216,60 @@ main (int argc, char **argv) + + maybe_xmkdir ("/tmp", 0755); + +- /* Now that we're pid 1 (effectively "root") we can mount /proc */ +- maybe_xmkdir ("/proc", 0777); +- if (mount ("proc", "/proc", "proc", 0, NULL) < 0) +- FAIL_EXIT1 ("Unable to mount /proc: "); +- +- /* We map our original UID to the same UID in the container so we +- can own our own files normally. */ +- UMAP = open ("/proc/self/uid_map", O_WRONLY); +- if (UMAP < 0) +- FAIL_EXIT1 ("can't write to /proc/self/uid_map\n"); +- +- sprintf (tmp, "%lld %lld 1\n", +- (long long) (be_su ? 0 : original_uid), (long long) original_uid); +- write (UMAP, tmp, strlen (tmp)); +- xclose (UMAP); +- +- /* We must disable setgroups () before we can map our groups, else we +- get EPERM. */ +- GMAP = open ("/proc/self/setgroups", O_WRONLY); +- if (GMAP >= 0) ++ if (require_pidns) + { +- /* We support kernels old enough to not have this. */ +- write (GMAP, "deny\n", 5); +- xclose (GMAP); ++ /* Now that we're pid 1 (effectively "root") we can mount /proc */ ++ maybe_xmkdir ("/proc", 0777); ++ if (mount ("proc", "/proc", "proc", 0, NULL) != 0) ++ { ++ /* This happens if we're trying to create a nested container, ++ like if the build is running under podman, and we lack ++ priviledges. ++ ++ Ideally we would WARN here, but that would just add noise to ++ *every* test-container test, and the ones that care should ++ have their own relevent diagnostics. ++ ++ FAIL_EXIT1 ("Unable to mount /proc: "); */ ++ } ++ else ++ do_proc_mounts = 1; + } + +- /* We map our original GID to the same GID in the container so we +- can own our own files normally. */ +- GMAP = open ("/proc/self/gid_map", O_WRONLY); +- if (GMAP < 0) +- FAIL_EXIT1 ("can't write to /proc/self/gid_map\n"); ++ if (do_proc_mounts) ++ { ++ /* We map our original UID to the same UID in the container so we ++ can own our own files normally. */ ++ UMAP = open ("/proc/self/uid_map", O_WRONLY); ++ if (UMAP < 0) ++ FAIL_EXIT1 ("can't write to /proc/self/uid_map\n"); ++ ++ sprintf (tmp, "%lld %lld 1\n", ++ (long long) (be_su ? 0 : original_uid), (long long) original_uid); ++ write (UMAP, tmp, strlen (tmp)); ++ xclose (UMAP); ++ ++ /* We must disable setgroups () before we can map our groups, else we ++ get EPERM. */ ++ GMAP = open ("/proc/self/setgroups", O_WRONLY); ++ if (GMAP >= 0) ++ { ++ /* We support kernels old enough to not have this. */ ++ write (GMAP, "deny\n", 5); ++ xclose (GMAP); ++ } + +- sprintf (tmp, "%lld %lld 1\n", +- (long long) (be_su ? 0 : original_gid), (long long) original_gid); +- write (GMAP, tmp, strlen (tmp)); +- xclose (GMAP); ++ /* We map our original GID to the same GID in the container so we ++ can own our own files normally. */ ++ GMAP = open ("/proc/self/gid_map", O_WRONLY); ++ if (GMAP < 0) ++ FAIL_EXIT1 ("can't write to /proc/self/gid_map\n"); ++ ++ sprintf (tmp, "%lld %lld 1\n", ++ (long long) (be_su ? 0 : original_gid), (long long) original_gid); ++ write (GMAP, tmp, strlen (tmp)); ++ xclose (GMAP); ++ } + + if (change_cwd) + { diff --git a/SOURCES/glibc-upstream-2.34-365.patch b/SOURCES/glibc-upstream-2.34-365.patch new file mode 100644 index 0000000..1fd3d7c --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-365.patch @@ -0,0 +1,39 @@ +commit 405b8ae13540e9fd614df614e3361ebf9abd14cf +Author: Adhemerval Zanella +Date: Tue Jul 5 12:58:40 2022 -0300 + + elf: Fix wrong fscanf usage on tst-pldd + + The fix done b2cd93fce666fdc8c9a5c64af2741a8a6940ac99 does not really + work since macro strification does not expand the sizeof nor the + arithmetic operation. + + Checked on x86_64-linux-gnu. + + (cherry picked from commit c353689e49e72f3aafa1a9e68d4f7a4f33a79cbe) + +diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c +index 6e4174cbf95b15c0..d3ecb99149d619c6 100644 +--- a/elf/tst-pldd.c ++++ b/elf/tst-pldd.c +@@ -108,15 +108,16 @@ do_test (void) + loader and libc. */ + { + pid_t pid; +- char buffer[512]; +-#define STRINPUT(size) "%" # size "s" ++#define BUFFERLEN 511 ++ char buffer[BUFFERLEN + 1]; ++#define STRINPUT(size) XSTRINPUT(size) ++#define XSTRINPUT(size) "%" # size "s" + + FILE *out = fmemopen (pldd.out.buffer, pldd.out.length, "r"); + TEST_VERIFY (out != NULL); + + /* First line is in the form of : */ +- TEST_COMPARE (fscanf (out, "%u: " STRINPUT (sizeof (buffer) - 1), &pid, +- buffer), 2); ++ TEST_COMPARE (fscanf (out, "%u: " STRINPUT (BUFFERLEN), &pid, buffer), 2); + + TEST_COMPARE (pid, *target_pid_ptr); + TEST_COMPARE (strcmp (basename (buffer), "tst-pldd"), 0); diff --git a/SOURCES/glibc-upstream-2.34-366.patch b/SOURCES/glibc-upstream-2.34-366.patch new file mode 100644 index 0000000..dec7dc4 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-366.patch @@ -0,0 +1,29 @@ +commit a1c12fdf3f9b8665719835ce8330b3b2e2574b37 +Author: Florian Weimer +Date: Fri Sep 10 13:18:36 2021 +0200 + + _Static_assert needs two arguments for compatibility with GCC before 9 + + This macro definition enforces two arguments even with newer compilers + that accept the single-argument form, too. + + Reviewed-by: Carlos O'Donell + (cherry picked from commit c9fef4b7d1d0f2dad192c74f06102752247677a9) + +diff --git a/include/sys/cdefs.h b/include/sys/cdefs.h +index 6a76160ed4e4cabb..56adb231aa8f8cbe 100644 +--- a/include/sys/cdefs.h ++++ b/include/sys/cdefs.h +@@ -1,5 +1,12 @@ + #ifndef _SYS_CDEFS_H + ++/* This is outside of _ISOMAC to enforce that _Static_assert always ++ uses the two-argument form. This can be removed once the minimum ++ GCC version used to compile glibc is GCC 9.1. */ ++#ifndef __cplusplus ++# define _Static_assert(expr, diagnostic) _Static_assert (expr, diagnostic) ++#endif ++ + #include + + #ifndef _ISOMAC diff --git a/SOURCES/glibc-upstream-2.34-367.patch b/SOURCES/glibc-upstream-2.34-367.patch new file mode 100644 index 0000000..7df9998 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-367.patch @@ -0,0 +1,72 @@ +commit a4217408a3d6050a7f42ac23adb6ac7218dca85f +Author: Tulio Magno Quites Machado Filho +Date: Fri Nov 11 17:00:15 2022 -0300 + + Apply asm redirections in syslog.h before first use [BZ #27087] + + Similar to d0fa09a770, but for syslog.h when _FORTIFY_SOURCE > 0. + Fixes [BZ #27087] by applying long double-related asm redirections + before using functions in bits/syslog.h. + + Tested with build-many-glibcs.py. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 227df6243a2b5b4d70d11772d12c02eb9cb666ca) + +diff --git a/misc/bits/syslog.h b/misc/bits/syslog.h +index 6f3137a98ee593f3..10c9c1151382a51c 100644 +--- a/misc/bits/syslog.h ++++ b/misc/bits/syslog.h +@@ -24,6 +24,20 @@ + extern void __syslog_chk (int __pri, int __flag, const char *__fmt, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); + ++#ifdef __USE_MISC ++extern void __vsyslog_chk (int __pri, int __flag, const char *__fmt, ++ __gnuc_va_list __ap) ++ __attribute__ ((__format__ (__printf__, 3, 0))); ++#endif ++ ++#include ++#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 ++# include ++#endif ++ ++/* The following functions must be used only after applying all asm ++ redirections, e.g. long double asm redirections. */ ++ + #ifdef __va_arg_pack + __fortify_function void + syslog (int __pri, const char *__fmt, ...) +@@ -37,10 +51,6 @@ syslog (int __pri, const char *__fmt, ...) + + + #ifdef __USE_MISC +-extern void __vsyslog_chk (int __pri, int __flag, const char *__fmt, +- __gnuc_va_list __ap) +- __attribute__ ((__format__ (__printf__, 3, 0))); +- + __fortify_function void + vsyslog (int __pri, const char *__fmt, __gnuc_va_list __ap) + { +diff --git a/misc/sys/syslog.h b/misc/sys/syslog.h +index dc3b0e7ef81de812..e7a98fb9b13ce132 100644 +--- a/misc/sys/syslog.h ++++ b/misc/sys/syslog.h +@@ -205,11 +205,11 @@ extern void vsyslog (int __pri, const char *__fmt, __gnuc_va_list __ap) + /* Define some macros helping to catch buffer overflows. */ + #if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function + # include +-#endif +- +-#include +-#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 +-# include ++#else ++# include ++# if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 ++# include ++# endif + #endif + + __END_DECLS diff --git a/SOURCES/glibc-upstream-2.34-368.patch b/SOURCES/glibc-upstream-2.34-368.patch new file mode 100644 index 0000000..3f61281 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-368.patch @@ -0,0 +1,241 @@ +commit 42eb735a5d3458a24a44ace9eca87c8b61573d97 +Author: Adhemerval Zanella +Date: Thu May 20 14:20:18 2021 -0300 + + Use LFS and 64 bit time for installed programs (BZ #15333) + + The installed programs are built with a combination of different + values for MODULE_NAME, as below. To enable both Long File Support + and 64 bt time, -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 is added for + nonlibi, nscd, lddlibc4, libresolv, ldconfig, locale_programs, + iconvprogs, libnss_files, libnss_compat, libnss_db, libnss_hesiod, + libutil, libpcprofile, and libSegFault. + + nscd/nscd + nscd/nscd.o MODULE_NAME=nscd + nscd/connections.o MODULE_NAME=nscd + nscd/pwdcache.o MODULE_NAME=nscd + nscd/getpwnam_r.o MODULE_NAME=nscd + nscd/getpwuid_r.o MODULE_NAME=nscd + nscd/grpcache.o MODULE_NAME=nscd + nscd/getgrnam_r.o MODULE_NAME=nscd + nscd/getgrgid_r.o MODULE_NAME=nscd + nscd/hstcache.o MODULE_NAME=nscd + nscd/gethstbyad_r.o MODULE_NAME=nscd + nscd/gethstbynm3_r.o MODULE_NAME=nscd + nscd/getsrvbynm_r.o MODULE_NAME=nscd + nscd/getsrvbypt_r.o MODULE_NAME=nscd + nscd/servicescache.o MODULE_NAME=nscd + nscd/dbg_log.o MODULE_NAME=nscd + nscd/nscd_conf.o MODULE_NAME=nscd + nscd/nscd_stat.o MODULE_NAME=nscd + nscd/cache.o MODULE_NAME=nscd + nscd/mem.o MODULE_NAME=nscd + nscd/nscd_setup_thread.o MODULE_NAME=nscd + nscd/xmalloc.o MODULE_NAME=nscd + nscd/xstrdup.o MODULE_NAME=nscd + nscd/aicache.o MODULE_NAME=nscd + nscd/initgrcache.o MODULE_NAME=nscd + nscd/gai.o MODULE_NAME=nscd + nscd/res_hconf.o MODULE_NAME=nscd + nscd/netgroupcache.o MODULE_NAME=nscd + nscd/cachedumper.o MODULE_NAME=nscd + elf/lddlibc4 + elf/lddlibc4 MODULE_NAME=lddlibc4 + elf/pldd + elf/pldd.o MODULE_NAME=nonlib + elf/xmalloc.o MODULE_NAME=nonlib + elf/sln + elf/sln.o MODULE_NAME=nonlib + elf/static-stubs.o MODULE_NAME=nonlib + elf/sprof MODULE_NAME=nonlib + elf/ldconfig + elf/ldconfig.o MODULE_NAME=ldconfig + elf/cache.o MODULE_NAME=nonlib + elf/readlib.o MODULE_NAME=nonlib + elf/xmalloc.o MODULE_NAME=nonlib + elf/xstrdup.o MODULE_NAME=nonlib + elf/chroot_canon.o MODULE_NAME=nonlib + elf/static-stubs.o MODULE_NAME=nonlib + elf/stringtable.o MODULE_NAME=nonlib + io/pwd + io/pwd.o MODULE_NAME=nonlib + locale/locale + locale/locale.o MODULE_NAME=locale_programs + locale/locale-spec.o MODULE_NAME=locale_programs + locale/charmap-dir.o MODULE_NAME=locale_programs + locale/simple-hash.o MODULE_NAME=locale_programs + locale/xmalloc.o MODULE_NAME=locale_programs + locale/xstrdup.o MODULE_NAME=locale_programs + locale/record-status.o MODULE_NAME=locale_programs + locale/xasprintf.o MODULE_NAME=locale_programs + locale/localedef + locale/localedef.o MODULE_NAME=locale_programs + locale/ld-ctype.o MODULE_NAME=locale_programs + locale/ld-messages.o MODULE_NAME=locale_programs + locale/ld-monetary.o MODULE_NAME=locale_programs + locale/ld-numeric.o MODULE_NAME=locale_programs + locale/ld-time.o MODULE_NAME=locale_programs + locale/ld-paper.o MODULE_NAME=locale_programs + locale/ld-name.o MODULE_NAME=locale_programs + locale/ld-address.o MODULE_NAME=locale_programs + locale/ld-telephone.o MODULE_NAME=locale_programs + locale/ld-measurement.o MODULE_NAME=locale_programs + locale/ld-identification.o MODULE_NAME=locale_programs + locale/ld-collate.o MODULE_NAME=locale_programs + locale/charmap.o MODULE_NAME=locale_programs + locale/linereader.o MODULE_NAME=locale_programs + locale/locfile.o MODULE_NAME=locale_programs + locale/repertoire.o MODULE_NAME=locale_programs + locale/locarchive.o MODULE_NAME=locale_programs + locale/md5.o MODULE_NAME=locale_programs + locale/charmap-dir.o MODULE_NAME=locale_programs + locale/simple-hash.o MODULE_NAME=locale_programs + locale/xmalloc.o MODULE_NAME=locale_programs + locale/xstrdup.o MODULE_NAME=locale_programs + locale/record-status.o MODULE_NAME=locale_programs + locale/xasprintf.o MODULE_NAME=locale_programs + catgets/gencat + catgets/gencat.o MODULE_NAME=nonlib + catgets/xmalloc.o MODULE_NAME=nonlib + nss/makedb + nss/makedb.o MODULE_NAME=nonlib + nss/xmalloc.o MODULE_NAME=nonlib + nss/hash-string.o MODULE_NAME=nonlib + nss/getent + nss/getent.o MODULE_NAME=nonlib + posix/getconf + posix/getconf.o MODULE_NAME=nonlib + login/utmpdump + login/utmpdump.o MODULE_NAME=nonlib + debug/pcprofiledump + debug/pcprofiledump.o MODULE_NAME=nonlib + timezone/zic + timezone/zic.o MODULE_NAME=nonlib + timezone/zdump + timezone/zdump.o MODULE_NAME=nonlib + iconv/iconv_prog + iconv/iconv_prog.o MODULE_NAME=nonlib + iconv/iconv_charmap.o MODULE_NAME=iconvprogs + iconv/charmap.o MODULE_NAME=iconvprogs + iconv/charmap-dir.o MODULE_NAME=iconvprogs + iconv/linereader.o MODULE_NAME=iconvprogs + iconv/dummy-repertoire.o MODULE_NAME=iconvprogs + iconv/simple-hash.o MODULE_NAME=iconvprogs + iconv/xstrdup.o MODULE_NAME=iconvprogs + iconv/xmalloc.o MODULE_NAME=iconvprogs + iconv/record-status.o MODULE_NAME=iconvprogs + iconv/iconvconfig + iconv/iconvconfig.o MODULE_NAME=nonlib + iconv/strtab.o MODULE_NAME=iconvprogs + iconv/xmalloc.o MODULE_NAME=iconvprogs + iconv/hash-string.o MODULE_NAME=iconvprogs + nss/libnss_files.so MODULE_NAME=libnss_files + nss/libnss_compat.so.2 MODULE_NAME=libnss_compat + nss/libnss_db.so MODULE_NAME=libnss_db + hesiod/libnss_hesiod.so MODULE_NAME=libnss_hesiod + login/libutil.so MODULE_NAME=libutil + debug/libpcprofile.so MODULE_NAME=libpcprofile + debug/libSegFault.so MODULE_NAME=libSegFault + + Also, to avoid adding both LFS and 64 bit time support on internal + tests they are moved to a newer 'testsuite-internal' module. It + should be similar to 'nonlib' regarding internal definition and + linking namespace. + + This patch also enables LFS and 64 bit support of libsupport container + programs (echo-container, test-container, shell-container, and + true-container). + + Checked on x86_64-linux-gnu and i686-linux-gnu. + + Reviewed-by: DJ Delorie + (cherry picked from commit a6d2f948b71adcb5ea395cb04833bc645eab45e6) + +diff --git a/Makeconfig b/Makeconfig +index 4e04dafb76a1e1a1..9accb5b38d1d37b3 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -882,6 +882,13 @@ endif + # -fno-math-errno. + +extra-math-flags = $(if $(filter libm,$(in-module)),-fno-math-errno,-fmath-errno) + ++# Use 64 bit time_t support for installed programs ++installed-modules = nonlib nscd lddlibc4 libresolv ldconfig locale_programs \ ++ iconvprogs libnss_files libnss_compat libnss_db libnss_hesiod \ ++ libutil libpcprofile libSegFault +++extra-time-flags = $(if $(filter $(installed-modules),\ ++ $(in-module)),-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64) ++ + # We might want to compile with some stack-protection flag. + ifneq ($(stack-protector),) + +stack-protector=$(stack-protector) +@@ -986,7 +993,7 @@ libio-include = -I$(..)libio + built-modules = iconvprogs iconvdata ldconfig lddlibc4 libmemusage \ + libSegFault libpcprofile librpcsvc locale-programs \ + memusagestat nonlib nscd extramodules libnldbl libsupport \ +- testsuite ++ testsuite testsuite-internal + + in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \ + $(libof-$( +Date: Wed Oct 26 16:04:23 2022 -0300 + + nis: Build libnsl with 64 bit time_t + + And remove the usage of glibc reserved names. + Reviewed-by: DJ Delorie + + (cherry picked from commit 545eefc2f5da61801ba82b7a32ca2589b769ec90) + +diff --git a/Makeconfig b/Makeconfig +index 9accb5b38d1d37b3..89a2881b1ef605e4 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -885,7 +885,7 @@ endif + # Use 64 bit time_t support for installed programs + installed-modules = nonlib nscd lddlibc4 libresolv ldconfig locale_programs \ + iconvprogs libnss_files libnss_compat libnss_db libnss_hesiod \ +- libutil libpcprofile libSegFault ++ libutil libpcprofile libSegFault libnsl + +extra-time-flags = $(if $(filter $(installed-modules),\ + $(in-module)),-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64) + +diff --git a/nis/nis_call.c b/nis/nis_call.c +index 043f1bd4316aa284..37feba201c37cbca 100644 +--- a/nis/nis_call.c ++++ b/nis/nis_call.c +@@ -575,7 +575,7 @@ static struct nis_server_cache + unsigned int size; + unsigned int server_used; + unsigned int current_ep; +- __time64_t expires; ++ time_t expires; + char name[]; + } *nis_server_cache[16]; + static time_t nis_cold_start_mtime; +@@ -584,7 +584,7 @@ __libc_lock_define_initialized (static, nis_server_cache_lock) + static directory_obj * + nis_server_cache_search (const_nis_name name, int search_parent, + unsigned int *server_used, unsigned int *current_ep, +- struct __timespec64 *now) ++ struct timespec *now) + { + directory_obj *ret = NULL; + int i; +@@ -642,7 +642,7 @@ nis_server_cache_search (const_nis_name name, int search_parent, + static void + nis_server_cache_add (const_nis_name name, int search_parent, + directory_obj *dir, unsigned int server_used, +- unsigned int current_ep, struct __timespec64 *now) ++ unsigned int current_ep, struct timespec *now) + { + struct nis_server_cache **loc; + struct nis_server_cache *new; +@@ -708,7 +708,7 @@ __nisfind_server (const_nis_name name, int search_parent, + nis_error result = NIS_SUCCESS; + nis_error status; + directory_obj *obj; +- struct __timespec64 ts; ++ struct timespec ts; + unsigned int server_used = ~0; + unsigned int current_ep = ~0; + +@@ -718,7 +718,7 @@ __nisfind_server (const_nis_name name, int search_parent, + if (*dir != NULL) + return NIS_SUCCESS; + +- __clock_gettime64 (CLOCK_REALTIME, &ts); ++ clock_gettime (CLOCK_REALTIME, &ts); + + if ((flags & NO_CACHE) == 0) + *dir = nis_server_cache_search (name, search_parent, &server_used, diff --git a/SOURCES/glibc-upstream-2.34-370.patch b/SOURCES/glibc-upstream-2.34-370.patch new file mode 100644 index 0000000..41037ec --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-370.patch @@ -0,0 +1,38 @@ +commit 01c0a0405c5ea63d9b528e062b935d2ff6a6e2ed +Author: Adhemerval Zanella Netto +Date: Wed Oct 26 16:04:24 2022 -0300 + + nscd: Use 64 bit time_t on libc nscd routines (BZ# 29402) + + Although the nscd module is built with 64 bit time_t, the routines + linked direct to libc.so need to use the internal symbols. + Reviewed-by: DJ Delorie + + (cherry picked from commit fa4a19277842fd09a4815a986f70e0fe0903836f) + +diff --git a/nscd/nscd.h b/nscd/nscd.h +index b5da5be98a11d4de..1ce4c1f7fdb215f0 100644 +--- a/nscd/nscd.h ++++ b/nscd/nscd.h +@@ -66,7 +66,7 @@ typedef enum + struct traced_file + { + /* Tracks the last modified time of the traced file. */ +- time_t mtime; ++ __time64_t mtime; + /* Support multiple registered files per database. */ + struct traced_file *next; + int call_res_init; +diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c +index 81bf324256384de7..b6baa8abf881461c 100644 +--- a/nscd/nscd_gethst_r.c ++++ b/nscd/nscd_gethst_r.c +@@ -113,7 +113,7 @@ __nscd_get_nl_timestamp (void) + if (map == NULL + || (map != NO_MAPPING + && map->head->nscd_certainly_running == 0 +- && map->head->timestamp + MAPPING_TIMEOUT < time_now ())) ++ && map->head->timestamp + MAPPING_TIMEOUT < time64_now ())) + map = __nscd_get_mapping (GETFDHST, "hosts", &__hst_map_handle.mapped); + + if (map == NO_MAPPING) diff --git a/SOURCES/glibc-upstream-2.34-371.patch b/SOURCES/glibc-upstream-2.34-371.patch new file mode 100644 index 0000000..b4ded31 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-371.patch @@ -0,0 +1,24 @@ +commit e14a91e59d35bf2fa649a9726ccce838b8c6e4b7 +Author: Adhemerval Zanella Netto +Date: Wed Oct 26 16:04:25 2022 -0300 + + time: Use 64 bit time on tzfile + + The tzfile_mtime is already compared to 64 bit time_t stat call. + Reviewed-by: DJ Delorie + + (cherry picked from commit 4e21c2075193e406a92c0d1cb091a7c804fda4d9) + +diff --git a/time/tzfile.c b/time/tzfile.c +index 8668392ad387af05..84fd9df65f76f148 100644 +--- a/time/tzfile.c ++++ b/time/tzfile.c +@@ -32,7 +32,7 @@ + int __use_tzfile; + static dev_t tzfile_dev; + static ino64_t tzfile_ino; +-static time_t tzfile_mtime; ++static __time64_t tzfile_mtime; + + struct ttinfo + { diff --git a/SOURCES/glibc-upstream-2.34-372.patch b/SOURCES/glibc-upstream-2.34-372.patch new file mode 100644 index 0000000..dd41022 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-372.patch @@ -0,0 +1,28 @@ +commit d0e2ac0c5902bd0e671863cc6cb14024d0365e67 +Author: Alan Modra +Date: Sat Nov 12 11:20:31 2022 +1030 + + elf/tst-tlsopt-powerpc fails when compiled with -mcpu=power10 (BZ# 29776) + + Supports pcrel addressing of TLS GOT entry. Also tweak the non-pcrel + asm constraint to better reflect how the reg is used. + + (cherry picked from commit 94628de77888c3292fc103840731ff85f283368e) + +diff --git a/sysdeps/powerpc/mod-tlsopt-powerpc.c b/sysdeps/powerpc/mod-tlsopt-powerpc.c +index ee0db12a737d6ab5..51cc502f2860e969 100644 +--- a/sysdeps/powerpc/mod-tlsopt-powerpc.c ++++ b/sysdeps/powerpc/mod-tlsopt-powerpc.c +@@ -24,7 +24,11 @@ tls_get_addr_opt_test (void) + tls_index *tls_arg; + #ifdef __powerpc64__ + register unsigned long thread_pointer __asm__ ("r13"); +- asm ("addi %0,2,foo@got@tlsgd" : "=r" (tls_arg)); ++# ifdef __PCREL__ ++ asm ("paddi %0,0,foo@got@tlsgd@pcrel,1" : "=b" (tls_arg)); ++# else ++ asm ("addi %0,2,foo@got@tlsgd" : "=b" (tls_arg)); ++# endif + #else + register unsigned long thread_pointer __asm__ ("r2"); + asm ("bcl 20,31,1f\n1:\t" diff --git a/SOURCES/glibc-upstream-2.34-373.patch b/SOURCES/glibc-upstream-2.34-373.patch new file mode 100644 index 0000000..01b4007 Binary files /dev/null and b/SOURCES/glibc-upstream-2.34-373.patch differ diff --git a/SOURCES/glibc-upstream-2.34-374.patch b/SOURCES/glibc-upstream-2.34-374.patch new file mode 100644 index 0000000..709b5c2 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-374.patch @@ -0,0 +1,526 @@ +commit bbe4bbb6e8997b5ff9843bd3f32ac77dbaec7284 +Author: Fangrui Song +Date: Mon Aug 16 09:59:30 2021 -0700 + + elf: Drop elf/tls-macros.h in favor of __thread and tls_model attributes [BZ #28152] [BZ #28205] + + elf/tls-macros.h was added for TLS testing when GCC did not support + __thread. __thread and tls_model attributes are mature now and have been + used by many newer tests. + + Also delete tst-tls2.c which tests .tls_common (unused by modern GCC and + unsupported by Clang/LLD). .tls_common and .tbss definition are almost + identical after linking, so the runtime test doesn't add additional + coverage. Assembler and linker tests should be on the binutils side. + + When LLD 13.0.0 is allowed in configure.ac + (https://sourceware.org/pipermail/libc-alpha/2021-August/129866.html), + `make check` result is on par with glibc built with GNU ld on aarch64 + and x86_64. + + As a future clean-up, TLS_GD/TLS_LD/TLS_IE/TLS_IE macros can be removed from + sysdeps/*/tls-macros.h. We can add optional -mtls-dialect={gnu2,trad} + tests to ensure coverage. + + Tested on aarch64-linux-gnu, powerpc64le-linux-gnu, and x86_64-linux-gnu. + + Reviewed-by: Szabolcs Nagy + (cherry picked from commit 33c50ef42878b07ee6ead8b3f1a81d8c2c74697c) + +Conflicts: + elf/Makefile + (different backport order) + +diff --git a/elf/Makefile b/elf/Makefile +index feec365e4e5fe9b3..3a8590e0d3cc33ab 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -275,7 +275,6 @@ tests-static-internal := \ + tst-ptrguard1-static \ + tst-stackguard1-static \ + tst-tls1-static \ +- tst-tls2-static \ + tst-tls1-static-non-pie \ + # tests-static-internal + +@@ -308,7 +307,6 @@ tests := \ + tests-internal := \ + $(tests-static-internal) \ + tst-tls1 \ +- tst-tls2 \ + # tests-internal + + tests-static := $(tests-static-normal) $(tests-static-internal) +diff --git a/elf/tls-macros.h b/elf/tls-macros.h +deleted file mode 100644 +index e25e33b0f032099d..0000000000000000 +--- a/elf/tls-macros.h ++++ /dev/null +@@ -1,25 +0,0 @@ +-/* Macros to support TLS testing in times of missing compiler support. */ +- +-#define COMMON_INT_DEF(x) \ +- asm (".tls_common " #x ",4,4") +-/* XXX Until we get compiler support we don't need declarations. */ +-#define COMMON_INT_DECL(x) +- +-/* XXX This definition will probably be machine specific, too. */ +-#define VAR_INT_DEF(x) \ +- asm (".section .tdata\n\t" \ +- ".globl " #x "\n" \ +- ".balign 4\n" \ +- #x ":\t.long 0\n\t" \ +- ".size " #x ",4\n\t" \ +- ".previous") +-/* XXX Until we get compiler support we don't need declarations. */ +-#define VAR_INT_DECL(x) +- +-#include_next +- +- /* XXX Each architecture must have its own asm for now. */ +-#if !defined TLS_LE || !defined TLS_IE \ +- || !defined TLS_LD || !defined TLS_GD +-# error "No support for this architecture so far." +-#endif +diff --git a/elf/tst-tls1.c b/elf/tst-tls1.c +index c31da56ce9cb3e8f..b3412213ee9eaa7e 100644 +--- a/elf/tst-tls1.c ++++ b/elf/tst-tls1.c +@@ -1,13 +1,14 @@ + /* glibc test for TLS in ld.so. */ + #include + +-#include "tls-macros.h" +- +- +-/* Two common 'int' variables in TLS. */ +-COMMON_INT_DEF(foo); +-COMMON_INT_DEF(bar); + ++__thread int foo, bar __attribute__ ((tls_model("local-exec"))); ++extern __thread int foo_gd asm ("foo") __attribute__ ((tls_model("global-dynamic"))); ++extern __thread int foo_ld asm ("foo") __attribute__ ((tls_model("local-dynamic"))); ++extern __thread int foo_ie asm ("foo") __attribute__ ((tls_model("initial-exec"))); ++extern __thread int bar_gd asm ("bar") __attribute__ ((tls_model("global-dynamic"))); ++extern __thread int bar_ld asm ("bar") __attribute__ ((tls_model("local-dynamic"))); ++extern __thread int bar_ie asm ("bar") __attribute__ ((tls_model("initial-exec"))); + + static int + do_test (void) +@@ -18,63 +19,48 @@ do_test (void) + + /* Set the variable using the local exec model. */ + puts ("set bar to 1 (LE)"); +- ap = TLS_LE (bar); +- *ap = 1; ++ bar = 1; + + + /* Get variables using initial exec model. */ + fputs ("get sum of foo and bar (IE)", stdout); +- ap = TLS_IE (foo); +- bp = TLS_IE (bar); ++ ap = &foo_ie; ++ bp = &bar_ie; + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) ++ if (*ap != 0 || *bp != 1) + { +- printf ("bar = %d\n", *bp); ++ printf ("foo = %d\nbar = %d\n", *ap, *bp); + result = 1; + } + + +- /* Get variables using local dynamic model. */ +- fputs ("get sum of foo and bar (LD)", stdout); +- ap = TLS_LD (foo); +- bp = TLS_LD (bar); ++ /* Get variables using local dynamic model or TLSDESC. */ ++ fputs ("get sum of foo and bar (LD or TLSDESC)", stdout); ++ ap = &foo_ld; ++ bp = &bar_ld; + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) ++ if (*ap != 0 || *bp != 1) + { +- printf ("bar = %d\n", *bp); ++ printf ("foo = %d\nbar = %d\n", *ap, *bp); + result = 1; + } + + +- /* Get variables using generic dynamic model. */ +- fputs ("get sum of foo and bar (GD)", stdout); +- ap = TLS_GD (foo); +- bp = TLS_GD (bar); ++ /* Get variables using general dynamic model or TLSDESC. */ ++ fputs ("get sum of foo and bar (GD or TLSDESC)", stdout); ++ ap = &foo_gd; ++ bp = &bar_gd; + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) ++ if (*ap != 0 || *bp != 1) + { +- printf ("bar = %d\n", *bp); ++ printf ("foo = %d\nbar = %d\n", *ap, *bp); + result = 1; + } + ++ + return result; + } + +diff --git a/elf/tst-tls2.c b/elf/tst-tls2.c +deleted file mode 100644 +index 963b8d6c88bba0b5..0000000000000000 +--- a/elf/tst-tls2.c ++++ /dev/null +@@ -1,82 +0,0 @@ +-/* glibc test for TLS in ld.so. */ +-#include +- +-#include "tls-macros.h" +- +- +-/* Two 'int' variables in TLS. */ +-VAR_INT_DEF(foo); +-VAR_INT_DEF(bar); +- +- +-static int +-do_test (void) +-{ +- int result = 0; +- int *ap, *bp; +- +- +- /* Set the variable using the local exec model. */ +- puts ("set bar to 1 (LE)"); +- ap = TLS_LE (bar); +- *ap = 1; +- +- +- /* Get variables using initial exec model. */ +- fputs ("get sum of foo and bar (IE)", stdout); +- ap = TLS_IE (foo); +- bp = TLS_IE (bar); +- printf (" = %d\n", *ap + *bp); +- result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) +- { +- printf ("bar = %d\n", *bp); +- result = 1; +- } +- +- +- /* Get variables using local dynamic model. */ +- fputs ("get sum of foo and bar (LD)", stdout); +- ap = TLS_LD (foo); +- bp = TLS_LD (bar); +- printf (" = %d\n", *ap + *bp); +- result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) +- { +- printf ("bar = %d\n", *bp); +- result = 1; +- } +- +- +- /* Get variables using generic dynamic model. */ +- fputs ("get sum of foo and bar (GD)", stdout); +- ap = TLS_GD (foo); +- bp = TLS_GD (bar); +- printf (" = %d\n", *ap + *bp); +- result |= *ap + *bp != 1; +- if (*ap != 0) +- { +- printf ("foo = %d\n", *ap); +- result = 1; +- } +- if (*bp != 1) +- { +- printf ("bar = %d\n", *bp); +- result = 1; +- } +- +- return result; +-} +- +- +-#include +diff --git a/elf/tst-tls3.c b/elf/tst-tls3.c +index 7e0abb4c58c8ff50..222b179626161897 100644 +--- a/elf/tst-tls3.c ++++ b/elf/tst-tls3.c +@@ -1,13 +1,12 @@ + /* glibc test for TLS in ld.so. */ + #include + +-#include "tls-macros.h" + +- +-/* One define int variable, two externs. */ +-COMMON_INT_DECL(foo); +-VAR_INT_DECL(bar); +-VAR_INT_DEF(baz); ++__thread int foo, bar __attribute__ ((tls_model("initial-exec"))); ++__thread int baz __attribute__ ((tls_model("local-exec"))); ++extern __thread int foo_gd __attribute__ ((alias("foo"), tls_model("global-dynamic"))); ++extern __thread int bar_gd __attribute__ ((alias("bar"), tls_model("global-dynamic"))); ++extern __thread int baz_ld __attribute__ ((alias("baz"), tls_model("local-dynamic"))); + + + extern int in_dso (void); +@@ -22,23 +21,20 @@ do_test (void) + + /* Set the variable using the local exec model. */ + puts ("set baz to 3 (LE)"); +- ap = TLS_LE (baz); +- *ap = 3; ++ baz = 3; + + + /* Get variables using initial exec model. */ + puts ("set variables foo and bar (IE)"); +- ap = TLS_IE (foo); +- *ap = 1; +- bp = TLS_IE (bar); +- *bp = 2; ++ foo = 1; ++ bar = 2; + + + /* Get variables using local dynamic model. */ + fputs ("get sum of foo, bar (GD) and baz (LD)", stdout); +- ap = TLS_GD (foo); +- bp = TLS_GD (bar); +- cp = TLS_LD (baz); ++ ap = &foo_gd; ++ bp = &bar_gd; ++ cp = &baz_ld; + printf (" = %d\n", *ap + *bp + *cp); + result |= *ap + *bp + *cp != 6; + if (*ap != 1) +diff --git a/elf/tst-tlsmod1.c b/elf/tst-tlsmod1.c +index 8d9156791be9eabf..a448c4dc37eaf01b 100644 +--- a/elf/tst-tlsmod1.c ++++ b/elf/tst-tlsmod1.c +@@ -1,12 +1,12 @@ + #include + +-#include "tls-macros.h" + ++__thread int foo, bar __attribute__ ((tls_model("global-dynamic"))); ++extern __thread int baz __attribute__ ((tls_model("global-dynamic"))); ++extern __thread int foo_ie asm ("foo") __attribute__ ((tls_model("initial-exec"))); ++extern __thread int bar_ie asm ("bar") __attribute__ ((tls_model("initial-exec"))); ++extern __thread int baz_ie asm ("baz") __attribute__ ((tls_model("initial-exec"))); + +-/* One define int variable, two externs. */ +-COMMON_INT_DEF(foo); +-VAR_INT_DEF(bar); +-VAR_INT_DECL(baz); + + extern int in_dso (void); + +@@ -19,8 +19,8 @@ in_dso (void) + /* Get variables using initial exec model. */ + fputs ("get sum of foo and bar (IE)", stdout); + asm ("" ::: "memory"); +- ap = TLS_IE (foo); +- bp = TLS_IE (bar); ++ ap = &foo_ie; ++ bp = &bar_ie; + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 3; + if (*ap != 1) +@@ -35,11 +35,11 @@ in_dso (void) + } + + +- /* Get variables using generic dynamic model. */ +- fputs ("get sum of foo and bar and baz (GD)", stdout); +- ap = TLS_GD (foo); +- bp = TLS_GD (bar); +- cp = TLS_GD (baz); ++ /* Get variables using generic dynamic model or TLSDESC. */ ++ fputs ("get sum of foo and bar and baz (GD or TLSDESC)", stdout); ++ ap = &foo; ++ bp = &bar; ++ cp = &baz; + printf (" = %d\n", *ap + *bp + *cp); + result |= *ap + *bp + *cp != 6; + if (*ap != 1) +diff --git a/elf/tst-tlsmod2.c b/elf/tst-tlsmod2.c +index 40eb1407f864f64a..3223fe494bb7e1f0 100644 +--- a/elf/tst-tlsmod2.c ++++ b/elf/tst-tlsmod2.c +@@ -1,9 +1,7 @@ + #include + +-#include "tls-macros.h" + +- +-COMMON_INT_DEF(foo); ++__thread int foo; + + + int +@@ -15,7 +13,7 @@ in_dso (int n, int *caller_foop) + puts ("foo"); /* Make sure PLT is used before macros. */ + asm ("" ::: "memory"); + +- foop = TLS_GD (foo); ++ foop = &foo; + + if (caller_foop != NULL && foop != caller_foop) + { +diff --git a/elf/tst-tlsmod3.c b/elf/tst-tlsmod3.c +index 6d186c47ee6ba104..d6e7498fd8331cb7 100644 +--- a/elf/tst-tlsmod3.c ++++ b/elf/tst-tlsmod3.c +@@ -1,10 +1,10 @@ + #include + +-#include "tls-macros.h" + + extern int in_dso (int n, int *caller_foop); + +-COMMON_INT_DEF(comm_n); ++extern __thread int foo; ++__thread int comm_n; + + + +@@ -20,8 +20,8 @@ in_dso2 (void) + puts ("foo"); /* Make sure PLT is used before macros. */ + asm ("" ::: "memory"); + +- foop = TLS_GD (foo); +- np = TLS_GD (comm_n); ++ foop = &foo; ++ np = &comm_n; + + if (n != *np) + { +diff --git a/elf/tst-tlsmod4.c b/elf/tst-tlsmod4.c +index 86889aac7e58bcf5..f38919a8a94861c1 100644 +--- a/elf/tst-tlsmod4.c ++++ b/elf/tst-tlsmod4.c +@@ -1,9 +1,7 @@ + #include + +-#include "tls-macros.h" + +- +-COMMON_INT_DEF(baz); ++__thread int baz; + + + int +@@ -15,7 +13,7 @@ in_dso (int n, int *caller_bazp) + puts ("foo"); /* Make sure PLT is used before macros. */ + asm ("" ::: "memory"); + +- bazp = TLS_GD (baz); ++ bazp = &baz; + + if (caller_bazp != NULL && bazp != caller_bazp) + { +diff --git a/elf/tst-tlsmod5.c b/elf/tst-tlsmod5.c +index a97c7e5e0c69de26..3f39c5bdb76e0b5c 100644 +--- a/elf/tst-tlsmod5.c ++++ b/elf/tst-tlsmod5.c +@@ -1,3 +1 @@ +-#include "tls-macros.h" +- +-COMMON_INT_DEF(foo); ++__thread int foo; +diff --git a/elf/tst-tlsmod6.c b/elf/tst-tlsmod6.c +index e968596dd4ef7756..7b3571f428b7243b 100644 +--- a/elf/tst-tlsmod6.c ++++ b/elf/tst-tlsmod6.c +@@ -1,3 +1 @@ +-#include "tls-macros.h" +- +-COMMON_INT_DEF(bar); ++__thread int bar; +diff --git a/sysdeps/powerpc/mod-tlsopt-powerpc.c b/sysdeps/powerpc/mod-tlsopt-powerpc.c +index 51cc502f2860e969..d941024963fc7e6a 100644 +--- a/sysdeps/powerpc/mod-tlsopt-powerpc.c ++++ b/sysdeps/powerpc/mod-tlsopt-powerpc.c +@@ -1,11 +1,9 @@ + /* shared library to test for __tls_get_addr optimization. */ + #include + +-#include "../../elf/tls-macros.h" + #include "dl-tls.h" + +-/* common 'int' variable in TLS. */ +-COMMON_INT_DEF(foo); ++__thread int foo __attribute__ ((tls_model("global-dynamic"))); + + + int +@@ -14,7 +12,7 @@ tls_get_addr_opt_test (void) + int result = 0; + + /* Get variable using general dynamic model. */ +- int *ap = TLS_GD (foo); ++ int *ap = &foo; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); +diff --git a/sysdeps/powerpc/tst-tlsifunc.c b/sysdeps/powerpc/tst-tlsifunc.c +index 3095d41a68320d72..c8c0bada4547e1a4 100644 +--- a/sysdeps/powerpc/tst-tlsifunc.c ++++ b/sysdeps/powerpc/tst-tlsifunc.c +@@ -21,9 +21,9 @@ + #include + #include + #include +-#include + + __thread int bar; ++extern __thread int bar_gd asm ("bar") __attribute__ ((tls_model("global-dynamic"))); + static int *bar_ptr = NULL; + + static uint32_t resolver_platform = 0; +@@ -57,7 +57,7 @@ get_platform (void) + void + init_foo (void) + { +- bar_ptr = TLS_GD (bar); ++ bar_ptr = &bar_gd; + } + + int diff --git a/SOURCES/glibc-upstream-2.34-375.patch b/SOURCES/glibc-upstream-2.34-375.patch new file mode 100644 index 0000000..a02bbb3 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-375.patch @@ -0,0 +1,39 @@ +commit d36f457870a807f6f29880a2f2bde5e9b761f00c +Author: Martin Sebor +Date: Tue Jan 25 17:38:31 2022 -0700 + + intl: Avoid -Wuse-after-free [BZ #26779] + + Reviewed-by: Carlos O'Donell + (cherry picked from commit 7845064d2d5a50e347ee9f4b78ec5e6316190154) + +diff --git a/intl/localealias.c b/intl/localealias.c +index 375af2b03153acce..28041f2a48f643fa 100644 +--- a/intl/localealias.c ++++ b/intl/localealias.c +@@ -318,7 +318,15 @@ read_alias_file (const char *fname, int fname_len) + + if (string_space_act + alias_len + value_len > string_space_max) + { +- /* Increase size of memory pool. */ ++#pragma GCC diagnostic push ++ ++#if defined __GNUC__ && __GNUC__ >= 12 ++ /* Suppress the valid GCC 12 warning until the code below is changed ++ to avoid using pointers to the reallocated block. */ ++# pragma GCC diagnostic ignored "-Wuse-after-free" ++#endif ++ ++ /* Increase size of memory pool. */ + size_t new_size = (string_space_max + + (alias_len + value_len > 1024 + ? alias_len + value_len : 1024)); +@@ -351,6 +359,8 @@ read_alias_file (const char *fname, int fname_len) + value, value_len); + string_space_act += value_len; + ++#pragma GCC diagnostic pop ++ + ++nmap; + ++added; + } diff --git a/SOURCES/glibc-upstream-2.34-376.patch b/SOURCES/glibc-upstream-2.34-376.patch new file mode 100644 index 0000000..d0513d9 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-376.patch @@ -0,0 +1,27 @@ +commit 92d5c52aaac0fa8e58b92e96bf2025d6848a2845 +Author: Martin Sebor +Date: Mon Oct 11 09:36:57 2021 -0600 + + resolv: Avoid GCC 12 false positive warning [BZ #28439]. + + Replace a call to sprintf with an equivalent pair of stpcpy/strcpy calls + to avoid a GCC 12 -Wformat-overflow false positive due to recent optimizer + improvements. + + (cherry picked from commit eb73b87897798de981dbbf019aa957045d768adb) + +diff --git a/resolv/res_query.c b/resolv/res_query.c +index 2f3c28cfc8c0d832..1d2c81737bc889c9 100644 +--- a/resolv/res_query.c ++++ b/resolv/res_query.c +@@ -626,7 +626,9 @@ __res_context_querydomain (struct resolv_context *ctx, + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } +- sprintf(nbuf, "%s.%s", name, domain); ++ char *p = __stpcpy (nbuf, name); ++ *p++ = '.'; ++ strcpy (p, domain); + } + return __res_context_query (ctx, longname, class, type, answer, + anslen, answerp, answerp2, nanswerp2, diff --git a/SOURCES/glibc-upstream-2.34-377.patch b/SOURCES/glibc-upstream-2.34-377.patch new file mode 100644 index 0000000..90cff64 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-377.patch @@ -0,0 +1,34 @@ +commit 26c7c6bac9da305b634a661aa491dae2756581ec +Author: Joseph Myers +Date: Tue Oct 5 14:25:40 2021 +0000 + + Fix stdlib/tst-setcontext.c for GCC 12 -Warray-compare + + Building stdlib/tst-setcontext.c fails with GCC mainline: + + tst-setcontext.c: In function 'f2': + tst-setcontext.c:61:16: error: comparison between two arrays [-Werror=array-compare] + 61 | if (on_stack < st2 || on_stack >= st2 + sizeof (st2)) + | ^ + tst-setcontext.c:61:16: note: use '&on_stack[0] < &st2[0]' to compare the addresses + + The comparison in this case is deliberate, so adjust it as suggested + in that note. + + Tested with build-many-glibcs.py (GCC mainline) for aarch64-linux-gnu. + + (cherry picked from commit a0f0c08e4fe18e78866539b0571f8e4b57dba7a3) + +diff --git a/stdlib/tst-setcontext.c b/stdlib/tst-setcontext.c +index 1b511708c1469444..1c2925bb760c9eb4 100644 +--- a/stdlib/tst-setcontext.c ++++ b/stdlib/tst-setcontext.c +@@ -58,7 +58,7 @@ f2 (void) + puts ("start f2"); + + printf ("&on_stack=%p\n", on_stack); +- if (on_stack < st2 || on_stack >= st2 + sizeof (st2)) ++ if (&on_stack[0] < &st2[0] || &on_stack[0] >= st2 + sizeof (st2)) + { + printf ("%s: memory stack is not where it belongs!", __FUNCTION__); + exit (1); diff --git a/SOURCES/glibc-upstream-2.34-378.patch b/SOURCES/glibc-upstream-2.34-378.patch new file mode 100644 index 0000000..76de777 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-378.patch @@ -0,0 +1,86 @@ +commit 6ff61a51459d141782fbcc32ae81c0ef1954dad6 +Author: Joseph Myers +Date: Mon Oct 4 19:10:43 2021 +0000 + + Fix stdio-common tests for GCC 12 -Waddress + + My glibc bot shows failures building the testsuite with GCC mainline + across all architectures: + + tst-vfprintf-width-prec.c: In function 'do_test': + tst-vfprintf-width-prec.c:90:16: error: the comparison will always evaluate as 'false' for the address of 'result' will never be NULL [-Werror=address] + 90 | if (result == NULL) + | ^~ + tst-vfprintf-width-prec.c:89:13: note: 'result' declared here + 89 | wchar_t result[100]; + | ^~~~~~ + + This is clearly a correct warning; the comparison against NULL is + clearly a cut-and-paste mistake from an earlier case in the test that + does use calloc. Thus, remove the unnecessary check for NULL shown up + by the warning. + + Similarly, two other tests have bogus comparisons against NULL; remove + those as well: + + scanf14a.c:95:13: error: the comparison will always evaluate as 'false' for the address of 'fname' will never be NULL [-Werror=address] + 95 | if (fname == NULL) + | ^~ + scanf14a.c:93:8: note: 'fname' declared here + 93 | char fname[strlen (tmpdir) + sizeof "/tst-scanf14.XXXXXX"]; + | ^~~~~ + + scanf16a.c:125:13: error: the comparison will always evaluate as 'false' for the address of 'fname' will never be NULL [-Werror=address] + 125 | if (fname == NULL) + | ^~ + scanf16a.c:123:8: note: 'fname' declared here + 123 | char fname[strlen (tmpdir) + sizeof "/tst-scanf16.XXXXXX"]; + | ^~~~~ + + Tested with build-many-glibcs.py (GCC mainline) for aarch64-linux-gnu. + + (cherry picked from commit a312e8fe6d89f5eae6a4583d5db577121e61c0b5) + +diff --git a/stdio-common/scanf14a.c b/stdio-common/scanf14a.c +index 12adcff5a4970da1..b37712d1c673fa3a 100644 +--- a/stdio-common/scanf14a.c ++++ b/stdio-common/scanf14a.c +@@ -92,8 +92,6 @@ main (void) + + char fname[strlen (tmpdir) + sizeof "/tst-scanf14.XXXXXX"]; + sprintf (fname, "%s/tst-scanf14.XXXXXX", tmpdir); +- if (fname == NULL) +- FAIL (); + + /* Create a temporary file. */ + int fd = mkstemp (fname); +diff --git a/stdio-common/scanf16a.c b/stdio-common/scanf16a.c +index 400d85a54e81c3cb..74d0295c97f73b14 100644 +--- a/stdio-common/scanf16a.c ++++ b/stdio-common/scanf16a.c +@@ -122,8 +122,6 @@ main (void) + + char fname[strlen (tmpdir) + sizeof "/tst-scanf16.XXXXXX"]; + sprintf (fname, "%s/tst-scanf16.XXXXXX", tmpdir); +- if (fname == NULL) +- FAIL (); + + /* Create a temporary file. */ + int fd = mkstemp (fname); +diff --git a/stdio-common/tst-vfprintf-width-prec.c b/stdio-common/tst-vfprintf-width-prec.c +index 3192fd797ad4ea90..278d57f739f576e9 100644 +--- a/stdio-common/tst-vfprintf-width-prec.c ++++ b/stdio-common/tst-vfprintf-width-prec.c +@@ -87,12 +87,6 @@ do_test (void) + } + { + wchar_t result[100]; +- if (result == NULL) +- { +- printf ("error: calloc (%d, %zu): %m", ret + 1, sizeof (wchar_t)); +- return 1; +- } +- + ret = swprintf (result, 100, L"%133000.999999999x", 17); + if (ret >= 0) + { diff --git a/SOURCES/glibc-upstream-2.34-379.patch b/SOURCES/glibc-upstream-2.34-379.patch new file mode 100644 index 0000000..8ceaa45 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-379.patch @@ -0,0 +1,33 @@ +commit 803c959745fd7c679e00f9bad58822616f0e51cb +Author: Joseph Myers +Date: Mon Aug 2 16:33:44 2021 +0000 + + Fix build of nptl/tst-thread_local1.cc with GCC 12 + + The test nptl/tst-thread_local1.cc fails to build with GCC mainline + because of changes to what libstdc++ headers implicitly include what + other headers: + + tst-thread_local1.cc: In function 'int do_test()': + tst-thread_local1.cc:177:5: error: variable 'std::array >, 2> do_thread_X' has initializer but incomplete type + 177 | do_thread_X + | ^~~~~~~~~~~ + + Fix this by adding an explicit include of . + + Tested with build-many-glibcs.py for aarch64-linux-gnu. + + (cherry picked from commit 2ee9b24f47db8d0a8d0ccadb999335a1d4cfc364) + +diff --git a/nptl/tst-thread_local1.cc b/nptl/tst-thread_local1.cc +index 9608afa4b739e360..338aafea059e10b7 100644 +--- a/nptl/tst-thread_local1.cc ++++ b/nptl/tst-thread_local1.cc +@@ -21,6 +21,7 @@ + #include + #include + ++#include + #include + #include + #include diff --git a/SOURCES/glibc-upstream-2.34-380.patch b/SOURCES/glibc-upstream-2.34-380.patch new file mode 100644 index 0000000..509a9e8 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-380.patch @@ -0,0 +1,176 @@ +commit 88b3228d9f6322b035fa89bb34f82d93b4190d48 +Author: Martin Sebor +Date: Tue Jan 25 15:39:38 2022 -0700 + + Avoid -Wuse-after-free in tests [BZ #26779]. + + Reviewed-by: Carlos O'Donell + (cherry picked from commit c094c232eb3246154265bb035182f92fe1b17ab8) + +diff --git a/malloc/tst-malloc-backtrace.c b/malloc/tst-malloc-backtrace.c +index 4eb42e7f32f706e9..2ae3fb11efc245cb 100644 +--- a/malloc/tst-malloc-backtrace.c ++++ b/malloc/tst-malloc-backtrace.c +@@ -20,6 +20,7 @@ + #include + + #include ++#include + + #define SIZE 4096 + +@@ -29,7 +30,15 @@ __attribute__((noinline)) + call_free (void *ptr) + { + free (ptr); ++#if __GNUC_PREREQ (12, 0) ++ /* Ignore a valid warning about using a pointer made indeterminate ++ by a prior call to free(). */ ++ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free"); ++#endif + *(size_t *)(ptr - sizeof (size_t)) = 1; ++#if __GNUC_PREREQ (12, 0) ++ DIAG_POP_NEEDS_COMMENT; ++#endif + } + + int +diff --git a/malloc/tst-malloc-check.c b/malloc/tst-malloc-check.c +index 6650d09cf6cdde75..c5c9254a9e8936b0 100644 +--- a/malloc/tst-malloc-check.c ++++ b/malloc/tst-malloc-check.c +@@ -87,7 +87,15 @@ do_test (void) + merror ("errno is not set correctly."); + DIAG_POP_NEEDS_COMMENT; + ++#if __GNUC_PREREQ (12, 0) ++ /* Ignore a valid warning about using a pointer made indeterminate ++ by a prior call to realloc(). */ ++ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free"); ++#endif + free (p); ++#if __GNUC_PREREQ (12, 0) ++ DIAG_POP_NEEDS_COMMENT; ++#endif + + p = malloc (512); + if (p == NULL) +@@ -105,7 +113,15 @@ do_test (void) + merror ("errno is not set correctly."); + DIAG_POP_NEEDS_COMMENT; + ++#if __GNUC_PREREQ (12, 0) ++ /* Ignore a valid warning about using a pointer made indeterminate ++ by a prior call to realloc(). */ ++ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free"); ++#endif + free (p); ++#if __GNUC_PREREQ (12, 0) ++ DIAG_POP_NEEDS_COMMENT; ++#endif + free (q); + + return errors != 0; +diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c +index a4349a9b4c506dfc..328b4a2a4fd72cf4 100644 +--- a/malloc/tst-malloc-too-large.c ++++ b/malloc/tst-malloc-too-large.c +@@ -95,7 +95,15 @@ test_large_allocations (size_t size) + DIAG_POP_NEEDS_COMMENT; + #endif + TEST_VERIFY (errno == ENOMEM); ++#if __GNUC_PREREQ (12, 0) ++ /* Ignore a warning about using a pointer made indeterminate by ++ a prior call to realloc(). */ ++ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free"); ++#endif + free (ptr_to_realloc); ++#if __GNUC_PREREQ (12, 0) ++ DIAG_POP_NEEDS_COMMENT; ++#endif + + for (size_t nmemb = 1; nmemb <= 8; nmemb *= 2) + if ((size % nmemb) == 0) +@@ -113,14 +121,30 @@ test_large_allocations (size_t size) + test_setup (); + TEST_VERIFY (reallocarray (ptr_to_realloc, nmemb, size / nmemb) == NULL); + TEST_VERIFY (errno == ENOMEM); ++#if __GNUC_PREREQ (12, 0) ++ /* Ignore a warning about using a pointer made indeterminate by ++ a prior call to realloc(). */ ++ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free"); ++#endif + free (ptr_to_realloc); ++#if __GNUC_PREREQ (12, 0) ++ DIAG_POP_NEEDS_COMMENT; ++#endif + + ptr_to_realloc = malloc (16); + TEST_VERIFY_EXIT (ptr_to_realloc != NULL); + test_setup (); + TEST_VERIFY (reallocarray (ptr_to_realloc, size / nmemb, nmemb) == NULL); + TEST_VERIFY (errno == ENOMEM); ++#if __GNUC_PREREQ (12, 0) ++ /* Ignore a warning about using a pointer made indeterminate by ++ a prior call to realloc(). */ ++ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free"); ++#endif + free (ptr_to_realloc); ++#if __GNUC_PREREQ (12, 0) ++ DIAG_POP_NEEDS_COMMENT; ++#endif + } + else + break; +diff --git a/malloc/tst-obstack.c b/malloc/tst-obstack.c +index ee1385d0f764e368..7d700c4f9a86b676 100644 +--- a/malloc/tst-obstack.c ++++ b/malloc/tst-obstack.c +@@ -21,8 +21,8 @@ verbose_malloc (size_t size) + static void + verbose_free (void *buf) + { +- free (buf); + printf ("free (%p)\n", buf); ++ free (buf); + } + + static int +diff --git a/malloc/tst-realloc.c b/malloc/tst-realloc.c +index c89ac07e192d70eb..80711beab1257ed5 100644 +--- a/malloc/tst-realloc.c ++++ b/malloc/tst-realloc.c +@@ -138,8 +138,16 @@ do_test (void) + if (ok == 0) + merror ("first 16 bytes were not correct after failed realloc"); + ++#if __GNUC_PREREQ (12, 0) ++ /* Ignore a valid warning about using a pointer made indeterminate ++ by a prior call to realloc(). */ ++ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free"); ++#endif + /* realloc (p, 0) frees p (C89) and returns NULL (glibc). */ + p = realloc (p, 0); ++#if __GNUC_PREREQ (12, 0) ++ DIAG_POP_NEEDS_COMMENT; ++#endif + if (p != NULL) + merror ("realloc (p, 0) returned non-NULL."); + +diff --git a/support/tst-support-open-dev-null-range.c b/support/tst-support-open-dev-null-range.c +index 8e29def1ce780629..80c97e51586bf6ce 100644 +--- a/support/tst-support-open-dev-null-range.c ++++ b/support/tst-support-open-dev-null-range.c +@@ -39,10 +39,11 @@ check_path (int fd) + char file_path[PATH_MAX]; + ssize_t file_path_length + = readlink (proc_fd_path, file_path, sizeof (file_path)); +- free (proc_fd_path); + if (file_path_length < 0) + FAIL_EXIT1 ("readlink (%s, %p, %zu)", proc_fd_path, file_path, + sizeof (file_path)); ++ ++ free (proc_fd_path); + file_path[file_path_length] = '\0'; + TEST_COMPARE_STRING (file_path, "/dev/null"); + } diff --git a/SOURCES/glibc-upstream-2.34-381.patch b/SOURCES/glibc-upstream-2.34-381.patch new file mode 100644 index 0000000..f123f25 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-381.patch @@ -0,0 +1,28 @@ +commit dd0c72fb461a8879164588cd870702efae0c7237 +Author: H.J. Lu +Date: Mon Dec 20 15:15:12 2021 -0800 + + Regenerate ulps on x86_64 with GCC 12 + + Fix + + FAIL: math/test-float-clog10 + FAIL: math/test-float32-clog10 + + on Intel Core i7-1165G7 with GCC 12. + + (cherry picked from commit de8a0897e3c084dc93676e331b610f146000a0ab) + +diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps +index 312575f93397c4b0..1c75f0ead46819a7 100644 +--- a/sysdeps/x86_64/fpu/libm-test-ulps ++++ b/sysdeps/x86_64/fpu/libm-test-ulps +@@ -705,7 +705,7 @@ ldouble: 3 + + Function: Real part of "clog10_towardzero": + double: 5 +-float: 5 ++float: 6 + float128: 4 + ldouble: 8 + diff --git a/SOURCES/glibc-upstream-2.34-382.patch b/SOURCES/glibc-upstream-2.34-382.patch new file mode 100644 index 0000000..e82998c --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-382.patch @@ -0,0 +1,111 @@ +commit 80b24b86548eee3d96130a48e760d1d6c2e0c587 +Author: H.J. Lu +Date: Mon Dec 20 15:00:24 2021 -0800 + + math: Properly cast X_TLOSS to float [BZ #28713] + + Add + + #define AS_FLOAT_CONSTANT_1(x) x##f + #define AS_FLOAT_CONSTANT(x) AS_FLOAT_CONSTANT_1(x) + + to cast X_TLOSS to float at compile-time to fix: + + FAIL: math/test-float-j0 + FAIL: math/test-float-jn + FAIL: math/test-float-y0 + FAIL: math/test-float-y1 + FAIL: math/test-float-yn + FAIL: math/test-float32-j0 + FAIL: math/test-float32-jn + FAIL: math/test-float32-y0 + FAIL: math/test-float32-y1 + FAIL: math/test-float32-yn + + when compiling with GCC 12. + + Reviewed-by: Paul Zimmermann + (cherry picked from commit 6e30181b4a3ab6c56da0378b65f4d60504982300) + +diff --git a/math/math-svid-compat.h b/math/math-svid-compat.h +index 5c18cb1b039cb3be..876cadde4084dab0 100644 +--- a/math/math-svid-compat.h ++++ b/math/math-svid-compat.h +@@ -49,6 +49,8 @@ extern int matherr (struct exception *__exc); + extern int __matherr (struct exception *__exc); + + #define X_TLOSS 1.41484755040568800000e+16 ++#define AS_FLOAT_CONSTANT_1(x) x##f ++#define AS_FLOAT_CONSTANT(x) AS_FLOAT_CONSTANT_1(x) + + /* Types of exceptions in the `type' field. */ + #define DOMAIN 1 +diff --git a/math/w_j0f_compat.c b/math/w_j0f_compat.c +index a4882eadb33853b2..f35a55219f7baa78 100644 +--- a/math/w_j0f_compat.c ++++ b/math/w_j0f_compat.c +@@ -28,7 +28,8 @@ + float + __j0f (float x) + { +- if (__builtin_expect (isgreater (fabsf (x), (float) X_TLOSS), 0) ++ if (__builtin_expect (isgreater (fabsf (x), ++ AS_FLOAT_CONSTANT (X_TLOSS)), 0) + && _LIB_VERSION != _IEEE_ && _LIB_VERSION != _POSIX_) + /* j0(|x|>X_TLOSS) */ + return __kernel_standard_f (x, x, 134); +@@ -43,7 +44,7 @@ float + __y0f (float x) + { + if (__builtin_expect (islessequal (x, 0.0f) +- || isgreater (x, (float) X_TLOSS), 0) ++ || isgreater (x, AS_FLOAT_CONSTANT (X_TLOSS)), 0) + && _LIB_VERSION != _IEEE_) + { + if (x < 0.0f) +diff --git a/math/w_j1f_compat.c b/math/w_j1f_compat.c +index f2ec7b327d2bc90a..c5e3ccd035031799 100644 +--- a/math/w_j1f_compat.c ++++ b/math/w_j1f_compat.c +@@ -28,7 +28,8 @@ + float + __j1f (float x) + { +- if (__builtin_expect (isgreater (fabsf (x), X_TLOSS), 0) ++ if (__builtin_expect (isgreater (fabsf (x), ++ AS_FLOAT_CONSTANT (X_TLOSS)), 0) + && _LIB_VERSION != _IEEE_ && _LIB_VERSION != _POSIX_) + /* j1(|x|>X_TLOSS) */ + return __kernel_standard_f (x, x, 136); +@@ -43,7 +44,7 @@ float + __y1f (float x) + { + if (__builtin_expect (islessequal (x, 0.0f) +- || isgreater (x, (float) X_TLOSS), 0) ++ || isgreater (x, AS_FLOAT_CONSTANT (X_TLOSS)), 0) + && _LIB_VERSION != _IEEE_) + { + if (x < 0.0f) +diff --git a/math/w_jnf_compat.c b/math/w_jnf_compat.c +index fb6e5060096fb070..925ccc4cd0988a8f 100644 +--- a/math/w_jnf_compat.c ++++ b/math/w_jnf_compat.c +@@ -28,7 +28,8 @@ + float + __jnf (int n, float x) + { +- if (__builtin_expect (isgreater (fabsf (x), (float) X_TLOSS), 0) ++ if (__builtin_expect (isgreater (fabsf (x), ++ AS_FLOAT_CONSTANT (X_TLOSS)), 0) + && _LIB_VERSION != _IEEE_ && _LIB_VERSION != _POSIX_) + /* jn(n,|x|>X_TLOSS) */ + return __kernel_standard_f (n, x, 138); +@@ -43,7 +44,7 @@ float + __ynf (int n, float x) + { + if (__builtin_expect (islessequal (x, 0.0f) +- || isgreater (x, (float) X_TLOSS), 0) ++ || isgreater (x, AS_FLOAT_CONSTANT (X_TLOSS)), 0) + && _LIB_VERSION != _IEEE_) + { + if (x < 0.0f) diff --git a/SOURCES/glibc-upstream-2.34-383.patch b/SOURCES/glibc-upstream-2.34-383.patch new file mode 100644 index 0000000..25a4892 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-383.patch @@ -0,0 +1,43 @@ +commit c5c666f34939d4bbf73aac8b753ab39621ebf33c +Author: H.J. Lu +Date: Mon Dec 20 14:37:26 2021 -0800 + + s_sincosf.h: Change pio4 type to float [BZ #28713] + + s_cosf.c and s_sinf.c have + + if (abstop12 (y) < abstop12 (pio4)) + + where abstop12 takes a float argument, but pio4 is static const double. + pio4 is used only in calls to abstop12 and never in arithmetic. Apply + + -static const double pio4 = 0x1.921FB54442D18p-1; + +static const float pio4 = 0x1.921FB6p-1f; + + to fix: + + FAIL: math/test-float-cos + FAIL: math/test-float-sin + FAIL: math/test-float-sincos + FAIL: math/test-float32-cos + FAIL: math/test-float32-sin + FAIL: math/test-float32-sincos + + when compiling with GCC 12. + + Reviewed-by: Paul Zimmermann + (cherry picked from commit d3e4f5a1014db09ff1c62c6506f92cba469e193d) + +diff --git a/sysdeps/ieee754/flt-32/s_sincosf.h b/sysdeps/ieee754/flt-32/s_sincosf.h +index 125ab7f846c463c6..372d8542c2c9a9c7 100644 +--- a/sysdeps/ieee754/flt-32/s_sincosf.h ++++ b/sysdeps/ieee754/flt-32/s_sincosf.h +@@ -24,7 +24,7 @@ + /* 2PI * 2^-64. */ + static const double pi63 = 0x1.921FB54442D18p-62; + /* PI / 4. */ +-static const double pio4 = 0x1.921FB54442D18p-1; ++static const float pio4 = 0x1.921FB6p-1f; + + /* Polynomial data (the cosine polynomial is negated in the 2nd entry). */ + extern const sincos_t __sincosf_table[2] attribute_hidden; diff --git a/SOURCES/glibc-upstream-2.34-384.patch b/SOURCES/glibc-upstream-2.34-384.patch new file mode 100644 index 0000000..1dfffbe --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-384.patch @@ -0,0 +1,83 @@ +commit 6484ae5b8c4d4314f748e4d3c9a9baa5385e57c5 +Author: Carlos O'Donell +Date: Fri Jan 28 15:14:29 2022 -0500 + + malloc: Fix -Wuse-after-free warning in tst-mallocalign1 [BZ #26779] + + The test leaks bits from the freed pointer via the return value + in ret, and the compiler correctly identifies this issue. + We switch the test to use TEST_VERIFY and terminate the test + if any of the pointers return an unexpected alignment. + + This fixes another -Wuse-after-free error when compiling glibc + with gcc 12. + + Tested on x86_64 and i686 without regression. + + Reviewed-by: Siddhesh Poyarekar + (cherry picked from commit 3a7bed5f5a527dbd87412551f41e42e63aeef07a) + +diff --git a/malloc/tst-mallocalign1.c b/malloc/tst-mallocalign1.c +index 294e821afebd25ac..3e09ff30c4aa9f91 100644 +--- a/malloc/tst-mallocalign1.c ++++ b/malloc/tst-mallocalign1.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + static void * + test (size_t s) +@@ -31,41 +32,42 @@ test (size_t s) + return p; + } + ++#define ALIGNED(p) (((uintptr_t )p & MALLOC_ALIGN_MASK) == 0) ++ + static int + do_test (void) + { + void *p; +- int ret = 0; + + p = test (2); +- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK; ++ TEST_VERIFY (ALIGNED (p)); + free (p); + + p = test (8); +- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK; ++ TEST_VERIFY (ALIGNED (p)); + free (p); + + p = test (13); +- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK; ++ TEST_VERIFY (ALIGNED (p)); + free (p); + + p = test (16); +- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK; ++ TEST_VERIFY (ALIGNED (p)); + free (p); + + p = test (23); +- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK; ++ TEST_VERIFY (ALIGNED (p)); + free (p); + + p = test (43); +- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK; ++ TEST_VERIFY (ALIGNED (p)); + free (p); + + p = test (123); +- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK; ++ TEST_VERIFY (ALIGNED (p)); + free (p); + +- return ret; ++ return 0; + } + + #include diff --git a/SOURCES/glibc-upstream-2.34-385.patch b/SOURCES/glibc-upstream-2.34-385.patch new file mode 100644 index 0000000..d952d48 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-385.patch @@ -0,0 +1,48 @@ +commit c5c792092b57687ae3ebecbe8645fa71ddb19f8c +Author: Siddhesh Poyarekar +Date: Thu Feb 2 07:49:02 2023 -0500 + + cdefs: Limit definition of fortification macros + + Define the __glibc_fortify and other macros only when __FORTIFY_LEVEL > + 0. This has the effect of not defining these macros on older C90 + compilers that do not have support for variable length argument lists. + + Also trim off the trailing backslashes from the definition of + __glibc_fortify and __glibc_fortify_n macros. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Florian Weimer + (cherry picked from commit 2337e04e21ba6040926ec871e403533f77043c40) + +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index b166f3d209fe361f..92dbd3e1fc68dae7 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -151,6 +151,7 @@ + # define __glibc_objsize(__o) __bos (__o) + #endif + ++#if __USE_FORTIFY_LEVEL > 0 + /* Compile time conditions to choose between the regular, _chk and _chk_warn + variants. These conditions should get evaluated to constant and optimized + away. */ +@@ -186,7 +187,7 @@ + ? __ ## f ## _alias (__VA_ARGS__) \ + : (__glibc_unsafe_len (__l, __s, __osz) \ + ? __ ## f ## _chk_warn (__VA_ARGS__, __osz) \ +- : __ ## f ## _chk (__VA_ARGS__, __osz))) \ ++ : __ ## f ## _chk (__VA_ARGS__, __osz))) + + /* Fortify function f, where object size argument passed to f is the number of + elements and not total size. */ +@@ -196,7 +197,8 @@ + ? __ ## f ## _alias (__VA_ARGS__) \ + : (__glibc_unsafe_len (__l, __s, __osz) \ + ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s)) \ +- : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s)))) \ ++ : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s)))) ++#endif + + #if __GNUC_PREREQ (4,3) + # define __warnattr(msg) __attribute__((__warning__ (msg))) diff --git a/SOURCES/glibc-upstream-2.34-386.patch b/SOURCES/glibc-upstream-2.34-386.patch new file mode 100644 index 0000000..fc111d4 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-386.patch @@ -0,0 +1,127 @@ +commit 0b962177ee3b45cf775176eb454fcf6aa1b0f6e3 +Author: Andreas Schwab +Date: Thu Jan 26 14:25:05 2023 +0100 + + Use 64-bit time_t interfaces in strftime and strptime (bug 30053) + + Both functions use time_t only internally, so the ABI is not affected. + + (cherry picked from commit 41349f6f67c83e7bafe49f985b56493d2c4c9c77) + +diff --git a/time/Makefile b/time/Makefile +index 38e3a7f4c77ea27f..ef3bb767b825f76a 100644 +--- a/time/Makefile ++++ b/time/Makefile +@@ -50,7 +50,7 @@ tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \ + tst-clock tst-clock2 tst-clock_nanosleep tst-cpuclock1 \ + tst-adjtime tst-ctime tst-difftime tst-mktime4 tst-clock_settime \ + tst-settimeofday tst-itimer tst-gmtime tst-timegm \ +- tst-timespec_get tst-timespec_getres ++ tst-timespec_get tst-timespec_getres tst-strftime4 + + tests-time64 := \ + tst-adjtime-time64 \ +@@ -65,6 +65,7 @@ tests-time64 := \ + tst-itimer-time64 \ + tst-mktime4-time64 \ + tst-settimeofday-time64 \ ++ tst-strftime4-time64 \ + tst-timegm-time64 \ + tst-timespec_get-time64 \ + tst-timespec_getres-time64 \ +diff --git a/time/strftime_l.c b/time/strftime_l.c +index d8cde9c5a3af87c7..57abbaa571694505 100644 +--- a/time/strftime_l.c ++++ b/time/strftime_l.c +@@ -159,6 +159,10 @@ extern char *tzname[]; + #ifdef _LIBC + # define tzname __tzname + # define tzset __tzset ++ ++# define time_t __time64_t ++# define __gmtime_r(t, tp) __gmtime64_r (t, tp) ++# define mktime(tp) __mktime64 (tp) + #endif + + #if !HAVE_TM_GMTOFF +diff --git a/time/strptime_l.c b/time/strptime_l.c +index 02c5d63c798f9c13..39d1e59b0871f4b4 100644 +--- a/time/strptime_l.c ++++ b/time/strptime_l.c +@@ -30,8 +30,10 @@ + #ifdef _LIBC + # define HAVE_LOCALTIME_R 0 + # include "../locale/localeinfo.h" +-#endif + ++# define time_t __time64_t ++# define __localtime_r(t, tp) __localtime64_r (t, tp) ++#endif + + #if ! HAVE_LOCALTIME_R && ! defined localtime_r + # ifdef _LIBC +diff --git a/time/tst-strftime4-time64.c b/time/tst-strftime4-time64.c +new file mode 100644 +index 0000000000000000..4d47ee7d79f9e648 +--- /dev/null ++++ b/time/tst-strftime4-time64.c +@@ -0,0 +1 @@ ++#include "tst-strftime4.c" +diff --git a/time/tst-strftime4.c b/time/tst-strftime4.c +new file mode 100644 +index 0000000000000000..659716d0fa4534ae +--- /dev/null ++++ b/time/tst-strftime4.c +@@ -0,0 +1,52 @@ ++/* Test strftime and strptime after 2038-01-19 03:14:07 UTC (bug 30053). ++ Copyright (C) 2023 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 ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ TEST_VERIFY_EXIT (setenv ("TZ", "UTC0", 1) == 0); ++ tzset (); ++ if (sizeof (time_t) > 4) ++ { ++ time_t wrap = (time_t) 2147483648LL; ++ char buf[80]; ++ struct tm *tm = gmtime (&wrap); ++ TEST_VERIFY_EXIT (tm != NULL); ++ TEST_VERIFY_EXIT (strftime (buf, sizeof buf, "%s", tm) > 0); ++ puts (buf); ++ TEST_VERIFY (strcmp (buf, "2147483648") == 0); ++ ++ struct tm tm2; ++ char *p = strptime (buf, "%s", &tm2); ++ TEST_VERIFY_EXIT (p != NULL && *p == '\0'); ++ time_t t = mktime (&tm2); ++ printf ("%lld\n", (long long) t); ++ TEST_VERIFY (t == wrap); ++ } ++ else ++ FAIL_UNSUPPORTED ("32-bit time_t"); ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-upstream-2.34-388.patch b/SOURCES/glibc-upstream-2.34-388.patch new file mode 100644 index 0000000..f749370 --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-388.patch @@ -0,0 +1,328 @@ +commit 11ad405fd4c4c9f320d461d9ae1dd2e087cc8c32 +Author: Adhemerval Zanella +Date: Wed Dec 29 10:20:46 2021 -0300 + + elf: Fix 64 time_t support for installed statically binaries + + The usage of internal static symbol for statically linked binaries + does not work correctly for objects built with -D_TIME_BITS=64, + since the internal definition does not provide the expected aliases. + + This patch makes it to use the default stat functions instead (which + uses the default 64 time_t alias and types). + + Checked on i686-linux-gnu. + + Reviewed-by: Carlos O'Donell + Tested-by: Carlos O'Donell + (cherry picked from commit 9fe6f6363886aae6b2b210cae3ed1f5921299083) + +diff --git a/elf/cache.c b/elf/cache.c +index 8a3404923c625d18..062ec7fb0c9c300f 100644 +--- a/elf/cache.c ++++ b/elf/cache.c +@@ -319,8 +319,8 @@ print_cache (const char *cache_name) + if (fd < 0) + error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name); + +- struct stat64 st; +- if (__fstat64 (fd, &st) < 0 ++ struct stat st; ++ if (fstat (fd, &st) < 0 + /* No need to map the file if it is empty. */ + || st.st_size == 0) + { +@@ -933,7 +933,7 @@ init_aux_cache (void) + } + + int +-search_aux_cache (struct stat64 *stat_buf, int *flags, ++search_aux_cache (struct stat *stat_buf, int *flags, + unsigned int *osversion, unsigned int *isa_level, + char **soname) + { +@@ -995,7 +995,7 @@ insert_to_aux_cache (struct aux_cache_entry_id *id, int flags, + } + + void +-add_to_aux_cache (struct stat64 *stat_buf, int flags, ++add_to_aux_cache (struct stat *stat_buf, int flags, + unsigned int osversion, unsigned int isa_level, + const char *soname) + { +@@ -1018,8 +1018,8 @@ load_aux_cache (const char *aux_cache_name) + return; + } + +- struct stat64 st; +- if (__fstat64 (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file)) ++ struct stat st; ++ if (fstat (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file)) + { + close (fd); + init_aux_cache (); +@@ -1135,8 +1135,8 @@ save_aux_cache (const char *aux_cache_name) + char *dir = strdupa (aux_cache_name); + dir = dirname (dir); + +- struct stat64 st; +- if (stat64 (dir, &st) < 0) ++ struct stat st; ++ if (stat (dir, &st) < 0) + { + if (mkdir (dir, 0700) < 0) + goto out_fail; +diff --git a/elf/chroot_canon.c b/elf/chroot_canon.c +index 045611e730be9e41..a70fd25046112290 100644 +--- a/elf/chroot_canon.c ++++ b/elf/chroot_canon.c +@@ -67,7 +67,7 @@ chroot_canon (const char *chroot, const char *name) + + for (start = end = name; *start; start = end) + { +- struct stat64 st; ++ struct stat st; + + /* Skip sequence of multiple path-separators. */ + while (*start == '/') +@@ -114,7 +114,7 @@ chroot_canon (const char *chroot, const char *name) + dest = mempcpy (dest, start, end - start); + *dest = '\0'; + +- if (lstat64 (rpath, &st) < 0) ++ if (lstat (rpath, &st) < 0) + { + if (*end == '\0') + goto done; +diff --git a/elf/ldconfig.c b/elf/ldconfig.c +index b8893637f8aaea8d..be47ad8c2d7f89f3 100644 +--- a/elf/ldconfig.c ++++ b/elf/ldconfig.c +@@ -338,7 +338,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ + inode data from *ST. */ + static struct dir_entry * + new_sub_entry (const struct dir_entry *entry, const char *path, +- const struct stat64 *st) ++ const struct stat *st) + { + struct dir_entry *new_entry = xmalloc (sizeof (struct dir_entry)); + new_entry->from_file = entry->from_file; +@@ -428,8 +428,8 @@ add_glibc_hwcaps_subdirectories (struct dir_entry *entry, const char *path) + continue; + + /* See if this entry eventually resolves to a directory. */ +- struct stat64 st; +- if (fstatat64 (dirfd (dir), e->d_name, &st, 0) < 0) ++ struct stat st; ++ if (fstatat (dirfd (dir), e->d_name, &st, 0) < 0) + /* Ignore unreadable entries. */ + continue; + +@@ -513,8 +513,8 @@ add_dir_1 (const char *line, const char *from_file, int from_line) + if (opt_chroot != NULL) + path = chroot_canon (opt_chroot, path); + +- struct stat64 stat_buf; +- if (path == NULL || stat64 (path, &stat_buf)) ++ struct stat stat_buf; ++ if (path == NULL || stat (path, &stat_buf)) + { + if (opt_verbose) + error (0, errno, _("Can't stat %s"), entry->path); +@@ -542,15 +542,15 @@ add_dir (const char *line) + } + + static int +-chroot_stat (const char *real_path, const char *path, struct stat64 *st) ++chroot_stat (const char *real_path, const char *path, struct stat *st) + { + int ret; + char *canon_path; + + if (!opt_chroot) +- return stat64 (real_path, st); ++ return stat (real_path, st); + +- ret = lstat64 (real_path, st); ++ ret = lstat (real_path, st); + if (ret || !S_ISLNK (st->st_mode)) + return ret; + +@@ -558,7 +558,7 @@ chroot_stat (const char *real_path, const char *path, struct stat64 *st) + if (canon_path == NULL) + return -1; + +- ret = stat64 (canon_path, st); ++ ret = stat (canon_path, st); + free (canon_path); + return ret; + } +@@ -570,7 +570,7 @@ create_links (const char *real_path, const char *path, const char *libname, + { + char *full_libname, *full_soname; + char *real_full_libname, *real_full_soname; +- struct stat64 stat_lib, stat_so, lstat_so; ++ struct stat stat_lib, stat_so, lstat_so; + int do_link = 1; + int do_remove = 1; + /* XXX: The logics in this function should be simplified. */ +@@ -605,7 +605,7 @@ create_links (const char *real_path, const char *path, const char *libname, + && stat_lib.st_ino == stat_so.st_ino) + /* Link is already correct. */ + do_link = 0; +- else if (lstat64 (full_soname, &lstat_so) == 0 ++ else if (lstat (full_soname, &lstat_so) == 0 + && !S_ISLNK (lstat_so.st_mode)) + { + error (0, 0, _("%s is not a symbolic link\n"), full_soname); +@@ -613,7 +613,7 @@ create_links (const char *real_path, const char *path, const char *libname, + do_remove = 0; + } + } +- else if (lstat64 (real_full_soname, &lstat_so) != 0 ++ else if (lstat (real_full_soname, &lstat_so) != 0 + || !S_ISLNK (lstat_so.st_mode)) + /* Unless it is a stale symlink, there is no need to remove. */ + do_remove = 0; +@@ -657,7 +657,7 @@ manual_link (char *library) + char *real_library; + char *libname; + char *soname; +- struct stat64 stat_buf; ++ struct stat stat_buf; + int flag; + unsigned int osversion; + unsigned int isa_level; +@@ -711,7 +711,7 @@ manual_link (char *library) + } + + /* Do some sanity checks first. */ +- if (lstat64 (real_library, &stat_buf)) ++ if (lstat (real_library, &stat_buf)) + { + error (0, errno, _("Cannot lstat %s"), library); + goto out; +@@ -886,18 +886,18 @@ search_dir (const struct dir_entry *entry) + sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name); + } + +- struct stat64 lstat_buf; ++ struct stat lstat_buf; + /* We optimize and try to do the lstat call only if needed. */ + if (direntry->d_type != DT_UNKNOWN) + lstat_buf.st_mode = DTTOIF (direntry->d_type); + else +- if (__glibc_unlikely (lstat64 (real_file_name, &lstat_buf))) ++ if (__glibc_unlikely (lstat (real_file_name, &lstat_buf))) + { + error (0, errno, _("Cannot lstat %s"), file_name); + continue; + } + +- struct stat64 stat_buf; ++ struct stat stat_buf; + bool is_dir; + int is_link = S_ISLNK (lstat_buf.st_mode); + if (is_link) +@@ -915,7 +915,7 @@ search_dir (const struct dir_entry *entry) + continue; + } + } +- if (__glibc_unlikely (stat64 (target_name, &stat_buf))) ++ if (__glibc_unlikely (stat (target_name, &stat_buf))) + { + if (opt_verbose) + error (0, errno, _("Cannot stat %s"), file_name); +@@ -951,7 +951,7 @@ search_dir (const struct dir_entry *entry) + { + if (!is_link + && direntry->d_type != DT_UNKNOWN +- && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0)) ++ && __builtin_expect (lstat (real_file_name, &lstat_buf), 0)) + { + error (0, errno, _("Cannot lstat %s"), file_name); + continue; +@@ -980,10 +980,10 @@ search_dir (const struct dir_entry *entry) + else + real_name = real_file_name; + +- /* Call lstat64 if not done yet. */ ++ /* Call lstat if not done yet. */ + if (!is_link + && direntry->d_type != DT_UNKNOWN +- && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0)) ++ && __builtin_expect (lstat (real_file_name, &lstat_buf), 0)) + { + error (0, errno, _("Cannot lstat %s"), file_name); + continue; +diff --git a/elf/readlib.c b/elf/readlib.c +index 7383c23249426c44..8901de2684835653 100644 +--- a/elf/readlib.c ++++ b/elf/readlib.c +@@ -76,10 +76,10 @@ int + process_file (const char *real_file_name, const char *file_name, + const char *lib, int *flag, unsigned int *osversion, + unsigned int *isa_level, char **soname, int is_link, +- struct stat64 *stat_buf) ++ struct stat *stat_buf) + { + FILE *file; +- struct stat64 statbuf; ++ struct stat statbuf; + void *file_contents; + int ret; + ElfW(Ehdr) *elf_header; +@@ -99,7 +99,7 @@ process_file (const char *real_file_name, const char *file_name, + return 1; + } + +- if (fstat64 (fileno (file), &statbuf) < 0) ++ if (fstat (fileno (file), &statbuf) < 0) + { + error (0, 0, _("Cannot fstat file %s.\n"), file_name); + fclose (file); +diff --git a/elf/sln.c b/elf/sln.c +index 26f371a4932cf475..f71321d565803f06 100644 +--- a/elf/sln.c ++++ b/elf/sln.c +@@ -153,11 +153,11 @@ makesymlinks (const char *file) + static int + makesymlink (const char *src, const char *dest) + { +- struct stat64 stats; ++ struct stat stats; + const char *error; + + /* Destination must not be a directory. */ +- if (lstat64 (dest, &stats) == 0) ++ if (lstat (dest, &stats) == 0) + { + if (S_ISDIR (stats.st_mode)) + { +diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h +index 3ab757077d160520..c0eb95bcf989dddc 100644 +--- a/sysdeps/generic/ldconfig.h ++++ b/sysdeps/generic/ldconfig.h +@@ -79,11 +79,11 @@ extern void init_aux_cache (void); + + extern void load_aux_cache (const char *aux_cache_name); + +-extern int search_aux_cache (struct stat64 *stat_buf, int *flags, ++extern int search_aux_cache (struct stat *stat_buf, int *flags, + unsigned int *osversion, + unsigned int *isa_level, char **soname); + +-extern void add_to_aux_cache (struct stat64 *stat_buf, int flags, ++extern void add_to_aux_cache (struct stat *stat_buf, int flags, + unsigned int osversion, + unsigned int isa_level, const char *soname); + +@@ -94,7 +94,7 @@ extern int process_file (const char *real_file_name, const char *file_name, + const char *lib, int *flag, + unsigned int *osversion, unsigned int *isa_level, + char **soname, int is_link, +- struct stat64 *stat_buf); ++ struct stat *stat_buf); + + extern char *implicit_soname (const char *lib, int flag); + diff --git a/SOURCES/glibc-upstream-2.34-389.patch b/SOURCES/glibc-upstream-2.34-389.patch new file mode 100644 index 0000000..83170ad --- /dev/null +++ b/SOURCES/glibc-upstream-2.34-389.patch @@ -0,0 +1,120 @@ +commit 2d7550e6cfff541380d3a1f2ac33e76aaf1273de +Author: Florian Weimer +Date: Wed Feb 8 18:11:04 2023 +0100 + + elf: Smoke-test ldconfig -p against system /etc/ld.so.cache + + The test is sufficient to detect the ldconfig bug fixed in + commit 9fe6f6363886aae6b2b210cae3ed1f5921299083 ("elf: Fix 64 time_t + support for installed statically binaries"). + + Reviewed-by: Carlos O'Donell + (cherry picked from commit 9fd63e35371b9939e9153907c6a753e6960b68ad) + +diff --git a/elf/Makefile b/elf/Makefile +index 3a8590e0d3cc33ab..0daa8a85ec1a1bc5 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -553,6 +553,7 @@ ifeq ($(run-built-tests),yes) + tests-special += \ + $(objpfx)noload-mem.out \ + $(objpfx)tst-ldconfig-X.out \ ++ $(objpfx)tst-ldconfig-p.out \ + $(objpfx)tst-leaks1-mem.out \ + $(objpfx)tst-rtld-help.out \ + # tests-special +@@ -2259,6 +2260,11 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig + '$(run-program-env)' > $@; \ + $(evaluate-test) + ++$(objpfx)tst-ldconfig-p.out : tst-ldconfig-p.sh $(objpfx)ldconfig ++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper-env)' \ ++ '$(run-program-env)' > $@; \ ++ $(evaluate-test) ++ + # Test static linking of all the libraries we can possibly link + # together. Note that in some configurations this may be less than the + # complete list of libraries we build but we try to maxmimize this list. +diff --git a/elf/tst-ldconfig-p.sh b/elf/tst-ldconfig-p.sh +new file mode 100644 +index 0000000000000000..ec937bf4ec04e8c0 +--- /dev/null ++++ b/elf/tst-ldconfig-p.sh +@@ -0,0 +1,77 @@ ++#!/bin/sh ++# Test that ldconfig -p prints something useful. ++# Copyright (C) 2023 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 ++# . ++ ++# Check that the newly built ldconfig -p can dump the system ++# /etc/ld.so.cache file. This should always work even if the ABIs are ++# not compatible, except in a cross-endian build (that presumably ++# involves emulation when running ldconfig). ++ ++common_objpfx=$1 ++test_wrapper_env=$2 ++run_program_env=$3 ++ ++if ! test -r /etc/ld.so.cache; then ++ echo "warning: /etc/ld.so.cache does not exist, test skipped" ++ exit 77 ++fi ++ ++testout="${common_objpfx}elf/tst-ldconfig-p.out" ++# Truncate file. ++: > "$testout" ++ ++${test_wrapper_env} \ ++${run_program_env} \ ++${common_objpfx}elf/ldconfig -p \ ++ $testroot/lib >>"$testout" 2>>"$testout" ++status=$? ++echo "info: ldconfig exit status: $status" >>"$testout" ++ ++errors=0 ++case $status in ++ (0) ++ if head -n 1 "$testout" | \ ++ grep -q "libs found in cache \`/etc/ld.so.cache'\$" ; then ++ echo "info: initial string found" >>"$testout" ++ else ++ echo "error: initial string not found" >>"$testout" ++ errors=1 ++ fi ++ if grep -q "^ libc\.so\..* => " "$testout"; then ++ echo "info: libc.so.* string found" >>"$testout" ++ else ++ echo "error: libc.so.* string not found" >>"$testout" ++ errors=1 ++ fi ++ ;; ++ (1) ++ if head -n 1 "$testout" | \ ++ grep -q ": Cache file has wrong endianness\.$" ; then ++ echo "info: cache file has wrong endianess" >> "$testout" ++ else ++ echo "error: unexpected ldconfig error message" >> "$testout" ++ errors=1 ++ fi ++ ;; ++ (*) ++ echo "error: unexpected exit status" >> "$testout" ++ errors=1 ++ ;; ++esac ++ ++exit $errors diff --git a/SOURCES/wrap-find-debuginfo.sh b/SOURCES/wrap-find-debuginfo.sh index 6a558df..4cbb01b 100644 --- a/SOURCES/wrap-find-debuginfo.sh +++ b/SOURCES/wrap-find-debuginfo.sh @@ -15,8 +15,16 @@ set -ex -ldso_tmp="$(mktemp)" -libc_tmp="$(mktemp)" +workdir="$(mktemp -d -t find_debuginfo.XXXXXX)" + +ldso_tmp="$workdir/ld.so" +libc_tmp_dir="$workdir/" + +# Return the path where a libc should be saved temporarily. This path is +# based on its original path received in $1. +libc_tmp_path() { + echo "$libc_tmp_dir"`dirname "$1"`"/libc.so" +} # Prefer a separately installed debugedit over the RPM-integrated one. if command -v debugedit >/dev/null ; then @@ -26,7 +34,7 @@ else fi cleanup () { - rm -f "$ldso_tmp" "$libc_tmp" + rm -rf "$workdir" } trap cleanup 0 @@ -37,8 +45,8 @@ shift # See ldso_path setting in glibc.spec. ldso_path= -for ldso_candidate in `find "$sysroot_path" -regextype posix-extended \ - -regex '.*/ld(-.*|64|)\.so\.[0-9]+$' -type f` ; do +for ldso_candidate in `find "$sysroot_path" -maxdepth 2 \ + -regextype posix-extended -regex '.*/ld(-.*|64|)\.so\.[0-9]+$' -type f` ; do if test -z "$ldso_path" ; then ldso_path="$ldso_candidate" else @@ -48,47 +56,71 @@ for ldso_candidate in `find "$sysroot_path" -regextype posix-extended \ done # libc.so.6 always uses this name, so it is simpler to locate. -libc_path= -for libc_candidate in `find "$sysroot_path" -name libc.so.6`; do - if test -z "$libc_path" ; then - libc_path="$libc_candidate" - else - echo "error: multiple libc.so.6 candidates: $libc_path, $libc_candidate" - exit 1 - fi -done +libc_path=`find "$sysroot_path" -name libc.so.6` # Preserve the original files. cp "$ldso_path" "$ldso_tmp" -cp "$libc_path" "$libc_tmp" +for lib in $libc_path ; do + libtmp=`libc_tmp_path $lib` + mkdir -p `dirname "$libtmp"` + cp "$lib" "$libtmp" +done # Run the debuginfo extraction. "$script_path" "$@" -# Restore the original files. +for lib in $libc_path ; do + libtmp=`libc_tmp_path "$lib"` + # libc.so.6: Extract the .gnu_debuglink section + objcopy -j.gnu_debuglink --set-section-flags .gnu_debuglink=alloc \ + -O binary "$lib" "$libtmp.debuglink" + # Restore the original files. + cp "$libtmp" "$lib" + + # Reduce the size of libc notes. Primarily for annobin. + objcopy --merge-notes "$lib" + + # libc.so.6: Restore the .gnu_debuglink section + objcopy --add-section .gnu_debuglink="$libtmp.debuglink" "$lib" + + # libc.so.6: Reduce to valuable symbols. Eliminate file symbols, + # annobin symbols, and symbols used by the glibc build to implement + # hidden aliases (__EI_*). We would also like to remove __GI_* + # symbols, but even listing them explicitly (as in -K __GI_strlen) + # still causes strip to remove them, so there is no filtering of + # __GI_* here. (Debuginfo is gone after this, so no need to optimize + # it.) + strip -w \ + -K '*' \ + -K '!*.c' \ + -K '!*.os' \ + -K '!.annobin_*' \ + -K '!__EI_*' \ + -K '!__PRETTY_FUNCTION__*' \ + "$lib" +done + +# Restore the original ld.so. cp "$ldso_tmp" "$ldso_path" -cp "$libc_tmp" "$libc_path" # Reduce the size of notes. Primarily for annobin. objcopy --merge-notes "$ldso_path" -objcopy --merge-notes "$libc_path" - -# libc.so.6: Reduce to valuable symbols. Eliminate file symbols, -# annobin symbols, and symbols used by the glibc build to implement -# hidden aliases (__EI_*). We would also like to remove __GI_* -# symbols, but even listing them explicitly (as in -K __GI_strlen) -# still causes strip to remove them, so there is no filtering of -# __GI_* here. (Debuginfo is gone after this, so no need to optimize -# it.) -strip -w \ - -K '*' \ - -K '!*.c' \ - -K '!*.os' \ - -K '!.annobin_*' \ - -K '!__EI_*' \ - -K '!__PRETTY_FUNCTION__*' \ - "$libc_path" + +# ld.so does not have separated debuginfo and so the debuginfo file +# generated by find-debuginfo is redundant. Therefore, remove it. +ldso_debug= +for ldso_debug_candidate in `find "$sysroot_path" -maxdepth 2 \ + -regextype posix-extended \ + -regex '.*/ld(-.*|64|)\.so\.[0-9]+.*debug$' -type f` ; do + if test -z "$ldso_debug" ; then + ldso_debug="$ldso_debug_candidate" + else + echo "error: multiple ld.so debug candidates: $ldso_debug, $ldso_debug_candidate" + exit 1 + fi +done +rm -f "$ldso_debug" # ld.so: Rewrite the source file paths to match the extracted # locations. First compute the arguments for invoking debugedit. @@ -112,6 +144,11 @@ while true ; do done debug_base_name=${last_arg:-$RPM_BUILD_ROOT} $debugedit -b "$debug_base_name" -d "$debug_dest_name" -n $ldso_path +# Remove the .annobin* symbols (and only them). +if nm --format=posix "$ldso_path" | cut -d' ' -f1 \ + | grep '^\.annobin' > "$ldso_tmp.annobin-symbols"; then + objcopy --strip-symbols="$ldso_tmp.annobin-symbols" "$ldso_path" +fi # Apply single-file DWARF optimization. dwz $ldso_path