From 7e0d43019934016e690b9f491c15c74eadbea764 Mon Sep 17 00:00:00 2001
From: Peridot Bot <rockyautomation@rockylinux.org>
Date: Fri, 1 Nov 2024 15:17:52 +0000
Subject: [PATCH] import glibc-2.34-122.el9_5

---
 .glibc.checksum                  |   2 +-
 SOURCES/glibc-RHEL-20172-1.patch | 369 +++++++++++++++
 SOURCES/glibc-RHEL-20172-2.patch |  29 ++
 SOURCES/glibc-RHEL-21884.patch   |  73 +++
 SOURCES/glibc-RHEL-22165-1.patch | 229 ++++++++++
 SOURCES/glibc-RHEL-22165-2.patch |  74 +++
 SOURCES/glibc-RHEL-22165-3.patch | 144 ++++++
 SOURCES/glibc-RHEL-22165-4.patch | 510 +++++++++++++++++++++
 SOURCES/glibc-RHEL-22165-5.patch | 262 +++++++++++
 SOURCES/glibc-RHEL-23472.patch   | 140 ++++++
 SOURCES/glibc-RHEL-25046.patch   |  88 ++++
 SOURCES/glibc-RHEL-25063.patch   | 109 +++++
 SOURCES/glibc-RHEL-25257-1.patch |  26 ++
 SOURCES/glibc-RHEL-25257-2.patch | 341 ++++++++++++++
 SOURCES/glibc-RHEL-25531-1.patch | 188 ++++++++
 SOURCES/glibc-RHEL-25531-2.patch | 155 +++++++
 SOURCES/glibc-RHEL-25531-3.patch |  34 ++
 SOURCES/glibc-RHEL-25531-4.patch |  29 ++
 SOURCES/glibc-RHEL-30823.patch   | 205 +++++++++
 SOURCES/glibc-RHEL-31805.patch   | 207 +++++++++
 SOURCES/glibc-RHEL-32681-1.patch | 142 ++++++
 SOURCES/glibc-RHEL-32681-2.patch |  66 +++
 SOURCES/glibc-RHEL-34265.patch   |  31 ++
 SOURCES/glibc-RHEL-34268-1.patch |  53 +++
 SOURCES/glibc-RHEL-34268-2.patch |  52 +++
 SOURCES/glibc-RHEL-34272-1.patch | 382 ++++++++++++++++
 SOURCES/glibc-RHEL-34272-2.patch |  30 ++
 SOURCES/glibc-RHEL-36148-1.patch |  88 ++++
 SOURCES/glibc-RHEL-36148-2.patch | 520 +++++++++++++++++++++
 SOURCES/glibc-RHEL-36148-3.patch |  16 +
 SOURCES/glibc-RHEL-39000-1.patch | 593 ++++++++++++++++++++++++
 SOURCES/glibc-RHEL-39000-2.patch | 756 +++++++++++++++++++++++++++++++
 SOURCES/glibc-RHEL-39000-3.patch |  28 ++
 SOURCES/glibc-RHEL-39006.patch   |  26 ++
 SOURCES/glibc-RHEL-39992-1.patch |  43 ++
 SOURCES/glibc-RHEL-39992-2.patch | 499 ++++++++++++++++++++
 SOURCES/glibc-RHEL-46723-1.patch |  44 ++
 SOURCES/glibc-RHEL-46723-2.patch |  53 +++
 SOURCES/glibc-RHEL-46741-1.patch |  50 ++
 SOURCES/glibc-RHEL-46741-2.patch |  71 +++
 SOURCES/glibc-RHEL-50101-1.patch | 240 ++++++++++
 SOURCES/glibc-RHEL-50101-2.patch |  86 ++++
 SOURCES/glibc-RHEL-50101-3.patch | 251 ++++++++++
 SOURCES/glibc-RHEL-54007.patch   | 121 +++++
 SPECS/glibc.spec                 | 122 ++++-
 45 files changed, 7575 insertions(+), 2 deletions(-)
 create mode 100644 SOURCES/glibc-RHEL-20172-1.patch
 create mode 100644 SOURCES/glibc-RHEL-20172-2.patch
 create mode 100644 SOURCES/glibc-RHEL-21884.patch
 create mode 100644 SOURCES/glibc-RHEL-22165-1.patch
 create mode 100644 SOURCES/glibc-RHEL-22165-2.patch
 create mode 100644 SOURCES/glibc-RHEL-22165-3.patch
 create mode 100644 SOURCES/glibc-RHEL-22165-4.patch
 create mode 100644 SOURCES/glibc-RHEL-22165-5.patch
 create mode 100644 SOURCES/glibc-RHEL-23472.patch
 create mode 100644 SOURCES/glibc-RHEL-25046.patch
 create mode 100644 SOURCES/glibc-RHEL-25063.patch
 create mode 100644 SOURCES/glibc-RHEL-25257-1.patch
 create mode 100644 SOURCES/glibc-RHEL-25257-2.patch
 create mode 100644 SOURCES/glibc-RHEL-25531-1.patch
 create mode 100644 SOURCES/glibc-RHEL-25531-2.patch
 create mode 100644 SOURCES/glibc-RHEL-25531-3.patch
 create mode 100644 SOURCES/glibc-RHEL-25531-4.patch
 create mode 100644 SOURCES/glibc-RHEL-30823.patch
 create mode 100644 SOURCES/glibc-RHEL-31805.patch
 create mode 100644 SOURCES/glibc-RHEL-32681-1.patch
 create mode 100644 SOURCES/glibc-RHEL-32681-2.patch
 create mode 100644 SOURCES/glibc-RHEL-34265.patch
 create mode 100644 SOURCES/glibc-RHEL-34268-1.patch
 create mode 100644 SOURCES/glibc-RHEL-34268-2.patch
 create mode 100644 SOURCES/glibc-RHEL-34272-1.patch
 create mode 100644 SOURCES/glibc-RHEL-34272-2.patch
 create mode 100644 SOURCES/glibc-RHEL-36148-1.patch
 create mode 100644 SOURCES/glibc-RHEL-36148-2.patch
 create mode 100644 SOURCES/glibc-RHEL-36148-3.patch
 create mode 100644 SOURCES/glibc-RHEL-39000-1.patch
 create mode 100644 SOURCES/glibc-RHEL-39000-2.patch
 create mode 100644 SOURCES/glibc-RHEL-39000-3.patch
 create mode 100644 SOURCES/glibc-RHEL-39006.patch
 create mode 100644 SOURCES/glibc-RHEL-39992-1.patch
 create mode 100644 SOURCES/glibc-RHEL-39992-2.patch
 create mode 100644 SOURCES/glibc-RHEL-46723-1.patch
 create mode 100644 SOURCES/glibc-RHEL-46723-2.patch
 create mode 100644 SOURCES/glibc-RHEL-46741-1.patch
 create mode 100644 SOURCES/glibc-RHEL-46741-2.patch
 create mode 100644 SOURCES/glibc-RHEL-50101-1.patch
 create mode 100644 SOURCES/glibc-RHEL-50101-2.patch
 create mode 100644 SOURCES/glibc-RHEL-50101-3.patch
 create mode 100644 SOURCES/glibc-RHEL-54007.patch

diff --git a/.glibc.checksum b/.glibc.checksum
index d358c37..ab98c47 100644
--- a/.glibc.checksum
+++ b/.glibc.checksum
@@ -1 +1 @@
-54baf21f992817d2a795951a8077b40f023c0234ba9e7be5a55de9e0cb83982d
+73b381f39d9e1aec615e5b290a87f3629ffd7227008b2847bfb841c5f874744e
diff --git a/SOURCES/glibc-RHEL-20172-1.patch b/SOURCES/glibc-RHEL-20172-1.patch
new file mode 100644
index 0000000..c9b7599
--- /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 0000000..0a77246
--- /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 0000000..39f1500
--- /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 0000000..3133966
--- /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 0000000..62c2711
--- /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 0000000..392e746
--- /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 0000000..0335b6f
--- /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 0000000..76b42ea
--- /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 0000000..95aae42
--- /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 0000000..db48ca3
--- /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 0000000..58580e9
--- /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 0000000..c7413d7
--- /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 0000000..d6e518b
--- /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 0000000..db0260f
--- /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 0000000..8b90365
--- /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 0000000..5d404f7
--- /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 0000000..089b29c
--- /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 0000000..96c256f
--- /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 0000000..0d7fa4e
--- /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 0000000..c416a97
--- /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 0000000..1f669ff
--- /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 0000000..f390d0c
--- /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 0000000..4642d7a
--- /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 0000000..6619d7c
--- /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 0000000..f8574ea
--- /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 0000000..62930fe
--- /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 0000000..3931b90
--- /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 0000000..607b346
--- /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 0000000..a2b3e76
--- /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 0000000..8de8d2d
--- /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 0000000..2ed92f7
--- /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 0000000..e2d2a83
--- /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 0000000..1d159ef
--- /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 0000000..040a499
--- /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 0000000..df021c9
--- /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 0000000..5f3f226
--- /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 0000000..5b7e73a
--- /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 0000000..c0ba98b
--- /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 0000000..cac84f0
--- /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-50101-1.patch b/SOURCES/glibc-RHEL-50101-1.patch
new file mode 100644
index 0000000..eb722e3
--- /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 0000000..318a037
--- /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 0000000..49c6e28
--- /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 0000000..35b96a6
--- /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/SPECS/glibc.spec b/SPECS/glibc.spec
index a573345..ccce97c 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}
+Release: 122%{?dist}
 
 # In general, GPLv2+ is used by programs, LGPLv2+ is used for
 # libraries.
@@ -808,6 +810,49 @@ 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-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
 
 ##############################################################################
 # Continued list of core "glibc" package information:
@@ -1816,6 +1861,7 @@ build()
 %ifarch aarch64
 		--enable-memory-tagging \
 %endif
+		--with-man-pages=%{man_pages_version} \
 		--disable-crypt ||
 		{ cat config.log; false; }
 
@@ -2966,6 +3012,80 @@ update_gconv_modules_cache ()
 %endif
 
 %changelog
+* 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-36148)
+
+* Thu Aug 15 2024 Florian Weimer <fweimer@redhat.com> - 2.34-121
+- Document dprintf, vdprintf in the manual (RHEL-46723)
+
+* 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-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)
+
+* Fri Mar  8 2024 DJ Delorie <dj@redhat.com> - 2.34-102
+- Add glibc.cpu.prefer_map_32bit_exec tunable (RHEL-20172)
+
+* 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)
 
-- 
GitLab