diff --git a/.glibc.checksum b/.glibc.checksum
index 243d0059ed34457b3cd49dcee645b6cf9317896a..1882d6a12f4c8d728e7e3024e7441b6a59f07a36 100644
--- a/.glibc.checksum
+++ b/.glibc.checksum
@@ -1 +1 @@
-609d4863fbcbcc09c71823c7b05065d719529c7500836bda2bc760b3f16d09f7
+a80b272db684a3386983a445e07d1b36c3e6fc723eb93ecf89cae7d08970fd83
diff --git a/SOURCES/glibc-RHEL-20172-1.patch b/SOURCES/glibc-RHEL-20172-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c9b759971762feac7fe919462022379a4ff00488
--- /dev/null
+++ b/SOURCES/glibc-RHEL-20172-1.patch
@@ -0,0 +1,369 @@
+From 317f1c0a8a71a862b1e600ff5386b08e02cf4b95 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Thu, 26 Jan 2023 08:26:18 -0800
+Subject: [PATCH] x86-64: Add glibc.cpu.prefer_map_32bit_exec [BZ #28656]
+Content-type: text/plain; charset=UTF-8
+
+Crossing 2GB boundaries with indirect calls and jumps can use more
+branch prediction resources on Intel Golden Cove CPU (see the
+"Misprediction for Branches >2GB" section in Intel 64 and IA-32
+Architectures Optimization Reference Manual.)  There is visible
+performance improvement on workloads with many PLT calls when executable
+and shared libraries are mmapped below 2GB.  Add the Prefer_MAP_32BIT_EXEC
+bit so that mmap will try to map executable or denywrite pages in shared
+libraries with MAP_32BIT first.
+
+NB: Prefer_MAP_32BIT_EXEC reduces bits available for address space
+layout randomization (ASLR), which is always disabled for SUID programs
+and can only be enabled by the tunable, glibc.cpu.prefer_map_32bit_exec,
+or the environment variable, LD_PREFER_MAP_32BIT_EXEC.  This works only
+between shared libraries or between shared libraries and executables with
+addresses below 2GB.  PIEs are usually loaded at a random address above
+4GB by the kernel.
+
+Conflicts:
+	manual/tunables.texi
+	(line numbers)
+	sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
+	(merged local @order list)
+	sysdeps/x86/cpu-features.c
+	(line numbers)
+
+---
+ manual/tunables.texi                          | 33 ++++++++++----
+ sysdeps/unix/sysv/linux/x86_64/64/Makefile    | 25 +++++++++++
+ .../sysv/linux/x86_64/64/dl-tunables.list     | 29 +++++++++++++
+ .../unix/sysv/linux/x86_64/64/mmap_internal.h | 43 +++++++++++++++++++
+ .../sysv/linux/x86_64/64/tst-map-32bit-1a.c   | 34 +++++++++++++++
+ .../sysv/linux/x86_64/64/tst-map-32bit-1b.c   |  1 +
+ .../sysv/linux/x86_64/64/tst-map-32bit-mod.c  | 33 ++++++++++++++
+ sysdeps/x86/cpu-features.c                    | 15 +++++++
+ ...cpu-features-preferred_feature_index_1.def |  1 +
+ 9 files changed, 205 insertions(+), 9 deletions(-)
+ create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
+ create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h
+ create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c
+ create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c
+ create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c
+
+diff --git a/manual/tunables.texi b/manual/tunables.texi
+index 0be7231e36..c76c5c53cd 100644
+--- a/manual/tunables.texi
++++ b/manual/tunables.texi
+@@ -35,27 +35,32 @@ tunables with minimum and maximum values:
+ @example
+ $ /lib64/ld-linux-x86-64.so.2 --list-tunables
+ glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
+-glibc.elision.skip_lock_after_retries: 3 (min: -2147483648, max: 2147483647)
++glibc.elision.skip_lock_after_retries: 3 (min: 0, max: 2147483647)
+ glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0xffffffffffffffff)
+ glibc.malloc.perturb: 0 (min: 0, max: 255)
+ glibc.cpu.x86_shared_cache_size: 0x100000 (min: 0x0, max: 0xffffffffffffffff)
++glibc.pthread.rseq: 1 (min: 0, max: 1)
++glibc.cpu.prefer_map_32bit_exec: 0 (min: 0, max: 1)
+ glibc.mem.tagging: 0 (min: 0, max: 255)
+-glibc.elision.tries: 3 (min: -2147483648, max: 2147483647)
++glibc.elision.tries: 3 (min: 0, max: 2147483647)
+ glibc.elision.enable: 0 (min: 0, max: 1)
+-glibc.cpu.x86_rep_movsb_threshold: 0x1000 (min: 0x100, max: 0xffffffffffffffff)
++glibc.malloc.hugetlb: 0x0 (min: 0x0, max: 0xffffffffffffffff)
++glibc.cpu.x86_rep_movsb_threshold: 0x2000 (min: 0x100, max: 0xffffffffffffffff)
+ glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0xffffffffffffffff)
+-glibc.elision.skip_lock_busy: 3 (min: -2147483648, max: 2147483647)
+-glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0xffffffffffffffff)
++glibc.rtld.dynamic_sort: 2 (min: 1, max: 2)
++glibc.elision.skip_lock_busy: 3 (min: 0, max: 2147483647)
++glibc.malloc.top_pad: 0x20000 (min: 0x0, max: 0xffffffffffffffff)
+ glibc.cpu.x86_rep_stosb_threshold: 0x800 (min: 0x1, max: 0xffffffffffffffff)
+-glibc.cpu.x86_non_temporal_threshold: 0xc0000 (min: 0x4040, max: 0x0fffffffffffffff)
++glibc.cpu.x86_non_temporal_threshold: 0xc0000 (min: 0x4040, max: 0xfffffffffffffff)
+ glibc.cpu.x86_shstk:
++glibc.pthread.stack_cache_size: 0x2800000 (min: 0x0, max: 0xffffffffffffffff)
+ glibc.cpu.hwcap_mask: 0x6 (min: 0x0, max: 0xffffffffffffffff)
+-glibc.malloc.mmap_max: 0 (min: -2147483648, max: 2147483647)
+-glibc.elision.skip_trylock_internal_abort: 3 (min: -2147483648, max: 2147483647)
++glibc.malloc.mmap_max: 0 (min: 0, max: 2147483647)
++glibc.elision.skip_trylock_internal_abort: 3 (min: 0, max: 2147483647)
+ glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0xffffffffffffffff)
+ glibc.cpu.x86_ibt:
+ glibc.cpu.hwcaps:
+-glibc.elision.skip_lock_internal_abort: 3 (min: -2147483648, max: 2147483647)
++glibc.elision.skip_lock_internal_abort: 3 (min: 0, max: 2147483647)
+ glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0xffffffffffffffff)
+ glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0xffffffffffffffff)
+ glibc.cpu.x86_data_cache_size: 0x8000 (min: 0x0, max: 0xffffffffffffffff)
+@@ -569,6 +574,16 @@ instead.
+ This tunable is specific to i386 and x86-64.
+ @end deftp
+ 
++@deftp Tunable glibc.cpu.prefer_map_32bit_exec
++When this tunable is set to \code{1}, shared libraries of non-setuid
++programs will be loaded below 2GB with MAP_32BIT.
++
++Note that the @env{LD_PREFER_MAP_32BIT_EXEC} environment is an alias of
++this tunable.
++
++This tunable is specific to 64-bit x86-64.
++@end deftp
++
+ @node Memory Related Tunables
+ @section Memory Related Tunables
+ @cindex memory related tunables
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/Makefile b/sysdeps/unix/sysv/linux/x86_64/64/Makefile
+index a7b6dc5a53..8ff4f27786 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/64/Makefile
++++ b/sysdeps/unix/sysv/linux/x86_64/64/Makefile
+@@ -1,2 +1,27 @@
+ # The default ABI is 64.
+ default-abi := 64
++
++ifeq ($(subdir),elf)
++ifneq ($(have-tunables),no)
++
++tests-map-32bit = \
++  tst-map-32bit-1a \
++  tst-map-32bit-1b \
++# tests-map-32bit
++tst-map-32bit-1a-no-pie = yes
++tst-map-32bit-1b-no-pie = yes
++tests += $(tests-map-32bit)
++
++modules-map-32bit = \
++  tst-map-32bit-mod \
++# modules-map-32bit
++modules-names += $(modules-map-32bit)
++
++$(objpfx)tst-map-32bit-mod.so: $(libsupport)
++tst-map-32bit-1a-ENV = LD_PREFER_MAP_32BIT_EXEC=1
++$(objpfx)tst-map-32bit-1a: $(objpfx)tst-map-32bit-mod.so
++tst-map-32bit-1b-ENV = GLIBC_TUNABLES=glibc.cpu.prefer_map_32bit_exec=1
++$(objpfx)tst-map-32bit-1b: $(objpfx)tst-map-32bit-mod.so
++
++endif
++endif
+diff -rup a/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
+--- a/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list	2024-03-06 17:52:50.968514369 -0500
++++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list	2024-03-06 17:55:48.778264896 -0500
+@@ -1,3 +1,33 @@
++# x86-64 specific tunables.
++# 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
++# <https://www.gnu.org/licenses/>.
++
++glibc {
++  cpu {
++    prefer_map_32bit_exec {
++      type: INT_32
++      minval: 0
++      maxval: 1
++      env_alias: LD_PREFER_MAP_32BIT_EXEC
++      security_level: SXID_IGNORE
++    }
++  }
++}
++
+ # Order of tunables in RHEL 9.1.z.
+ @order glibc.rtld.nns
+ @order glibc.elision.skip_lock_after_retries
+@@ -35,3 +65,5 @@
+ @order glibc.malloc.check
+ @order glibc.gmon.minarcs
+ @order glibc.gmon.maxarcs
++# Order of tunables in RHEL 9.5.z
++@order glibc.cpu.prefer_map_32bit_exec
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h b/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h
+new file mode 100644
+index 0000000000..33dec3f805
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h
+@@ -0,0 +1,43 @@
++/* Linux mmap system call.  x86-64 version.
++   Copyright (C) 2015-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
++   <https://www.gnu.org/licenses/>.  */
++
++#ifndef MMAP_X86_64_INTERNAL_H
++#define MMAP_X86_64_INTERNAL_H
++
++#include <ldsodefs.h>
++
++/* If the Prefer_MAP_32BIT_EXEC bit is set, try to map executable or
++    denywrite pages with MAP_32BIT first.  */
++#define MMAP_PREPARE(addr, len, prot, flags, fd, offset)		\
++  if ((addr) == NULL							\
++      && (((prot) & PROT_EXEC) != 0					\
++	  || ((flags) & MAP_DENYWRITE) != 0)				\
++      && HAS_ARCH_FEATURE (Prefer_MAP_32BIT_EXEC))			\
++    {									\
++      void *ret = (void*) INLINE_SYSCALL_CALL (mmap, (addr), (len),	\
++					      (prot),			\
++					      (flags) | MAP_32BIT,	\
++					      (fd), (offset));		\
++      if (ret != MAP_FAILED)						\
++	return ret;							\
++    }
++
++#include_next <mmap_internal.h>
++
++#endif
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c
+new file mode 100644
+index 0000000000..abc396589e
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c
+@@ -0,0 +1,34 @@
++/* Check that LD_PREFER_MAP_32BIT_EXEC works in PDE and shared library.
++   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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++#include <stdint.h>
++#include <support/check.h>
++
++extern void dso_check_map_32bit (void);
++
++static int
++do_test (void)
++{
++  printf ("do_test: %p\n", do_test);
++  TEST_VERIFY ((uintptr_t) do_test < 0xffffffffUL);
++  dso_check_map_32bit ();
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c
+new file mode 100644
+index 0000000000..34ab01c773
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c
+@@ -0,0 +1 @@
++#include "tst-map-32bit-1a.c"
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c
+new file mode 100644
+index 0000000000..78d4b6133c
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c
+@@ -0,0 +1,33 @@
++/* Check that LD_PREFER_MAP_32BIT_EXEC works in shared library.
++   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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++#include <stdint.h>
++#include <support/check.h>
++
++static void
++dso_do_test (void)
++{
++}
++
++void
++dso_check_map_32bit (void)
++{
++  printf ("dso_do_test: %p\n", dso_do_test);
++  TEST_VERIFY ((uintptr_t) dso_do_test < 0xffffffffUL);
++}
+diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
+index a2197ed211..822688e21f 100644
+--- a/sysdeps/x86/cpu-features.c
++++ b/sysdeps/x86/cpu-features.c
+@@ -27,6 +27,16 @@
+ extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *)
+   attribute_hidden;
+ 
++# ifdef __LP64__
++static void
++TUNABLE_CALLBACK (set_prefer_map_32bit_exec) (tunable_val_t *valp)
++{
++  if (valp->numval)
++    GLRO(dl_x86_cpu_features).preferred[index_arch_Prefer_MAP_32BIT_EXEC]
++      |= bit_arch_Prefer_MAP_32BIT_EXEC;
++}
++# endif
++
+ # if CET_ENABLED
+ extern void TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *)
+   attribute_hidden;
+@@ -949,6 +959,11 @@ no_cpuid:
+ #if HAVE_TUNABLES
+   TUNABLE_GET (hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
+ 
++# ifdef __LP64__
++  TUNABLE_GET (prefer_map_32bit_exec, tunable_val_t *,
++	       TUNABLE_CALLBACK (set_prefer_map_32bit_exec));
++# endif
++
+   bool disable_xsave_features = false;
+ 
+   if (!CPU_FEATURE_USABLE_P (cpu_features, OSXSAVE))
+diff --git a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
+index e45f9cb159..d20c5b3196 100644
+--- a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
++++ b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
+@@ -26,6 +26,7 @@ BIT (I586)
+ BIT (I686)
+ BIT (Slow_SSE4_2)
+ BIT (AVX_Fast_Unaligned_Load)
++BIT (Prefer_MAP_32BIT_EXEC)
+ BIT (Prefer_No_VZEROUPPER)
+ BIT (Prefer_ERMS)
+ BIT (Prefer_No_AVX512)
+-- 
+2.39.3
+
diff --git a/SOURCES/glibc-RHEL-20172-2.patch b/SOURCES/glibc-RHEL-20172-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..0a7724677edec29cac11426f719d3d09dc2ee0ee
--- /dev/null
+++ b/SOURCES/glibc-RHEL-20172-2.patch
@@ -0,0 +1,29 @@
+From 188ecdb7774145050a6e167a277f45f03dac5fe8 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Wed, 22 Feb 2023 20:04:26 -0800
+Subject: [PATCH] tunables.texi: Change \code{1} to @code{1}
+Content-type: text/plain; charset=UTF-8
+
+Update
+
+317f1c0a8a x86-64: Add glibc.cpu.prefer_map_32bit_exec [BZ #28656]
+---
+ manual/tunables.texi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/manual/tunables.texi b/manual/tunables.texi
+index c76c5c53cd..70dd2264c5 100644
+--- a/manual/tunables.texi
++++ b/manual/tunables.texi
+@@ -589,7 +589,7 @@ This tunable is specific to i386 and x86-64.
+ @end deftp
+ 
+ @deftp Tunable glibc.cpu.prefer_map_32bit_exec
+-When this tunable is set to \code{1}, shared libraries of non-setuid
++When this tunable is set to @code{1}, shared libraries of non-setuid
+ programs will be loaded below 2GB with MAP_32BIT.
+ 
+ Note that the @env{LD_PREFER_MAP_32BIT_EXEC} environment is an alias of
+-- 
+2.39.3
+
diff --git a/SOURCES/glibc-RHEL-21884.patch b/SOURCES/glibc-RHEL-21884.patch
new file mode 100644
index 0000000000000000000000000000000000000000..39f1500439f99742d9b24785022002f7dc44ef7d
--- /dev/null
+++ b/SOURCES/glibc-RHEL-21884.patch
@@ -0,0 +1,73 @@
+commit 85860ad6eaf4c9739318f6b2a1ff7c2fa6b12ab5
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Mon Aug 15 16:45:40 2022 +0200
+
+    malloc: Do not use MAP_NORESERVE to allocate heap segments
+    
+    Address space for heap segments is reserved in a mmap call with
+    MAP_ANONYMOUS | MAP_PRIVATE and protection flags PROT_NONE.  This
+    reservation does not count against the RSS limit of the process or
+    system.  Backing memory is allocated using mprotect in alloc_new_heap
+    and grow_heap, and at this point, the allocator expects the kernel
+    to provide memory (subject to memory overcommit).
+    
+    The SIGSEGV that might generate due to MAP_NORESERVE (according to
+    the mmap manual page) does not seem to occur in practice, it's always
+    SIGKILL from the OOM killer.  Even if there is a way that SIGSEGV
+    could be generated, it is confusing to applications that this only
+    happens for secondary heaps, not for large mmap-based allocations,
+    and not for the main arena.
+    
+    Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+Conflicts:
+	malloc/arena.c
+	(huge page support was added upstream)
+
+diff --git a/malloc/arena.c b/malloc/arena.c
+index 667484630ed0afa5..2852783355d3d869 100644
+--- a/malloc/arena.c
++++ b/malloc/arena.c
+@@ -466,8 +466,7 @@ new_heap (size_t size, size_t top_pad)
+   p2 = MAP_FAILED;
+   if (aligned_heap_area)
+     {
+-      p2 = (char *) MMAP (aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE,
+-                          MAP_NORESERVE);
++      p2 = (char *) MMAP (aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE, 0);
+       aligned_heap_area = NULL;
+       if (p2 != MAP_FAILED && ((unsigned long) p2 & (HEAP_MAX_SIZE - 1)))
+         {
+@@ -477,7 +476,7 @@ new_heap (size_t size, size_t top_pad)
+     }
+   if (p2 == MAP_FAILED)
+     {
+-      p1 = (char *) MMAP (0, HEAP_MAX_SIZE << 1, PROT_NONE, MAP_NORESERVE);
++      p1 = (char *) MMAP (0, HEAP_MAX_SIZE << 1, PROT_NONE, 0);
+       if (p1 != MAP_FAILED)
+         {
+           p2 = (char *) (((unsigned long) p1 + (HEAP_MAX_SIZE - 1))
+@@ -493,7 +492,7 @@ new_heap (size_t size, size_t top_pad)
+         {
+           /* Try to take the chance that an allocation of only HEAP_MAX_SIZE
+              is already aligned. */
+-          p2 = (char *) MMAP (0, HEAP_MAX_SIZE, PROT_NONE, MAP_NORESERVE);
++          p2 = (char *) MMAP (0, HEAP_MAX_SIZE, PROT_NONE, 0);
+           if (p2 == MAP_FAILED)
+             return 0;
+ 
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index 375f50f5db13e234..fe80b8239756a7c9 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -1112,10 +1112,6 @@ static mchunkptr mremap_chunk(mchunkptr p, size_t new_size);
+ # define MAP_ANONYMOUS MAP_ANON
+ #endif
+ 
+-#ifndef MAP_NORESERVE
+-# define MAP_NORESERVE 0
+-#endif
+-
+ #define MMAP(addr, size, prot, flags) \
+  __mmap((addr), (size), (prot), (flags)|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)
+ 
diff --git a/SOURCES/glibc-RHEL-22165-1.patch b/SOURCES/glibc-RHEL-22165-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..313396655dee85ecea64f989d3e0a86a45cc704d
--- /dev/null
+++ b/SOURCES/glibc-RHEL-22165-1.patch
@@ -0,0 +1,229 @@
+commit f21962ddfc8bb23e92597da1f98e313dbde11cc1
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Fri Aug 25 14:15:28 2023 +0200
+
+    manual: Document ld.so --list-diagnostics output
+    
+    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+diff --git a/manual/dynlink.texi b/manual/dynlink.texi
+index 45bf5a5b55..df41c56bfc 100644
+--- a/manual/dynlink.texi
++++ b/manual/dynlink.texi
+@@ -13,9 +13,216 @@ as plugins) later at run time.
+ Dynamic linkers are sometimes called @dfn{dynamic loaders}.
+ 
+ @menu
++* Dynamic Linker Invocation::   Explicit invocation of the dynamic linker.
+ * Dynamic Linker Introspection::    Interfaces for querying mapping information.
+ @end menu
+ 
++@node Dynamic Linker Invocation
++
++@cindex program interpreter
++When a dynamically linked program starts, the operating system
++automatically loads the dynamic linker along with the program.
++@Theglibc{} also supports invoking the dynamic linker explicitly to
++launch a program.  This command uses the implied dynamic linker
++(also sometimes called the @dfn{program interpreter}):
++
++@smallexample
++sh -c 'echo "Hello, world!"'
++@end smallexample
++
++This command specifies the dynamic linker explicitly:
++
++@smallexample
++ld.so /bin/sh -c 'echo "Hello, world!"'
++@end smallexample
++
++Note that @command{ld.so} does not search the @env{PATH} environment
++variable, so the full file name of the executable needs to be specified.
++
++The @command{ld.so} program supports various options.  Options start
++@samp{--} and need to come before the program that is being launched.
++Some of the supported options are listed below.
++
++@table @code
++@item --list-diagnostics
++Print system diagnostic information in a machine-readable format.
++@xref{Dynamic Linker Diagnostics}.
++@end table
++
++@menu
++* Dynamic Linker Diagnostics::   Obtaining system diagnostic information.
++@end menu
++
++@node Dynamic Linker Diagnostics
++@section Dynamic Linker Diagnostics
++@cindex diagnostics (dynamic linker)
++
++The @samp{ld.so --list-diagnostics} produces machine-readable
++diagnostics output.  This output contains system data that affects the
++behavior of @theglibc{}, and potentially application behavior as well.
++
++The exact set of diagnostic items can change between releases of
++@theglibc{}.  The output format itself is not expected to change
++radically.
++
++The following table shows some example lines that can be written by the
++diagnostics command.
++
++@table @code
++@item dl_pagesize=0x1000
++The system page size is 4096 bytes.
++
++@item env[0x14]="LANG=en_US.UTF-8"
++This item indicates that the 21st environment variable at process
++startup contains a setting for @code{LANG}.
++
++@item env_filtered[0x22]="DISPLAY"
++The 35th environment variable is @code{DISPLAY}.  Its value is not
++included in the output for privacy reasons because it is not recognized
++as harmless by the diagnostics code.
++
++@item path.prefix="/usr"
++This means that @theglibc{} was configured with @code{--prefix=/usr}.
++
++@item path.system_dirs[0x0]="/lib64/"
++@itemx path.system_dirs[0x1]="/usr/lib64/"
++The built-in dynamic linker search path contains two directories,
++@code{/lib64} and @code{/usr/lib64}.
++@end table
++
++@subsection Dynamic Linker Diagnostics Output Format
++
++As seen above, diagnostic lines assign values (integers or strings) to a
++sequence of labeled subscripts, separated by @samp{.}.  Some subscripts
++have integer indices associated with them.  The subscript indices are
++not necessarily contiguous or small, so an associative array should be
++used to store them.  Currently, all integers fit into the 64-bit
++unsigned integer range.  Every access path to a value has a fixed type
++(string or integer) independent of subscript index values.  Likewise,
++whether a subscript is indexed does not depend on previous indices (but
++may depend on previous subscript labels).
++
++A syntax description in ABNF (RFC 5234) follows.  Note that
++@code{%x30-39} denotes the range of decimal digits.  Diagnostic output
++lines are expected to match the @code{line} production.
++
++@c ABNF-START
++@smallexample
++HEXDIG = %x30-39 / %x61-6f ; lowercase a-f only
++ALPHA = %x41-5a / %x61-7a / %x7f ; letters and underscore
++ALPHA-NUMERIC = ALPHA / %x30-39 / "_"
++DQUOTE = %x22 ; "
++
++; Numbers are always hexadecimal and use a 0x prefix.
++hex-value-prefix = %x30 %x78
++hex-value = hex-value-prefix 1*HEXDIG
++
++; Strings use octal escape sequences and \\, \".
++string-char = %x20-21 / %x23-5c / %x5d-7e ; printable but not "\
++string-quoted-octal = %x30-33 2*2%x30-37
++string-quoted = "\" ("\" / DQUOTE / string-quoted-octal)
++string-value = DQUOTE *(string-char / string-quoted) DQUOTE
++
++value = hex-value / string-value
++
++label = ALPHA *ALPHA-NUMERIC
++index = "[" hex-value "]"
++subscript = label [index]
++
++line = subscript *("." subscript) "=" value
++@end smallexample
++
++@subsection Dynamic Linker Diagnostics Values
++
++As mentioned above, the set of diagnostics may change between
++@theglibc{} releases.  Nevertheless, the following table documents a few
++common diagnostic items.  All numbers are in hexadecimal, with a
++@samp{0x} prefix.
++
++@table @code
++@item dl_dst_lib=@var{string}
++The @code{$LIB} dynamic string token expands to @var{string}.
++
++@cindex HWCAP (diagnostics)
++@item dl_hwcap=@var{integer}
++@itemx dl_hwcap2=@var{integer}
++The HWCAP and HWCAP2 values, as returned for @code{getauxval}, and as
++used in other places depending on the architecture.
++
++@cindex page size (diagnostics)
++@item dl_pagesize=@var{integer}
++The system page size is @var{integer} bytes.
++
++@item dl_platform=@var{string}
++The @code{$PLATFORM} dynamic string token expands to @var{string}.
++
++@item dso.libc=@var{string}
++This is the soname of the shared @code{libc} object that is part of
++@theglibc{}.  On most architectures, this is @code{libc.so.6}.
++
++@item env[@var{index}]=@var{string}
++@itemx env_filtered[@var{index}]=@var{string}
++An environment variable from the process environment.  The integer
++@var{index} is the array index in the environment array.  Variables
++under @code{env} include the variable value after the @samp{=} (assuming
++that it was present), variables under @code{env_filtered} do not.
++
++@item path.prefix=@var{string}
++This indicates that @theglibc{} was configured using
++@samp{--prefix=@var{string}}.
++
++@item path.sysconfdir=@var{string}
++@Theglibc{} was configured (perhaps implicitly) with
++@samp{--sysconfdir=@var{string}} (typically @code{/etc}).
++
++@item path.system_dirs[@var{index}]=@var{string}
++These items list the elements of the built-in array that describes the
++default library search path.  The value @var{string} is a directory file
++name with a trailing @samp{/}.
++
++@item path.rtld=@var{string}
++This string indicates the application binary interface (ABI) file name
++of the run-time dynamic linker.
++
++@item version.release="stable"
++@itemx version.release="development"
++The value @code{"stable"} indicates that this build of @theglibc{} is
++from a release branch.  Releases labeled as @code{"development"} are
++unreleased development versions.
++
++@cindex version (diagnostics)
++@item version.version="@var{major}.@var{minor}"
++@itemx version.version="@var{major}.@var{minor}.9000"
++@Theglibc{} version.  Development releases end in @samp{.9000}.
++
++@cindex auxiliary vector (diagnostics)
++@item auxv[@var{index}].a_type=@var{type}
++@itemx auxv[@var{index}].a_val=@var{integer}
++@itemx auxv[@var{index}].a_val_string=@var{string}
++An entry in the auxiliary vector (specific to Linux).  The values
++@var{type} (an integer) and @var{integer} correspond to the members of
++@code{struct auxv}.  If the value is a string, @code{a_val_string} is
++used instead of @code{a_val}, so that values have consistent types.
++
++The @code{AT_HWCAP} and @code{AT_HWCAP2} values in this output do not
++reflect adjustment by @theglibc{}.
++
++@item uname.sysname=@var{string}
++@itemx uname.nodename=@var{string}
++@itemx uname.release=@var{string}
++@itemx uname.version=@var{string}
++@itemx uname.machine=@var{string}
++@itemx uname.domain=@var{string}
++These Linux-specific items show the values of @code{struct utsname}, as
++reported by the @code{uname} function.  @xref{Platform Type}.
++
++@cindex CPUID (diagnostics)
++@item x86.cpu_features.@dots{}
++These items are specific to the i386 and x86-64 architectures.  They
++reflect supported CPU features and information on cache geometry, mostly
++collected using the @code{CPUID} instruction.
++@end table
++
+ @node Dynamic Linker Introspection
+ @section Dynamic Linker Introspection
+ 
diff --git a/SOURCES/glibc-RHEL-22165-2.patch b/SOURCES/glibc-RHEL-22165-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..62c2711e6d6c499a4eae56e7cc6327205871c0d6
--- /dev/null
+++ b/SOURCES/glibc-RHEL-22165-2.patch
@@ -0,0 +1,74 @@
+commit d99609a3eb8bc96c3af841fd35294a679e0fea7f
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Wed Sep 6 18:37:21 2023 +0200
+
+    manual: Fix ld.so diagnostics menu/section structure
+    
+    And shorten the section/node names a bit, so that the menu
+    entries become easier to read.
+    
+    Texinfo 6.5 fails to process the previous structure:
+    
+    ./dynlink.texi:56: warning: node `Dynamic Linker Introspection' is
+      next for `Dynamic Linker Diagnostics' in sectioning but not in menu
+    ./dynlink.texi:56: warning: node up `Dynamic Linker Diagnostics'
+      in menu `Dynamic Linker Invocation' and
+      in sectioning `Dynamic Linker' differ
+    ./dynlink.texi:1: node `Dynamic Linker' lacks menu item for
+      `Dynamic Linker Diagnostics' despite being its Up target
+    ./dynlink.texi:226: warning: node prev `Dynamic Linker Introspection' in menu `Dynamic Linker Invocation'
+      and in sectioning `Dynamic Linker Diagnostics' differ
+    
+    Texinfo 7.0.2 does not report an error.
+    
+    This fixes commit f21962ddfc8bb23e92597da1f98e313dbde11cc1
+    ("manual: Document ld.so --list-diagnostics output").
+    
+    Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+diff --git a/manual/dynlink.texi b/manual/dynlink.texi
+index df41c56bfc..06a6c15533 100644
+--- a/manual/dynlink.texi
++++ b/manual/dynlink.texi
+@@ -18,6 +18,7 @@ Dynamic linkers are sometimes called @dfn{dynamic loaders}.
+ @end menu
+ 
+ @node Dynamic Linker Invocation
++@section Dynamic Linker Invocation
+ 
+ @cindex program interpreter
+ When a dynamically linked program starts, the operating system
+@@ -54,7 +55,7 @@ Print system diagnostic information in a machine-readable format.
+ @end menu
+ 
+ @node Dynamic Linker Diagnostics
+-@section Dynamic Linker Diagnostics
++@subsection Dynamic Linker Diagnostics
+ @cindex diagnostics (dynamic linker)
+ 
+ The @samp{ld.so --list-diagnostics} produces machine-readable
+@@ -90,7 +91,13 @@ The built-in dynamic linker search path contains two directories,
+ @code{/lib64} and @code{/usr/lib64}.
+ @end table
+ 
+-@subsection Dynamic Linker Diagnostics Output Format
++@menu
++* Dynamic Linker Diagnostics Format::  Format of ld.so output.
++* Dynamic Linker Diagnostics Values::  Data contain in ld.so output.
++@end menu
++
++@node Dynamic Linker Diagnostics Format
++@subsubsection Dynamic Linker Diagnostics Format
+ 
+ As seen above, diagnostic lines assign values (integers or strings) to a
+ sequence of labeled subscripts, separated by @samp{.}.  Some subscripts
+@@ -132,7 +139,8 @@ subscript = label [index]
+ line = subscript *("." subscript) "=" value
+ @end smallexample
+ 
+-@subsection Dynamic Linker Diagnostics Values
++@node Dynamic Linker Diagnostics Values
++@subsubsection Dynamic Linker Diagnostics Values
+ 
+ As mentioned above, the set of diagnostics may change between
+ @theglibc{} releases.  Nevertheless, the following table documents a few
diff --git a/SOURCES/glibc-RHEL-22165-3.patch b/SOURCES/glibc-RHEL-22165-3.patch
new file mode 100644
index 0000000000000000000000000000000000000000..392e746705562272f12d09455a1fcf420e1b2c6a
--- /dev/null
+++ b/SOURCES/glibc-RHEL-22165-3.patch
@@ -0,0 +1,144 @@
+commit f8d8b1b1e6d3b8b93f224efc796b7ea083fdb83f
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Mon Apr 8 16:48:55 2024 +0200
+
+    aarch64: Enhanced CPU diagnostics for ld.so
+    
+    This prints some information from struct cpu_features, and the midr_el1
+    and dczid_el0 system register contents on every CPU.
+    
+    Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+    Modified for RHEL by: Patsy Griffin <patsy@redhat.com>
+    Diagnostics for the cpu_features mops and prefer_sve_ifuncs are not
+    currently supported on aarch64.
+
+diff -Nrup a/manual/dynlink.texi b/manual/dynlink.texi
+--- a/manual/dynlink.texi	2024-05-31 20:55:08.238959456 -0400
++++ b/manual/dynlink.texi	2024-05-31 20:55:41.298121623 -0400
+@@ -224,6 +224,40 @@ reflect adjustment by @theglibc{}.
+ These Linux-specific items show the values of @code{struct utsname}, as
+ reported by the @code{uname} function.  @xref{Platform Type}.
+ 
++@item aarch64.cpu_features.@dots{}
++These items are specific to the AArch64 architectures.  They report data
++@theglibc{} uses to activate conditionally supported features such as
++BTI and MTE, and to select alternative function implementations.
++
++@item aarch64.processor[@var{index}].@dots{}
++These are additional items for the AArch64 architecture and are
++described below.
++
++@item aarch64.processor[@var{index}].requested=@var{kernel-cpu}
++The kernel is told to run the subsequent probing on the CPU numbered
++@var{kernel-cpu}.  The values @var{kernel-cpu} and @var{index} can be
++distinct if there are gaps in the process CPU affinity mask.  This line
++is not included if CPU affinity mask information is not available.
++
++@item aarch64.processor[@var{index}].observed=@var{kernel-cpu}
++This line reports the kernel CPU number @var{kernel-cpu} on which the
++probing code initially ran.  If the CPU number cannot be obtained,
++this line is not printed.
++
++@item aarch64.processor[@var{index}].observed_node=@var{node}
++This reports the observed NUMA node number, as reported by the
++@code{getcpu} system call.  If this information cannot be obtained, this
++line is not printed.
++
++@item aarch64.processor[@var{index}].midr_el1=@var{value}
++The value of the @code{midr_el1} system register on the processor
++@var{index}.  This line is only printed if the kernel indicates that
++this system register is supported.
++
++@item aarch64.processor[@var{index}].dczid_el0=@var{value}
++The value of the @code{dczid_el0} system register on the processor
++@var{index}.
++
+ @cindex CPUID (diagnostics)
+ @item x86.cpu_features.@dots{}
+ These items are specific to the i386 and x86-64 architectures.  They
+diff -Nrup a/sysdeps/aarch64/dl-diagnostics-cpu.c b/sysdeps/aarch64/dl-diagnostics-cpu.c
+--- a/sysdeps/aarch64/dl-diagnostics-cpu.c	1969-12-31 19:00:00.000000000 -0500
++++ b/sysdeps/aarch64/dl-diagnostics-cpu.c	2024-05-31 20:57:23.536623129 -0400
+@@ -0,0 +1,81 @@
++/* Print CPU diagnostics data in ld.so.  AArch64 version.
++   Copyright (C) 2021-2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <dl-diagnostics.h>
++
++#include <cpu-features.h>
++#include <dl-iterate_cpu.h>
++#include <ldsodefs.h>
++#include <sys/auxv.h>
++
++static void
++print_cpu_features_value (const char *label, uint64_t value)
++{
++  _dl_printf ("aarch64.cpu_features.");
++  _dl_diagnostics_print_labeled_value (label, value);
++}
++
++static void
++print_per_cpu_value (const struct dl_iterate_cpu *dic,
++                     const char *label, uint64_t value)
++{
++  _dl_printf ("aarch64.processor[0x%x].", dic->processor_index);
++  _dl_diagnostics_print_labeled_value (label, value);
++}
++
++void
++_dl_diagnostics_cpu (void)
++{
++  print_cpu_features_value ("bti", GLRO (dl_aarch64_cpu_features).bti);
++  print_cpu_features_value ("midr_el1",
++                            GLRO (dl_aarch64_cpu_features).midr_el1);
++  print_cpu_features_value ("mte_state",
++                            GLRO (dl_aarch64_cpu_features).mte_state);
++  print_cpu_features_value ("sve", GLRO (dl_aarch64_cpu_features).sve);
++  print_cpu_features_value ("zva_size",
++                            GLRO (dl_aarch64_cpu_features).zva_size);
++
++  struct dl_iterate_cpu dic;
++  _dl_iterate_cpu_init (&dic);
++
++  while (_dl_iterate_cpu_next (&dic))
++    {
++      if (dic.requested_cpu >= 0)
++        _dl_printf ("aarch64.processor[0x%x].requested=0x%x\n",
++                    dic.processor_index, dic.requested_cpu);
++      if (dic.actual_cpu >= 0)
++        _dl_printf ("aarch64.processor[0x%x].observed=0x%x\n",
++                    dic.processor_index, dic.actual_cpu);
++      if (dic.actual_node >= 0)
++        _dl_printf ("aarch64.processor[0x%x].observed_node=0x%x\n",
++                    dic.processor_index, dic.actual_node);
++
++      if (GLRO (dl_hwcap) & HWCAP_CPUID)
++        {
++          uint64_t midr_el1;
++          asm ("mrs %0, midr_el1" : "=r" (midr_el1));
++          print_per_cpu_value (&dic, "midr_el1", midr_el1);
++        }
++
++      {
++        uint64_t dczid_el0;
++        asm ("mrs %0, dczid_el0" : "=r" (dczid_el0));
++        print_per_cpu_value (&dic, "dczid_el0", dczid_el0);
++      }
++    }
++}
diff --git a/SOURCES/glibc-RHEL-22165-4.patch b/SOURCES/glibc-RHEL-22165-4.patch
new file mode 100644
index 0000000000000000000000000000000000000000..0335b6f6776935391647e4199f0f9be83b723052
--- /dev/null
+++ b/SOURCES/glibc-RHEL-22165-4.patch
@@ -0,0 +1,510 @@
+commit 7a430f40c46acfa7ce4c3bff193b278c190b2efc
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Mon Apr 8 16:48:55 2024 +0200
+
+    x86: Add generic CPUID data dumper to ld.so --list-diagnostics
+
+    This is surprisingly difficult to implement if the goal is to produce
+    reasonably sized output.  With the current approaches to output
+    compression (suppressing zeros and repeated results between CPUs,
+    folding ranges of identical subleaves, dealing with the %ecx
+    reflection issue), the output is less than 600 KiB even for systems
+    with 256 logical CPUs.
+
+    Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+
+diff -Nrup a/manual/dynlink.texi b/manual/dynlink.texi
+--- a/manual/dynlink.texi	2024-06-03 08:42:17.011026573 -0400
++++ b/manual/dynlink.texi	2024-06-03 08:55:18.607771972 -0400
+@@ -262,7 +262,90 @@ The value of the @code{dczid_el0} system
+ @item x86.cpu_features.@dots{}
+ These items are specific to the i386 and x86-64 architectures.  They
+ reflect supported CPU features and information on cache geometry, mostly
+-collected using the @code{CPUID} instruction.
++collected using the CPUID instruction.
++
++@item x86.processor[@var{index}].@dots{}
++These are additional items for the i386 and x86-64 architectures, as
++described below.  They mostly contain raw data from the CPUID
++instruction.  The probes are performed for each active CPU for the
++@code{ld.so} process, and data for different probed CPUs receives a
++uniqe @var{index} value.  Some CPUID data is expected to differ from CPU
++core to CPU core.  In some cases, CPUs are not correctly initialized and
++indicate the presence of different feature sets.
++
++@item x86.processor[@var{index}].requested=@var{kernel-cpu}
++The kernel is told to run the subsequent probing on the CPU numbered
++@var{kernel-cpu}.  The values @var{kernel-cpu} and @var{index} can be
++distinct if there are gaps in the process CPU affinity mask.  This line
++is not included if CPU affinity mask information is not available.
++
++@item x86.processor[@var{index}].observed=@var{kernel-cpu}
++This line reports the kernel CPU number @var{kernel-cpu} on which the
++probing code initially ran.  If the CPU number cannot be obtained,
++this line is not printed.
++
++@item x86.processor[@var{index}].observed_node=@var{node}
++This reports the observed NUMA node number, as reported by the
++@code{getcpu} system call.  If this information cannot be obtained, this
++line is not printed.
++
++@item x86.processor[@var{index}].cpuid_leaves=@var{count}
++This line indicates that @var{count} distinct CPUID leaves were
++encountered.  (This reflects internal @code{ld.so} storage space, it
++does not directly correspond to @code{CPUID} enumeration ranges.)
++
++@item x86.processor[@var{index}].ecx_limit=@var{value}
++The CPUID data extraction code uses a brute-force approach to enumerate
++subleaves (see the @samp{.subleaf_eax} lines below).  The last
++@code{%rcx} value used in a CPUID query on this probed CPU was
++@var{value}.
++
++@item x86.processor[@var{index}].cpuid.eax[@var{query_eax}].eax=@var{eax}
++@itemx x86.processor[@var{index}].cpuid.eax[@var{query_eax}].ebx=@var{ebx}
++@itemx x86.processor[@var{index}].cpuid.eax[@var{query_eax}].ecx=@var{ecx}
++@itemx x86.processor[@var{index}].cpuid.eax[@var{query_eax}].edx=@var{edx}
++These lines report the register contents after executing the CPUID
++instruction with @samp{%rax == @var{query_eax}} and @samp{%rcx == 0} (a
++@dfn{leaf}).  For the first probed CPU (with a zero @var{index}), only
++leaves with non-zero register contents are reported.  For subsequent
++CPUs, only leaves whose register contents differs from the previously
++probed CPUs (with @var{index} one less) are reported.
++
++Basic and extended leaves are reported using the same syntax.  This
++means there is a large jump in @var{query_eax} for the first reported
++extended leaf.
++
++@item x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].eax=@var{eax}
++@itemx x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].ebx=@var{ebx}
++@itemx x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].ecx=@var{ecx}
++@itemx x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].edx=@var{edx}
++This is similar to the leaves above, but for a @dfn{subleaf}.  For
++subleaves, the CPUID instruction is executed with @samp{%rax ==
++@var{query_eax}} and @samp{%rcx == @var{query_ecx}}, so the result
++depends on both register values.  The same rules about filtering zero
++and identical results apply.
++
++@item x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].until_ecx=@var{ecx_limit}
++Some CPUID results are the same regardless the @var{query_ecx} value.
++If this situation is detected, a line with the @samp{.until_ecx}
++selector ins included, and this indicates that the CPUID register
++contents is the same for @code{%rcx} values between @var{query_ecx}
++and @var{ecx_limit} (inclusive).
++
++@item x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].ecx_query_mask=0xff
++This line indicates that in an @samp{.until_ecx} range, the CPUID
++instruction preserved the lowested 8 bits of the input @code{%rcx} in
++the output @code{%rcx} registers.  Otherwise, the subleaves in the range
++have identical values.  This special treatment is necessary to report
++compact range information in case such copying occurs (because the
++subleaves would otherwise be all different).
++
++@item x86.processor[@var{index}].xgetbv.ecx[@var{query_ecx}]=@var{result}
++This line shows the 64-bit @var{result} value in the @code{%rdx:%rax}
++register pair after executing the XGETBV instruction with @code{%rcx}
++set to @var{query_ecx}.  Zero values and values matching the previously
++probed CPU are omitted.  Nothing is printed if the system does not
++support the XGETBV instruction.
+ @end table
+ 
+ @node Dynamic Linker Introspection
+diff -Nrup a/sysdeps/x86/dl-diagnostics-cpu.c b/sysdeps/x86/dl-diagnostics-cpu.c
+--- a/sysdeps/x86/dl-diagnostics-cpu.c	2024-06-03 08:42:16.825025689 -0400
++++ b/sysdeps/x86/dl-diagnostics-cpu.c	2024-06-03 09:49:47.528510916 -0400
+@@ -17,7 +17,18 @@
+    <https://www.gnu.org/licenses/>.  */
+ 
+ #include <dl-diagnostics.h>
++
++#include <array_length.h>
++#include <cpu-features.h>
++#include <cpuid.h>
++#include <dl-iterate_cpu.h>
+ #include <ldsodefs.h>
++#include <stdbool.h>
++#include <string.h>
++#include <sysdep.h>
++
++/* The generic CPUID dumping code.  */
++static void _dl_diagnostics_cpuid (void);
+ 
+ static void
+ print_cpu_features_value (const char *label, uint64_t value)
+@@ -119,4 +130,377 @@ _dl_diagnostics_cpu (void)
+                   "last cpu_features field has been printed");
+   print_cpu_features_value ("cachesize_non_temporal_divisor",
+ 			    __rtld_global_ro_cachesize_non_temporal_divisor);
++
++  _dl_diagnostics_cpuid ();
++}
++
++/* The following code implements a generic CPUID dumper that tries to
++   gather CPUID data without knowing about CPUID implementation
++   details.  */
++
++/* Register arguments to CPUID.  Multiple ECX subleaf values yielding
++   the same result are combined, to shorten the output.  Both
++   identical matches (EAX to EDX are the same) and matches where EAX,
++   EBX, EDX, and ECX are equal except in the lower byte, which must
++   match the query ECX value.  The latter is needed to compress ranges
++   on CPUs which preserve the lowest byte in ECX if an unknown leaf is
++   queried.  */
++struct cpuid_query
++{
++  unsigned int eax;
++  unsigned ecx_first;
++  unsigned ecx_last;
++  bool ecx_preserves_query_byte;
++};
++
++/* Single integer value that can be used for sorting/ordering
++   comparisons.  Uses Q->eax and Q->ecx_first only because ecx_last is
++   always greater than the previous ecx_first value and less than the
++   subsequent one.  */
++static inline unsigned long long int
++cpuid_query_combined (struct cpuid_query *q)
++{
++  /* ecx can be -1 (that is, ~0U).  If this happens, this the only ecx
++     value for this eax value, so the ordering does not matter.  */
++  return ((unsigned long long int) q->eax << 32) | (unsigned int) q->ecx_first;
++};
++
++/* Used for differential reporting of zero/non-zero values.  */
++static const struct cpuid_registers cpuid_registers_zero;
++
++/* Register arguments to CPUID paired with the results that came back.  */
++struct cpuid_query_result
++{
++  struct cpuid_query q;
++  struct cpuid_registers r;
++};
++
++/* During a first enumeration pass, we try to collect data for
++  cpuid_initial_subleaf_limit subleaves per leaf/EAX value.  If we run
++  out of space, we try once more with applying the lower limit.  */
++enum { cpuid_main_leaf_limit = 128 };
++enum { cpuid_initial_subleaf_limit = 512 };
++enum { cpuid_subleaf_limit = 32 };
++
++/* Offset of the extended leaf area.  */
++enum {cpuid_extended_leaf_offset = 0x80000000 };
++
++/* Collected CPUID data.  Everything is stored in a statically sized
++   array that is sized so that the second pass will collect some data
++   for all leaves, after the limit is applied.  On the second pass,
++   ecx_limit is set to cpuid_subleaf_limit.  */
++struct cpuid_collected_data
++{
++  unsigned int used;
++  unsigned int ecx_limit;
++  uint64_t xgetbv_ecx_0;
++  struct cpuid_query_result qr[cpuid_main_leaf_limit
++                               * 2 * cpuid_subleaf_limit];
++};
++
++/* Fill in the result of a CPUID query.  Returns true if there is
++   room, false if nothing could be stored.  */
++static bool
++_dl_diagnostics_cpuid_store (struct cpuid_collected_data *ccd,
++                             unsigned eax, int ecx)
++{
++  if (ccd->used >= array_length (ccd->qr))
++    return false;
++
++  /* Tentatively fill in the next value.  */
++  __cpuid_count (eax, ecx,
++                 ccd->qr[ccd->used].r.eax,
++                 ccd->qr[ccd->used].r.ebx,
++                 ccd->qr[ccd->used].r.ecx,
++                 ccd->qr[ccd->used].r.edx);
++
++  /* If the ECX subleaf is next subleaf after the previous one (for
++     the same leaf), and the values are the same, merge the result
++     with the already-stored one.  Do this before skipping zero
++     leaves, which avoids artifiacts for ECX == 256 queries.  */
++  if (ccd->used > 0
++      && ccd->qr[ccd->used - 1].q.eax == eax
++      && ccd->qr[ccd->used - 1].q.ecx_last + 1 == ecx)
++    {
++      /* Exact match of the previous result. Ignore the value of
++         ecx_preserves_query_byte if this is a singleton range so far
++         because we can treat ECX as fixed if the same value repeats.  */
++      if ((!ccd->qr[ccd->used - 1].q.ecx_preserves_query_byte
++           || (ccd->qr[ccd->used - 1].q.ecx_first
++               == ccd->qr[ccd->used - 1].q.ecx_last))
++          && memcmp (&ccd->qr[ccd->used - 1].r, &ccd->qr[ccd->used].r,
++                     sizeof (ccd->qr[ccd->used].r)) == 0)
++        {
++          ccd->qr[ccd->used - 1].q.ecx_last = ecx;
++          /* ECX is now fixed because the same value has been observed
++             twice, even if we had a low-byte match before.  */
++          ccd->qr[ccd->used - 1].q.ecx_preserves_query_byte = false;
++          return true;
++        }
++      /* Match except for the low byte in ECX, which must match the
++         incoming ECX value.  */
++      if (ccd->qr[ccd->used - 1].q.ecx_preserves_query_byte
++          && (ecx & 0xff) == (ccd->qr[ccd->used].r.ecx & 0xff)
++          && ccd->qr[ccd->used].r.eax == ccd->qr[ccd->used - 1].r.eax
++          && ccd->qr[ccd->used].r.ebx == ccd->qr[ccd->used - 1].r.ebx
++          && ((ccd->qr[ccd->used].r.ecx & 0xffffff00)
++              == (ccd->qr[ccd->used - 1].r.ecx & 0xffffff00))
++          && ccd->qr[ccd->used].r.edx == ccd->qr[ccd->used - 1].r.edx)
++        {
++          ccd->qr[ccd->used - 1].q.ecx_last = ecx;
++          return true;
++        }
++    }
++
++  /* Do not store zero results.  All-zero values usually mean that the
++     subleaf is unsupported.  */
++  if (ccd->qr[ccd->used].r.eax == 0
++      && ccd->qr[ccd->used].r.ebx == 0
++      && ccd->qr[ccd->used].r.ecx == 0
++      && ccd->qr[ccd->used].r.edx == 0)
++    return true;
++
++  /* The result needs to be stored.  Fill in the query parameters and
++     consume the storage.  */
++  ccd->qr[ccd->used].q.eax = eax;
++  ccd->qr[ccd->used].q.ecx_first = ecx;
++  ccd->qr[ccd->used].q.ecx_last = ecx;
++  ccd->qr[ccd->used].q.ecx_preserves_query_byte
++    = (ecx & 0xff) == (ccd->qr[ccd->used].r.ecx & 0xff);
++  ++ccd->used;
++  return true;
++}
++
++/* Collected CPUID data into *CCD.  If LIMIT, apply per-leaf limits to
++   avoid exceeding the pre-allocated space.  Return true if all data
++   could be stored, false if the retrying without a limit is
++   requested.  */
++static bool
++_dl_diagnostics_cpuid_collect_1 (struct cpuid_collected_data *ccd, bool limit)
++{
++  ccd->used = 0;
++  ccd->ecx_limit
++    = (limit ? cpuid_subleaf_limit : cpuid_initial_subleaf_limit) - 1;
++  _dl_diagnostics_cpuid_store (ccd, 0x00, 0x00);
++  if (ccd->used == 0)
++    /* CPUID reported all 0.  Should not happen.  */
++    return true;
++  unsigned int maximum_leaf = ccd->qr[0x00].r.eax;
++  if (limit && maximum_leaf >= cpuid_main_leaf_limit)
++    maximum_leaf = cpuid_main_leaf_limit - 1;
++
++  for (unsigned int eax = 1; eax <= maximum_leaf; ++eax)
++    {
++      for (unsigned int ecx = 0; ecx <= ccd->ecx_limit; ++ecx)
++        if (!_dl_diagnostics_cpuid_store (ccd, eax, ecx))
++          return false;
++    }
++
++  if (!_dl_diagnostics_cpuid_store (ccd, cpuid_extended_leaf_offset, 0x00))
++    return false;
++  maximum_leaf = ccd->qr[ccd->used - 1].r.eax;
++  if (maximum_leaf < cpuid_extended_leaf_offset)
++    /* No extended CPUID information.  */
++    return true;
++  if (limit
++      && maximum_leaf - cpuid_extended_leaf_offset >= cpuid_main_leaf_limit)
++    maximum_leaf = cpuid_extended_leaf_offset + cpuid_main_leaf_limit - 1;
++  for (unsigned int eax = cpuid_extended_leaf_offset + 1;
++       eax <= maximum_leaf; ++eax)
++    {
++      for (unsigned int ecx = 0; ecx <= ccd->ecx_limit; ++ecx)
++        if (!_dl_diagnostics_cpuid_store (ccd, eax, ecx))
++          return false;
++    }
++  return true;
++}
++
++/* Call _dl_diagnostics_cpuid_collect_1 twice if necessary, the
++   second time with the limit applied.  */
++static void
++_dl_diagnostics_cpuid_collect (struct cpuid_collected_data *ccd)
++{
++  if (!_dl_diagnostics_cpuid_collect_1 (ccd, false))
++    _dl_diagnostics_cpuid_collect_1 (ccd, true);
++
++  /* Re-use the result of the official feature probing here.  */
++  const struct cpu_features *cpu_features = __get_cpu_features ();
++  if (CPU_FEATURES_CPU_P (cpu_features, OSXSAVE))
++    {
++      unsigned int xcrlow;
++      unsigned int xcrhigh;
++      asm ("xgetbv" : "=a" (xcrlow), "=d" (xcrhigh) : "c" (0));
++      ccd->xgetbv_ecx_0 = ((uint64_t) xcrhigh << 32) + xcrlow;
++    }
++  else
++    ccd->xgetbv_ecx_0 = 0;
++}
++
++/* Print a CPUID register value (passed as REG_VALUE) if it differs
++   from the expected REG_REFERENCE value.  PROCESSOR_INDEX is the
++   process sequence number (always starting at zero; not a kernel ID).  */
++static void
++_dl_diagnostics_cpuid_print_reg (unsigned int processor_index,
++                                 const struct cpuid_query *q,
++                                 const char *reg_label, unsigned int reg_value,
++                                 bool subleaf)
++{
++  if (subleaf)
++    _dl_printf ("x86.processor[0x%x].cpuid.subleaf_eax[0x%x]"
++                ".ecx[0x%x].%s=0x%x\n",
++                processor_index, q->eax, q->ecx_first, reg_label, reg_value);
++  else
++    _dl_printf ("x86.processor[0x%x].cpuid.eax[0x%x].%s=0x%x\n",
++                processor_index, q->eax, reg_label, reg_value);
++}
++
++/* Print CPUID result values in *RESULT for the query in
++   CCD->qr[CCD_IDX].  PROCESSOR_INDEX is the process sequence number
++   (always starting at zero; not a kernel ID).  */
++static void
++_dl_diagnostics_cpuid_print_query (unsigned int processor_index,
++                                   struct cpuid_collected_data *ccd,
++                                   unsigned int ccd_idx,
++                                   const struct cpuid_registers *result)
++{
++  /* Treat this as a value if subleaves if ecx isn't zero (maybe
++     within the [ecx_fist, ecx_last] range), or if eax matches its
++     neighbors.  If the range is [0, ecx_limit], then the subleaves
++     are not distinct (independently of ecx_preserves_query_byte),
++     so do not report them separately.  */
++  struct cpuid_query *q = &ccd->qr[ccd_idx].q;
++  bool subleaf = (q->ecx_first > 0
++                  || (q->ecx_first != q->ecx_last
++                      && !(q->ecx_first == 0 && q->ecx_last == ccd->ecx_limit))
++                  || (ccd_idx > 0 && q->eax == ccd->qr[ccd_idx - 1].q.eax)
++                  || (ccd_idx + 1 < ccd->used
++                      && q->eax == ccd->qr[ccd_idx + 1].q.eax));
++  _dl_diagnostics_cpuid_print_reg (processor_index, q, "eax", result->eax,
++                                   subleaf);
++  _dl_diagnostics_cpuid_print_reg (processor_index, q, "ebx", result->ebx,
++                                   subleaf);
++  _dl_diagnostics_cpuid_print_reg (processor_index, q, "ecx", result->ecx,
++                                   subleaf);
++  _dl_diagnostics_cpuid_print_reg (processor_index, q, "edx", result->edx,
++                                   subleaf);
++
++  if (subleaf && q->ecx_first != q->ecx_last)
++    {
++      _dl_printf ("x86.processor[0x%x].cpuid.subleaf_eax[0x%x]"
++                  ".ecx[0x%x].until_ecx=0x%x\n",
++                  processor_index, q->eax, q->ecx_first, q->ecx_last);
++      if (q->ecx_preserves_query_byte)
++        _dl_printf ("x86.processor[0x%x].cpuid.subleaf_eax[0x%x]"
++                    ".ecx[0x%x].ecx_query_mask=0xff\n",
++                    processor_index, q->eax, q->ecx_first);
++    }
++}
++
++/* Perform differential reporting of the data in *CURRENT against
++   *BASE.  REQUESTED_CPU is the kernel CPU ID the thread was
++   configured to run on, or -1 if no configuration was possible.
++   PROCESSOR_INDEX is the process sequence number (always starting at
++   zero; not a kernel ID).  */
++static void
++_dl_diagnostics_cpuid_report (struct dl_iterate_cpu *dci,
++                              struct cpuid_collected_data *current,
++                              struct cpuid_collected_data *base)
++{
++  if (dci->requested_cpu >= 0)
++    _dl_printf ("x86.processor[0x%x].requested=0x%x\n",
++                dci->processor_index, dci->requested_cpu);
++  if (dci->actual_cpu >= 0)
++    _dl_printf ("x86.processor[0x%x].observed=0x%x\n",
++                dci->processor_index, dci->actual_cpu);
++  if (dci->actual_node >= 0)
++    _dl_printf ("x86.processor[0x%x].observed_node=0x%x\n",
++                dci->processor_index, dci->actual_node);
++
++  _dl_printf ("x86.processor[0x%x].cpuid_leaves=0x%x\n",
++              dci->processor_index, current->used);
++  _dl_printf ("x86.processor[0x%x].ecx_limit=0x%x\n",
++              dci->processor_index, current->ecx_limit);
++
++  unsigned int base_idx = 0;
++  for (unsigned int current_idx = 0; current_idx < current->used;
++       ++current_idx)
++    {
++      /* Report missing data on the current CPU as 0.  */
++      unsigned long long int current_query
++        = cpuid_query_combined (&current->qr[current_idx].q);
++      while (base_idx < base->used
++             && cpuid_query_combined (&base->qr[base_idx].q) < current_query)
++      {
++        _dl_diagnostics_cpuid_print_query (dci->processor_index,
++                                           base, base_idx,
++                                           &cpuid_registers_zero);
++        ++base_idx;
++      }
++
++      if (base_idx < base->used
++          && cpuid_query_combined (&base->qr[base_idx].q) == current_query)
++        {
++          _Static_assert (sizeof (struct cpuid_registers) == 4 * 4,
++                          "no padding in struct cpuid_registers");
++          if (current->qr[current_idx].q.ecx_last
++              != base->qr[base_idx].q.ecx_last
++              || memcmp (&current->qr[current_idx].r,
++                         &base->qr[base_idx].r,
++                         sizeof (struct cpuid_registers)) != 0)
++              /* The ECX range or the values have changed.  Show the
++                 new values.  */
++            _dl_diagnostics_cpuid_print_query (dci->processor_index,
++                                               current, current_idx,
++                                               &current->qr[current_idx].r);
++          ++base_idx;
++        }
++      else
++        /* Data is absent in the base reference.  Report the new data.  */
++        _dl_diagnostics_cpuid_print_query (dci->processor_index,
++                                           current, current_idx,
++                                           &current->qr[current_idx].r);
++    }
++
++  if (current->xgetbv_ecx_0 != base->xgetbv_ecx_0)
++    {
++      /* Re-use the 64-bit printing routine.  */
++      _dl_printf ("x86.processor[0x%x].", dci->processor_index);
++      _dl_diagnostics_print_labeled_value ("xgetbv.ecx[0x0]",
++                                           current->xgetbv_ecx_0);
++    }
++}
++
++static void
++_dl_diagnostics_cpuid (void)
++{
++#if !HAS_CPUID
++  /* CPUID is not supported, so there is nothing to dump.  */
++  if (__get_cpuid_max (0, 0) == 0)
++    return;
++#endif
++
++  struct dl_iterate_cpu dic;
++  _dl_iterate_cpu_init (&dic);
++
++  /* Two copies of the data are used.  Data is written to the index
++     (dic.processor_index & 1).  The previous version against which the
++     data dump is reported is at index !(processor_index & 1).  */
++  struct cpuid_collected_data ccd[2];
++
++  /* The initial data is presumed to be all zero.  Zero results are
++     not recorded.  */
++  ccd[1].used = 0;
++  ccd[1].xgetbv_ecx_0 = 0;
++
++  /* Run the CPUID probing on a specific CPU.  There are expected
++     differences for encoding core IDs and topology information in
++     CPUID output, but some firmware/kernel bugs also may result in
++     asymmetric data across CPUs in some cases.  */
++  while (_dl_iterate_cpu_next (&dic))
++    {
++      _dl_diagnostics_cpuid_collect (&ccd[dic.processor_index & 1]);
++      _dl_diagnostics_cpuid_report
++        (&dic, &ccd[dic.processor_index & 1],
++         &ccd[!(dic.processor_index & 1)]);
++    }
+ }
diff --git a/SOURCES/glibc-RHEL-22165-5.patch b/SOURCES/glibc-RHEL-22165-5.patch
new file mode 100644
index 0000000000000000000000000000000000000000..76b42ea00ead4f08a48c2ed96d78532836a13a6c
--- /dev/null
+++ b/SOURCES/glibc-RHEL-22165-5.patch
@@ -0,0 +1,262 @@
+commit 5653ccd847f0cd3a98906e44c97c71d68652d326
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Mon Apr 8 16:48:55 2024 +0200
+
+    elf: Add CPU iteration support for future use in ld.so diagnostics
+    
+    Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+diff --git a/elf/dl-iterate_cpu.h b/elf/dl-iterate_cpu.h
+new file mode 100644
+index 0000000000..60db167b13
+--- /dev/null
++++ b/elf/dl-iterate_cpu.h
+@@ -0,0 +1,136 @@
++/* Iterate over all CPUs, for CPU-specific diagnostics.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#ifndef DL_ITERATE_CPU_H
++#define DL_ITERATE_CPU_H
++
++#include <dl-affinity.h>
++#include <stdbool.h>
++
++struct dl_iterate_cpu
++{
++  /* Sequential iteration count, starting at 0.  */
++  unsigned int processor_index;
++
++  /* Requested CPU.  Can be -1 if affinity could not be set.  */
++  int requested_cpu;
++
++  /* Observed current CPU.  -1 if unavailable.  */
++  int actual_cpu;
++
++  /* Observed node ID for the CPU.  -1 if unavailable.  */
++  int actual_node;
++
++  /* Internal fields to implement the iteration.   */
++
++  /* Affinity as obtained by _dl_iterate_cpu_init, using
++     _dl_getaffinity.  Space for 8,192 CPUs.  */
++  unsigned long int mask_reference[8192 / sizeof (unsigned long int) / 8];
++
++  /* This array is used by _dl_setaffinity calls.  */
++  unsigned long int mask_request[8192 / sizeof (unsigned long int) / 8];
++
++  /* Return value from the initial _dl_getaffinity call.   */
++  int length_reference;
++};
++
++static void
++_dl_iterate_cpu_init (struct dl_iterate_cpu *dic)
++{
++  dic->length_reference
++    = _dl_getaffinity (dic->mask_reference, sizeof (dic->mask_reference));
++  /* Prepare for the first _dl_iterate_cpu_next call.  */
++  dic->processor_index = -1;
++  dic->requested_cpu = -1;
++}
++
++static bool
++_dl_iterate_cpu_next (struct dl_iterate_cpu *dic)
++{
++  ++dic->processor_index;
++
++  if (dic->length_reference > 0)
++    {
++      /* Search for the next CPU to switch to.  */
++      while (true)
++        {
++          ++dic->requested_cpu;
++
++          /* Array index and bit number within the array.  */
++          unsigned int long_index
++            = dic->requested_cpu / sizeof (unsigned long int) / 8;
++          unsigned int bit_index
++            = dic->requested_cpu % (sizeof (unsigned long int) * 8);
++
++          if (long_index * sizeof (unsigned long int) >= dic->length_reference)
++            /* All possible CPUs have been covered.  */
++            return false;
++
++          unsigned long int bit = 1UL << bit_index;
++          if (dic->mask_reference[long_index] & bit)
++            {
++              /* The CPU is available.  Try to select it.  */
++              dic->mask_request[long_index] = bit;
++              if (_dl_setaffinity (dic->mask_request,
++                                   (long_index + 1)
++                                   * sizeof (unsigned long int)) < 0)
++                {
++                  /* Record that we could not perform a CPU request.  */
++                  dic->length_reference = -1;
++
++                  if (dic->processor_index > 0)
++                    /* We already reported something.  There is no need to
++                       continue because the new data is probably not useful.  */
++                    return false;
++                }
++
++              /* Clear the bit in case the next iteration switches to the
++                 next long value.  */
++              dic->mask_request[long_index] = 0;
++
++              /* We found a CPU to run on.  */
++              break;
++            }
++        }
++    }
++  else
++    {
++      /* No way to set CPU affinity.  Iterate just once.  */
++      if (dic->processor_index > 0)
++        return false;
++    }
++
++  /* Fill in the actual CPU information.  CPU pinning may not actually
++     be effective, depending on the container host.  */
++  unsigned int cpu, node;
++  if (_dl_getcpu (&cpu, &node) < 0)
++    {
++      /* No CPU information available.  */
++      dic->actual_cpu = -1;
++      dic->actual_node = -1;
++    }
++  else
++    {
++      dic->actual_cpu = cpu;
++      dic->actual_node = node;
++    }
++
++  return true;
++}
++
++#endif /* DL_ITERATE_CPU_H */
+diff --git a/sysdeps/generic/dl-affinity.h b/sysdeps/generic/dl-affinity.h
+new file mode 100644
+index 0000000000..d117f737e9
+--- /dev/null
++++ b/sysdeps/generic/dl-affinity.h
+@@ -0,0 +1,54 @@
++/* CPU affinity handling for the dynamic linker.  Stub version.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#ifndef DL_AFFINITY_H
++#define DL_AFFINITY_H
++
++#include <errno.h>
++#include <stddef.h>
++
++/* On success, write the current CPU ID to *CPU, and the current node
++   ID to *NODE, and return 0.  Return a negative error code on
++   failure.  */
++static inline int
++_dl_getcpu (unsigned int *cpu, unsigned int *node)
++{
++  return -ENOSYS;
++}
++
++/* On success, write CPU ID affinity bits for the current thread to
++   *BITS, which must be SIZE bytes long, and return the number of
++   bytes updated, a multiple of sizeof (unsigned long int).  On
++   failure, return a negative error code.  */
++static int
++_dl_getaffinity (unsigned long int *bits, size_t size)
++{
++  return -ENOSYS;
++}
++
++/* Set the CPU affinity mask for the current thread to *BITS, using
++   the SIZE bytes from that array, which should be a multiple of
++   sizeof (unsigned long int).  Return 0 on success, and a negative
++   error code on failure.  */
++static int
++_dl_setaffinity (const unsigned long int *bits, size_t size)
++{
++  return -ENOSYS;
++}
++
++#endif /* DL_AFFINITY_H */
+diff --git a/sysdeps/unix/sysv/linux/dl-affinity.h b/sysdeps/unix/sysv/linux/dl-affinity.h
+new file mode 100644
+index 0000000000..bbfede7750
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/dl-affinity.h
+@@ -0,0 +1,46 @@
++/* CPU affinity handling for the dynamic linker.  Linux version.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++/* See sysdeps/generic/dl-affinity.h for documentation of these interfaces.  */
++
++#ifndef DL_AFFINITY_H
++#define DL_AFFINITY_H
++
++#include <sysdep.h>
++#include <stddef.h>
++#include <unistd.h>
++
++static inline int
++_dl_getcpu (unsigned int *cpu, unsigned int *node)
++{
++  return INTERNAL_SYSCALL_CALL (getcpu, cpu, node);
++}
++
++static int
++_dl_getaffinity (unsigned long int *bits, size_t size)
++{
++  return INTERNAL_SYSCALL_CALL (sched_getaffinity, /* TID */ 0, size, bits);
++}
++
++static int
++_dl_setaffinity (const unsigned long int *bits, size_t size)
++{
++  return INTERNAL_SYSCALL_CALL (sched_setaffinity, /* TID */ 0, size, bits);
++}
++
++#endif /* DL_AFFINITY_H */
diff --git a/SOURCES/glibc-RHEL-23472.patch b/SOURCES/glibc-RHEL-23472.patch
new file mode 100644
index 0000000000000000000000000000000000000000..95aae42c0830baa3f47ebc8ab09c03f0a252af2a
--- /dev/null
+++ b/SOURCES/glibc-RHEL-23472.patch
@@ -0,0 +1,140 @@
+commit 6a04404521ac4119ae36827eeb288ea84eee7cf6 
+Author: Florian Weimer <fweimer@redhat.com> 
+Date:   Sat Feb 17 09:17:04 2024 +0100 
+ 
+    Linux: Switch back to assembly syscall wrapper for prctl (bug 29770) 
+     
+    Commit ff026950e280bc3e9487b41b460fb31bc5b57721 ("Add a C wrapper for 
+    prctl [BZ #25896]") replaced the assembler wrapper with a C function. 
+    However, on powerpc64le-linux-gnu, the C variadic function 
+    implementation requires extra work in the caller to set up the 
+    parameter save area.  Calling a function that needs a parameter save 
+    area without one (because the prototype used indicates the function is 
+    not variadic) corrupts the caller's stack.   The Linux manual pages 
+    project documents prctl as a non-variadic function.  This has resulted 
+    in various projects over the years using non-variadic prototypes, 
+    including the sanitizer libraries in LLVm and GCC (GCC PR 113728). 
+     
+    This commit switches back to the assembler implementation on most 
+    targets and only keeps the C implementation for x86-64 x32. 
+     
+    Also add the __prctl_time64 alias from commit 
+    b39ffab860cd743a82c91946619f1b8158b0b65e ("Linux: Add time64 alias for 
+    prctl") to sysdeps/unix/sysv/linux/syscalls.list; it was not yet 
+    present in commit ff026950e280bc3e9487b41b460fb31bc5b57721. 
+     
+    This restores the old ABI on powerpc64le-linux-gnu, thus fixing 
+    bug 29770. 
+     
+    Reviewed-By: Simon Chopin <simon.chopin@canonical.com> 
+
+    Resolved conflicts:
+	sysdeps/unix/sysv/linux/syscalls.list
+	sysdeps/unix/sysv/linux/x86_64/x32/prctl.c
+
+diff -Nrup a/sysdeps/unix/sysv/linux/prctl.c b/sysdeps/unix/sysv/linux/prctl.c
+--- a/sysdeps/unix/sysv/linux/prctl.c	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/prctl.c	1969-12-31 19:00:00.000000000 -0500
+@@ -1,45 +0,0 @@
+-/* prctl - Linux specific syscall.
+-   Copyright (C) 2020-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
+-   <https://www.gnu.org/licenses/>.  */
+-
+-#include <sysdep.h>
+-#include <stdarg.h>
+-#include <sys/prctl.h>
+-
+-/* Unconditionally read all potential arguments.  This may pass
+-   garbage values to the kernel, but avoids the need for teaching
+-   glibc the argument counts of individual options (including ones
+-   that are added to the kernel in the future).  */
+-
+-int
+-__prctl (int option, ...)
+-{
+-  va_list arg;
+-  va_start (arg, option);
+-  unsigned long int arg2 = va_arg (arg, unsigned long int);
+-  unsigned long int arg3 = va_arg (arg, unsigned long int);
+-  unsigned long int arg4 = va_arg (arg, unsigned long int);
+-  unsigned long int arg5 = va_arg (arg, unsigned long int);
+-  va_end (arg);
+-  return INLINE_SYSCALL_CALL (prctl, option, arg2, arg3, arg4, arg5);
+-}
+-
+-libc_hidden_def (__prctl)
+-weak_alias (__prctl, prctl)
+-#if __TIMESIZE != 64
+-weak_alias (__prctl, __prctl_time64)
+-#endif
+diff -Nrup a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
+--- a/sysdeps/unix/sysv/linux/syscalls.list	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/syscalls.list	2024-02-27 14:33:01.594782897 -0500
+@@ -41,6 +41,7 @@ munlockall	-	munlockall	i:	munlockall
+ nfsservctl	EXTRA	nfsservctl	i:ipp	__compat_nfsservctl	nfsservctl@GLIBC_2.0:GLIBC_2.28
+ pipe		-	pipe		i:f	__pipe		pipe
+ pipe2		-	pipe2		i:fi	__pipe2		pipe2
++prctl		EXTRA   prctl           i:iiiii __prctl         prctl __prctl_time64
+ pivot_root	EXTRA	pivot_root	i:ss	pivot_root
+ query_module	EXTRA	query_module	i:sipip	__compat_query_module	query_module@GLIBC_2.0:GLIBC_2.23
+ quotactl	EXTRA	quotactl	i:isip	quotactl
+diff -Nrup a/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c b/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c
+--- a/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c	1969-12-31 19:00:00.000000000 -0500
++++ b/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c	2024-02-27 14:35:03.388602623 -0500
+@@ -0,0 +1,42 @@
++/* prctl - Linux specific syscall.  x86-64 x32 version.
++   Copyright (C) 2020-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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <sysdep.h>
++#include <stdarg.h>
++#include <sys/prctl.h>
++
++/* Unconditionally read all potential arguments.  This may pass
++   garbage values to the kernel, but avoids the need for teaching
++   glibc the argument counts of individual options (including ones
++   that are added to the kernel in the future).  */
++
++int
++__prctl (int option, ...)
++{
++  va_list arg;
++  va_start (arg, option);
++  unsigned long int arg2 = va_arg (arg, unsigned long int);
++  unsigned long int arg3 = va_arg (arg, unsigned long int);
++  unsigned long int arg4 = va_arg (arg, unsigned long int);
++  unsigned long int arg5 = va_arg (arg, unsigned long int);
++  va_end (arg);
++  return INLINE_SYSCALL_CALL (prctl, option, arg2, arg3, arg4, arg5);
++}
++
++libc_hidden_def (__prctl)
++weak_alias (__prctl, prctl)
diff --git a/SOURCES/glibc-RHEL-25046.patch b/SOURCES/glibc-RHEL-25046.patch
new file mode 100644
index 0000000000000000000000000000000000000000..db48ca3fb25c3dbbc2b45d8843dbe71f4738527f
--- /dev/null
+++ b/SOURCES/glibc-RHEL-25046.patch
@@ -0,0 +1,88 @@
+From dfb05f8e704edac70db38c4c8ee700769d91a413 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Fri, 16 Feb 2024 07:17:10 -0800
+Subject: [PATCH] x86-64: Save APX registers in ld.so trampoline
+Content-type: text/plain; charset=UTF-8
+
+Add APX registers to STATE_SAVE_MASK so that APX registers are saved in
+ld.so trampoline.  This fixes BZ #31371.
+
+Also update STATE_SAVE_OFFSET and STATE_SAVE_MASK for i386 which will
+be used by i386 _dl_tlsdesc_dynamic.
+Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
+
+Conflicts:
+	sysdeps/x86/sysdep.h
+	(rebased for context and line numbers)
+---
+ sysdeps/x86/sysdep.h | 52 +++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 46 insertions(+), 6 deletions(-)
+
+diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h
+index 85d0a8c943..837fd28734 100644
+--- a/sysdeps/x86/sysdep.h
++++ b/sysdeps/x86/sysdep.h
+@@ -48,14 +48,54 @@
+ # define SHSTK_ENABLED	0
+ #endif
+ 
++/* The extended state feature IDs in the state component bitmap.  */
++#define X86_XSTATE_X87_ID	0
++#define X86_XSTATE_SSE_ID	1
++#define X86_XSTATE_AVX_ID	2
++#define X86_XSTATE_BNDREGS_ID	3
++#define X86_XSTATE_BNDCFG_ID	4
++#define X86_XSTATE_K_ID		5
++#define X86_XSTATE_ZMM_H_ID	6
++#define X86_XSTATE_ZMM_ID	7
++#define X86_XSTATE_PKRU_ID	9
++#define X86_XSTATE_TILECFG_ID	17
++#define X86_XSTATE_TILEDATA_ID	18
++#define X86_XSTATE_APX_F_ID	19
++
++#ifdef __x86_64__
+ /* Offset for fxsave/xsave area used by _dl_runtime_resolve.  Also need
+    space to preserve RCX, RDX, RSI, RDI, R8, R9 and RAX.  It must be
+-   aligned to 16 bytes for fxsave and 64 bytes for xsave.  */
+-#define STATE_SAVE_OFFSET (8 * 7 + 8)
+-
+-/* Save SSE, AVX, AVX512, mask and bound registers.  */
+-#define STATE_SAVE_MASK \
+-  ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7))
++   aligned to 16 bytes for fxsave and 64 bytes for xsave.
++
++   NB: Is is non-zero because of the 128-byte red-zone.  Some registers
++   are saved on stack without adjusting stack pointer first.  When we
++   update stack pointer to allocate more space, we need to take the
++   red-zone into account.  */
++# define STATE_SAVE_OFFSET (8 * 7 + 8)
++
++/* Save SSE, AVX, AVX512, mask, bound and APX registers.  Bound and APX
++   registers are mutually exclusive.  */
++# define STATE_SAVE_MASK		\
++  ((1 << X86_XSTATE_SSE_ID)		\
++   | (1 << X86_XSTATE_AVX_ID)		\
++   | (1 << X86_XSTATE_BNDREGS_ID)	\
++   | (1 << X86_XSTATE_K_ID)		\
++   | (1 << X86_XSTATE_ZMM_H_ID) 	\
++   | (1 << X86_XSTATE_ZMM_ID)		\
++   | (1 << X86_XSTATE_APX_F_ID))
++#else
++/* Offset for fxsave/xsave area used by _dl_tlsdesc_dynamic.  Since i386
++   doesn't have red-zone, use 0 here.  */
++# define STATE_SAVE_OFFSET 0
++
++/* Save SSE, AVX, AXV512, mask and bound registers.   */
++# define STATE_SAVE_MASK		\
++  ((1 << X86_XSTATE_SSE_ID)		\
++   | (1 << X86_XSTATE_AVX_ID)		\
++   | (1 << X86_XSTATE_BNDREGS_ID)	\
++   | (1 << X86_XSTATE_K_ID)		\
++   | (1 << X86_XSTATE_ZMM_H_ID))
++#endif
+ 
+ /* Constants for bits in __x86_string_control:  */
+ 
+-- 
+2.39.3
+
diff --git a/SOURCES/glibc-RHEL-25063.patch b/SOURCES/glibc-RHEL-25063.patch
new file mode 100644
index 0000000000000000000000000000000000000000..58580e927984dc3786e6a7f2dd24b11dbc14beba
--- /dev/null
+++ b/SOURCES/glibc-RHEL-25063.patch
@@ -0,0 +1,109 @@
+commit 127fc56152347d73cb7c1c283e60e1cb1f15e9f9
+Author: sayan paul <saypaul@redhat.com>
+Date:   Wed May 29 15:31:04 2024 +0530
+
+    malloc: New test to check malloc alternate path using memory obstruction
+    
+    The test aims to ensure that malloc uses the alternate path to
+    allocate memory when sbrk() or brk() fails.To achieve this,
+    the test first creates an obstruction at current program break,
+    tests that obstruction with a failing sbrk(), then checks if malloc
+    is still returning a valid ptr thus inferring that malloc() used
+    mmap() instead of brk() or sbrk() to allocate the memory.
+    Reviewed-by: Arjun Shankar <arjun@redhat.com>
+    Reviewed-by: Zack Weinberg <zack@owlfolio.org>
+
+Conflicts:
+	malloc/Makefile
+	  (usual tests conflict)
+
+diff --git a/malloc/Makefile b/malloc/Makefile
+index 9b70831d383cb522..cb4e027d28b179f0 100644
+--- a/malloc/Makefile
++++ b/malloc/Makefile
+@@ -43,6 +43,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
+ 	 tst-tcfree1 tst-tcfree2 tst-tcfree3 \
+ 	 tst-safe-linking \
+ 	 tst-mallocalign1 \
++	 tst-malloc-alternate-path \
+ 
+ tests-static := \
+ 	 tst-interpose-static-nothread \
+diff --git a/malloc/tst-malloc-alternate-path.c b/malloc/tst-malloc-alternate-path.c
+new file mode 100644
+index 0000000000000000..43ae916815d6ff47
+--- /dev/null
++++ b/malloc/tst-malloc-alternate-path.c
+@@ -0,0 +1,72 @@
++/* Test that malloc uses mmap when sbrk or brk fails.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++/* This test sets up an obstruction to ensure that brk/sbrk fails to
++   grow the heap, then verifies that malloc uses mmap for allocations
++   instead.  */
++
++#include <unistd.h>
++#include <sys/mman.h>
++#include <stdlib.h>
++#include <libc-pointer-arith.h>
++#include <support/check.h>
++#include <stddef.h>
++#include <stdalign.h>
++
++#define LARGE_SIZE (10 * (1 << 20)) // 10 MB
++static long page_size;
++
++static int
++do_test (void)
++{
++  /* Get current program break.  */
++  void *current_brk = sbrk (0);
++
++  page_size = sysconf (_SC_PAGESIZE);
++
++  /* Round up to the next page boundary.  */
++  void *next_page_boundary = PTR_ALIGN_UP (current_brk, page_size);
++
++  /* Place a mapping using mmap at the next page boundary.  */
++  void *obstruction_addr
++  = mmap (next_page_boundary, page_size, PROT_READ,
++    MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
++
++  /* Check if memory obstruction is set up correctly.  */
++  TEST_VERIFY_EXIT (obstruction_addr == next_page_boundary);
++
++  /* Try to extend the heap beyond the obstruction using sbrk */
++  int *ptr = sbrk (page_size);
++  TEST_VERIFY_EXIT (ptr == (void *) -1);
++
++  /* Attempt multiple small allocations using malloc.  */
++  for (size_t i = 0; i < page_size / alignof (max_align_t); i++)
++    {
++      TEST_VERIFY (malloc (alignof (max_align_t)));
++    }
++
++  /* Attempt to allocate a large block of memory using malloc.  */
++  TEST_VERIFY_EXIT (malloc (LARGE_SIZE) != NULL);
++
++  /* Check if malloc changed current program break.  */
++  TEST_VERIFY_EXIT (current_brk == sbrk (0));
++
++  return 0;
++}
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-RHEL-25257-1.patch b/SOURCES/glibc-RHEL-25257-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c7413d77ea19e1bc8254a86a188fd9ff57a298ac
--- /dev/null
+++ b/SOURCES/glibc-RHEL-25257-1.patch
@@ -0,0 +1,26 @@
+From a07e000e82cb71238259e674529c37c12dc7d423 Mon Sep 17 00:00:00 2001
+From: DJ Delorie <dj@redhat.com>
+Date: Fri, 10 May 2024 17:34:29 -0400
+Subject: manual: add dup3
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+diff --git a/manual/llio.texi b/manual/llio.texi
+index fae49d1433..fe1807a849 100644
+--- a/manual/llio.texi
++++ b/manual/llio.texi
+@@ -3415,6 +3415,14 @@ middle of calling @code{dup2} at which @var{new} is closed and not yet a
+ duplicate of @var{old}.
+ @end deftypefun
+ 
++@deftypefun int dup3 (int @var{old}, int @var{new}, int @var{flags})
++@standards{Linux, unistd.h}
++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
++This function is the same as @code{dup2} but creates the new
++descriptor as if it had been opened with flags @var{flags}.  The only
++allowed flag is @code{O_CLOEXEC}.
++@end deftypefun
++
+ @deftypevr Macro int F_DUPFD
+ @standards{POSIX.1, fcntl.h}
+ This macro is used as the @var{command} argument to @code{fcntl}, to
diff --git a/SOURCES/glibc-RHEL-25257-2.patch b/SOURCES/glibc-RHEL-25257-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d6e518b30deef6175123c3413d682f84c295a01f
--- /dev/null
+++ b/SOURCES/glibc-RHEL-25257-2.patch
@@ -0,0 +1,341 @@
+From 6c0be74305745c8f78bcfb69442c8c379459d99b Mon Sep 17 00:00:00 2001
+From: DJ Delorie <dj@redhat.com>
+Date: Mon, 8 Jul 2024 17:52:15 -0400
+Subject: manual: add syscalls
+
+The purpose of this patch is to add some system calls that (1) aren't
+otherwise documented, and (2) are merely redirected to the kernel, so
+can refer to their documentation; and define a standard way of doing
+so in the future.  A more detailed explaination of how system calls
+are wrapped is added along with reference to the Linux Man-Pages
+project.
+
+Default version of man-pages is in configure.ac but can be overridden
+by --with-man-pages=X.Y
+
+Reviewed-by: Alejandro Colomar <alx@kernel.org>
+
+diff --git a/config.make.in b/config.make.in
+index 55e8b7563b..36096881b7 100644
+--- a/config.make.in
++++ b/config.make.in
+@@ -101,6 +101,7 @@ build-hardcoded-path-in-tests= @hardcode
+ build-pt-chown = @build_pt_chown@
+ have-tunables = @have_tunables@
+ pthread-in-libc = @pthread_in_libc@
++man-pages-version = @man_pages_version@
+ 
+ # Build tools.
+ CC = @CC@
+diff --git a/configure b/configure
+index 55e8b7563b..36096881b7 100644
+--- a/configure	2024-07-17 15:45:55.033649362 -0400
++++ b/configure	2024-07-17 15:47:44.281886629 -0400
+@@ -681,6 +681,7 @@ force_install
+ bindnow
+ hardcoded_path_in_tests
+ enable_timezone_tools
++man_pages_version
+ rtld_early_cflags
+ extra_nonshared_cflags
+ use_default_link
+@@ -763,6 +764,7 @@ with_headers
+ with_default_link
+ with_nonshared_cflags
+ with_rtld_early_cflags
++with_man_pages
+ enable_sanity_checks
+ enable_shared
+ enable_profile
+@@ -1483,6 +1485,8 @@ Optional Packages:
+                           build nonshared libraries with additional CFLAGS
+   --with-rtld-early-cflags=CFLAGS
+                           build early initialization with additional CFLAGS
++  --with-man-pages=VERSION
++                          tie manual to a specific man-pages version
+   --with-cpu=CPU          select code for CPU variant
+ 
+ Some influential environment variables:
+@@ -3396,6 +3400,15 @@ fi
+ 
+ 
+ 
++man_pages_version=6.9.1
++
++
++# Check whether --with-man-pages was given.
++if test "${with_man_pages+set}" = set; then :
++  withval=$with_man_pages; man_pages_version=$withval
++fi
++
++
+ 
+ # Check whether --enable-sanity-checks was given.
+ if test "${enable_sanity_checks+set}" = set; then :
+diff --git a/configure.ac b/configure.ac
+index e48957f318..9cbc0bf68f 100644
+--- a/configure.ac	2024-07-17 15:45:52.181538742 -0400
++++ b/configure.ac	2024-07-17 15:46:29.885001095 -0400
+@@ -169,6 +169,15 @@ AC_ARG_WITH([rtld-early-cflags],
+ 	    [rtld_early_cflags=])
+ AC_SUBST(rtld_early_cflags)
+ 
++man_pages_version=6.9.1
++
++AC_ARG_WITH([man-pages],
++	    AS_HELP_STRING([--with-man-pages=VERSION],
++			   [tie manual to a specific man-pages version]),
++	    [man_pages_version=$withval],
++	    [])
++AC_SUBST(man_pages_version)
++
+ AC_ARG_ENABLE([sanity-checks],
+ 	      AS_HELP_STRING([--disable-sanity-checks],
+ 			     [really do not use threads (should not be used except in special situations) @<:@default=yes@:>@]),
+diff --git a/manual/Makefile b/manual/Makefile
+index b5fda4a7ae..a6c05db540 100644
+--- a/manual/Makefile
++++ b/manual/Makefile
+@@ -117,6 +117,7 @@ $(objpfx)stamp-pkgvers: $(common-objpfx)config.make
+ 	  echo "@set PKGVERSION_DEFAULT" >> $(objpfx)pkgvers-tmp; \
+ 	fi
+ 	echo "@set REPORT_BUGS_TO $(REPORT_BUGS_TEXI)" >> $(objpfx)pkgvers-tmp
++	echo "@set man_pages_version $(man-pages-version)" >> $(objpfx)pkgvers-tmp; \
+ 	echo "@end ifclear" >> $(objpfx)pkgvers-tmp
+ 	$(move-if-change) $(objpfx)pkgvers-tmp $(objpfx)pkgvers.texi
+ 	touch $@
+diff --git a/manual/intro.texi b/manual/intro.texi
+index ff43c5a7fb..879c1b38d9 100644
+--- a/manual/intro.texi
++++ b/manual/intro.texi
+@@ -85,6 +85,7 @@ standards each function or symbol comes from.
+ * Berkeley Unix::               BSD and SunOS.
+ * SVID::                        The System V Interface Description.
+ * XPG::                         The X/Open Portability Guide.
++* Linux Kernel::                The Linux kernel.
+ @end menu
+ 
+ @node ISO C, POSIX,  , Standards and Portability
+@@ -941,7 +942,7 @@ inter-process communication and shared memory, the @code{hsearch} and
+ @code{drand48} families of functions, @code{fmtmsg} and several of the
+ mathematical functions.
+ 
+-@node XPG, , SVID, Standards and Portability
++@node XPG, Linux Kernel, SVID, Standards and Portability
+ @subsection XPG (The X/Open Portability Guide)
+ 
+ The X/Open Portability Guide, published by the X/Open Company, Ltd., is
+@@ -960,6 +961,20 @@ fulfilling the XPG standard with the Unix extensions is a
+ precondition for getting the Unix brand chances are good that the
+ functionality is available on commercial systems.
+ 
++@node Linux Kernel, , XPG, Standards and Portability
++@subsection Linux (The Linux Kernel)
++
++@Theglibc{} includes by reference the Linux man-pages
++@value{man_pages_version} documentation to document the listed
++syscalls for the Linux kernel. For reference purposes only the latest
++@uref{https://www.kernel.org/doc/man-pages/,Linux man-pages Project}
++documentation can be accessed from the
++@uref{https://www.kernel.org,Linux kernel} website.  Where the syscall
++has more specific documentation in this manual that more specific
++documentation is considered authoritative.
++
++Additional details on the Linux system call interface can be found in
++@xref{System Calls}.
+ 
+ @node Using the Library, Roadmap to the Manual, Standards and Portability, Introduction
+ @section Using the Library
+diff --git a/manual/llio.texi b/manual/llio.texi
+index 78c7c79913..6f0a48609b 100644
+--- a/manual/llio.texi
++++ b/manual/llio.texi
+@@ -65,6 +65,7 @@ directly.)
+ * Interrupt Input::                     Getting an asynchronous signal when
+                                          input arrives.
+ * IOCTLs::                              Generic I/O Control operations.
++* Other Low-Level I/O APIs::            Other low-level-I/O-related functions.
+ @end menu
+ 
+ 
+@@ -2324,6 +2325,8 @@ file descriptor, or until the timeout period expires.
+ There is another example showing the use of @code{select} to multiplex
+ input from multiple sockets in @ref{Server Example}.
+ 
++For an alternate interface to this functionality, see @code{poll}
++(@pxref{Other Low-Level I/O APIs}).
+ 
+ @node Synchronizing I/O
+ @section Synchronizing I/O operations
+@@ -3407,7 +3410,9 @@ require additional arguments to be supplied.  These additional arguments
+ and the return value and error conditions are given in the detailed
+ descriptions of the individual commands.
+ 
+-Briefly, here is a list of what the various commands are.
++Briefly, here is a list of what the various commands are.  For an
++exhaustive list of kernel-specific options, please see @xref{System
++Calls}.
+ 
+ @vtable @code
+ @item F_DUPFD
+@@ -4743,5 +4748,28 @@ Most IOCTLs are OS-specific and/or only used in special system utilities,
+ and are thus beyond the scope of this document.  For an example of the use
+ of an IOCTL, see @ref{Out-of-Band Data}.
+ 
+-@c FIXME this is undocumented:
+-@c dup3
++@node Other Low-Level I/O APIs
++@section Other low-level-I/O-related functions
++
++@deftp {Data Type} {struct pollfd}
++@standards{POSIX.1,poll.h}
++@end deftp
++
++@deftp {Data Type} {struct epoll_event}
++@standards{Linux,sys/epoll.h}
++@end deftp
++
++@deftypefun int poll (struct pollfd *@var{fds}, nfds_t @var{nfds}, int @var{timeout})
++
++@manpagefunctionstub{poll,2}
++@end deftypefun
++
++@deftypefun int epoll_create(int @var{size})
++
++@manpagefunctionstub{epoll_create,2}
++@end deftypefun
++
++@deftypefun int epoll_wait(int @var{epfd}, struct epoll_event *@var{events}, int @var{maxevents}, int @var{timeout})
++
++@manpagefunctionstub{epoll_wait,2}
++@end deftypefun
+diff --git a/manual/macros.texi b/manual/macros.texi
+index 4a2e22f473..579da3fb81 100644
+--- a/manual/macros.texi
++++ b/manual/macros.texi
+@@ -282,4 +282,11 @@ cwd\comments\
+ @macro standardsx {element, standard, header}
+ @end macro
+ 
++@macro manpagefunctionstub {func,sec}
++This documentation is a stub.  For additional information on this
++function, consult the manual page
++@url{https://man7.org/linux/man-pages/man\sec\/\func\.\sec\.html}.
++@xref{Linux Kernel}.
++@end macro
++
+ @end ifclear
+diff --git a/manual/socket.texi b/manual/socket.texi
+index f0e35d9e13..8708cbb07c 100644
+--- a/manual/socket.texi
++++ b/manual/socket.texi
+@@ -41,6 +41,7 @@ aren't documented either so far.
+ 			   is to make it work with Inetd.
+ * Socket Options::	Miscellaneous low-level socket options.
+ * Networks Database::   Accessing the database of network names.
++* Other Socket APIs::   Other socket-related functions.
+ @end menu
+ 
+ @node Socket Concepts
+@@ -3134,38 +3135,8 @@ You can use plain @code{recv} (@pxref{Receiving Data}) instead of
+ treat all possible senders alike).  Even @code{read} can be used if
+ you don't want to specify @var{flags} (@pxref{I/O Primitives}).
+ 
+-@ignore
+-@c sendmsg and recvmsg are like readv and writev in that they
+-@c use a series of buffers.  It's not clear this is worth
+-@c supporting or that we support them.
+-@c !!! they can do more; it is hairy
+-
+-@deftp {Data Type} {struct msghdr}
+-@standards{BSD, sys/socket.h}
+-@end deftp
+-
+-@deftypefun ssize_t sendmsg (int @var{socket}, const struct msghdr *@var{message}, int @var{flags})
+-@standards{BSD, sys/socket.h}
+-@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+-
+-This function is defined as a cancellation point in multi-threaded
+-programs, so one has to be prepared for this and make sure that
+-allocated resources (like memory, files descriptors, semaphores or
+-whatever) are freed even if the thread is cancel.
+-@c @xref{pthread_cleanup_push}, for a method how to do this.
+-@end deftypefun
+-
+-@deftypefun ssize_t recvmsg (int @var{socket}, struct msghdr *@var{message}, int @var{flags})
+-@standards{BSD, sys/socket.h}
+-@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+-
+-This function is defined as a cancellation point in multi-threaded
+-programs, so one has to be prepared for this and make sure that
+-allocated resources (like memory, files descriptors, semaphores or
+-whatever) are freed even if the thread is canceled.
+-@c @xref{pthread_cleanup_push}, for a method how to do this.
+-@end deftypefun
+-@end ignore
++If you need more flexibility and/or control over sending and receiving
++packets, see @code{sendmsg} and @code{recvmsg} (@pxref{Other Socket APIs}).
+ 
+ @node Datagram Example
+ @subsection Datagram Socket Example
+@@ -3664,3 +3635,20 @@ returns a null pointer if there are no more entries.
+ @c  libc_lock_unlock @aculock
+ This function closes the networks database.
+ @end deftypefun
++
++@node Other Socket APIs
++@section Other Socket APIs
++
++@deftp {Data Type} {struct msghdr}
++@standards{BSD, sys/socket.h}
++@end deftp
++
++@deftypefun ssize_t sendmsg (int @var{socket}, const struct msghdr *@var{message}, int @var{flags})
++
++@manpagefunctionstub{sendmsg,2}
++@end deftypefun
++
++@deftypefun ssize_t recvmsg (int @var{socket}, struct msghdr *@var{message}, int @var{flags})
++
++@manpagefunctionstub{recvmsg,2}
++@end deftypefun
+diff --git a/manual/startup.texi b/manual/startup.texi
+index 224dd98c1e..747beed4d9 100644
+--- a/manual/startup.texi
++++ b/manual/startup.texi
+@@ -689,7 +689,25 @@ you don't need to know about it because you can just use @theglibc{}'s
+ @code{chmod} function.
+ 
+ @cindex kernel call
+-System calls are sometimes called kernel calls.
++System calls are sometimes called syscalls or kernel calls, and this
++interface is mostly a purely mechanical translation from the kernel's
++ABI to the C ABI. For the set of syscalls where we do not guarantee
++POSIX Thread cancellation the wrappers only organize the incoming
++arguments from the C calling convention to the calling convention of
++the target kernel. For the set of syscalls where we provided POSIX
++Thread cancellation the wrappers set some internal state in the
++library to support cancellation, but this does not impact the
++behaviour of the syscall provided by the kernel.
++
++In some cases, if @theglibc{} detects that a system call has been
++superseded by a more capable one, the wrapper may map the old call to
++the new one.  For example, @code{dup2} is implemented via @code{dup3}
++by passing an additional empty flags argument, and @code{open} calls
++@code{openat} passing the additional @code{AT_FDCWD}.  Sometimes even
++more is done, such as converting between 32-bit and 64-bit time
++values.  In general, though, such processing is only to make the
++system call better match the C ABI, rather than change its
++functionality.
+ 
+ However, there are times when you want to make a system call explicitly,
+ and for that, @theglibc{} provides the @code{syscall} function.
+@@ -711,6 +729,8 @@ we won't describe it here either because anyone who is coding
+ library source code as a specification of the interface between them
+ anyway.
+ 
++@code{syscall} does not provide cancellation logic, even if the system
++call you're calling is listed as cancellable above.
+ 
+ @code{syscall} is declared in @file{unistd.h}.
+ 
diff --git a/SOURCES/glibc-RHEL-25531-1.patch b/SOURCES/glibc-RHEL-25531-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..db0260f2bee00614ac66592f8e8561416f7c85f3
--- /dev/null
+++ b/SOURCES/glibc-RHEL-25531-1.patch
@@ -0,0 +1,188 @@
+From a4c3f5f46e850c977cda81c251036475aab8313c Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Thu, 23 Nov 2023 14:29:14 -0300
+Subject: [PATCH] elf: Add a way to check if tunable is set (BZ 27069)
+Content-type: text/plain; charset=UTF-8
+
+The patch adds two new macros, TUNABLE_GET_DEFAULT and TUNABLE_IS_INITIALIZED,
+here the former get the default value with a signature similar to
+TUNABLE_GET, while the later returns whether the tunable was set by
+the environment variable.
+
+Checked on x86_64-linux-gnu.
+Reviewed-by: DJ Delorie <dj@redhat.com>
+Tested-by: Zhangfei Gao <zhangfei.gao@linaro.org>
+
+Conflicts:
+	elf/Versions
+	(removed to preserve ABI)
+	elf/dl-tunable-types.h
+	(line numbers)
+	scripts/gen-tunables.awk
+	(account for missing TUNABLE_SECLEVEL patch)
+
+---
+ elf/dl-tunable-types.h   |  1 +
+ elf/dl-tunables.c        | 40 ++++++++++++++++++++++++++++++++++++++++
+ elf/dl-tunables.h        | 28 ++++++++++++++++++++++++++++
+ elf/dl-tunables.list     |  1 +
+ scripts/gen-tunables.awk |  4 ++--
+ 6 files changed, 73 insertions(+), 2 deletions(-)
+
+diff -rup a/elf/dl-tunable-types.h b/elf/dl-tunable-types.h
+--- a/elf/dl-tunable-types.h	2021-08-01 21:33:43.000000000 -0400
++++ b/elf/dl-tunable-types.h	2024-03-26 18:23:22.211504813 -0400
+@@ -61,6 +61,7 @@ struct _tunable
+ {
+   const char name[TUNABLE_NAME_MAX];	/* Internal name of the tunable.  */
+   tunable_type_t type;			/* Data type of the tunable.  */
++  const tunable_val_t def;		/* The value.  */
+   tunable_val_t val;			/* The value.  */
+   bool initialized;			/* Flag to indicate that the tunable is
+ 					   initialized.  */
+diff -rup a/elf/dl-tunables.c b/elf/dl-tunables.c
+--- a/elf/dl-tunables.c	2024-03-26 18:21:10.090681748 -0400
++++ b/elf/dl-tunables.c	2024-03-26 18:23:22.214504923 -0400
+@@ -152,6 +152,13 @@ tunable_initialize (tunable_t *cur, cons
+   do_tunable_update_val (cur, &val, NULL, NULL);
+ }
+ 
++bool
++__tunable_is_initialized (tunable_id_t id)
++{
++  return tunable_list[id].initialized;
++}
++rtld_hidden_def (__tunable_is_initialized)
++
+ void
+ __tunable_set_val (tunable_id_t id, tunable_val_t *valp, tunable_num_t *minp,
+ 		   tunable_num_t *maxp)
+@@ -399,6 +406,39 @@ __tunables_print (void)
+     }
+ }
+ 
++void
++__tunable_get_default (tunable_id_t id, void *valp)
++{
++  tunable_t *cur = &tunable_list[id];
++
++  switch (cur->type.type_code)
++    {
++    case TUNABLE_TYPE_UINT_64:
++	{
++	  *((uint64_t *) valp) = (uint64_t) cur->def.numval;
++	  break;
++	}
++    case TUNABLE_TYPE_INT_32:
++	{
++	  *((int32_t *) valp) = (int32_t) cur->def.numval;
++	  break;
++	}
++    case TUNABLE_TYPE_SIZE_T:
++	{
++	  *((size_t *) valp) = (size_t) cur->def.numval;
++	  break;
++	}
++    case TUNABLE_TYPE_STRING:
++	{
++	  *((const char **)valp) = cur->def.strval;
++	  break;
++	}
++    default:
++      __builtin_unreachable ();
++    }
++}
++rtld_hidden_def (__tunable_get_default)
++
+ /* Set the tunable value.  This is called by the module that the tunable exists
+    in. */
+ void
+diff -rup a/elf/dl-tunables.h b/elf/dl-tunables.h
+--- a/elf/dl-tunables.h	2021-08-01 21:33:43.000000000 -0400
++++ b/elf/dl-tunables.h	2024-03-26 18:23:22.217505032 -0400
+@@ -53,18 +53,26 @@ typedef void (*tunable_callback_t) (tuna
+ 
+ extern void __tunables_init (char **);
+ extern void __tunables_print (void);
++extern bool __tunable_is_initialized (tunable_id_t);
+ extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
+ extern void __tunable_set_val (tunable_id_t, tunable_val_t *, tunable_num_t *,
+ 			       tunable_num_t *);
++extern void __tunable_get_default (tunable_id_t id, void *valp);
+ rtld_hidden_proto (__tunables_init)
+ rtld_hidden_proto (__tunables_print)
++rtld_hidden_proto (__tunable_is_initialized)
+ rtld_hidden_proto (__tunable_get_val)
+ rtld_hidden_proto (__tunable_set_val)
++rtld_hidden_proto (__tunable_get_default)
+ 
+ /* Define TUNABLE_GET and TUNABLE_SET in short form if TOP_NAMESPACE and
+    TUNABLE_NAMESPACE are defined.  This is useful shorthand to get and set
+    tunables within a module.  */
+ #if defined TOP_NAMESPACE && defined TUNABLE_NAMESPACE
++# define TUNABLE_IS_INITIALIZED(__id) \
++  TUNABLE_IS_INITIALIZED_FULL(TOP_NAMESPACE, TUNABLE_NAMESPACE, __id)
++# define TUNABLE_GET_DEFAULT(__id, __type) \
++  TUNABLE_GET_DEFAULT_FULL(TOP_NAMESPACE, TUNABLE_NAMESPACE,__id, __type)
+ # define TUNABLE_GET(__id, __type, __cb) \
+   TUNABLE_GET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __cb)
+ # define TUNABLE_SET(__id, __val) \
+@@ -73,6 +81,10 @@ rtld_hidden_proto (__tunable_set_val)
+   TUNABLE_SET_WITH_BOUNDS_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, \
+ 				__val, __min, __max)
+ #else
++# define TUNABLE_IS_INITIALIZED(__top, __ns, __id) \
++  TUNABLE_IS_INITIALIZED_FULL(__top, __ns, __id)
++# define TUNABLE_GET_DEFAULT(__top, __ns, __type) \
++  TUNABLE_GET_DEFAULT_FULL(__top, __ns, __id, __type)
+ # define TUNABLE_GET(__top, __ns, __id, __type, __cb) \
+   TUNABLE_GET_FULL (__top, __ns, __id, __type, __cb)
+ # define TUNABLE_SET(__top, __ns, __id, __val) \
+@@ -81,6 +93,22 @@ rtld_hidden_proto (__tunable_set_val)
+   TUNABLE_SET_WITH_BOUNDS_FULL (__top, __ns, __id, __val, __min, __max)
+ #endif
+ 
++/* Return whether the tunable was initialized by the environment variable.  */
++#define TUNABLE_IS_INITIALIZED_FULL(__top, __ns, __id) \
++({									      \
++  tunable_id_t id = TUNABLE_ENUM_NAME (__top, __ns, __id);		      \
++  __tunable_is_initialized (id);					      \
++})
++
++/* Return the default value of the tunable.  */
++#define TUNABLE_GET_DEFAULT_FULL(__top, __ns, __id, __type) \
++({									      \
++  tunable_id_t id = TUNABLE_ENUM_NAME (__top, __ns, __id);		      \
++  __type __ret;								      \
++  __tunable_get_default (id, &__ret);					      \
++  __ret;								      \
++})
++
+ /* Get and return a tunable value.  If the tunable was set externally and __CB
+    is defined then call __CB before returning the value.  */
+ # define TUNABLE_GET_FULL(__top, __ns, __id, __type, __cb) \
+diff -rup a/elf/dl-tunables.list b/elf/dl-tunables.list
+--- a/elf/dl-tunables.list	2024-03-26 18:21:09.664666196 -0400
++++ b/elf/dl-tunables.list	2024-03-26 18:23:22.220505142 -0400
+@@ -20,6 +20,7 @@
+ # type: Defaults to STRING
+ # minval: Optional minimum acceptable value
+ # maxval: Optional maximum acceptable value
++# default: Optional default value (if not specified it will be 0 or "")
+ # env_alias: An alias environment variable
+ # security_level: Specify security level of the tunable for AT_SECURE binaries.
+ # 		  Valid values are:
+diff -rup a/scripts/gen-tunables.awk b/scripts/gen-tunables.awk
+--- a/scripts/gen-tunables.awk	2024-03-26 18:21:09.523661049 -0400
++++ b/scripts/gen-tunables.awk	2024-03-26 18:34:45.385462341 -0400
+@@ -236,8 +236,8 @@ END {
+     n = indices[2];
+     m = indices[3];
+     printf ("  {TUNABLE_NAME_S(%s, %s, %s)", t, n, m)
+-    printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, NULL, TUNABLE_SECLEVEL_%s, %s},\n",
+-	    types[t,n,m], minvals[t,n,m], maxvals[t,n,m],
++    printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, {%s}, NULL, TUNABLE_SECLEVEL_%s, %s},\n",
++	    types[t,n,m], minvals[t,n,m], maxvals[t,n,m],default_val[t,n,m],
+ 	    default_val[t,n,m], security_level[t,n,m], env_alias[t,n,m]);
+   }
+   print "};"
diff --git a/SOURCES/glibc-RHEL-25531-2.patch b/SOURCES/glibc-RHEL-25531-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..8b903654234cceb18eb992e7ec33fab8a7e6777e
--- /dev/null
+++ b/SOURCES/glibc-RHEL-25531-2.patch
@@ -0,0 +1,155 @@
+From 0c0d39fe4aeb0f69b26e76337c5dfd5530d5d44e Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Thu, 8 Feb 2024 10:08:38 -0300
+Subject: [PATCH] x86: Fix Zen3/Zen4 ERMS selection (BZ 30994)
+Content-type: text/plain; charset=UTF-8
+
+The REP MOVSB usage on memcpy/memmove does not show much performance
+improvement on Zen3/Zen4 cores compared to the vectorized loops.  Also,
+as from BZ 30994, if the source is aligned and the destination is not
+the performance can be 20x slower.
+
+The performance difference is noticeable with small buffer sizes, closer
+to the lower bounds limits when memcpy/memmove starts to use ERMS.  The
+performance of REP MOVSB is similar to vectorized instruction on the
+size limit (the L2 cache).  Also, there is no drawback to multiple cores
+sharing the cache.
+
+Checked on x86_64-linux-gnu on Zen3.
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+
+Conflicts:
+	sysdeps/x86/dl-cacheinfo.h
+	(tweaked for changed context)
+
+---
+ sysdeps/x86/dl-cacheinfo.h | 38 ++++++++++++++++++--------------------
+ 1 file changed, 18 insertions(+), 20 deletions(-)
+
+diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
+index d5101615e3..f34d12846c 100644
+--- a/sysdeps/x86/dl-cacheinfo.h
++++ b/sysdeps/x86/dl-cacheinfo.h
+@@ -791,7 +791,6 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
+   long int data = -1;
+   long int shared = -1;
+   long int shared_per_thread = -1;
+-  long int core = -1;
+   unsigned int threads = 0;
+   unsigned long int level1_icache_size = -1;
+   unsigned long int level1_icache_linesize = -1;
+@@ -809,7 +808,6 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
+   if (cpu_features->basic.kind == arch_kind_intel)
+     {
+       data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features);
+-      core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features);
+       shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, cpu_features);
+       shared_per_thread = shared;
+ 
+@@ -822,7 +820,8 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
+ 	= handle_intel (_SC_LEVEL1_DCACHE_ASSOC, cpu_features);
+       level1_dcache_linesize
+ 	= handle_intel (_SC_LEVEL1_DCACHE_LINESIZE, cpu_features);
+-      level2_cache_size = core;
++      level2_cache_size
++	= handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features);
+       level2_cache_assoc
+ 	= handle_intel (_SC_LEVEL2_CACHE_ASSOC, cpu_features);
+       level2_cache_linesize
+@@ -835,12 +834,12 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
+       level4_cache_size
+ 	= handle_intel (_SC_LEVEL4_CACHE_SIZE, cpu_features);
+ 
+-      get_common_cache_info (&shared, &shared_per_thread, &threads, core);
++      get_common_cache_info (&shared, &shared_per_thread, &threads,
++			     level2_cache_size);
+     }
+   else if (cpu_features->basic.kind == arch_kind_zhaoxin)
+     {
+       data = handle_zhaoxin (_SC_LEVEL1_DCACHE_SIZE);
+-      core = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE);
+       shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE);
+       shared_per_thread = shared;
+ 
+@@ -849,19 +848,19 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
+       level1_dcache_size = data;
+       level1_dcache_assoc = handle_zhaoxin (_SC_LEVEL1_DCACHE_ASSOC);
+       level1_dcache_linesize = handle_zhaoxin (_SC_LEVEL1_DCACHE_LINESIZE);
+-      level2_cache_size = core;
++      level2_cache_size = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE);
+       level2_cache_assoc = handle_zhaoxin (_SC_LEVEL2_CACHE_ASSOC);
+       level2_cache_linesize = handle_zhaoxin (_SC_LEVEL2_CACHE_LINESIZE);
+       level3_cache_size = shared;
+       level3_cache_assoc = handle_zhaoxin (_SC_LEVEL3_CACHE_ASSOC);
+       level3_cache_linesize = handle_zhaoxin (_SC_LEVEL3_CACHE_LINESIZE);
+ 
+-      get_common_cache_info (&shared, &shared_per_thread, &threads, core);
++      get_common_cache_info (&shared, &shared_per_thread, &threads,
++			     level2_cache_size);
+     }
+   else if (cpu_features->basic.kind == arch_kind_amd)
+     {
+       data = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
+-      core = handle_amd (_SC_LEVEL2_CACHE_SIZE);
+       shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
+ 
+       level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE);
+@@ -869,7 +868,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
+       level1_dcache_size = data;
+       level1_dcache_assoc = handle_amd (_SC_LEVEL1_DCACHE_ASSOC);
+       level1_dcache_linesize = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE);
+-      level2_cache_size = core;
++      level2_cache_size = handle_amd (_SC_LEVEL2_CACHE_SIZE);;
+       level2_cache_assoc = handle_amd (_SC_LEVEL2_CACHE_ASSOC);
+       level2_cache_linesize = handle_amd (_SC_LEVEL2_CACHE_LINESIZE);
+       level3_cache_size = shared;
+@@ -880,12 +879,12 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
+       if (shared <= 0)
+         {
+            /* No shared L3 cache.  All we have is the L2 cache.  */
+-           shared = core;
++           shared = level2_cache_size;
+         }
+       else if (cpu_features->basic.family < 0x17)
+         {
+            /* Account for exclusive L2 and L3 caches.  */
+-           shared += core;
++           shared += level2_cache_size;
+         }
+ 
+       shared_per_thread = shared;
+@@ -987,6 +986,12 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
+   if (CPU_FEATURE_USABLE_P (cpu_features, FSRM))
+     rep_movsb_threshold = 2112;
+ 
++   /* For AMD CPUs that support ERMS (Zen3+), REP MOVSB is in a lot of
++      cases slower than the vectorized path (and for some alignments,
++      it is really slow, check BZ #30994).  */
++  if (cpu_features->basic.kind == arch_kind_amd)
++    rep_movsb_threshold = non_temporal_threshold;
++
+   /* The default threshold to use Enhanced REP STOSB.  */
+   unsigned long int rep_stosb_threshold = 2048;
+ 
+@@ -1028,15 +1033,8 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
+#endif
+ 
+   unsigned long int rep_movsb_stop_threshold;
+-  /* ERMS feature is implemented from AMD Zen3 architecture and it is
+-     performing poorly for data above L2 cache size. Henceforth, adding
+-     an upper bound threshold parameter to limit the usage of Enhanced
+-     REP MOVSB operations and setting its value to L2 cache size.  */
+-  if (cpu_features->basic.kind == arch_kind_amd)
+-    rep_movsb_stop_threshold = core;
+   /* Setting the upper bound of ERMS to the computed value of
+-     non-temporal threshold for architectures other than AMD.  */
+-  else
+-    rep_movsb_stop_threshold = non_temporal_threshold;
++     non-temporal threshold for all architectures.  */
++  rep_movsb_stop_threshold = non_temporal_threshold;
+ 
+   cpu_features->data_cache_size = data;
+   cpu_features->shared_cache_size = shared;
+-- 
+2.39.3
+
diff --git a/SOURCES/glibc-RHEL-25531-3.patch b/SOURCES/glibc-RHEL-25531-3.patch
new file mode 100644
index 0000000000000000000000000000000000000000..5d404f7ea581ad786e8a8c958f556cc8797d7c69
--- /dev/null
+++ b/SOURCES/glibc-RHEL-25531-3.patch
@@ -0,0 +1,34 @@
+From 272708884cb750f12f5c74a00e6620c19dc6d567 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Thu, 8 Feb 2024 10:08:39 -0300
+Subject: [PATCH] x86: Do not prefer ERMS for memset on Zen3+
+Content-type: text/plain; charset=UTF-8
+
+For AMD Zen3+ architecture, the performance of the vectorized loop is
+slightly better than ERMS.
+
+Checked on x86_64-linux-gnu on Zen3.
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+---
+ sysdeps/x86/dl-cacheinfo.h | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
+index f34d12846c..5a98f70364 100644
+--- a/sysdeps/x86/dl-cacheinfo.h
++++ b/sysdeps/x86/dl-cacheinfo.h
+@@ -1021,6 +1021,11 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
+      minimum value is fixed.  */
+   rep_stosb_threshold = TUNABLE_GET (x86_rep_stosb_threshold,
+ 				     long int, NULL);
++  if (cpu_features->basic.kind == arch_kind_amd
++      && !TUNABLE_IS_INITIALIZED (x86_rep_stosb_threshold))
++    /* For AMD Zen3+ architecture, the performance of the vectorized loop is
++       slightly better than ERMS.  */
++    rep_stosb_threshold = SIZE_MAX;
+ 
+   TUNABLE_SET_WITH_BOUNDS (x86_data_cache_size, data, 0, SIZE_MAX);
+   TUNABLE_SET_WITH_BOUNDS (x86_shared_cache_size, shared, 0, SIZE_MAX);
+-- 
+2.39.3
+
diff --git a/SOURCES/glibc-RHEL-25531-4.patch b/SOURCES/glibc-RHEL-25531-4.patch
new file mode 100644
index 0000000000000000000000000000000000000000..089b29cdc9dcda6bfbb5362ac81437f5edaa8f9e
--- /dev/null
+++ b/SOURCES/glibc-RHEL-25531-4.patch
@@ -0,0 +1,29 @@
+From 491e55beab7457ed310a4a47496f4a333c5d1032 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Thu, 8 Feb 2024 10:08:40 -0300
+Subject: [PATCH] x86: Expand the comment on when REP STOSB is used on memset
+Content-type: text/plain; charset=UTF-8
+
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+---
+ sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
+index 9984c3ca0f..97839a2248 100644
+--- a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
++++ b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
+@@ -21,7 +21,9 @@
+    2. If size is less than VEC, use integer register stores.
+    3. If size is from VEC_SIZE to 2 * VEC_SIZE, use 2 VEC stores.
+    4. If size is from 2 * VEC_SIZE to 4 * VEC_SIZE, use 4 VEC stores.
+-   5. If size is more to 4 * VEC_SIZE, align to 4 * VEC_SIZE with
++   5. On machines ERMS feature, if size is greater or equal than
++      __x86_rep_stosb_threshold then REP STOSB will be used.
++   6. If size is more to 4 * VEC_SIZE, align to 4 * VEC_SIZE with
+       4 VEC stores and store 4 * VEC at a time until done.  */
+ 
+ #include <sysdep.h>
+-- 
+2.39.3
+
diff --git a/SOURCES/glibc-RHEL-30823.patch b/SOURCES/glibc-RHEL-30823.patch
new file mode 100644
index 0000000000000000000000000000000000000000..96c256fd5f62fc0c52242f8feef0bfddce0281ca
--- /dev/null
+++ b/SOURCES/glibc-RHEL-30823.patch
@@ -0,0 +1,205 @@
+From dce754b1553b86fc6352636f1fa490a85b7cf0ff Mon Sep 17 00:00:00 2001
+From: DJ Delorie <dj@redhat.com>
+Date: Fri, 10 May 2024 14:52:09 -0400
+Subject: Update mmap() flags and errors lists
+
+Extend the list of MAP_* macros to include all macros available
+to the average program (gcc -E -dM | grep MAP_*)
+
+Extend the list of errno codes.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+diff --git a/manual/llio.texi b/manual/llio.texi
+index fe1807a849..78c7c79913 100644
+--- a/manual/llio.texi
++++ b/manual/llio.texi
+@@ -1573,10 +1573,15 @@ permitted.  They include @code{PROT_READ}, @code{PROT_WRITE}, and
+ of address space for future use.  The @code{mprotect} function can be
+ used to change the protection flags.  @xref{Memory Protection}.
+ 
+-@var{flags} contains flags that control the nature of the map.
+-One of @code{MAP_SHARED} or @code{MAP_PRIVATE} must be specified.
++The @var{flags} parameter contains flags that control the nature of
++the map.  One of @code{MAP_SHARED}, @code{MAP_SHARED_VALIDATE}, or
++@code{MAP_PRIVATE} must be specified.  Additional flags may be bitwise
++OR'd to further define the mapping.
+ 
+-They include:
++Note that, aside from @code{MAP_PRIVATE} and @code{MAP_SHARED}, not
++all flags are supported on all versions of all operating systems.
++Consult the kernel-specific documentation for details.  The flags
++include:
+ 
+ @vtable @code
+ @item MAP_PRIVATE
+@@ -1598,9 +1603,19 @@ Note that actual writing may take place at any time.  You need to use
+ @code{msync}, described below, if it is important that other processes
+ using conventional I/O get a consistent view of the file.
+ 
++@item MAP_SHARED_VALIDATE
++Similar to @code{MAP_SHARED} except that additional flags will be
++validated by the kernel, and the call will fail if an unrecognized
++flag is provided.  With @code{MAP_SHARED} using a flag on a kernel
++that doesn't support it causes the flag to be ignored.
++@code{MAP_SHARED_VALIDATE} should be used when the behavior of all
++flags is required.
++
+ @item MAP_FIXED
+ This forces the system to use the exact mapping address specified in
+-@var{address} and fail if it can't.
++@var{address} and fail if it can't.  Note that if the new mapping
++would overlap an existing mapping, the overlapping portion of the
++existing map is unmapped.
+ 
+ @c One of these is official - the other is obviously an obsolete synonym
+ @c Which is which?
+@@ -1641,10 +1656,73 @@ The @code{MAP_HUGETLB} flag is specific to Linux.
+ @c There is a mechanism to select different hugepage sizes; see
+ @c include/uapi/asm-generic/hugetlb_encode.h in the kernel sources.
+ 
+-@c Linux has some other MAP_ options, which I have not discussed here.
+-@c MAP_DENYWRITE, MAP_EXECUTABLE and MAP_GROWSDOWN don't seem applicable to
+-@c user programs (and I don't understand the last two).  MAP_LOCKED does
+-@c not appear to be implemented.
++@item MAP_32BIT
++Require addresses that can be accessed with a signed 32 bit pointer,
++i.e., within the first 2 GiB.  Ignored if MAP_FIXED is specified.
++
++@item MAP_DENYWRITE
++@itemx MAP_EXECUTABLE
++@itemx MAP_FILE
++
++Provided for compatibility.  Ignored by the Linux kernel.
++
++@item MAP_FIXED_NOREPLACE
++Similar to @code{MAP_FIXED} except the call will fail with
++@code{EEXIST} if the new mapping would overwrite an existing mapping.
++To test for support for this flag, specify MAP_FIXED_NOREPLACE without
++MAP_FIXED, and (if the call was successful) check the actual address
++returned.  If it does not match the address passed, then this flag is
++not supported.
++
++@item MAP_GROWSDOWN
++This flag is used to make stacks, and is typically only needed inside
++the program loader to set up the main stack for the running process.
++The mapping is created according to the other flags, except an
++additional page just prior to the mapping is marked as a ``guard
++page''.  If a write is attempted inside this guard page, that page is
++mapped, the mapping is extended, and a new guard page is created.
++Thus, the mapping continues to grow towards lower addresses until it
++encounters some other mapping.
++
++Note that accessing memory beyond the guard page will not trigger this
++feature.  In gcc, use @code{-fstack-clash-protection} to ensure the
++guard page is always touched.
++
++@item MAP_LOCKED
++A hint that requests that mapped pages are locked in memory (i.e. not
++paged out).  Note that this is a request and not a requirement; use
++@code{mlock} if locking is required.
++
++@item MAP_POPULATE
++@itemx MAP_NONBLOCK
++@code{MAP_POPULATE} is a hint that requests that the kernel read-ahead
++a file-backed mapping, causing pages to be mapped before they're
++needed.  @code{MAP_NONBLOCK} is a hint that requests that the kernel
++@emph{not} attempt such except for pages are already in memory.  Note
++that neither of these hints affects future paging activity, use
++@code{mlock} if such needs to be controlled.
++
++@item MAP_NORESERVE
++Asks the kernel to not reserve physical backing (i.e. space in a swap
++device) for a mapping.  This would be useful for, for example, a very
++large but sparsely used mapping which need not be limited in total
++length by available RAM, but with very few mapped pages.  Note that
++writes to such a mapping may cause a @code{SIGSEGV} if the system is
++unable to map a page due to lack of resources.
++
++On Linux, this flag's behavior may be overwridden by
++@file{/proc/sys/vm/overcommit_memory} as documented in the proc(5) man
++page.
++
++@item MAP_STACK
++Ensures that the resulting mapping is suitable for use as a program
++stack.  For example, the use of huge pages might be precluded.
++
++@item MAP_SYNC
++This is a special flag for DAX devices, which tells the kernel to
++write dirty metadata out whenever dirty data is written out.  Unlike
++most other flags, this one will fail unless @code{MAP_SHARED_VALIDATE}
++is also given.
+ 
+ @end vtable
+ 
+@@ -1655,6 +1733,24 @@ Possible errors include:
+ 
+ @table @code
+ 
++@item EACCES
++
++@var{filedes} was not open for the type of access specified in @var{protect}.
++
++@item EAGAIN
++
++The system has temporarily run out of resources.
++
++@item EBADF
++
++The @var{fd} passed is invalid, and a valid file descriptor is
++required (i.e. MAP_ANONYMOUS was not specified).
++
++@item EEXIST
++
++@code{MAP_FIXED_NOREPLACE} was specified and an existing mapping was
++found overlapping the requested address range.
++
+ @item EINVAL
+ 
+ Either @var{address} was unusable (because it is not a multiple of the
+@@ -1663,23 +1759,37 @@ applicable page size), or inconsistent @var{flags} were given.
+ If @code{MAP_HUGETLB} was specified, the file or system does not support
+ large page sizes.
+ 
+-@item EACCES
++@item ENODEV
+ 
+-@var{filedes} was not open for the type of access specified in @var{protect}.
++This file is of a type that doesn't support mapping, the process has
++exceeded its data space limit, or the map request would exceed the
++process's virtual address space.
+ 
+ @item ENOMEM
+ 
+-Either there is not enough memory for the operation, or the process is
+-out of address space.
+-
+-@item ENODEV
+-
+-This file is of a type that doesn't support mapping.
++There is not enough memory for the operation, the process is out of
++address space, or there are too many mappings.  On Linux, the maximum
++number of mappings can be controlled via
++@file{/proc/sys/vm/max_map_count} or, if your OS supports it, via
++the @code{vm.max_map_count} @code{sysctl} setting.
+ 
+ @item ENOEXEC
+ 
+ The file is on a filesystem that doesn't support mapping.
+ 
++@item EPERM
++
++@code{PROT_EXEC} was requested but the file is on a filesystem that
++was mounted with execution denied, a file seal prevented the mapping,
++or the caller set MAP_HUDETLB but does not have the required
++priviledges.
++
++@item EOVERFLOW
++
++Either the offset into the file plus the length of the mapping causes
++internal page counts to overflow, or the offset requested exceeds the
++length of the file.
++
+ @c On Linux, EAGAIN will appear if the file has a conflicting mandatory lock.
+ @c However mandatory locks are not discussed in this manual.
+ @c
diff --git a/SOURCES/glibc-RHEL-31805.patch b/SOURCES/glibc-RHEL-31805.patch
new file mode 100644
index 0000000000000000000000000000000000000000..0d7fa4ee88a3489c1c7981a755544da016797c15
--- /dev/null
+++ b/SOURCES/glibc-RHEL-31805.patch
@@ -0,0 +1,207 @@
+Author: Charles Fol <folcharles@gmail.com>
+Date:   Thu Mar 28 12:25:38 2024 -0300
+
+    iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence (CVE-2024-2961)
+
+    ISO-2022-CN-EXT uses escape sequences to indicate character set changes
+    (as specified by RFC 1922).  While the SOdesignation has the expected
+    bounds checks, neither SS2designation nor SS3designation have its;
+    allowing a write overflow of 1, 2, or 3 bytes with fixed values:
+    '$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'.
+
+    Checked on aarch64-linux-gnu.
+
+    Co-authored-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+    Tested-by: Carlos O'Donell <carlos@redhat.com>
+
+Conflicts:
+	iconvdata/Makefile
+	  (usual tests conflict)
+
+diff --git a/iconvdata/Makefile b/iconvdata/Makefile
+index d5507a048c6a6508..25bd004e7f92a994 100644
+--- a/iconvdata/Makefile
++++ b/iconvdata/Makefile
+@@ -75,7 +75,7 @@ ifeq (yes,$(build-shared))
+ tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
+ 	tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
+ 	bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
+-	bug-iconv13 bug-iconv14 bug-iconv15
++	bug-iconv13 bug-iconv14 bug-iconv15 tst-iconv-iso-2022-cn-ext
+ ifeq ($(have-thread-library),yes)
+ tests += bug-iconv3
+ endif
+@@ -330,6 +330,8 @@ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
+ 			  $(addprefix $(objpfx),$(modules.so))
+ $(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
+ 			  $(addprefix $(objpfx),$(modules.so))
++$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
++					$(addprefix $(objpfx),$(modules.so))
+ 
+ $(objpfx)iconv-test.out: run-iconv-test.sh \
+ 			 $(addprefix $(objpfx), $(gconv-modules)) \
+diff --git a/iconvdata/iso-2022-cn-ext.c b/iconvdata/iso-2022-cn-ext.c
+index 2aca91c021f21ba0..c1339fe933d9d1c4 100644
+--- a/iconvdata/iso-2022-cn-ext.c
++++ b/iconvdata/iso-2022-cn-ext.c
+@@ -575,6 +575,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
+ 	      {								      \
+ 		const char *escseq;					      \
+ 									      \
++		if (outptr + 4 > outend)				      \
++		  {							      \
++		    result = __GCONV_FULL_OUTPUT;			      \
++		    break;						      \
++		  }							      \
++									      \
+ 		assert (used == CNS11643_2_set); /* XXX */		      \
+ 		escseq = "*H";						      \
+ 		*outptr++ = ESC;					      \
+@@ -588,6 +594,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
+ 	      {								      \
+ 		const char *escseq;					      \
+ 									      \
++		if (outptr + 4 > outend)				      \
++		  {							      \
++		    result = __GCONV_FULL_OUTPUT;			      \
++		    break;						      \
++		  }							      \
++									      \
+ 		assert ((used >> 5) >= 3 && (used >> 5) <= 7);		      \
+ 		escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2;		      \
+ 		*outptr++ = ESC;					      \
+diff --git a/iconvdata/tst-iconv-iso-2022-cn-ext.c b/iconvdata/tst-iconv-iso-2022-cn-ext.c
+new file mode 100644
+index 0000000000000000..96a8765fd5369681
+--- /dev/null
++++ b/iconvdata/tst-iconv-iso-2022-cn-ext.c
+@@ -0,0 +1,128 @@
++/* Verify ISO-2022-CN-EXT does not write out of the bounds.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++#include <string.h>
++
++#include <errno.h>
++#include <iconv.h>
++#include <sys/mman.h>
++
++#include <support/xunistd.h>
++#include <support/check.h>
++#include <support/support.h>
++
++/* The test sets up a two memory page buffer with the second page marked
++   PROT_NONE to trigger a fault if the conversion writes beyond the exact
++   expected amount.  Then we carry out various conversions and precisely
++   place the start of the output buffer in order to trigger a SIGSEGV if the
++   process writes anywhere between 1 and page sized bytes more (only one
++   PROT_NONE page is setup as a canary) than expected.  These tests exercise
++   all three of the cases in ISO-2022-CN-EXT where the converter must switch
++   character sets and may run out of buffer space while doing the
++   operation.  */
++
++static int
++do_test (void)
++{
++  iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8");
++  TEST_VERIFY_EXIT (cd != (iconv_t) -1);
++
++  char *ntf;
++  size_t ntfsize;
++  char *outbufbase;
++  {
++    int pgz = getpagesize ();
++    TEST_VERIFY_EXIT (pgz > 0);
++    ntfsize = 2 * pgz;
++
++    ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE
++		 | MAP_ANONYMOUS, -1);
++    xmprotect (ntf + pgz, pgz, PROT_NONE);
++
++    outbufbase = ntf + pgz;
++  }
++
++  /* Check if SOdesignation escape sequence does not trigger an OOB write.  */
++  {
++    char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2";
++
++    for (int i = 0; i < 9; i++)
++      {
++	char *inp = inbuf;
++	size_t inleft = sizeof (inbuf) - 1;
++
++	char *outp = outbufbase - i;
++	size_t outleft = i;
++
++	TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
++			  == (size_t) -1);
++	TEST_COMPARE (errno, E2BIG);
++
++	TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
++      }
++  }
++
++  /* Same as before for SS2designation.  */
++  {
++    char inbuf[] = "ã´½ \xe3\xb4\xbd";
++
++    for (int i = 0; i < 14; i++)
++      {
++	char *inp = inbuf;
++	size_t inleft = sizeof (inbuf) - 1;
++
++	char *outp = outbufbase - i;
++	size_t outleft = i;
++
++	TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
++			  == (size_t) -1);
++	TEST_COMPARE (errno, E2BIG);
++
++	TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
++      }
++  }
++
++  /* Same as before for SS3designation.  */
++  {
++    char inbuf[] = "劄 \xe5\x8a\x84";
++
++    for (int i = 0; i < 14; i++)
++      {
++	char *inp = inbuf;
++	size_t inleft = sizeof (inbuf) - 1;
++
++	char *outp = outbufbase - i;
++	size_t outleft = i;
++
++	TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
++			  == (size_t) -1);
++	TEST_COMPARE (errno, E2BIG);
++
++	TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
++      }
++  }
++
++  TEST_VERIFY_EXIT (iconv_close (cd) != -1);
++
++  xmunmap (ntf, ntfsize);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-RHEL-32681-1.patch b/SOURCES/glibc-RHEL-32681-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c416a97980d6eff8a18f72d3ad1198c01fb80e10
--- /dev/null
+++ b/SOURCES/glibc-RHEL-32681-1.patch
@@ -0,0 +1,142 @@
+commit 3a83f79024cc023a74c3892a1673542e8e972485
+Author: Sergey Kolosov <skolosov@redhat.com>
+Date:   Wed Apr 10 17:58:05 2024 +0200
+
+    socket: Add new test for connect
+
+    This commit adds a simple bind/accept/connect test for an IPv4 TCP
+    connection to a local process via the loopback interface.
+
+    Reviewed-by: Arjun Shankar <arjun@redhat.com>
+
+diff -Nrup a/socket/Makefile b/socket/Makefile
+--- a/socket/Makefile	2024-05-19 21:52:59.775055152 -0400
++++ b/socket/Makefile	2024-05-19 22:05:27.717703460 -0400
+@@ -33,8 +33,9 @@ routines := accept bind connect getpeern
+ 
+ tests := \
+   tst-accept4 \
+-  tst-sockopt \
+   tst-cmsghdr \
++  tst-connect \
++  tst-sockopt \
+   # tests
+ 
+ tests-internal := \
+diff -Nrup a/socket/tst-connect.c b/socket/tst-connect.c
+--- a/socket/tst-connect.c	1969-12-31 19:00:00.000000000 -0500
++++ b/socket/tst-connect.c	2024-05-19 21:58:22.069058144 -0400
+@@ -0,0 +1,113 @@
++/* Test the connect function.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <arpa/inet.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <signal.h>
++#include <stdbool.h>
++#include <support/check.h>
++#include <support/xsocket.h>
++#include <support/xunistd.h>
++#include <sys/socket.h>
++#include <stdio.h>
++
++static struct sockaddr_in server_address;
++
++int
++open_socket_inet_tcp (void)
++{
++  int fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
++  if (fd < 0)
++    {
++      if (errno == EAFNOSUPPORT)
++        FAIL_UNSUPPORTED ("The host does not support IPv4");
++      else
++        FAIL_EXIT1 ("socket (AF_INET, SOCK_STREAM, IPPROTO_TCP): %m\n");
++    }
++  return fd;
++}
++
++static pid_t
++start_server (void)
++{
++  server_address.sin_family = AF_INET;
++  server_address.sin_port = 0;
++  server_address.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
++
++  int server_sock = open_socket_inet_tcp ();
++
++  xbind (server_sock, (struct sockaddr *) &server_address,
++         sizeof (server_address));
++
++  socklen_t sa_len = sizeof (server_address);
++  xgetsockname (server_sock, (struct sockaddr *) &server_address, &sa_len);
++  xlisten (server_sock, 5);
++
++  pid_t my_pid = xfork ();
++  if (my_pid > 0)
++    {
++      xclose (server_sock);
++      return my_pid;
++    }
++
++  struct sockaddr_in client_address;
++  socklen_t ca_len = sizeof (server_address);
++  int client_sock = xaccept (server_sock, (struct sockaddr *) &client_address,
++                             &ca_len);
++  printf ("socket accepted %d\n", client_sock);
++
++  _exit (0);
++}
++
++static int
++do_test (void)
++{
++  pid_t serv_pid;
++  struct sockaddr_in peer;
++  socklen_t peer_len;
++
++  serv_pid = start_server ();
++  int client_sock = open_socket_inet_tcp ();
++  xconnect (client_sock, (const struct sockaddr *) &server_address,
++            sizeof (server_address));
++
++  /* A second connect with same arguments should fail with EISCONN.  */
++  int result = connect (client_sock,
++                        (const struct sockaddr *) &server_address,
++                        sizeof (server_address));
++  if (result == 0 || errno != EISCONN)
++    FAIL_EXIT1 ("Second connect (%d), should fail with EISCONN: %m",
++                client_sock);
++
++  peer_len = sizeof (peer);
++  xgetpeername (client_sock, (struct sockaddr *) &peer, &peer_len);
++  TEST_COMPARE (peer_len, sizeof (peer));
++  TEST_COMPARE (peer.sin_port, server_address.sin_port);
++  TEST_COMPARE_BLOB (&peer.sin_addr, sizeof (peer.sin_addr),
++                     &server_address.sin_addr,
++                     sizeof (server_address.sin_addr));
++
++  int status;
++  xwaitpid (serv_pid, &status, 0);
++  TEST_COMPARE (status, 0);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-RHEL-32681-2.patch b/SOURCES/glibc-RHEL-32681-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1f669ff665d641ffbe6931792dca8d8eb63b24ff
--- /dev/null
+++ b/SOURCES/glibc-RHEL-32681-2.patch
@@ -0,0 +1,66 @@
+commit 6687a6e3f962759536a8019d31c68c1009ccd6eb
+Author: Sergey Kolosov <skolosov@redhat.com>
+Date:   Wed Apr 10 17:58:04 2024 +0200
+
+    libsupport: Add xgetpeername
+
+    The patch adds redirections for getpeername.
+
+    Reviewed-by: Arjun Shankar <arjun@redhat.com>
+
+diff -Nrup a/support/Makefile b/support/Makefile
+--- a/support/Makefile	2024-05-19 23:27:12.379362736 -0400
++++ b/support/Makefile	2024-05-19 23:29:28.668182089 -0400
+@@ -126,6 +126,7 @@ libsupport-routines = \
+   xfork \
+   xftruncate \
+   xgetline \
++  xgetpeername \
+   xgetsockname \
+   xlisten \
+   xlseek \
+diff -Nrup a/support/xgetpeername.c b/support/xgetpeername.c
+--- a/support/xgetpeername.c	1969-12-31 19:00:00.000000000 -0500
++++ b/support/xgetpeername.c	2024-05-19 23:30:31.852561947 -0400
+@@ -0,0 +1,30 @@
++/* getpeername with error checking.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <support/xsocket.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <support/check.h>
++
++void
++xgetpeername (int fd, struct sockaddr *sa, socklen_t *plen)
++{
++  if (getpeername (fd, sa, plen) != 0)
++    FAIL_EXIT1 ("getpeername (%d): %m", fd);
++}
+diff -Nrup a/support/xsocket.h b/support/xsocket.h
+--- a/support/xsocket.h	2021-08-01 21:33:43.000000000 -0400
++++ b/support/xsocket.h	2024-05-19 23:31:24.541878715 -0400
+@@ -26,6 +26,7 @@
+ int xsocket (int, int, int);
+ void xsetsockopt (int, int, int, const void *, socklen_t);
+ void xgetsockname (int, struct sockaddr *, socklen_t *);
++void xgetpeername (int, struct sockaddr *, socklen_t *);
+ void xconnect (int, const struct sockaddr *, socklen_t);
+ void xbind (int, const struct sockaddr *, socklen_t);
+ void xlisten (int, int);
diff --git a/SOURCES/glibc-RHEL-34265.patch b/SOURCES/glibc-RHEL-34265.patch
new file mode 100644
index 0000000000000000000000000000000000000000..f390d0c433b40dd1649ee197752facdb56e1ada5
--- /dev/null
+++ b/SOURCES/glibc-RHEL-34265.patch
@@ -0,0 +1,31 @@
+commit 87801a8fd06db1d654eea3e4f7626ff476a9bdaa
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Apr 25 15:00:45 2024 +0200
+
+    CVE-2024-33599: nscd: Stack-based buffer overflow in netgroup cache (bug 31677)
+    
+    Using alloca matches what other caches do.  The request length is
+    bounded by MAXKEYLEN.
+    
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
+index 0c6e46f15c..f227dc7fa2 100644
+--- a/nscd/netgroupcache.c
++++ b/nscd/netgroupcache.c
+@@ -502,12 +502,13 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
+       = (struct indataset *) mempool_alloc (db,
+ 					    sizeof (*dataset) + req->key_len,
+ 					    1);
+-  struct indataset dataset_mem;
+   bool cacheable = true;
+   if (__glibc_unlikely (dataset == NULL))
+     {
+       cacheable = false;
+-      dataset = &dataset_mem;
++      /* The alloca is safe because nscd_run_worker verfies that
++	 key_len is not larger than MAXKEYLEN.  */
++      dataset = alloca (sizeof (*dataset) + req->key_len);
+     }
+ 
+   datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
diff --git a/SOURCES/glibc-RHEL-34268-1.patch b/SOURCES/glibc-RHEL-34268-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..4642d7a5bd0c35b7824881485546ff224e7c2cf7
--- /dev/null
+++ b/SOURCES/glibc-RHEL-34268-1.patch
@@ -0,0 +1,53 @@
+commit b048a482f088e53144d26a61c390bed0210f49f2
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Apr 25 15:01:07 2024 +0200
+
+    CVE-2024-33600: nscd: Avoid null pointer crashes after notfound response (bug 31678)
+    
+    The addgetnetgrentX call in addinnetgrX may have failed to produce
+    a result, so the result variable in addinnetgrX can be NULL.
+    Use db->negtimeout as the fallback value if there is no result data;
+    the timeout is also overwritten below.
+    
+    Also avoid sending a second not-found response.  (The client
+    disconnects after receiving the first response, so the data stream did
+    not go out of sync even without this fix.)  It is still beneficial to
+    add the negative response to the mapping, so that the client can get
+    it from there in the future, instead of going through the socket.
+    
+    Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
+index c18fe111f3..e22ffa5884 100644
+--- a/nscd/netgroupcache.c
++++ b/nscd/netgroupcache.c
+@@ -511,14 +511,15 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
+ 
+   datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
+ 		     sizeof (innetgroup_response_header),
+-		     he == NULL ? 0 : dh->nreloads + 1, result->head.ttl);
++		     he == NULL ? 0 : dh->nreloads + 1,
++		     result == NULL ? db->negtimeout : result->head.ttl);
+   /* Set the notfound status and timeout based on the result from
+      getnetgrent.  */
+-  dataset->head.notfound = result->head.notfound;
++  dataset->head.notfound = result == NULL || result->head.notfound;
+   dataset->head.timeout = timeout;
+ 
+   dataset->resp.version = NSCD_VERSION;
+-  dataset->resp.found = result->resp.found;
++  dataset->resp.found = result != NULL && result->resp.found;
+   /* Until we find a matching entry the result is 0.  */
+   dataset->resp.result = 0;
+ 
+@@ -566,7 +567,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
+       goto out;
+     }
+ 
+-  if (he == NULL)
++  /* addgetnetgrentX may have already sent a notfound response.  Do
++     not send another one.  */
++  if (he == NULL && dataset->resp.found)
+     {
+       /* We write the dataset before inserting it to the database
+ 	 since while inserting this thread might block and so would
diff --git a/SOURCES/glibc-RHEL-34268-2.patch b/SOURCES/glibc-RHEL-34268-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6619d7c94911940f843a9a5d50f12039cf3d3dce
--- /dev/null
+++ b/SOURCES/glibc-RHEL-34268-2.patch
@@ -0,0 +1,52 @@
+commit 7835b00dbce53c3c87bbbb1754a95fb5e58187aa
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Apr 25 15:01:07 2024 +0200
+
+    CVE-2024-33600: nscd: Do not send missing not-found response in addgetnetgrentX (bug 31678)
+    
+    If we failed to add a not-found response to the cache, the dataset
+    point can be null, resulting in a null pointer dereference.
+    
+    Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
+index f227dc7fa2..c18fe111f3 100644
+--- a/nscd/netgroupcache.c
++++ b/nscd/netgroupcache.c
+@@ -147,7 +147,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+       /* No such service.  */
+       cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
+ 			       &key_copy);
+-      goto writeout;
++      goto maybe_cache_add;
+     }
+ 
+   memset (&data, '\0', sizeof (data));
+@@ -348,7 +348,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+     {
+       cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
+ 			       &key_copy);
+-      goto writeout;
++      goto maybe_cache_add;
+     }
+ 
+   total = buffilled;
+@@ -410,14 +410,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+   }
+ 
+   if (he == NULL && fd != -1)
+-    {
+-      /* We write the dataset before inserting it to the database
+-	 since while inserting this thread might block and so would
+-	 unnecessarily let the receiver wait.  */
+-    writeout:
++    /* We write the dataset before inserting it to the database since
++       while inserting this thread might block and so would
++       unnecessarily let the receiver wait.  */
+       writeall (fd, &dataset->resp, dataset->head.recsize);
+-    }
+ 
++ maybe_cache_add:
+   if (cacheable)
+     {
+       /* If necessary, we also propagate the data to disk.  */
diff --git a/SOURCES/glibc-RHEL-34272-1.patch b/SOURCES/glibc-RHEL-34272-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..f8574ea9dbfd2a7d0e4e1001825d05b318c367b2
--- /dev/null
+++ b/SOURCES/glibc-RHEL-34272-1.patch
@@ -0,0 +1,382 @@
+commit c04a21e050d64a1193a6daab872bca2528bda44b
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Apr 25 15:01:07 2024 +0200
+
+    CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX (bug 31680)
+    
+    This avoids potential memory corruption when the underlying NSS
+    callback function does not use the buffer space to store all strings
+    (e.g., for constant strings).
+    
+    Instead of custom buffer management, two scratch buffers are used.
+    This increases stack usage somewhat.
+    
+    Scratch buffer allocation failure is handled by return -1
+    (an invalid timeout value) instead of terminating the process.
+    This fixes bug 31679.
+    
+    Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+diff -Nrup glibc-2.34/nscd/netgroupcache.c b/nscd/netgroupcache.c
+--- glibc-2.34/nscd/netgroupcache.c	2024-06-13 13:55:16.406511485 -0400
++++ b/nscd/netgroupcache.c	2024-06-13 13:34:45.523345077 -0400
+@@ -24,6 +24,7 @@
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <sys/mman.h>
++#include <scratch_buffer.h>
+ 
+ #include "../inet/netgroup.h"
+ #include "nscd.h"
+@@ -66,6 +67,16 @@ struct dataset
+   char strdata[0];
+ };
+ 
++/* Send a notfound response to FD.  Always returns -1 to indicate an
++   ephemeral error.  */
++static time_t
++send_notfound (int fd)
++{
++  if (fd != -1)
++    TEMP_FAILURE_RETRY (send (fd, &notfound, sizeof (notfound), MSG_NOSIGNAL));
++  return -1;
++}
++
+ /* Sends a notfound message and prepares a notfound dataset to write to the
+    cache.  Returns true if there was enough memory to allocate the dataset and
+    returns the dataset in DATASETP, total bytes to write in TOTALP and the
+@@ -84,8 +95,7 @@ do_notfound (struct database_dyn *db, in
+   total = sizeof (notfound);
+   timeout = time (NULL) + db->negtimeout;
+ 
+-  if (fd != -1)
+-    TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
++  send_notfound (fd);
+ 
+   dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
+   /* If we cannot permanently store the result, so be it.  */
+@@ -110,11 +120,78 @@ do_notfound (struct database_dyn *db, in
+   return cacheable;
+ }
+ 
++struct addgetnetgrentX_scratch
++{
++  /* This is the result that the caller should use.  It can be NULL,
++     point into buffer, or it can be in the cache.  */
++  struct dataset *dataset;
++
++  struct scratch_buffer buffer;
++
++  /* Used internally in addgetnetgrentX as a staging area.  */
++  struct scratch_buffer tmp;
++
++  /* Number of bytes in buffer that are actually used.  */
++  size_t buffer_used;
++};
++
++static void
++addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch)
++{
++  scratch->dataset = NULL;
++  scratch_buffer_init (&scratch->buffer);
++  scratch_buffer_init (&scratch->tmp);
++
++  /* Reserve space for the header.  */
++  scratch->buffer_used = sizeof (struct dataset);
++  static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space),
++		 "initial buffer space");
++  memset (scratch->tmp.data, 0, sizeof (struct dataset));
++}
++
++static void
++addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch)
++{
++  scratch_buffer_free (&scratch->buffer);
++  scratch_buffer_free (&scratch->tmp);
++}
++
++/* Copy LENGTH bytes from S into SCRATCH.  Returns NULL if SCRATCH
++   could not be resized, otherwise a pointer to the copy.  */
++static char *
++addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch,
++			  const char *s, size_t length)
++{
++  while (true)
++    {
++      size_t remaining = scratch->buffer.length - scratch->buffer_used;
++      if (remaining >= length)
++	break;
++      if (!scratch_buffer_grow_preserve (&scratch->buffer))
++	return NULL;
++    }
++  char *copy = scratch->buffer.data + scratch->buffer_used;
++  memcpy (copy, s, length);
++  scratch->buffer_used += length;
++  return copy;
++}
++
++/* Copy S into SCRATCH, including its null terminator.  Returns false
++   if SCRATCH could not be resized.  */
++static bool
++addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s)
++{
++  if (s == NULL)
++    s = "";
++  return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL;
++}
++
++/* Caller must initialize and free *SCRATCH.  If the return value is
++   negative, this function has sent a notfound response.  */
+ static time_t
+ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ 		 const char *key, uid_t uid, struct hashentry *he,
+-		 struct datahead *dh, struct dataset **resultp,
+-		 void **tofreep)
++		 struct datahead *dh, struct addgetnetgrentX_scratch *scratch)
+ {
+   if (__glibc_unlikely (debug_level > 0))
+     {
+@@ -133,14 +210,10 @@ addgetnetgrentX (struct database_dyn *db
+ 
+   char *key_copy = NULL;
+   struct __netgrent data;
+-  size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len);
+-  size_t buffilled = sizeof (*dataset);
+-  char *buffer = NULL;
+   size_t nentries = 0;
+   size_t group_len = strlen (key) + 1;
+   struct name_list *first_needed
+     = alloca (sizeof (struct name_list) + group_len);
+-  *tofreep = NULL;
+ 
+   if (netgroup_database == NULL
+       && !__nss_database_get (nss_database_netgroup, &netgroup_database))
+@@ -152,8 +225,6 @@ addgetnetgrentX (struct database_dyn *db
+     }
+ 
+   memset (&data, '\0', sizeof (data));
+-  buffer = xmalloc (buflen);
+-  *tofreep = buffer;
+   first_needed->next = first_needed;
+   memcpy (first_needed->name, key, group_len);
+   data.needed_groups = first_needed;
+@@ -196,8 +267,8 @@ addgetnetgrentX (struct database_dyn *db
+ 		while (1)
+ 		  {
+ 		    int e;
+-		    status = getfct.f (&data, buffer + buffilled,
+-				       buflen - buffilled - req->key_len, &e);
++		    status = getfct.f (&data, scratch->tmp.data,
++				       scratch->tmp.length, &e);
+ 		    if (status == NSS_STATUS_SUCCESS)
+ 		      {
+ 			if (data.type == triple_val)
+@@ -205,68 +276,10 @@ addgetnetgrentX (struct database_dyn *db
+ 			    const char *nhost = data.val.triple.host;
+ 			    const char *nuser = data.val.triple.user;
+ 			    const char *ndomain = data.val.triple.domain;
+-
+-			    size_t hostlen = strlen (nhost ?: "") + 1;
+-			    size_t userlen = strlen (nuser ?: "") + 1;
+-			    size_t domainlen = strlen (ndomain ?: "") + 1;
+-
+-			    if (nhost == NULL || nuser == NULL || ndomain == NULL
+-				|| nhost > nuser || nuser > ndomain)
+-			      {
+-				const char *last = nhost;
+-				if (last == NULL
+-				    || (nuser != NULL && nuser > last))
+-				  last = nuser;
+-				if (last == NULL
+-				    || (ndomain != NULL && ndomain > last))
+-				  last = ndomain;
+-
+-				size_t bufused
+-				  = (last == NULL
+-				     ? buffilled
+-				     : last + strlen (last) + 1 - buffer);
+-
+-				/* We have to make temporary copies.  */
+-				size_t needed = hostlen + userlen + domainlen;
+-
+-				if (buflen - req->key_len - bufused < needed)
+-				  {
+-				    buflen += MAX (buflen, 2 * needed);
+-				    /* Save offset in the old buffer.  We don't
+-				       bother with the NULL check here since
+-				       we'll do that later anyway.  */
+-				    size_t nhostdiff = nhost - buffer;
+-				    size_t nuserdiff = nuser - buffer;
+-				    size_t ndomaindiff = ndomain - buffer;
+-
+-				    char *newbuf = xrealloc (buffer, buflen);
+-				    /* Fix up the triplet pointers into the new
+-				       buffer.  */
+-				    nhost = (nhost ? newbuf + nhostdiff
+-					     : NULL);
+-				    nuser = (nuser ? newbuf + nuserdiff
+-					     : NULL);
+-				    ndomain = (ndomain ? newbuf + ndomaindiff
+-					       : NULL);
+-				    *tofreep = buffer = newbuf;
+-				  }
+-
+-				nhost = memcpy (buffer + bufused,
+-						nhost ?: "", hostlen);
+-				nuser = memcpy ((char *) nhost + hostlen,
+-						nuser ?: "", userlen);
+-				ndomain = memcpy ((char *) nuser + userlen,
+-						  ndomain ?: "", domainlen);
+-			      }
+-
+-			    char *wp = buffer + buffilled;
+-			    wp = memmove (wp, nhost ?: "", hostlen);
+-			    wp += hostlen;
+-			    wp = memmove (wp, nuser ?: "", userlen);
+-			    wp += userlen;
+-			    wp = memmove (wp, ndomain ?: "", domainlen);
+-			    wp += domainlen;
+-			    buffilled = wp - buffer;
++			    if (!(addgetnetgrentX_append (scratch, nhost)
++				  && addgetnetgrentX_append (scratch, nuser)
++				  && addgetnetgrentX_append (scratch, ndomain)))
++			      return send_notfound (fd);
+ 			    ++nentries;
+ 			  }
+ 			else
+@@ -318,8 +331,8 @@ addgetnetgrentX (struct database_dyn *db
+ 		      }
+ 		    else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
+ 		      {
+-			buflen *= 2;
+-			*tofreep = buffer = xrealloc (buffer, buflen);
++			if (!scratch_buffer_grow (&scratch->tmp))
++			  return send_notfound (fd);
+ 		      }
+ 		    else if (status == NSS_STATUS_RETURN
+ 			     || status == NSS_STATUS_NOTFOUND
+@@ -352,10 +365,17 @@ addgetnetgrentX (struct database_dyn *db
+       goto maybe_cache_add;
+     }
+ 
+-  total = buffilled;
++  /* Capture the result size without the key appended.   */
++  total = scratch->buffer_used;
++
++  /* Make a copy of the key.  The scratch buffer must not move after
++     this point.  */
++  key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len);
++  if (key_copy == NULL)
++    return send_notfound (fd);
+ 
+   /* Fill in the dataset.  */
+-  dataset = (struct dataset *) buffer;
++  dataset = scratch->buffer.data;
+   timeout = datahead_init_pos (&dataset->head, total + req->key_len,
+ 			       total - offsetof (struct dataset, resp),
+ 			       he == NULL ? 0 : dh->nreloads + 1,
+@@ -364,11 +384,7 @@ addgetnetgrentX (struct database_dyn *db
+   dataset->resp.version = NSCD_VERSION;
+   dataset->resp.found = 1;
+   dataset->resp.nresults = nentries;
+-  dataset->resp.result_len = buffilled - sizeof (*dataset);
+-
+-  assert (buflen - buffilled >= req->key_len);
+-  key_copy = memcpy (buffer + buffilled, key, req->key_len);
+-  buffilled += req->key_len;
++  dataset->resp.result_len = total - sizeof (*dataset);
+ 
+   /* Now we can determine whether on refill we have to create a new
+      record or not.  */
+@@ -399,7 +415,7 @@ addgetnetgrentX (struct database_dyn *db
+     if (__glibc_likely (newp != NULL))
+       {
+ 	/* Adjust pointer into the memory block.  */
+-	key_copy = (char *) newp + (key_copy - buffer);
++	key_copy = (char *) newp + (key_copy - (char *) dataset);
+ 
+ 	dataset = memcpy (newp, dataset, total + req->key_len);
+ 	cacheable = true;
+@@ -440,7 +456,7 @@ addgetnetgrentX (struct database_dyn *db
+     }
+ 
+  out:
+-  *resultp = dataset;
++  scratch->dataset = dataset;
+ 
+   return timeout;
+ }
+@@ -461,6 +477,9 @@ addinnetgrX (struct database_dyn *db, in
+   if (user != NULL)
+     key = (char *) rawmemchr (key, '\0') + 1;
+   const char *domain = *key++ ? key : NULL;
++  struct addgetnetgrentX_scratch scratch;
++
++  addgetnetgrentX_scratch_init (&scratch);
+ 
+   if (__glibc_unlikely (debug_level > 0))
+     {
+@@ -476,12 +495,8 @@ addinnetgrX (struct database_dyn *db, in
+ 							    group, group_len,
+ 							    db, uid);
+   time_t timeout;
+-  void *tofree;
+   if (result != NULL)
+-    {
+-      timeout = result->head.timeout;
+-      tofree = NULL;
+-    }
++    timeout = result->head.timeout;
+   else
+     {
+       request_header req_get =
+@@ -490,7 +505,10 @@ addinnetgrX (struct database_dyn *db, in
+ 	  .key_len = group_len
+ 	};
+       timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
+-				 &result, &tofree);
++				 &scratch);
++      result = scratch.dataset;
++      if (timeout < 0)
++	goto out;
+     }
+ 
+   struct indataset
+@@ -604,7 +622,7 @@ addinnetgrX (struct database_dyn *db, in
+     }
+ 
+  out:
+-  free (tofree);
++  addgetnetgrentX_scratch_free (&scratch);
+   return timeout;
+ }
+ 
+@@ -614,11 +632,12 @@ addgetnetgrentX_ignore (struct database_
+ 			const char *key, uid_t uid, struct hashentry *he,
+ 			struct datahead *dh)
+ {
+-  struct dataset *ignore;
+-  void *tofree;
+-  time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
+-				    &ignore, &tofree);
+-  free (tofree);
++  struct addgetnetgrentX_scratch scratch;
++  addgetnetgrentX_scratch_init (&scratch);
++  time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch);
++  addgetnetgrentX_scratch_free (&scratch);
++  if (timeout < 0)
++    timeout = 0;
+   return timeout;
+ }
+ 
+@@ -662,5 +681,9 @@ readdinnetgr (struct database_dyn *db, s
+       .key_len = he->len
+     };
+ 
+-  return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh);
++  int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
++			     he, dh);
++  if (timeout < 0)
++    timeout = 0;
++  return timeout;
+ }
diff --git a/SOURCES/glibc-RHEL-34272-2.patch b/SOURCES/glibc-RHEL-34272-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..62930fe509671fd6ee68defedb9cf707dcd5bedf
--- /dev/null
+++ b/SOURCES/glibc-RHEL-34272-2.patch
@@ -0,0 +1,30 @@
+commit 4bbca1a44691a6e9adcee5c6798a707b626bc331
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu May 2 17:06:19 2024 +0200
+
+    nscd: Use time_t for return type of addgetnetgrentX
+    
+    Using int may give false results for future dates (timeouts after the
+    year 2028).
+    
+    Fixes commit 04a21e050d64a1193a6daab872bca2528bda44b ("CVE-2024-33601,
+    CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX
+    (bug 31680)").
+    
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
+index 4b35498e3f..5fdcf4204e 100644
+--- a/nscd/netgroupcache.c
++++ b/nscd/netgroupcache.c
+@@ -680,8 +680,8 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he,
+       .key_len = he->len
+     };
+ 
+-  int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
+-			     he, dh);
++  time_t timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
++				he, dh);
+   if (timeout < 0)
+     timeout = 0;
+   return timeout;
diff --git a/SOURCES/glibc-RHEL-36148-1.patch b/SOURCES/glibc-RHEL-36148-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..3931b90497867ebdeaef3866dc1ccc290fe450a9
--- /dev/null
+++ b/SOURCES/glibc-RHEL-36148-1.patch
@@ -0,0 +1,88 @@
+commit fe06fb313bddf7e4530056897d4a706606e49377
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Aug 1 23:31:23 2024 +0200
+
+    elf: Clarify and invert second argument of _dl_allocate_tls_init
+    
+    Also remove an outdated comment: _dl_allocate_tls_init is
+    called as part of pthread_create.
+    
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+diff -Nrup a/elf/dl-tls.c b/elf/dl-tls.c
+--- a/elf/dl-tls.c	2024-08-27 22:51:44.720953314 -0400
++++ b/elf/dl-tls.c	2024-08-27 22:51:07.686759191 -0400
+@@ -558,9 +558,14 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_m
+ /* Allocate initial TLS.  RESULT should be a non-NULL pointer to storage
+    for the TLS space.  The DTV may be resized, and so this function may
+    call malloc to allocate that space.  The loader's GL(dl_load_tls_lock)
+-   is taken when manipulating global TLS-related data in the loader.  */
++   is taken when manipulating global TLS-related data in the loader.
++
++   If MAIN_THREAD, this is the first call during process
++   initialization.  In this case, TLS initialization for secondary
++   (audit) namespaces is skipped because that has already been handled
++   by dlopen.  */
+ void *
+-_dl_allocate_tls_init (void *result, bool init_tls)
++_dl_allocate_tls_init (void *result, bool main_thread)
+ {
+   if (result == NULL)
+     /* The memory allocation failed.  */
+@@ -639,7 +644,7 @@ _dl_allocate_tls_init (void *result, boo
+ 	     because it would already be set by the audit setup.  However,
+ 	     subsequent thread creation would need to follow the default
+ 	     behaviour.   */
+-	  if (map->l_ns != LM_ID_BASE && !init_tls)
++	  if (map->l_ns != LM_ID_BASE && main_thread)
+ 	    continue;
+ 	  memset (__mempcpy (dest, map->l_tls_initimage,
+ 			     map->l_tls_initimage_size), '\0',
+@@ -667,7 +672,7 @@ _dl_allocate_tls (void *mem)
+ {
+   return _dl_allocate_tls_init (mem == NULL
+ 				? _dl_allocate_tls_storage ()
+-				: allocate_dtv (mem), true);
++				: allocate_dtv (mem), false);
+ }
+ rtld_hidden_def (_dl_allocate_tls)
+ 
+diff -Nrup a/elf/rtld.c b/elf/rtld.c
+--- a/elf/rtld.c	2024-08-27 22:51:44.720953314 -0400
++++ b/elf/rtld.c	2024-08-27 22:54:51.136930475 -0400
+@@ -2485,7 +2485,7 @@ dl_main (const ElfW(Phdr) *phdr,
+      into the main thread's TLS area, which we allocated above.
+      Note: thread-local variables must only be accessed after completing
+      the next step.  */
+-  _dl_allocate_tls_init (tcbp, false);
++  _dl_allocate_tls_init (tcbp, true);
+ 
+   /* And finally install it for the main thread.  */
+   if (! tls_init_tp_called)
+diff -Nrup a/nptl/allocatestack.c b/nptl/allocatestack.c
+--- a/nptl/allocatestack.c	2024-08-27 22:51:43.922949131 -0400
++++ b/nptl/allocatestack.c	2024-08-27 22:51:07.687759197 -0400
+@@ -137,7 +137,7 @@ get_cached_stack (size_t *sizep, void **
+   memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
+ 
+   /* Re-initialize the TLS.  */
+-  _dl_allocate_tls_init (TLS_TPADJ (result), true);
++  _dl_allocate_tls_init (TLS_TPADJ (result), false);
+ 
+   return result;
+ }
+diff -Nrup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+--- a/sysdeps/generic/ldsodefs.h	2024-08-27 22:51:44.720953314 -0400
++++ b/sysdeps/generic/ldsodefs.h	2024-08-27 22:56:44.425524320 -0400
+@@ -1258,10 +1258,8 @@ extern void _dl_get_tls_static_info (siz
+ 
+ extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden;
+ 
+-/* These are internal entry points to the two halves of _dl_allocate_tls,
+-   only used within rtld.c itself at startup time.  */
+ extern void *_dl_allocate_tls_storage (void) attribute_hidden;
+-extern void *_dl_allocate_tls_init (void *, bool);
++extern void *_dl_allocate_tls_init (void *result, bool main_thread);
+ rtld_hidden_proto (_dl_allocate_tls_init)
+ 
+ /* Deallocate memory allocated with _dl_allocate_tls.  */
diff --git a/SOURCES/glibc-RHEL-36148-2.patch b/SOURCES/glibc-RHEL-36148-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..607b346963f0e22c316efb760b9e079bcf6fafce
--- /dev/null
+++ b/SOURCES/glibc-RHEL-36148-2.patch
@@ -0,0 +1,520 @@
+commit 5097cd344fd243fb8deb6dec96e8073753f962f9
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Aug 1 23:31:30 2024 +0200
+
+    elf: Avoid re-initializing already allocated TLS in dlopen (bug 31717)
+    
+    The old code used l_init_called as an indicator for whether TLS
+    initialization was complete.  However, it is possible that
+    TLS for an object is initialized, written to, and then dlopen
+    for this object is called again, and l_init_called is not true at
+    this point.  Previously, this resulted in TLS being initialized
+    twice, discarding any interim writes (technically introducing a
+    use-after-free bug even).
+    
+    This commit introduces an explicit per-object flag, l_tls_in_slotinfo.
+    It indicates whether _dl_add_to_slotinfo has been called for this
+    object.  This flag is used to avoid double-initialization of TLS.
+    In update_tls_slotinfo, the first_static_tls micro-optimization
+    is removed because preserving the initalization flag for subsequent
+    use by the second loop for static TLS is a bit complicated, and
+    another per-object flag does not seem to be worth it.  Furthermore,
+    the l_init_called flag is dropped from the second loop (for static
+    TLS initialization) because l_need_tls_init on its own prevents
+    double-initialization.
+    
+    The remaining l_init_called usage in resize_scopes and update_scopes
+    is just an optimization due to the use of scope_has_map, so it is
+    not changed in this commit.
+    
+    The isupper check ensures that libc.so.6 is TLS is not reverted.
+    Such a revert happens if l_need_tls_init is not cleared in
+    _dl_allocate_tls_init for the main_thread case, now that
+    l_init_called is not checked anymore in update_tls_slotinfo
+    in elf/dl-open.c.
+    
+    Reported-by: Jonathon Anderson <janderson@rice.edu>
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+diff -Nrup a/elf/Makefile b/elf/Makefile
+--- a/elf/Makefile	2024-08-27 23:25:59.327755050 -0400
++++ b/elf/Makefile	2024-08-27 23:16:50.456864065 -0400
+@@ -399,6 +399,10 @@ tests += \
+   tst-dlmopen-dlerror \
+   tst-dlmopen-gethostbyname \
+   tst-dlmopen-twice \
++  tst-dlopen-tlsreinit1 \
++  tst-dlopen-tlsreinit2 \
++  tst-dlopen-tlsreinit3 \
++  tst-dlopen-tlsreinit4 \
+   tst-dlopenfail \
+   tst-dlopenfail-2 \
+   tst-dlopenrpath \
+@@ -753,6 +757,9 @@ modules-names = \
+   tst-dlmopen-gethostbyname-mod \
+   tst-dlmopen-twice-mod1 \
+   tst-dlmopen-twice-mod2 \
++  tst-dlopen-tlsreinitmod1 \
++  tst-dlopen-tlsreinitmod2 \
++  tst-dlopen-tlsreinitmod3 \
+   tst-dlopenfaillinkmod \
+   tst-dlopenfailmod1 \
+   tst-dlopenfailmod2 \
+@@ -2751,3 +2758,26 @@ $(objpfx)tst-recursive-tls.out: \
+     0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
+ $(objpfx)tst-recursive-tlsmod%.os: tst-recursive-tlsmodN.c
+ 	$(compile-command.c) -DVAR=thread_$* -DFUNC=get_threadvar_$*
++
++# Order matters here.  The test needs the constructor for
++# tst-dlopen-tlsreinitmod2.so to be called first.
++LDFLAGS-tst-dlopen-tlsreinitmod1.so = -Wl,--no-as-needed
++$(objpfx)tst-dlopen-tlsreinitmod1.so: \
++  $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
++LDFLAGS-tst-dlopen-tlsreinit2 = -Wl,--no-as-needed
++$(objpfx)tst-dlopen-tlsreinit2: \
++  $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
++LDFLAGS-tst-dlopen-tlsreinit4 = -Wl,--no-as-needed
++$(objpfx)tst-dlopen-tlsreinit4: \
++  $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
++# tst-dlopen-tlsreinitmod2.so is underlinked and refers to
++# tst-dlopen-tlsreinitmod3.so.  The dependency is provided via
++# $(objpfx)tst-dlopen-tlsreinitmod1.so.
++tst-dlopen-tlsreinitmod2.so-no-z-defs = yes
++$(objpfx)tst-dlopen-tlsreinit.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
++  $(objpfx)tst-dlopen-tlsreinitmod2.so $(objpfx)tst-dlopen-tlsreinitmod3.so
++# Reuse an audit module which provides ample debug logging.
++$(objpfx)tst-dlopen-tlsreinit3.out: $(objpfx)tst-auditmod1.so
++tst-dlopen-tlsreinit3-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
++$(objpfx)tst-dlopen-tlsreinit4.out: $(objpfx)tst-auditmod1.so
++tst-dlopen-tlsreinit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
+diff -Nrup a/elf/dl-open.c b/elf/dl-open.c
+--- a/elf/dl-open.c	2024-08-27 23:25:59.237754576 -0400
++++ b/elf/dl-open.c	2024-08-27 23:10:52.497978645 -0400
+@@ -362,17 +362,8 @@ resize_tls_slotinfo (struct link_map *ne
+ {
+   bool any_tls = false;
+   for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
+-    {
+-      struct link_map *imap = new->l_searchlist.r_list[i];
+-
+-      /* Only add TLS memory if this object is loaded now and
+-	 therefore is not yet initialized.  */
+-      if (! imap->l_init_called && imap->l_tls_blocksize > 0)
+-	{
+-	  _dl_add_to_slotinfo (imap, false);
+-	  any_tls = true;
+-	}
+-    }
++    if (_dl_add_to_slotinfo (new->l_searchlist.r_list[i], false))
++      any_tls = true;
+   return any_tls;
+ }
+ 
+@@ -382,22 +373,8 @@ resize_tls_slotinfo (struct link_map *ne
+ static void
+ update_tls_slotinfo (struct link_map *new)
+ {
+-  unsigned int first_static_tls = new->l_searchlist.r_nlist;
+   for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
+-    {
+-      struct link_map *imap = new->l_searchlist.r_list[i];
+-
+-      /* Only add TLS memory if this object is loaded now and
+-	 therefore is not yet initialized.  */
+-      if (! imap->l_init_called && imap->l_tls_blocksize > 0)
+-	{
+-	  _dl_add_to_slotinfo (imap, true);
+-
+-	  if (imap->l_need_tls_init
+-	      && first_static_tls == new->l_searchlist.r_nlist)
+-	    first_static_tls = i;
+-	}
+-    }
++    _dl_add_to_slotinfo (new->l_searchlist.r_list[i], true);
+ 
+   size_t newgen = GL(dl_tls_generation) + 1;
+   if (__glibc_unlikely (newgen == 0))
+@@ -409,13 +386,11 @@ TLS generation counter wrapped!  Please
+   /* We need a second pass for static tls data, because
+      _dl_update_slotinfo must not be run while calls to
+      _dl_add_to_slotinfo are still pending.  */
+-  for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
++  for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
+     {
+       struct link_map *imap = new->l_searchlist.r_list[i];
+ 
+-      if (imap->l_need_tls_init
+-	  && ! imap->l_init_called
+-	  && imap->l_tls_blocksize > 0)
++      if (imap->l_need_tls_init && imap->l_tls_blocksize > 0)
+ 	{
+ 	  /* For static TLS we have to allocate the memory here and
+ 	     now, but we can delay updating the DTV.  */
+diff -Nrup a/elf/dl-tls.c b/elf/dl-tls.c
+--- a/elf/dl-tls.c	2024-08-27 23:25:59.358755213 -0400
++++ b/elf/dl-tls.c	2024-08-27 23:21:04.960204566 -0400
+@@ -638,17 +638,21 @@ _dl_allocate_tls_init (void *result, boo
+ 	     some platforms use in static programs requires it.  */
+ 	  dtv[map->l_tls_modid].pointer.val = dest;
+ 
+-	  /* Copy the initialization image and clear the BSS part.  For
+-	     audit modules or dependencies with initial-exec TLS, we can not
+-	     set the initial TLS image on default loader initialization
+-	     because it would already be set by the audit setup.  However,
+-	     subsequent thread creation would need to follow the default
+-	     behaviour.   */
++	  /* Copy the initialization image and clear the BSS part.
++	     For audit modules or dependencies with initial-exec TLS,
++	     we can not set the initial TLS image on default loader
++	     initialization because it would already be set by the
++	     audit setup, which uses the dlopen code and already
++	     clears l_need_tls_init.  Calls with !main_thread from
++	     pthread_create need to initialze TLS for the current
++	     thread regardless of namespace.  */
+ 	  if (map->l_ns != LM_ID_BASE && main_thread)
+ 	    continue;
+ 	  memset (__mempcpy (dest, map->l_tls_initimage,
+ 			     map->l_tls_initimage_size), '\0',
+ 		  map->l_tls_blocksize - map->l_tls_initimage_size);
++	  if (main_thread)
++	    map->l_need_tls_init = 0;
+ 	}
+ 
+       total += cnt;
+@@ -1105,9 +1109,32 @@ _dl_tls_initial_modid_limit_setup (void)
+ }
+ 
+ 
+-void
++/* Add module to slot information data.  If DO_ADD is false, only the
++   required memory is allocated.  Must be called with
++   GL (dl_load_tls_lock) acquired.  If the function has already been
++   called for the link map L with !DO_ADD, then this function will not
++   raise an exception, otherwise it is possible that it encounters a
++   memory allocation failure.
++
++   Return false if L has already been added to the slotinfo data, or
++   if L has no TLS data.  If the returned value is true, L has been
++   added with this call (DO_ADD), or has been added in a previous call
++   (!DO_ADD).
++
++   The expected usage is as follows: Call _dl_add_to_slotinfo for
++   several link maps with DO_ADD set to false, and record if any calls
++   result in a true result.  If there was a true result, call
++   _dl_add_to_slotinfo again, this time with DO_ADD set to true.  (For
++   simplicity, it's possible to call the function for link maps where
++   the previous result was false.)  The return value from the second
++   round of calls can be ignored.  If there was true result initially,
++   call _dl_update_slotinfo to update the TLS generation counter.  */
++bool
+ _dl_add_to_slotinfo (struct link_map *l, bool do_add)
+ {
++  if (l->l_tls_blocksize == 0 || l->l_tls_in_slotinfo)
++    return false;
++
+   /* Now that we know the object is loaded successfully add
+      modules containing TLS data to the dtv info table.  We
+      might have to increase its size.  */
+@@ -1163,7 +1190,10 @@ cannot create TLS data structures"));
+       atomic_store_relaxed (&listp->slotinfo[idx].map, l);
+       atomic_store_relaxed (&listp->slotinfo[idx].gen,
+ 			    GL(dl_tls_generation) + 1);
++      l->l_tls_in_slotinfo = true;
+     }
++
++  return true;
+ }
+ 
+ #if THREAD_GSCOPE_IN_TCB
+diff -Nrup a/elf/tst-dlopen-tlsreinit1.c b/elf/tst-dlopen-tlsreinit1.c
+--- a/elf/tst-dlopen-tlsreinit1.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinit1.c	2024-08-27 23:10:52.497978645 -0400
+@@ -0,0 +1,40 @@
++/* Test that dlopen preserves already accessed TLS (bug 31717).
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <stdbool.h>
++#include <support/check.h>
++#include <support/xdlfcn.h>
++#include <ctype.h>
++
++static int
++do_test (void)
++{
++  void *handle = xdlopen ("tst-dlopen-tlsreinitmod1.so", RTLD_NOW);
++
++  bool *tlsreinitmod3_tested = xdlsym (handle, "tlsreinitmod3_tested");
++  TEST_VERIFY (*tlsreinitmod3_tested);
++
++  xdlclose (handle);
++
++  /* This crashes if the libc.so.6 TLS image has been reverted.  */
++  TEST_VERIFY (!isupper ('@'));
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff -Nrup a/elf/tst-dlopen-tlsreinit2.c b/elf/tst-dlopen-tlsreinit2.c
+--- a/elf/tst-dlopen-tlsreinit2.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinit2.c	2024-08-27 23:10:52.497978645 -0400
+@@ -0,0 +1,39 @@
++/* Test that dlopen preserves already accessed TLS (bug 31717).
++   Variant with initially-linked modules.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <ctype.h>
++#include <stdbool.h>
++#include <support/check.h>
++#include <support/xdlfcn.h>
++
++
++static int
++do_test (void)
++{
++  /* Defined in tst-dlopen-tlsreinitmod3.so.  */
++  extern bool tlsreinitmod3_tested;
++  TEST_VERIFY (tlsreinitmod3_tested);
++
++  /* This crashes if the libc.so.6 TLS image has been reverted.  */
++  TEST_VERIFY (!isupper ('@'));
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff -Nrup a/elf/tst-dlopen-tlsreinit3.c b/elf/tst-dlopen-tlsreinit3.c
+--- a/elf/tst-dlopen-tlsreinit3.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinit3.c	2024-08-27 23:10:52.497978645 -0400
+@@ -0,0 +1,2 @@
++/* Same code, but run with LD_AUDIT=tst-auditmod1.so.  */
++#include "tst-dlopen-tlsreinit1.c"
+diff -Nrup a/elf/tst-dlopen-tlsreinit4.c b/elf/tst-dlopen-tlsreinit4.c
+--- a/elf/tst-dlopen-tlsreinit4.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinit4.c	2024-08-27 23:10:52.497978645 -0400
+@@ -0,0 +1,2 @@
++/* Same code, but run with LD_AUDIT=tst-auditmod1.so.  */
++#include "tst-dlopen-tlsreinit2.c"
+diff -Nrup a/elf/tst-dlopen-tlsreinitmod1.c b/elf/tst-dlopen-tlsreinitmod1.c
+--- a/elf/tst-dlopen-tlsreinitmod1.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinitmod1.c	2024-08-27 23:10:52.497978645 -0400
+@@ -0,0 +1,20 @@
++/* Test that dlopen preserves already accessed TLS (bug 31717), module 1.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++/* This module triggers loading of tst-dlopen-tlsreinitmod2.so and
++   tst-dlopen-tlsreinitmod3.so.  */
+diff -Nrup a/elf/tst-dlopen-tlsreinitmod2.c b/elf/tst-dlopen-tlsreinitmod2.c
+--- a/elf/tst-dlopen-tlsreinitmod2.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinitmod2.c	2024-08-27 23:10:52.497978645 -0400
+@@ -0,0 +1,30 @@
++/* Test that dlopen preserves already accessed TLS (bug 31717), module 2.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++
++/* Defined in tst-dlopen-tlsreinitmod3.so.  This an underlinked symbol
++   dependency.  */
++extern void call_tlsreinitmod3 (void);
++
++static void __attribute__ ((constructor))
++tlsreinitmod2_init (void)
++{
++  puts ("info: constructor of tst-dlopen-tlsreinitmod2.so invoked");
++  call_tlsreinitmod3 ();
++}
+diff -Nrup a/elf/tst-dlopen-tlsreinitmod3.c b/elf/tst-dlopen-tlsreinitmod3.c
+--- a/elf/tst-dlopen-tlsreinitmod3.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/tst-dlopen-tlsreinitmod3.c	2024-08-27 23:10:52.498978651 -0400
+@@ -0,0 +1,102 @@
++/* Test that dlopen preserves already accessed TLS (bug 31717), module 3.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <dlfcn.h>
++#include <stdbool.h>
++#include <stdio.h>
++#include <unistd.h>
++
++/* Used to verify from the main program that the test ran.  */
++bool tlsreinitmod3_tested;
++
++/* This TLS variable must not revert back to the initial state after
++   dlopen.  */
++static __thread int tlsreinitmod3_state = 1;
++
++/* Set from the ELF constructor during dlopen.  */
++static bool tlsreinitmod3_constructed;
++
++/* Second half of test, behind a compiler barrier.  The compiler
++   barrier is necessary to prevent carrying over TLS address
++   information from call_tlsreinitmod3 to call_tlsreinitmod3_tail.  */
++void call_tlsreinitmod3_tail (void *self) __attribute__ ((weak));
++
++/* Called from tst-dlopen-tlsreinitmod2.so.  */
++void
++call_tlsreinitmod3 (void)
++{
++  printf ("info: call_tlsreinitmod3 invoked (state=%d)\n",
++          tlsreinitmod3_state);
++
++  if (tlsreinitmod3_constructed)
++    {
++      puts ("error: call_tlsreinitmod3 called after ELF constructor");
++      fflush (stdout);
++      /* Cannot rely on test harness due to dynamic linking.  */
++      _exit (1);
++    }
++
++  tlsreinitmod3_state = 2;
++
++  /* Self-dlopen.  This will run the ELF constructor.   */
++  void *self = dlopen ("tst-dlopen-tlsreinitmod3.so", RTLD_NOW);
++  if (self == NULL)
++    {
++      printf ("error: dlopen: %s\n", dlerror ());
++      fflush (stdout);
++      /* Cannot rely on test harness due to dynamic linking.  */
++      _exit (1);
++    }
++
++  call_tlsreinitmod3_tail (self);
++}
++
++void
++call_tlsreinitmod3_tail (void *self)
++{
++  printf ("info: dlopen returned in tlsreinitmod3 (state=%d)\n",
++          tlsreinitmod3_state);
++
++  if (!tlsreinitmod3_constructed)
++    {
++      puts ("error: dlopen did not call tlsreinitmod3 ELF constructor");
++      fflush (stdout);
++      /* Cannot rely on test harness due to dynamic linking.  */
++      _exit (1);
++    }
++
++  if (tlsreinitmod3_state != 2)
++    {
++      puts ("error: TLS state reverted in tlsreinitmod3");
++      fflush (stdout);
++      /* Cannot rely on test harness due to dynamic linking.  */
++      _exit (1);
++    }
++
++  dlclose (self);
++
++  /* Signal test completion to the main program.  */
++  tlsreinitmod3_tested = true;
++}
++
++static void __attribute__ ((constructor))
++tlsreinitmod3_init (void)
++{
++  puts ("info: constructor of tst-dlopen-tlsreinitmod3.so invoked");
++  tlsreinitmod3_constructed = true;
++}
+diff -Nrup a/include/link.h b/include/link.h
+--- a/include/link.h	2024-08-27 23:25:58.503750710 -0400
++++ b/include/link.h	2024-08-27 23:23:42.209032820 -0400
+@@ -211,6 +211,7 @@ struct link_map
+ 				       freed, ie. not allocated with
+ 				       the dummy malloc in ld.so.  */
+     unsigned int l_ld_readonly:1; /* Nonzero if dynamic section is readonly.  */
++    unsigned int l_tls_in_slotinfo:1; /* TLS slotinfo updated in dlopen.  */
+ 
+     /* NODELETE status of the map.  Only valid for maps of type
+        lt_loaded.  Lazy binding sets l_nodelete_active directly,
+diff -Nrup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+--- a/sysdeps/generic/ldsodefs.h	2024-08-27 23:25:59.359755218 -0400
++++ b/sysdeps/generic/ldsodefs.h	2024-08-27 23:10:52.498978651 -0400
+@@ -1291,13 +1291,7 @@ extern void *_dl_open (const char *name,
+ extern int _dl_scope_free (void *) attribute_hidden;
+ 
+ 
+-/* Add module to slot information data.  If DO_ADD is false, only the
+-   required memory is allocated.  Must be called with GL
+-   (dl_load_tls_lock) acquired.  If the function has already been called
+-   for the link map L with !do_add, then this function will not raise
+-   an exception, otherwise it is possible that it encounters a memory
+-   allocation failure.  */
+-extern void _dl_add_to_slotinfo (struct link_map *l, bool do_add)
++extern bool _dl_add_to_slotinfo (struct link_map *l, bool do_add)
+   attribute_hidden;
+ 
+ /* Update slot information data for at least the generation of the
diff --git a/SOURCES/glibc-RHEL-36148-3.patch b/SOURCES/glibc-RHEL-36148-3.patch
new file mode 100644
index 0000000000000000000000000000000000000000..a2b3e7699e1d831d5db812fc03561f55542bf34d
--- /dev/null
+++ b/SOURCES/glibc-RHEL-36148-3.patch
@@ -0,0 +1,16 @@
+Author: Patsy Griffin <patsy@redhat.com>
+  
+    Fix a typo in naming tst-dlopen-tlsreinit1.out
+
+diff -Nrup a/elf/Makefile b/elf/Makefile
+--- a/elf/Makefile	2024-08-16 13:27:00.700921146 -0400
++++ b/elf/Makefile	2024-08-16 13:29:12.951628406 -0400
+@@ -2802,7 +2802,7 @@ $(objpfx)tst-dlopen-tlsreinit4: \
+ # tst-dlopen-tlsreinitmod3.so.  The dependency is provided via
+ # $(objpfx)tst-dlopen-tlsreinitmod1.so.
+ tst-dlopen-tlsreinitmod2.so-no-z-defs = yes
+-$(objpfx)tst-dlopen-tlsreinit.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
++$(objpfx)tst-dlopen-tlsreinit1.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
+   $(objpfx)tst-dlopen-tlsreinitmod2.so $(objpfx)tst-dlopen-tlsreinitmod3.so
+ # Reuse an audit module which provides ample debug logging.
+ $(objpfx)tst-dlopen-tlsreinit3.out: $(objpfx)tst-auditmod1.so
diff --git a/SOURCES/glibc-RHEL-39000-1.patch b/SOURCES/glibc-RHEL-39000-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..8de8d2d7506b48d25c03d2a6f595a0dbbf910498
--- /dev/null
+++ b/SOURCES/glibc-RHEL-39000-1.patch
@@ -0,0 +1,593 @@
+commit df11c05be91fda5ef490c76fd0d4a53821750116
+Author: Joseph Myers <josmyers@redhat.com>
+Date:   Wed Jan 17 15:38:54 2024 +0000
+
+    Update syscall lists for Linux 6.7
+    
+    Linux 6.7 adds the futex_requeue, futex_wait and futex_wake syscalls,
+    and enables map_shadow_stack for architectures previously missing it.
+    Update syscall-names.list and regenerate the arch-syscall.h headers
+    with build-many-glibcs.py update-syscalls.
+    
+    Tested with build-many-glibcs.py.
+
+    Modified for RHEL by: Patsy Griffin <patsy@redhat.com>
+
+diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
+index 746991aa2f..1713897f85 100644
+--- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
+@@ -64,7 +64,10 @@
+ #define __NR_fsync 82
+ #define __NR_ftruncate 46
+ #define __NR_futex 98
++#define __NR_futex_requeue 456
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_get_mempolicy 236
+ #define __NR_get_robust_list 100
+ #define __NR_getcpu 168
+@@ -126,6 +129,7 @@
+ #define __NR_lseek 62
+ #define __NR_lsetxattr 6
+ #define __NR_madvise 233
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+ #define __NR_membarrier 283
+ #define __NR_memfd_create 279
+diff --git a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
+index 32efe51267..5457d2d8ae 100644
+--- a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
+@@ -80,7 +80,10 @@
+ #define __NR_fsync 95
+ #define __NR_ftruncate 130
+ #define __NR_futex 394
++#define __NR_futex_requeue 566
++#define __NR_futex_wait 565
+ #define __NR_futex_waitv 559
++#define __NR_futex_wake 564
+ #define __NR_futimesat 454
+ #define __NR_get_kernel_syms 309
+ #define __NR_get_mempolicy 430
+@@ -156,6 +159,7 @@
+ #define __NR_lstat 68
+ #define __NR_lstat64 426
+ #define __NR_madvise 75
++#define __NR_map_shadow_stack 563
+ #define __NR_mbind 429
+ #define __NR_membarrier 517
+ #define __NR_memfd_create 512
+diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
+index 1d2879e877..a66471c83a 100644
+--- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
+@@ -66,8 +66,11 @@
+ #define __NR_fstatfs64 44
+ #define __NR_fsync 82
+ #define __NR_ftruncate64 46
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_get_mempolicy 236
+ #define __NR_get_robust_list 100
+ #define __NR_getcpu 168
+@@ -130,6 +133,7 @@
+ #define __NR_lremovexattr 15
+ #define __NR_lsetxattr 6
+ #define __NR_madvise 233
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+ #define __NR_membarrier 283
+ #define __NR_memfd_create 279
+diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
+index 6711981e78..74a57f4520 100644
+--- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
+@@ -91,8 +91,11 @@
+ #define __NR_ftruncate 93
+ #define __NR_ftruncate64 194
+ #define __NR_futex 240
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 326
+ #define __NR_get_mempolicy 320
+ #define __NR_get_robust_list 339
+@@ -170,6 +173,7 @@
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 220
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 319
+ #define __NR_membarrier 389
+ #define __NR_memfd_create 385
+diff --git a/sysdeps/unix/sysv/linux/csky/arch-syscall.h b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
+index 92d9a703ea..ba7632e018 100644
+--- a/sysdeps/unix/sysv/linux/csky/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
+@@ -71,8 +71,11 @@
+ #define __NR_fsync 82
+ #define __NR_ftruncate64 46
+ #define __NR_futex 98
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_get_mempolicy 236
+ #define __NR_get_robust_list 100
+ #define __NR_getcpu 168
+@@ -135,6 +138,7 @@
+ #define __NR_lremovexattr 15
+ #define __NR_lsetxattr 6
+ #define __NR_madvise 233
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+ #define __NR_membarrier 283
+ #define __NR_memfd_create 279
+diff --git a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
+index fbac124b70..483706de9b 100644
+--- a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
+@@ -89,8 +89,11 @@
+ #define __NR_ftruncate 93
+ #define __NR_ftruncate64 200
+ #define __NR_futex 210
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 279
+ #define __NR_get_mempolicy 261
+ #define __NR_get_robust_list 290
+@@ -161,6 +164,7 @@
+ #define __NR_lstat 84
+ #define __NR_lstat64 198
+ #define __NR_madvise 119
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 260
+ #define __NR_membarrier 343
+ #define __NR_memfd_create 340
+diff --git a/sysdeps/unix/sysv/linux/i386/arch-syscall.h b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
+index 8961788a96..21c1308bb3 100644
+--- a/sysdeps/unix/sysv/linux/i386/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
+@@ -95,8 +95,11 @@
+ #define __NR_ftruncate 93
+ #define __NR_ftruncate64 194
+ #define __NR_futex 240
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 299
+ #define __NR_get_kernel_syms 130
+ #define __NR_get_mempolicy 275
+@@ -183,6 +186,7 @@
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 219
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 274
+ #define __NR_membarrier 375
+ #define __NR_memfd_create 356
+diff --git a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
+index 2053d5d392..6d788e3440 100644
+--- a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
+@@ -94,8 +94,11 @@
+ #define __NR_ftruncate 93
+ #define __NR_ftruncate64 194
+ #define __NR_futex 235
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 292
+ #define __NR_get_kernel_syms 130
+ #define __NR_get_mempolicy 269
+@@ -177,6 +180,7 @@
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 238
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 268
+ #define __NR_membarrier 374
+ #define __NR_memfd_create 353
+diff --git a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
+index 6865b1693c..91e1630f7b 100644
+--- a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
+@@ -95,8 +95,11 @@
+ #define __NR_ftruncate 93
+ #define __NR_ftruncate64 194
+ #define __NR_futex 240
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 299
+ #define __NR_get_kernel_syms 130
+ #define __NR_get_mempolicy 275
+@@ -183,6 +186,7 @@
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 219
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 274
+ #define __NR_membarrier 390
+ #define __NR_memfd_create 386
+diff --git a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
+index b13ace8e1c..d75af97467 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
+@@ -94,8 +94,11 @@
+ #define __NR_ftruncate 4093
+ #define __NR_ftruncate64 4212
+ #define __NR_futex 4238
++#define __NR_futex_requeue 4456
+ #define __NR_futex_time64 4422
++#define __NR_futex_wait 4455
+ #define __NR_futex_waitv 4449
++#define __NR_futex_wake 4454
+ #define __NR_futimesat 4292
+ #define __NR_get_kernel_syms 4130
+ #define __NR_get_mempolicy 4269
+@@ -173,6 +176,7 @@
+ #define __NR_lstat 4107
+ #define __NR_lstat64 4214
+ #define __NR_madvise 4218
++#define __NR_map_shadow_stack 4453
+ #define __NR_mbind 4268
+ #define __NR_membarrier 4358
+ #define __NR_memfd_create 4354
+diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
+index b7a7c0dfa7..05bf7d251d 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
+@@ -87,8 +87,11 @@
+ #define __NR_fsync 6072
+ #define __NR_ftruncate 6075
+ #define __NR_futex 6194
++#define __NR_futex_requeue 6456
+ #define __NR_futex_time64 6422
++#define __NR_futex_wait 6455
+ #define __NR_futex_waitv 6449
++#define __NR_futex_wake 6454
+ #define __NR_futimesat 6255
+ #define __NR_get_kernel_syms 6170
+ #define __NR_get_mempolicy 6232
+@@ -159,6 +162,7 @@
+ #define __NR_lsetxattr 6181
+ #define __NR_lstat 6006
+ #define __NR_madvise 6027
++#define __NR_map_shadow_stack 6453
+ #define __NR_mbind 6231
+ #define __NR_membarrier 6322
+ #define __NR_memfd_create 6318
+diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
+index e5d7f91f48..41ffaf3255 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
+@@ -80,7 +80,10 @@
+ #define __NR_fsync 5072
+ #define __NR_ftruncate 5075
+ #define __NR_futex 5194
++#define __NR_futex_requeue 5456
++#define __NR_futex_wait 5455
+ #define __NR_futex_waitv 5449
++#define __NR_futex_wake 5454
+ #define __NR_futimesat 5251
+ #define __NR_get_kernel_syms 5170
+ #define __NR_get_mempolicy 5228
+@@ -150,6 +153,7 @@
+ #define __NR_lsetxattr 5181
+ #define __NR_lstat 5006
+ #define __NR_madvise 5027
++#define __NR_map_shadow_stack 5453
+ #define __NR_mbind 5227
+ #define __NR_membarrier 5318
+ #define __NR_memfd_create 5314
+diff --git a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
+index 89950cc33a..d94e7e9ee9 100644
+--- a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
+@@ -70,8 +70,11 @@
+ #define __NR_fsync 82
+ #define __NR_ftruncate64 46
+ #define __NR_futex 98
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_get_mempolicy 236
+ #define __NR_get_robust_list 100
+ #define __NR_getcpu 168
+@@ -134,6 +137,7 @@
+ #define __NR_lremovexattr 15
+ #define __NR_lsetxattr 6
+ #define __NR_madvise 233
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+ #define __NR_membarrier 283
+ #define __NR_memfd_create 279
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
+index 64683bcb76..b5522e8889 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
+@@ -93,8 +93,11 @@
+ #define __NR_ftruncate 93
+ #define __NR_ftruncate64 194
+ #define __NR_futex 221
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 290
+ #define __NR_get_kernel_syms 130
+ #define __NR_get_mempolicy 260
+@@ -173,6 +176,7 @@
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 205
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 259
+ #define __NR_membarrier 365
+ #define __NR_memfd_create 360
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
+index af1bbf32e8..162d782ae6 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
+@@ -83,7 +83,10 @@
+ #define __NR_ftime 35
+ #define __NR_ftruncate 93
+ #define __NR_futex 221
++#define __NR_futex_requeue 456
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 290
+ #define __NR_get_kernel_syms 130
+ #define __NR_get_mempolicy 260
+@@ -160,6 +163,7 @@
+ #define __NR_lsetxattr 210
+ #define __NR_lstat 107
+ #define __NR_madvise 205
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 259
+ #define __NR_membarrier 365
+ #define __NR_memfd_create 360
+diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
+index 56e3088cbf..013222e5de 100644
+--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
+@@ -61,8 +61,11 @@
+ #define __NR_fstatfs64 44
+ #define __NR_fsync 82
+ #define __NR_ftruncate64 46
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_get_mempolicy 236
+ #define __NR_get_robust_list 100
+ #define __NR_getcpu 168
+@@ -121,6 +124,7 @@
+ #define __NR_lremovexattr 15
+ #define __NR_lsetxattr 6
+ #define __NR_madvise 233
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+ #define __NR_membarrier 283
+ #define __NR_memfd_create 279
+diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
+index 508161b47a..d03dad8200 100644
+--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
+@@ -64,7 +64,10 @@
+ #define __NR_fsync 82
+ #define __NR_ftruncate 46
+ #define __NR_futex 98
++#define __NR_futex_requeue 456
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_get_mempolicy 236
+ #define __NR_get_robust_list 100
+ #define __NR_getcpu 168
+@@ -126,6 +129,7 @@
+ #define __NR_lseek 62
+ #define __NR_lsetxattr 6
+ #define __NR_madvise 233
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+ #define __NR_membarrier 283
+ #define __NR_memfd_create 279
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
+index 1498ebf42e..98e6b68b31 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
+@@ -92,8 +92,11 @@
+ #define __NR_ftruncate 93
+ #define __NR_ftruncate64 194
+ #define __NR_futex 238
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 292
+ #define __NR_get_kernel_syms 130
+ #define __NR_get_mempolicy 269
+@@ -177,6 +180,7 @@
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 219
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 268
+ #define __NR_membarrier 356
+ #define __NR_memfd_create 350
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
+index 624d71b56d..951fbd7c97 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
+@@ -78,7 +78,10 @@
+ #define __NR_fsync 118
+ #define __NR_ftruncate 93
+ #define __NR_futex 238
++#define __NR_futex_requeue 456
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 292
+ #define __NR_get_kernel_syms 130
+ #define __NR_get_mempolicy 269
+@@ -151,6 +154,7 @@
+ #define __NR_lsetxattr 225
+ #define __NR_lstat 107
+ #define __NR_madvise 219
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 268
+ #define __NR_membarrier 356
+ #define __NR_memfd_create 350
+diff --git a/sysdeps/unix/sysv/linux/sh/arch-syscall.h b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
+index 37211f5f8c..6b4418bcae 100644
+--- a/sysdeps/unix/sysv/linux/sh/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
+@@ -91,8 +91,11 @@
+ #define __NR_ftruncate 93
+ #define __NR_ftruncate64 194
+ #define __NR_futex 240
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 299
+ #define __NR_get_mempolicy 275
+ #define __NR_get_robust_list 312
+@@ -170,6 +173,7 @@
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 219
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 274
+ #define __NR_membarrier 378
+ #define __NR_memfd_create 374
+diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
+index 8093abcc9c..4f9460b1a3 100644
+--- a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
+@@ -93,8 +93,11 @@
+ #define __NR_ftruncate 130
+ #define __NR_ftruncate64 84
+ #define __NR_futex 142
++#define __NR_futex_requeue 456
+ #define __NR_futex_time64 422
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 288
+ #define __NR_get_kernel_syms 223
+ #define __NR_get_mempolicy 304
+@@ -175,6 +178,7 @@
+ #define __NR_lstat 40
+ #define __NR_lstat64 132
+ #define __NR_madvise 75
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 303
+ #define __NR_membarrier 351
+ #define __NR_memfd_create 348
+diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
+index d25ccfb571..129ce50646 100644
+--- a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
+@@ -84,7 +84,10 @@
+ #define __NR_fsync 95
+ #define __NR_ftruncate 130
+ #define __NR_futex 142
++#define __NR_futex_requeue 456
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 288
+ #define __NR_get_kernel_syms 223
+ #define __NR_get_mempolicy 304
+@@ -158,6 +161,7 @@
+ #define __NR_lstat 40
+ #define __NR_lstat64 132
+ #define __NR_madvise 75
++#define __NR_map_shadow_stack 453
+ #define __NR_mbind 303
+ #define __NR_membarrier 351
+ #define __NR_memfd_create 348
+diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
+index c039d5c37f..aac065e7b3 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 6.6.
+-kernel 6.6
++# The list of system calls is current as of Linux 6.7.
++kernel 6.7
+ 
+ FAST_atomic_update
+ FAST_cmpxchg
+@@ -147,8 +147,11 @@ ftime
+ ftruncate
+ ftruncate64
+ futex
++futex_requeue
+ futex_time64
++futex_wait
+ futex_waitv
++futex_wake
+ futimesat
+ get_kernel_syms
+ get_mempolicy
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
+index 5e4c9e901c..4fa5b942c5 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
+@@ -80,7 +80,10 @@
+ #define __NR_fsync 74
+ #define __NR_ftruncate 77
+ #define __NR_futex 202
++#define __NR_futex_requeue 456
++#define __NR_futex_wait 455
+ #define __NR_futex_waitv 449
++#define __NR_futex_wake 454
+ #define __NR_futimesat 261
+ #define __NR_get_kernel_syms 177
+ #define __NR_get_mempolicy 239
+diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
+index dd5e196272..b9db8bc5be 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
+@@ -76,7 +76,10 @@
+ #define __NR_fsync 1073741898
+ #define __NR_ftruncate 1073741901
+ #define __NR_futex 1073742026
++#define __NR_futex_requeue 1073742280
++#define __NR_futex_wait 1073742279
+ #define __NR_futex_waitv 1073742273
++#define __NR_futex_wake 1073742278
+ #define __NR_futimesat 1073742085
+ #define __NR_get_mempolicy 1073742063
+ #define __NR_get_robust_list 1073742355
diff --git a/SOURCES/glibc-RHEL-39000-2.patch b/SOURCES/glibc-RHEL-39000-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2ed92f7e299f75cf0802e75fafd79fed45e46cfa
--- /dev/null
+++ b/SOURCES/glibc-RHEL-39000-2.patch
@@ -0,0 +1,756 @@
+commit 3de2f8755c6c036dcd0b1f4acd6bcdefe0e775c0
+Author: Joseph Myers <josmyers@redhat.com>
+Date:   Wed Mar 13 13:57:56 2024 +0000
+
+    Update syscall lists for Linux 6.8
+    
+    Linux 6.8 adds five new syscalls.  Update syscall-names.list and
+    regenerate the arch-syscall.h headers with build-many-glibcs.py
+    update-syscalls.
+    
+    Tested with build-many-glibcs.py.
+
+    Modified for RHEL by: Patsy Griffin <patsy@redhat.com>
+
+diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
+index 1713897f85..7ee8a2167a 100644
+--- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
+@@ -122,12 +122,16 @@
+ #define __NR_lgetxattr 9
+ #define __NR_linkat 37
+ #define __NR_listen 201
++#define __NR_listmount 458
+ #define __NR_listxattr 11
+ #define __NR_llistxattr 12
+ #define __NR_lookup_dcookie 18
+ #define __NR_lremovexattr 15
+ #define __NR_lseek 62
+ #define __NR_lsetxattr 6
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_madvise 233
+ #define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+@@ -276,6 +280,7 @@
+ #define __NR_socketpair 199
+ #define __NR_splice 76
+ #define __NR_statfs 43
++#define __NR_statmount 457
+ #define __NR_statx 291
+ #define __NR_swapoff 225
+ #define __NR_swapon 224
+diff --git a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
+index 5457d2d8ae..0f4ea7670b 100644
+--- a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
+@@ -150,12 +150,16 @@
+ #define __NR_link 9
+ #define __NR_linkat 458
+ #define __NR_listen 106
++#define __NR_listmount 568
+ #define __NR_listxattr 388
+ #define __NR_llistxattr 389
+ #define __NR_lookup_dcookie 406
+ #define __NR_lremovexattr 392
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 383
++#define __NR_lsm_get_self_attr 569
++#define __NR_lsm_list_modules 571
++#define __NR_lsm_set_self_attr 570
+ #define __NR_lstat 68
+ #define __NR_lstat64 426
+ #define __NR_madvise 75
+@@ -441,6 +445,7 @@
+ #define __NR_stat64 425
+ #define __NR_statfs 328
+ #define __NR_statfs64 528
++#define __NR_statmount 567
+ #define __NR_statx 522
+ #define __NR_swapoff 304
+ #define __NR_swapon 322
+diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
+index a66471c83a..90359482a8 100644
+--- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
+@@ -126,12 +126,16 @@
+ #define __NR_lgetxattr 9
+ #define __NR_linkat 37
+ #define __NR_listen 201
++#define __NR_listmount 458
+ #define __NR_listxattr 11
+ #define __NR_llistxattr 12
+ #define __NR_llseek 62
+ #define __NR_lookup_dcookie 18
+ #define __NR_lremovexattr 15
+ #define __NR_lsetxattr 6
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_madvise 233
+ #define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+@@ -278,6 +282,7 @@
+ #define __NR_socketpair 199
+ #define __NR_splice 76
+ #define __NR_statfs64 43
++#define __NR_statmount 457
+ #define __NR_statx 291
+ #define __NR_swapoff 225
+ #define __NR_swapon 224
+diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
+index 74a57f4520..4930167a03 100644
+--- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
+@@ -164,12 +164,16 @@
+ #define __NR_link 9
+ #define __NR_linkat 330
+ #define __NR_listen 284
++#define __NR_listmount 458
+ #define __NR_listxattr 232
+ #define __NR_llistxattr 233
+ #define __NR_lookup_dcookie 249
+ #define __NR_lremovexattr 236
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 227
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 220
+@@ -361,6 +365,7 @@
+ #define __NR_stat64 195
+ #define __NR_statfs 99
+ #define __NR_statfs64 266
++#define __NR_statmount 457
+ #define __NR_statx 397
+ #define __NR_swapoff 115
+ #define __NR_swapon 87
+diff --git a/sysdeps/unix/sysv/linux/csky/arch-syscall.h b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
+index ba7632e018..3f16a29f57 100644
+--- a/sysdeps/unix/sysv/linux/csky/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
+@@ -131,12 +131,16 @@
+ #define __NR_lgetxattr 9
+ #define __NR_linkat 37
+ #define __NR_listen 201
++#define __NR_listmount 458
+ #define __NR_listxattr 11
+ #define __NR_llistxattr 12
+ #define __NR_llseek 62
+ #define __NR_lookup_dcookie 18
+ #define __NR_lremovexattr 15
+ #define __NR_lsetxattr 6
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_madvise 233
+ #define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+@@ -291,6 +295,7 @@
+ #define __NR_socketpair 199
+ #define __NR_splice 76
+ #define __NR_statfs64 43
++#define __NR_statmount 457
+ #define __NR_statx 291
+ #define __NR_swapoff 225
+ #define __NR_swapon 224
+diff --git a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
+index 483706de9b..a1b2c819d6 100644
+--- a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
+@@ -155,12 +155,16 @@
+ #define __NR_link 9
+ #define __NR_linkat 283
+ #define __NR_listen 32
++#define __NR_listmount 458
+ #define __NR_listxattr 244
+ #define __NR_llistxattr 245
+ #define __NR_lookup_dcookie 223
+ #define __NR_lremovexattr 248
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 239
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 84
+ #define __NR_lstat64 198
+ #define __NR_madvise 119
+@@ -339,6 +343,7 @@
+ #define __NR_stat64 101
+ #define __NR_statfs 99
+ #define __NR_statfs64 298
++#define __NR_statmount 457
+ #define __NR_statx 349
+ #define __NR_stime 25
+ #define __NR_swapoff 115
+diff --git a/sysdeps/unix/sysv/linux/i386/arch-syscall.h b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
+index 21c1308bb3..cc775432d6 100644
+--- a/sysdeps/unix/sysv/linux/i386/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
+@@ -176,6 +176,7 @@
+ #define __NR_link 9
+ #define __NR_linkat 303
+ #define __NR_listen 363
++#define __NR_listmount 458
+ #define __NR_listxattr 232
+ #define __NR_llistxattr 233
+ #define __NR_lock 53
+@@ -183,6 +184,9 @@
+ #define __NR_lremovexattr 236
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 227
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 219
+@@ -386,6 +390,7 @@
+ #define __NR_stat64 195
+ #define __NR_statfs 99
+ #define __NR_statfs64 268
++#define __NR_statmount 457
+ #define __NR_statx 383
+ #define __NR_stime 25
+ #define __NR_stty 31
+diff --git a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
+index 6d788e3440..79f277dd5b 100644
+--- a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
+@@ -171,12 +171,16 @@
+ #define __NR_link 9
+ #define __NR_linkat 296
+ #define __NR_listen 360
++#define __NR_listmount 458
+ #define __NR_listxattr 229
+ #define __NR_llistxattr 230
+ #define __NR_lookup_dcookie 248
+ #define __NR_lremovexattr 233
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 224
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 238
+@@ -373,6 +377,7 @@
+ #define __NR_stat64 195
+ #define __NR_statfs 99
+ #define __NR_statfs64 263
++#define __NR_statmount 457
+ #define __NR_statx 379
+ #define __NR_stime 25
+ #define __NR_swapoff 115
+diff --git a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
+index 91e1630f7b..779d5d5d70 100644
+--- a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
+@@ -176,6 +176,7 @@
+ #define __NR_link 9
+ #define __NR_linkat 303
+ #define __NR_listen 348
++#define __NR_listmount 458
+ #define __NR_listxattr 232
+ #define __NR_llistxattr 233
+ #define __NR_lock 53
+@@ -183,6 +184,9 @@
+ #define __NR_lremovexattr 236
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 227
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 219
+@@ -389,6 +393,7 @@
+ #define __NR_stat64 195
+ #define __NR_statfs 99
+ #define __NR_statfs64 268
++#define __NR_statmount 457
+ #define __NR_statx 398
+ #define __NR_stime 25
+ #define __NR_stty 31
+diff --git a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
+index d75af97467..86ffd5ce84 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
+@@ -166,6 +166,7 @@
+ #define __NR_link 4009
+ #define __NR_linkat 4296
+ #define __NR_listen 4174
++#define __NR_listmount 4458
+ #define __NR_listxattr 4230
+ #define __NR_llistxattr 4231
+ #define __NR_lock 4053
+@@ -173,6 +174,9 @@
+ #define __NR_lremovexattr 4234
+ #define __NR_lseek 4019
+ #define __NR_lsetxattr 4225
++#define __NR_lsm_get_self_attr 4459
++#define __NR_lsm_list_modules 4461
++#define __NR_lsm_set_self_attr 4460
+ #define __NR_lstat 4107
+ #define __NR_lstat64 4214
+ #define __NR_madvise 4218
+@@ -362,6 +366,7 @@
+ #define __NR_stat64 4213
+ #define __NR_statfs 4099
+ #define __NR_statfs64 4255
++#define __NR_statmount 4457
+ #define __NR_statx 4366
+ #define __NR_stime 4025
+ #define __NR_stty 4031
+diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
+index 05bf7d251d..5d37a686e5 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
+@@ -154,12 +154,16 @@
+ #define __NR_link 6084
+ #define __NR_linkat 6259
+ #define __NR_listen 6049
++#define __NR_listmount 6458
+ #define __NR_listxattr 6186
+ #define __NR_llistxattr 6187
+ #define __NR_lookup_dcookie 6206
+ #define __NR_lremovexattr 6190
+ #define __NR_lseek 6008
+ #define __NR_lsetxattr 6181
++#define __NR_lsm_get_self_attr 6459
++#define __NR_lsm_list_modules 6461
++#define __NR_lsm_set_self_attr 6460
+ #define __NR_lstat 6006
+ #define __NR_madvise 6027
+ #define __NR_map_shadow_stack 6453
+@@ -332,6 +336,7 @@
+ #define __NR_stat 6004
+ #define __NR_statfs 6134
+ #define __NR_statfs64 6217
++#define __NR_statmount 6457
+ #define __NR_statx 6330
+ #define __NR_swapoff 6163
+ #define __NR_swapon 6162
+diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
+index 41ffaf3255..9b1e846e76 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
+@@ -145,12 +145,16 @@
+ #define __NR_link 5084
+ #define __NR_linkat 5255
+ #define __NR_listen 5049
++#define __NR_listmount 5458
+ #define __NR_listxattr 5186
+ #define __NR_llistxattr 5187
+ #define __NR_lookup_dcookie 5206
+ #define __NR_lremovexattr 5190
+ #define __NR_lseek 5008
+ #define __NR_lsetxattr 5181
++#define __NR_lsm_get_self_attr 5459
++#define __NR_lsm_list_modules 5461
++#define __NR_lsm_set_self_attr 5460
+ #define __NR_lstat 5006
+ #define __NR_madvise 5027
+ #define __NR_map_shadow_stack 5453
+@@ -313,6 +317,7 @@
+ #define __NR_splice 5263
+ #define __NR_stat 5004
+ #define __NR_statfs 5134
++#define __NR_statmount 5457
+ #define __NR_statx 5326
+ #define __NR_swapoff 5163
+ #define __NR_swapon 5162
+diff --git a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
+index d94e7e9ee9..abbc9ab6b0 100644
+--- a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
+@@ -130,12 +130,16 @@
+ #define __NR_lgetxattr 9
+ #define __NR_linkat 37
+ #define __NR_listen 201
++#define __NR_listmount 458
+ #define __NR_listxattr 11
+ #define __NR_llistxattr 12
+ #define __NR_llseek 62
+ #define __NR_lookup_dcookie 18
+ #define __NR_lremovexattr 15
+ #define __NR_lsetxattr 6
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_madvise 233
+ #define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+@@ -290,6 +294,7 @@
+ #define __NR_socketpair 199
+ #define __NR_splice 76
+ #define __NR_statfs64 43
++#define __NR_statmount 457
+ #define __NR_statx 291
+ #define __NR_swapoff 225
+ #define __NR_swapon 224
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
+index b5522e8889..af0d2b121e 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
+@@ -166,6 +166,7 @@
+ #define __NR_link 9
+ #define __NR_linkat 294
+ #define __NR_listen 329
++#define __NR_listmount 458
+ #define __NR_listxattr 215
+ #define __NR_llistxattr 216
+ #define __NR_lock 53
+@@ -173,6 +174,9 @@
+ #define __NR_lremovexattr 219
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 210
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 205
+@@ -374,6 +378,7 @@
+ #define __NR_stat64 195
+ #define __NR_statfs 99
+ #define __NR_statfs64 252
++#define __NR_statmount 457
+ #define __NR_statx 383
+ #define __NR_stime 25
+ #define __NR_stty 31
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
+index 162d782ae6..a4c70aa7fe 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
+@@ -154,6 +154,7 @@
+ #define __NR_link 9
+ #define __NR_linkat 294
+ #define __NR_listen 329
++#define __NR_listmount 458
+ #define __NR_listxattr 215
+ #define __NR_llistxattr 216
+ #define __NR_lock 53
+@@ -161,6 +162,9 @@
+ #define __NR_lremovexattr 219
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 210
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 107
+ #define __NR_madvise 205
+ #define __NR_map_shadow_stack 453
+@@ -352,6 +356,7 @@
+ #define __NR_stat 106
+ #define __NR_statfs 99
+ #define __NR_statfs64 252
++#define __NR_statmount 457
+ #define __NR_statx 383
+ #define __NR_stime 25
+ #define __NR_stty 31
+diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
+index 013222e5de..7315d164d6 100644
+--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
+@@ -117,12 +117,16 @@
+ #define __NR_lgetxattr 9
+ #define __NR_linkat 37
+ #define __NR_listen 201
++#define __NR_listmount 458
+ #define __NR_listxattr 11
+ #define __NR_llistxattr 12
+ #define __NR_llseek 62
+ #define __NR_lookup_dcookie 18
+ #define __NR_lremovexattr 15
+ #define __NR_lsetxattr 6
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_madvise 233
+ #define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+@@ -268,6 +272,7 @@
+ #define __NR_socketpair 199
+ #define __NR_splice 76
+ #define __NR_statfs64 43
++#define __NR_statmount 457
+ #define __NR_statx 291
+ #define __NR_swapoff 225
+ #define __NR_swapon 224
+diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
+index d03dad8200..31a1130db9 100644
+--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
+@@ -122,12 +122,16 @@
+ #define __NR_lgetxattr 9
+ #define __NR_linkat 37
+ #define __NR_listen 201
++#define __NR_listmount 458
+ #define __NR_listxattr 11
+ #define __NR_llistxattr 12
+ #define __NR_lookup_dcookie 18
+ #define __NR_lremovexattr 15
+ #define __NR_lseek 62
+ #define __NR_lsetxattr 6
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_madvise 233
+ #define __NR_map_shadow_stack 453
+ #define __NR_mbind 235
+@@ -277,6 +281,7 @@
+ #define __NR_socketpair 199
+ #define __NR_splice 76
+ #define __NR_statfs 43
++#define __NR_statmount 457
+ #define __NR_statx 291
+ #define __NR_swapoff 225
+ #define __NR_swapon 224
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
+index 98e6b68b31..cf8569304d 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
+@@ -171,12 +171,16 @@
+ #define __NR_link 9
+ #define __NR_linkat 296
+ #define __NR_listen 363
++#define __NR_listmount 458
+ #define __NR_listxattr 230
+ #define __NR_llistxattr 231
+ #define __NR_lookup_dcookie 110
+ #define __NR_lremovexattr 234
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 225
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 219
+@@ -372,6 +376,7 @@
+ #define __NR_stat64 195
+ #define __NR_statfs 99
+ #define __NR_statfs64 265
++#define __NR_statmount 457
+ #define __NR_statx 379
+ #define __NR_stime 25
+ #define __NR_swapoff 115
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
+index 951fbd7c97..f3536ed03f 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
+@@ -146,12 +146,16 @@
+ #define __NR_link 9
+ #define __NR_linkat 296
+ #define __NR_listen 363
++#define __NR_listmount 458
+ #define __NR_listxattr 230
+ #define __NR_llistxattr 231
+ #define __NR_lookup_dcookie 110
+ #define __NR_lremovexattr 234
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 225
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 107
+ #define __NR_madvise 219
+ #define __NR_map_shadow_stack 453
+@@ -329,6 +333,7 @@
+ #define __NR_stat 106
+ #define __NR_statfs 99
+ #define __NR_statfs64 265
++#define __NR_statmount 457
+ #define __NR_statx 379
+ #define __NR_swapoff 115
+ #define __NR_swapon 87
+diff --git a/sysdeps/unix/sysv/linux/sh/arch-syscall.h b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
+index 6b4418bcae..0c88bf10c7 100644
+--- a/sysdeps/unix/sysv/linux/sh/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
+@@ -164,12 +164,16 @@
+ #define __NR_link 9
+ #define __NR_linkat 303
+ #define __NR_listen 343
++#define __NR_listmount 458
+ #define __NR_listxattr 232
+ #define __NR_llistxattr 233
+ #define __NR_lookup_dcookie 253
+ #define __NR_lremovexattr 236
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 227
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 107
+ #define __NR_lstat64 196
+ #define __NR_madvise 219
+@@ -365,6 +369,7 @@
+ #define __NR_stat64 195
+ #define __NR_statfs 99
+ #define __NR_statfs64 268
++#define __NR_statmount 457
+ #define __NR_statx 383
+ #define __NR_stime 25
+ #define __NR_swapoff 115
+diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
+index 4f9460b1a3..19fa614624 100644
+--- a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
+@@ -169,12 +169,16 @@
+ #define __NR_link 9
+ #define __NR_linkat 292
+ #define __NR_listen 354
++#define __NR_listmount 458
+ #define __NR_listxattr 178
+ #define __NR_llistxattr 179
+ #define __NR_lookup_dcookie 208
+ #define __NR_lremovexattr 182
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 170
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 40
+ #define __NR_lstat64 132
+ #define __NR_madvise 75
+@@ -370,6 +374,7 @@
+ #define __NR_stat64 139
+ #define __NR_statfs 157
+ #define __NR_statfs64 234
++#define __NR_statmount 457
+ #define __NR_statx 360
+ #define __NR_stime 233
+ #define __NR_swapoff 213
+diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
+index 129ce50646..18516f20cb 100644
+--- a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
+@@ -152,12 +152,16 @@
+ #define __NR_link 9
+ #define __NR_linkat 292
+ #define __NR_listen 354
++#define __NR_listmount 458
+ #define __NR_listxattr 178
+ #define __NR_llistxattr 179
+ #define __NR_lookup_dcookie 208
+ #define __NR_lremovexattr 182
+ #define __NR_lseek 19
+ #define __NR_lsetxattr 170
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 40
+ #define __NR_lstat64 132
+ #define __NR_madvise 75
+@@ -339,6 +343,7 @@
+ #define __NR_stat64 139
+ #define __NR_statfs 157
+ #define __NR_statfs64 234
++#define __NR_statmount 457
+ #define __NR_statx 360
+ #define __NR_stime 233
+ #define __NR_swapoff 213
+diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
+index aac065e7b3..6557bcfde4 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 6.7.
+-kernel 6.7
++# The list of system calls is current as of Linux 6.8.
++kernel 6.8
+ 
+ FAST_atomic_update
+ FAST_cmpxchg
+@@ -239,6 +239,7 @@ lgetxattr
+ link
+ linkat
+ listen
++listmount
+ listxattr
+ llistxattr
+ llseek
+@@ -247,6 +248,9 @@ lookup_dcookie
+ lremovexattr
+ lseek
+ lsetxattr
++lsm_get_self_attr
++lsm_list_modules
++lsm_set_self_attr
+ lstat
+ lstat64
+ madvise
+@@ -593,6 +597,7 @@ stat
+ stat64
+ statfs
+ statfs64
++statmount
+ statx
+ stime
+ stty
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
+index 4fa5b942c5..b122216013 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
+@@ -149,12 +149,16 @@
+ #define __NR_link 86
+ #define __NR_linkat 265
+ #define __NR_listen 50
++#define __NR_listmount 458
+ #define __NR_listxattr 194
+ #define __NR_llistxattr 195
+ #define __NR_lookup_dcookie 212
+ #define __NR_lremovexattr 198
+ #define __NR_lseek 8
+ #define __NR_lsetxattr 189
++#define __NR_lsm_get_self_attr 459
++#define __NR_lsm_list_modules 461
++#define __NR_lsm_set_self_attr 460
+ #define __NR_lstat 6
+ #define __NR_madvise 28
+ #define __NR_map_shadow_stack 453
+@@ -321,6 +325,7 @@
+ #define __NR_splice 275
+ #define __NR_stat 4
+ #define __NR_statfs 137
++#define __NR_statmount 457
+ #define __NR_statx 332
+ #define __NR_swapoff 168
+ #define __NR_swapon 167
+diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
+index b9db8bc5be..3040a47d72 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
++++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
+@@ -143,12 +143,16 @@
+ #define __NR_link 1073741910
+ #define __NR_linkat 1073742089
+ #define __NR_listen 1073741874
++#define __NR_listmount 1073742282
+ #define __NR_listxattr 1073742018
+ #define __NR_llistxattr 1073742019
+ #define __NR_lookup_dcookie 1073742036
+ #define __NR_lremovexattr 1073742022
+ #define __NR_lseek 1073741832
+ #define __NR_lsetxattr 1073742013
++#define __NR_lsm_get_self_attr 1073742283
++#define __NR_lsm_list_modules 1073742285
++#define __NR_lsm_set_self_attr 1073742284
+ #define __NR_lstat 1073741830
+ #define __NR_madvise 1073741852
+ #define __NR_mbind 1073742061
+@@ -312,6 +316,7 @@
+ #define __NR_splice 1073742099
+ #define __NR_stat 1073741828
+ #define __NR_statfs 1073741961
++#define __NR_statmount 1073742281
+ #define __NR_statx 1073742156
+ #define __NR_swapoff 1073741992
+ #define __NR_swapon 1073741991
diff --git a/SOURCES/glibc-RHEL-39000-3.patch b/SOURCES/glibc-RHEL-39000-3.patch
new file mode 100644
index 0000000000000000000000000000000000000000..e2d2a8318d9a3f957f2f7d71742658cdfb44106e
--- /dev/null
+++ b/SOURCES/glibc-RHEL-39000-3.patch
@@ -0,0 +1,28 @@
+commit cf0ca8d52e1653d4aa4311a4649af8dc541ce6b4
+Author: Joseph Myers <josmyers@redhat.com>
+Date:   Mon May 20 13:10:31 2024 +0000
+
+    Update syscall lists for Linux 6.9
+    
+    Linux 6.9 has no new syscalls.  Update the version number in
+    syscall-names.list to reflect that it is still current for 6.9.
+    
+    Tested with build-many-glibcs.py.
+
+    Modified for RHEL by: Patsy Griffin <patsy@redhat.com>
+
+diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
+index 6557bcfde4..672d39eaad 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 6.8.
+-kernel 6.8
++# The list of system calls is current as of Linux 6.9.
++kernel 6.9
+ 
+ FAST_atomic_update
+ FAST_cmpxchg
diff --git a/SOURCES/glibc-RHEL-39006.patch b/SOURCES/glibc-RHEL-39006.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1d159efa91b59b5a00d20e424f6d0b4a725e3a87
--- /dev/null
+++ b/SOURCES/glibc-RHEL-39006.patch
@@ -0,0 +1,26 @@
+From cb8c78b2ffa0b77ae453b2d328d7e2fe5186ef2a Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Tue, 31 Oct 2023 13:32:35 -0300
+Subject: linux: Add MMAP_ABOVE4G from Linux 6.6 to sys/mman.h
+
+x86 added the flag (29f890d1050fc099f) for CET enabled.
+
+Also update tst-mman-consts.py test.
+
+Conflicts:
+	sysdeps/unix/sysv/linux/tst-mman-consts.py
+	  (removed patch to keep alerting about kernel differences)
+	sysdeps/unix/sysv/linux/x86/bits/mman.h
+	  (adapted to missing __USE_MISC conditional upstream)
+
+diff -rup a/sysdeps/unix/sysv/linux/x86/bits/mman.h b/sysdeps/unix/sysv/linux/x86/bits/mman.h
+--- a/sysdeps/unix/sysv/linux/x86/bits/mman.h	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/x86/bits/mman.h	2024-05-29 14:03:12.426182715 -0400
+@@ -26,6 +26,7 @@
+ /* Other flags.  */
+ #ifdef __USE_MISC
+ # define MAP_32BIT	0x40		/* Only give out 32-bit addresses.  */
++# define MAP_ABOVE4G	0x80		/* Only map above 4GB.  */
+ #endif
+ 
+ #include <bits/mman-map-flags-generic.h>
diff --git a/SOURCES/glibc-RHEL-39992-1.patch b/SOURCES/glibc-RHEL-39992-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..040a499311723a4717029250d7c80379f96246f0
--- /dev/null
+++ b/SOURCES/glibc-RHEL-39992-1.patch
@@ -0,0 +1,43 @@
+commit afe42e935b3ee97bac9a7064157587777259c60e
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Mon Jun 3 10:49:40 2024 +0200
+
+    elf: Avoid some free (NULL) calls in _dl_update_slotinfo
+    
+    This has been confirmed to work around some interposed mallocs.  Here
+    is a discussion of the impact test ust/libc-wrapper/test_libc-wrapper
+    in lttng-tools:
+    
+      New TLS usage in libgcc_s.so.1, compatibility impact
+      <https://inbox.sourceware.org/libc-alpha/8734v1ieke.fsf@oldenburg.str.redhat.com/>
+    
+    Reportedly, this patch also papers over a similar issue when tcmalloc
+    2.9.1 is not compiled with -ftls-model=initial-exec.  Of course the
+    goal really should be to compile mallocs with the initial-exec TLS
+    model, but this commit appears to be a useful interim workaround.
+    
+    Fixes commit d2123d68275acc0f061e73d5f86ca504e0d5a344 ("elf: Fix slow
+    tls access after dlopen [BZ #19924]").
+    
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+diff --git a/elf/dl-tls.c b/elf/dl-tls.c
+index 7b3dd9ab60..670dbc42fc 100644
+--- a/elf/dl-tls.c
++++ b/elf/dl-tls.c
+@@ -819,7 +819,14 @@ _dl_update_slotinfo (unsigned long int req_modid, size_t new_gen)
+ 		 dtv entry free it.  Note: this is not AS-safe.  */
+ 	      /* XXX Ideally we will at some point create a memory
+ 		 pool.  */
+-	      free (dtv[modid].pointer.to_free);
++	      /* Avoid calling free on a null pointer.  Some mallocs
++		 incorrectly use dynamic TLS, and depending on how the
++		 free function was compiled, it could call
++		 __tls_get_addr before the null pointer check in the
++		 free implementation.  Checking here papers over at
++		 least some dynamic TLS usage by interposed mallocs.  */
++	      if (dtv[modid].pointer.to_free != NULL)
++		free (dtv[modid].pointer.to_free);
+ 	      dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
+ 	      dtv[modid].pointer.to_free = NULL;
+ 
diff --git a/SOURCES/glibc-RHEL-39992-2.patch b/SOURCES/glibc-RHEL-39992-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..df021c9174399db901ed93bb462ab62b127e8829
--- /dev/null
+++ b/SOURCES/glibc-RHEL-39992-2.patch
@@ -0,0 +1,499 @@
+commit 018f0fc3b818d4d1460a4e2384c24802504b1d20
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Mon Jul 1 17:42:04 2024 +0200
+
+    elf: Support recursive use of dynamic TLS in interposed malloc
+    
+    It turns out that quite a few applications use bundled mallocs that
+    have been built to use global-dynamic TLS (instead of the recommended
+    initial-exec TLS).  The previous workaround from
+    commit afe42e935b3ee97bac9a7064157587777259c60e ("elf: Avoid some
+    free (NULL) calls in _dl_update_slotinfo") does not fix all
+    encountered cases unfortunatelly.
+    
+    This change avoids the TLS generation update for recursive use
+    of TLS from a malloc that was called during a TLS update.  This
+    is possible because an interposed malloc has a fixed module ID and
+    TLS slot.  (It cannot be unloaded.)  If an initially-loaded module ID
+    is encountered in __tls_get_addr and the dynamic linker is already
+    in the middle of a TLS update, use the outdated DTV, thus avoiding
+    another call into malloc.  It's still necessary to update the
+    DTV to the most recent generation, to get out of the slow path,
+    which is why the check for recursion is needed.
+    
+    The bookkeeping is done using a global counter instead of per-thread
+    flag because TLS access in the dynamic linker is tricky.
+    
+    All this will go away once the dynamic linker stops using malloc
+    for TLS, likely as part of a change that pre-allocates all TLS
+    during pthread_create/dlopen.
+    
+    Fixes commit d2123d68275acc0f061e73d5f86ca504e0d5a344 ("elf: Fix slow
+    tls access after dlopen [BZ #19924]").
+    
+    Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+    Reworked for RHEL by: Patsy Griffin <patsy@redhat.com>
+
+diff -Nrup a/elf/Makefile b/elf/Makefile
+--- a/elf/Makefile	2024-07-09 22:06:30.237752048 -0400
++++ b/elf/Makefile	2024-07-10 14:09:02.996759220 -0400
+@@ -423,6 +423,7 @@ tests += \
+   tst-nodeps2 \
+   tst-noload \
+   tst-null-argv \
++  tst-recursive-tls \
+   tst-relsort1 \
+   tst-ro-dynamic \
+   tst-rtld-run-static \
+@@ -783,6 +784,23 @@ modules-names = \
+   tst-nodeps1-mod \
+   tst-nodeps2-mod \
+   tst-null-argv-lib \
++  tst-recursive-tlsmallocmod \
++  tst-recursive-tlsmod0 \
++  tst-recursive-tlsmod1 \
++  tst-recursive-tlsmod2 \
++  tst-recursive-tlsmod3 \
++  tst-recursive-tlsmod4 \
++  tst-recursive-tlsmod5 \
++  tst-recursive-tlsmod6 \
++  tst-recursive-tlsmod7 \
++  tst-recursive-tlsmod8 \
++  tst-recursive-tlsmod9 \
++  tst-recursive-tlsmod10 \
++  tst-recursive-tlsmod11 \
++  tst-recursive-tlsmod12 \
++  tst-recursive-tlsmod13 \
++  tst-recursive-tlsmod14 \
++  tst-recursive-tlsmod15 \
+   tst-relsort1mod1 \
+   tst-relsort1mod2 \
+   tst-ro-dynamic-mod \
+@@ -2725,3 +2743,11 @@ CFLAGS-tst-tlsgap-mod0.c += -mtls-dialec
+ CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=gnu2
+ CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2
+ endif
++
++$(objpfx)tst-recursive-tls: $(objpfx)tst-recursive-tlsmallocmod.so
++# More objects than DTV_SURPLUS, to trigger DTV reallocation.
++$(objpfx)tst-recursive-tls.out: \
++  $(patsubst %,$(objpfx)tst-recursive-tlsmod%.so, \
++    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
++$(objpfx)tst-recursive-tlsmod%.os: tst-recursive-tlsmodN.c
++	$(compile-command.c) -DVAR=thread_$* -DFUNC=get_threadvar_$*
+diff --git a/elf/dl-tls.c b/elf/dl-tls.c
+index 670dbc42fc..3d221273f1 100644
+--- a/elf/dl-tls.c
++++ b/elf/dl-tls.c
+@@ -75,6 +75,31 @@
+ /* Default for dl_tls_static_optional.  */
+ #define OPTIONAL_TLS 512
+ 
++/* Used to count the number of threads currently executing dynamic TLS
++   updates.  Used to avoid recursive malloc calls in __tls_get_addr
++   for an interposed malloc that uses global-dynamic TLS (which is not
++   recommended); see _dl_tls_allocate_active checks.  This could be a
++   per-thread flag, but would need TLS access in the dynamic linker.  */
++unsigned int _dl_tls_threads_in_update;
++
++static inline void
++_dl_tls_allocate_begin (void)
++{
++  atomic_fetch_add_relaxed (&_dl_tls_threads_in_update, 1);
++}
++
++static inline void
++_dl_tls_allocate_end (void)
++{
++  atomic_fetch_add_relaxed (&_dl_tls_threads_in_update, -1);
++}
++
++static inline bool
++_dl_tls_allocate_active (void)
++{
++  return atomic_load_relaxed (&_dl_tls_threads_in_update) > 0;
++}
++
+ /* Compute the static TLS surplus based on the namespace count and the
+    TLS space that can be used for optimizations.  */
+ static inline int
+@@ -425,12 +450,18 @@ _dl_allocate_tls_storage (void)
+   size += TLS_PRE_TCB_SIZE;
+ #endif
+ 
+-  /* Perform the allocation.  Reserve space for the required alignment
+-     and the pointer to the original allocation.  */
++  /* Reserve space for the required alignment and the pointer to the
++     original allocation.  */
+   size_t alignment = GLRO (dl_tls_static_align);
++
++  /* Perform the allocation.  */
++  _dl_tls_allocate_begin ();
+   void *allocated = malloc (size + alignment + sizeof (void *));
+   if (__glibc_unlikely (allocated == NULL))
+-    return NULL;
++    {
++      _dl_tls_allocate_end ();
++      return NULL;
++    }
+ 
+   /* Perform alignment and allocate the DTV.  */
+ #if TLS_TCB_AT_TP
+@@ -466,6 +497,8 @@ _dl_allocate_tls_storage (void)
+   result = allocate_dtv (result);
+   if (result == NULL)
+     free (allocated);
++
++  _dl_tls_allocate_end ();
+   return result;
+ }
+ 
+@@ -483,6 +516,7 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
+   size_t newsize = max_modid + DTV_SURPLUS;
+   size_t oldsize = dtv[-1].counter;
+ 
++  _dl_tls_allocate_begin ();
+   if (dtv == GL(dl_initial_dtv))
+     {
+       /* This is the initial dtv that was either statically allocated in
+@@ -502,6 +536,7 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
+       if (newp == NULL)
+ 	oom ();
+     }
++  _dl_tls_allocate_end ();
+ 
+   newp[0].counter = newsize;
+ 
+@@ -676,7 +711,9 @@ allocate_dtv_entry (size_t alignment, size_t size)
+   if (powerof2 (alignment) && alignment <= _Alignof (max_align_t))
+     {
+       /* The alignment is supported by malloc.  */
++      _dl_tls_allocate_begin ();
+       void *ptr = malloc (size);
++      _dl_tls_allocate_end ();
+       return (struct dtv_pointer) { ptr, ptr };
+     }
+ 
+@@ -688,7 +725,10 @@ allocate_dtv_entry (size_t alignment, size_t size)
+ 
+   /* Perform the allocation.  This is the pointer we need to free
+      later.  */
++  _dl_tls_allocate_begin ();
+   void *start = malloc (alloc_size);
++  _dl_tls_allocate_end ();
++
+   if (start == NULL)
+     return (struct dtv_pointer) {};
+ 
+@@ -826,7 +866,11 @@ _dl_update_slotinfo (unsigned long int req_modid, size_t new_gen)
+ 		 free implementation.  Checking here papers over at
+ 		 least some dynamic TLS usage by interposed mallocs.  */
+ 	      if (dtv[modid].pointer.to_free != NULL)
+-		free (dtv[modid].pointer.to_free);
++		{
++		  _dl_tls_allocate_begin ();
++		  free (dtv[modid].pointer.to_free);
++		  _dl_tls_allocate_end ();
++		}
+ 	      dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
+ 	      dtv[modid].pointer.to_free = NULL;
+ 
+@@ -956,10 +1000,22 @@ __tls_get_addr (GET_ADDR_ARGS)
+   size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
+   if (__glibc_unlikely (dtv[0].counter != gen))
+     {
+-      /* Update DTV up to the global generation, see CONCURRENCY NOTES
+-         in _dl_update_slotinfo.  */
+-      gen = atomic_load_acquire (&GL(dl_tls_generation));
+-      return update_get_addr (GET_ADDR_PARAM, gen);
++      if (_dl_tls_allocate_active ()
++	  && GET_ADDR_MODULE < _dl_tls_initial_modid_limit)
++	  /* This is a reentrant __tls_get_addr call, but we can
++	     satisfy it because it's an initially-loaded module ID.
++	     These TLS slotinfo slots do not change, so the
++	     out-of-date generation counter does not matter.  However,
++	     if not in a TLS update, still update_get_addr below, to
++	     get off the slow path eventually.  */
++	;
++      else
++	{
++	  /* Update DTV up to the global generation, see CONCURRENCY NOTES
++	     in _dl_update_slotinfo.  */
++	  gen = atomic_load_acquire (&GL(dl_tls_generation));
++	  return update_get_addr (GET_ADDR_PARAM, gen);
++	}
+     }
+ 
+   void *p = dtv[GET_ADDR_MODULE].pointer.val;
+@@ -969,7 +1025,7 @@ __tls_get_addr (GET_ADDR_ARGS)
+ 
+   return (char *) p + GET_ADDR_OFFSET;
+ }
+-#endif
++#endif /* SHARED */
+ 
+ 
+ /* Look up the module's TLS block as for __tls_get_addr,
+@@ -1018,6 +1074,25 @@ _dl_tls_get_addr_soft (struct link_map *l)
+   return data;
+ }
+ 
++size_t _dl_tls_initial_modid_limit;
++
++void
++_dl_tls_initial_modid_limit_setup (void)
++{
++  struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
++  size_t idx;
++  for (idx = 0; idx < listp->len; ++idx)
++    {
++      struct link_map *l = listp->slotinfo[idx].map;
++      if (l == NULL
++	  /* The object can be unloaded, so its modid can be
++	     reassociated.  */
++	  || !(l->l_type == lt_executable || l->l_type == lt_library))
++	break;
++    }
++  _dl_tls_initial_modid_limit = idx;
++}
++
+ 
+ void
+ _dl_add_to_slotinfo (struct link_map *l, bool do_add)
+@@ -1050,9 +1125,11 @@ _dl_add_to_slotinfo (struct link_map *l, bool do_add)
+ 	 the first slot.  */
+       assert (idx == 0);
+ 
++      _dl_tls_allocate_begin ();
+       listp = (struct dtv_slotinfo_list *)
+ 	malloc (sizeof (struct dtv_slotinfo_list)
+ 		+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
++      _dl_tls_allocate_end ();
+       if (listp == NULL)
+ 	{
+ 	  /* We ran out of memory while resizing the dtv slotinfo list.  */
+diff --git a/elf/rtld.c b/elf/rtld.c
+index e9525ea987..6352ba76c5 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -788,6 +788,8 @@ init_tls (size_t naudit)
+     _dl_fatal_printf ("\
+ cannot allocate TLS data structures for initial thread\n");
+ 
++  _dl_tls_initial_modid_limit_setup ();
++
+   /* Store for detection of the special case by __tls_get_addr
+      so it knows not to pass this dtv to the normal realloc.  */
+   GL(dl_initial_dtv) = GET_DTV (tcbp);
+diff --git a/elf/tst-recursive-tls.c b/elf/tst-recursive-tls.c
+new file mode 100644
+index 0000000000..716d1f783a
+--- /dev/null
++++ b/elf/tst-recursive-tls.c
+@@ -0,0 +1,60 @@
++/* Test with interposed malloc with dynamic TLS.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <array_length.h>
++#include <stdio.h>
++#include <support/check.h>
++#include <support/xdlfcn.h>
++
++/* Defined in tst-recursive-tlsmallocmod.so.  */
++extern __thread unsigned int malloc_subsytem_counter;
++
++static int
++do_test (void)
++{
++  /* 16 is large enough to exercise the DTV resizing case.  */
++  void *handles[16];
++
++  for (unsigned int i = 0; i < array_length (handles); ++i)
++    {
++      /* Re-use the TLS slot for module 0.  */
++      if (i > 0)
++        xdlclose (handles[0]);
++
++      char soname[30];
++      snprintf (soname, sizeof (soname), "tst-recursive-tlsmod%u.so", i);
++      handles[i] = xdlopen (soname, RTLD_NOW);
++
++      if (i > 0)
++        {
++          handles[0] = xdlopen ("tst-recursive-tlsmod0.so", RTLD_NOW);
++          int (*fptr) (void) = xdlsym (handles[0], "get_threadvar_0");
++          /* May trigger TLS storage allocation using malloc.  */
++          TEST_COMPARE (fptr (), 0);
++        }
++    }
++
++  for (unsigned int i = 0; i < array_length (handles); ++i)
++    xdlclose (handles[i]);
++
++  printf ("info: malloc subsystem calls: %u\n", malloc_subsytem_counter);
++  TEST_VERIFY (malloc_subsytem_counter > 0);
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/elf/tst-recursive-tlsmallocmod.c b/elf/tst-recursive-tlsmallocmod.c
+new file mode 100644
+index 0000000000..c24e9945d1
+--- /dev/null
++++ b/elf/tst-recursive-tlsmallocmod.c
+@@ -0,0 +1,64 @@
++/* Interposed malloc with dynamic TLS.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <stdlib.h>
++#include <dlfcn.h>
++
++__thread unsigned int malloc_subsytem_counter;
++
++static __typeof (malloc) *malloc_fptr;
++static __typeof (free) *free_fptr;
++static __typeof (calloc) *calloc_fptr;
++static __typeof (realloc) *realloc_fptr;
++
++static void __attribute__ ((constructor))
++init (void)
++{
++  malloc_fptr = dlsym (RTLD_NEXT, "malloc");
++  free_fptr = dlsym (RTLD_NEXT, "free");
++  calloc_fptr = dlsym (RTLD_NEXT, "calloc");
++  realloc_fptr = dlsym (RTLD_NEXT, "realloc");
++}
++
++void *
++malloc (size_t size)
++{
++  ++malloc_subsytem_counter;
++  return malloc_fptr (size);
++}
++
++void
++free (void *ptr)
++{
++  ++malloc_subsytem_counter;
++  return free_fptr (ptr);
++}
++
++void *
++calloc (size_t a, size_t b)
++{
++  ++malloc_subsytem_counter;
++  return calloc_fptr (a, b);
++}
++
++void *
++realloc (void *ptr, size_t size)
++{
++  ++malloc_subsytem_counter;
++  return realloc_fptr (ptr, size);
++}
+diff --git a/elf/tst-recursive-tlsmodN.c b/elf/tst-recursive-tlsmodN.c
+new file mode 100644
+index 0000000000..bb7592aee6
+--- /dev/null
++++ b/elf/tst-recursive-tlsmodN.c
+@@ -0,0 +1,28 @@
++/* Test module with global-dynamic TLS.  Used to trigger DTV reallocation.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++/* Compiled with VAR and FUNC set via -D.  FUNC requires some
++   relocation against TLS variable VAR.  */
++
++__thread int VAR;
++
++int
++FUNC (void)
++{
++  return VAR;
++}
+diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+index 50f58a60e3..656e8a3fa0 100644
+--- a/sysdeps/generic/ldsodefs.h
++++ b/sysdeps/generic/ldsodefs.h
+@@ -1256,6 +1256,20 @@ extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid,
+ 					     size_t gen)
+      attribute_hidden;
+ 
++/* The last TLS module ID that is initially loaded, plus 1.  TLS
++   addresses for modules with IDs lower than that can be obtained from
++   the DTV even if its generation is outdated.  */
++extern size_t _dl_tls_initial_modid_limit attribute_hidden attribute_relro;
++
++/* Compute _dl_tls_initial_modid_limit.  To be called after initial
++   relocation.  */
++void _dl_tls_initial_modid_limit_setup (void) attribute_hidden;
++
++/* Number of threads currently in a TLS update.  This is used to
++   detect reentrant __tls_get_addr calls without a per-thread
++   flag.  */
++extern unsigned int _dl_tls_threads_in_update attribute_hidden;
++
+ /* Look up the module's TLS block as for __tls_get_addr,
+    but never touch anything.  Return null if it's not allocated yet.  */
+ extern void *_dl_tls_get_addr_soft (struct link_map *l) attribute_hidden;
+diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c
+index 869023bbba..b3c1e4fcd7 100644
+--- a/sysdeps/x86_64/dl-tls.c
++++ b/sysdeps/x86_64/dl-tls.c
+@@ -41,7 +41,10 @@ __tls_get_addr_slow (GET_ADDR_ARGS)
+   dtv_t *dtv = THREAD_DTV ();
+ 
+   size_t gen = atomic_load_acquire (&GL(dl_tls_generation));
+-  if (__glibc_unlikely (dtv[0].counter != gen))
++  if (__glibc_unlikely (dtv[0].counter != gen)
++      /* See comment in __tls_get_addr in elf/dl-tls.c.  */
++      && !(_dl_tls_allocate_active ()
++           && GET_ADDR_MODULE < _dl_tls_initial_modid_limit))
+     return update_get_addr (GET_ADDR_PARAM, gen);
+ 
+   return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL);
diff --git a/SOURCES/glibc-RHEL-46723-1.patch b/SOURCES/glibc-RHEL-46723-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..5f3f2266490df2d9040bd62344ff801485741e0f
--- /dev/null
+++ b/SOURCES/glibc-RHEL-46723-1.patch
@@ -0,0 +1,44 @@
+commit 0e16db440cc73d2cdd94e439c0efa1ec43d92b2a
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Tue Aug 13 15:52:34 2024 +0200
+
+    manual: Document generic printf error codes
+    
+    Describe EOVERFLOW, ENOMEN, EILSEQ.
+    
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+diff --git a/manual/stdio.texi b/manual/stdio.texi
+index 567f6780011f9db1..41298b87a4a6c7d9 100644
+--- a/manual/stdio.texi
++++ b/manual/stdio.texi
+@@ -2318,6 +2318,29 @@ the easiest way to make sure you have all the right prototypes is to
+ just include @file{stdio.h}.
+ @pindex stdio.h
+ 
++The @code{printf} family shares the error codes listed below.
++Individual functions may report additional @code{errno} values if they
++fail.
++
++@table @code
++@item EOVERFLOW
++The number of written bytes would have exceeded @code{INT_MAX}, and thus
++could not be represented in the return type @code{int}.
++
++@item ENOMEM
++The function could not allocate memory during processing.  Long argument
++lists and certain floating point conversions may require memory
++allocation, as does initialization of an output stream upon first use.
++
++@item EILSEQ
++POSIX specifies this error code should be used if a wide character is
++encountered that does not have a matching valid character.  @Theglibc{}
++always performs transliteration, using a replacement character if
++necessary, so this error condition cannot occur on output.  However,
++@theglibc{} uses @code{EILSEQ} to indicate that an input character
++sequence (wide or multi-byte) could not be converted successfully.
++@end table
++
+ @deftypefun int printf (const char *@var{template}, @dots{})
+ @standards{ISO, stdio.h}
+ @safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}}
diff --git a/SOURCES/glibc-RHEL-46723-2.patch b/SOURCES/glibc-RHEL-46723-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..5b7e73afac65dd46e5d2a3f4311bd0431511de6f
--- /dev/null
+++ b/SOURCES/glibc-RHEL-46723-2.patch
@@ -0,0 +1,53 @@
+commit 2be0572f3a41d5d5a8bb3b2b04244b7c01ac0f58
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Tue Aug 13 15:52:34 2024 +0200
+
+    manual: Document dprintf and vdprintf
+    
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+diff --git a/manual/stdio.texi b/manual/stdio.texi
+index 41298b87a4a6c7d9..d3d855fc62b8768b 100644
+--- a/manual/stdio.texi
++++ b/manual/stdio.texi
+@@ -2483,6 +2483,26 @@ store the result in which case @code{-1} is returned.  This was
+ changed in order to comply with the @w{ISO C99} standard.
+ @end deftypefun
+ 
++@deftypefun dprintf (int @var{fd}, @var{template}, ...)
++@standards{POSIX, stdio.h}
++@safety{@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
++This function formats its arguments according to @var{template} and
++writes the result to the file descriptor @var{fd}, using the
++@code{write} function.  It returns the number of bytes written, or a
++negative value if there was an error.  In the error case, @code{errno}
++is set appropriately.  The possible @code{errno} values depend on the
++type of the file descriptor @var{fd}, in addition to the general
++@code{printf} error codes.
++
++The number of calls to @code{write} is unspecified, and some @code{write}
++calls may have happened even if @code{dprintf} returns with an error.
++
++@strong{Portability Note:} POSIX does not require that this function is
++async-signal-safe, and @theglibc{} implementation is not.  However, some
++other systems offer this function as an async-signal-safe alternative to
++@code{fprintf}.  @xref{POSIX Safety Concepts}.
++@end deftypefun
++
+ @node Dynamic Output
+ @subsection Dynamically Allocating Formatted Output
+ 
+@@ -2696,6 +2716,13 @@ The @code{obstack_vprintf} function is the equivalent of
+ as for @code{vprintf}.@refill
+ @end deftypefun
+ 
++@deftypefun int vdprintf (int @var{fd}, const char *@var{template}, va_list @var{ap})
++@standards{POSIX, stdio.h}
++@safety{@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
++The @code{vdprintf} is the equivalent of @code{dprintf}, but processes
++an argument list.
++@end deftypefun
++
+ Here's an example showing how you might use @code{vfprintf}.  This is a
+ function that prints error messages to the stream @code{stderr}, along
+ with a prefix indicating the name of the program
diff --git a/SOURCES/glibc-RHEL-46741-1.patch b/SOURCES/glibc-RHEL-46741-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c0ba98b41e45fa234b98ee3db6ee28263c699261
--- /dev/null
+++ b/SOURCES/glibc-RHEL-46741-1.patch
@@ -0,0 +1,50 @@
+commit 10de4a47ef3f481592e3c62eb07bcda23e9fde4d
+Author: Arjun Shankar <arjun@redhat.com>
+Date:   Mon Jul 29 14:30:59 2024 +0200
+
+    manual/stdio: Clarify putc and putwc
+    
+    The manual entry for `putc' described what "most systems" do instead of
+    describing the glibc implementation and its guarantees.  This commit
+    fixes that by warning that putc may be implemented as a macro that
+    double-evaluates `stream', and removing the performance claim.
+    
+    Even though the current `putc' implementation does not double-evaluate
+    `stream', offering this obscure guarantee as an extension to what
+    POSIX allows does not seem very useful.
+    
+    The entry for `putwc' is also edited to bring it in line with `putc'.
+    Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+diff --git a/manual/stdio.texi b/manual/stdio.texi
+index fd7ed0cedc7c1a59..0c9a7ce4a9df4c05 100644
+--- a/manual/stdio.texi
++++ b/manual/stdio.texi
+@@ -903,21 +903,21 @@ This function is a GNU extension.
+ @deftypefun int putc (int @var{c}, FILE *@var{stream})
+ @standards{ISO, stdio.h}
+ @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
+-This is just like @code{fputc}, except that most systems implement it as
++This is just like @code{fputc}, except that it may be implemented as
+ a macro, making it faster.  One consequence is that it may evaluate the
+ @var{stream} argument more than once, which is an exception to the
+-general rule for macros.  @code{putc} is usually the best function to
+-use for writing a single character.
++general rule for macros.  Therefore, @var{stream} should never be an
++expression with side-effects.
+ @end deftypefun
+ 
+ @deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream})
+ @standards{ISO, wchar.h}
+ @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
+-This is just like @code{fputwc}, except that it can be implement as
++This is just like @code{fputwc}, except that it may be implemented as
+ a macro, making it faster.  One consequence is that it may evaluate the
+ @var{stream} argument more than once, which is an exception to the
+-general rule for macros.  @code{putwc} is usually the best function to
+-use for writing a single wide character.
++general rule for macros.  Therefore, @var{stream} should never be an
++expression with side-effects.
+ @end deftypefun
+ 
+ @deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream})
diff --git a/SOURCES/glibc-RHEL-46741-2.patch b/SOURCES/glibc-RHEL-46741-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..cac84f0c8006cfe0eab2a3c57b2c3c53b01c8007
--- /dev/null
+++ b/SOURCES/glibc-RHEL-46741-2.patch
@@ -0,0 +1,71 @@
+commit 942670c81dc8071dd75d6213e771daa5d2084cb6
+Author: Arjun Shankar <arjun@redhat.com>
+Date:   Tue Jul 30 11:37:57 2024 +0200
+
+    manual/stdio: Further clarify putc, putwc, getc, and getwc
+    
+    This is a follow-up to 10de4a47ef3f481592e3c62eb07bcda23e9fde4d that
+    reworded the manual entries for putc and putwc and removed any
+    performance claims.
+    
+    This commit further clarifies these entries and brings getc and getwc in
+    line with the descriptions of putc and putwc, removing any performance
+    claims from them as well.
+    Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+diff --git a/manual/stdio.texi b/manual/stdio.texi
+index 0c9a7ce4a9df4c05..567f6780011f9db1 100644
+--- a/manual/stdio.texi
++++ b/manual/stdio.texi
+@@ -904,20 +904,16 @@ This function is a GNU extension.
+ @standards{ISO, stdio.h}
+ @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
+ This is just like @code{fputc}, except that it may be implemented as
+-a macro, making it faster.  One consequence is that it may evaluate the
+-@var{stream} argument more than once, which is an exception to the
+-general rule for macros.  Therefore, @var{stream} should never be an
+-expression with side-effects.
++a macro and may evaluate the @var{stream} argument more than once.
++Therefore, @var{stream} should never be an expression with side-effects.
+ @end deftypefun
+ 
+ @deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream})
+ @standards{ISO, wchar.h}
+ @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
+ This is just like @code{fputwc}, except that it may be implemented as
+-a macro, making it faster.  One consequence is that it may evaluate the
+-@var{stream} argument more than once, which is an exception to the
+-general rule for macros.  Therefore, @var{stream} should never be an
+-expression with side-effects.
++a macro and may evaluate the @var{stream} argument more than once.
++Therefore, @var{stream} should never be an expression with side-effects.
+ @end deftypefun
+ 
+ @deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream})
+@@ -1110,20 +1106,17 @@ This function is a GNU extension.
+ @deftypefun int getc (FILE *@var{stream})
+ @standards{ISO, stdio.h}
+ @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}}
+-This is just like @code{fgetc}, except that it is permissible (and
+-typical) for it to be implemented as a macro that evaluates the
+-@var{stream} argument more than once.  @code{getc} is often highly
+-optimized, so it is usually the best function to use to read a single
+-character.
++This is just like @code{fgetc}, except that it may be implemented as
++a macro and may evaluate the @var{stream} argument more than once.
++Therefore, @var{stream} should never be an expression with side-effects.
+ @end deftypefun
+ 
+ @deftypefun wint_t getwc (FILE *@var{stream})
+ @standards{ISO, wchar.h}
+ @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}}
+-This is just like @code{fgetwc}, except that it is permissible for it to
+-be implemented as a macro that evaluates the @var{stream} argument more
+-than once.  @code{getwc} can be highly optimized, so it is usually the
+-best function to use to read a single wide character.
++This is just like @code{fgetwc}, except that it may be implemented as
++a macro and may evaluate the @var{stream} argument more than once.
++Therefore, @var{stream} should never be an expression with side-effects.
+ @end deftypefun
+ 
+ @deftypefun int getc_unlocked (FILE *@var{stream})
diff --git a/SOURCES/glibc-RHEL-46979-1.patch b/SOURCES/glibc-RHEL-46979-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..24308804f3ef17fa79f7f849819b89004bf6c069
--- /dev/null
+++ b/SOURCES/glibc-RHEL-46979-1.patch
@@ -0,0 +1,83 @@
+From a65ff76c9a1811dd2396ab45563f645579c0e687 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 27 Oct 2022 11:36:44 +0200
+Subject: ld.so: Export tls_init_tp_called as __rtld_tls_init_tp_called
+
+This allows the rest of dynamic loader to check whether the TCB
+has been set up (and THREAD_GETMEM and THREAD_SETMEM will work).
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
+
+Conflicts:
+	Regenerated for context changes.
+
+diff -rup a/elf/rtld.c b/elf/rtld.c
+--- a/elf/rtld.c	2024-08-22 17:57:02.000830481 -0400
++++ b/elf/rtld.c	2024-08-22 17:59:30.666562835 -0400
+@@ -740,7 +740,7 @@ match_version (const char *string, struc
+   return 0;
+ }
+ 
+-static bool tls_init_tp_called;
++bool __rtld_tls_init_tp_called;
+ 
+ static void *
+ init_tls (size_t naudit)
+@@ -812,7 +812,7 @@ cannot allocate TLS data structures for
+   if (__glibc_unlikely (lossage != NULL))
+     _dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
+   __tls_init_tp ();
+-  tls_init_tp_called = true;
++  __rtld_tls_init_tp_called = true;
+ 
+   return tcbp;
+ }
+@@ -2057,7 +2057,7 @@ dl_main (const ElfW(Phdr) *phdr,
+      an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
+      used.  Trying to do it lazily is too hairy to try when there could be
+      multiple threads (from a non-TLS-using libpthread).  */
+-  bool was_tls_init_tp_called = tls_init_tp_called;
++  bool was_tls_init_tp_called = __rtld_tls_init_tp_called;
+   if (tcbp == NULL)
+     tcbp = init_tls (0);
+ 
+@@ -2411,7 +2411,7 @@ dl_main (const ElfW(Phdr) *phdr,
+ 	    _dl_protect_relro (l);
+ 
+ 	  /* Add object to slot information data if necessasy.  */
+-	  if (l->l_tls_blocksize != 0 && tls_init_tp_called)
++	  if (l->l_tls_blocksize != 0 && __rtld_tls_init_tp_called)
+ 	    _dl_add_to_slotinfo (l, true);
+ 	}
+     }
+@@ -2462,7 +2462,7 @@ dl_main (const ElfW(Phdr) *phdr,
+ 				 consider_profiling);
+ 
+ 	  /* Add object to slot information data if necessasy.  */
+-	  if (l->l_tls_blocksize != 0 && tls_init_tp_called)
++	  if (l->l_tls_blocksize != 0 && __rtld_tls_init_tp_called)
+ 	    _dl_add_to_slotinfo (l, true);
+ 	}
+       rtld_timer_stop (&relocate_time, start);
+@@ -2488,7 +2488,7 @@ dl_main (const ElfW(Phdr) *phdr,
+   _dl_allocate_tls_init (tcbp, true);
+ 
+   /* And finally install it for the main thread.  */
+-  if (! tls_init_tp_called)
++  if (! __rtld_tls_init_tp_called)
+     {
+       const char *lossage = TLS_INIT_TP (tcbp);
+       if (__glibc_unlikely (lossage != NULL))
+diff -rup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+--- a/sysdeps/generic/ldsodefs.h	2024-08-22 17:57:02.011830906 -0400
++++ b/sysdeps/generic/ldsodefs.h	2024-08-22 17:58:10.900487160 -0400
+@@ -1262,6 +1262,9 @@ extern void *_dl_allocate_tls_storage (v
+ extern void *_dl_allocate_tls_init (void *result, bool main_thread);
+ rtld_hidden_proto (_dl_allocate_tls_init)
+ 
++/* True if the TCB has been set up.  */
++extern bool __rtld_tls_init_tp_called attribute_hidden;
++
+ /* Deallocate memory allocated with _dl_allocate_tls.  */
+ extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb);
+ rtld_hidden_proto (_dl_deallocate_tls)
diff --git a/SOURCES/glibc-RHEL-46979-2.patch b/SOURCES/glibc-RHEL-46979-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..0671c4fed0fa930ad88b927ae5c8684bc6605337
--- /dev/null
+++ b/SOURCES/glibc-RHEL-46979-2.patch
@@ -0,0 +1,1030 @@
+From ee1ada1bdb8074de6e1bdc956ab19aef7b6a7872 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 3 Nov 2022 09:39:31 +0100
+Subject: elf: Rework exception handling in the dynamic loader [BZ #25486]
+
+The old exception handling implementation used function interposition
+to replace the dynamic loader implementation (no TLS support) with the
+libc implementation (TLS support).  This results in problems if the
+link order between the dynamic loader and libc is reversed (bug 25486).
+
+The new implementation moves the entire implementation of the
+exception handling functions back into the dynamic loader, using
+THREAD_GETMEM and THREAD_SETMEM for thread-local data support.
+These depends on Hurd support for these macros, added in commit
+b65a82e4e757c1e6cb7073916 ("hurd: Add THREAD_GET/SETMEM/_NC").
+
+One small obstacle is that the exception handling facilities are used
+before the TCB has been set up, so a check is needed if the TCB is
+available.  If not, a regular global variable is used to store the
+exception handling information.
+
+Also rename dl-error.c to dl-catch.c, to avoid confusion with the
+dlerror function.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+Conflicts
+	Rebased due to context changes
+
+diff -rupN a/elf/Makefile b/elf/Makefile
+--- a/elf/Makefile	2024-08-29 11:28:38.488322915 -0400
++++ b/elf/Makefile	2024-08-29 11:29:16.773809945 -0400
+@@ -34,7 +34,6 @@ routines = \
+   dl-addr \
+   dl-addr-obj \
+   dl-early_allocate \
+-  dl-error \
+   dl-iteratephdr \
+   dl-libc \
+   dl-origin \
+@@ -52,6 +51,7 @@ routines = \
+ # profiled libraries.
+ dl-routines = \
+   dl-call-libc-early-init \
++  dl-catch \
+   dl-close \
+   dl-debug \
+   dl-deps \
+@@ -127,7 +127,6 @@ rtld-routines = \
+   dl-diagnostics-cpu \
+   dl-diagnostics-kernel \
+   dl-environ \
+-  dl-error-minimal \
+   dl-hwcaps \
+   dl-hwcaps-subdirs \
+   dl-hwcaps_split \
+diff -rupN a/elf/Versions b/elf/Versions
+--- a/elf/Versions	2024-08-29 11:28:36.214234588 -0400
++++ b/elf/Versions	2024-08-29 11:29:16.778810139 -0400
+@@ -23,10 +23,6 @@ libc {
+   GLIBC_PRIVATE {
+     # functions used in other libraries
+     __libc_early_init;
+-
+-    # Internal error handling support.  Interposes the functions in ld.so.
+-    _dl_signal_exception; _dl_catch_exception;
+-    _dl_signal_error; _dl_catch_error;
+   }
+ }
+ 
+@@ -69,10 +65,8 @@ ld {
+ 
+     # Internal error handling support.
+     _dl_exception_create; _dl_exception_create_format; _dl_exception_free;
+-
+-    # Internal error handling support.  Interposed by libc.so.
+     _dl_signal_exception; _dl_catch_exception;
+-    _dl_signal_error; _dl_catch_error;
++    _dl_signal_error;
+ 
+     # Set value of a tunable.
+     __tunable_get_val;
+diff -rupN a/elf/dl-catch.c b/elf/dl-catch.c
+--- a/elf/dl-catch.c	1969-12-31 19:00:00.000000000 -0500
++++ b/elf/dl-catch.c	2024-08-29 11:29:16.782810295 -0400
+@@ -0,0 +1,261 @@
++/* Exception handling in the dynamic linker.
++   Copyright (C) 1995-2022 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <libintl.h>
++#include <setjmp.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <ldsodefs.h>
++#include <stdio.h>
++#include <tls.h>
++
++/* This structure communicates state between _dl_catch_error and
++   _dl_signal_error.  */
++struct rtld_catch
++  {
++    struct dl_exception *exception; /* The exception data is stored there.  */
++    volatile int *errcode;	/* Return value of _dl_signal_error.  */
++    jmp_buf env;		/* longjmp here on error.  */
++  };
++
++/* Multiple threads at once can use the `_dl_catch_error' function.
++   The calls can come from `_dl_map_object_deps', `_dlerror_run', or
++   from any of the libc functionality which loads dynamic objects
++   (NSS, iconv).  Therefore we have to be prepared to save the state
++   in thread-local memory.  We use THREAD_GETMEM and THREAD_SETMEM
++   instead of ELF TLS because ELF TLS is not available in the dynamic
++   loader.  Additionally, the exception handling mechanism must be
++   usable before the TCB has been set up, which is why
++   rtld_catch_notls is used if !__rtld_tls_init_tp_called.  This is
++   not needed for static builds, where initialization completes before
++   static dlopen etc. can be called.  */
++
++#if IS_IN (rtld)
++static struct rtld_catch *rtld_catch_notls;
++#endif
++
++static struct rtld_catch *
++get_catch (void)
++{
++#if IS_IN (rtld)
++  if (!__rtld_tls_init_tp_called)
++    return rtld_catch_notls;
++  else
++#endif
++    return THREAD_GETMEM (THREAD_SELF, rtld_catch);
++}
++
++static void
++set_catch (struct rtld_catch *catch)
++{
++#if IS_IN (rtld)
++  if (!__rtld_tls_init_tp_called)
++    rtld_catch_notls = catch;
++  else
++#endif
++    THREAD_SETMEM (THREAD_SELF, rtld_catch, catch);
++}
++
++/* Lossage while resolving the program's own symbols is always fatal.  */
++static void
++__attribute__ ((noreturn))
++fatal_error (int errcode, const char *objname, const char *occasion,
++	     const char *errstring)
++{
++  char buffer[1024];
++  _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n",
++		    RTLD_PROGNAME,
++		    occasion ?: N_("error while loading shared libraries"),
++		    objname, *objname ? ": " : "",
++		    errstring, errcode ? ": " : "",
++		    (errcode
++		     ? __strerror_r (errcode, buffer, sizeof buffer)
++		     : ""));
++}
++
++void
++_dl_signal_exception (int errcode, struct dl_exception *exception,
++		      const char *occasion)
++{
++  struct rtld_catch *lcatch = get_catch ();
++  if (lcatch != NULL)
++    {
++      *lcatch->exception = *exception;
++      *lcatch->errcode = errcode;
++
++      /* We do not restore the signal mask because none was saved.  */
++      __longjmp (lcatch->env[0].__jmpbuf, 1);
++    }
++  else
++    fatal_error (errcode, exception->objname, occasion, exception->errstring);
++}
++rtld_hidden_def (_dl_signal_exception)
++
++void
++_dl_signal_error (int errcode, const char *objname, const char *occation,
++		  const char *errstring)
++{
++  struct rtld_catch *lcatch = get_catch ();
++
++  if (! errstring)
++    errstring = N_("DYNAMIC LINKER BUG!!!");
++
++  if (lcatch != NULL)
++    {
++      _dl_exception_create (lcatch->exception, objname, errstring);
++      *lcatch->errcode = errcode;
++
++      /* We do not restore the signal mask because none was saved.  */
++      __longjmp (lcatch->env[0].__jmpbuf, 1);
++    }
++  else
++    fatal_error (errcode, objname, occation, errstring);
++}
++rtld_hidden_def (_dl_signal_error)
++
++#if IS_IN (rtld)
++/* This points to a function which is called when a continuable error is
++   received.  Unlike the handling of `catch' this function may return.
++   The arguments will be the `errstring' and `objname'.
++
++   Since this functionality is not used in normal programs (only in ld.so)
++   we do not care about multi-threaded programs here.  We keep this as a
++   global variable.  */
++static receiver_fct receiver;
++
++void
++_dl_signal_cexception (int errcode, struct dl_exception *exception,
++		       const char *occasion)
++{
++  if (__builtin_expect (GLRO(dl_debug_mask)
++			& ~(DL_DEBUG_STATISTICS), 0))
++    _dl_debug_printf ("%s: error: %s: %s (%s)\n",
++		      exception->objname, occasion,
++		      exception->errstring, receiver ? "continued" : "fatal");
++
++  if (receiver)
++    {
++      /* We are inside _dl_receive_error.  Call the user supplied
++	 handler and resume the work.  The receiver will still be
++	 installed.  */
++      (*receiver) (errcode, exception->objname, exception->errstring);
++    }
++  else
++    _dl_signal_exception (errcode, exception, occasion);
++}
++
++void
++_dl_signal_cerror (int errcode, const char *objname, const char *occation,
++		   const char *errstring)
++{
++  if (__builtin_expect (GLRO(dl_debug_mask)
++			& ~(DL_DEBUG_STATISTICS), 0))
++    _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation,
++		      errstring, receiver ? "continued" : "fatal");
++
++  if (receiver)
++    {
++      /* We are inside _dl_receive_error.  Call the user supplied
++	 handler and resume the work.  The receiver will still be
++	 installed.  */
++      (*receiver) (errcode, objname, errstring);
++    }
++  else
++    _dl_signal_error (errcode, objname, occation, errstring);
++}
++
++void
++_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
++{
++  struct rtld_catch *old_catch = get_catch ();
++  receiver_fct old_receiver = receiver;
++
++  /* Set the new values.  */
++  set_catch (NULL);
++  receiver = fct;
++
++  (*operate) (args);
++
++  set_catch (old_catch);
++  receiver = old_receiver;
++}
++#endif
++
++int
++_dl_catch_exception (struct dl_exception *exception,
++		     void (*operate) (void *), void *args)
++{
++  /* If exception is NULL, temporarily disable exception handling.
++     Exceptions during operate (args) are fatal.  */
++  if (exception == NULL)
++    {
++      struct rtld_catch *old_catch = get_catch ();
++      set_catch (NULL);
++      operate (args);
++      /* If we get here, the operation was successful.  */
++      set_catch (old_catch);
++      return 0;
++    }
++
++  /* We need not handle `receiver' since setting a `catch' is handled
++     before it.  */
++
++  /* Only this needs to be marked volatile, because it is the only local
++     variable that gets changed between the setjmp invocation and the
++     longjmp call.  All others are just set here (before setjmp) and read
++     in _dl_signal_error (before longjmp).  */
++  volatile int errcode;
++
++  struct rtld_catch c;
++  /* Don't use an initializer since we don't need to clear C.env.  */
++  c.exception = exception;
++  c.errcode = &errcode;
++
++  struct rtld_catch *old = get_catch ();
++  set_catch (&c);
++
++  /* Do not save the signal mask.  */
++  if (__builtin_expect (__sigsetjmp (c.env, 0), 0) == 0)
++    {
++      (*operate) (args);
++      set_catch (old);
++      *exception = (struct dl_exception) { NULL };
++      return 0;
++    }
++
++  /* We get here only if we longjmp'd out of OPERATE.
++     _dl_signal_exception has already stored values into
++     *EXCEPTION.  */
++  set_catch (old);
++  return errcode;
++}
++rtld_hidden_def (_dl_catch_exception)
++
++int
++_dl_catch_error (const char **objname, const char **errstring,
++		 bool *mallocedp, void (*operate) (void *), void *args)
++{
++  struct dl_exception exception;
++  int errorcode = _dl_catch_exception (&exception, operate, args);
++  *objname = exception.objname;
++  *errstring = exception.errstring;
++  *mallocedp = exception.message_buffer == exception.errstring;
++  return errorcode;
++}
+diff -rupN a/elf/dl-error-minimal.c b/elf/dl-error-minimal.c
+--- a/elf/dl-error-minimal.c	2021-08-01 21:33:43.000000000 -0400
++++ b/elf/dl-error-minimal.c	1969-12-31 19:00:00.000000000 -0500
+@@ -1,23 +0,0 @@
+-/* Error handling for runtime dynamic linker, minimal version.
+-   Copyright (C) 1995-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
+-   <https://www.gnu.org/licenses/>.  */
+-
+-/* This version does lives in ld.so, does not use thread-local data
+-   and supports _dl_signal_cerror and _dl_receive_error.  */
+-
+-#define DL_ERROR_BOOTSTRAP 1
+-#include "dl-error-skeleton.c"
+diff -rupN a/elf/dl-error-skeleton.c b/elf/dl-error-skeleton.c
+--- a/elf/dl-error-skeleton.c	2021-08-01 21:33:43.000000000 -0400
++++ b/elf/dl-error-skeleton.c	1969-12-31 19:00:00.000000000 -0500
+@@ -1,263 +0,0 @@
+-/* Template for error handling for runtime dynamic linker.
+-   Copyright (C) 1995-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
+-   <https://www.gnu.org/licenses/>.  */
+-
+-/* The following macro needs to be defined before including this
+-   skeleton file:
+-
+-   DL_ERROR_BOOTSTRAP
+-
+-     If 1, do not use TLS and implement _dl_signal_cerror and
+-     _dl_receive_error.  If 0, TLS is used, and the variants with
+-     error callbacks are not provided.  */
+-
+-
+-#include <libintl.h>
+-#include <setjmp.h>
+-#include <stdbool.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <unistd.h>
+-#include <ldsodefs.h>
+-#include <stdio.h>
+-
+-/* This structure communicates state between _dl_catch_error and
+-   _dl_signal_error.  */
+-struct catch
+-  {
+-    struct dl_exception *exception; /* The exception data is stored there.  */
+-    volatile int *errcode;	/* Return value of _dl_signal_error.  */
+-    jmp_buf env;		/* longjmp here on error.  */
+-  };
+-
+-/* Multiple threads at once can use the `_dl_catch_error' function.  The
+-   calls can come from `_dl_map_object_deps', `_dlerror_run', or from
+-   any of the libc functionality which loads dynamic objects (NSS, iconv).
+-   Therefore we have to be prepared to save the state in thread-local
+-   memory.  */
+-#if !DL_ERROR_BOOTSTRAP
+-static __thread struct catch *catch_hook attribute_tls_model_ie;
+-#else
+-/* The version of this code in ld.so cannot use thread-local variables
+-   and is used during bootstrap only.  */
+-static struct catch *catch_hook;
+-#endif
+-
+-#if DL_ERROR_BOOTSTRAP
+-/* This points to a function which is called when an continuable error is
+-   received.  Unlike the handling of `catch' this function may return.
+-   The arguments will be the `errstring' and `objname'.
+-
+-   Since this functionality is not used in normal programs (only in ld.so)
+-   we do not care about multi-threaded programs here.  We keep this as a
+-   global variable.  */
+-static receiver_fct receiver;
+-#endif /* DL_ERROR_BOOTSTRAP */
+-
+-/* Lossage while resolving the program's own symbols is always fatal.  */
+-static void
+-__attribute__ ((noreturn))
+-fatal_error (int errcode, const char *objname, const char *occasion,
+-	     const char *errstring)
+-{
+-  char buffer[1024];
+-  _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n",
+-		    RTLD_PROGNAME,
+-		    occasion ?: N_("error while loading shared libraries"),
+-		    objname, *objname ? ": " : "",
+-		    errstring, errcode ? ": " : "",
+-		    (errcode
+-		     ? __strerror_r (errcode, buffer, sizeof buffer)
+-		     : ""));
+-}
+-
+-void
+-_dl_signal_exception (int errcode, struct dl_exception *exception,
+-		      const char *occasion)
+-{
+-  struct catch *lcatch = catch_hook;
+-  if (lcatch != NULL)
+-    {
+-      *lcatch->exception = *exception;
+-      *lcatch->errcode = errcode;
+-
+-      /* We do not restore the signal mask because none was saved.  */
+-      __longjmp (lcatch->env[0].__jmpbuf, 1);
+-    }
+-  else
+-    fatal_error (errcode, exception->objname, occasion, exception->errstring);
+-}
+-libc_hidden_def (_dl_signal_exception)
+-
+-void
+-_dl_signal_error (int errcode, const char *objname, const char *occation,
+-		  const char *errstring)
+-{
+-  struct catch *lcatch = catch_hook;
+-
+-  if (! errstring)
+-    errstring = N_("DYNAMIC LINKER BUG!!!");
+-
+-  if (lcatch != NULL)
+-    {
+-      _dl_exception_create (lcatch->exception, objname, errstring);
+-      *lcatch->errcode = errcode;
+-
+-      /* We do not restore the signal mask because none was saved.  */
+-      __longjmp (lcatch->env[0].__jmpbuf, 1);
+-    }
+-  else
+-    fatal_error (errcode, objname, occation, errstring);
+-}
+-libc_hidden_def (_dl_signal_error)
+-
+-
+-#if DL_ERROR_BOOTSTRAP
+-void
+-_dl_signal_cexception (int errcode, struct dl_exception *exception,
+-		       const char *occasion)
+-{
+-  if (__builtin_expect (GLRO(dl_debug_mask)
+-			& ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0))
+-    _dl_debug_printf ("%s: error: %s: %s (%s)\n",
+-		      exception->objname, occasion,
+-		      exception->errstring, receiver ? "continued" : "fatal");
+-
+-  if (receiver)
+-    {
+-      /* We are inside _dl_receive_error.  Call the user supplied
+-	 handler and resume the work.  The receiver will still be
+-	 installed.  */
+-      (*receiver) (errcode, exception->objname, exception->errstring);
+-    }
+-  else
+-    _dl_signal_exception (errcode, exception, occasion);
+-}
+-
+-void
+-_dl_signal_cerror (int errcode, const char *objname, const char *occation,
+-		   const char *errstring)
+-{
+-  if (__builtin_expect (GLRO(dl_debug_mask)
+-			& ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0))
+-    _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation,
+-		      errstring, receiver ? "continued" : "fatal");
+-
+-  if (receiver)
+-    {
+-      /* We are inside _dl_receive_error.  Call the user supplied
+-	 handler and resume the work.  The receiver will still be
+-	 installed.  */
+-      (*receiver) (errcode, objname, errstring);
+-    }
+-  else
+-    _dl_signal_error (errcode, objname, occation, errstring);
+-}
+-#endif /* DL_ERROR_BOOTSTRAP */
+-
+-int
+-_dl_catch_exception (struct dl_exception *exception,
+-		     void (*operate) (void *), void *args)
+-{
+-  /* If exception is NULL, temporarily disable exception handling.
+-     Exceptions during operate (args) are fatal.  */
+-  if (exception == NULL)
+-    {
+-      struct catch *const old = catch_hook;
+-      catch_hook = NULL;
+-      operate (args);
+-      /* If we get here, the operation was successful.  */
+-      catch_hook = old;
+-      return 0;
+-    }
+-
+-  /* We need not handle `receiver' since setting a `catch' is handled
+-     before it.  */
+-
+-  /* Only this needs to be marked volatile, because it is the only local
+-     variable that gets changed between the setjmp invocation and the
+-     longjmp call.  All others are just set here (before setjmp) and read
+-     in _dl_signal_error (before longjmp).  */
+-  volatile int errcode;
+-
+-  struct catch c;
+-  /* Don't use an initializer since we don't need to clear C.env.  */
+-  c.exception = exception;
+-  c.errcode = &errcode;
+-
+-  struct catch *const old = catch_hook;
+-  catch_hook = &c;
+-
+-  /* Do not save the signal mask.  */
+-  if (__builtin_expect (__sigsetjmp (c.env, 0), 0) == 0)
+-    {
+-      (*operate) (args);
+-      catch_hook = old;
+-      *exception = (struct dl_exception) { NULL };
+-      return 0;
+-    }
+-
+-  /* We get here only if we longjmp'd out of OPERATE.
+-     _dl_signal_exception has already stored values into
+-     *EXCEPTION.  */
+-  catch_hook = old;
+-  return errcode;
+-}
+-libc_hidden_def (_dl_catch_exception)
+-
+-int
+-_dl_catch_error (const char **objname, const char **errstring,
+-		 bool *mallocedp, void (*operate) (void *), void *args)
+-{
+-  struct dl_exception exception;
+-  int errorcode = _dl_catch_exception (&exception, operate, args);
+-  *objname = exception.objname;
+-  *errstring = exception.errstring;
+-  *mallocedp = exception.message_buffer == exception.errstring;
+-  return errorcode;
+-}
+-libc_hidden_def (_dl_catch_error)
+-
+-#if DL_ERROR_BOOTSTRAP
+-void
+-_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
+-{
+-  struct catch *old_catch = catch_hook;
+-  receiver_fct old_receiver = receiver;
+-
+-  /* Set the new values.  */
+-  catch_hook = NULL;
+-  receiver = fct;
+-
+-  (*operate) (args);
+-
+-  catch_hook = old_catch;
+-  receiver = old_receiver;
+-}
+-
+-/* Forwarder used for initializing GLRO (_dl_catch_error).  */
+-int
+-_rtld_catch_error (const char **objname, const char **errstring,
+-		   bool *mallocedp, void (*operate) (void *),
+-		   void *args)
+-{
+-  /* The reference to _dl_catch_error will eventually be relocated to
+-     point to the implementation in libc.so.  */
+-  return _dl_catch_error (objname, errstring, mallocedp, operate, args);
+-}
+-
+-#endif /* DL_ERROR_BOOTSTRAP */
+diff -rupN a/elf/dl-error.c b/elf/dl-error.c
+--- a/elf/dl-error.c	2021-08-01 21:33:43.000000000 -0400
++++ b/elf/dl-error.c	1969-12-31 19:00:00.000000000 -0500
+@@ -1,27 +0,0 @@
+-/* Error handling for runtime dynamic linker, full version.
+-   Copyright (C) 1995-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
+-   <https://www.gnu.org/licenses/>.  */
+-
+-/* This implementation lives in libc.so because it uses thread-local
+-   data, which is not available in ld.so.  It interposes the version
+-   in dl-error-minimal.c after ld.so bootstrap.
+-
+-   The signal/catch mechanism is used by the audit framework, which
+-   means that even in ld.so, not all errors are fatal.  */
+-
+-#define DL_ERROR_BOOTSTRAP 0
+-#include "dl-error-skeleton.c"
+diff -rupN a/elf/rtld.c b/elf/rtld.c
+--- a/elf/rtld.c	2024-08-29 11:28:38.569326061 -0400
++++ b/elf/rtld.c	2024-08-29 11:29:16.798810916 -0400
+@@ -377,7 +377,7 @@ struct rtld_global_ro _rtld_global_ro at
+     ._dl_lookup_symbol_x = _dl_lookup_symbol_x,
+     ._dl_open = _dl_open,
+     ._dl_close = _dl_close,
+-    ._dl_catch_error = _rtld_catch_error,
++    ._dl_catch_error = _dl_catch_error,
+     ._dl_error_free = _dl_error_free,
+     ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft,
+ #ifdef HAVE_DL_DISCOVER_OSVERSION
+diff -rupN a/nptl/descr.h b/nptl/descr.h
+--- a/nptl/descr.h	2024-08-29 11:28:37.858298444 -0400
++++ b/nptl/descr.h	2024-08-29 11:29:16.801811033 -0400
+@@ -396,6 +396,9 @@ struct pthread
+      masked.)  */
+   sigset_t sigmask;
+ 
++  /* Used by the exception handling implementation in the dynamic loader.  */
++  struct rtld_catch *rtld_catch;
++
+   /* Indicates whether is a C11 thread created by thrd_creat.  */
+   bool c11;
+ 
+diff -rupN a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+--- a/sysdeps/generic/ldsodefs.h	2024-08-29 11:28:38.571326139 -0400
++++ b/sysdeps/generic/ldsodefs.h	2024-08-29 11:29:16.805811188 -0400
+@@ -897,13 +897,13 @@ rtld_hidden_proto (_dl_exception_free)
+ void _dl_signal_exception (int errcode, struct dl_exception *,
+ 			   const char *occasion)
+   __attribute__ ((__noreturn__));
+-libc_hidden_proto (_dl_signal_exception)
++rtld_hidden_proto (_dl_signal_exception)
+ 
+ /* Like _dl_signal_exception, but creates the exception first.  */
+ extern void _dl_signal_error (int errcode, const char *object,
+ 			      const char *occasion, const char *errstring)
+      __attribute__ ((__noreturn__));
+-libc_hidden_proto (_dl_signal_error)
++rtld_hidden_proto (_dl_signal_error)
+ 
+ /* Like _dl_signal_exception, but may return when called in the
+    context of _dl_receive_error.  This is only used during ld.so
+@@ -955,11 +955,7 @@ extern void _dl_receive_error (receiver_
+    the returned string is allocated using the libc's malloc.  */
+ extern int _dl_catch_error (const char **objname, const char **errstring,
+ 			    bool *mallocedp, void (*operate) (void *),
+-			    void *args);
+-libc_hidden_proto (_dl_catch_error)
+-
+-/* Used for initializing GLRO (_dl_catch_error).  */
+-extern __typeof__ (_dl_catch_error) _rtld_catch_error attribute_hidden;
++			    void *args) attribute_hidden;
+ 
+ /* Call OPERATE (ARGS).  If no error occurs, set *EXCEPTION to zero.
+    Otherwise, store a copy of the raised exception in *EXCEPTION,
+@@ -968,7 +964,7 @@ extern __typeof__ (_dl_catch_error) _rtl
+    disabled (so that exceptions are fatal).  */
+ int _dl_catch_exception (struct dl_exception *exception,
+ 			 void (*operate) (void *), void *args);
+-libc_hidden_proto (_dl_catch_exception)
++rtld_hidden_proto (_dl_catch_exception)
+ 
+ /* Open the shared object NAME and map in its segments.
+    LOADER's DT_RPATH is used in searching for NAME.
+diff -rupN a/sysdeps/generic/localplt.data b/sysdeps/generic/localplt.data
+--- a/sysdeps/generic/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/generic/localplt.data	2024-08-29 11:29:16.806811227 -0400
+@@ -6,8 +6,3 @@ libc.so: free
+ libc.so: malloc
+ libc.so: realloc
+ libm.so: matherr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/mach/hurd/i386/localplt.data b/sysdeps/mach/hurd/i386/localplt.data
+--- a/sysdeps/mach/hurd/i386/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/mach/hurd/i386/localplt.data	2024-08-29 11:29:16.808811305 -0400
+@@ -8,11 +8,6 @@ libc.so: free + REL R_386_GLOB_DAT
+ libc.so: malloc + REL R_386_GLOB_DAT
+ libc.so: realloc + REL R_386_GLOB_DAT
+ libm.so: matherr + REL R_386_GLOB_DAT
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error + REL R_386_GLOB_DAT
+-ld.so: _dl_catch_error + REL R_386_GLOB_DAT
+-ld.so: _dl_signal_exception + REL R_386_GLOB_DAT
+-ld.so: _dl_catch_exception + REL R_386_GLOB_DAT
+ # The dynamic linker has its own versions of basic functions for initial loading
+ # of shared libraries.  These need to be overriden by libc once loaded.
+ ld.so: __open ?
+diff -rupN a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h
+--- a/sysdeps/mach/hurd/i386/tls.h	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/mach/hurd/i386/tls.h	2024-08-29 11:29:16.810811382 -0400
+@@ -48,6 +48,9 @@ typedef struct
+      compatible with the i386 Linux version.  */
+   mach_port_t reply_port;      /* This thread's reply port.  */
+   struct hurd_sigstate *_hurd_sigstate;
++
++  /* Used by the exception handling implementation in the dynamic loader.  */
++  struct rtld_catch *rtld_catch;
+ } tcbhead_t;
+ #endif
+ 
+diff -rupN a/sysdeps/unix/sysv/linux/aarch64/localplt.data b/sysdeps/unix/sysv/linux/aarch64/localplt.data
+--- a/sysdeps/unix/sysv/linux/aarch64/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/aarch64/localplt.data	2024-08-29 11:29:16.810811382 -0400
+@@ -11,8 +11,3 @@ libm.so: matherr
+ libc.so: __getauxval ?
+ # The dynamic loader needs __tls_get_addr for TLS.
+ ld.so: __tls_get_addr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/alpha/localplt.data b/sysdeps/unix/sysv/linux/alpha/localplt.data
+--- a/sysdeps/unix/sysv/linux/alpha/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/alpha/localplt.data	2024-08-29 11:29:16.810811382 -0400
+@@ -25,8 +25,3 @@ libm.so: matherr + RELA R_ALPHA_GLOB_DAT
+ libm.so: __atan2
+ # The dynamic loader needs __tls_get_addr for TLS.
+ ld.so: __tls_get_addr ?
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error + RELA R_ALPHA_GLOB_DAT
+-ld.so: _dl_catch_error + RELA R_ALPHA_GLOB_DAT
+-ld.so: _dl_signal_exception + RELA R_ALPHA_GLOB_DAT
+-ld.so: _dl_catch_exception + RELA R_ALPHA_GLOB_DAT
+diff -rupN a/sysdeps/unix/sysv/linux/arc/localplt.data b/sysdeps/unix/sysv/linux/arc/localplt.data
+--- a/sysdeps/unix/sysv/linux/arc/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/arc/localplt.data	2024-08-29 11:29:16.814811538 -0400
+@@ -4,8 +4,3 @@ libc.so: calloc
+ libc.so: free
+ # At -Os, a struct assignment in libgcc-static pulls this in
+ libc.so: memcpy ?
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/arm/localplt.data b/sysdeps/unix/sysv/linux/arm/localplt.data
+--- a/sysdeps/unix/sysv/linux/arm/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/arm/localplt.data	2024-08-29 11:29:16.814811538 -0400
+@@ -6,8 +6,3 @@ libc.so: realloc
+ libm.so: matherr
+ # The dynamic loader needs __tls_get_addr for TLS.
+ ld.so: __tls_get_addr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/csky/localplt.data b/sysdeps/unix/sysv/linux/csky/localplt.data
+--- a/sysdeps/unix/sysv/linux/csky/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/csky/localplt.data	2024-08-29 11:29:16.814811538 -0400
+@@ -5,8 +5,3 @@ libc.so: calloc
+ libc.so: free
+ libc.so: malloc
+ libc.so: realloc
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/hppa/localplt.data b/sysdeps/unix/sysv/linux/hppa/localplt.data
+--- a/sysdeps/unix/sysv/linux/hppa/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/hppa/localplt.data	2024-08-29 11:29:16.814811538 -0400
+@@ -9,8 +9,3 @@ libc.so: __sigsetjmp
+ libc.so: _IO_funlockfile
+ libc.so: __errno_location
+ libm.so: matherr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/i386/localplt.data b/sysdeps/unix/sysv/linux/i386/localplt.data
+--- a/sysdeps/unix/sysv/linux/i386/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/i386/localplt.data	2024-08-29 11:29:16.816811615 -0400
+@@ -6,8 +6,3 @@ libc.so: free + REL R_386_GLOB_DAT
+ libc.so: malloc + REL R_386_GLOB_DAT
+ libc.so: realloc + REL R_386_GLOB_DAT
+ libm.so: matherr + REL R_386_GLOB_DAT
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error + REL R_386_GLOB_DAT
+-ld.so: _dl_catch_error + REL R_386_GLOB_DAT
+-ld.so: _dl_signal_exception + REL R_386_GLOB_DAT
+-ld.so: _dl_catch_exception + REL R_386_GLOB_DAT
+diff -rupN a/sysdeps/unix/sysv/linux/ia64/localplt.data b/sysdeps/unix/sysv/linux/ia64/localplt.data
+--- a/sysdeps/unix/sysv/linux/ia64/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/ia64/localplt.data	2024-08-29 11:29:16.816811615 -0400
+@@ -5,8 +5,3 @@ libc.so: realloc
+ libm.so: matherr
+ libm.so: matherrf
+ libm.so: matherrl
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data b/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data
+--- a/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data	2024-08-29 11:29:16.819811732 -0400
+@@ -4,8 +4,3 @@ libc.so: free
+ libc.so: malloc
+ libc.so: realloc
+ libm.so: matherr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data b/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data
+--- a/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data	2024-08-29 11:29:16.820811771 -0400
+@@ -5,8 +5,3 @@ libc.so: free
+ libc.so: malloc
+ libc.so: realloc
+ libm.so: matherr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/microblaze/localplt.data b/sysdeps/unix/sysv/linux/microblaze/localplt.data
+--- a/sysdeps/unix/sysv/linux/microblaze/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/microblaze/localplt.data	2024-08-29 11:29:16.822811848 -0400
+@@ -6,8 +6,3 @@ libc.so: realloc
+ libm.so: matherr
+ # The dynamic loader needs __tls_get_addr for TLS.
+ ld.so: __tls_get_addr ?
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/nios2/localplt.data b/sysdeps/unix/sysv/linux/nios2/localplt.data
+--- a/sysdeps/unix/sysv/linux/nios2/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/nios2/localplt.data	2024-08-29 11:29:16.825811965 -0400
+@@ -27,8 +27,3 @@ libc.so: __eqdf2
+ libc.so: __extendsfdf2
+ libc.so: __floatundidf ?
+ libm.so: matherr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data	2024-08-29 11:29:16.829812120 -0400
+@@ -4,8 +4,3 @@ libc.so: free
+ libc.so: malloc
+ libc.so: realloc
+ libm.so: matherr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data	2024-08-29 11:29:16.831812198 -0400
+@@ -35,8 +35,3 @@ libc.so: realloc
+ libm.so: copysignl ?
+ libm.so: fabsl
+ libm.so: matherr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data	2024-08-29 11:29:16.833812276 -0400
+@@ -3,8 +3,3 @@ libc.so: free
+ libc.so: malloc
+ libc.so: realloc
+ libm.so: matherr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/riscv/localplt.data b/sysdeps/unix/sysv/linux/riscv/localplt.data
+--- a/sysdeps/unix/sysv/linux/riscv/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/riscv/localplt.data	2024-08-29 11:29:16.835812353 -0400
+@@ -6,8 +6,3 @@ libc.so: free
+ libc.so: malloc
+ libc.so: memset ?
+ libc.so: realloc
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/s390/localplt.data b/sysdeps/unix/sysv/linux/s390/localplt.data
+--- a/sysdeps/unix/sysv/linux/s390/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/s390/localplt.data	2024-08-29 11:29:16.837812431 -0400
+@@ -4,8 +4,3 @@ libc.so: free
+ libc.so: malloc
+ libc.so: realloc
+ libm.so: matherr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/sh/localplt.data b/sysdeps/unix/sysv/linux/sh/localplt.data
+--- a/sysdeps/unix/sysv/linux/sh/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/sh/localplt.data	2024-08-29 11:29:16.838812470 -0400
+@@ -11,8 +11,3 @@ libc.so: __errno_location
+ libm.so: matherr
+ # Generated by the compiler because there is no trap insn pattern.
+ libc.so: abort ?
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data
+--- a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data	2024-08-29 11:29:16.840812547 -0400
+@@ -18,8 +18,3 @@ libc.so: free
+ libc.so: malloc
+ libc.so: realloc
+ libm.so: matherr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data
+--- a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data	2024-08-29 11:29:16.844812703 -0400
+@@ -17,8 +17,3 @@ libc.so: free
+ libc.so: malloc
+ libc.so: realloc
+ libm.so: matherr
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error
+-ld.so: _dl_catch_error
+-ld.so: _dl_signal_exception
+-ld.so: _dl_catch_exception
+diff -rupN a/sysdeps/x86_64/localplt.data b/sysdeps/x86_64/localplt.data
+--- a/sysdeps/x86_64/localplt.data	2021-08-01 21:33:43.000000000 -0400
++++ b/sysdeps/x86_64/localplt.data	2024-08-29 11:29:16.847812819 -0400
+@@ -8,8 +8,3 @@ libc.so: free + RELA R_X86_64_GLOB_DAT
+ libc.so: malloc + RELA R_X86_64_GLOB_DAT
+ libc.so: realloc + RELA R_X86_64_GLOB_DAT
+ libm.so: matherr + RELA R_X86_64_GLOB_DAT
+-# The TLS-enabled version of these functions is interposed from libc.so.
+-ld.so: _dl_signal_error + RELA R_X86_64_GLOB_DAT
+-ld.so: _dl_catch_error + RELA R_X86_64_GLOB_DAT
+-ld.so: _dl_signal_exception + RELA R_X86_64_GLOB_DAT
+-ld.so: _dl_catch_exception + RELA R_X86_64_GLOB_DAT
diff --git a/SOURCES/glibc-RHEL-46979-3.patch b/SOURCES/glibc-RHEL-46979-3.patch
new file mode 100644
index 0000000000000000000000000000000000000000..de8b39020c1a34e9de9ccab54f96bbf8da986e91
--- /dev/null
+++ b/SOURCES/glibc-RHEL-46979-3.patch
@@ -0,0 +1,82 @@
+Extra changes needed for backport:
+
+* rename field "rtld_catch" to "rtld_catch_f" to avoid conflict
+  between "struct rtld-catch" and rtld_catch macro
+
+* move rtld_catch into one of the unused padding fields to preserve
+  ABI
+
+* Validate that the padding fields used don't overlap other fields.
+
+diff -rup a/elf/dl-catch.c b/elf/dl-catch.c
+--- a/elf/dl-catch.c	2024-09-04 16:30:02.086402568 -0400
++++ b/elf/dl-catch.c	2024-09-04 16:55:01.933440181 -0400
+@@ -59,7 +59,7 @@ get_catch (void)
+     return rtld_catch_notls;
+   else
+ #endif
+-    return THREAD_GETMEM (THREAD_SELF, rtld_catch);
++    return THREAD_GETMEM (THREAD_SELF, rtld_catch_f);
+ }
+ 
+ static void
+@@ -70,7 +70,7 @@ set_catch (struct rtld_catch *catch)
+     rtld_catch_notls = catch;
+   else
+ #endif
+-    THREAD_SETMEM (THREAD_SELF, rtld_catch, catch);
++    THREAD_SETMEM (THREAD_SELF, rtld_catch_f, catch);
+ }
+ 
+ /* Lossage while resolving the program's own symbols is always fatal.  */
+diff -rup a/nptl/descr.h b/nptl/descr.h
+--- a/nptl/descr.h	2024-08-29 11:29:16.801811033 -0400
++++ b/nptl/descr.h	2024-08-29 11:48:56.547644398 -0400
+@@ -164,6 +164,12 @@ struct pthread
+     void *__padding[24];
+   };
+ 
++#ifdef __x86_64__
++#define rtld_catch_f header.__padding[7]
++#else
++#define rtld_catch_f __padding[23]
++#endif
++
+   /* This descriptor's link on the GL (dl_stack_used) or
+      GL (dl_stack_user) list.  */
+   list_t list;
+@@ -396,9 +402,6 @@ struct pthread
+      masked.)  */
+   sigset_t sigmask;
+ 
+-  /* Used by the exception handling implementation in the dynamic loader.  */
+-  struct rtld_catch *rtld_catch;
+-
+   /* Indicates whether is a C11 thread created by thrd_creat.  */
+   bool c11;
+ 
+@@ -432,6 +435,12 @@ struct pthread
+    + sizeof ((struct pthread) {}.rseq_area))
+ } __attribute ((aligned (TCB_ALIGNMENT)));
+ 
++#ifdef __x86_64__
++_Static_assert (sizeof ((*(struct pthread *)0).header) > sizeof ((*(struct pthread *)0).__padding), "rtld_catch");
++#else
++_Static_assert (sizeof ((*(struct pthread *)0).header) < sizeof ((*(struct pthread *)0).__padding), "rtld_catch");
++#endif
++
+ static inline bool
+ cancel_enabled_and_canceled (int value)
+ {
+diff -rup a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h
+--- a/sysdeps/mach/hurd/i386/tls.h	2024-08-29 11:29:16.810811382 -0400
++++ b/sysdeps/mach/hurd/i386/tls.h	2024-08-29 11:35:45.262899113 -0400
+@@ -50,7 +50,7 @@ typedef struct
+   struct hurd_sigstate *_hurd_sigstate;
+ 
+   /* Used by the exception handling implementation in the dynamic loader.  */
+-  struct rtld_catch *rtld_catch;
++  struct rtld_catch *rtld_catch_f;
+ } tcbhead_t;
+ #endif
+ 
diff --git a/SOURCES/glibc-RHEL-46979-4.patch b/SOURCES/glibc-RHEL-46979-4.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d9d6985072ca30ff8f3fc3c7b83350931d2e5127
--- /dev/null
+++ b/SOURCES/glibc-RHEL-46979-4.patch
@@ -0,0 +1,79 @@
+New test case to verify padding usage.
+
+diff --git a/nptl/Makefile b/nptl/Makefile
+index ff4d590f11c38277..9a56d34313d06444 100644
+--- a/nptl/Makefile
++++ b/nptl/Makefile
+@@ -319,6 +319,8 @@ tests-internal := tst-robustpi8 tst-rwlock19 tst-rwlock20 \
+ 		  tst-barrier5 tst-signal7 tst-mutex8 tst-mutex8-static \
+ 		  tst-mutexpi8 tst-mutexpi8-static \
+ 		  tst-setgetname \
++		  tst-nptl-padding \
++		  # tests-internal
+ 
+ xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \
+ 	tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 tst-setgroups \
+diff --git a/nptl/tst-nptl-padding.c b/nptl/tst-nptl-padding.c
+new file mode 100644
+index 0000000000000000..5bb64f4a54335e36
+--- /dev/null
++++ b/nptl/tst-nptl-padding.c
+@@ -0,0 +1,57 @@
++/* Downstream-only test for verifying that fields that have been
++   relocated into struct pthread padding actually use the padding.
++
++   At present, only rtld_catch (downstream: rtld_catch_f) has been
++   placed into padding.  */
++
++#include <descr.h>
++#include <stddef.h>
++#include <stdint.h>
++#include <string.h>
++#include <support/check.h>
++
++static int
++do_test (void)
++{
++  struct pthread descr;
++
++  /* Mark the entire descriptor as used.  */
++  memset (&descr, 0xff, sizeof (descr));
++
++  /* Mark the padding as unused.  */
++#ifdef __x86_64__
++  /* Special case: Usable padding is in the header.   */
++  memset (&descr.header.__padding, 0, sizeof (descr.header.__padding));
++#else
++  /* The padding should be directly adjacent to the first real
++     struct field.  */
++  TEST_COMPARE (sizeof (descr.__padding), offsetof (struct pthread, list));
++
++  /* Clear the unused tail of the padding.  */
++  {
++    char *base = (char *) &descr;
++    char *end_of_header = base + sizeof (descr.header);
++    char *end_of_padding = base + sizeof (descr.__padding);
++    memset (end_of_header, 0, end_of_padding - end_of_header);
++  }
++#endif
++
++  /* These fields are not in padding and should remain marked as used.   */
++  TEST_COMPARE (descr.header.gscope_flag, -1);
++  TEST_COMPARE ((intptr_t) descr.list.next, -1);
++  TEST_COMPARE ((intptr_t) descr.list.prev, -1);
++
++  /* But this field remains in padding.  */
++  TEST_COMPARE ((intptr_t) descr.rtld_catch_f, 0);
++
++  /* Write to all padding-relocated fields below to show that they
++     have independent locations.  */
++  struct rtld_catch *rtld_catch_dummy = (void *) "rtld_catch_dummy";
++  descr.rtld_catch_f = rtld_catch_dummy;
++
++  TEST_VERIFY (descr.rtld_catch_f == rtld_catch_dummy);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+
diff --git a/SOURCES/glibc-RHEL-49489-1.patch b/SOURCES/glibc-RHEL-49489-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..3f2d6d8c9c9de580e20ccbb47e50b6903fa7c7cc
--- /dev/null
+++ b/SOURCES/glibc-RHEL-49489-1.patch
@@ -0,0 +1,51 @@
+commit 9b7651410375ec8848a1944992d663d514db4ba7
+Author: Stefan Liebler <stli@linux.ibm.com>
+Date:   Thu Jul 11 11:28:53 2024 +0200
+
+    s390x: Fix segfault in wcsncmp [BZ #31934]
+    
+    The z13/vector-optimized wcsncmp implementation segfaults if n=1
+    and there is only one character (equal on both strings) before
+    the page end.  Then it loads and compares one character and misses
+    to check n again.  The following load fails.
+    
+    This patch removes the extra load and compare of the first character
+    and just start with the loop which uses vector-load-to-block-boundary.
+    This code-path also checks n.
+    
+    With this patch both tests are passing:
+    - the simplified one mentioned in the bugzilla 31934
+    - the full one in Florian Weimer's patch:
+    "manual: Document a GNU extension for strncmp/wcsncmp"
+    (https://patchwork.sourceware.org/project/glibc/patch/874j9eml6y.fsf@oldenburg.str.redhat.com/):
+    On s390x-linux-gnu (z16), the new wcsncmp test fails due to bug 31934.
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+diff --git a/sysdeps/s390/wcsncmp-vx.S b/sysdeps/s390/wcsncmp-vx.S
+index bf6dfa6bc2..8b081567a2 100644
+--- a/sysdeps/s390/wcsncmp-vx.S
++++ b/sysdeps/s390/wcsncmp-vx.S
+@@ -59,14 +59,7 @@ ENTRY(WCSNCMP_Z13)
+ 	sllg	%r4,%r4,2	/* Convert character-count to byte-count.  */
+ 	locgrne	%r4,%r1		/* Use max byte-count, if bit 0/1 was one.  */
+ 
+-	/* Check first character without vector load.  */
+-	lghi	%r5,4		/* current_len = 4 bytes.  */
+-	/* Check s1/2[0].  */
+-	lt	%r0,0(%r2)
+-	l	%r1,0(%r3)
+-	je	.Lend_cmp_one_char
+-	crjne	%r0,%r1,.Lend_cmp_one_char
+-
++	lghi	%r5,0		/* current_len = 0 bytes.  */
+ .Lloop:
+ 	vlbb	%v17,0(%r5,%r3),6 /* Load s2 to block boundary.  */
+ 	vlbb	%v16,0(%r5,%r2),6 /* Load s1 to block boundary.  */
+@@ -167,7 +160,6 @@ ENTRY(WCSNCMP_Z13)
+ 	srl	%r4,2		/* And convert it to character-index.  */
+ 	vlgvf	%r0,%v16,0(%r4)	/* Load character-values.  */
+ 	vlgvf	%r1,%v17,0(%r4)
+-.Lend_cmp_one_char:
+ 	cr	%r0,%r1
+ 	je	.Lend_equal
+ 	lghi	%r2,1
diff --git a/SOURCES/glibc-RHEL-49489-2.patch b/SOURCES/glibc-RHEL-49489-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6802b1fd398e91f4d3b038e930aba5a995358830
--- /dev/null
+++ b/SOURCES/glibc-RHEL-49489-2.patch
@@ -0,0 +1,248 @@
+commit 54252394c25ddf0062e288d4a6ab7a885f8ae009
+Author: Florian Weimer <fweimer@redhat.com>
+Date:   Thu Jun 27 16:26:56 2024 +0200
+
+    Enhanced test coverage for strncmp, wcsncmp
+
+    Add string/test-strncmp-nonarray and
+    wcsmbs/test-wcsncmp-nonarray.
+
+    This is the test that uncovered bug 31934.  Test run time
+    is more than one minute on a fairly current system, so turn
+    these into xtests that do not run automatically.
+
+    Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
+
+diff -Nrup a/string/Makefile b/string/Makefile
+--- a/string/Makefile	2024-09-03 11:42:30.396319962 -0400
++++ b/string/Makefile	2024-09-03 11:52:17.707438963 -0400
+@@ -76,7 +76,10 @@ tests-unsupported += $(tests-translation
+ endif
+ 
+ # This test allocates a lot of memory and can run for a long time.
+-xtests = tst-strcoll-overflow
++xtests += tst-strcoll-overflow
++
++# This test runs for a long time.
++xtests += test-strncmp-nonarray
+ 
+ # This test needs libdl.
+ ifeq (yes,$(build-shared))
+diff -Nrup a/string/test-Xncmp-nonarray.c b/string/test-Xncmp-nonarray.c
+--- a/string/test-Xncmp-nonarray.c	1969-12-31 19:00:00.000000000 -0500
++++ b/string/test-Xncmp-nonarray.c	2024-09-03 11:52:17.707438963 -0400
+@@ -0,0 +1,183 @@
++/* Test non-array inputs to string comparison functions.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++/* This skeleton file is included from string/test-strncmp-nonarray.c and
++   wcsmbs/test-wcsncmp-nonarray.c to test that reading of the arrays stops
++   at the first null character.
++
++   TEST_IDENTIFIER must be the test function identifier.  TEST_NAME is
++   the same as a string.
++
++   CHAR must be defined as the character type.  */
++
++#include <array_length.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/next_to_fault.h>
++#include <support/test-driver.h>
++#include <sys/param.h>
++#include <unistd.h>
++
++/* Much shorter than test-Xnlen-nonarray.c because of deeply nested loops.  */
++enum { buffer_length = 80 };
++
++/* The test buffer layout follows what is described test-Xnlen-nonarray.c,
++   except that there two buffers, left and right.  The variables
++   a_count, zero_count, start_offset are all duplicated.  */
++
++/* Return the maximum string length for a string that starts at
++   start_offset.  */
++static int
++string_length (int a_count, int start_offset)
++{
++  if (start_offset == buffer_length || start_offset >= a_count)
++    return 0;
++  else
++    return a_count - start_offset;
++}
++
++/* This is the valid maximum length argument computation for
++   strnlen/wcsnlen.  See text-Xnlen-nonarray.c.  */
++static int
++maximum_length (int start_offset, int zero_count)
++{
++  if (start_offset == buffer_length)
++    return 0;
++  else if (zero_count > 0)
++    /* Effectively unbounded, but we need to stop fairly low,
++       otherwise testing takes too long.  */
++    return buffer_length + 32;
++  else
++    return buffer_length - start_offset;
++}
++
++typedef __typeof (TEST_IDENTIFIER) *proto_t;
++
++#define TEST_MAIN
++#include "test-string.h"
++
++IMPL (TEST_IDENTIFIER, 1)
++
++static int
++test_main (void)
++{
++  TEST_VERIFY_EXIT (sysconf (_SC_PAGESIZE) >= buffer_length);
++  test_init ();
++
++  struct support_next_to_fault left_ntf
++    = support_next_to_fault_allocate (buffer_length * sizeof (CHAR));
++  CHAR *left_buffer = (CHAR *) left_ntf.buffer;
++  struct support_next_to_fault right_ntf
++    = support_next_to_fault_allocate (buffer_length * sizeof (CHAR));
++  CHAR *right_buffer = (CHAR *) right_ntf.buffer;
++
++  FOR_EACH_IMPL (impl, 0)
++    {
++      printf ("info: testing %s\n", impl->name);
++      for (size_t i = 0; i < buffer_length; ++i)
++        left_buffer[i] = 'A';
++
++      for (int left_zero_count = 0; left_zero_count <= buffer_length;
++           ++left_zero_count)
++        {
++          if (left_zero_count > 0)
++            left_buffer[buffer_length - left_zero_count] = 0;
++          int left_a_count = buffer_length - left_zero_count;
++          for (size_t i = 0; i < buffer_length; ++i)
++            right_buffer[i] = 'A';
++          for (int right_zero_count = 0; right_zero_count <= buffer_length;
++               ++right_zero_count)
++            {
++              if (right_zero_count > 0)
++                right_buffer[buffer_length - right_zero_count] = 0;
++              int right_a_count = buffer_length - right_zero_count;
++              for (int left_start_offset = 0;
++                   left_start_offset <= buffer_length;
++                   ++left_start_offset)
++                {
++                  CHAR *left_start_pointer = left_buffer + left_start_offset;
++                  int left_maxlen
++                    = maximum_length (left_start_offset, left_zero_count);
++                  int left_length
++                    = string_length (left_a_count, left_start_offset);
++                  for (int right_start_offset = 0;
++                       right_start_offset <= buffer_length;
++                       ++right_start_offset)
++                    {
++                      CHAR *right_start_pointer
++                        = right_buffer + right_start_offset;
++                      int right_maxlen
++                        = maximum_length (right_start_offset, right_zero_count);
++                      int right_length
++                        = string_length (right_a_count, right_start_offset);
++
++                      /* Maximum length is modelled after strnlen/wcsnlen,
++                         and must be valid for both pointer arguments at
++                         the same time.  */
++                      int maxlen = MIN (left_maxlen, right_maxlen);
++
++                      for (int length_argument = 0; length_argument <= maxlen;
++                           ++length_argument)
++                        {
++                          if (test_verbose)
++                            {
++                              printf ("left: zero_count=%d"
++                                      " a_count=%d start_offset=%d\n",
++                                      left_zero_count, left_a_count,
++                                      left_start_offset);
++                              printf ("right: zero_count=%d"
++                                      " a_count=%d start_offset=%d\n",
++                                      right_zero_count, right_a_count,
++                                      right_start_offset);
++                              printf ("length argument: %d\n",
++                                      length_argument);
++                            }
++
++                          /* Effective lengths bounded by length argument.
++                             The effective length determines the
++                             outcome of the comparison.  */
++                          int left_effective
++                            = MIN (left_length, length_argument);
++                          int right_effective
++                            = MIN (right_length, length_argument);
++                          if (left_effective == right_effective)
++                            TEST_COMPARE (CALL (impl,
++                                                left_start_pointer,
++                                                right_start_pointer,
++                                                length_argument), 0);
++                          else if (left_effective < right_effective)
++                            TEST_COMPARE (CALL (impl,
++                                                left_start_pointer,
++                                                right_start_pointer,
++                                                length_argument) < 0, 1);
++                          else
++                            TEST_COMPARE (CALL (impl,
++                                                left_start_pointer,
++                                                right_start_pointer,
++                                                length_argument) > 0, 1);
++                        }
++                    }
++                }
++            }
++        }
++    }
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff -Nrup a/string/test-strncmp-nonarray.c b/string/test-strncmp-nonarray.c
+--- a/string/test-strncmp-nonarray.c	1969-12-31 19:00:00.000000000 -0500
++++ b/string/test-strncmp-nonarray.c	2024-09-03 11:52:17.707438963 -0400
+@@ -0,0 +1,4 @@
++#define TEST_IDENTIFIER strncmp
++#define TEST_NAME "strncmp"
++typedef char CHAR;
++#include "test-Xncmp-nonarray.c"
+diff -Nrup a/wcsmbs/Makefile b/wcsmbs/Makefile
+--- a/wcsmbs/Makefile	2024-09-03 11:42:30.398319976 -0400
++++ b/wcsmbs/Makefile	2024-09-03 11:53:44.806049806 -0400
+@@ -56,6 +56,10 @@ tests := tst-wcstof wcsmbs-tst1 tst-wcsn
+ 	 $(addprefix test-,$(strop-tests)) tst-mbstowcs \
+ 	 test-wcsdup
+ 
++# This test runs for a long time.
++xtests += test-wcsncmp-nonarray
++
++
+ include ../Rules
+ 
+ ifeq ($(run-built-tests),yes)
+diff -Nrup a/wcsmbs/test-wcsncmp-nonarray.c b/wcsmbs/test-wcsncmp-nonarray.c
+--- a/wcsmbs/test-wcsncmp-nonarray.c	1969-12-31 19:00:00.000000000 -0500
++++ b/wcsmbs/test-wcsncmp-nonarray.c	2024-09-03 11:52:17.708438970 -0400
+@@ -0,0 +1,5 @@
++#include <wchar.h>
++#define TEST_IDENTIFIER wcsncmp
++#define TEST_NAME "wcsncmp"
++typedef wchar_t CHAR;
++#include "../string/test-Xncmp-nonarray.c"
diff --git a/SOURCES/glibc-RHEL-49489-3.patch b/SOURCES/glibc-RHEL-49489-3.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c81264073eb6a51a30aa02fc1991e8bc3ccfdad6
--- /dev/null
+++ b/SOURCES/glibc-RHEL-49489-3.patch
@@ -0,0 +1,327 @@
+commit 2f47198b04a02097f438ecb765306fa39568a006
+Author: Rajalakshmi Srinivasaraghavan <rajis@linux.ibm.com>
+Date:   Fri Dec 2 14:26:41 2022 -0600
+
+    powerpc64: Remove old strncmp optimization
+    
+    This patch cleans up the power4 strncmp optimization for powerpc64 which
+    is unlikely to be used anywhere.
+    
+    Tested on ppc64le with and without --disable-multi-arch flag.
+    
+    Reviewed-by: Paul E. Murphy <murphyp@linux.ibm.com>
+    Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+Conflicts:
+	sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S
+	sysdeps/powerpc/powerpc64/power4/strncmp.S
+	  (copyright year changes upstream)
+
+diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile
+index 626845a43c4e8ded..5b20dab108de14ab 100644
+--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile
++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile
+@@ -12,8 +12,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \
+ 		   strnlen-power8 strnlen-power7 strnlen-ppc64 \
+ 		   strcasecmp-power7 strcasecmp_l-power7 \
+ 		   strncase-power7 strncase_l-power7 \
+-		   strncmp-power8 strncmp-power7 \
+-		   strncmp-power4 strncmp-ppc64 \
++		   strncmp-power8 strncmp-power7 strncmp-ppc64 \
+ 		   strchr-power8 strchr-power7 strchr-ppc64 \
+ 		   strchrnul-power8 strchrnul-power7 strchrnul-ppc64 \
+ 		   strcpy-power8 strcpy-power7 strcpy-ppc64 stpcpy-power8 \
+diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
+index 7b83aa7b8ff28bb7..914e7d5e28a98b5d 100644
+--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
+@@ -177,8 +177,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
+ 			      __strncmp_power8)
+ 	      IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_ARCH_2_06,
+ 			      __strncmp_power7)
+-	      IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_POWER4,
+-			      __strncmp_power4)
+ 	      IFUNC_IMPL_ADD (array, i, strncmp, 1,
+ 			      __strncmp_ppc))
+ 
+diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S
+deleted file mode 100644
+index 6ead3b6374749e6a..0000000000000000
+--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S
++++ /dev/null
+@@ -1,23 +0,0 @@
+-/* Copyright (C) 2013-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
+-   <https://www.gnu.org/licenses/>.  */
+-
+-#define STRNCMP __strncmp_power4
+-
+-#undef libc_hidden_builtin_def
+-#define libc_hidden_builtin_def(name)
+-
+-#include <sysdeps/powerpc/powerpc64/power4/strncmp.S>
+diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
+index 2d2112285445a450..275a558e4afa7d61 100644
+--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
++++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
+@@ -26,7 +26,6 @@
+ # include "init-arch.h"
+ 
+ extern __typeof (strncmp) __strncmp_ppc attribute_hidden;
+-extern __typeof (strncmp) __strncmp_power4 attribute_hidden;
+ extern __typeof (strncmp) __strncmp_power7 attribute_hidden;
+ extern __typeof (strncmp) __strncmp_power8 attribute_hidden;
+ # ifdef __LITTLE_ENDIAN__
+@@ -46,7 +45,5 @@ libc_ifunc_redirected (__redirect_strncmp, strncmp,
+ 		       ? __strncmp_power8
+ 		       : (hwcap & PPC_FEATURE_ARCH_2_06)
+ 			 ? __strncmp_power7
+-			 : (hwcap & PPC_FEATURE_POWER4)
+-			   ? __strncmp_power4
+-			   : __strncmp_ppc);
++			 : __strncmp_ppc);
+ #endif
+diff --git a/sysdeps/powerpc/powerpc64/power4/strncmp.S b/sysdeps/powerpc/powerpc64/power4/strncmp.S
+deleted file mode 100644
+index cf5f4e5fb8fb2522..0000000000000000
+--- a/sysdeps/powerpc/powerpc64/power4/strncmp.S
++++ /dev/null
+@@ -1,225 +0,0 @@
+-/* Optimized strcmp implementation for PowerPC64.
+-   Copyright (C) 2003-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
+-   <https://www.gnu.org/licenses/>.  */
+-
+-#include <sysdep.h>
+-
+-#ifndef STRNCMP
+-# define STRNCMP strncmp
+-#endif
+-
+-/* See strlen.s for comments on how the end-of-string testing works.  */
+-
+-/* int [r3] strncmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5])  */
+-
+-ENTRY_TOCLESS (STRNCMP, 4)
+-	CALL_MCOUNT 3
+-
+-#define rTMP2	r0
+-#define rRTN	r3
+-#define rSTR1	r3	/* first string arg */
+-#define rSTR2	r4	/* second string arg */
+-#define rN	r5	/* max string length */
+-#define rWORD1	r6	/* current word in s1 */
+-#define rWORD2	r7	/* current word in s2 */
+-#define rWORD3  r10
+-#define rWORD4  r11
+-#define rFEFE	r8	/* constant 0xfefefefefefefeff (-0x0101010101010101) */
+-#define r7F7F	r9	/* constant 0x7f7f7f7f7f7f7f7f */
+-#define rNEG	r10	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
+-#define rBITDIF	r11	/* bits that differ in s1 & s2 words */
+-#define rTMP	r12
+-
+-	dcbt	0,rSTR1
+-	or	rTMP, rSTR2, rSTR1
+-	lis	r7F7F, 0x7f7f
+-	dcbt	0,rSTR2
+-	clrldi.	rTMP, rTMP, 61
+-	cmpldi	cr1, rN, 0
+-	lis	rFEFE, -0x101
+-	bne	L(unaligned)
+-/* We are doubleword aligned so set up for two loops.  first a double word
+-   loop, then fall into the byte loop if any residual.  */
+-	srdi.	rTMP, rN, 3
+-	clrldi	rN, rN, 61
+-	addi	rFEFE, rFEFE, -0x101
+-	addi	r7F7F, r7F7F, 0x7f7f
+-	cmpldi	cr1, rN, 0
+-	beq	L(unaligned)
+-
+-	mtctr	rTMP	/* Power4 wants mtctr 1st in dispatch group.  */
+-	ld	rWORD1, 0(rSTR1)
+-	ld	rWORD2, 0(rSTR2)
+-	sldi	rTMP, rFEFE, 32
+-	insrdi	r7F7F, r7F7F, 32, 0
+-	add	rFEFE, rFEFE, rTMP
+-	b	L(g1)
+-
+-L(g0):
+-	ldu	rWORD1, 8(rSTR1)
+-	bne-	cr1, L(different)
+-	ldu	rWORD2, 8(rSTR2)
+-L(g1):	add	rTMP, rFEFE, rWORD1
+-	nor	rNEG, r7F7F, rWORD1
+-	bdz	L(tail)
+-	and.	rTMP, rTMP, rNEG
+-	cmpd	cr1, rWORD1, rWORD2
+-	beq+	L(g0)
+-
+-/* OK. We've hit the end of the string. We need to be careful that
+-   we don't compare two strings as different because of gunk beyond
+-   the end of the strings...  */
+-
+-#ifdef __LITTLE_ENDIAN__
+-L(endstring):
+-	addi    rTMP2, rTMP, -1
+-	beq	cr1, L(equal)
+-	andc    rTMP2, rTMP2, rTMP
+-	rldimi	rTMP2, rTMP2, 1, 0
+-	and	rWORD2, rWORD2, rTMP2	/* Mask off gunk.  */
+-	and	rWORD1, rWORD1, rTMP2
+-	cmpd	cr1, rWORD1, rWORD2
+-	beq	cr1, L(equal)
+-	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
+-	neg	rNEG, rBITDIF
+-	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
+-	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
+-	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
+-	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
+-	sld	rWORD2, rWORD2, rNEG
+-	xor.	rBITDIF, rWORD1, rWORD2
+-	sub	rRTN, rWORD1, rWORD2
+-	blt-	L(highbit)
+-	sradi	rRTN, rRTN, 63		/* must return an int.  */
+-	ori	rRTN, rRTN, 1
+-	blr
+-L(equal):
+-	li	rRTN, 0
+-	blr
+-
+-L(different):
+-	ld	rWORD1, -8(rSTR1)
+-	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
+-	neg	rNEG, rBITDIF
+-	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
+-	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
+-	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
+-	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
+-	sld	rWORD2, rWORD2, rNEG
+-	xor.	rBITDIF, rWORD1, rWORD2
+-	sub	rRTN, rWORD1, rWORD2
+-	blt-	L(highbit)
+-	sradi	rRTN, rRTN, 63
+-	ori	rRTN, rRTN, 1
+-	blr
+-L(highbit):
+-	sradi	rRTN, rWORD2, 63
+-	ori	rRTN, rRTN, 1
+-	blr
+-
+-#else
+-L(endstring):
+-	and	rTMP, r7F7F, rWORD1
+-	beq	cr1, L(equal)
+-	add	rTMP, rTMP, r7F7F
+-	xor.	rBITDIF, rWORD1, rWORD2
+-	andc	rNEG, rNEG, rTMP
+-	blt-	L(highbit)
+-	cntlzd	rBITDIF, rBITDIF
+-	cntlzd	rNEG, rNEG
+-	addi	rNEG, rNEG, 7
+-	cmpd	cr1, rNEG, rBITDIF
+-	sub	rRTN, rWORD1, rWORD2
+-	blt-	cr1, L(equal)
+-	sradi	rRTN, rRTN, 63		/* must return an int.  */
+-	ori	rRTN, rRTN, 1
+-	blr
+-L(equal):
+-	li	rRTN, 0
+-	blr
+-
+-L(different):
+-	ld	rWORD1, -8(rSTR1)
+-	xor.	rBITDIF, rWORD1, rWORD2
+-	sub	rRTN, rWORD1, rWORD2
+-	blt-	L(highbit)
+-	sradi	rRTN, rRTN, 63
+-	ori	rRTN, rRTN, 1
+-	blr
+-L(highbit):
+-	sradi	rRTN, rWORD2, 63
+-	ori	rRTN, rRTN, 1
+-	blr
+-#endif
+-
+-/* Oh well.  In this case, we just do a byte-by-byte comparison.  */
+-	.align 4
+-L(tail):
+-	and.	rTMP, rTMP, rNEG
+-	cmpd	cr1, rWORD1, rWORD2
+-	bne-	L(endstring)
+-	addi	rSTR1, rSTR1, 8
+-	bne-	cr1, L(different)
+-	addi	rSTR2, rSTR2, 8
+-	cmpldi	cr1, rN, 0
+-L(unaligned):
+-	mtctr   rN	/* Power4 wants mtctr 1st in dispatch group */
+-	ble	cr1, L(ux)
+-L(uz):
+-	lbz	rWORD1, 0(rSTR1)
+-	lbz	rWORD2, 0(rSTR2)
+-	.align 4
+-L(u1):
+-	cmpdi	cr1, rWORD1, 0
+-	bdz	L(u4)
+-	cmpd	rWORD1, rWORD2
+-	beq-	cr1, L(u4)
+-	bne-	L(u4)
+-	lbzu    rWORD3, 1(rSTR1)
+-	lbzu	rWORD4, 1(rSTR2)
+-	cmpdi	cr1, rWORD3, 0
+-	bdz	L(u3)
+-	cmpd	rWORD3, rWORD4
+-	beq-    cr1, L(u3)
+-	bne-    L(u3)
+-	lbzu	rWORD1, 1(rSTR1)
+-	lbzu	rWORD2, 1(rSTR2)
+-	cmpdi	cr1, rWORD1, 0
+-	bdz	L(u4)
+-	cmpd	rWORD1, rWORD2
+-	beq-	cr1, L(u4)
+-	bne-	L(u4)
+-	lbzu	rWORD3, 1(rSTR1)
+-	lbzu	rWORD4, 1(rSTR2)
+-	cmpdi	cr1, rWORD3, 0
+-	bdz	L(u3)
+-	cmpd	rWORD3, rWORD4
+-	beq-    cr1, L(u3)
+-	bne-    L(u3)
+-	lbzu	rWORD1, 1(rSTR1)
+-	lbzu	rWORD2, 1(rSTR2)
+-	b       L(u1)
+-
+-L(u3):  sub     rRTN, rWORD3, rWORD4
+-	blr
+-L(u4):	sub	rRTN, rWORD1, rWORD2
+-	blr
+-L(ux):
+-	li	rRTN, 0
+-	blr
+-END (STRNCMP)
+-libc_hidden_builtin_def (strncmp)
diff --git a/SOURCES/glibc-RHEL-49489-4.patch b/SOURCES/glibc-RHEL-49489-4.patch
new file mode 100644
index 0000000000000000000000000000000000000000..bc22daa712bcfbddcc210421d3d430e8c644f77a
--- /dev/null
+++ b/SOURCES/glibc-RHEL-49489-4.patch
@@ -0,0 +1,595 @@
+commit 92fdb11ae7aa1ab6b18622670ea702205cd6fdc5
+Author: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
+Date:   Tue Feb 28 14:23:59 2023 -0300
+
+    powerpc: Remove powerpc64 strncmp variants
+    
+    The default, and power7 implementation just adds word aligned
+    access when inputs have the same aligment.  The unaligned case
+    is still done by byte operations.
+    
+    This is already covered by the generic implementation, which also add
+    the unaligned input optimization.
+    
+    Checked on powerpc64-linux-gnu built without multi-arch for powerpc64,
+    power7, power8, and power9 (build for le).
+    Reviewed-by: Rajalakshmi Srinivasaraghavan <rajis@linux.ibm.com>
+
+Conflicts:
+	sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S
+	sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S
+	sysdeps/powerpc/powerpc64/power7/strncmp.S
+	sysdeps/powerpc/powerpc64/strncmp.S
+	  (copyright year changes upstream)
+
+diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile
+index 5b20dab108de14ab..0ee7ce39d6470d80 100644
+--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile
++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile
+@@ -12,7 +12,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \
+ 		   strnlen-power8 strnlen-power7 strnlen-ppc64 \
+ 		   strcasecmp-power7 strcasecmp_l-power7 \
+ 		   strncase-power7 strncase_l-power7 \
+-		   strncmp-power8 strncmp-power7 strncmp-ppc64 \
++		   strncmp-power8 strncmp-ppc64 \
+ 		   strchr-power8 strchr-power7 strchr-ppc64 \
+ 		   strchrnul-power8 strchrnul-power7 strchrnul-ppc64 \
+ 		   strcpy-power8 strcpy-power7 strcpy-ppc64 stpcpy-power8 \
+diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
+index 914e7d5e28a98b5d..2c84d287ee76a7ea 100644
+--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
+@@ -175,8 +175,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
+ #endif
+ 	      IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_2_07,
+ 			      __strncmp_power8)
+-	      IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_ARCH_2_06,
+-			      __strncmp_power7)
+ 	      IFUNC_IMPL_ADD (array, i, strncmp, 1,
+ 			      __strncmp_ppc))
+ 
+diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S
+deleted file mode 100644
+index 8282ff076c9e00ce..0000000000000000
+--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S
++++ /dev/null
+@@ -1,23 +0,0 @@
+-/* Copyright (C) 2013-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
+-   <https://www.gnu.org/licenses/>.  */
+-
+-#define STRNCMP __strncmp_power7
+-
+-#undef libc_hidden_builtin_def
+-#define libc_hidden_builtin_def(name)
+-
+-#include <sysdeps/powerpc/powerpc64/power7/strncmp.S>
+diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S
+deleted file mode 100644
+index c6f325650c9ace3b..0000000000000000
+--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S
++++ /dev/null
+@@ -1,26 +0,0 @@
+-/* Copyright (C) 2013-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
+-   <https://www.gnu.org/licenses/>.  */
+-
+-#if defined SHARED && IS_IN (libc)
+-# define STRNCMP __strncmp_ppc
+-
+-# undef libc_hidden_builtin_def
+-# define libc_hidden_builtin_def(name)				\
+-    .globl __GI_strncmp; __GI_strncmp = __strncmp_ppc
+-#endif
+-
+-#include <sysdeps/powerpc/powerpc64/strncmp.S>
+diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c
+new file mode 100644
+index 0000000000000000..09cc009a913ed169
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c
+@@ -0,0 +1,7 @@
++#if defined SHARED && IS_IN (libc)
++# define STRNCMP __strncmp_ppc
++# undef libc_hidden_builtin_def
++# define libc_hidden_builtin_def(name) \
++    __hidden_ver1 (__strncmp_ppc, __GI_strncmp, __strncmp_ppc);
++#endif
++#include <string/strncmp.c>
+diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
+index 275a558e4afa7d61..df2c0707a919ad79 100644
+--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
++++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
+@@ -26,7 +26,6 @@
+ # include "init-arch.h"
+ 
+ extern __typeof (strncmp) __strncmp_ppc attribute_hidden;
+-extern __typeof (strncmp) __strncmp_power7 attribute_hidden;
+ extern __typeof (strncmp) __strncmp_power8 attribute_hidden;
+ # ifdef __LITTLE_ENDIAN__
+ extern __typeof (strncmp) __strncmp_power9 attribute_hidden;
+@@ -43,7 +42,5 @@ libc_ifunc_redirected (__redirect_strncmp, strncmp,
+ # endif
+ 		       (hwcap2 & PPC_FEATURE2_ARCH_2_07)
+ 		       ? __strncmp_power8
+-		       : (hwcap & PPC_FEATURE_ARCH_2_06)
+-			 ? __strncmp_power7
+-			 : __strncmp_ppc);
++		       : __strncmp_ppc);
+ #endif
+diff --git a/sysdeps/powerpc/powerpc64/power7/strncmp.S b/sysdeps/powerpc/powerpc64/power7/strncmp.S
+deleted file mode 100644
+index d91aeb6077a558f2..0000000000000000
+--- a/sysdeps/powerpc/powerpc64/power7/strncmp.S
++++ /dev/null
+@@ -1,228 +0,0 @@
+-/* Optimized strcmp implementation for POWER7/PowerPC64.
+-   Copyright (C) 2010-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
+-   <https://www.gnu.org/licenses/>.  */
+-
+-#include <sysdep.h>
+-
+-#ifndef STRNCMP
+-# define STRNCMP strncmp
+-#endif
+-
+-/* See strlen.s for comments on how the end-of-string testing works.  */
+-
+-/* int [r3] strncmp (const char *s1 [r3],
+-		     const char *s2 [r4],
+-		     size_t size [r5])  */
+-
+-	.machine power7
+-ENTRY_TOCLESS (STRNCMP, 5)
+-	CALL_MCOUNT 3
+-
+-#define rTMP2	r0
+-#define rRTN	r3
+-#define rSTR1	r3	/* first string arg */
+-#define rSTR2	r4	/* second string arg */
+-#define rN	r5	/* max string length */
+-#define rWORD1	r6	/* current word in s1 */
+-#define rWORD2	r7	/* current word in s2 */
+-#define rWORD3  r10
+-#define rWORD4  r11
+-#define rFEFE	r8	/* constant 0xfefefefefefefeff (-0x0101010101010101) */
+-#define r7F7F	r9	/* constant 0x7f7f7f7f7f7f7f7f */
+-#define rNEG	r10	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
+-#define rBITDIF	r11	/* bits that differ in s1 & s2 words */
+-#define rTMP	r12
+-
+-	dcbt	0,rSTR1
+-	nop
+-	or	rTMP,rSTR2,rSTR1
+-	lis	r7F7F,0x7f7f
+-	dcbt	0,rSTR2
+-	nop
+-	clrldi.	rTMP,rTMP,61
+-	cmpldi	cr1,rN,0
+-	lis	rFEFE,-0x101
+-	bne	L(unaligned)
+-/* We are doubleword aligned so set up for two loops.  first a double word
+-   loop, then fall into the byte loop if any residual.  */
+-	srdi.	rTMP,rN,3
+-	clrldi	rN,rN,61
+-	addi	rFEFE,rFEFE,-0x101
+-	addi	r7F7F,r7F7F,0x7f7f
+-	cmpldi	cr1,rN,0
+-	beq	L(unaligned)
+-
+-	mtctr	rTMP
+-	ld	rWORD1,0(rSTR1)
+-	ld	rWORD2,0(rSTR2)
+-	sldi	rTMP,rFEFE,32
+-	insrdi	r7F7F,r7F7F,32,0
+-	add	rFEFE,rFEFE,rTMP
+-	b	L(g1)
+-
+-L(g0):
+-	ldu	rWORD1,8(rSTR1)
+-	bne	cr1,L(different)
+-	ldu	rWORD2,8(rSTR2)
+-L(g1):	add	rTMP,rFEFE,rWORD1
+-	nor	rNEG,r7F7F,rWORD1
+-	bdz	L(tail)
+-	and.	rTMP,rTMP,rNEG
+-	cmpd	cr1,rWORD1,rWORD2
+-	beq	L(g0)
+-
+-/* OK. We've hit the end of the string. We need to be careful that
+-   we don't compare two strings as different because of gunk beyond
+-   the end of the strings...  */
+-
+-#ifdef __LITTLE_ENDIAN__
+-L(endstring):
+-	addi    rTMP2, rTMP, -1
+-	beq	cr1, L(equal)
+-	andc    rTMP2, rTMP2, rTMP
+-	rldimi	rTMP2, rTMP2, 1, 0
+-	and	rWORD2, rWORD2, rTMP2	/* Mask off gunk.  */
+-	and	rWORD1, rWORD1, rTMP2
+-	cmpd	cr1, rWORD1, rWORD2
+-	beq	cr1, L(equal)
+-	cmpb	rBITDIF, rWORD1, rWORD2	/* 0xff on equal bytes.  */
+-	addi	rNEG, rBITDIF, 1
+-	orc	rNEG, rNEG, rBITDIF	/* 0's below LS differing byte.  */
+-	sldi	rNEG, rNEG, 8		/* 1's above LS differing byte.  */
+-	andc	rWORD1, rWORD1, rNEG	/* mask off MS bytes.  */
+-	andc	rWORD2, rWORD2, rNEG
+-	xor.	rBITDIF, rWORD1, rWORD2
+-	sub	rRTN, rWORD1, rWORD2
+-	blt	L(highbit)
+-	sradi	rRTN, rRTN, 63		/* must return an int.  */
+-	ori	rRTN, rRTN, 1
+-	blr
+-L(equal):
+-	li	rRTN, 0
+-	blr
+-
+-L(different):
+-	ld	rWORD1, -8(rSTR1)
+-	cmpb	rBITDIF, rWORD1, rWORD2	/* 0xff on equal bytes.  */
+-	addi	rNEG, rBITDIF, 1
+-	orc	rNEG, rNEG, rBITDIF	/* 0's below LS differing byte.  */
+-	sldi	rNEG, rNEG, 8		/* 1's above LS differing byte.  */
+-	andc	rWORD1, rWORD1, rNEG	/* mask off MS bytes.  */
+-	andc	rWORD2, rWORD2, rNEG
+-	xor.	rBITDIF, rWORD1, rWORD2
+-	sub	rRTN, rWORD1, rWORD2
+-	blt	L(highbit)
+-	sradi	rRTN, rRTN, 63
+-	ori	rRTN, rRTN, 1
+-	blr
+-L(highbit):
+-	sradi	rRTN, rWORD2, 63
+-	ori	rRTN, rRTN, 1
+-	blr
+-
+-#else
+-L(endstring):
+-	and	rTMP,r7F7F,rWORD1
+-	beq	cr1,L(equal)
+-	add	rTMP,rTMP,r7F7F
+-	xor.	rBITDIF,rWORD1,rWORD2
+-	andc	rNEG,rNEG,rTMP
+-	blt	L(highbit)
+-	cntlzd	rBITDIF,rBITDIF
+-	cntlzd	rNEG,rNEG
+-	addi	rNEG,rNEG,7
+-	cmpd	cr1,rNEG,rBITDIF
+-	sub	rRTN,rWORD1,rWORD2
+-	blt	cr1,L(equal)
+-	sradi	rRTN,rRTN,63		/* must return an int.  */
+-	ori	rRTN,rRTN,1
+-	blr
+-L(equal):
+-	li	rRTN,0
+-	blr
+-
+-L(different):
+-	ld	rWORD1,-8(rSTR1)
+-	xor.	rBITDIF,rWORD1,rWORD2
+-	sub	rRTN,rWORD1,rWORD2
+-	blt	L(highbit)
+-	sradi	rRTN,rRTN,63
+-	ori	rRTN,rRTN,1
+-	blr
+-L(highbit):
+-	sradi	rRTN,rWORD2,63
+-	ori	rRTN,rRTN,1
+-	blr
+-#endif
+-
+-/* Oh well.  In this case, we just do a byte-by-byte comparison.  */
+-	.align	4
+-L(tail):
+-	and.	rTMP,rTMP,rNEG
+-	cmpd	cr1,rWORD1,rWORD2
+-	bne	L(endstring)
+-	addi	rSTR1,rSTR1,8
+-	bne	cr1,L(different)
+-	addi	rSTR2,rSTR2,8
+-	cmpldi	cr1,rN,0
+-L(unaligned):
+-	mtctr	rN
+-	ble	cr1,L(ux)
+-L(uz):
+-	lbz	rWORD1,0(rSTR1)
+-	lbz	rWORD2,0(rSTR2)
+-	.align	4
+-L(u1):
+-	cmpdi	cr1,rWORD1,0
+-	bdz	L(u4)
+-	cmpd	rWORD1,rWORD2
+-	beq	cr1,L(u4)
+-	bne	L(u4)
+-	lbzu	rWORD3,1(rSTR1)
+-	lbzu	rWORD4,1(rSTR2)
+-	cmpdi	cr1,rWORD3,0
+-	bdz	L(u3)
+-	cmpd	rWORD3,rWORD4
+-	beq	cr1,L(u3)
+-	bne	L(u3)
+-	lbzu	rWORD1,1(rSTR1)
+-	lbzu	rWORD2,1(rSTR2)
+-	cmpdi	cr1,rWORD1,0
+-	bdz	L(u4)
+-	cmpd	rWORD1,rWORD2
+-	beq	cr1,L(u4)
+-	bne	L(u4)
+-	lbzu	rWORD3,1(rSTR1)
+-	lbzu	rWORD4,1(rSTR2)
+-	cmpdi	cr1,rWORD3,0
+-	bdz	L(u3)
+-	cmpd	rWORD3,rWORD4
+-	beq	cr1,L(u3)
+-	bne	L(u3)
+-	lbzu	rWORD1,1(rSTR1)
+-	lbzu	rWORD2,1(rSTR2)
+-	b	L(u1)
+-
+-L(u3):  sub	rRTN,rWORD3,rWORD4
+-	blr
+-L(u4):	sub	rRTN,rWORD1,rWORD2
+-	blr
+-L(ux):
+-	li	rRTN,0
+-	blr
+-END (STRNCMP)
+-libc_hidden_builtin_def (strncmp)
+diff --git a/sysdeps/powerpc/powerpc64/strncmp.S b/sysdeps/powerpc/powerpc64/strncmp.S
+deleted file mode 100644
+index 40a230242cbdf733..0000000000000000
+--- a/sysdeps/powerpc/powerpc64/strncmp.S
++++ /dev/null
+@@ -1,210 +0,0 @@
+-/* Optimized strcmp implementation for PowerPC64.
+-   Copyright (C) 2003-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
+-   <https://www.gnu.org/licenses/>.  */
+-
+-#include <sysdep.h>
+-
+-/* See strlen.s for comments on how the end-of-string testing works.  */
+-
+-/* int [r3] strncmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5])  */
+-
+-#ifndef STRNCMP
+-# define STRNCMP strncmp
+-#endif
+-
+-ENTRY_TOCLESS (STRNCMP, 4)
+-	CALL_MCOUNT 3
+-
+-#define rTMP2	r0
+-#define rRTN	r3
+-#define rSTR1	r3	/* first string arg */
+-#define rSTR2	r4	/* second string arg */
+-#define rN	r5	/* max string length */
+-#define rWORD1	r6	/* current word in s1 */
+-#define rWORD2	r7	/* current word in s2 */
+-#define rFEFE	r8	/* constant 0xfefefefefefefeff (-0x0101010101010101) */
+-#define r7F7F	r9	/* constant 0x7f7f7f7f7f7f7f7f */
+-#define rNEG	r10	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
+-#define rBITDIF	r11	/* bits that differ in s1 & s2 words */
+-#define rTMP	r12
+-
+-	dcbt	0,rSTR1
+-	or	rTMP, rSTR2, rSTR1
+-	lis	r7F7F, 0x7f7f
+-	dcbt	0,rSTR2
+-	clrldi.	rTMP, rTMP, 61
+-	cmpldi	cr1, rN, 0
+-	lis	rFEFE, -0x101
+-	bne	L(unaligned)
+-/* We are doubleword aligned so set up for two loops.  first a double word
+-   loop, then fall into the byte loop if any residual.  */
+-	srdi.	rTMP, rN, 3
+-	clrldi	rN, rN, 61
+-	addi	rFEFE, rFEFE, -0x101
+-	addi	r7F7F, r7F7F, 0x7f7f
+-	cmpldi	cr1, rN, 0
+-	beq	L(unaligned)
+-
+-	mtctr	rTMP	/* Power4 wants mtctr 1st in dispatch group.  */
+-	ld	rWORD1, 0(rSTR1)
+-	ld	rWORD2, 0(rSTR2)
+-	sldi	rTMP, rFEFE, 32
+-	insrdi	r7F7F, r7F7F, 32, 0
+-	add	rFEFE, rFEFE, rTMP
+-	b	L(g1)
+-
+-L(g0):
+-	ldu	rWORD1, 8(rSTR1)
+-	bne-	cr1, L(different)
+-	ldu	rWORD2, 8(rSTR2)
+-L(g1):	add	rTMP, rFEFE, rWORD1
+-	nor	rNEG, r7F7F, rWORD1
+-	bdz	L(tail)
+-	and.	rTMP, rTMP, rNEG
+-	cmpd	cr1, rWORD1, rWORD2
+-	beq+	L(g0)
+-
+-/* OK. We've hit the end of the string. We need to be careful that
+-   we don't compare two strings as different because of gunk beyond
+-   the end of the strings...  */
+-
+-#ifdef __LITTLE_ENDIAN__
+-L(endstring):
+-	addi    rTMP2, rTMP, -1
+-	beq	cr1, L(equal)
+-	andc    rTMP2, rTMP2, rTMP
+-	rldimi	rTMP2, rTMP2, 1, 0
+-	and	rWORD2, rWORD2, rTMP2	/* Mask off gunk.  */
+-	and	rWORD1, rWORD1, rTMP2
+-	cmpd	cr1, rWORD1, rWORD2
+-	beq	cr1, L(equal)
+-	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
+-	neg	rNEG, rBITDIF
+-	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
+-	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
+-	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
+-	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
+-	sld	rWORD2, rWORD2, rNEG
+-	xor.	rBITDIF, rWORD1, rWORD2
+-	sub	rRTN, rWORD1, rWORD2
+-	blt-	L(highbit)
+-	sradi	rRTN, rRTN, 63		/* must return an int.  */
+-	ori	rRTN, rRTN, 1
+-	blr
+-L(equal):
+-	li	rRTN, 0
+-	blr
+-
+-L(different):
+-	ld	rWORD1, -8(rSTR1)
+-	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
+-	neg	rNEG, rBITDIF
+-	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
+-	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
+-	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
+-	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
+-	sld	rWORD2, rWORD2, rNEG
+-	xor.	rBITDIF, rWORD1, rWORD2
+-	sub	rRTN, rWORD1, rWORD2
+-	blt-	L(highbit)
+-	sradi	rRTN, rRTN, 63
+-	ori	rRTN, rRTN, 1
+-	blr
+-L(highbit):
+-	sradi	rRTN, rWORD2, 63
+-	ori	rRTN, rRTN, 1
+-	blr
+-
+-#else
+-L(endstring):
+-	and	rTMP, r7F7F, rWORD1
+-	beq	cr1, L(equal)
+-	add	rTMP, rTMP, r7F7F
+-	xor.	rBITDIF, rWORD1, rWORD2
+-	andc	rNEG, rNEG, rTMP
+-	blt-	L(highbit)
+-	cntlzd	rBITDIF, rBITDIF
+-	cntlzd	rNEG, rNEG
+-	addi	rNEG, rNEG, 7
+-	cmpd	cr1, rNEG, rBITDIF
+-	sub	rRTN, rWORD1, rWORD2
+-	blt-	cr1, L(equal)
+-	sradi	rRTN, rRTN, 63		/* must return an int.  */
+-	ori	rRTN, rRTN, 1
+-	blr
+-L(equal):
+-	li	rRTN, 0
+-	blr
+-
+-L(different):
+-	ld	rWORD1, -8(rSTR1)
+-	xor.	rBITDIF, rWORD1, rWORD2
+-	sub	rRTN, rWORD1, rWORD2
+-	blt-	L(highbit)
+-	sradi	rRTN, rRTN, 63
+-	ori	rRTN, rRTN, 1
+-	blr
+-L(highbit):
+-	sradi	rRTN, rWORD2, 63
+-	ori	rRTN, rRTN, 1
+-	blr
+-#endif
+-
+-/* Oh well.  In this case, we just do a byte-by-byte comparison.  */
+-	.align 4
+-L(tail):
+-	and.	rTMP, rTMP, rNEG
+-	cmpd	cr1, rWORD1, rWORD2
+-	bne-	L(endstring)
+-	addi	rSTR1, rSTR1, 8
+-	bne-	cr1, L(different)
+-	addi	rSTR2, rSTR2, 8
+-	cmpldi	cr1, rN, 0
+-L(unaligned):
+-	mtctr   rN	/* Power4 wants mtctr 1st in dispatch group */
+-	bgt	cr1, L(uz)
+-L(ux):
+-	li	rRTN, 0
+-	blr
+-	.align 4
+-L(uz):
+-	lbz	rWORD1, 0(rSTR1)
+-	lbz	rWORD2, 0(rSTR2)
+-	nop
+-	b	L(u1)
+-L(u0):
+-	lbzu	rWORD2, 1(rSTR2)
+-L(u1):
+-	bdz	L(u3)
+-	cmpdi	cr1, rWORD1, 0
+-	cmpd	rWORD1, rWORD2
+-	beq-	cr1, L(u3)
+-	lbzu	rWORD1, 1(rSTR1)
+-	bne-	L(u2)
+-	lbzu	rWORD2, 1(rSTR2)
+-	bdz	L(u3)
+-	cmpdi	cr1, rWORD1, 0
+-	cmpd	rWORD1, rWORD2
+-	bne-	L(u3)
+-	lbzu	rWORD1, 1(rSTR1)
+-	bne+	cr1, L(u0)
+-
+-L(u2):	lbzu	rWORD1, -1(rSTR1)
+-L(u3):	sub	rRTN, rWORD1, rWORD2
+-	blr
+-END (STRNCMP)
+-libc_hidden_builtin_def (strncmp)
diff --git a/SOURCES/glibc-RHEL-50101-1.patch b/SOURCES/glibc-RHEL-50101-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..eb722e3c10026880b58aacbccdb65624c414da4b
--- /dev/null
+++ b/SOURCES/glibc-RHEL-50101-1.patch
@@ -0,0 +1,240 @@
+commit 3395157ff2b0657d70c36169156f67440205c8bf
+Author: Joe Simmons-Talbott <josimmon@redhat.com>
+Date:   Tue May 14 14:36:50 2024 +0000
+
+    malloc: Improve aligned_alloc and calloc test coverage.
+    
+    Add a DSO (malloc/tst-aligned_alloc-lib.so) that can be used during
+    testing to interpose malloc with a call that randomly uses either
+    aligned_alloc, __libc_malloc, or __libc_calloc in the place of malloc.
+    Use LD_PRELOAD with the DSO to mirror malloc/tst-malloc.c testing as an
+    example in malloc/tst-malloc-random.c.  Add malloc/tst-aligned-alloc-random.c
+    as another example that does a number of malloc calls with randomly sized,
+    but limited to 0xffff, requests.
+    
+    The intention is to be able to utilize existing malloc testing to ensure
+    that similar allocation APIs are also exposed to the same rigors.
+    
+    Reviewed-by: DJ Delorie <dj@redhat.com>
+
+Conflicts:
+	malloc/Makefile
+	  (usual tests conflict)
+
+diff --git a/malloc/Makefile b/malloc/Makefile
+index cb4e027d28b179f0..e0fb433a15bad2c2 100644
+--- a/malloc/Makefile
++++ b/malloc/Makefile
+@@ -44,6 +44,8 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
+ 	 tst-safe-linking \
+ 	 tst-mallocalign1 \
+ 	 tst-malloc-alternate-path \
++	 tst-aligned-alloc-random \
++	 tst-malloc-random \
+ 
+ tests-static := \
+ 	 tst-interpose-static-nothread \
+@@ -123,6 +125,7 @@ extra-libs-others = $(extra-libs)
+ 
+ # Helper objects for some tests.
+ extra-tests-objs += \
++  tst-aligned_alloc-lib.so \
+   tst-interpose-aux-nothread.o \
+   tst-interpose-aux-thread.o \
+ 
+@@ -130,6 +133,9 @@ test-extras = \
+   tst-interpose-aux-nothread \
+   tst-interpose-aux-thread \
+ 
++modules-names = \
++  tst-aligned_alloc-lib
++
+ libmemusage-routines = memusage
+ libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
+ 
+@@ -328,3 +334,9 @@ tst-mallocstate-malloc-check-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
+ # libc_malloc_debug.so.
+ $(objpfx)tst-mallocstate: $(objpfx)libc_malloc_debug.so
+ $(objpfx)tst-mallocstate-malloc-check: $(objpfx)libc_malloc_debug.so
++
++$(objpfx)tst-aligned-alloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
++$(objpfx)tst-malloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
++
++tst-aligned-alloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
++tst-malloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+diff --git a/malloc/tst-aligned-alloc-random.c b/malloc/tst-aligned-alloc-random.c
+new file mode 100644
+index 0000000000000000..f2825ce38f04e04e
+--- /dev/null
++++ b/malloc/tst-aligned-alloc-random.c
+@@ -0,0 +1,43 @@
++/* Test for randomized malloc that calls aligned_alloc
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <stdlib.h>
++#include <support/check.h>
++#include <time.h>
++
++static int
++do_test (void)
++{
++  void *p1;
++  int i;
++
++  srandom (time (NULL));
++
++  for (i = 0; i < 1024; i++)
++  {
++    size_t size = random () & 0xffff;
++
++    p1 = malloc (size);
++    TEST_VERIFY (p1 != NULL);
++  }
++
++  return 0;
++}
++
++
++#include <support/test-driver.c>
+diff --git a/malloc/tst-aligned_alloc-lib.c b/malloc/tst-aligned_alloc-lib.c
+new file mode 100644
+index 0000000000000000..0205df5acf6297a5
+--- /dev/null
++++ b/malloc/tst-aligned_alloc-lib.c
+@@ -0,0 +1,72 @@
++/* Module used for improved aligned_alloc testing.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   Copyright The GNU Toolchain Authors.
++   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; see the file COPYING.LIB.  If
++   not, see <https://www.gnu.org/licenses/>.  */
++
++#include <array_length.h>
++#include <libc-symbols.h>
++#include <stdlib.h>
++
++extern void *__libc_malloc (size_t size);
++extern void *__libc_calloc (size_t n, size_t size);
++
++int aligned_alloc_count = 0;
++int libc_malloc_count = 0;
++int libc_calloc_count = 0;
++
++/* Get a random alignment value.  Biased towards the smaller values.  Must be
++   a power of 2. */
++static size_t get_random_alignment (void)
++{
++  size_t aligns[] = {
++    1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384
++  };
++
++  return aligns[random () % array_length (aligns)];
++}
++
++static void *get_random_alloc (size_t size)
++{
++  void *retval;
++  size_t align;
++
++  switch (random() % 3)
++  {
++    case 1:
++      align = get_random_alignment ();
++      retval = aligned_alloc (align, size);
++      aligned_alloc_count++;
++      break;
++    case 2:
++      retval = __libc_calloc (1, size);
++      libc_calloc_count++;
++      break;
++    default:
++      retval = __libc_malloc (size);
++      libc_malloc_count++;
++      break;
++  }
++
++  return retval;
++}
++
++
++void * __random_malloc (size_t size)
++{
++  return get_random_alloc (size);
++}
++strong_alias (__random_malloc, malloc)
+diff --git a/malloc/tst-malloc-random.c b/malloc/tst-malloc-random.c
+new file mode 100644
+index 0000000000000000..762b70c918cc6004
+--- /dev/null
++++ b/malloc/tst-malloc-random.c
+@@ -0,0 +1,20 @@
++/* Test malloc with random calls to aligned_alloc and calloc.
++
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include "tst-malloc.c"
+diff --git a/malloc/tst-malloc.c b/malloc/tst-malloc.c
+index a587cbded66039fb..98be3ee254d75d4e 100644
+--- a/malloc/tst-malloc.c
++++ b/malloc/tst-malloc.c
+@@ -19,7 +19,9 @@
+ #include <errno.h>
+ #include <malloc.h>
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <libc-diag.h>
++#include <time.h>
+ 
+ static int errors = 0;
+ 
+@@ -36,6 +38,8 @@ do_test (void)
+   void *p, *q;
+   int save;
+ 
++  srandom (time (NULL));
++
+   errno = 0;
+ 
+   DIAG_PUSH_NEEDS_COMMENT;
diff --git a/SOURCES/glibc-RHEL-50101-2.patch b/SOURCES/glibc-RHEL-50101-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..318a0377e1a46a408e38b453f71ff714073a3555
--- /dev/null
+++ b/SOURCES/glibc-RHEL-50101-2.patch
@@ -0,0 +1,86 @@
+commit 9a27b566b2048f599048f2f4afe1cce06c4ef43d
+Author: Miguel Martín <mmartinv@redhat.com>
+Date:   Tue Jul 16 17:14:56 2024 +0200
+
+    malloc: avoid global locks in tst-aligned_alloc-lib.c
+    
+    Make sure the DSO used by aligned_alloc/calloc/malloc tests does not get
+    a global lock on multithreaded tests.
+    Reviewed-by: Arjun Shankar <arjun@redhat.com>
+
+diff --git a/malloc/tst-aligned_alloc-lib.c b/malloc/tst-aligned_alloc-lib.c
+index 0205df5acf6297a5..9ef1f839c101a6ae 100644
+--- a/malloc/tst-aligned_alloc-lib.c
++++ b/malloc/tst-aligned_alloc-lib.c
+@@ -17,37 +17,38 @@
+    License along with the GNU C Library; see the file COPYING.LIB.  If
+    not, see <https://www.gnu.org/licenses/>.  */
+ 
+-#include <array_length.h>
+ #include <libc-symbols.h>
+ #include <stdlib.h>
++#include <time.h>
+ 
+ extern void *__libc_malloc (size_t size);
+ extern void *__libc_calloc (size_t n, size_t size);
+ 
++__thread unsigned int seed = 0;
++
+ int aligned_alloc_count = 0;
+ int libc_malloc_count = 0;
+ int libc_calloc_count = 0;
+ 
+-/* Get a random alignment value.  Biased towards the smaller values.  Must be
+-   a power of 2. */
+-static size_t get_random_alignment (void)
+-{
+-  size_t aligns[] = {
+-    1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384
+-  };
+-
+-  return aligns[random () % array_length (aligns)];
+-}
+-
+-static void *get_random_alloc (size_t size)
++static void *
++get_random_alloc (size_t size)
+ {
+   void *retval;
+   size_t align;
++  struct timespec tp;
++
++  if (seed == 0)
++    {
++      clock_gettime (CLOCK_REALTIME, &tp);
++      seed = tp.tv_nsec;
++    }
+ 
+-  switch (random() % 3)
+-  {
++  switch (rand_r (&seed) % 3)
++    {
+     case 1:
+-      align = get_random_alignment ();
++      /* Get a random alignment value.  Biased towards the smaller
++       * values up to 16384. Must be a power of 2. */
++      align = 1 << rand_r (&seed) % 15;
+       retval = aligned_alloc (align, size);
+       aligned_alloc_count++;
+       break;
+@@ -59,13 +60,13 @@ static void *get_random_alloc (size_t size)
+       retval = __libc_malloc (size);
+       libc_malloc_count++;
+       break;
+-  }
++    }
+ 
+   return retval;
+ }
+ 
+-
+-void * __random_malloc (size_t size)
++void *
++__random_malloc (size_t size)
+ {
+   return get_random_alloc (size);
+ }
diff --git a/SOURCES/glibc-RHEL-50101-3.patch b/SOURCES/glibc-RHEL-50101-3.patch
new file mode 100644
index 0000000000000000000000000000000000000000..49c6e2835a10ea3c0fd529b005f4ebcc6040362d
--- /dev/null
+++ b/SOURCES/glibc-RHEL-50101-3.patch
@@ -0,0 +1,251 @@
+commit b0fbcb7d0051a68baf26b2aed51a8a31c34d68e5
+Author: Miguel Martín <mmartinv@redhat.com>
+Date:   Tue Jul 16 17:14:57 2024 +0200
+
+    malloc: add multi-threaded tests for aligned_alloc/calloc/malloc
+    
+    Improve aligned_alloc/calloc/malloc test coverage by adding
+    multi-threaded tests with random memory allocations and with/without
+    cross-thread memory deallocations.
+    
+    Perform a number of memory allocation calls with random sizes limited
+    to 0xffff.
+    
+    Use the existing DSO ('malloc/tst-aligned_alloc-lib.c') to randomize
+    allocator selection.
+    
+    The multi-threaded allocation/deallocation is staged as described below:
+    
+    - Stage 1: Half of the threads will be allocating memory and the
+      other half will be waiting for them to finish the allocation.
+    - Stage 2: Half of the threads will be allocating memory and the
+      other half will be deallocating memory.
+    - Stage 3: Half of the threads will be deallocating memory and the
+      second half waiting on them to finish.
+    
+    Add 'malloc/tst-aligned-alloc-random-thread.c' where each thread will
+    deallocate only the memory that was previously allocated by itself.
+    
+    Add 'malloc/tst-aligned-alloc-random-thread-cross.c' where each thread
+    will deallocate memory that was previously allocated by another thread.
+    
+    The intention is to be able to utilize existing malloc testing to ensure
+    that similar allocation APIs are also exposed to the same rigors.
+    Reviewed-by: Arjun Shankar <arjun@redhat.com>
+
+Conflicts:
+	malloc/Makefile
+	  (usual tests conflict)
+
+diff --git a/malloc/Makefile b/malloc/Makefile
+index e0fb433a15bad2c2..9dc068f6b3a69caa 100644
+--- a/malloc/Makefile
++++ b/malloc/Makefile
+@@ -46,6 +46,8 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
+ 	 tst-malloc-alternate-path \
+ 	 tst-aligned-alloc-random \
+ 	 tst-malloc-random \
++	 tst-aligned-alloc-random-thread \
++	 tst-aligned-alloc-random-thread-cross \
+ 
+ tests-static := \
+ 	 tst-interpose-static-nothread \
+@@ -96,7 +98,9 @@ tests-exclude-mcheck = tst-mallocstate \
+ 	tst-malloc-thread-fail \
+ 	tst-malloc-usable-tunables \
+ 	tst-malloc_info \
+-	tst-compathooks-off tst-compathooks-on
++	tst-compathooks-off tst-compathooks-on \
++	tst-aligned-alloc-random-thread \
++	tst-aligned-alloc-random-thread-cross \
+ 
+ tests-mcheck = $(filter-out $(tests-exclude-mcheck) $(tests-static), $(tests))
+ endif
+@@ -336,7 +340,11 @@ $(objpfx)tst-mallocstate: $(objpfx)libc_malloc_debug.so
+ $(objpfx)tst-mallocstate-malloc-check: $(objpfx)libc_malloc_debug.so
+ 
+ $(objpfx)tst-aligned-alloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
++$(objpfx)tst-aligned-alloc-random-thread.out: $(objpfx)tst-aligned_alloc-lib.so
++$(objpfx)tst-aligned-alloc-random-thread-cross.out: $(objpfx)tst-aligned_alloc-lib.so
+ $(objpfx)tst-malloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
+ 
+ tst-aligned-alloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
++tst-aligned-alloc-random-thread-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
++tst-aligned-alloc-random-thread-cross-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+ tst-malloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+diff --git a/malloc/tst-aligned-alloc-random-thread-cross.c b/malloc/tst-aligned-alloc-random-thread-cross.c
+new file mode 100644
+index 0000000000000000..360ecc56ee7c8c06
+--- /dev/null
++++ b/malloc/tst-aligned-alloc-random-thread-cross.c
+@@ -0,0 +1,19 @@
++/* multi-threaded memory allocation and cross-thread deallocation test.
++   Copyright (C) 2024 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; see the file COPYING.LIB.  If
++   not, see <https://www.gnu.org/licenses/>.  */
++#define CROSS_THREAD_DEALLOC
++#include "tst-aligned-alloc-random-thread.c"
+diff --git a/malloc/tst-aligned-alloc-random-thread.c b/malloc/tst-aligned-alloc-random-thread.c
+new file mode 100644
+index 0000000000000000..e95f79250abec85e
+--- /dev/null
++++ b/malloc/tst-aligned-alloc-random-thread.c
+@@ -0,0 +1,145 @@
++/* multi-threaded memory allocation/deallocation test.
++   Copyright (C) 2024 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; see the file COPYING.LIB.  If
++   not, see <https://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <support/xthread.h>
++#include <support/test-driver.h>
++#include <sys/sysinfo.h>
++#include <unistd.h>
++
++#ifndef ITERATIONS
++#  define ITERATIONS 16
++#endif
++
++#ifndef NUM_THREADS
++#  define NUM_THREADS 8
++#endif
++
++#ifndef NUM_ALLOCATIONS
++#  define NUM_ALLOCATIONS 2048
++#endif
++
++static pthread_barrier_t barrier;
++
++__thread unsigned int seed;
++
++typedef struct
++{
++  int id;
++  pthread_t thread;
++} thread;
++
++thread threads[NUM_THREADS];
++
++void *allocations[NUM_THREADS][NUM_ALLOCATIONS];
++
++void
++run_thread_dealloc (int id)
++{
++  for (int i = 0; i < NUM_ALLOCATIONS; i++)
++    {
++      free (allocations[id][i]);
++      allocations[id][i] = NULL;
++    }
++}
++
++void
++run_thread_alloc (int id)
++{
++  size_t msb, size;
++  for (int i = 0; i < NUM_ALLOCATIONS; i++)
++    {
++      msb = 1 << rand_r (&seed) % 16;
++      size = msb + rand_r (&seed) % msb;
++      allocations[id][i] = malloc (size);
++      TEST_VERIFY_EXIT (allocations[id][i] != NULL);
++    }
++}
++
++void *
++run_allocations (void *arg)
++{
++  int id = *((int *) arg);
++  seed = time (NULL) + id;
++
++  /* Stage 1: First half o the threads allocating memory and the second
++   * half waiting for them to finish
++   */
++  if (id < NUM_THREADS / 2)
++    run_thread_alloc (id);
++
++  xpthread_barrier_wait (&barrier);
++
++  /* Stage 2: Half of the threads allocationg memory and the other
++   * half deallocating:
++   * - In the non cross-thread dealloc scenario the first half will be
++   *   deallocating the memory allocated by themselves in stage 1 and the
++   *   second half will be allocating memory.
++   * - In the cross-thread dealloc scenario the first half will continue
++   *   to allocate memory and the second half will deallocate the memory
++   *   allocated by the first half in stage 1.
++   */
++  if (id < NUM_THREADS / 2)
++#ifndef CROSS_THREAD_DEALLOC
++    run_thread_dealloc (id);
++#else
++    run_thread_alloc (id + NUM_THREADS / 2);
++#endif
++  else
++#ifndef CROSS_THREAD_DEALLOC
++    run_thread_alloc (id);
++#else
++    run_thread_dealloc (id - NUM_THREADS / 2);
++#endif
++
++  xpthread_barrier_wait (&barrier);
++
++  // Stage 3: Second half of the threads deallocating and the first half
++  // waiting for them to finish.
++  if (id >= NUM_THREADS / 2)
++    run_thread_dealloc (id);
++
++  return NULL;
++}
++
++static int
++do_test (void)
++{
++  xpthread_barrier_init (&barrier, NULL, NUM_THREADS);
++
++  for (int i = 0; i < ITERATIONS; i++)
++    {
++      for (int t = 0; t < NUM_THREADS; t++)
++	{
++	  threads[t].id = t;
++	  threads[t].thread
++	      = xpthread_create (NULL, run_allocations, &threads[t].id);
++	}
++
++      for (int t = 0; t < NUM_THREADS; t++)
++	xpthread_join (threads[t].thread);
++    }
++
++  return 0;
++}
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-RHEL-54007.patch b/SOURCES/glibc-RHEL-54007.patch
new file mode 100644
index 0000000000000000000000000000000000000000..35b96a6352df864a46f58a8aa25170046508234d
--- /dev/null
+++ b/SOURCES/glibc-RHEL-54007.patch
@@ -0,0 +1,121 @@
+commit a09183aed7bb8ace211e042b2e6e982bcc004957
+Author: Andreas Schwab <schwab@suse.de>
+Date:   Mon Dec 19 12:40:45 2022 +0100
+
+    getdelim: ensure error indicator is set on error (bug 29917)
+    
+    POSIX requires that getdelim and getline set the error indicator on the
+    stream when an error occured, in addition to setting errno.
+
+Conflicts:
+	libio/Makefile - Manual merge for the newly added test
+
+diff --git a/libio/Makefile b/libio/Makefile
+index 64398ab1ee..9c69a85c87 100644
+--- a/libio/Makefile
++++ b/libio/Makefile
+@@ -66,7 +66,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \
+ 	tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \
+ 	tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \
+ 	tst-sprintf-ub tst-sprintf-chk-ub tst-bz24051 tst-bz24153 \
+-	tst-wfile-sync
++	tst-wfile-sync tst-getdelim
+ 
+ tests-internal = tst-vtables tst-vtables-interposed
+ 
+diff --git a/libio/iogetdelim.c b/libio/iogetdelim.c
+index b6c4c07b45..591526e9c1 100644
+--- a/libio/iogetdelim.c
++++ b/libio/iogetdelim.c
+@@ -43,11 +43,6 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
+   ssize_t cur_len = 0;
+   ssize_t len;
+ 
+-  if (lineptr == NULL || n == NULL)
+-    {
+-      __set_errno (EINVAL);
+-      return -1;
+-    }
+   CHECK_FILE (fp, -1);
+   _IO_acquire_lock (fp);
+   if (_IO_ferror_unlocked (fp))
+@@ -56,12 +51,21 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
+       goto unlock_return;
+     }
+ 
++  if (lineptr == NULL || n == NULL)
++    {
++      __set_errno (EINVAL);
++      fseterr_unlocked (fp);
++      result = -1;
++      goto unlock_return;
++    }
++
+   if (*lineptr == NULL || *n == 0)
+     {
+       *n = 120;
+       *lineptr = (char *) malloc (*n);
+       if (*lineptr == NULL)
+ 	{
++	  fseterr_unlocked (fp);
+ 	  result = -1;
+ 	  goto unlock_return;
+ 	}
+@@ -88,6 +92,7 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
+       if (__glibc_unlikely (len >= SSIZE_MAX - cur_len))
+ 	{
+ 	  __set_errno (EOVERFLOW);
++	  fseterr_unlocked (fp);
+ 	  result = -1;
+ 	  goto unlock_return;
+ 	}
+@@ -102,6 +107,7 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
+ 	  new_lineptr = (char *) realloc (*lineptr, needed);
+ 	  if (new_lineptr == NULL)
+ 	    {
++	      fseterr_unlocked (fp);
+ 	      result = -1;
+ 	      goto unlock_return;
+ 	    }
+diff --git a/libio/tst-getdelim.c b/libio/tst-getdelim.c
+new file mode 100644
+index 0000000000..4443732669
+--- /dev/null
++++ b/libio/tst-getdelim.c
+@@ -0,0 +1,36 @@
++/* Check that getdelim sets error indicator on error (BZ #29917)
++
++   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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++#include <errno.h>
++
++#include <support/check.h>
++
++static int
++do_test (void)
++{
++  clearerr (stdin);
++  TEST_VERIFY (getdelim (0, 0, '\n', stdin) == -1);
++  TEST_VERIFY (ferror (stdin) != 0);
++  TEST_VERIFY (errno == EINVAL);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-RHEL-54447-1.patch b/SOURCES/glibc-RHEL-54447-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..e6258154061f1f4898ecb468240b0e788932d189
--- /dev/null
+++ b/SOURCES/glibc-RHEL-54447-1.patch
@@ -0,0 +1,331 @@
+commit 5456af201d4c0a2950200ba756e5f8314ddbbccd
+Author: Carlos O'Donell <carlos@redhat.com>
+Date:   Thu May 11 14:00:41 2023 -0400
+
+    stdio-common: Reformat Makefile.
+    
+    Reflow Makefile.
+    Sort using scripts/sort-makefile-lines.py.
+    
+    Code generation is changed as routines are linked in sorted order
+    as expected.
+    
+    No regressions on x86_64 and i686.
+    
+    (cherry picked from commit c3004417afc98585089a9282d1d4d60cdef5317a)
+    (cherry picked from commit 5b4e90230b8147e273585bf296bf1a9fb6e2b4c2)
+
+diff --git a/stdio-common/Makefile b/stdio-common/Makefile
+index 803f16dae030cb72..76d1d0a1193aa109 100644
+--- a/stdio-common/Makefile
++++ b/stdio-common/Makefile
+@@ -22,82 +22,241 @@ subdir	:= stdio-common
+ 
+ include ../Makeconfig
+ 
+-headers	:= stdio_ext.h printf.h bits/printf-ldbl.h bits/stdio_lim.h
+-
+-routines	:=							      \
+-	ctermid cuserid							      \
+-	_itoa _itowa itoa-digits itoa-udigits itowa-digits		      \
+-	vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex	      \
+-	reg-modifier reg-type						      \
+-	printf_size fprintf printf snprintf sprintf asprintf dprintf	      \
+-	vfwprintf vfscanf vfwscanf					      \
+-	fscanf scanf sscanf						      \
+-	perror psignal							      \
+-	tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname		      \
+-	getline getw putw						      \
+-	remove rename renameat renameat2				      \
+-	flockfile ftrylockfile funlockfile				      \
+-	isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \
+-	isoc99_vsscanf							      \
+-	psiginfo gentempfd						      \
+-	vfscanf-internal vfwscanf-internal iovfscanf			      \
+-	vfprintf-internal vfwprintf-internal
+-
+-aux	:= errlist siglist printf-parsemb printf-parsewc fxprintf
+-
+-tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
+-	 temptest tst-fileno test-fwrite tst-ungetc tst-ferror \
+-	 xbug errnobug \
+-	 bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 \
+-	 tfformat tiformat tllformat tstdiomisc tst-printfsz tst-wc-printf \
+-	 scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \
+-	 scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \
+-	 tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \
+-	 tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 \
+-	 tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \
+-	 tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \
+-	 bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \
+-	 scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \
+-	 bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \
+-	 bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 tst-fmemopen3 \
+-	 tst-printf-bz18872 tst-vfprintf-width-prec tst-fmemopen4 \
+-	 tst-vfprintf-user-type \
+-	 tst-vfprintf-mbs-prec \
+-	 tst-scanf-round \
+-	 tst-renameat2 tst-bz11319 tst-bz11319-fortify2 \
+-	 scanf14a scanf16a \
+-	 tst-printf-bz25691 \
+-	 tst-vfprintf-width-prec-alloc \
+-	 tst-printf-fp-free \
+-	 tst-printf-fp-leak \
+-	 test-strerr
+-
+-
+-test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble
++headers := \
++  bits/printf-ldbl.h \
++  bits/stdio_lim.h \
++  printf.h \
++  stdio_ext.h \
++  # headers
++
++routines := \
++  _itoa \
++  _itowa \
++  asprintf \
++  ctermid \
++  cuserid \
++  dprintf \
++  flockfile \
++  fprintf \
++  fscanf \
++  ftrylockfile \
++  funlockfile \
++  gentempfd \
++  getline \
++  getw \
++  iovfscanf \
++  isoc99_fscanf \
++  isoc99_scanf \
++  isoc99_sscanf \
++  isoc99_vfscanf \
++  isoc99_vscanf \
++  isoc99_vsscanf \
++  itoa-digits \
++  itoa-udigits \
++  itowa-digits \
++  perror \
++  printf \
++  printf-prs \
++  printf_fp \
++  printf_fphex \
++  printf_size \
++  psiginfo \
++  psignal \
++  putw \
++  reg-modifier \
++  reg-printf \
++  reg-type \
++  remove \
++  rename \
++  renameat \
++  renameat2 \
++  scanf \
++  snprintf \
++  sprintf \
++  sscanf \
++  tempnam \
++  tempname \
++  tmpfile \
++  tmpfile64 tmpnam \
++  tmpnam_r \
++  vfprintf \
++  vfprintf-internal \
++  vfscanf \
++  vfscanf-internal \
++  vfwprintf \
++  vfwprintf-internal \
++  vfwscanf \
++  vfwscanf-internal \
++  vprintf \
++  # routines
++
++aux := \
++  errlist \
++  fxprintf \
++  printf-parsemb \
++  printf-parsewc \
++  siglist \
++  # aux
++
++tests := \
++  bug-vfprintf-nargs \
++  bug1 \
++  bug10 \
++  bug11 \
++  bug12 \
++  bug13 \
++  bug14 \
++  bug16 \
++  bug17 \
++  bug18 \
++  bug18a \
++  bug19 \
++  bug19a \
++  bug2 \
++  bug20 \
++  bug21 \
++  bug22 \
++  bug23 \
++  bug23-2 \
++  bug23-3 \
++  bug23-4 \
++  bug24 \
++  bug25 \
++  bug26 \
++  bug3 \
++  bug4 \
++  bug5 \
++  bug6 \
++  bug7 \
++  bug8 \
++  bug9 \
++  errnobug \
++  scanf1 \
++  scanf10 \
++  scanf11 \
++  scanf12 \
++  scanf13 \
++  scanf14 \
++  scanf14a \
++  scanf15 \
++  scanf16 \
++  scanf16a \
++  scanf17 \
++  scanf2 \
++  scanf3 \
++  scanf4 \
++  scanf5 \
++  scanf7 \
++  scanf8 \
++  scanf9 \
++  temptest \
++  test-fseek \
++  test-fwrite \
++  test-popen \
++  test-strerr \
++  test-vfprintf \
++  test_rdwr \
++  tfformat \
++  tiformat \
++  tllformat \
++  tst-bz11319 \
++  tst-bz11319-fortify2 \
++  tst-cookie \
++  tst-fdopen \
++  tst-ferror \
++  tst-fgets \
++  tst-fileno \
++  tst-fmemopen \
++  tst-fmemopen2 \
++  tst-fmemopen3 \
++  tst-fmemopen4 \
++  tst-fphex \
++  tst-fphex-wide \
++  tst-fseek \
++  tst-fwrite \
++  tst-gets \
++  tst-grouping \
++  tst-long-dbl-fphex \
++  tst-obprintf \
++  tst-perror \
++  tst-popen \
++  tst-popen2 \
++  tst-printf-bz18872 \
++  tst-printf-bz25691 \
++  tst-printf-fp-free \
++  tst-printf-fp-leak \
++  tst-printf-round \
++  tst-printfsz \
++  tst-put-error \
++  tst-renameat2 \
++  tst-rndseek \
++  tst-scanf-round \
++  tst-setvbuf1 \
++  tst-sprintf \
++  tst-sprintf2 \
++  tst-sprintf3 \
++  tst-sscanf \
++  tst-swprintf \
++  tst-swscanf \
++  tst-tmpnam \
++  tst-ungetc \
++  tst-unlockedio \
++  tst-vfprintf-mbs-prec \
++  tst-vfprintf-user-type \
++  tst-vfprintf-width-prec \
++  tst-vfprintf-width-prec-alloc \
++  tst-wc-printf \
++  tstdiomisc \
++  tstgetln \
++  tstscanf \
++  xbug \
++  # tests
++
++test-srcs = \
++  tst-printf \
++  tst-printfsz-islongdouble \
++  tst-unbputc \
++  # test-srcs
+ 
+ ifeq ($(run-built-tests),yes)
+-tests-special += $(objpfx)tst-unbputc.out $(objpfx)tst-printf.out \
+-		 $(objpfx)tst-printf-bz18872-mem.out \
+-		 $(objpfx)tst-setvbuf1-cmp.out \
+-		 $(objpfx)tst-vfprintf-width-prec-mem.out \
+-		 $(objpfx)tst-printfsz-islongdouble.out \
+-		 $(objpfx)tst-printf-bz25691-mem.out \
+-		 $(objpfx)tst-printf-fp-free-mem.out \
+-		 $(objpfx)tst-printf-fp-leak-mem.out
+-generated += tst-printf-bz18872.c tst-printf-bz18872.mtrace \
+-	     tst-printf-bz18872-mem.out \
+-	     tst-vfprintf-width-prec.mtrace tst-vfprintf-width-prec-mem.out \
+-	     tst-printf-bz25691.mtrace tst-printf-bz25691-mem.out \
+-	     tst-printf-fp-free.mtrace tst-printf-fp-free-mem.out \
+-	     tst-printf-fp-leak.mtrace tst-printf-fp-leak-mem.out
+-endif
++tests-special += \
++  $(objpfx)tst-printf-bz18872-mem.out \
++  $(objpfx)tst-printf-bz25691-mem.out \
++  $(objpfx)tst-printf-fp-free-mem.out \
++  $(objpfx)tst-printf-fp-leak-mem.out \
++  $(objpfx)tst-printf.out \
++  $(objpfx)tst-printfsz-islongdouble.out \
++  $(objpfx)tst-setvbuf1-cmp.out \
++  $(objpfx)tst-unbputc.out \
++  $(objpfx)tst-vfprintf-width-prec-mem.out \
++  # tests-special
++
++generated += \
++  tst-printf-bz18872-mem.out \
++  tst-printf-bz18872.c \
++  tst-printf-bz18872.mtrace \
++  tst-printf-bz25691-mem.out \
++  tst-printf-bz25691.mtrace \
++  tst-printf-fp-free-mem.out \
++  tst-printf-fp-free.mtrace \
++  tst-printf-fp-leak-mem.out \
++  tst-printf-fp-leak.mtrace \
++  tst-vfprintf-width-prec-mem.out \
++  tst-vfprintf-width-prec.mtrace \
++  # generated
++endif # $(run-built-tests)
+ 
+ tests-special += $(objpfx)tst-errno-manual.out
+ 
+ include ../Rules
+ 
+ ifeq ($(run-built-tests),yes)
+-LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ISO-8859-1 ja_JP.EUC-JP
++LOCALES := \
++  de_DE.ISO-8859-1 \
++  de_DE.UTF-8 \
++  en_US.ISO-8859-1 \
++  ja_JP.EUC-JP \
++  # LOCALES
+ include ../gen-locales.mk
+ 
+ $(objpfx)bug14.out: $(gen-locales)
diff --git a/SOURCES/glibc-RHEL-54447-10.patch b/SOURCES/glibc-RHEL-54447-10.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6258b77eb2330a5c5fe1d41a7a76665516d094f2
--- /dev/null
+++ b/SOURCES/glibc-RHEL-54447-10.patch
@@ -0,0 +1,201 @@
+commit 9556acd249687ac562deb6309503165d66eb06fa
+Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date:   Thu Dec 21 15:59:15 2023 -0300
+
+    debug: Adapt fortify tests to libsupport
+    
+    Checked on aarch64, armhf, x86_64, and i686.
+    Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+diff --git a/debug/test-stpcpy_chk.c b/debug/test-stpcpy_chk.c
+index 96ad600bc2760cbd..c3cb52d987f9db4f 100644
+--- a/debug/test-stpcpy_chk.c
++++ b/debug/test-stpcpy_chk.c
+@@ -20,7 +20,7 @@
+ #define STRCPY_RESULT(dst, len) ((dst) + (len))
+ #define TEST_MAIN
+ #define TEST_NAME "stpcpy_chk"
+-#include "../string/test-string.h"
++#include <string/test-string.h>
+ 
+ extern void __attribute__ ((noreturn)) __chk_fail (void);
+ char *simple_stpcpy_chk (char *, const char *, size_t);
+diff --git a/debug/test-strcpy_chk.c b/debug/test-strcpy_chk.c
+index 80c07482aaa54e3b..bb89e342caef470b 100644
+--- a/debug/test-strcpy_chk.c
++++ b/debug/test-strcpy_chk.c
+@@ -21,7 +21,7 @@
+ # define STRCPY_RESULT(dst, len) dst
+ # define TEST_MAIN
+ # define TEST_NAME "strcpy_chk"
+-# include "../string/test-string.h"
++# include <string/test-string.h>
+ 
+ /* This test case implicitly tests the availability of the __chk_fail
+    symbol, which is part of the public ABI and may be used
+diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c
+index fb02452f5993c594..01a8703de1e6e09a 100644
+--- a/debug/tst-fortify.c
++++ b/debug/tst-fortify.c
+@@ -24,6 +24,7 @@
+ 
+ #include <assert.h>
+ #include <fcntl.h>
++#include <limits.h>
+ #include <locale.h>
+ #include <obstack.h>
+ #include <setjmp.h>
+@@ -37,6 +38,10 @@
+ #include <sys/select.h>
+ #include <sys/socket.h>
+ #include <sys/un.h>
++#include <paths.h>
++
++#include <support/temp_file.h>
++#include <support/support.h>
+ 
+ #ifndef _GNU_SOURCE
+ # define MEMPCPY memcpy
+@@ -53,15 +58,10 @@
+ #define obstack_chunk_alloc malloc
+ #define obstack_chunk_free free
+ 
+-char *temp_filename;
+-static void do_prepare (void);
+-static int do_test (void);
+-#define PREPARE(argc, argv) do_prepare ()
+-#define TEST_FUNCTION do_test ()
+-#include "../test-skeleton.c"
++static char *temp_filename;
+ 
+ static void
+-do_prepare (void)
++do_prepare (int argc, char *argv[])
+ {
+   int temp_fd = create_temp_file ("tst-chk1.", &temp_filename);
+   if (temp_fd == -1)
+@@ -78,10 +78,11 @@ do_prepare (void)
+       exit (1);
+     }
+ }
++#define PREPARE do_prepare
+ 
+-volatile int chk_fail_ok;
+-volatile int ret;
+-jmp_buf chk_fail_buf;
++static volatile int chk_fail_ok;
++static volatile int ret;
++static jmp_buf chk_fail_buf;
+ 
+ static void
+ handler (int sig)
+@@ -103,22 +104,22 @@ wchar_t wbuf[10];
+ #define buf_size sizeof (buf)
+ #endif
+ 
+-volatile size_t l0;
+-volatile char *p;
+-volatile wchar_t *wp;
+-const char *str1 = "JIHGFEDCBA";
+-const char *str2 = "F";
+-const char *str3 = "%s%n%s%n";
+-const char *str4 = "Hello, ";
+-const char *str5 = "World!\n";
+-const wchar_t *wstr1 = L"JIHGFEDCBA";
+-const wchar_t *wstr2 = L"F";
+-const wchar_t *wstr3 = L"%s%n%s%n";
+-const wchar_t *wstr4 = L"Hello, ";
+-const wchar_t *wstr5 = L"World!\n";
+-char buf2[10] = "%s";
+-int num1 = 67;
+-int num2 = 987654;
++static volatile size_t l0;
++static volatile char *p;
++static volatile wchar_t *wp;
++static const char *str1 = "JIHGFEDCBA";
++static const char *str2 = "F";
++static const char *str3 = "%s%n%s%n";
++static const char *str4 = "Hello, ";
++static const char *str5 = "World!\n";
++static const wchar_t *wstr1 = L"JIHGFEDCBA";
++static const wchar_t *wstr2 = L"F";
++static const wchar_t *wstr3 = L"%s%n%s%n";
++static const wchar_t *wstr4 = L"Hello, ";
++static const wchar_t *wstr5 = L"World!\n";
++static char buf2[10] = "%s";
++static int num1 = 67;
++static int num2 = 987654;
+ 
+ #define FAIL() \
+   do { printf ("Failure on line %d\n", __LINE__); ret = 1; } while (0)
+@@ -1763,3 +1764,5 @@ do_test (void)
+ 
+   return ret;
+ }
++
++#include <support/test-driver.c>
+diff --git a/debug/tst-longjmp_chk.c b/debug/tst-longjmp_chk.c
+index e4e93d2a36b537d9..37f858606be4c4a2 100644
+--- a/debug/tst-longjmp_chk.c
++++ b/debug/tst-longjmp_chk.c
+@@ -10,11 +10,7 @@
+ #include <stdlib.h>
+ #include <unistd.h>
+ 
+-
+-static int do_test(void);
+-#define TEST_FUNCTION do_test ()
+-#include "../test-skeleton.c"
+-
++#include <support/support.h>
+ 
+ static jmp_buf b;
+ 
+@@ -76,3 +72,5 @@ do_test (void)
+   puts ("second longjmp returned");
+   return 1;
+ }
++
++#include <support/test-driver.c>
+diff --git a/debug/tst-longjmp_chk2.c b/debug/tst-longjmp_chk2.c
+index 23d3436d1d26d2d1..69c1ab9db73f14ae 100644
+--- a/debug/tst-longjmp_chk2.c
++++ b/debug/tst-longjmp_chk2.c
+@@ -12,9 +12,7 @@
+ #include <sys/resource.h>
+ #include <unistd.h>
+ 
+-static int do_test (void);
+-#define TEST_FUNCTION do_test ()
+-#include "../test-skeleton.c"
++#include <support/support.h>
+ 
+ static jmp_buf mainloop;
+ static sigset_t mainsigset;
+@@ -128,3 +126,5 @@ do_test (void)
+ 
+   return 0;
+ }
++
++#include <support/test-driver.c>
+diff --git a/debug/tst-longjmp_chk3.c b/debug/tst-longjmp_chk3.c
+index 3155c7769fcbd83f..4434937c597dbe10 100644
+--- a/debug/tst-longjmp_chk3.c
++++ b/debug/tst-longjmp_chk3.c
+@@ -20,10 +20,6 @@
+ #include <signal.h>
+ #include <string.h>
+ 
+-static int do_test (void);
+-#define TEST_FUNCTION do_test ()
+-#include "../test-skeleton.c"
+-
+ static char buf[SIGSTKSZ * 4];
+ static jmp_buf jb;
+ 
+@@ -83,3 +79,5 @@ do_test (void)
+   puts ("longjmp returned and shouldn't");
+   return 1;
+ }
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-RHEL-54447-2.patch b/SOURCES/glibc-RHEL-54447-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1c39e952d00c85ad9084128e29dfae11eb07069f
--- /dev/null
+++ b/SOURCES/glibc-RHEL-54447-2.patch
@@ -0,0 +1,195 @@
+commit 388c9d7294e5ee3b741aef2e8af63eb1f76ace86
+Author: Maciej W. Rozycki <macro@redhat.com>
+Date:   Fri Jul 26 13:21:34 2024 +0100
+
+    support: Add FAIL test failure helper
+    
+    Add a FAIL test failure helper analogous to FAIL_RET, that does not
+    cause the current function to return, providing a standardized way to
+    report a test failure with a message supplied while permitting the
+    caller to continue executing, for further reporting, cleaning up, etc.
+    
+    Update existing test cases that provide a conflicting definition of FAIL
+    by removing the local FAIL definition and then as follows:
+    
+    - tst-fortify-syslog: provide a meaningful message in addition to the
+      file name already added by <support/check.h>; 'support_record_failure'
+      is already called by 'support_print_failure_impl' invoked by the new
+      FAIL test failure helper.
+    
+    - tst-ctype: no update to FAIL calls required, with the name of the file
+      and the line number within of the failure site additionally included
+      by the new FAIL test failure helper, and error counting plus count
+      reporting upon test program termination also already provided by
+      'support_record_failure' and 'support_report_failure' respectively,
+      called by 'support_print_failure_impl' and 'adjust_exit_status' also
+      respectively.  However in a number of places 'printf' is called and
+      the error count adjusted by hand, so update these places to make use
+      of FAIL instead.  And last but not least adjust the final summary just
+      to report completion, with any error count following as reported by
+      the test driver.
+    
+    - test-tgmath2: no update to FAIL calls required, with the name of the
+      file of the failure site additionally included by the new FAIL test
+      failure helper.  Also there is no need to track the return status by
+      hand as any call to FAIL will eventually cause the test case to return
+      an unsuccesful exit status regardless of the return status from the
+      test function, via a call to 'adjust_exit_status' made by the test
+      driver.
+    
+    Reviewed-by: DJ Delorie <dj@redhat.com>
+    (cherry picked from commit 1b97a9f23bf605ca608162089c94187573fb2a9e)
+    (cherry picked from commit 28f358bc4209ab0425170cdccf65bb1fe861148f)
+
+diff --git a/localedata/tst-ctype.c b/localedata/tst-ctype.c
+index 1e4fa132bb4e17c6..f8645e31db8a1691 100644
+--- a/localedata/tst-ctype.c
++++ b/localedata/tst-ctype.c
+@@ -22,6 +22,8 @@
+ #include <stdio.h>
+ #include <string.h>
+ 
++#include <support/check.h>
++
+ 
+ static const char lower[] = "abcdefghijklmnopqrstuvwxyz";
+ static const char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+@@ -54,19 +56,11 @@ static struct classes
+ #define nclasses (sizeof (classes) / sizeof (classes[0]))
+ 
+ 
+-#define FAIL(str, args...) \
+-  {									      \
+-    printf ("      " str "\n", ##args);					      \
+-    ++errors;								      \
+-  }
+-
+-
+ static int
+ do_test (void)
+ {
+   const char *cp;
+   const char *cp2;
+-  int errors = 0;
+   char *inpline = NULL;
+   size_t inplinelen = 0;
+   char *resline = NULL;
+@@ -395,11 +389,8 @@ punct = %04x  alnum = %04x\n",
+ 	    {
+ 	      if (((__ctype_b[(unsigned int) *inp] & classes[n].mask) != 0)
+ 		  != (*resp != '0'))
+-		{
+-		  printf ("    is%s('%c' = '\\x%02x') %s true\n", inpline,
+-			  *inp, *inp, *resp == '1' ? "not" : "is");
+-		  ++errors;
+-		}
++		FAIL ("    is%s('%c' = '\\x%02x') %s true\n", inpline,
++		      *inp, *inp, *resp == '1' ? "not" : "is");
+ 	      ++inp;
+ 	      ++resp;
+ 	    }
+@@ -409,11 +400,8 @@ punct = %04x  alnum = %04x\n",
+ 	  while (*inp != '\0')
+ 	    {
+ 	      if (tolower (*inp) != *resp)
+-		{
+-		  printf ("    tolower('%c' = '\\x%02x') != '%c'\n",
+-			  *inp, *inp, *resp);
+-		  ++errors;
+-		}
++		FAIL ("    tolower('%c' = '\\x%02x') != '%c'\n",
++		      *inp, *inp, *resp);
+ 	      ++inp;
+ 	      ++resp;
+ 	    }
+@@ -423,11 +411,8 @@ punct = %04x  alnum = %04x\n",
+ 	  while (*inp != '\0')
+ 	    {
+ 	      if (toupper (*inp) != *resp)
+-		{
+-		  printf ("    toupper('%c' = '\\x%02x') != '%c'\n",
+-			  *inp, *inp, *resp);
+-		  ++errors;
+-		}
++		FAIL ("    toupper('%c' = '\\x%02x') != '%c'\n",
++		      *inp, *inp, *resp);
+ 	      ++inp;
+ 	      ++resp;
+ 	    }
+@@ -437,14 +422,7 @@ punct = %04x  alnum = %04x\n",
+     }
+ 
+ 
+-  if (errors != 0)
+-    {
+-      printf ("  %d error%s for `%s' locale\n\n\n", errors,
+-	      errors == 1 ? "" : "s", setlocale (LC_ALL, NULL));
+-      return 1;
+-    }
+-
+-  printf ("  No errors for `%s' locale\n\n\n", setlocale (LC_ALL, NULL));
++  printf ("Completed testing for `%s' locale\n\n\n", setlocale (LC_ALL, NULL));
+   return 0;
+ }
+ 
+diff --git a/math/test-tgmath2.c b/math/test-tgmath2.c
+index b8fb00c566439ab0..e3b7a3a3615e083a 100644
+--- a/math/test-tgmath2.c
++++ b/math/test-tgmath2.c
+@@ -25,6 +25,8 @@
+ #include <string.h>
+ #include <tgmath.h>
+ 
++#include <support/check.h>
++
+ //#define DEBUG
+ 
+ typedef complex float cfloat;
+@@ -88,13 +90,6 @@ enum
+ int count;
+ int counts[Tlast][C_last];
+ 
+-#define FAIL(str) \
+-  do								\
+-    {								\
+-      printf ("%s failure on line %d\n", (str), __LINE__);	\
+-      result = 1;						\
+-    }								\
+-  while (0)
+ #define TEST_TYPE_ONLY(expr, rettype) \
+   do								\
+     {								\
+@@ -134,8 +129,6 @@ int counts[Tlast][C_last];
+ int
+ test_cos (const int Vint4, const long long int Vllong4)
+ {
+-  int result = 0;
+-
+   TEST (cos (vfloat1), float, cos);
+   TEST (cos (vdouble1), double, cos);
+   TEST (cos (vldouble1), ldouble, cos);
+@@ -153,7 +146,7 @@ test_cos (const int Vint4, const long long int Vllong4)
+   TEST (cos (Vcdouble1), cdouble, cos);
+   TEST (cos (Vcldouble1), cldouble, cos);
+ 
+-  return result;
++  return 0;
+ }
+ 
+ int
+diff --git a/support/check.h b/support/check.h
+index 9b1844352f32513a..8e045dd9c0c36b4c 100644
+--- a/support/check.h
++++ b/support/check.h
+@@ -24,6 +24,11 @@
+ 
+ __BEGIN_DECLS
+ 
++/* Record a test failure, print the failure message to standard output
++   and pass the result of 1 through.  */
++#define FAIL(...) \
++  support_print_failure_impl (__FILE__, __LINE__, __VA_ARGS__)
++
+ /* Record a test failure, print the failure message to standard output
+    and return 1.  */
+ #define FAIL_RET(...) \
diff --git a/SOURCES/glibc-RHEL-54447-3.patch b/SOURCES/glibc-RHEL-54447-3.patch
new file mode 100644
index 0000000000000000000000000000000000000000..a7b2bdd58ea79105c15e7ac02432e9dc5f440d1d
--- /dev/null
+++ b/SOURCES/glibc-RHEL-54447-3.patch
@@ -0,0 +1,169 @@
+commit 86f5cfe77d60ca4f78f270adc7ae2c15a1d8d4bc
+Author: Maciej W. Rozycki <macro@redhat.com>
+Date:   Fri Jul 26 13:21:34 2024 +0100
+
+    stdio-common: Add test for vfscanf with matches longer than INT_MAX [BZ #27650]
+    
+    Complement commit b03e4d7bd25b ("stdio: fix vfscanf with matches longer
+    than INT_MAX (bug 27650)") and add a test case for the issue, inspired
+    by the reproducer provided with the bug report.
+    
+    This has been verified to succeed as from the commit referred and fail
+    beforehand.
+    
+    As the test requires 2GiB of data to be passed around its performance
+    has been evaluated using a choice of systems and the execution time
+    determined to be respectively in the range of 9s for POWER9@2.166GHz,
+    24s for FU740@1.2GHz, and 40s for 74Kf@950MHz.  As this is on the verge
+    of and beyond the default timeout it has been increased by the factor of
+    8.  Regardless, following recent practice the test has been added to the
+    standard rather than extended set.
+    
+    Reviewed-by: DJ Delorie <dj@redhat.com>
+    (cherry picked from commit 89cddc8a7096f3d9225868304d2bc0a1aaf07d63)
+    (cherry picked from commit 99ffa84bdcdc3d81e82f448279f0c8278dd30964)
+
+diff --git a/stdio-common/Makefile b/stdio-common/Makefile
+index 76d1d0a1193aa109..08bedd01be61a55d 100644
+--- a/stdio-common/Makefile
++++ b/stdio-common/Makefile
+@@ -190,6 +190,7 @@ tests := \
+   tst-put-error \
+   tst-renameat2 \
+   tst-rndseek \
++  tst-scanf-bz27650 \
+   tst-scanf-round \
+   tst-setvbuf1 \
+   tst-sprintf \
+@@ -241,6 +242,7 @@ generated += \
+   tst-printf-fp-free.mtrace \
+   tst-printf-fp-leak-mem.out \
+   tst-printf-fp-leak.mtrace \
++  tst-scanf-bz27650.mtrace \
+   tst-vfprintf-width-prec-mem.out \
+   tst-vfprintf-width-prec.mtrace \
+   # generated
+@@ -283,6 +285,9 @@ tst-printf-fp-free-ENV = \
+ tst-printf-fp-leak-ENV = \
+   MALLOC_TRACE=$(objpfx)tst-printf-fp-leak.mtrace \
+   LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
++tst-scanf-bz27650-ENV = \
++  MALLOC_TRACE=$(objpfx)tst-scanf-bz27650.mtrace \
++  LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
+ 
+ $(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
+ 	$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
+diff --git a/stdio-common/tst-scanf-bz27650.c b/stdio-common/tst-scanf-bz27650.c
+new file mode 100644
+index 0000000000000000..3a742bc86556908c
+--- /dev/null
++++ b/stdio-common/tst-scanf-bz27650.c
+@@ -0,0 +1,108 @@
++/* Test for BZ #27650, formatted input matching beyond INT_MAX.
++   Copyright (C) 2024 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <error.h>
++#include <errno.h>
++#include <limits.h>
++#include <mcheck.h>
++#include <stddef.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <sys/types.h>
++
++#include <support/check.h>
++#include <support/test-driver.h>
++
++/* Produce a stream of more than INT_MAX characters via buffer BUF of
++   size SIZE according to bookkeeping in COOKIE and then return EOF.  */
++
++static ssize_t
++io_read (void *cookie, char *buf, size_t size)
++{
++  unsigned int *written = cookie;
++  unsigned int w = *written;
++
++  if (w > INT_MAX)
++    return 0;
++
++  memset (buf, 'a', size);
++  *written = w + size;
++  return size;
++}
++
++/* Consume a stream of more than INT_MAX characters from an artificial
++   input stream of which none is the new line character.  The call to
++   fscanf is supposed to complete upon the EOF condition of input,
++   however in the presence of BZ #27650 it will terminate prematurely
++   with characters still outstanding in input.  Diagnose the condition
++   and return status accordingly.  */
++
++int
++do_test (void)
++{
++  static cookie_io_functions_t io_funcs = { .read = io_read };
++  unsigned int written = 0;
++  FILE *in;
++  int v;
++
++  mtrace ();
++
++  in = fopencookie (&written, "r", io_funcs);
++  if (in == NULL)
++    {
++      FAIL ("fopencookie: %m");
++      goto out;
++    }
++
++  v = fscanf (in, "%*[^\n]");
++  if (ferror (in))
++    {
++      FAIL ("fscanf: input failure, at %u: %m", written);
++      goto out_close;
++    }
++  else if (v == EOF)
++    {
++      FAIL ("fscanf: unexpected end of file, at %u", written);
++      goto out_close;
++    }
++
++  if (!feof (in))
++    {
++      v = fgetc (in);
++      if (ferror (in))
++	FAIL ("fgetc: input failure: %m");
++      else if (v == EOF)
++	FAIL ("fgetc: unexpected end of file after missing end of file");
++      else if (v == '\n')
++	FAIL ("unexpected new line character received");
++      else
++	FAIL ("character received after end of file expected: \\x%02x", v);
++    }
++
++out_close:
++  if (fclose (in) != 0)
++    FAIL ("fclose: %m");
++
++out:
++  return EXIT_SUCCESS;
++}
++
++#define TIMEOUT (DEFAULT_TIMEOUT * 8)
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-RHEL-54447-4.patch b/SOURCES/glibc-RHEL-54447-4.patch
new file mode 100644
index 0000000000000000000000000000000000000000..525ce22d958cb87d310b060cc905b44490559e0e
--- /dev/null
+++ b/SOURCES/glibc-RHEL-54447-4.patch
@@ -0,0 +1,143 @@
+commit af68f0f6755c3b82ecef6dd67079df64eee8d946
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Wed Aug 14 19:20:04 2024 -0400
+
+    Make tst-ungetc use libsupport
+    
+    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+    (cherry picked from commit 3f7df7e757f4efec38e45d4068e5492efcac4856)
+    (cherry picked from commit 87a1968a72e4b4e5436f3e2be1ed8a8d5a5862c7)
+
+diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c
+index 1344b2b591e3d6b1..5c808f073419f00b 100644
+--- a/stdio-common/tst-ungetc.c
++++ b/stdio-common/tst-ungetc.c
+@@ -1,70 +1,72 @@
+-/* Test for ungetc bugs.  */
++/* Test for ungetc bugs.
++   Copyright (C) 1996-2024 Free Software Foundation, Inc.
++   Copyright The GNU Toolchain Authors.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+-#include <unistd.h>
+-
+-#undef assert
+-#define assert(x) \
+-  if (!(x)) \
+-    { \
+-      fputs ("test failed: " #x "\n", stderr); \
+-      retval = 1; \
+-      goto the_end; \
+-    }
++#include <support/check.h>
++#include <support/support.h>
++#include <support/temp_file.h>
++#include <support/xstdio.h>
++#include <support/xunistd.h>
+ 
+-int
+-main (int argc, char *argv[])
++static int
++do_test (void)
+ {
+-  char name[] = "/tmp/tst-ungetc.XXXXXX";
++  char *name = NULL;
+   FILE *fp = NULL;
+-  int retval = 0;
+   int c;
+   char buffer[64];
+ 
+-  int fd = mkstemp (name);
++  int fd = create_temp_file ("tst-ungetc.", &name);
+   if (fd == -1)
+-    {
+-      printf ("mkstemp failed: %m\n");
+-      return 1;
+-    }
+-  close (fd);
+-  fp = fopen (name, "w");
+-  assert (fp != NULL)
+-  fputs ("bla", fp);
+-  fclose (fp);
+-  fp = NULL;
++    FAIL_EXIT1 ("cannot create temporary file: %m");
++  xclose (fd);
+ 
+-  fp = fopen (name, "r");
+-  assert (fp != NULL);
+-  assert (ungetc ('z', fp) == 'z');
+-  assert (getc (fp) == 'z');
+-  assert (getc (fp) == 'b');
+-  assert (getc (fp) == 'l');
+-  assert (ungetc ('m', fp) == 'm');
+-  assert (getc (fp) == 'm');
+-  assert ((c = getc (fp)) == 'a');
+-  assert (getc (fp) == EOF);
+-  assert (ungetc (c, fp) == c);
+-  assert (feof (fp) == 0);
+-  assert (getc (fp) == c);
+-  assert (getc (fp) == EOF);
+-  fclose (fp);
+-  fp = NULL;
++  fp = xfopen (name, "w");
++  fputs ("bla", fp);
++  xfclose (fp);
+ 
+-  fp = fopen (name, "r");
+-  assert (fp != NULL);
+-  assert (getc (fp) == 'b');
+-  assert (getc (fp) == 'l');
+-  assert (ungetc ('b', fp) == 'b');
+-  assert (fread (buffer, 1, 64, fp) == 2);
+-  assert (buffer[0] == 'b');
+-  assert (buffer[1] == 'a');
++  fp = xfopen (name, "r");
++  TEST_VERIFY_EXIT (ungetc ('z', fp) == 'z');
++  TEST_VERIFY_EXIT (getc (fp) == 'z');
++  TEST_VERIFY_EXIT (getc (fp) == 'b');
++  TEST_VERIFY_EXIT (getc (fp) == 'l');
++  TEST_VERIFY_EXIT (ungetc ('m', fp) == 'm');
++  TEST_VERIFY_EXIT (getc (fp) == 'm');
++  TEST_VERIFY_EXIT ((c = getc (fp)) == 'a');
++  TEST_VERIFY_EXIT (getc (fp) == EOF);
++  TEST_VERIFY_EXIT (ungetc (c, fp) == c);
++  TEST_VERIFY_EXIT (feof (fp) == 0);
++  TEST_VERIFY_EXIT (getc (fp) == c);
++  TEST_VERIFY_EXIT (getc (fp) == EOF);
++  xfclose (fp);
+ 
+-the_end:
+-  if (fp != NULL)
+-    fclose (fp);
+-  unlink (name);
++  fp = xfopen (name, "r");
++  TEST_VERIFY_EXIT (getc (fp) == 'b');
++  TEST_VERIFY_EXIT (getc (fp) == 'l');
++  TEST_VERIFY_EXIT (ungetc ('b', fp) == 'b');
++  TEST_VERIFY_EXIT (fread (buffer, 1, 64, fp) == 2);
++  TEST_VERIFY_EXIT (buffer[0] == 'b');
++  TEST_VERIFY_EXIT (buffer[1] == 'a');
++  xfclose (fp);
+ 
+-  return retval;
++  return 0;
+ }
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-RHEL-54447-5.patch b/SOURCES/glibc-RHEL-54447-5.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d2d72aa195cd5bc09ef277f2cd4f1594d9c035bf
--- /dev/null
+++ b/SOURCES/glibc-RHEL-54447-5.patch
@@ -0,0 +1,71 @@
+commit 01a731da41a6d47cdd6b90f0da1d89dd8cf2b9cd
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Tue Aug 13 21:00:06 2024 -0400
+
+    ungetc: Fix uninitialized read when putting into unused streams [BZ #27821]
+    
+    When ungetc is called on an unused stream, the backup buffer is
+    allocated without the main get area being present.  This results in
+    every subsequent ungetc (as the stream remains in the backup area)
+    checking uninitialized memory in the backup buffer when trying to put a
+    character back into the stream.
+    
+    Avoid comparing the input character with buffer contents when in backup
+    to avoid this uninitialized read.  The uninitialized read is harmless in
+    this context since the location is promptly overwritten with the input
+    character, thus fulfilling ungetc functionality.
+    
+    Also adjust wording in the manual to drop the paragraph that says glibc
+    cannot do multiple ungetc back to back since with this change, ungetc
+    can actually do this.
+    
+    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+    (cherry picked from commit cdf0f88f97b0aaceb894cc02b21159d148d7065c)
+    (cherry picked from commit 804d3c8db79db204154dcf5e11a76f14fdddc570)
+
+diff --git a/libio/genops.c b/libio/genops.c
+index fa509f6219abaf23..a5dd6a06d9e259d8 100644
+--- a/libio/genops.c
++++ b/libio/genops.c
+@@ -635,7 +635,7 @@ _IO_sputbackc (FILE *fp, int c)
+ {
+   int result;
+ 
+-  if (fp->_IO_read_ptr > fp->_IO_read_base
++  if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp)
+       && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
+     {
+       fp->_IO_read_ptr--;
+diff --git a/manual/stdio.texi b/manual/stdio.texi
+index d3d855fc62b8768b..60ab7e7a5d505bb6 100644
+--- a/manual/stdio.texi
++++ b/manual/stdio.texi
+@@ -1467,11 +1467,9 @@ program; usually @code{ungetc} is used only to unread a character that
+ was just read from the same stream.  @Theglibc{} supports this
+ even on files opened in binary mode, but other systems might not.
+ 
+-@Theglibc{} only supports one character of pushback---in other
+-words, it does not work to call @code{ungetc} twice without doing input
+-in between.  Other systems might let you push back multiple characters;
+-then reading from the stream retrieves the characters in the reverse
+-order that they were pushed.
++@Theglibc{} supports pushing back multiple characters; subsequently
++reading from the stream retrieves the characters in the reverse order
++that they were pushed.
+ 
+ Pushing back characters doesn't alter the file; only the internal
+ buffering for the stream is affected.  If a file positioning function
+diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c
+index 5c808f073419f00b..388b202493ddd586 100644
+--- a/stdio-common/tst-ungetc.c
++++ b/stdio-common/tst-ungetc.c
+@@ -48,6 +48,8 @@ do_test (void)
+   TEST_VERIFY_EXIT (getc (fp) == 'b');
+   TEST_VERIFY_EXIT (getc (fp) == 'l');
+   TEST_VERIFY_EXIT (ungetc ('m', fp) == 'm');
++  TEST_VERIFY_EXIT (ungetc ('n', fp) == 'n');
++  TEST_VERIFY_EXIT (getc (fp) == 'n');
+   TEST_VERIFY_EXIT (getc (fp) == 'm');
+   TEST_VERIFY_EXIT ((c = getc (fp)) == 'a');
+   TEST_VERIFY_EXIT (getc (fp) == EOF);
diff --git a/SOURCES/glibc-RHEL-54447-6.patch b/SOURCES/glibc-RHEL-54447-6.patch
new file mode 100644
index 0000000000000000000000000000000000000000..006e312af871c3371be63212f940335455de5d1c
--- /dev/null
+++ b/SOURCES/glibc-RHEL-54447-6.patch
@@ -0,0 +1,136 @@
+commit a5cd39541396b91d90cc611858ee7b3355fcfe47
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Tue Aug 13 21:08:49 2024 -0400
+
+    ungetc: Fix backup buffer leak on program exit [BZ #27821]
+    
+    If a file descriptor is left unclosed and is cleaned up by _IO_cleanup
+    on exit, its backup buffer remains unfreed, registering as a leak in
+    valgrind.  This is not strictly an issue since (1) the program should
+    ideally be closing the stream once it's not in use and (2) the program
+    is about to exit anyway, so keeping the backup buffer around a wee bit
+    longer isn't a real problem.  Free it anyway to keep valgrind happy
+    when the streams in question are the standard ones, i.e. stdout, stdin
+    or stderr.
+    
+    Also, the _IO_have_backup macro checks for _IO_save_base,
+    which is a roundabout way to check for a backup buffer instead of
+    directly looking for _IO_backup_base.  The roundabout check breaks when
+    the main get area has not been used and user pushes a char into the
+    backup buffer with ungetc.  Fix this to use the _IO_backup_base
+    directly.
+    
+    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+    (cherry picked from commit 3e1d8d1d1dca24ae90df2ea826a8916896fc7e77)
+    (cherry picked from commit b9f72bd5de931eac39219018c2fa319a449bb2cf)
+
+diff --git a/libio/genops.c b/libio/genops.c
+index a5dd6a06d9e259d8..b5fc53fd1ef6e911 100644
+--- a/libio/genops.c
++++ b/libio/genops.c
+@@ -796,6 +796,12 @@ _IO_unbuffer_all (void)
+ 	legacy = 1;
+ #endif
+ 
++      /* Free up the backup area if it was ever allocated.  */
++      if (_IO_have_backup (fp))
++	_IO_free_backup_area (fp);
++      if (fp->_mode > 0 && _IO_have_wbackup (fp))
++	_IO_free_wbackup_area (fp);
++
+       if (! (fp->_flags & _IO_UNBUFFERED)
+ 	  /* Iff stream is un-orientated, it wasn't used. */
+ 	  && (legacy || fp->_mode != 0))
+diff --git a/libio/libioP.h b/libio/libioP.h
+index dc9a2ce9c8d7744c..bab5f3770f0760c4 100644
+--- a/libio/libioP.h
++++ b/libio/libioP.h
+@@ -529,8 +529,8 @@ extern void _IO_old_init (FILE *fp, int flags) __THROW;
+        ((__fp)->_wide_data->_IO_write_base \
+ 	= (__fp)->_wide_data->_IO_write_ptr = __p, \
+ 	(__fp)->_wide_data->_IO_write_end = (__ep))
+-#define _IO_have_backup(fp) ((fp)->_IO_save_base != NULL)
+-#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_save_base != NULL)
++#define _IO_have_backup(fp) ((fp)->_IO_backup_base != NULL)
++#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_backup_base != NULL)
+ #define _IO_in_backup(fp) ((fp)->_flags & _IO_IN_BACKUP)
+ #define _IO_have_markers(fp) ((fp)->_markers != NULL)
+ #define _IO_blen(fp) ((fp)->_IO_buf_end - (fp)->_IO_buf_base)
+diff --git a/stdio-common/Makefile b/stdio-common/Makefile
+index 08bedd01be61a55d..f10bf28878e0aebc 100644
+--- a/stdio-common/Makefile
++++ b/stdio-common/Makefile
+@@ -201,6 +201,7 @@ tests := \
+   tst-swscanf \
+   tst-tmpnam \
+   tst-ungetc \
++  tst-ungetc-leak \
+   tst-unlockedio \
+   tst-vfprintf-mbs-prec \
+   tst-vfprintf-user-type \
+@@ -229,6 +230,7 @@ tests-special += \
+   $(objpfx)tst-printfsz-islongdouble.out \
+   $(objpfx)tst-setvbuf1-cmp.out \
+   $(objpfx)tst-unbputc.out \
++  $(objpfx)tst-ungetc-leak-mem.out \
+   $(objpfx)tst-vfprintf-width-prec-mem.out \
+   # tests-special
+ 
+@@ -243,6 +245,8 @@ generated += \
+   tst-printf-fp-leak-mem.out \
+   tst-printf-fp-leak.mtrace \
+   tst-scanf-bz27650.mtrace \
++  tst-ungetc-leak-mem.out \
++  tst-ungetc-leak.mtrace \
+   tst-vfprintf-width-prec-mem.out \
+   tst-vfprintf-width-prec.mtrace \
+   # generated
+@@ -288,6 +292,9 @@ tst-printf-fp-leak-ENV = \
+ tst-scanf-bz27650-ENV = \
+   MALLOC_TRACE=$(objpfx)tst-scanf-bz27650.mtrace \
+   LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
++tst-ungetc-leak-ENV = \
++  MALLOC_TRACE=$(objpfx)tst-ungetc-leak.mtrace \
++  LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
+ 
+ $(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
+ 	$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
+diff --git a/stdio-common/tst-ungetc-leak.c b/stdio-common/tst-ungetc-leak.c
+new file mode 100644
+index 0000000000000000..6c5152b43f80b217
+--- /dev/null
++++ b/stdio-common/tst-ungetc-leak.c
+@@ -0,0 +1,32 @@
++/* Test for memory leak with ungetc when stream is unused.
++   Copyright The GNU Toolchain Authors.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <stdio.h>
++#include <mcheck.h>
++#include <support/check.h>
++#include <support/support.h>
++
++static int
++do_test (void)
++{
++  mtrace ();
++  TEST_COMPARE (ungetc('y', stdin), 'y');
++  return 0;
++}
++
++#include <support/test-driver.c>
diff --git a/SOURCES/glibc-RHEL-54447-7.patch b/SOURCES/glibc-RHEL-54447-7.patch
new file mode 100644
index 0000000000000000000000000000000000000000..9446d2a2547591f893da87e4a86092a18913f23e
--- /dev/null
+++ b/SOURCES/glibc-RHEL-54447-7.patch
@@ -0,0 +1,83 @@
+commit 9d26e50364def249e483b1601beb6ecf9141ecc7
+Author: Maciej W. Rozycki <macro@redhat.com>
+Date:   Fri Jul 26 13:21:34 2024 +0100
+
+    posix: Use <support/check.h> facilities in tst-truncate and tst-truncate64
+    
+    Remove local FAIL macro in favor to FAIL_RET from <support/check.h>,
+    which provides equivalent reporting, with the name of the file of the
+    failure site additionally included, for the tst-truncate-common core
+    shared between the tst-truncate and tst-truncate64 tests.
+    
+    Reviewed-by: DJ Delorie <dj@redhat.com>
+    (cherry picked from commit fe47595504a55e7bb992f8928533df154b510383)
+
+diff --git a/posix/tst-truncate-common.c b/posix/tst-truncate-common.c
+index 00c999d372693bfa..1f6c4bd256a638f9 100644
+--- a/posix/tst-truncate-common.c
++++ b/posix/tst-truncate-common.c
+@@ -21,6 +21,8 @@
+ #include <sys/stat.h>
+ #include <unistd.h>
+ 
++#include <support/check.h>
++
+ static void do_prepare (void);
+ #define PREPARE(argc, argv)     do_prepare ()
+ static int do_test (void);
+@@ -42,9 +44,6 @@ do_prepare (void)
+     }
+ }
+ 
+-#define FAIL(str) \
+-  do { printf ("error: %s (line %d)\n", str, __LINE__); return 1; } while (0)
+-
+ static int
+ do_test_with_offset (off_t offset)
+ {
+@@ -54,35 +53,35 @@ do_test_with_offset (off_t offset)
+   memset (buf, 0xcf, sizeof (buf));
+ 
+   if (pwrite (temp_fd, buf, sizeof (buf), offset) != sizeof (buf))
+-    FAIL ("write failed");
++    FAIL_RET ("write failed");
+   if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + sizeof (buf)))
+-    FAIL ("initial size wrong");
++    FAIL_RET ("initial size wrong");
+ 
+   if (ftruncate (temp_fd, offset + 800) < 0)
+-    FAIL ("size reduction with ftruncate failed");
++    FAIL_RET ("size reduction with ftruncate failed");
+   if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800))
+-    FAIL ("size after reduction with ftruncate is incorrect");
++    FAIL_RET ("size after reduction with ftruncate is incorrect");
+ 
+   /* The following test covers more than POSIX.  POSIX does not require
+      that ftruncate() can increase the file size.  But we are testing
+      Unix systems.  */
+   if (ftruncate (temp_fd, offset + 1200) < 0)
+-    FAIL ("size increate with ftruncate failed");
++    FAIL_RET ("size increate with ftruncate failed");
+   if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200))
+-    FAIL ("size after increase is incorrect");
++    FAIL_RET ("size after increase is incorrect");
+ 
+   if (truncate (temp_filename, offset + 800) < 0)
+-    FAIL ("size reduction with truncate failed");
++    FAIL_RET ("size reduction with truncate failed");
+   if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800))
+-    FAIL ("size after reduction with truncate incorrect");
++    FAIL_RET ("size after reduction with truncate incorrect");
+ 
+   /* The following test covers more than POSIX.  POSIX does not require
+      that truncate() can increase the file size.  But we are testing
+      Unix systems.  */
+   if (truncate (temp_filename, (offset + 1200)) < 0)
+-    FAIL ("size increase with truncate failed");
++    FAIL_RET ("size increase with truncate failed");
+   if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200))
+-    FAIL ("size increase with truncate is incorrect");
++    FAIL_RET ("size increase with truncate is incorrect");
+ 
+   return 0;
+ }
diff --git a/SOURCES/glibc-RHEL-54447-8.patch b/SOURCES/glibc-RHEL-54447-8.patch
new file mode 100644
index 0000000000000000000000000000000000000000..b4e804fd6f72af52c5f3f4f398198c8c4c583533
--- /dev/null
+++ b/SOURCES/glibc-RHEL-54447-8.patch
@@ -0,0 +1,129 @@
+commit c21ca2a696c03ff3f3931768a3ada234eebf6337
+Author: Maciej W. Rozycki <macro@redhat.com>
+Date:   Fri Jul 26 13:21:34 2024 +0100
+
+    nptl: Use <support/check.h> facilities in tst-setuid3
+    
+    Remove local FAIL macro in favor to FAIL_EXIT1 from <support/check.h>,
+    which provides equivalent reporting, with the name of the file and the
+    line number within of the failure site additionally included.  Remove
+    FAIL_ERR altogether and include ": %m" explicitly with the format string
+    supplied to FAIL_EXIT1 as there seems little value to have a separate
+    macro just for this.
+    
+    Reviewed-by: DJ Delorie <dj@redhat.com>
+    (cherry picked from commit 8c98195af6e6f1ce21743fc26c723e0f7e45bcf2)
+
+diff --git a/sysdeps/pthread/tst-setuid3.c b/sysdeps/pthread/tst-setuid3.c
+index 254555960e1ffe74..88a2a3ef20e273f7 100644
+--- a/sysdeps/pthread/tst-setuid3.c
++++ b/sysdeps/pthread/tst-setuid3.c
+@@ -15,24 +15,19 @@
+    License along with the GNU C Library; if not, see
+    <https://www.gnu.org/licenses/>.  */
+ 
+-#include <stdio.h>
+ #include <errno.h>
+ #include <pthread.h>
+ #include <stdbool.h>
+ #include <unistd.h>
+ 
++#include <support/check.h>
++
+ /* The test must run under a non-privileged user ID.  */
+ static const uid_t test_uid = 1;
+ 
+ static pthread_barrier_t barrier1;
+ static pthread_barrier_t barrier2;
+ 
+-#define FAIL(fmt, ...) \
+-  do { printf ("FAIL: " fmt "\n", __VA_ARGS__); _exit (1); } while (0)
+-
+-#define FAIL_ERR(fmt, ...) \
+-  do { printf ("FAIL: " fmt ": %m\n", __VA_ARGS__); _exit (1); } while (0)
+-
+ /* True if x is not a successful return code from pthread_barrier_wait.  */
+ static inline bool
+ is_invalid_barrier_ret (int x)
+@@ -45,10 +40,10 @@ thread_func (void *ctx __attribute__ ((unused)))
+ {
+   int ret = pthread_barrier_wait (&barrier1);
+   if (is_invalid_barrier_ret (ret))
+-    FAIL ("pthread_barrier_wait (barrier1) (on thread): %d", ret);
++    FAIL_EXIT1 ("pthread_barrier_wait (barrier1) (on thread): %d", ret);
+   ret = pthread_barrier_wait (&barrier2);
+   if (is_invalid_barrier_ret (ret))
+-    FAIL ("pthread_barrier_wait (barrier2) (on thread): %d", ret);
++    FAIL_EXIT1 ("pthread_barrier_wait (barrier2) (on thread): %d", ret);
+   return NULL;
+ }
+ 
+@@ -59,13 +54,13 @@ setuid_failure (int phase)
+   switch (ret)
+     {
+     case 0:
+-      FAIL ("setuid succeeded unexpectedly in phase %d", phase);
++      FAIL_EXIT1 ("setuid succeeded unexpectedly in phase %d", phase);
+     case -1:
+       if (errno != EPERM)
+-	FAIL_ERR ("setuid phase %d", phase);
++	FAIL_EXIT1 ("setuid phase %d: %m", phase);
+       break;
+     default:
+-      FAIL ("invalid setuid return value in phase %d: %d", phase, ret);
++      FAIL_EXIT1 ("invalid setuid return value in phase %d: %d", phase, ret);
+     }
+ }
+ 
+@@ -74,42 +69,42 @@ do_test (void)
+ {
+   if (getuid () == 0)
+     if (setuid (test_uid) != 0)
+-      FAIL_ERR ("setuid (%u)", (unsigned) test_uid);
++      FAIL_EXIT1 ("setuid (%u): %m", (unsigned) test_uid);
+   if (setuid (getuid ()))
+-    FAIL_ERR ("setuid (%s)", "getuid ()");
++    FAIL_EXIT1 ("setuid (%s): %m", "getuid ()");
+   setuid_failure (1);
+ 
+   int ret = pthread_barrier_init (&barrier1, NULL, 2);
+   if (ret != 0)
+-    FAIL ("pthread_barrier_init (barrier1): %d", ret);
++    FAIL_EXIT1 ("pthread_barrier_init (barrier1): %d", ret);
+   ret = pthread_barrier_init (&barrier2, NULL, 2);
+   if (ret != 0)
+-    FAIL ("pthread_barrier_init (barrier2): %d", ret);
++    FAIL_EXIT1 ("pthread_barrier_init (barrier2): %d", ret);
+ 
+   pthread_t thread;
+   ret = pthread_create (&thread, NULL, thread_func, NULL);
+   if (ret != 0)
+-    FAIL ("pthread_create: %d", ret);
++    FAIL_EXIT1 ("pthread_create: %d", ret);
+ 
+   /* Ensure that the thread is running properly.  */
+   ret = pthread_barrier_wait (&barrier1);
+   if (is_invalid_barrier_ret (ret))
+-    FAIL ("pthread_barrier_wait (barrier1): %d", ret);
++    FAIL_EXIT1 ("pthread_barrier_wait (barrier1): %d", ret);
+ 
+   setuid_failure (2);
+ 
+   /* Check success case. */
+   if (setuid (getuid ()) != 0)
+-    FAIL_ERR ("setuid (%s)", "getuid ()");
++    FAIL_EXIT1 ("setuid (%s): %m", "getuid ()");
+ 
+   /* Shutdown.  */
+   ret = pthread_barrier_wait (&barrier2);
+   if (is_invalid_barrier_ret (ret))
+-    FAIL ("pthread_barrier_wait (barrier2): %d", ret);
++    FAIL_EXIT1 ("pthread_barrier_wait (barrier2): %d", ret);
+ 
+   ret = pthread_join (thread, NULL);
+   if (ret != 0)
+-    FAIL ("pthread_join: %d", ret);
++    FAIL_EXIT1 ("pthread_join: %d", ret);
+ 
+   return 0;
+ }
diff --git a/SOURCES/glibc-RHEL-54447-9.patch b/SOURCES/glibc-RHEL-54447-9.patch
new file mode 100644
index 0000000000000000000000000000000000000000..18e63df09a805e300610a5d49794aeda36605472
--- /dev/null
+++ b/SOURCES/glibc-RHEL-54447-9.patch
@@ -0,0 +1,27 @@
+commit ae4d44b1d501421ad9a3af95279b8f4d1546f1ce
+Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date:   Tue Sep 3 14:58:33 2024 -0400
+
+    libio: Attempt wide backup free only for non-legacy code
+    
+    _wide_data and _mode are not available in legacy code, so do not attempt
+    to free the wide backup buffer in legacy code.
+    
+    Resolves: BZ #32137 and BZ #27821
+    
+    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+    Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+diff --git a/libio/genops.c b/libio/genops.c
+index b5fc53fd1ef6e911..99ef9d03505f3238 100644
+--- a/libio/genops.c
++++ b/libio/genops.c
+@@ -799,7 +799,7 @@ _IO_unbuffer_all (void)
+       /* Free up the backup area if it was ever allocated.  */
+       if (_IO_have_backup (fp))
+ 	_IO_free_backup_area (fp);
+-      if (fp->_mode > 0 && _IO_have_wbackup (fp))
++      if (!legacy && fp->_mode > 0 && _IO_have_wbackup (fp))
+ 	_IO_free_wbackup_area (fp);
+ 
+       if (! (fp->_flags & _IO_UNBUFFERED)
diff --git a/SPECS/glibc.spec b/SPECS/glibc.spec
index f1d2ec3181fba003f8abe2dd1d74995104a2c049..a4b9704ab23dec4ef0b1d5dfce12fd5a941b9591 100644
--- a/SPECS/glibc.spec
+++ b/SPECS/glibc.spec
@@ -84,6 +84,8 @@
 %undefine _annotated_build
 %endif
 
+%define man_pages_version 6.04-1.el9
+
 ##############################################################################
 # Any architecture/kernel combination that supports running 32-bit and 64-bit
 # code in userspace is considered a biarch arch.
@@ -155,7 +157,7 @@ end \
 Summary: The GNU libc libraries
 Name: glibc
 Version: %{glibcversion}
-Release: 100%{?dist}.4
+Release: 125%{?dist}.1
 
 # In general, GPLv2+ is used by programs, LGPLv2+ is used for
 # libraries.
@@ -808,16 +810,67 @@ Patch571: glibc-RHEL-16643-5.patch
 Patch572: glibc-RHEL-16643-6.patch
 Patch573: glibc-RHEL-19444.patch
 Patch574: glibc-RHEL-21556.patch
-Patch575: glibc-RHEL-32480.patch
-Patch576: glibc-RHEL-34318-1.patch
-Patch577: glibc-RHEL-34318-2.patch
-Patch578: glibc-RHEL-34318-3.patch
-Patch579: glibc-RHEL-34318-4.patch
-Patch580: glibc-RHEL-39993-1.patch
-Patch581: glibc-RHEL-39993-2.patch
-Patch582: glibc-RHEL-46763-1.patch
-Patch583: glibc-RHEL-46763-2.patch
-Patch584: glibc-RHEL-46763-3.patch
+Patch575: glibc-RHEL-23472.patch
+Patch576: glibc-RHEL-20172-1.patch
+Patch577: glibc-RHEL-20172-2.patch
+Patch578: glibc-RHEL-21884.patch
+Patch579: glibc-RHEL-25531-1.patch
+Patch580: glibc-RHEL-25531-2.patch
+Patch581: glibc-RHEL-25531-3.patch
+Patch582: glibc-RHEL-25531-4.patch
+Patch583: glibc-RHEL-25046.patch
+Patch584: glibc-RHEL-32681-1.patch
+Patch585: glibc-RHEL-32681-2.patch
+Patch586: glibc-RHEL-39006.patch
+Patch587: glibc-RHEL-22165-1.patch
+Patch588: glibc-RHEL-22165-2.patch
+Patch589: glibc-RHEL-22165-3.patch
+Patch590: glibc-RHEL-22165-4.patch
+Patch591: glibc-RHEL-22165-5.patch
+Patch592: glibc-RHEL-31805.patch
+Patch593: glibc-RHEL-25063.patch
+Patch594: glibc-RHEL-34265.patch
+Patch595: glibc-RHEL-34268-1.patch
+Patch596: glibc-RHEL-34268-2.patch
+Patch597: glibc-RHEL-34272-1.patch
+Patch598: glibc-RHEL-34272-2.patch
+Patch599: glibc-RHEL-39000-1.patch
+Patch600: glibc-RHEL-39000-2.patch
+Patch601: glibc-RHEL-39000-3.patch
+Patch602: glibc-RHEL-39992-1.patch
+Patch603: glibc-RHEL-39992-2.patch
+Patch604: glibc-RHEL-30823.patch
+Patch605: glibc-RHEL-25257-1.patch
+Patch606: glibc-RHEL-25257-2.patch
+Patch607: glibc-RHEL-46741-1.patch
+Patch608: glibc-RHEL-46741-2.patch
+Patch609: glibc-RHEL-50101-1.patch
+Patch610: glibc-RHEL-50101-2.patch
+Patch611: glibc-RHEL-50101-3.patch
+Patch612: glibc-RHEL-54007.patch
+Patch613: glibc-RHEL-46723-1.patch
+Patch614: glibc-RHEL-46723-2.patch
+Patch615: glibc-RHEL-36148-1.patch
+Patch616: glibc-RHEL-36148-2.patch
+Patch617: glibc-RHEL-36148-3.patch
+Patch618: glibc-RHEL-49489-1.patch
+Patch619: glibc-RHEL-49489-2.patch
+Patch620: glibc-RHEL-54447-1.patch
+Patch621: glibc-RHEL-54447-2.patch
+Patch622: glibc-RHEL-54447-3.patch
+Patch623: glibc-RHEL-54447-4.patch
+Patch624: glibc-RHEL-54447-5.patch
+Patch625: glibc-RHEL-54447-6.patch
+Patch626: glibc-RHEL-54447-7.patch
+Patch627: glibc-RHEL-54447-8.patch
+Patch628: glibc-RHEL-54447-9.patch
+Patch629: glibc-RHEL-54447-10.patch
+Patch630: glibc-RHEL-46979-1.patch
+Patch631: glibc-RHEL-46979-2.patch
+Patch632: glibc-RHEL-46979-3.patch
+Patch633: glibc-RHEL-46979-4.patch
+Patch634: glibc-RHEL-49489-3.patch
+Patch635: glibc-RHEL-49489-4.patch
 
 ##############################################################################
 # Continued list of core "glibc" package information:
@@ -1826,6 +1879,7 @@ build()
 %ifarch aarch64
 		--enable-memory-tagging \
 %endif
+		--with-man-pages=%{man_pages_version} \
 		--disable-crypt ||
 		{ cat config.log; false; }
 
@@ -2976,22 +3030,92 @@ update_gconv_modules_cache ()
 %endif
 
 %changelog
-* Tue Aug 27 2024 Patsy Griffin <patsy@redhat.com> - 2.34-100.4
+* Fri Sep 27 2024 Florian Weimer <fweimer@redhat.com> - 2.34-125.1
+- Remove some unused ppc64le string functions (RHEL-49489)
+
+* Thu Sep  5 2024 DJ Delorie <dj@redhat.com> - 2.34-125
+- elf: Rework exception handling in the dynamic loader (RHEL-46979)
+
+* Thu Sep  5 2024 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.34-124
+- Fix ungetc leak and invalid read (RHEL-54447)
+
+* Tue Sep 03 2024 Patsy Griffin <patsy@redhat.com> - 2.34-123
+- s390x: Fix segfault in wcsncmp
+- Enhanced test coverage for strncmp, wcsncmp (RHEL-49489)
+
+* Wed Aug 28 2024 Patsy Griffin <patsy@redhat.com> - 2.34-122
 - elf: Clarify and invert second argument of _dl_allocate_tls_init
-- elf: Avoid re-initializing already allocated TLS in dlopen (RHEL-46763)
+- elf: Avoid re-initializing already allocated TLS in dlopen (RHEL-36148)
+
+* Thu Aug 15 2024 Florian Weimer <fweimer@redhat.com> - 2.34-121
+- Document dprintf, vdprintf in the manual (RHEL-46723)
 
-* Fri Jul 12 2024 Patsy Griffin <patsy@redhat.com> - 2.34-100.3
+* Tue Aug 13 2024 Frédéric Bérat <fberat@redhat.com> - 2.34-120
+- getdelim: ensure error indicator is set on error (RHEL-54007)
+
+* Tue Aug 06 2024 Arjun Shankar <arjun@redhat.com> - 2.34-119
+- Add new tests for aligned_alloc (RHEL-50101)
+
+* Tue Aug 06 2024 Arjun Shankar <arjun@redhat.com> - 2.34-118
+- manual: Improve documentation of putc, putwc, getc, and getwc (RHEL-46741)
+
+* Wed Jul 17 2024 DJ Delorie <dj@redhat.com> - 2.34-117
+- manual: add syscalls (RHEL-25257)
+
+* Fri Jul 12 2024 DJ Delorie <dj@redhat.com> - 2.34-116
+- Update mmap() flags and errors lists (RHEL-30823)
+
+* Wed Jul 03 2024 Patsy Griffin <patsy@redhat.com> - 2.34-115
 - elf: Avoid some free (NULL) calls in _dl_update_slotinfo
-- elf: Support recursive use of dynamic TLS in interposed malloc (RHEL-39993)
+- elf: Support recursive use of dynamic TLS in interposed malloc (RHEL-39992)
+
+* Wed Jun 26 2024 Patsy Griffin <patsy@redhat.com> - 2.34-114
+- Update syscall list for Linux 6.9. (RHEL-39000)
+
+* Thu Jun 13 2024 Patsy Griffin <patsy@redhat.com> - 2.34-113
+- CVE-2024-33601 glibc: netgroup cache may terminate daemon on
+  memory allocation failure (RHEL-34272)
+- CVE-2024-33602 glibc: netgroup cache assumes NSS callback 
+  uses in-buffer strings (RHEL-34274) 
+
+* Tue Jun 11 2024 Patsy Griffin <patsy@redhat.com> - 2.34-112
+- CVE-2024-33600: nscd: Avoid null pointer crashes after notfound
+  response (RHEL-34268)
+
+* Mon Jun 10 2024 Patsy Griffin <patsy@redhat.com> - 2.34-111
+- CVE-2024-33599: nscd: buffer overflow in netgroup cache (RHEL-34265)
+
+* Mon Jun 10 2024 Arjun Shankar <arjun@redhat.com> - 2.34-110
+- Add new test for malloc mmap fall-back path upon sbrk failure (RHEL-25063)
+
+* Thu Jun 06 2024 Patsy Griffin <patsy@redhat.com> - 2.34-109
+- CVE-2024-2961: Out of bounds write in iconv conversion to
+  ISO-2022-CN-EXT (RHEL-31805)
+
+* Thu Jun 06 2024 Patsy Griffin <patsy@redhat.com> - 2.34-108
+- aarch64: enhance ld.so --list-diagnostics on aarch64 similar
+  to x86_64 (RHEL-22165)
+
+* Tue May 28 2024 <dj@redhat.com> - 2.34-107
+- Add MMAP_ABOVE4G from Linux 6.6 to sys/mman.h (RHEL-39006)
+
+* Sun May 19 2024 Patsy Griffin <patsy@redhat.com> - 2.34-106
+- Improve test coverage for connect() (RHEL-32681)
+
+* Wed Apr  3 2024 DJ Delorie <dj@redhat.com> - 2.34-105
+- x86-64: Save APX registers in ld.so trampoline (RHEL-25046)
+
+* Tue Mar 26 2024 DJ Delorie <dj@redhat.com> - 2.34-104
+- x86: Fix Zen3/Zen4 ERMS selection (RHEL-25531)
+
+* Tue Mar 12 2024 Arjun Shankar <arjun@redhat.com> - 2.34-103
+- malloc: Do not use MAP_NORESERVE to allocate heap segments (RHEL-21884)
 
-* Mon Apr 29 2024 Florian Weimer <fweimer@redhat.com> - 2.34-100.2
-- CVE-2024-33599: nscd: buffer overflow in netgroup cache (RHEL-34318)
-- CVE-2024-33600: nscd: null pointer dereferences in netgroup cache
-- CVE-2024-33601: nscd: crash on out-of-memory condition
-- CVE-2024-33602: nscd: memory corruption with NSS netgroup modules
+* Fri Mar  8 2024 DJ Delorie <dj@redhat.com> - 2.34-102
+- Add glibc.cpu.prefer_map_32bit_exec tunable (RHEL-20172)
 
-* Tue Apr 16 2024 Florian Weimer <fweimer@redhat.com> - 2.34-100.1
-- CVE-2024-2961: Out of bounds write in iconv conversion to ISO-2022-CN-EXT (RHEL-32480)
+* Tue Feb 27 2024 Patsy Griffin <patsy@redhat.com> - 2.34-101
+- Switch back to assembly syscall wrapper for prctl (RHEL-23472)
 
 * Wed Jan 24 2024 Patsy Griffin <patsy@redhat.com> - 2.34-100
 - manual: fix order of arguments of memalign and aligned_alloc (RHEL-21556)