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" +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 ++# . ++ ++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 ++ . */ ++ ++#ifndef MMAP_X86_64_INTERNAL_H ++#define MMAP_X86_64_INTERNAL_H ++ ++#include ++ ++/* 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 ++ ++#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 ++ . */ ++ ++#include ++#include ++#include ++ ++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 +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 ++ . */ ++ ++#include ++#include ++#include ++ ++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" +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 +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 + +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 +Date: Fri Aug 25 14:15:28 2023 +0200 + + manual: Document ld.so --list-diagnostics output + + Reviewed-by: Adhemerval Zanella + +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 +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 + +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 +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 + + Modified for RHEL by: Patsy Griffin + 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 ++ . */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++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 +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 + +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 @@ + . */ + + #include ++ ++#include ++#include ++#include ++#include + #include ++#include ++#include ++#include ++ ++/* 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 (¤t->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 (¤t->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, ++ ¤t->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, ++ ¤t->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 +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 + +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 ++ . */ ++ ++#ifndef DL_ITERATE_CPU_H ++#define DL_ITERATE_CPU_H ++ ++#include ++#include ++ ++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 ++ . */ ++ ++#ifndef DL_AFFINITY_H ++#define DL_AFFINITY_H ++ ++#include ++#include ++ ++/* 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 ++ . */ ++ ++/* See sysdeps/generic/dl-affinity.h for documentation of these interfaces. */ ++ ++#ifndef DL_AFFINITY_H ++#define DL_AFFINITY_H ++ ++#include ++#include ++#include ++ ++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 +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 + + 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 +- . */ +- +-#include +-#include +-#include +- +-/* 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 ++ . */ ++ ++#include ++#include ++#include ++ ++/* 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" +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 + +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 +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 + Reviewed-by: Zack Weinberg + +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 ++ . */ ++ ++/* 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 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 +Date: Fri, 10 May 2024 17:34:29 -0400 +Subject: manual: add dup3 + +Reviewed-by: Florian Weimer + +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 +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 + +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 +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 +Tested-by: Zhangfei Gao + +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 +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 + +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 +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 +--- + 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 +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 +--- + 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 +-- +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 +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 + +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 +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 + Reviewed-by: Carlos O'Donell + Tested-by: Carlos O'Donell + +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 ++ . */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* 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 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 +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 + +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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 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 +Date: Wed Apr 10 17:58:04 2024 +0200 + + libsupport: Add xgetpeername + + The patch adds redirections for getpeername. + + Reviewed-by: Arjun Shankar + +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 ++ . */ ++ ++#include ++ ++#include ++#include ++#include ++ ++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 +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 + +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 +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 + +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 +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 + +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 +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 + +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 + #include + #include ++#include + + #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, ¬found, 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, ¬found, 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 +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 + +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 +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 + +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 +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 + Reviewed-by: Carlos O'Donell + +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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++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 +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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++ ++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 +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 ++ . */ ++ ++/* 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 ++ . */ ++ ++#include ++ ++/* 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++/* 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 + + 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 +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 + +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 +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 + +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 +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 + +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 +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 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 +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 + + + 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 + +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 +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 + + Reworked for RHEL by: Patsy Griffin + +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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++/* 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 +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 ++ . */ ++ ++#include ++#include ++ ++__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 ++ . */ ++ ++/* 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 +Date: Tue Aug 13 15:52:34 2024 +0200 + + manual: Document generic printf error codes + + Describe EOVERFLOW, ENOMEN, EILSEQ. + + Reviewed-by: Carlos O'Donell + +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 +Date: Tue Aug 13 15:52:34 2024 +0200 + + manual: Document dprintf and vdprintf + + Reviewed-by: Carlos O'Donell + +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 +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 + +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 +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 + +diff --git a/manual/stdio.texi b/manual/stdio.texi +index 0c9a7ce4a9df4c05..567f6780011f9db1 100644 +--- a/manual/stdio.texi ++++ b/manual/stdio.texi +@@ -904,20 +904,16 @@ This function is a GNU extension. + @standards{ISO, stdio.h} + @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} + This is just like @code{fputc}, except that it may be implemented as +-a macro, making it faster. One consequence is that it may evaluate the +-@var{stream} argument more than once, which is an exception to the +-general rule for macros. Therefore, @var{stream} should never be an +-expression with side-effects. ++a macro and may evaluate the @var{stream} argument more than once. ++Therefore, @var{stream} should never be an expression with side-effects. + @end deftypefun + + @deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream}) + @standards{ISO, wchar.h} + @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} + This is just like @code{fputwc}, except that it may be implemented as +-a macro, making it faster. One consequence is that it may evaluate the +-@var{stream} argument more than once, which is an exception to the +-general rule for macros. Therefore, @var{stream} should never be an +-expression with side-effects. ++a macro and may evaluate the @var{stream} argument more than once. ++Therefore, @var{stream} should never be an expression with side-effects. + @end deftypefun + + @deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream}) +@@ -1110,20 +1106,17 @@ This function is a GNU extension. + @deftypefun int getc (FILE *@var{stream}) + @standards{ISO, stdio.h} + @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} +-This is just like @code{fgetc}, except that it is permissible (and +-typical) for it to be implemented as a macro that evaluates the +-@var{stream} argument more than once. @code{getc} is often highly +-optimized, so it is usually the best function to use to read a single +-character. ++This is just like @code{fgetc}, except that it may be implemented as ++a macro and may evaluate the @var{stream} argument more than once. ++Therefore, @var{stream} should never be an expression with side-effects. + @end deftypefun + + @deftypefun wint_t getwc (FILE *@var{stream}) + @standards{ISO, wchar.h} + @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} +-This is just like @code{fgetwc}, except that it is permissible for it to +-be implemented as a macro that evaluates the @var{stream} argument more +-than once. @code{getwc} can be highly optimized, so it is usually the +-best function to use to read a single wide character. ++This is just like @code{fgetwc}, except that it may be implemented as ++a macro and may evaluate the @var{stream} argument more than once. ++Therefore, @var{stream} should never be an expression with side-effects. + @end deftypefun + + @deftypefun int getc_unlocked (FILE *@var{stream}) diff --git a/SOURCES/glibc-RHEL-46979-1.patch b/SOURCES/glibc-RHEL-46979-1.patch new file mode 100644 index 0000000..2430880 --- /dev/null +++ b/SOURCES/glibc-RHEL-46979-1.patch @@ -0,0 +1,83 @@ +From a65ff76c9a1811dd2396ab45563f645579c0e687 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 27 Oct 2022 11:36:44 +0200 +Subject: ld.so: Export tls_init_tp_called as __rtld_tls_init_tp_called + +This allows the rest of dynamic loader to check whether the TCB +has been set up (and THREAD_GETMEM and THREAD_SETMEM will work). + +Reviewed-by: Siddhesh Poyarekar + +Conflicts: + Regenerated for context changes. + +diff -rup a/elf/rtld.c b/elf/rtld.c +--- a/elf/rtld.c 2024-08-22 17:57:02.000830481 -0400 ++++ b/elf/rtld.c 2024-08-22 17:59:30.666562835 -0400 +@@ -740,7 +740,7 @@ match_version (const char *string, struc + return 0; + } + +-static bool tls_init_tp_called; ++bool __rtld_tls_init_tp_called; + + static void * + init_tls (size_t naudit) +@@ -812,7 +812,7 @@ cannot allocate TLS data structures for + if (__glibc_unlikely (lossage != NULL)) + _dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage); + __tls_init_tp (); +- tls_init_tp_called = true; ++ __rtld_tls_init_tp_called = true; + + return tcbp; + } +@@ -2057,7 +2057,7 @@ dl_main (const ElfW(Phdr) *phdr, + an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever + used. Trying to do it lazily is too hairy to try when there could be + multiple threads (from a non-TLS-using libpthread). */ +- bool was_tls_init_tp_called = tls_init_tp_called; ++ bool was_tls_init_tp_called = __rtld_tls_init_tp_called; + if (tcbp == NULL) + tcbp = init_tls (0); + +@@ -2411,7 +2411,7 @@ dl_main (const ElfW(Phdr) *phdr, + _dl_protect_relro (l); + + /* Add object to slot information data if necessasy. */ +- if (l->l_tls_blocksize != 0 && tls_init_tp_called) ++ if (l->l_tls_blocksize != 0 && __rtld_tls_init_tp_called) + _dl_add_to_slotinfo (l, true); + } + } +@@ -2462,7 +2462,7 @@ dl_main (const ElfW(Phdr) *phdr, + consider_profiling); + + /* Add object to slot information data if necessasy. */ +- if (l->l_tls_blocksize != 0 && tls_init_tp_called) ++ if (l->l_tls_blocksize != 0 && __rtld_tls_init_tp_called) + _dl_add_to_slotinfo (l, true); + } + rtld_timer_stop (&relocate_time, start); +@@ -2488,7 +2488,7 @@ dl_main (const ElfW(Phdr) *phdr, + _dl_allocate_tls_init (tcbp, true); + + /* And finally install it for the main thread. */ +- if (! tls_init_tp_called) ++ if (! __rtld_tls_init_tp_called) + { + const char *lossage = TLS_INIT_TP (tcbp); + if (__glibc_unlikely (lossage != NULL)) +diff -rup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +--- a/sysdeps/generic/ldsodefs.h 2024-08-22 17:57:02.011830906 -0400 ++++ b/sysdeps/generic/ldsodefs.h 2024-08-22 17:58:10.900487160 -0400 +@@ -1262,6 +1262,9 @@ extern void *_dl_allocate_tls_storage (v + extern void *_dl_allocate_tls_init (void *result, bool main_thread); + rtld_hidden_proto (_dl_allocate_tls_init) + ++/* True if the TCB has been set up. */ ++extern bool __rtld_tls_init_tp_called attribute_hidden; ++ + /* Deallocate memory allocated with _dl_allocate_tls. */ + extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb); + rtld_hidden_proto (_dl_deallocate_tls) diff --git a/SOURCES/glibc-RHEL-46979-2.patch b/SOURCES/glibc-RHEL-46979-2.patch new file mode 100644 index 0000000..0671c4f --- /dev/null +++ b/SOURCES/glibc-RHEL-46979-2.patch @@ -0,0 +1,1030 @@ +From ee1ada1bdb8074de6e1bdc956ab19aef7b6a7872 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 3 Nov 2022 09:39:31 +0100 +Subject: elf: Rework exception handling in the dynamic loader [BZ #25486] + +The old exception handling implementation used function interposition +to replace the dynamic loader implementation (no TLS support) with the +libc implementation (TLS support). This results in problems if the +link order between the dynamic loader and libc is reversed (bug 25486). + +The new implementation moves the entire implementation of the +exception handling functions back into the dynamic loader, using +THREAD_GETMEM and THREAD_SETMEM for thread-local data support. +These depends on Hurd support for these macros, added in commit +b65a82e4e757c1e6cb7073916 ("hurd: Add THREAD_GET/SETMEM/_NC"). + +One small obstacle is that the exception handling facilities are used +before the TCB has been set up, so a check is needed if the TCB is +available. If not, a regular global variable is used to store the +exception handling information. + +Also rename dl-error.c to dl-catch.c, to avoid confusion with the +dlerror function. + +Reviewed-by: Siddhesh Poyarekar + +Conflicts + Rebased due to context changes + +diff -rupN a/elf/Makefile b/elf/Makefile +--- a/elf/Makefile 2024-08-29 11:28:38.488322915 -0400 ++++ b/elf/Makefile 2024-08-29 11:29:16.773809945 -0400 +@@ -34,7 +34,6 @@ routines = \ + dl-addr \ + dl-addr-obj \ + dl-early_allocate \ +- dl-error \ + dl-iteratephdr \ + dl-libc \ + dl-origin \ +@@ -52,6 +51,7 @@ routines = \ + # profiled libraries. + dl-routines = \ + dl-call-libc-early-init \ ++ dl-catch \ + dl-close \ + dl-debug \ + dl-deps \ +@@ -127,7 +127,6 @@ rtld-routines = \ + dl-diagnostics-cpu \ + dl-diagnostics-kernel \ + dl-environ \ +- dl-error-minimal \ + dl-hwcaps \ + dl-hwcaps-subdirs \ + dl-hwcaps_split \ +diff -rupN a/elf/Versions b/elf/Versions +--- a/elf/Versions 2024-08-29 11:28:36.214234588 -0400 ++++ b/elf/Versions 2024-08-29 11:29:16.778810139 -0400 +@@ -23,10 +23,6 @@ libc { + GLIBC_PRIVATE { + # functions used in other libraries + __libc_early_init; +- +- # Internal error handling support. Interposes the functions in ld.so. +- _dl_signal_exception; _dl_catch_exception; +- _dl_signal_error; _dl_catch_error; + } + } + +@@ -69,10 +65,8 @@ ld { + + # Internal error handling support. + _dl_exception_create; _dl_exception_create_format; _dl_exception_free; +- +- # Internal error handling support. Interposed by libc.so. + _dl_signal_exception; _dl_catch_exception; +- _dl_signal_error; _dl_catch_error; ++ _dl_signal_error; + + # Set value of a tunable. + __tunable_get_val; +diff -rupN a/elf/dl-catch.c b/elf/dl-catch.c +--- a/elf/dl-catch.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/elf/dl-catch.c 2024-08-29 11:29:16.782810295 -0400 +@@ -0,0 +1,261 @@ ++/* Exception handling in the dynamic linker. ++ Copyright (C) 1995-2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* This structure communicates state between _dl_catch_error and ++ _dl_signal_error. */ ++struct rtld_catch ++ { ++ struct dl_exception *exception; /* The exception data is stored there. */ ++ volatile int *errcode; /* Return value of _dl_signal_error. */ ++ jmp_buf env; /* longjmp here on error. */ ++ }; ++ ++/* Multiple threads at once can use the `_dl_catch_error' function. ++ The calls can come from `_dl_map_object_deps', `_dlerror_run', or ++ from any of the libc functionality which loads dynamic objects ++ (NSS, iconv). Therefore we have to be prepared to save the state ++ in thread-local memory. We use THREAD_GETMEM and THREAD_SETMEM ++ instead of ELF TLS because ELF TLS is not available in the dynamic ++ loader. Additionally, the exception handling mechanism must be ++ usable before the TCB has been set up, which is why ++ rtld_catch_notls is used if !__rtld_tls_init_tp_called. This is ++ not needed for static builds, where initialization completes before ++ static dlopen etc. can be called. */ ++ ++#if IS_IN (rtld) ++static struct rtld_catch *rtld_catch_notls; ++#endif ++ ++static struct rtld_catch * ++get_catch (void) ++{ ++#if IS_IN (rtld) ++ if (!__rtld_tls_init_tp_called) ++ return rtld_catch_notls; ++ else ++#endif ++ return THREAD_GETMEM (THREAD_SELF, rtld_catch); ++} ++ ++static void ++set_catch (struct rtld_catch *catch) ++{ ++#if IS_IN (rtld) ++ if (!__rtld_tls_init_tp_called) ++ rtld_catch_notls = catch; ++ else ++#endif ++ THREAD_SETMEM (THREAD_SELF, rtld_catch, catch); ++} ++ ++/* Lossage while resolving the program's own symbols is always fatal. */ ++static void ++__attribute__ ((noreturn)) ++fatal_error (int errcode, const char *objname, const char *occasion, ++ const char *errstring) ++{ ++ char buffer[1024]; ++ _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n", ++ RTLD_PROGNAME, ++ occasion ?: N_("error while loading shared libraries"), ++ objname, *objname ? ": " : "", ++ errstring, errcode ? ": " : "", ++ (errcode ++ ? __strerror_r (errcode, buffer, sizeof buffer) ++ : "")); ++} ++ ++void ++_dl_signal_exception (int errcode, struct dl_exception *exception, ++ const char *occasion) ++{ ++ struct rtld_catch *lcatch = get_catch (); ++ if (lcatch != NULL) ++ { ++ *lcatch->exception = *exception; ++ *lcatch->errcode = errcode; ++ ++ /* We do not restore the signal mask because none was saved. */ ++ __longjmp (lcatch->env[0].__jmpbuf, 1); ++ } ++ else ++ fatal_error (errcode, exception->objname, occasion, exception->errstring); ++} ++rtld_hidden_def (_dl_signal_exception) ++ ++void ++_dl_signal_error (int errcode, const char *objname, const char *occation, ++ const char *errstring) ++{ ++ struct rtld_catch *lcatch = get_catch (); ++ ++ if (! errstring) ++ errstring = N_("DYNAMIC LINKER BUG!!!"); ++ ++ if (lcatch != NULL) ++ { ++ _dl_exception_create (lcatch->exception, objname, errstring); ++ *lcatch->errcode = errcode; ++ ++ /* We do not restore the signal mask because none was saved. */ ++ __longjmp (lcatch->env[0].__jmpbuf, 1); ++ } ++ else ++ fatal_error (errcode, objname, occation, errstring); ++} ++rtld_hidden_def (_dl_signal_error) ++ ++#if IS_IN (rtld) ++/* This points to a function which is called when a continuable error is ++ received. Unlike the handling of `catch' this function may return. ++ The arguments will be the `errstring' and `objname'. ++ ++ Since this functionality is not used in normal programs (only in ld.so) ++ we do not care about multi-threaded programs here. We keep this as a ++ global variable. */ ++static receiver_fct receiver; ++ ++void ++_dl_signal_cexception (int errcode, struct dl_exception *exception, ++ const char *occasion) ++{ ++ if (__builtin_expect (GLRO(dl_debug_mask) ++ & ~(DL_DEBUG_STATISTICS), 0)) ++ _dl_debug_printf ("%s: error: %s: %s (%s)\n", ++ exception->objname, occasion, ++ exception->errstring, receiver ? "continued" : "fatal"); ++ ++ if (receiver) ++ { ++ /* We are inside _dl_receive_error. Call the user supplied ++ handler and resume the work. The receiver will still be ++ installed. */ ++ (*receiver) (errcode, exception->objname, exception->errstring); ++ } ++ else ++ _dl_signal_exception (errcode, exception, occasion); ++} ++ ++void ++_dl_signal_cerror (int errcode, const char *objname, const char *occation, ++ const char *errstring) ++{ ++ if (__builtin_expect (GLRO(dl_debug_mask) ++ & ~(DL_DEBUG_STATISTICS), 0)) ++ _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation, ++ errstring, receiver ? "continued" : "fatal"); ++ ++ if (receiver) ++ { ++ /* We are inside _dl_receive_error. Call the user supplied ++ handler and resume the work. The receiver will still be ++ installed. */ ++ (*receiver) (errcode, objname, errstring); ++ } ++ else ++ _dl_signal_error (errcode, objname, occation, errstring); ++} ++ ++void ++_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args) ++{ ++ struct rtld_catch *old_catch = get_catch (); ++ receiver_fct old_receiver = receiver; ++ ++ /* Set the new values. */ ++ set_catch (NULL); ++ receiver = fct; ++ ++ (*operate) (args); ++ ++ set_catch (old_catch); ++ receiver = old_receiver; ++} ++#endif ++ ++int ++_dl_catch_exception (struct dl_exception *exception, ++ void (*operate) (void *), void *args) ++{ ++ /* If exception is NULL, temporarily disable exception handling. ++ Exceptions during operate (args) are fatal. */ ++ if (exception == NULL) ++ { ++ struct rtld_catch *old_catch = get_catch (); ++ set_catch (NULL); ++ operate (args); ++ /* If we get here, the operation was successful. */ ++ set_catch (old_catch); ++ return 0; ++ } ++ ++ /* We need not handle `receiver' since setting a `catch' is handled ++ before it. */ ++ ++ /* Only this needs to be marked volatile, because it is the only local ++ variable that gets changed between the setjmp invocation and the ++ longjmp call. All others are just set here (before setjmp) and read ++ in _dl_signal_error (before longjmp). */ ++ volatile int errcode; ++ ++ struct rtld_catch c; ++ /* Don't use an initializer since we don't need to clear C.env. */ ++ c.exception = exception; ++ c.errcode = &errcode; ++ ++ struct rtld_catch *old = get_catch (); ++ set_catch (&c); ++ ++ /* Do not save the signal mask. */ ++ if (__builtin_expect (__sigsetjmp (c.env, 0), 0) == 0) ++ { ++ (*operate) (args); ++ set_catch (old); ++ *exception = (struct dl_exception) { NULL }; ++ return 0; ++ } ++ ++ /* We get here only if we longjmp'd out of OPERATE. ++ _dl_signal_exception has already stored values into ++ *EXCEPTION. */ ++ set_catch (old); ++ return errcode; ++} ++rtld_hidden_def (_dl_catch_exception) ++ ++int ++_dl_catch_error (const char **objname, const char **errstring, ++ bool *mallocedp, void (*operate) (void *), void *args) ++{ ++ struct dl_exception exception; ++ int errorcode = _dl_catch_exception (&exception, operate, args); ++ *objname = exception.objname; ++ *errstring = exception.errstring; ++ *mallocedp = exception.message_buffer == exception.errstring; ++ return errorcode; ++} +diff -rupN a/elf/dl-error-minimal.c b/elf/dl-error-minimal.c +--- a/elf/dl-error-minimal.c 2021-08-01 21:33:43.000000000 -0400 ++++ b/elf/dl-error-minimal.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,23 +0,0 @@ +-/* Error handling for runtime dynamic linker, minimal version. +- Copyright (C) 1995-2021 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-/* This version does lives in ld.so, does not use thread-local data +- and supports _dl_signal_cerror and _dl_receive_error. */ +- +-#define DL_ERROR_BOOTSTRAP 1 +-#include "dl-error-skeleton.c" +diff -rupN a/elf/dl-error-skeleton.c b/elf/dl-error-skeleton.c +--- a/elf/dl-error-skeleton.c 2021-08-01 21:33:43.000000000 -0400 ++++ b/elf/dl-error-skeleton.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,263 +0,0 @@ +-/* Template for error handling for runtime dynamic linker. +- Copyright (C) 1995-2021 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-/* The following macro needs to be defined before including this +- skeleton file: +- +- DL_ERROR_BOOTSTRAP +- +- If 1, do not use TLS and implement _dl_signal_cerror and +- _dl_receive_error. If 0, TLS is used, and the variants with +- error callbacks are not provided. */ +- +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* This structure communicates state between _dl_catch_error and +- _dl_signal_error. */ +-struct catch +- { +- struct dl_exception *exception; /* The exception data is stored there. */ +- volatile int *errcode; /* Return value of _dl_signal_error. */ +- jmp_buf env; /* longjmp here on error. */ +- }; +- +-/* Multiple threads at once can use the `_dl_catch_error' function. The +- calls can come from `_dl_map_object_deps', `_dlerror_run', or from +- any of the libc functionality which loads dynamic objects (NSS, iconv). +- Therefore we have to be prepared to save the state in thread-local +- memory. */ +-#if !DL_ERROR_BOOTSTRAP +-static __thread struct catch *catch_hook attribute_tls_model_ie; +-#else +-/* The version of this code in ld.so cannot use thread-local variables +- and is used during bootstrap only. */ +-static struct catch *catch_hook; +-#endif +- +-#if DL_ERROR_BOOTSTRAP +-/* This points to a function which is called when an continuable error is +- received. Unlike the handling of `catch' this function may return. +- The arguments will be the `errstring' and `objname'. +- +- Since this functionality is not used in normal programs (only in ld.so) +- we do not care about multi-threaded programs here. We keep this as a +- global variable. */ +-static receiver_fct receiver; +-#endif /* DL_ERROR_BOOTSTRAP */ +- +-/* Lossage while resolving the program's own symbols is always fatal. */ +-static void +-__attribute__ ((noreturn)) +-fatal_error (int errcode, const char *objname, const char *occasion, +- const char *errstring) +-{ +- char buffer[1024]; +- _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n", +- RTLD_PROGNAME, +- occasion ?: N_("error while loading shared libraries"), +- objname, *objname ? ": " : "", +- errstring, errcode ? ": " : "", +- (errcode +- ? __strerror_r (errcode, buffer, sizeof buffer) +- : "")); +-} +- +-void +-_dl_signal_exception (int errcode, struct dl_exception *exception, +- const char *occasion) +-{ +- struct catch *lcatch = catch_hook; +- if (lcatch != NULL) +- { +- *lcatch->exception = *exception; +- *lcatch->errcode = errcode; +- +- /* We do not restore the signal mask because none was saved. */ +- __longjmp (lcatch->env[0].__jmpbuf, 1); +- } +- else +- fatal_error (errcode, exception->objname, occasion, exception->errstring); +-} +-libc_hidden_def (_dl_signal_exception) +- +-void +-_dl_signal_error (int errcode, const char *objname, const char *occation, +- const char *errstring) +-{ +- struct catch *lcatch = catch_hook; +- +- if (! errstring) +- errstring = N_("DYNAMIC LINKER BUG!!!"); +- +- if (lcatch != NULL) +- { +- _dl_exception_create (lcatch->exception, objname, errstring); +- *lcatch->errcode = errcode; +- +- /* We do not restore the signal mask because none was saved. */ +- __longjmp (lcatch->env[0].__jmpbuf, 1); +- } +- else +- fatal_error (errcode, objname, occation, errstring); +-} +-libc_hidden_def (_dl_signal_error) +- +- +-#if DL_ERROR_BOOTSTRAP +-void +-_dl_signal_cexception (int errcode, struct dl_exception *exception, +- const char *occasion) +-{ +- if (__builtin_expect (GLRO(dl_debug_mask) +- & ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0)) +- _dl_debug_printf ("%s: error: %s: %s (%s)\n", +- exception->objname, occasion, +- exception->errstring, receiver ? "continued" : "fatal"); +- +- if (receiver) +- { +- /* We are inside _dl_receive_error. Call the user supplied +- handler and resume the work. The receiver will still be +- installed. */ +- (*receiver) (errcode, exception->objname, exception->errstring); +- } +- else +- _dl_signal_exception (errcode, exception, occasion); +-} +- +-void +-_dl_signal_cerror (int errcode, const char *objname, const char *occation, +- const char *errstring) +-{ +- if (__builtin_expect (GLRO(dl_debug_mask) +- & ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0)) +- _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation, +- errstring, receiver ? "continued" : "fatal"); +- +- if (receiver) +- { +- /* We are inside _dl_receive_error. Call the user supplied +- handler and resume the work. The receiver will still be +- installed. */ +- (*receiver) (errcode, objname, errstring); +- } +- else +- _dl_signal_error (errcode, objname, occation, errstring); +-} +-#endif /* DL_ERROR_BOOTSTRAP */ +- +-int +-_dl_catch_exception (struct dl_exception *exception, +- void (*operate) (void *), void *args) +-{ +- /* If exception is NULL, temporarily disable exception handling. +- Exceptions during operate (args) are fatal. */ +- if (exception == NULL) +- { +- struct catch *const old = catch_hook; +- catch_hook = NULL; +- operate (args); +- /* If we get here, the operation was successful. */ +- catch_hook = old; +- return 0; +- } +- +- /* We need not handle `receiver' since setting a `catch' is handled +- before it. */ +- +- /* Only this needs to be marked volatile, because it is the only local +- variable that gets changed between the setjmp invocation and the +- longjmp call. All others are just set here (before setjmp) and read +- in _dl_signal_error (before longjmp). */ +- volatile int errcode; +- +- struct catch c; +- /* Don't use an initializer since we don't need to clear C.env. */ +- c.exception = exception; +- c.errcode = &errcode; +- +- struct catch *const old = catch_hook; +- catch_hook = &c; +- +- /* Do not save the signal mask. */ +- if (__builtin_expect (__sigsetjmp (c.env, 0), 0) == 0) +- { +- (*operate) (args); +- catch_hook = old; +- *exception = (struct dl_exception) { NULL }; +- return 0; +- } +- +- /* We get here only if we longjmp'd out of OPERATE. +- _dl_signal_exception has already stored values into +- *EXCEPTION. */ +- catch_hook = old; +- return errcode; +-} +-libc_hidden_def (_dl_catch_exception) +- +-int +-_dl_catch_error (const char **objname, const char **errstring, +- bool *mallocedp, void (*operate) (void *), void *args) +-{ +- struct dl_exception exception; +- int errorcode = _dl_catch_exception (&exception, operate, args); +- *objname = exception.objname; +- *errstring = exception.errstring; +- *mallocedp = exception.message_buffer == exception.errstring; +- return errorcode; +-} +-libc_hidden_def (_dl_catch_error) +- +-#if DL_ERROR_BOOTSTRAP +-void +-_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args) +-{ +- struct catch *old_catch = catch_hook; +- receiver_fct old_receiver = receiver; +- +- /* Set the new values. */ +- catch_hook = NULL; +- receiver = fct; +- +- (*operate) (args); +- +- catch_hook = old_catch; +- receiver = old_receiver; +-} +- +-/* Forwarder used for initializing GLRO (_dl_catch_error). */ +-int +-_rtld_catch_error (const char **objname, const char **errstring, +- bool *mallocedp, void (*operate) (void *), +- void *args) +-{ +- /* The reference to _dl_catch_error will eventually be relocated to +- point to the implementation in libc.so. */ +- return _dl_catch_error (objname, errstring, mallocedp, operate, args); +-} +- +-#endif /* DL_ERROR_BOOTSTRAP */ +diff -rupN a/elf/dl-error.c b/elf/dl-error.c +--- a/elf/dl-error.c 2021-08-01 21:33:43.000000000 -0400 ++++ b/elf/dl-error.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,27 +0,0 @@ +-/* Error handling for runtime dynamic linker, full version. +- Copyright (C) 1995-2021 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-/* This implementation lives in libc.so because it uses thread-local +- data, which is not available in ld.so. It interposes the version +- in dl-error-minimal.c after ld.so bootstrap. +- +- The signal/catch mechanism is used by the audit framework, which +- means that even in ld.so, not all errors are fatal. */ +- +-#define DL_ERROR_BOOTSTRAP 0 +-#include "dl-error-skeleton.c" +diff -rupN a/elf/rtld.c b/elf/rtld.c +--- a/elf/rtld.c 2024-08-29 11:28:38.569326061 -0400 ++++ b/elf/rtld.c 2024-08-29 11:29:16.798810916 -0400 +@@ -377,7 +377,7 @@ struct rtld_global_ro _rtld_global_ro at + ._dl_lookup_symbol_x = _dl_lookup_symbol_x, + ._dl_open = _dl_open, + ._dl_close = _dl_close, +- ._dl_catch_error = _rtld_catch_error, ++ ._dl_catch_error = _dl_catch_error, + ._dl_error_free = _dl_error_free, + ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft, + #ifdef HAVE_DL_DISCOVER_OSVERSION +diff -rupN a/nptl/descr.h b/nptl/descr.h +--- a/nptl/descr.h 2024-08-29 11:28:37.858298444 -0400 ++++ b/nptl/descr.h 2024-08-29 11:29:16.801811033 -0400 +@@ -396,6 +396,9 @@ struct pthread + masked.) */ + sigset_t sigmask; + ++ /* Used by the exception handling implementation in the dynamic loader. */ ++ struct rtld_catch *rtld_catch; ++ + /* Indicates whether is a C11 thread created by thrd_creat. */ + bool c11; + +diff -rupN a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +--- a/sysdeps/generic/ldsodefs.h 2024-08-29 11:28:38.571326139 -0400 ++++ b/sysdeps/generic/ldsodefs.h 2024-08-29 11:29:16.805811188 -0400 +@@ -897,13 +897,13 @@ rtld_hidden_proto (_dl_exception_free) + void _dl_signal_exception (int errcode, struct dl_exception *, + const char *occasion) + __attribute__ ((__noreturn__)); +-libc_hidden_proto (_dl_signal_exception) ++rtld_hidden_proto (_dl_signal_exception) + + /* Like _dl_signal_exception, but creates the exception first. */ + extern void _dl_signal_error (int errcode, const char *object, + const char *occasion, const char *errstring) + __attribute__ ((__noreturn__)); +-libc_hidden_proto (_dl_signal_error) ++rtld_hidden_proto (_dl_signal_error) + + /* Like _dl_signal_exception, but may return when called in the + context of _dl_receive_error. This is only used during ld.so +@@ -955,11 +955,7 @@ extern void _dl_receive_error (receiver_ + the returned string is allocated using the libc's malloc. */ + extern int _dl_catch_error (const char **objname, const char **errstring, + bool *mallocedp, void (*operate) (void *), +- void *args); +-libc_hidden_proto (_dl_catch_error) +- +-/* Used for initializing GLRO (_dl_catch_error). */ +-extern __typeof__ (_dl_catch_error) _rtld_catch_error attribute_hidden; ++ void *args) attribute_hidden; + + /* Call OPERATE (ARGS). If no error occurs, set *EXCEPTION to zero. + Otherwise, store a copy of the raised exception in *EXCEPTION, +@@ -968,7 +964,7 @@ extern __typeof__ (_dl_catch_error) _rtl + disabled (so that exceptions are fatal). */ + int _dl_catch_exception (struct dl_exception *exception, + void (*operate) (void *), void *args); +-libc_hidden_proto (_dl_catch_exception) ++rtld_hidden_proto (_dl_catch_exception) + + /* Open the shared object NAME and map in its segments. + LOADER's DT_RPATH is used in searching for NAME. +diff -rupN a/sysdeps/generic/localplt.data b/sysdeps/generic/localplt.data +--- a/sysdeps/generic/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/generic/localplt.data 2024-08-29 11:29:16.806811227 -0400 +@@ -6,8 +6,3 @@ libc.so: free + libc.so: malloc + libc.so: realloc + libm.so: matherr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/mach/hurd/i386/localplt.data b/sysdeps/mach/hurd/i386/localplt.data +--- a/sysdeps/mach/hurd/i386/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/mach/hurd/i386/localplt.data 2024-08-29 11:29:16.808811305 -0400 +@@ -8,11 +8,6 @@ libc.so: free + REL R_386_GLOB_DAT + libc.so: malloc + REL R_386_GLOB_DAT + libc.so: realloc + REL R_386_GLOB_DAT + libm.so: matherr + REL R_386_GLOB_DAT +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error + REL R_386_GLOB_DAT +-ld.so: _dl_catch_error + REL R_386_GLOB_DAT +-ld.so: _dl_signal_exception + REL R_386_GLOB_DAT +-ld.so: _dl_catch_exception + REL R_386_GLOB_DAT + # The dynamic linker has its own versions of basic functions for initial loading + # of shared libraries. These need to be overriden by libc once loaded. + ld.so: __open ? +diff -rupN a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h +--- a/sysdeps/mach/hurd/i386/tls.h 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/mach/hurd/i386/tls.h 2024-08-29 11:29:16.810811382 -0400 +@@ -48,6 +48,9 @@ typedef struct + compatible with the i386 Linux version. */ + mach_port_t reply_port; /* This thread's reply port. */ + struct hurd_sigstate *_hurd_sigstate; ++ ++ /* Used by the exception handling implementation in the dynamic loader. */ ++ struct rtld_catch *rtld_catch; + } tcbhead_t; + #endif + +diff -rupN a/sysdeps/unix/sysv/linux/aarch64/localplt.data b/sysdeps/unix/sysv/linux/aarch64/localplt.data +--- a/sysdeps/unix/sysv/linux/aarch64/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/aarch64/localplt.data 2024-08-29 11:29:16.810811382 -0400 +@@ -11,8 +11,3 @@ libm.so: matherr + libc.so: __getauxval ? + # The dynamic loader needs __tls_get_addr for TLS. + ld.so: __tls_get_addr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/alpha/localplt.data b/sysdeps/unix/sysv/linux/alpha/localplt.data +--- a/sysdeps/unix/sysv/linux/alpha/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/alpha/localplt.data 2024-08-29 11:29:16.810811382 -0400 +@@ -25,8 +25,3 @@ libm.so: matherr + RELA R_ALPHA_GLOB_DAT + libm.so: __atan2 + # The dynamic loader needs __tls_get_addr for TLS. + ld.so: __tls_get_addr ? +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error + RELA R_ALPHA_GLOB_DAT +-ld.so: _dl_catch_error + RELA R_ALPHA_GLOB_DAT +-ld.so: _dl_signal_exception + RELA R_ALPHA_GLOB_DAT +-ld.so: _dl_catch_exception + RELA R_ALPHA_GLOB_DAT +diff -rupN a/sysdeps/unix/sysv/linux/arc/localplt.data b/sysdeps/unix/sysv/linux/arc/localplt.data +--- a/sysdeps/unix/sysv/linux/arc/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/arc/localplt.data 2024-08-29 11:29:16.814811538 -0400 +@@ -4,8 +4,3 @@ libc.so: calloc + libc.so: free + # At -Os, a struct assignment in libgcc-static pulls this in + libc.so: memcpy ? +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/arm/localplt.data b/sysdeps/unix/sysv/linux/arm/localplt.data +--- a/sysdeps/unix/sysv/linux/arm/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/arm/localplt.data 2024-08-29 11:29:16.814811538 -0400 +@@ -6,8 +6,3 @@ libc.so: realloc + libm.so: matherr + # The dynamic loader needs __tls_get_addr for TLS. + ld.so: __tls_get_addr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/csky/localplt.data b/sysdeps/unix/sysv/linux/csky/localplt.data +--- a/sysdeps/unix/sysv/linux/csky/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/csky/localplt.data 2024-08-29 11:29:16.814811538 -0400 +@@ -5,8 +5,3 @@ libc.so: calloc + libc.so: free + libc.so: malloc + libc.so: realloc +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/hppa/localplt.data b/sysdeps/unix/sysv/linux/hppa/localplt.data +--- a/sysdeps/unix/sysv/linux/hppa/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/hppa/localplt.data 2024-08-29 11:29:16.814811538 -0400 +@@ -9,8 +9,3 @@ libc.so: __sigsetjmp + libc.so: _IO_funlockfile + libc.so: __errno_location + libm.so: matherr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/i386/localplt.data b/sysdeps/unix/sysv/linux/i386/localplt.data +--- a/sysdeps/unix/sysv/linux/i386/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/i386/localplt.data 2024-08-29 11:29:16.816811615 -0400 +@@ -6,8 +6,3 @@ libc.so: free + REL R_386_GLOB_DAT + libc.so: malloc + REL R_386_GLOB_DAT + libc.so: realloc + REL R_386_GLOB_DAT + libm.so: matherr + REL R_386_GLOB_DAT +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error + REL R_386_GLOB_DAT +-ld.so: _dl_catch_error + REL R_386_GLOB_DAT +-ld.so: _dl_signal_exception + REL R_386_GLOB_DAT +-ld.so: _dl_catch_exception + REL R_386_GLOB_DAT +diff -rupN a/sysdeps/unix/sysv/linux/ia64/localplt.data b/sysdeps/unix/sysv/linux/ia64/localplt.data +--- a/sysdeps/unix/sysv/linux/ia64/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/ia64/localplt.data 2024-08-29 11:29:16.816811615 -0400 +@@ -5,8 +5,3 @@ libc.so: realloc + libm.so: matherr + libm.so: matherrf + libm.so: matherrl +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data b/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data +--- a/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data 2024-08-29 11:29:16.819811732 -0400 +@@ -4,8 +4,3 @@ libc.so: free + libc.so: malloc + libc.so: realloc + libm.so: matherr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data b/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data +--- a/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data 2024-08-29 11:29:16.820811771 -0400 +@@ -5,8 +5,3 @@ libc.so: free + libc.so: malloc + libc.so: realloc + libm.so: matherr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/microblaze/localplt.data b/sysdeps/unix/sysv/linux/microblaze/localplt.data +--- a/sysdeps/unix/sysv/linux/microblaze/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/microblaze/localplt.data 2024-08-29 11:29:16.822811848 -0400 +@@ -6,8 +6,3 @@ libc.so: realloc + libm.so: matherr + # The dynamic loader needs __tls_get_addr for TLS. + ld.so: __tls_get_addr ? +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/nios2/localplt.data b/sysdeps/unix/sysv/linux/nios2/localplt.data +--- a/sysdeps/unix/sysv/linux/nios2/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/nios2/localplt.data 2024-08-29 11:29:16.825811965 -0400 +@@ -27,8 +27,3 @@ libc.so: __eqdf2 + libc.so: __extendsfdf2 + libc.so: __floatundidf ? + libm.so: matherr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data 2024-08-29 11:29:16.829812120 -0400 +@@ -4,8 +4,3 @@ libc.so: free + libc.so: malloc + libc.so: realloc + libm.so: matherr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data 2024-08-29 11:29:16.831812198 -0400 +@@ -35,8 +35,3 @@ libc.so: realloc + libm.so: copysignl ? + libm.so: fabsl + libm.so: matherr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data 2024-08-29 11:29:16.833812276 -0400 +@@ -3,8 +3,3 @@ libc.so: free + libc.so: malloc + libc.so: realloc + libm.so: matherr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/riscv/localplt.data b/sysdeps/unix/sysv/linux/riscv/localplt.data +--- a/sysdeps/unix/sysv/linux/riscv/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/riscv/localplt.data 2024-08-29 11:29:16.835812353 -0400 +@@ -6,8 +6,3 @@ libc.so: free + libc.so: malloc + libc.so: memset ? + libc.so: realloc +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/s390/localplt.data b/sysdeps/unix/sysv/linux/s390/localplt.data +--- a/sysdeps/unix/sysv/linux/s390/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/s390/localplt.data 2024-08-29 11:29:16.837812431 -0400 +@@ -4,8 +4,3 @@ libc.so: free + libc.so: malloc + libc.so: realloc + libm.so: matherr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/sh/localplt.data b/sysdeps/unix/sysv/linux/sh/localplt.data +--- a/sysdeps/unix/sysv/linux/sh/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/sh/localplt.data 2024-08-29 11:29:16.838812470 -0400 +@@ -11,8 +11,3 @@ libc.so: __errno_location + libm.so: matherr + # Generated by the compiler because there is no trap insn pattern. + libc.so: abort ? +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data +--- a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data 2024-08-29 11:29:16.840812547 -0400 +@@ -18,8 +18,3 @@ libc.so: free + libc.so: malloc + libc.so: realloc + libm.so: matherr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data 2024-08-29 11:29:16.844812703 -0400 +@@ -17,8 +17,3 @@ libc.so: free + libc.so: malloc + libc.so: realloc + libm.so: matherr +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error +-ld.so: _dl_catch_error +-ld.so: _dl_signal_exception +-ld.so: _dl_catch_exception +diff -rupN a/sysdeps/x86_64/localplt.data b/sysdeps/x86_64/localplt.data +--- a/sysdeps/x86_64/localplt.data 2021-08-01 21:33:43.000000000 -0400 ++++ b/sysdeps/x86_64/localplt.data 2024-08-29 11:29:16.847812819 -0400 +@@ -8,8 +8,3 @@ libc.so: free + RELA R_X86_64_GLOB_DAT + libc.so: malloc + RELA R_X86_64_GLOB_DAT + libc.so: realloc + RELA R_X86_64_GLOB_DAT + libm.so: matherr + RELA R_X86_64_GLOB_DAT +-# The TLS-enabled version of these functions is interposed from libc.so. +-ld.so: _dl_signal_error + RELA R_X86_64_GLOB_DAT +-ld.so: _dl_catch_error + RELA R_X86_64_GLOB_DAT +-ld.so: _dl_signal_exception + RELA R_X86_64_GLOB_DAT +-ld.so: _dl_catch_exception + RELA R_X86_64_GLOB_DAT diff --git a/SOURCES/glibc-RHEL-46979-3.patch b/SOURCES/glibc-RHEL-46979-3.patch new file mode 100644 index 0000000..de8b390 --- /dev/null +++ b/SOURCES/glibc-RHEL-46979-3.patch @@ -0,0 +1,82 @@ +Extra changes needed for backport: + +* rename field "rtld_catch" to "rtld_catch_f" to avoid conflict + between "struct rtld-catch" and rtld_catch macro + +* move rtld_catch into one of the unused padding fields to preserve + ABI + +* Validate that the padding fields used don't overlap other fields. + +diff -rup a/elf/dl-catch.c b/elf/dl-catch.c +--- a/elf/dl-catch.c 2024-09-04 16:30:02.086402568 -0400 ++++ b/elf/dl-catch.c 2024-09-04 16:55:01.933440181 -0400 +@@ -59,7 +59,7 @@ get_catch (void) + return rtld_catch_notls; + else + #endif +- return THREAD_GETMEM (THREAD_SELF, rtld_catch); ++ return THREAD_GETMEM (THREAD_SELF, rtld_catch_f); + } + + static void +@@ -70,7 +70,7 @@ set_catch (struct rtld_catch *catch) + rtld_catch_notls = catch; + else + #endif +- THREAD_SETMEM (THREAD_SELF, rtld_catch, catch); ++ THREAD_SETMEM (THREAD_SELF, rtld_catch_f, catch); + } + + /* Lossage while resolving the program's own symbols is always fatal. */ +diff -rup a/nptl/descr.h b/nptl/descr.h +--- a/nptl/descr.h 2024-08-29 11:29:16.801811033 -0400 ++++ b/nptl/descr.h 2024-08-29 11:48:56.547644398 -0400 +@@ -164,6 +164,12 @@ struct pthread + void *__padding[24]; + }; + ++#ifdef __x86_64__ ++#define rtld_catch_f header.__padding[7] ++#else ++#define rtld_catch_f __padding[23] ++#endif ++ + /* This descriptor's link on the GL (dl_stack_used) or + GL (dl_stack_user) list. */ + list_t list; +@@ -396,9 +402,6 @@ struct pthread + masked.) */ + sigset_t sigmask; + +- /* Used by the exception handling implementation in the dynamic loader. */ +- struct rtld_catch *rtld_catch; +- + /* Indicates whether is a C11 thread created by thrd_creat. */ + bool c11; + +@@ -432,6 +435,12 @@ struct pthread + + sizeof ((struct pthread) {}.rseq_area)) + } __attribute ((aligned (TCB_ALIGNMENT))); + ++#ifdef __x86_64__ ++_Static_assert (sizeof ((*(struct pthread *)0).header) > sizeof ((*(struct pthread *)0).__padding), "rtld_catch"); ++#else ++_Static_assert (sizeof ((*(struct pthread *)0).header) < sizeof ((*(struct pthread *)0).__padding), "rtld_catch"); ++#endif ++ + static inline bool + cancel_enabled_and_canceled (int value) + { +diff -rup a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h +--- a/sysdeps/mach/hurd/i386/tls.h 2024-08-29 11:29:16.810811382 -0400 ++++ b/sysdeps/mach/hurd/i386/tls.h 2024-08-29 11:35:45.262899113 -0400 +@@ -50,7 +50,7 @@ typedef struct + struct hurd_sigstate *_hurd_sigstate; + + /* Used by the exception handling implementation in the dynamic loader. */ +- struct rtld_catch *rtld_catch; ++ struct rtld_catch *rtld_catch_f; + } tcbhead_t; + #endif + diff --git a/SOURCES/glibc-RHEL-46979-4.patch b/SOURCES/glibc-RHEL-46979-4.patch new file mode 100644 index 0000000..d9d6985 --- /dev/null +++ b/SOURCES/glibc-RHEL-46979-4.patch @@ -0,0 +1,79 @@ +New test case to verify padding usage. + +diff --git a/nptl/Makefile b/nptl/Makefile +index ff4d590f11c38277..9a56d34313d06444 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -319,6 +319,8 @@ tests-internal := tst-robustpi8 tst-rwlock19 tst-rwlock20 \ + tst-barrier5 tst-signal7 tst-mutex8 tst-mutex8-static \ + tst-mutexpi8 tst-mutexpi8-static \ + tst-setgetname \ ++ tst-nptl-padding \ ++ # tests-internal + + xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \ + tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 tst-setgroups \ +diff --git a/nptl/tst-nptl-padding.c b/nptl/tst-nptl-padding.c +new file mode 100644 +index 0000000000000000..5bb64f4a54335e36 +--- /dev/null ++++ b/nptl/tst-nptl-padding.c +@@ -0,0 +1,57 @@ ++/* Downstream-only test for verifying that fields that have been ++ relocated into struct pthread padding actually use the padding. ++ ++ At present, only rtld_catch (downstream: rtld_catch_f) has been ++ placed into padding. */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ struct pthread descr; ++ ++ /* Mark the entire descriptor as used. */ ++ memset (&descr, 0xff, sizeof (descr)); ++ ++ /* Mark the padding as unused. */ ++#ifdef __x86_64__ ++ /* Special case: Usable padding is in the header. */ ++ memset (&descr.header.__padding, 0, sizeof (descr.header.__padding)); ++#else ++ /* The padding should be directly adjacent to the first real ++ struct field. */ ++ TEST_COMPARE (sizeof (descr.__padding), offsetof (struct pthread, list)); ++ ++ /* Clear the unused tail of the padding. */ ++ { ++ char *base = (char *) &descr; ++ char *end_of_header = base + sizeof (descr.header); ++ char *end_of_padding = base + sizeof (descr.__padding); ++ memset (end_of_header, 0, end_of_padding - end_of_header); ++ } ++#endif ++ ++ /* These fields are not in padding and should remain marked as used. */ ++ TEST_COMPARE (descr.header.gscope_flag, -1); ++ TEST_COMPARE ((intptr_t) descr.list.next, -1); ++ TEST_COMPARE ((intptr_t) descr.list.prev, -1); ++ ++ /* But this field remains in padding. */ ++ TEST_COMPARE ((intptr_t) descr.rtld_catch_f, 0); ++ ++ /* Write to all padding-relocated fields below to show that they ++ have independent locations. */ ++ struct rtld_catch *rtld_catch_dummy = (void *) "rtld_catch_dummy"; ++ descr.rtld_catch_f = rtld_catch_dummy; ++ ++ TEST_VERIFY (descr.rtld_catch_f == rtld_catch_dummy); ++ ++ return 0; ++} ++ ++#include + diff --git a/SOURCES/glibc-RHEL-49489-1.patch b/SOURCES/glibc-RHEL-49489-1.patch new file mode 100644 index 0000000..3f2d6d8 --- /dev/null +++ b/SOURCES/glibc-RHEL-49489-1.patch @@ -0,0 +1,51 @@ +commit 9b7651410375ec8848a1944992d663d514db4ba7 +Author: Stefan Liebler +Date: Thu Jul 11 11:28:53 2024 +0200 + + s390x: Fix segfault in wcsncmp [BZ #31934] + + The z13/vector-optimized wcsncmp implementation segfaults if n=1 + and there is only one character (equal on both strings) before + the page end. Then it loads and compares one character and misses + to check n again. The following load fails. + + This patch removes the extra load and compare of the first character + and just start with the loop which uses vector-load-to-block-boundary. + This code-path also checks n. + + With this patch both tests are passing: + - the simplified one mentioned in the bugzilla 31934 + - the full one in Florian Weimer's patch: + "manual: Document a GNU extension for strncmp/wcsncmp" + (https://patchwork.sourceware.org/project/glibc/patch/874j9eml6y.fsf@oldenburg.str.redhat.com/): + On s390x-linux-gnu (z16), the new wcsncmp test fails due to bug 31934. + Reviewed-by: Carlos O'Donell + +diff --git a/sysdeps/s390/wcsncmp-vx.S b/sysdeps/s390/wcsncmp-vx.S +index bf6dfa6bc2..8b081567a2 100644 +--- a/sysdeps/s390/wcsncmp-vx.S ++++ b/sysdeps/s390/wcsncmp-vx.S +@@ -59,14 +59,7 @@ ENTRY(WCSNCMP_Z13) + sllg %r4,%r4,2 /* Convert character-count to byte-count. */ + locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */ + +- /* Check first character without vector load. */ +- lghi %r5,4 /* current_len = 4 bytes. */ +- /* Check s1/2[0]. */ +- lt %r0,0(%r2) +- l %r1,0(%r3) +- je .Lend_cmp_one_char +- crjne %r0,%r1,.Lend_cmp_one_char +- ++ lghi %r5,0 /* current_len = 0 bytes. */ + .Lloop: + vlbb %v17,0(%r5,%r3),6 /* Load s2 to block boundary. */ + vlbb %v16,0(%r5,%r2),6 /* Load s1 to block boundary. */ +@@ -167,7 +160,6 @@ ENTRY(WCSNCMP_Z13) + srl %r4,2 /* And convert it to character-index. */ + vlgvf %r0,%v16,0(%r4) /* Load character-values. */ + vlgvf %r1,%v17,0(%r4) +-.Lend_cmp_one_char: + cr %r0,%r1 + je .Lend_equal + lghi %r2,1 diff --git a/SOURCES/glibc-RHEL-49489-2.patch b/SOURCES/glibc-RHEL-49489-2.patch new file mode 100644 index 0000000..6802b1f --- /dev/null +++ b/SOURCES/glibc-RHEL-49489-2.patch @@ -0,0 +1,248 @@ +commit 54252394c25ddf0062e288d4a6ab7a885f8ae009 +Author: Florian Weimer +Date: Thu Jun 27 16:26:56 2024 +0200 + + Enhanced test coverage for strncmp, wcsncmp + + Add string/test-strncmp-nonarray and + wcsmbs/test-wcsncmp-nonarray. + + This is the test that uncovered bug 31934. Test run time + is more than one minute on a fairly current system, so turn + these into xtests that do not run automatically. + + Reviewed-by: Noah Goldstein + +diff -Nrup a/string/Makefile b/string/Makefile +--- a/string/Makefile 2024-09-03 11:42:30.396319962 -0400 ++++ b/string/Makefile 2024-09-03 11:52:17.707438963 -0400 +@@ -76,7 +76,10 @@ tests-unsupported += $(tests-translation + endif + + # This test allocates a lot of memory and can run for a long time. +-xtests = tst-strcoll-overflow ++xtests += tst-strcoll-overflow ++ ++# This test runs for a long time. ++xtests += test-strncmp-nonarray + + # This test needs libdl. + ifeq (yes,$(build-shared)) +diff -Nrup a/string/test-Xncmp-nonarray.c b/string/test-Xncmp-nonarray.c +--- a/string/test-Xncmp-nonarray.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/string/test-Xncmp-nonarray.c 2024-09-03 11:52:17.707438963 -0400 +@@ -0,0 +1,183 @@ ++/* Test non-array inputs to string comparison functions. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* This skeleton file is included from string/test-strncmp-nonarray.c and ++ wcsmbs/test-wcsncmp-nonarray.c to test that reading of the arrays stops ++ at the first null character. ++ ++ TEST_IDENTIFIER must be the test function identifier. TEST_NAME is ++ the same as a string. ++ ++ CHAR must be defined as the character type. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Much shorter than test-Xnlen-nonarray.c because of deeply nested loops. */ ++enum { buffer_length = 80 }; ++ ++/* The test buffer layout follows what is described test-Xnlen-nonarray.c, ++ except that there two buffers, left and right. The variables ++ a_count, zero_count, start_offset are all duplicated. */ ++ ++/* Return the maximum string length for a string that starts at ++ start_offset. */ ++static int ++string_length (int a_count, int start_offset) ++{ ++ if (start_offset == buffer_length || start_offset >= a_count) ++ return 0; ++ else ++ return a_count - start_offset; ++} ++ ++/* This is the valid maximum length argument computation for ++ strnlen/wcsnlen. See text-Xnlen-nonarray.c. */ ++static int ++maximum_length (int start_offset, int zero_count) ++{ ++ if (start_offset == buffer_length) ++ return 0; ++ else if (zero_count > 0) ++ /* Effectively unbounded, but we need to stop fairly low, ++ otherwise testing takes too long. */ ++ return buffer_length + 32; ++ else ++ return buffer_length - start_offset; ++} ++ ++typedef __typeof (TEST_IDENTIFIER) *proto_t; ++ ++#define TEST_MAIN ++#include "test-string.h" ++ ++IMPL (TEST_IDENTIFIER, 1) ++ ++static int ++test_main (void) ++{ ++ TEST_VERIFY_EXIT (sysconf (_SC_PAGESIZE) >= buffer_length); ++ test_init (); ++ ++ struct support_next_to_fault left_ntf ++ = support_next_to_fault_allocate (buffer_length * sizeof (CHAR)); ++ CHAR *left_buffer = (CHAR *) left_ntf.buffer; ++ struct support_next_to_fault right_ntf ++ = support_next_to_fault_allocate (buffer_length * sizeof (CHAR)); ++ CHAR *right_buffer = (CHAR *) right_ntf.buffer; ++ ++ FOR_EACH_IMPL (impl, 0) ++ { ++ printf ("info: testing %s\n", impl->name); ++ for (size_t i = 0; i < buffer_length; ++i) ++ left_buffer[i] = 'A'; ++ ++ for (int left_zero_count = 0; left_zero_count <= buffer_length; ++ ++left_zero_count) ++ { ++ if (left_zero_count > 0) ++ left_buffer[buffer_length - left_zero_count] = 0; ++ int left_a_count = buffer_length - left_zero_count; ++ for (size_t i = 0; i < buffer_length; ++i) ++ right_buffer[i] = 'A'; ++ for (int right_zero_count = 0; right_zero_count <= buffer_length; ++ ++right_zero_count) ++ { ++ if (right_zero_count > 0) ++ right_buffer[buffer_length - right_zero_count] = 0; ++ int right_a_count = buffer_length - right_zero_count; ++ for (int left_start_offset = 0; ++ left_start_offset <= buffer_length; ++ ++left_start_offset) ++ { ++ CHAR *left_start_pointer = left_buffer + left_start_offset; ++ int left_maxlen ++ = maximum_length (left_start_offset, left_zero_count); ++ int left_length ++ = string_length (left_a_count, left_start_offset); ++ for (int right_start_offset = 0; ++ right_start_offset <= buffer_length; ++ ++right_start_offset) ++ { ++ CHAR *right_start_pointer ++ = right_buffer + right_start_offset; ++ int right_maxlen ++ = maximum_length (right_start_offset, right_zero_count); ++ int right_length ++ = string_length (right_a_count, right_start_offset); ++ ++ /* Maximum length is modelled after strnlen/wcsnlen, ++ and must be valid for both pointer arguments at ++ the same time. */ ++ int maxlen = MIN (left_maxlen, right_maxlen); ++ ++ for (int length_argument = 0; length_argument <= maxlen; ++ ++length_argument) ++ { ++ if (test_verbose) ++ { ++ printf ("left: zero_count=%d" ++ " a_count=%d start_offset=%d\n", ++ left_zero_count, left_a_count, ++ left_start_offset); ++ printf ("right: zero_count=%d" ++ " a_count=%d start_offset=%d\n", ++ right_zero_count, right_a_count, ++ right_start_offset); ++ printf ("length argument: %d\n", ++ length_argument); ++ } ++ ++ /* Effective lengths bounded by length argument. ++ The effective length determines the ++ outcome of the comparison. */ ++ int left_effective ++ = MIN (left_length, length_argument); ++ int right_effective ++ = MIN (right_length, length_argument); ++ if (left_effective == right_effective) ++ TEST_COMPARE (CALL (impl, ++ left_start_pointer, ++ right_start_pointer, ++ length_argument), 0); ++ else if (left_effective < right_effective) ++ TEST_COMPARE (CALL (impl, ++ left_start_pointer, ++ right_start_pointer, ++ length_argument) < 0, 1); ++ else ++ TEST_COMPARE (CALL (impl, ++ left_start_pointer, ++ right_start_pointer, ++ length_argument) > 0, 1); ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++#include +diff -Nrup a/string/test-strncmp-nonarray.c b/string/test-strncmp-nonarray.c +--- a/string/test-strncmp-nonarray.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/string/test-strncmp-nonarray.c 2024-09-03 11:52:17.707438963 -0400 +@@ -0,0 +1,4 @@ ++#define TEST_IDENTIFIER strncmp ++#define TEST_NAME "strncmp" ++typedef char CHAR; ++#include "test-Xncmp-nonarray.c" +diff -Nrup a/wcsmbs/Makefile b/wcsmbs/Makefile +--- a/wcsmbs/Makefile 2024-09-03 11:42:30.398319976 -0400 ++++ b/wcsmbs/Makefile 2024-09-03 11:53:44.806049806 -0400 +@@ -56,6 +56,10 @@ tests := tst-wcstof wcsmbs-tst1 tst-wcsn + $(addprefix test-,$(strop-tests)) tst-mbstowcs \ + test-wcsdup + ++# This test runs for a long time. ++xtests += test-wcsncmp-nonarray ++ ++ + include ../Rules + + ifeq ($(run-built-tests),yes) +diff -Nrup a/wcsmbs/test-wcsncmp-nonarray.c b/wcsmbs/test-wcsncmp-nonarray.c +--- a/wcsmbs/test-wcsncmp-nonarray.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/wcsmbs/test-wcsncmp-nonarray.c 2024-09-03 11:52:17.708438970 -0400 +@@ -0,0 +1,5 @@ ++#include ++#define TEST_IDENTIFIER wcsncmp ++#define TEST_NAME "wcsncmp" ++typedef wchar_t CHAR; ++#include "../string/test-Xncmp-nonarray.c" diff --git a/SOURCES/glibc-RHEL-49489-3.patch b/SOURCES/glibc-RHEL-49489-3.patch new file mode 100644 index 0000000..c812640 --- /dev/null +++ b/SOURCES/glibc-RHEL-49489-3.patch @@ -0,0 +1,327 @@ +commit 2f47198b04a02097f438ecb765306fa39568a006 +Author: Rajalakshmi Srinivasaraghavan +Date: Fri Dec 2 14:26:41 2022 -0600 + + powerpc64: Remove old strncmp optimization + + This patch cleans up the power4 strncmp optimization for powerpc64 which + is unlikely to be used anywhere. + + Tested on ppc64le with and without --disable-multi-arch flag. + + Reviewed-by: Paul E. Murphy + Reviewed-by: Adhemerval Zanella + +Conflicts: + sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S + sysdeps/powerpc/powerpc64/power4/strncmp.S + (copyright year changes upstream) + +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 626845a43c4e8ded..5b20dab108de14ab 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -12,8 +12,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + strnlen-power8 strnlen-power7 strnlen-ppc64 \ + strcasecmp-power7 strcasecmp_l-power7 \ + strncase-power7 strncase_l-power7 \ +- strncmp-power8 strncmp-power7 \ +- strncmp-power4 strncmp-ppc64 \ ++ strncmp-power8 strncmp-power7 strncmp-ppc64 \ + strchr-power8 strchr-power7 strchr-ppc64 \ + strchrnul-power8 strchrnul-power7 strchrnul-ppc64 \ + strcpy-power8 strcpy-power7 strcpy-ppc64 stpcpy-power8 \ +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 7b83aa7b8ff28bb7..914e7d5e28a98b5d 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -177,8 +177,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __strncmp_power8) + IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_ARCH_2_06, + __strncmp_power7) +- IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_POWER4, +- __strncmp_power4) + IFUNC_IMPL_ADD (array, i, strncmp, 1, + __strncmp_ppc)) + +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S +deleted file mode 100644 +index 6ead3b6374749e6a..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S ++++ /dev/null +@@ -1,23 +0,0 @@ +-/* Copyright (C) 2013-2021 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#define STRNCMP __strncmp_power4 +- +-#undef libc_hidden_builtin_def +-#define libc_hidden_builtin_def(name) +- +-#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c +index 2d2112285445a450..275a558e4afa7d61 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c +@@ -26,7 +26,6 @@ + # include "init-arch.h" + + extern __typeof (strncmp) __strncmp_ppc attribute_hidden; +-extern __typeof (strncmp) __strncmp_power4 attribute_hidden; + extern __typeof (strncmp) __strncmp_power7 attribute_hidden; + extern __typeof (strncmp) __strncmp_power8 attribute_hidden; + # ifdef __LITTLE_ENDIAN__ +@@ -46,7 +45,5 @@ libc_ifunc_redirected (__redirect_strncmp, strncmp, + ? __strncmp_power8 + : (hwcap & PPC_FEATURE_ARCH_2_06) + ? __strncmp_power7 +- : (hwcap & PPC_FEATURE_POWER4) +- ? __strncmp_power4 +- : __strncmp_ppc); ++ : __strncmp_ppc); + #endif +diff --git a/sysdeps/powerpc/powerpc64/power4/strncmp.S b/sysdeps/powerpc/powerpc64/power4/strncmp.S +deleted file mode 100644 +index cf5f4e5fb8fb2522..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/power4/strncmp.S ++++ /dev/null +@@ -1,225 +0,0 @@ +-/* Optimized strcmp implementation for PowerPC64. +- Copyright (C) 2003-2021 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +- +-#ifndef STRNCMP +-# define STRNCMP strncmp +-#endif +- +-/* See strlen.s for comments on how the end-of-string testing works. */ +- +-/* int [r3] strncmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5]) */ +- +-ENTRY_TOCLESS (STRNCMP, 4) +- CALL_MCOUNT 3 +- +-#define rTMP2 r0 +-#define rRTN r3 +-#define rSTR1 r3 /* first string arg */ +-#define rSTR2 r4 /* second string arg */ +-#define rN r5 /* max string length */ +-#define rWORD1 r6 /* current word in s1 */ +-#define rWORD2 r7 /* current word in s2 */ +-#define rWORD3 r10 +-#define rWORD4 r11 +-#define rFEFE r8 /* constant 0xfefefefefefefeff (-0x0101010101010101) */ +-#define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */ +-#define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ +-#define rBITDIF r11 /* bits that differ in s1 & s2 words */ +-#define rTMP r12 +- +- dcbt 0,rSTR1 +- or rTMP, rSTR2, rSTR1 +- lis r7F7F, 0x7f7f +- dcbt 0,rSTR2 +- clrldi. rTMP, rTMP, 61 +- cmpldi cr1, rN, 0 +- lis rFEFE, -0x101 +- bne L(unaligned) +-/* We are doubleword aligned so set up for two loops. first a double word +- loop, then fall into the byte loop if any residual. */ +- srdi. rTMP, rN, 3 +- clrldi rN, rN, 61 +- addi rFEFE, rFEFE, -0x101 +- addi r7F7F, r7F7F, 0x7f7f +- cmpldi cr1, rN, 0 +- beq L(unaligned) +- +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group. */ +- ld rWORD1, 0(rSTR1) +- ld rWORD2, 0(rSTR2) +- sldi rTMP, rFEFE, 32 +- insrdi r7F7F, r7F7F, 32, 0 +- add rFEFE, rFEFE, rTMP +- b L(g1) +- +-L(g0): +- ldu rWORD1, 8(rSTR1) +- bne- cr1, L(different) +- ldu rWORD2, 8(rSTR2) +-L(g1): add rTMP, rFEFE, rWORD1 +- nor rNEG, r7F7F, rWORD1 +- bdz L(tail) +- and. rTMP, rTMP, rNEG +- cmpd cr1, rWORD1, rWORD2 +- beq+ L(g0) +- +-/* OK. We've hit the end of the string. We need to be careful that +- we don't compare two strings as different because of gunk beyond +- the end of the strings... */ +- +-#ifdef __LITTLE_ENDIAN__ +-L(endstring): +- addi rTMP2, rTMP, -1 +- beq cr1, L(equal) +- andc rTMP2, rTMP2, rTMP +- rldimi rTMP2, rTMP2, 1, 0 +- and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ +- and rWORD1, rWORD1, rTMP2 +- cmpd cr1, rWORD1, rWORD2 +- beq cr1, L(equal) +- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ +- neg rNEG, rBITDIF +- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ +- cntlzd rNEG, rNEG /* bitcount of the bit. */ +- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ +- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ +- sld rWORD2, rWORD2, rNEG +- xor. rBITDIF, rWORD1, rWORD2 +- sub rRTN, rWORD1, rWORD2 +- blt- L(highbit) +- sradi rRTN, rRTN, 63 /* must return an int. */ +- ori rRTN, rRTN, 1 +- blr +-L(equal): +- li rRTN, 0 +- blr +- +-L(different): +- ld rWORD1, -8(rSTR1) +- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ +- neg rNEG, rBITDIF +- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ +- cntlzd rNEG, rNEG /* bitcount of the bit. */ +- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ +- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ +- sld rWORD2, rWORD2, rNEG +- xor. rBITDIF, rWORD1, rWORD2 +- sub rRTN, rWORD1, rWORD2 +- blt- L(highbit) +- sradi rRTN, rRTN, 63 +- ori rRTN, rRTN, 1 +- blr +-L(highbit): +- sradi rRTN, rWORD2, 63 +- ori rRTN, rRTN, 1 +- blr +- +-#else +-L(endstring): +- and rTMP, r7F7F, rWORD1 +- beq cr1, L(equal) +- add rTMP, rTMP, r7F7F +- xor. rBITDIF, rWORD1, rWORD2 +- andc rNEG, rNEG, rTMP +- blt- L(highbit) +- cntlzd rBITDIF, rBITDIF +- cntlzd rNEG, rNEG +- addi rNEG, rNEG, 7 +- cmpd cr1, rNEG, rBITDIF +- sub rRTN, rWORD1, rWORD2 +- blt- cr1, L(equal) +- sradi rRTN, rRTN, 63 /* must return an int. */ +- ori rRTN, rRTN, 1 +- blr +-L(equal): +- li rRTN, 0 +- blr +- +-L(different): +- ld rWORD1, -8(rSTR1) +- xor. rBITDIF, rWORD1, rWORD2 +- sub rRTN, rWORD1, rWORD2 +- blt- L(highbit) +- sradi rRTN, rRTN, 63 +- ori rRTN, rRTN, 1 +- blr +-L(highbit): +- sradi rRTN, rWORD2, 63 +- ori rRTN, rRTN, 1 +- blr +-#endif +- +-/* Oh well. In this case, we just do a byte-by-byte comparison. */ +- .align 4 +-L(tail): +- and. rTMP, rTMP, rNEG +- cmpd cr1, rWORD1, rWORD2 +- bne- L(endstring) +- addi rSTR1, rSTR1, 8 +- bne- cr1, L(different) +- addi rSTR2, rSTR2, 8 +- cmpldi cr1, rN, 0 +-L(unaligned): +- mtctr rN /* Power4 wants mtctr 1st in dispatch group */ +- ble cr1, L(ux) +-L(uz): +- lbz rWORD1, 0(rSTR1) +- lbz rWORD2, 0(rSTR2) +- .align 4 +-L(u1): +- cmpdi cr1, rWORD1, 0 +- bdz L(u4) +- cmpd rWORD1, rWORD2 +- beq- cr1, L(u4) +- bne- L(u4) +- lbzu rWORD3, 1(rSTR1) +- lbzu rWORD4, 1(rSTR2) +- cmpdi cr1, rWORD3, 0 +- bdz L(u3) +- cmpd rWORD3, rWORD4 +- beq- cr1, L(u3) +- bne- L(u3) +- lbzu rWORD1, 1(rSTR1) +- lbzu rWORD2, 1(rSTR2) +- cmpdi cr1, rWORD1, 0 +- bdz L(u4) +- cmpd rWORD1, rWORD2 +- beq- cr1, L(u4) +- bne- L(u4) +- lbzu rWORD3, 1(rSTR1) +- lbzu rWORD4, 1(rSTR2) +- cmpdi cr1, rWORD3, 0 +- bdz L(u3) +- cmpd rWORD3, rWORD4 +- beq- cr1, L(u3) +- bne- L(u3) +- lbzu rWORD1, 1(rSTR1) +- lbzu rWORD2, 1(rSTR2) +- b L(u1) +- +-L(u3): sub rRTN, rWORD3, rWORD4 +- blr +-L(u4): sub rRTN, rWORD1, rWORD2 +- blr +-L(ux): +- li rRTN, 0 +- blr +-END (STRNCMP) +-libc_hidden_builtin_def (strncmp) diff --git a/SOURCES/glibc-RHEL-49489-4.patch b/SOURCES/glibc-RHEL-49489-4.patch new file mode 100644 index 0000000..bc22daa --- /dev/null +++ b/SOURCES/glibc-RHEL-49489-4.patch @@ -0,0 +1,595 @@ +commit 92fdb11ae7aa1ab6b18622670ea702205cd6fdc5 +Author: Adhemerval Zanella Netto +Date: Tue Feb 28 14:23:59 2023 -0300 + + powerpc: Remove powerpc64 strncmp variants + + The default, and power7 implementation just adds word aligned + access when inputs have the same aligment. The unaligned case + is still done by byte operations. + + This is already covered by the generic implementation, which also add + the unaligned input optimization. + + Checked on powerpc64-linux-gnu built without multi-arch for powerpc64, + power7, power8, and power9 (build for le). + Reviewed-by: Rajalakshmi Srinivasaraghavan + +Conflicts: + sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S + sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S + sysdeps/powerpc/powerpc64/power7/strncmp.S + sysdeps/powerpc/powerpc64/strncmp.S + (copyright year changes upstream) + +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 5b20dab108de14ab..0ee7ce39d6470d80 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -12,7 +12,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + strnlen-power8 strnlen-power7 strnlen-ppc64 \ + strcasecmp-power7 strcasecmp_l-power7 \ + strncase-power7 strncase_l-power7 \ +- strncmp-power8 strncmp-power7 strncmp-ppc64 \ ++ strncmp-power8 strncmp-ppc64 \ + strchr-power8 strchr-power7 strchr-ppc64 \ + strchrnul-power8 strchrnul-power7 strchrnul-ppc64 \ + strcpy-power8 strcpy-power7 strcpy-ppc64 stpcpy-power8 \ +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 914e7d5e28a98b5d..2c84d287ee76a7ea 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -175,8 +175,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + #endif + IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_2_07, + __strncmp_power8) +- IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_ARCH_2_06, +- __strncmp_power7) + IFUNC_IMPL_ADD (array, i, strncmp, 1, + __strncmp_ppc)) + +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S +deleted file mode 100644 +index 8282ff076c9e00ce..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S ++++ /dev/null +@@ -1,23 +0,0 @@ +-/* Copyright (C) 2013-2021 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#define STRNCMP __strncmp_power7 +- +-#undef libc_hidden_builtin_def +-#define libc_hidden_builtin_def(name) +- +-#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S +deleted file mode 100644 +index c6f325650c9ace3b..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S ++++ /dev/null +@@ -1,26 +0,0 @@ +-/* Copyright (C) 2013-2021 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#if defined SHARED && IS_IN (libc) +-# define STRNCMP __strncmp_ppc +- +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) \ +- .globl __GI_strncmp; __GI_strncmp = __strncmp_ppc +-#endif +- +-#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c +new file mode 100644 +index 0000000000000000..09cc009a913ed169 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c +@@ -0,0 +1,7 @@ ++#if defined SHARED && IS_IN (libc) ++# define STRNCMP __strncmp_ppc ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ ++ __hidden_ver1 (__strncmp_ppc, __GI_strncmp, __strncmp_ppc); ++#endif ++#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c +index 275a558e4afa7d61..df2c0707a919ad79 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c +@@ -26,7 +26,6 @@ + # include "init-arch.h" + + extern __typeof (strncmp) __strncmp_ppc attribute_hidden; +-extern __typeof (strncmp) __strncmp_power7 attribute_hidden; + extern __typeof (strncmp) __strncmp_power8 attribute_hidden; + # ifdef __LITTLE_ENDIAN__ + extern __typeof (strncmp) __strncmp_power9 attribute_hidden; +@@ -43,7 +42,5 @@ libc_ifunc_redirected (__redirect_strncmp, strncmp, + # endif + (hwcap2 & PPC_FEATURE2_ARCH_2_07) + ? __strncmp_power8 +- : (hwcap & PPC_FEATURE_ARCH_2_06) +- ? __strncmp_power7 +- : __strncmp_ppc); ++ : __strncmp_ppc); + #endif +diff --git a/sysdeps/powerpc/powerpc64/power7/strncmp.S b/sysdeps/powerpc/powerpc64/power7/strncmp.S +deleted file mode 100644 +index d91aeb6077a558f2..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/power7/strncmp.S ++++ /dev/null +@@ -1,228 +0,0 @@ +-/* Optimized strcmp implementation for POWER7/PowerPC64. +- Copyright (C) 2010-2021 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +- +-#ifndef STRNCMP +-# define STRNCMP strncmp +-#endif +- +-/* See strlen.s for comments on how the end-of-string testing works. */ +- +-/* int [r3] strncmp (const char *s1 [r3], +- const char *s2 [r4], +- size_t size [r5]) */ +- +- .machine power7 +-ENTRY_TOCLESS (STRNCMP, 5) +- CALL_MCOUNT 3 +- +-#define rTMP2 r0 +-#define rRTN r3 +-#define rSTR1 r3 /* first string arg */ +-#define rSTR2 r4 /* second string arg */ +-#define rN r5 /* max string length */ +-#define rWORD1 r6 /* current word in s1 */ +-#define rWORD2 r7 /* current word in s2 */ +-#define rWORD3 r10 +-#define rWORD4 r11 +-#define rFEFE r8 /* constant 0xfefefefefefefeff (-0x0101010101010101) */ +-#define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */ +-#define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ +-#define rBITDIF r11 /* bits that differ in s1 & s2 words */ +-#define rTMP r12 +- +- dcbt 0,rSTR1 +- nop +- or rTMP,rSTR2,rSTR1 +- lis r7F7F,0x7f7f +- dcbt 0,rSTR2 +- nop +- clrldi. rTMP,rTMP,61 +- cmpldi cr1,rN,0 +- lis rFEFE,-0x101 +- bne L(unaligned) +-/* We are doubleword aligned so set up for two loops. first a double word +- loop, then fall into the byte loop if any residual. */ +- srdi. rTMP,rN,3 +- clrldi rN,rN,61 +- addi rFEFE,rFEFE,-0x101 +- addi r7F7F,r7F7F,0x7f7f +- cmpldi cr1,rN,0 +- beq L(unaligned) +- +- mtctr rTMP +- ld rWORD1,0(rSTR1) +- ld rWORD2,0(rSTR2) +- sldi rTMP,rFEFE,32 +- insrdi r7F7F,r7F7F,32,0 +- add rFEFE,rFEFE,rTMP +- b L(g1) +- +-L(g0): +- ldu rWORD1,8(rSTR1) +- bne cr1,L(different) +- ldu rWORD2,8(rSTR2) +-L(g1): add rTMP,rFEFE,rWORD1 +- nor rNEG,r7F7F,rWORD1 +- bdz L(tail) +- and. rTMP,rTMP,rNEG +- cmpd cr1,rWORD1,rWORD2 +- beq L(g0) +- +-/* OK. We've hit the end of the string. We need to be careful that +- we don't compare two strings as different because of gunk beyond +- the end of the strings... */ +- +-#ifdef __LITTLE_ENDIAN__ +-L(endstring): +- addi rTMP2, rTMP, -1 +- beq cr1, L(equal) +- andc rTMP2, rTMP2, rTMP +- rldimi rTMP2, rTMP2, 1, 0 +- and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ +- and rWORD1, rWORD1, rTMP2 +- cmpd cr1, rWORD1, rWORD2 +- beq cr1, L(equal) +- cmpb rBITDIF, rWORD1, rWORD2 /* 0xff on equal bytes. */ +- addi rNEG, rBITDIF, 1 +- orc rNEG, rNEG, rBITDIF /* 0's below LS differing byte. */ +- sldi rNEG, rNEG, 8 /* 1's above LS differing byte. */ +- andc rWORD1, rWORD1, rNEG /* mask off MS bytes. */ +- andc rWORD2, rWORD2, rNEG +- xor. rBITDIF, rWORD1, rWORD2 +- sub rRTN, rWORD1, rWORD2 +- blt L(highbit) +- sradi rRTN, rRTN, 63 /* must return an int. */ +- ori rRTN, rRTN, 1 +- blr +-L(equal): +- li rRTN, 0 +- blr +- +-L(different): +- ld rWORD1, -8(rSTR1) +- cmpb rBITDIF, rWORD1, rWORD2 /* 0xff on equal bytes. */ +- addi rNEG, rBITDIF, 1 +- orc rNEG, rNEG, rBITDIF /* 0's below LS differing byte. */ +- sldi rNEG, rNEG, 8 /* 1's above LS differing byte. */ +- andc rWORD1, rWORD1, rNEG /* mask off MS bytes. */ +- andc rWORD2, rWORD2, rNEG +- xor. rBITDIF, rWORD1, rWORD2 +- sub rRTN, rWORD1, rWORD2 +- blt L(highbit) +- sradi rRTN, rRTN, 63 +- ori rRTN, rRTN, 1 +- blr +-L(highbit): +- sradi rRTN, rWORD2, 63 +- ori rRTN, rRTN, 1 +- blr +- +-#else +-L(endstring): +- and rTMP,r7F7F,rWORD1 +- beq cr1,L(equal) +- add rTMP,rTMP,r7F7F +- xor. rBITDIF,rWORD1,rWORD2 +- andc rNEG,rNEG,rTMP +- blt L(highbit) +- cntlzd rBITDIF,rBITDIF +- cntlzd rNEG,rNEG +- addi rNEG,rNEG,7 +- cmpd cr1,rNEG,rBITDIF +- sub rRTN,rWORD1,rWORD2 +- blt cr1,L(equal) +- sradi rRTN,rRTN,63 /* must return an int. */ +- ori rRTN,rRTN,1 +- blr +-L(equal): +- li rRTN,0 +- blr +- +-L(different): +- ld rWORD1,-8(rSTR1) +- xor. rBITDIF,rWORD1,rWORD2 +- sub rRTN,rWORD1,rWORD2 +- blt L(highbit) +- sradi rRTN,rRTN,63 +- ori rRTN,rRTN,1 +- blr +-L(highbit): +- sradi rRTN,rWORD2,63 +- ori rRTN,rRTN,1 +- blr +-#endif +- +-/* Oh well. In this case, we just do a byte-by-byte comparison. */ +- .align 4 +-L(tail): +- and. rTMP,rTMP,rNEG +- cmpd cr1,rWORD1,rWORD2 +- bne L(endstring) +- addi rSTR1,rSTR1,8 +- bne cr1,L(different) +- addi rSTR2,rSTR2,8 +- cmpldi cr1,rN,0 +-L(unaligned): +- mtctr rN +- ble cr1,L(ux) +-L(uz): +- lbz rWORD1,0(rSTR1) +- lbz rWORD2,0(rSTR2) +- .align 4 +-L(u1): +- cmpdi cr1,rWORD1,0 +- bdz L(u4) +- cmpd rWORD1,rWORD2 +- beq cr1,L(u4) +- bne L(u4) +- lbzu rWORD3,1(rSTR1) +- lbzu rWORD4,1(rSTR2) +- cmpdi cr1,rWORD3,0 +- bdz L(u3) +- cmpd rWORD3,rWORD4 +- beq cr1,L(u3) +- bne L(u3) +- lbzu rWORD1,1(rSTR1) +- lbzu rWORD2,1(rSTR2) +- cmpdi cr1,rWORD1,0 +- bdz L(u4) +- cmpd rWORD1,rWORD2 +- beq cr1,L(u4) +- bne L(u4) +- lbzu rWORD3,1(rSTR1) +- lbzu rWORD4,1(rSTR2) +- cmpdi cr1,rWORD3,0 +- bdz L(u3) +- cmpd rWORD3,rWORD4 +- beq cr1,L(u3) +- bne L(u3) +- lbzu rWORD1,1(rSTR1) +- lbzu rWORD2,1(rSTR2) +- b L(u1) +- +-L(u3): sub rRTN,rWORD3,rWORD4 +- blr +-L(u4): sub rRTN,rWORD1,rWORD2 +- blr +-L(ux): +- li rRTN,0 +- blr +-END (STRNCMP) +-libc_hidden_builtin_def (strncmp) +diff --git a/sysdeps/powerpc/powerpc64/strncmp.S b/sysdeps/powerpc/powerpc64/strncmp.S +deleted file mode 100644 +index 40a230242cbdf733..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/strncmp.S ++++ /dev/null +@@ -1,210 +0,0 @@ +-/* Optimized strcmp implementation for PowerPC64. +- Copyright (C) 2003-2021 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +- +-/* See strlen.s for comments on how the end-of-string testing works. */ +- +-/* int [r3] strncmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5]) */ +- +-#ifndef STRNCMP +-# define STRNCMP strncmp +-#endif +- +-ENTRY_TOCLESS (STRNCMP, 4) +- CALL_MCOUNT 3 +- +-#define rTMP2 r0 +-#define rRTN r3 +-#define rSTR1 r3 /* first string arg */ +-#define rSTR2 r4 /* second string arg */ +-#define rN r5 /* max string length */ +-#define rWORD1 r6 /* current word in s1 */ +-#define rWORD2 r7 /* current word in s2 */ +-#define rFEFE r8 /* constant 0xfefefefefefefeff (-0x0101010101010101) */ +-#define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */ +-#define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ +-#define rBITDIF r11 /* bits that differ in s1 & s2 words */ +-#define rTMP r12 +- +- dcbt 0,rSTR1 +- or rTMP, rSTR2, rSTR1 +- lis r7F7F, 0x7f7f +- dcbt 0,rSTR2 +- clrldi. rTMP, rTMP, 61 +- cmpldi cr1, rN, 0 +- lis rFEFE, -0x101 +- bne L(unaligned) +-/* We are doubleword aligned so set up for two loops. first a double word +- loop, then fall into the byte loop if any residual. */ +- srdi. rTMP, rN, 3 +- clrldi rN, rN, 61 +- addi rFEFE, rFEFE, -0x101 +- addi r7F7F, r7F7F, 0x7f7f +- cmpldi cr1, rN, 0 +- beq L(unaligned) +- +- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group. */ +- ld rWORD1, 0(rSTR1) +- ld rWORD2, 0(rSTR2) +- sldi rTMP, rFEFE, 32 +- insrdi r7F7F, r7F7F, 32, 0 +- add rFEFE, rFEFE, rTMP +- b L(g1) +- +-L(g0): +- ldu rWORD1, 8(rSTR1) +- bne- cr1, L(different) +- ldu rWORD2, 8(rSTR2) +-L(g1): add rTMP, rFEFE, rWORD1 +- nor rNEG, r7F7F, rWORD1 +- bdz L(tail) +- and. rTMP, rTMP, rNEG +- cmpd cr1, rWORD1, rWORD2 +- beq+ L(g0) +- +-/* OK. We've hit the end of the string. We need to be careful that +- we don't compare two strings as different because of gunk beyond +- the end of the strings... */ +- +-#ifdef __LITTLE_ENDIAN__ +-L(endstring): +- addi rTMP2, rTMP, -1 +- beq cr1, L(equal) +- andc rTMP2, rTMP2, rTMP +- rldimi rTMP2, rTMP2, 1, 0 +- and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ +- and rWORD1, rWORD1, rTMP2 +- cmpd cr1, rWORD1, rWORD2 +- beq cr1, L(equal) +- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ +- neg rNEG, rBITDIF +- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ +- cntlzd rNEG, rNEG /* bitcount of the bit. */ +- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ +- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ +- sld rWORD2, rWORD2, rNEG +- xor. rBITDIF, rWORD1, rWORD2 +- sub rRTN, rWORD1, rWORD2 +- blt- L(highbit) +- sradi rRTN, rRTN, 63 /* must return an int. */ +- ori rRTN, rRTN, 1 +- blr +-L(equal): +- li rRTN, 0 +- blr +- +-L(different): +- ld rWORD1, -8(rSTR1) +- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ +- neg rNEG, rBITDIF +- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ +- cntlzd rNEG, rNEG /* bitcount of the bit. */ +- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ +- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ +- sld rWORD2, rWORD2, rNEG +- xor. rBITDIF, rWORD1, rWORD2 +- sub rRTN, rWORD1, rWORD2 +- blt- L(highbit) +- sradi rRTN, rRTN, 63 +- ori rRTN, rRTN, 1 +- blr +-L(highbit): +- sradi rRTN, rWORD2, 63 +- ori rRTN, rRTN, 1 +- blr +- +-#else +-L(endstring): +- and rTMP, r7F7F, rWORD1 +- beq cr1, L(equal) +- add rTMP, rTMP, r7F7F +- xor. rBITDIF, rWORD1, rWORD2 +- andc rNEG, rNEG, rTMP +- blt- L(highbit) +- cntlzd rBITDIF, rBITDIF +- cntlzd rNEG, rNEG +- addi rNEG, rNEG, 7 +- cmpd cr1, rNEG, rBITDIF +- sub rRTN, rWORD1, rWORD2 +- blt- cr1, L(equal) +- sradi rRTN, rRTN, 63 /* must return an int. */ +- ori rRTN, rRTN, 1 +- blr +-L(equal): +- li rRTN, 0 +- blr +- +-L(different): +- ld rWORD1, -8(rSTR1) +- xor. rBITDIF, rWORD1, rWORD2 +- sub rRTN, rWORD1, rWORD2 +- blt- L(highbit) +- sradi rRTN, rRTN, 63 +- ori rRTN, rRTN, 1 +- blr +-L(highbit): +- sradi rRTN, rWORD2, 63 +- ori rRTN, rRTN, 1 +- blr +-#endif +- +-/* Oh well. In this case, we just do a byte-by-byte comparison. */ +- .align 4 +-L(tail): +- and. rTMP, rTMP, rNEG +- cmpd cr1, rWORD1, rWORD2 +- bne- L(endstring) +- addi rSTR1, rSTR1, 8 +- bne- cr1, L(different) +- addi rSTR2, rSTR2, 8 +- cmpldi cr1, rN, 0 +-L(unaligned): +- mtctr rN /* Power4 wants mtctr 1st in dispatch group */ +- bgt cr1, L(uz) +-L(ux): +- li rRTN, 0 +- blr +- .align 4 +-L(uz): +- lbz rWORD1, 0(rSTR1) +- lbz rWORD2, 0(rSTR2) +- nop +- b L(u1) +-L(u0): +- lbzu rWORD2, 1(rSTR2) +-L(u1): +- bdz L(u3) +- cmpdi cr1, rWORD1, 0 +- cmpd rWORD1, rWORD2 +- beq- cr1, L(u3) +- lbzu rWORD1, 1(rSTR1) +- bne- L(u2) +- lbzu rWORD2, 1(rSTR2) +- bdz L(u3) +- cmpdi cr1, rWORD1, 0 +- cmpd rWORD1, rWORD2 +- bne- L(u3) +- lbzu rWORD1, 1(rSTR1) +- bne+ cr1, L(u0) +- +-L(u2): lbzu rWORD1, -1(rSTR1) +-L(u3): sub rRTN, rWORD1, rWORD2 +- blr +-END (STRNCMP) +-libc_hidden_builtin_def (strncmp) diff --git a/SOURCES/glibc-RHEL-50101-1.patch b/SOURCES/glibc-RHEL-50101-1.patch new file mode 100644 index 0000000..eb722e3 --- /dev/null +++ b/SOURCES/glibc-RHEL-50101-1.patch @@ -0,0 +1,240 @@ +commit 3395157ff2b0657d70c36169156f67440205c8bf +Author: Joe Simmons-Talbott +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 + +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 ++ . */ ++ ++#include ++#include ++#include ++ ++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 +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 . */ ++ ++#include ++#include ++#include ++ ++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 ++ . */ ++ ++#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 + #include + #include ++#include + #include ++#include + + 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 +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 + +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 . */ + +-#include + #include + #include ++#include + + 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 +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 + +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 . */ ++#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 . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 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 +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 ++ . */ ++ ++#include ++#include ++ ++#include ++ ++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 diff --git a/SOURCES/glibc-RHEL-54447-1.patch b/SOURCES/glibc-RHEL-54447-1.patch new file mode 100644 index 0000000..e625815 --- /dev/null +++ b/SOURCES/glibc-RHEL-54447-1.patch @@ -0,0 +1,331 @@ +commit 5456af201d4c0a2950200ba756e5f8314ddbbccd +Author: Carlos O'Donell +Date: Thu May 11 14:00:41 2023 -0400 + + stdio-common: Reformat Makefile. + + Reflow Makefile. + Sort using scripts/sort-makefile-lines.py. + + Code generation is changed as routines are linked in sorted order + as expected. + + No regressions on x86_64 and i686. + + (cherry picked from commit c3004417afc98585089a9282d1d4d60cdef5317a) + (cherry picked from commit 5b4e90230b8147e273585bf296bf1a9fb6e2b4c2) + +diff --git a/stdio-common/Makefile b/stdio-common/Makefile +index 803f16dae030cb72..76d1d0a1193aa109 100644 +--- a/stdio-common/Makefile ++++ b/stdio-common/Makefile +@@ -22,82 +22,241 @@ subdir := stdio-common + + include ../Makeconfig + +-headers := stdio_ext.h printf.h bits/printf-ldbl.h bits/stdio_lim.h +- +-routines := \ +- ctermid cuserid \ +- _itoa _itowa itoa-digits itoa-udigits itowa-digits \ +- vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex \ +- reg-modifier reg-type \ +- printf_size fprintf printf snprintf sprintf asprintf dprintf \ +- vfwprintf vfscanf vfwscanf \ +- fscanf scanf sscanf \ +- perror psignal \ +- tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \ +- getline getw putw \ +- remove rename renameat renameat2 \ +- flockfile ftrylockfile funlockfile \ +- isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \ +- isoc99_vsscanf \ +- psiginfo gentempfd \ +- vfscanf-internal vfwscanf-internal iovfscanf \ +- vfprintf-internal vfwprintf-internal +- +-aux := errlist siglist printf-parsemb printf-parsewc fxprintf +- +-tests := tstscanf test_rdwr test-popen tstgetln test-fseek \ +- temptest tst-fileno test-fwrite tst-ungetc tst-ferror \ +- xbug errnobug \ +- bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 \ +- tfformat tiformat tllformat tstdiomisc tst-printfsz tst-wc-printf \ +- scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \ +- scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \ +- tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \ +- tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 \ +- tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \ +- tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \ +- bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \ +- scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \ +- bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \ +- bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 tst-fmemopen3 \ +- tst-printf-bz18872 tst-vfprintf-width-prec tst-fmemopen4 \ +- tst-vfprintf-user-type \ +- tst-vfprintf-mbs-prec \ +- tst-scanf-round \ +- tst-renameat2 tst-bz11319 tst-bz11319-fortify2 \ +- scanf14a scanf16a \ +- tst-printf-bz25691 \ +- tst-vfprintf-width-prec-alloc \ +- tst-printf-fp-free \ +- tst-printf-fp-leak \ +- test-strerr +- +- +-test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble ++headers := \ ++ bits/printf-ldbl.h \ ++ bits/stdio_lim.h \ ++ printf.h \ ++ stdio_ext.h \ ++ # headers ++ ++routines := \ ++ _itoa \ ++ _itowa \ ++ asprintf \ ++ ctermid \ ++ cuserid \ ++ dprintf \ ++ flockfile \ ++ fprintf \ ++ fscanf \ ++ ftrylockfile \ ++ funlockfile \ ++ gentempfd \ ++ getline \ ++ getw \ ++ iovfscanf \ ++ isoc99_fscanf \ ++ isoc99_scanf \ ++ isoc99_sscanf \ ++ isoc99_vfscanf \ ++ isoc99_vscanf \ ++ isoc99_vsscanf \ ++ itoa-digits \ ++ itoa-udigits \ ++ itowa-digits \ ++ perror \ ++ printf \ ++ printf-prs \ ++ printf_fp \ ++ printf_fphex \ ++ printf_size \ ++ psiginfo \ ++ psignal \ ++ putw \ ++ reg-modifier \ ++ reg-printf \ ++ reg-type \ ++ remove \ ++ rename \ ++ renameat \ ++ renameat2 \ ++ scanf \ ++ snprintf \ ++ sprintf \ ++ sscanf \ ++ tempnam \ ++ tempname \ ++ tmpfile \ ++ tmpfile64 tmpnam \ ++ tmpnam_r \ ++ vfprintf \ ++ vfprintf-internal \ ++ vfscanf \ ++ vfscanf-internal \ ++ vfwprintf \ ++ vfwprintf-internal \ ++ vfwscanf \ ++ vfwscanf-internal \ ++ vprintf \ ++ # routines ++ ++aux := \ ++ errlist \ ++ fxprintf \ ++ printf-parsemb \ ++ printf-parsewc \ ++ siglist \ ++ # aux ++ ++tests := \ ++ bug-vfprintf-nargs \ ++ bug1 \ ++ bug10 \ ++ bug11 \ ++ bug12 \ ++ bug13 \ ++ bug14 \ ++ bug16 \ ++ bug17 \ ++ bug18 \ ++ bug18a \ ++ bug19 \ ++ bug19a \ ++ bug2 \ ++ bug20 \ ++ bug21 \ ++ bug22 \ ++ bug23 \ ++ bug23-2 \ ++ bug23-3 \ ++ bug23-4 \ ++ bug24 \ ++ bug25 \ ++ bug26 \ ++ bug3 \ ++ bug4 \ ++ bug5 \ ++ bug6 \ ++ bug7 \ ++ bug8 \ ++ bug9 \ ++ errnobug \ ++ scanf1 \ ++ scanf10 \ ++ scanf11 \ ++ scanf12 \ ++ scanf13 \ ++ scanf14 \ ++ scanf14a \ ++ scanf15 \ ++ scanf16 \ ++ scanf16a \ ++ scanf17 \ ++ scanf2 \ ++ scanf3 \ ++ scanf4 \ ++ scanf5 \ ++ scanf7 \ ++ scanf8 \ ++ scanf9 \ ++ temptest \ ++ test-fseek \ ++ test-fwrite \ ++ test-popen \ ++ test-strerr \ ++ test-vfprintf \ ++ test_rdwr \ ++ tfformat \ ++ tiformat \ ++ tllformat \ ++ tst-bz11319 \ ++ tst-bz11319-fortify2 \ ++ tst-cookie \ ++ tst-fdopen \ ++ tst-ferror \ ++ tst-fgets \ ++ tst-fileno \ ++ tst-fmemopen \ ++ tst-fmemopen2 \ ++ tst-fmemopen3 \ ++ tst-fmemopen4 \ ++ tst-fphex \ ++ tst-fphex-wide \ ++ tst-fseek \ ++ tst-fwrite \ ++ tst-gets \ ++ tst-grouping \ ++ tst-long-dbl-fphex \ ++ tst-obprintf \ ++ tst-perror \ ++ tst-popen \ ++ tst-popen2 \ ++ tst-printf-bz18872 \ ++ tst-printf-bz25691 \ ++ tst-printf-fp-free \ ++ tst-printf-fp-leak \ ++ tst-printf-round \ ++ tst-printfsz \ ++ tst-put-error \ ++ tst-renameat2 \ ++ tst-rndseek \ ++ tst-scanf-round \ ++ tst-setvbuf1 \ ++ tst-sprintf \ ++ tst-sprintf2 \ ++ tst-sprintf3 \ ++ tst-sscanf \ ++ tst-swprintf \ ++ tst-swscanf \ ++ tst-tmpnam \ ++ tst-ungetc \ ++ tst-unlockedio \ ++ tst-vfprintf-mbs-prec \ ++ tst-vfprintf-user-type \ ++ tst-vfprintf-width-prec \ ++ tst-vfprintf-width-prec-alloc \ ++ tst-wc-printf \ ++ tstdiomisc \ ++ tstgetln \ ++ tstscanf \ ++ xbug \ ++ # tests ++ ++test-srcs = \ ++ tst-printf \ ++ tst-printfsz-islongdouble \ ++ tst-unbputc \ ++ # test-srcs + + ifeq ($(run-built-tests),yes) +-tests-special += $(objpfx)tst-unbputc.out $(objpfx)tst-printf.out \ +- $(objpfx)tst-printf-bz18872-mem.out \ +- $(objpfx)tst-setvbuf1-cmp.out \ +- $(objpfx)tst-vfprintf-width-prec-mem.out \ +- $(objpfx)tst-printfsz-islongdouble.out \ +- $(objpfx)tst-printf-bz25691-mem.out \ +- $(objpfx)tst-printf-fp-free-mem.out \ +- $(objpfx)tst-printf-fp-leak-mem.out +-generated += tst-printf-bz18872.c tst-printf-bz18872.mtrace \ +- tst-printf-bz18872-mem.out \ +- tst-vfprintf-width-prec.mtrace tst-vfprintf-width-prec-mem.out \ +- tst-printf-bz25691.mtrace tst-printf-bz25691-mem.out \ +- tst-printf-fp-free.mtrace tst-printf-fp-free-mem.out \ +- tst-printf-fp-leak.mtrace tst-printf-fp-leak-mem.out +-endif ++tests-special += \ ++ $(objpfx)tst-printf-bz18872-mem.out \ ++ $(objpfx)tst-printf-bz25691-mem.out \ ++ $(objpfx)tst-printf-fp-free-mem.out \ ++ $(objpfx)tst-printf-fp-leak-mem.out \ ++ $(objpfx)tst-printf.out \ ++ $(objpfx)tst-printfsz-islongdouble.out \ ++ $(objpfx)tst-setvbuf1-cmp.out \ ++ $(objpfx)tst-unbputc.out \ ++ $(objpfx)tst-vfprintf-width-prec-mem.out \ ++ # tests-special ++ ++generated += \ ++ tst-printf-bz18872-mem.out \ ++ tst-printf-bz18872.c \ ++ tst-printf-bz18872.mtrace \ ++ tst-printf-bz25691-mem.out \ ++ tst-printf-bz25691.mtrace \ ++ tst-printf-fp-free-mem.out \ ++ tst-printf-fp-free.mtrace \ ++ tst-printf-fp-leak-mem.out \ ++ tst-printf-fp-leak.mtrace \ ++ tst-vfprintf-width-prec-mem.out \ ++ tst-vfprintf-width-prec.mtrace \ ++ # generated ++endif # $(run-built-tests) + + tests-special += $(objpfx)tst-errno-manual.out + + include ../Rules + + ifeq ($(run-built-tests),yes) +-LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ISO-8859-1 ja_JP.EUC-JP ++LOCALES := \ ++ de_DE.ISO-8859-1 \ ++ de_DE.UTF-8 \ ++ en_US.ISO-8859-1 \ ++ ja_JP.EUC-JP \ ++ # LOCALES + include ../gen-locales.mk + + $(objpfx)bug14.out: $(gen-locales) diff --git a/SOURCES/glibc-RHEL-54447-10.patch b/SOURCES/glibc-RHEL-54447-10.patch new file mode 100644 index 0000000..6258b77 --- /dev/null +++ b/SOURCES/glibc-RHEL-54447-10.patch @@ -0,0 +1,201 @@ +commit 9556acd249687ac562deb6309503165d66eb06fa +Author: Adhemerval Zanella +Date: Thu Dec 21 15:59:15 2023 -0300 + + debug: Adapt fortify tests to libsupport + + Checked on aarch64, armhf, x86_64, and i686. + Reviewed-by: Siddhesh Poyarekar + +diff --git a/debug/test-stpcpy_chk.c b/debug/test-stpcpy_chk.c +index 96ad600bc2760cbd..c3cb52d987f9db4f 100644 +--- a/debug/test-stpcpy_chk.c ++++ b/debug/test-stpcpy_chk.c +@@ -20,7 +20,7 @@ + #define STRCPY_RESULT(dst, len) ((dst) + (len)) + #define TEST_MAIN + #define TEST_NAME "stpcpy_chk" +-#include "../string/test-string.h" ++#include + + extern void __attribute__ ((noreturn)) __chk_fail (void); + char *simple_stpcpy_chk (char *, const char *, size_t); +diff --git a/debug/test-strcpy_chk.c b/debug/test-strcpy_chk.c +index 80c07482aaa54e3b..bb89e342caef470b 100644 +--- a/debug/test-strcpy_chk.c ++++ b/debug/test-strcpy_chk.c +@@ -21,7 +21,7 @@ + # define STRCPY_RESULT(dst, len) dst + # define TEST_MAIN + # define TEST_NAME "strcpy_chk" +-# include "../string/test-string.h" ++# include + + /* This test case implicitly tests the availability of the __chk_fail + symbol, which is part of the public ABI and may be used +diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c +index fb02452f5993c594..01a8703de1e6e09a 100644 +--- a/debug/tst-fortify.c ++++ b/debug/tst-fortify.c +@@ -24,6 +24,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -37,6 +38,10 @@ + #include + #include + #include ++#include ++ ++#include ++#include + + #ifndef _GNU_SOURCE + # define MEMPCPY memcpy +@@ -53,15 +58,10 @@ + #define obstack_chunk_alloc malloc + #define obstack_chunk_free free + +-char *temp_filename; +-static void do_prepare (void); +-static int do_test (void); +-#define PREPARE(argc, argv) do_prepare () +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" ++static char *temp_filename; + + static void +-do_prepare (void) ++do_prepare (int argc, char *argv[]) + { + int temp_fd = create_temp_file ("tst-chk1.", &temp_filename); + if (temp_fd == -1) +@@ -78,10 +78,11 @@ do_prepare (void) + exit (1); + } + } ++#define PREPARE do_prepare + +-volatile int chk_fail_ok; +-volatile int ret; +-jmp_buf chk_fail_buf; ++static volatile int chk_fail_ok; ++static volatile int ret; ++static jmp_buf chk_fail_buf; + + static void + handler (int sig) +@@ -103,22 +104,22 @@ wchar_t wbuf[10]; + #define buf_size sizeof (buf) + #endif + +-volatile size_t l0; +-volatile char *p; +-volatile wchar_t *wp; +-const char *str1 = "JIHGFEDCBA"; +-const char *str2 = "F"; +-const char *str3 = "%s%n%s%n"; +-const char *str4 = "Hello, "; +-const char *str5 = "World!\n"; +-const wchar_t *wstr1 = L"JIHGFEDCBA"; +-const wchar_t *wstr2 = L"F"; +-const wchar_t *wstr3 = L"%s%n%s%n"; +-const wchar_t *wstr4 = L"Hello, "; +-const wchar_t *wstr5 = L"World!\n"; +-char buf2[10] = "%s"; +-int num1 = 67; +-int num2 = 987654; ++static volatile size_t l0; ++static volatile char *p; ++static volatile wchar_t *wp; ++static const char *str1 = "JIHGFEDCBA"; ++static const char *str2 = "F"; ++static const char *str3 = "%s%n%s%n"; ++static const char *str4 = "Hello, "; ++static const char *str5 = "World!\n"; ++static const wchar_t *wstr1 = L"JIHGFEDCBA"; ++static const wchar_t *wstr2 = L"F"; ++static const wchar_t *wstr3 = L"%s%n%s%n"; ++static const wchar_t *wstr4 = L"Hello, "; ++static const wchar_t *wstr5 = L"World!\n"; ++static char buf2[10] = "%s"; ++static int num1 = 67; ++static int num2 = 987654; + + #define FAIL() \ + do { printf ("Failure on line %d\n", __LINE__); ret = 1; } while (0) +@@ -1763,3 +1764,5 @@ do_test (void) + + return ret; + } ++ ++#include +diff --git a/debug/tst-longjmp_chk.c b/debug/tst-longjmp_chk.c +index e4e93d2a36b537d9..37f858606be4c4a2 100644 +--- a/debug/tst-longjmp_chk.c ++++ b/debug/tst-longjmp_chk.c +@@ -10,11 +10,7 @@ + #include + #include + +- +-static int do_test(void); +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" +- ++#include + + static jmp_buf b; + +@@ -76,3 +72,5 @@ do_test (void) + puts ("second longjmp returned"); + return 1; + } ++ ++#include +diff --git a/debug/tst-longjmp_chk2.c b/debug/tst-longjmp_chk2.c +index 23d3436d1d26d2d1..69c1ab9db73f14ae 100644 +--- a/debug/tst-longjmp_chk2.c ++++ b/debug/tst-longjmp_chk2.c +@@ -12,9 +12,7 @@ + #include + #include + +-static int do_test (void); +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" ++#include + + static jmp_buf mainloop; + static sigset_t mainsigset; +@@ -128,3 +126,5 @@ do_test (void) + + return 0; + } ++ ++#include +diff --git a/debug/tst-longjmp_chk3.c b/debug/tst-longjmp_chk3.c +index 3155c7769fcbd83f..4434937c597dbe10 100644 +--- a/debug/tst-longjmp_chk3.c ++++ b/debug/tst-longjmp_chk3.c +@@ -20,10 +20,6 @@ + #include + #include + +-static int do_test (void); +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" +- + static char buf[SIGSTKSZ * 4]; + static jmp_buf jb; + +@@ -83,3 +79,5 @@ do_test (void) + puts ("longjmp returned and shouldn't"); + return 1; + } ++ ++#include diff --git a/SOURCES/glibc-RHEL-54447-2.patch b/SOURCES/glibc-RHEL-54447-2.patch new file mode 100644 index 0000000..1c39e95 --- /dev/null +++ b/SOURCES/glibc-RHEL-54447-2.patch @@ -0,0 +1,195 @@ +commit 388c9d7294e5ee3b741aef2e8af63eb1f76ace86 +Author: Maciej W. Rozycki +Date: Fri Jul 26 13:21:34 2024 +0100 + + support: Add FAIL test failure helper + + Add a FAIL test failure helper analogous to FAIL_RET, that does not + cause the current function to return, providing a standardized way to + report a test failure with a message supplied while permitting the + caller to continue executing, for further reporting, cleaning up, etc. + + Update existing test cases that provide a conflicting definition of FAIL + by removing the local FAIL definition and then as follows: + + - tst-fortify-syslog: provide a meaningful message in addition to the + file name already added by ; 'support_record_failure' + is already called by 'support_print_failure_impl' invoked by the new + FAIL test failure helper. + + - tst-ctype: no update to FAIL calls required, with the name of the file + and the line number within of the failure site additionally included + by the new FAIL test failure helper, and error counting plus count + reporting upon test program termination also already provided by + 'support_record_failure' and 'support_report_failure' respectively, + called by 'support_print_failure_impl' and 'adjust_exit_status' also + respectively. However in a number of places 'printf' is called and + the error count adjusted by hand, so update these places to make use + of FAIL instead. And last but not least adjust the final summary just + to report completion, with any error count following as reported by + the test driver. + + - test-tgmath2: no update to FAIL calls required, with the name of the + file of the failure site additionally included by the new FAIL test + failure helper. Also there is no need to track the return status by + hand as any call to FAIL will eventually cause the test case to return + an unsuccesful exit status regardless of the return status from the + test function, via a call to 'adjust_exit_status' made by the test + driver. + + Reviewed-by: DJ Delorie + (cherry picked from commit 1b97a9f23bf605ca608162089c94187573fb2a9e) + (cherry picked from commit 28f358bc4209ab0425170cdccf65bb1fe861148f) + +diff --git a/localedata/tst-ctype.c b/localedata/tst-ctype.c +index 1e4fa132bb4e17c6..f8645e31db8a1691 100644 +--- a/localedata/tst-ctype.c ++++ b/localedata/tst-ctype.c +@@ -22,6 +22,8 @@ + #include + #include + ++#include ++ + + static const char lower[] = "abcdefghijklmnopqrstuvwxyz"; + static const char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +@@ -54,19 +56,11 @@ static struct classes + #define nclasses (sizeof (classes) / sizeof (classes[0])) + + +-#define FAIL(str, args...) \ +- { \ +- printf (" " str "\n", ##args); \ +- ++errors; \ +- } +- +- + static int + do_test (void) + { + const char *cp; + const char *cp2; +- int errors = 0; + char *inpline = NULL; + size_t inplinelen = 0; + char *resline = NULL; +@@ -395,11 +389,8 @@ punct = %04x alnum = %04x\n", + { + if (((__ctype_b[(unsigned int) *inp] & classes[n].mask) != 0) + != (*resp != '0')) +- { +- printf (" is%s('%c' = '\\x%02x') %s true\n", inpline, +- *inp, *inp, *resp == '1' ? "not" : "is"); +- ++errors; +- } ++ FAIL (" is%s('%c' = '\\x%02x') %s true\n", inpline, ++ *inp, *inp, *resp == '1' ? "not" : "is"); + ++inp; + ++resp; + } +@@ -409,11 +400,8 @@ punct = %04x alnum = %04x\n", + while (*inp != '\0') + { + if (tolower (*inp) != *resp) +- { +- printf (" tolower('%c' = '\\x%02x') != '%c'\n", +- *inp, *inp, *resp); +- ++errors; +- } ++ FAIL (" tolower('%c' = '\\x%02x') != '%c'\n", ++ *inp, *inp, *resp); + ++inp; + ++resp; + } +@@ -423,11 +411,8 @@ punct = %04x alnum = %04x\n", + while (*inp != '\0') + { + if (toupper (*inp) != *resp) +- { +- printf (" toupper('%c' = '\\x%02x') != '%c'\n", +- *inp, *inp, *resp); +- ++errors; +- } ++ FAIL (" toupper('%c' = '\\x%02x') != '%c'\n", ++ *inp, *inp, *resp); + ++inp; + ++resp; + } +@@ -437,14 +422,7 @@ punct = %04x alnum = %04x\n", + } + + +- if (errors != 0) +- { +- printf (" %d error%s for `%s' locale\n\n\n", errors, +- errors == 1 ? "" : "s", setlocale (LC_ALL, NULL)); +- return 1; +- } +- +- printf (" No errors for `%s' locale\n\n\n", setlocale (LC_ALL, NULL)); ++ printf ("Completed testing for `%s' locale\n\n\n", setlocale (LC_ALL, NULL)); + return 0; + } + +diff --git a/math/test-tgmath2.c b/math/test-tgmath2.c +index b8fb00c566439ab0..e3b7a3a3615e083a 100644 +--- a/math/test-tgmath2.c ++++ b/math/test-tgmath2.c +@@ -25,6 +25,8 @@ + #include + #include + ++#include ++ + //#define DEBUG + + typedef complex float cfloat; +@@ -88,13 +90,6 @@ enum + int count; + int counts[Tlast][C_last]; + +-#define FAIL(str) \ +- do \ +- { \ +- printf ("%s failure on line %d\n", (str), __LINE__); \ +- result = 1; \ +- } \ +- while (0) + #define TEST_TYPE_ONLY(expr, rettype) \ + do \ + { \ +@@ -134,8 +129,6 @@ int counts[Tlast][C_last]; + int + test_cos (const int Vint4, const long long int Vllong4) + { +- int result = 0; +- + TEST (cos (vfloat1), float, cos); + TEST (cos (vdouble1), double, cos); + TEST (cos (vldouble1), ldouble, cos); +@@ -153,7 +146,7 @@ test_cos (const int Vint4, const long long int Vllong4) + TEST (cos (Vcdouble1), cdouble, cos); + TEST (cos (Vcldouble1), cldouble, cos); + +- return result; ++ return 0; + } + + int +diff --git a/support/check.h b/support/check.h +index 9b1844352f32513a..8e045dd9c0c36b4c 100644 +--- a/support/check.h ++++ b/support/check.h +@@ -24,6 +24,11 @@ + + __BEGIN_DECLS + ++/* Record a test failure, print the failure message to standard output ++ and pass the result of 1 through. */ ++#define FAIL(...) \ ++ support_print_failure_impl (__FILE__, __LINE__, __VA_ARGS__) ++ + /* Record a test failure, print the failure message to standard output + and return 1. */ + #define FAIL_RET(...) \ diff --git a/SOURCES/glibc-RHEL-54447-3.patch b/SOURCES/glibc-RHEL-54447-3.patch new file mode 100644 index 0000000..a7b2bdd --- /dev/null +++ b/SOURCES/glibc-RHEL-54447-3.patch @@ -0,0 +1,169 @@ +commit 86f5cfe77d60ca4f78f270adc7ae2c15a1d8d4bc +Author: Maciej W. Rozycki +Date: Fri Jul 26 13:21:34 2024 +0100 + + stdio-common: Add test for vfscanf with matches longer than INT_MAX [BZ #27650] + + Complement commit b03e4d7bd25b ("stdio: fix vfscanf with matches longer + than INT_MAX (bug 27650)") and add a test case for the issue, inspired + by the reproducer provided with the bug report. + + This has been verified to succeed as from the commit referred and fail + beforehand. + + As the test requires 2GiB of data to be passed around its performance + has been evaluated using a choice of systems and the execution time + determined to be respectively in the range of 9s for POWER9@2.166GHz, + 24s for FU740@1.2GHz, and 40s for 74Kf@950MHz. As this is on the verge + of and beyond the default timeout it has been increased by the factor of + 8. Regardless, following recent practice the test has been added to the + standard rather than extended set. + + Reviewed-by: DJ Delorie + (cherry picked from commit 89cddc8a7096f3d9225868304d2bc0a1aaf07d63) + (cherry picked from commit 99ffa84bdcdc3d81e82f448279f0c8278dd30964) + +diff --git a/stdio-common/Makefile b/stdio-common/Makefile +index 76d1d0a1193aa109..08bedd01be61a55d 100644 +--- a/stdio-common/Makefile ++++ b/stdio-common/Makefile +@@ -190,6 +190,7 @@ tests := \ + tst-put-error \ + tst-renameat2 \ + tst-rndseek \ ++ tst-scanf-bz27650 \ + tst-scanf-round \ + tst-setvbuf1 \ + tst-sprintf \ +@@ -241,6 +242,7 @@ generated += \ + tst-printf-fp-free.mtrace \ + tst-printf-fp-leak-mem.out \ + tst-printf-fp-leak.mtrace \ ++ tst-scanf-bz27650.mtrace \ + tst-vfprintf-width-prec-mem.out \ + tst-vfprintf-width-prec.mtrace \ + # generated +@@ -283,6 +285,9 @@ tst-printf-fp-free-ENV = \ + tst-printf-fp-leak-ENV = \ + MALLOC_TRACE=$(objpfx)tst-printf-fp-leak.mtrace \ + LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so ++tst-scanf-bz27650-ENV = \ ++ MALLOC_TRACE=$(objpfx)tst-scanf-bz27650.mtrace \ ++ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so + + $(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc + $(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \ +diff --git a/stdio-common/tst-scanf-bz27650.c b/stdio-common/tst-scanf-bz27650.c +new file mode 100644 +index 0000000000000000..3a742bc86556908c +--- /dev/null ++++ b/stdio-common/tst-scanf-bz27650.c +@@ -0,0 +1,108 @@ ++/* Test for BZ #27650, formatted input matching beyond INT_MAX. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++/* Produce a stream of more than INT_MAX characters via buffer BUF of ++ size SIZE according to bookkeeping in COOKIE and then return EOF. */ ++ ++static ssize_t ++io_read (void *cookie, char *buf, size_t size) ++{ ++ unsigned int *written = cookie; ++ unsigned int w = *written; ++ ++ if (w > INT_MAX) ++ return 0; ++ ++ memset (buf, 'a', size); ++ *written = w + size; ++ return size; ++} ++ ++/* Consume a stream of more than INT_MAX characters from an artificial ++ input stream of which none is the new line character. The call to ++ fscanf is supposed to complete upon the EOF condition of input, ++ however in the presence of BZ #27650 it will terminate prematurely ++ with characters still outstanding in input. Diagnose the condition ++ and return status accordingly. */ ++ ++int ++do_test (void) ++{ ++ static cookie_io_functions_t io_funcs = { .read = io_read }; ++ unsigned int written = 0; ++ FILE *in; ++ int v; ++ ++ mtrace (); ++ ++ in = fopencookie (&written, "r", io_funcs); ++ if (in == NULL) ++ { ++ FAIL ("fopencookie: %m"); ++ goto out; ++ } ++ ++ v = fscanf (in, "%*[^\n]"); ++ if (ferror (in)) ++ { ++ FAIL ("fscanf: input failure, at %u: %m", written); ++ goto out_close; ++ } ++ else if (v == EOF) ++ { ++ FAIL ("fscanf: unexpected end of file, at %u", written); ++ goto out_close; ++ } ++ ++ if (!feof (in)) ++ { ++ v = fgetc (in); ++ if (ferror (in)) ++ FAIL ("fgetc: input failure: %m"); ++ else if (v == EOF) ++ FAIL ("fgetc: unexpected end of file after missing end of file"); ++ else if (v == '\n') ++ FAIL ("unexpected new line character received"); ++ else ++ FAIL ("character received after end of file expected: \\x%02x", v); ++ } ++ ++out_close: ++ if (fclose (in) != 0) ++ FAIL ("fclose: %m"); ++ ++out: ++ return EXIT_SUCCESS; ++} ++ ++#define TIMEOUT (DEFAULT_TIMEOUT * 8) ++#include diff --git a/SOURCES/glibc-RHEL-54447-4.patch b/SOURCES/glibc-RHEL-54447-4.patch new file mode 100644 index 0000000..525ce22 --- /dev/null +++ b/SOURCES/glibc-RHEL-54447-4.patch @@ -0,0 +1,143 @@ +commit af68f0f6755c3b82ecef6dd67079df64eee8d946 +Author: Siddhesh Poyarekar +Date: Wed Aug 14 19:20:04 2024 -0400 + + Make tst-ungetc use libsupport + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Carlos O'Donell + (cherry picked from commit 3f7df7e757f4efec38e45d4068e5492efcac4856) + (cherry picked from commit 87a1968a72e4b4e5436f3e2be1ed8a8d5a5862c7) + +diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c +index 1344b2b591e3d6b1..5c808f073419f00b 100644 +--- a/stdio-common/tst-ungetc.c ++++ b/stdio-common/tst-ungetc.c +@@ -1,70 +1,72 @@ +-/* Test for ungetc bugs. */ ++/* Test for ungetc bugs. ++ Copyright (C) 1996-2024 Free Software Foundation, Inc. ++ Copyright The GNU Toolchain Authors. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ + + #include + #include +-#include +- +-#undef assert +-#define assert(x) \ +- if (!(x)) \ +- { \ +- fputs ("test failed: " #x "\n", stderr); \ +- retval = 1; \ +- goto the_end; \ +- } ++#include ++#include ++#include ++#include ++#include + +-int +-main (int argc, char *argv[]) ++static int ++do_test (void) + { +- char name[] = "/tmp/tst-ungetc.XXXXXX"; ++ char *name = NULL; + FILE *fp = NULL; +- int retval = 0; + int c; + char buffer[64]; + +- int fd = mkstemp (name); ++ int fd = create_temp_file ("tst-ungetc.", &name); + if (fd == -1) +- { +- printf ("mkstemp failed: %m\n"); +- return 1; +- } +- close (fd); +- fp = fopen (name, "w"); +- assert (fp != NULL) +- fputs ("bla", fp); +- fclose (fp); +- fp = NULL; ++ FAIL_EXIT1 ("cannot create temporary file: %m"); ++ xclose (fd); + +- fp = fopen (name, "r"); +- assert (fp != NULL); +- assert (ungetc ('z', fp) == 'z'); +- assert (getc (fp) == 'z'); +- assert (getc (fp) == 'b'); +- assert (getc (fp) == 'l'); +- assert (ungetc ('m', fp) == 'm'); +- assert (getc (fp) == 'm'); +- assert ((c = getc (fp)) == 'a'); +- assert (getc (fp) == EOF); +- assert (ungetc (c, fp) == c); +- assert (feof (fp) == 0); +- assert (getc (fp) == c); +- assert (getc (fp) == EOF); +- fclose (fp); +- fp = NULL; ++ fp = xfopen (name, "w"); ++ fputs ("bla", fp); ++ xfclose (fp); + +- fp = fopen (name, "r"); +- assert (fp != NULL); +- assert (getc (fp) == 'b'); +- assert (getc (fp) == 'l'); +- assert (ungetc ('b', fp) == 'b'); +- assert (fread (buffer, 1, 64, fp) == 2); +- assert (buffer[0] == 'b'); +- assert (buffer[1] == 'a'); ++ fp = xfopen (name, "r"); ++ TEST_VERIFY_EXIT (ungetc ('z', fp) == 'z'); ++ TEST_VERIFY_EXIT (getc (fp) == 'z'); ++ TEST_VERIFY_EXIT (getc (fp) == 'b'); ++ TEST_VERIFY_EXIT (getc (fp) == 'l'); ++ TEST_VERIFY_EXIT (ungetc ('m', fp) == 'm'); ++ TEST_VERIFY_EXIT (getc (fp) == 'm'); ++ TEST_VERIFY_EXIT ((c = getc (fp)) == 'a'); ++ TEST_VERIFY_EXIT (getc (fp) == EOF); ++ TEST_VERIFY_EXIT (ungetc (c, fp) == c); ++ TEST_VERIFY_EXIT (feof (fp) == 0); ++ TEST_VERIFY_EXIT (getc (fp) == c); ++ TEST_VERIFY_EXIT (getc (fp) == EOF); ++ xfclose (fp); + +-the_end: +- if (fp != NULL) +- fclose (fp); +- unlink (name); ++ fp = xfopen (name, "r"); ++ TEST_VERIFY_EXIT (getc (fp) == 'b'); ++ TEST_VERIFY_EXIT (getc (fp) == 'l'); ++ TEST_VERIFY_EXIT (ungetc ('b', fp) == 'b'); ++ TEST_VERIFY_EXIT (fread (buffer, 1, 64, fp) == 2); ++ TEST_VERIFY_EXIT (buffer[0] == 'b'); ++ TEST_VERIFY_EXIT (buffer[1] == 'a'); ++ xfclose (fp); + +- return retval; ++ return 0; + } ++ ++#include diff --git a/SOURCES/glibc-RHEL-54447-5.patch b/SOURCES/glibc-RHEL-54447-5.patch new file mode 100644 index 0000000..d2d72aa --- /dev/null +++ b/SOURCES/glibc-RHEL-54447-5.patch @@ -0,0 +1,71 @@ +commit 01a731da41a6d47cdd6b90f0da1d89dd8cf2b9cd +Author: Siddhesh Poyarekar +Date: Tue Aug 13 21:00:06 2024 -0400 + + ungetc: Fix uninitialized read when putting into unused streams [BZ #27821] + + When ungetc is called on an unused stream, the backup buffer is + allocated without the main get area being present. This results in + every subsequent ungetc (as the stream remains in the backup area) + checking uninitialized memory in the backup buffer when trying to put a + character back into the stream. + + Avoid comparing the input character with buffer contents when in backup + to avoid this uninitialized read. The uninitialized read is harmless in + this context since the location is promptly overwritten with the input + character, thus fulfilling ungetc functionality. + + Also adjust wording in the manual to drop the paragraph that says glibc + cannot do multiple ungetc back to back since with this change, ungetc + can actually do this. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Carlos O'Donell + (cherry picked from commit cdf0f88f97b0aaceb894cc02b21159d148d7065c) + (cherry picked from commit 804d3c8db79db204154dcf5e11a76f14fdddc570) + +diff --git a/libio/genops.c b/libio/genops.c +index fa509f6219abaf23..a5dd6a06d9e259d8 100644 +--- a/libio/genops.c ++++ b/libio/genops.c +@@ -635,7 +635,7 @@ _IO_sputbackc (FILE *fp, int c) + { + int result; + +- if (fp->_IO_read_ptr > fp->_IO_read_base ++ if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp) + && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c) + { + fp->_IO_read_ptr--; +diff --git a/manual/stdio.texi b/manual/stdio.texi +index d3d855fc62b8768b..60ab7e7a5d505bb6 100644 +--- a/manual/stdio.texi ++++ b/manual/stdio.texi +@@ -1467,11 +1467,9 @@ program; usually @code{ungetc} is used only to unread a character that + was just read from the same stream. @Theglibc{} supports this + even on files opened in binary mode, but other systems might not. + +-@Theglibc{} only supports one character of pushback---in other +-words, it does not work to call @code{ungetc} twice without doing input +-in between. Other systems might let you push back multiple characters; +-then reading from the stream retrieves the characters in the reverse +-order that they were pushed. ++@Theglibc{} supports pushing back multiple characters; subsequently ++reading from the stream retrieves the characters in the reverse order ++that they were pushed. + + Pushing back characters doesn't alter the file; only the internal + buffering for the stream is affected. If a file positioning function +diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c +index 5c808f073419f00b..388b202493ddd586 100644 +--- a/stdio-common/tst-ungetc.c ++++ b/stdio-common/tst-ungetc.c +@@ -48,6 +48,8 @@ do_test (void) + TEST_VERIFY_EXIT (getc (fp) == 'b'); + TEST_VERIFY_EXIT (getc (fp) == 'l'); + TEST_VERIFY_EXIT (ungetc ('m', fp) == 'm'); ++ TEST_VERIFY_EXIT (ungetc ('n', fp) == 'n'); ++ TEST_VERIFY_EXIT (getc (fp) == 'n'); + TEST_VERIFY_EXIT (getc (fp) == 'm'); + TEST_VERIFY_EXIT ((c = getc (fp)) == 'a'); + TEST_VERIFY_EXIT (getc (fp) == EOF); diff --git a/SOURCES/glibc-RHEL-54447-6.patch b/SOURCES/glibc-RHEL-54447-6.patch new file mode 100644 index 0000000..006e312 --- /dev/null +++ b/SOURCES/glibc-RHEL-54447-6.patch @@ -0,0 +1,136 @@ +commit a5cd39541396b91d90cc611858ee7b3355fcfe47 +Author: Siddhesh Poyarekar +Date: Tue Aug 13 21:08:49 2024 -0400 + + ungetc: Fix backup buffer leak on program exit [BZ #27821] + + If a file descriptor is left unclosed and is cleaned up by _IO_cleanup + on exit, its backup buffer remains unfreed, registering as a leak in + valgrind. This is not strictly an issue since (1) the program should + ideally be closing the stream once it's not in use and (2) the program + is about to exit anyway, so keeping the backup buffer around a wee bit + longer isn't a real problem. Free it anyway to keep valgrind happy + when the streams in question are the standard ones, i.e. stdout, stdin + or stderr. + + Also, the _IO_have_backup macro checks for _IO_save_base, + which is a roundabout way to check for a backup buffer instead of + directly looking for _IO_backup_base. The roundabout check breaks when + the main get area has not been used and user pushes a char into the + backup buffer with ungetc. Fix this to use the _IO_backup_base + directly. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Carlos O'Donell + (cherry picked from commit 3e1d8d1d1dca24ae90df2ea826a8916896fc7e77) + (cherry picked from commit b9f72bd5de931eac39219018c2fa319a449bb2cf) + +diff --git a/libio/genops.c b/libio/genops.c +index a5dd6a06d9e259d8..b5fc53fd1ef6e911 100644 +--- a/libio/genops.c ++++ b/libio/genops.c +@@ -796,6 +796,12 @@ _IO_unbuffer_all (void) + legacy = 1; + #endif + ++ /* Free up the backup area if it was ever allocated. */ ++ if (_IO_have_backup (fp)) ++ _IO_free_backup_area (fp); ++ if (fp->_mode > 0 && _IO_have_wbackup (fp)) ++ _IO_free_wbackup_area (fp); ++ + if (! (fp->_flags & _IO_UNBUFFERED) + /* Iff stream is un-orientated, it wasn't used. */ + && (legacy || fp->_mode != 0)) +diff --git a/libio/libioP.h b/libio/libioP.h +index dc9a2ce9c8d7744c..bab5f3770f0760c4 100644 +--- a/libio/libioP.h ++++ b/libio/libioP.h +@@ -529,8 +529,8 @@ extern void _IO_old_init (FILE *fp, int flags) __THROW; + ((__fp)->_wide_data->_IO_write_base \ + = (__fp)->_wide_data->_IO_write_ptr = __p, \ + (__fp)->_wide_data->_IO_write_end = (__ep)) +-#define _IO_have_backup(fp) ((fp)->_IO_save_base != NULL) +-#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_save_base != NULL) ++#define _IO_have_backup(fp) ((fp)->_IO_backup_base != NULL) ++#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_backup_base != NULL) + #define _IO_in_backup(fp) ((fp)->_flags & _IO_IN_BACKUP) + #define _IO_have_markers(fp) ((fp)->_markers != NULL) + #define _IO_blen(fp) ((fp)->_IO_buf_end - (fp)->_IO_buf_base) +diff --git a/stdio-common/Makefile b/stdio-common/Makefile +index 08bedd01be61a55d..f10bf28878e0aebc 100644 +--- a/stdio-common/Makefile ++++ b/stdio-common/Makefile +@@ -201,6 +201,7 @@ tests := \ + tst-swscanf \ + tst-tmpnam \ + tst-ungetc \ ++ tst-ungetc-leak \ + tst-unlockedio \ + tst-vfprintf-mbs-prec \ + tst-vfprintf-user-type \ +@@ -229,6 +230,7 @@ tests-special += \ + $(objpfx)tst-printfsz-islongdouble.out \ + $(objpfx)tst-setvbuf1-cmp.out \ + $(objpfx)tst-unbputc.out \ ++ $(objpfx)tst-ungetc-leak-mem.out \ + $(objpfx)tst-vfprintf-width-prec-mem.out \ + # tests-special + +@@ -243,6 +245,8 @@ generated += \ + tst-printf-fp-leak-mem.out \ + tst-printf-fp-leak.mtrace \ + tst-scanf-bz27650.mtrace \ ++ tst-ungetc-leak-mem.out \ ++ tst-ungetc-leak.mtrace \ + tst-vfprintf-width-prec-mem.out \ + tst-vfprintf-width-prec.mtrace \ + # generated +@@ -288,6 +292,9 @@ tst-printf-fp-leak-ENV = \ + tst-scanf-bz27650-ENV = \ + MALLOC_TRACE=$(objpfx)tst-scanf-bz27650.mtrace \ + LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so ++tst-ungetc-leak-ENV = \ ++ MALLOC_TRACE=$(objpfx)tst-ungetc-leak.mtrace \ ++ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so + + $(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc + $(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \ +diff --git a/stdio-common/tst-ungetc-leak.c b/stdio-common/tst-ungetc-leak.c +new file mode 100644 +index 0000000000000000..6c5152b43f80b217 +--- /dev/null ++++ b/stdio-common/tst-ungetc-leak.c +@@ -0,0 +1,32 @@ ++/* Test for memory leak with ungetc when stream is unused. ++ Copyright The GNU Toolchain Authors. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ mtrace (); ++ TEST_COMPARE (ungetc('y', stdin), 'y'); ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-RHEL-54447-7.patch b/SOURCES/glibc-RHEL-54447-7.patch new file mode 100644 index 0000000..9446d2a --- /dev/null +++ b/SOURCES/glibc-RHEL-54447-7.patch @@ -0,0 +1,83 @@ +commit 9d26e50364def249e483b1601beb6ecf9141ecc7 +Author: Maciej W. Rozycki +Date: Fri Jul 26 13:21:34 2024 +0100 + + posix: Use facilities in tst-truncate and tst-truncate64 + + Remove local FAIL macro in favor to FAIL_RET from , + which provides equivalent reporting, with the name of the file of the + failure site additionally included, for the tst-truncate-common core + shared between the tst-truncate and tst-truncate64 tests. + + Reviewed-by: DJ Delorie + (cherry picked from commit fe47595504a55e7bb992f8928533df154b510383) + +diff --git a/posix/tst-truncate-common.c b/posix/tst-truncate-common.c +index 00c999d372693bfa..1f6c4bd256a638f9 100644 +--- a/posix/tst-truncate-common.c ++++ b/posix/tst-truncate-common.c +@@ -21,6 +21,8 @@ + #include + #include + ++#include ++ + static void do_prepare (void); + #define PREPARE(argc, argv) do_prepare () + static int do_test (void); +@@ -42,9 +44,6 @@ do_prepare (void) + } + } + +-#define FAIL(str) \ +- do { printf ("error: %s (line %d)\n", str, __LINE__); return 1; } while (0) +- + static int + do_test_with_offset (off_t offset) + { +@@ -54,35 +53,35 @@ do_test_with_offset (off_t offset) + memset (buf, 0xcf, sizeof (buf)); + + if (pwrite (temp_fd, buf, sizeof (buf), offset) != sizeof (buf)) +- FAIL ("write failed"); ++ FAIL_RET ("write failed"); + if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + sizeof (buf))) +- FAIL ("initial size wrong"); ++ FAIL_RET ("initial size wrong"); + + if (ftruncate (temp_fd, offset + 800) < 0) +- FAIL ("size reduction with ftruncate failed"); ++ FAIL_RET ("size reduction with ftruncate failed"); + if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800)) +- FAIL ("size after reduction with ftruncate is incorrect"); ++ FAIL_RET ("size after reduction with ftruncate is incorrect"); + + /* The following test covers more than POSIX. POSIX does not require + that ftruncate() can increase the file size. But we are testing + Unix systems. */ + if (ftruncate (temp_fd, offset + 1200) < 0) +- FAIL ("size increate with ftruncate failed"); ++ FAIL_RET ("size increate with ftruncate failed"); + if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200)) +- FAIL ("size after increase is incorrect"); ++ FAIL_RET ("size after increase is incorrect"); + + if (truncate (temp_filename, offset + 800) < 0) +- FAIL ("size reduction with truncate failed"); ++ FAIL_RET ("size reduction with truncate failed"); + if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800)) +- FAIL ("size after reduction with truncate incorrect"); ++ FAIL_RET ("size after reduction with truncate incorrect"); + + /* The following test covers more than POSIX. POSIX does not require + that truncate() can increase the file size. But we are testing + Unix systems. */ + if (truncate (temp_filename, (offset + 1200)) < 0) +- FAIL ("size increase with truncate failed"); ++ FAIL_RET ("size increase with truncate failed"); + if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200)) +- FAIL ("size increase with truncate is incorrect"); ++ FAIL_RET ("size increase with truncate is incorrect"); + + return 0; + } diff --git a/SOURCES/glibc-RHEL-54447-8.patch b/SOURCES/glibc-RHEL-54447-8.patch new file mode 100644 index 0000000..b4e804f --- /dev/null +++ b/SOURCES/glibc-RHEL-54447-8.patch @@ -0,0 +1,129 @@ +commit c21ca2a696c03ff3f3931768a3ada234eebf6337 +Author: Maciej W. Rozycki +Date: Fri Jul 26 13:21:34 2024 +0100 + + nptl: Use facilities in tst-setuid3 + + Remove local FAIL macro in favor to FAIL_EXIT1 from , + which provides equivalent reporting, with the name of the file and the + line number within of the failure site additionally included. Remove + FAIL_ERR altogether and include ": %m" explicitly with the format string + supplied to FAIL_EXIT1 as there seems little value to have a separate + macro just for this. + + Reviewed-by: DJ Delorie + (cherry picked from commit 8c98195af6e6f1ce21743fc26c723e0f7e45bcf2) + +diff --git a/sysdeps/pthread/tst-setuid3.c b/sysdeps/pthread/tst-setuid3.c +index 254555960e1ffe74..88a2a3ef20e273f7 100644 +--- a/sysdeps/pthread/tst-setuid3.c ++++ b/sysdeps/pthread/tst-setuid3.c +@@ -15,24 +15,19 @@ + License along with the GNU C Library; if not, see + . */ + +-#include + #include + #include + #include + #include + ++#include ++ + /* The test must run under a non-privileged user ID. */ + static const uid_t test_uid = 1; + + static pthread_barrier_t barrier1; + static pthread_barrier_t barrier2; + +-#define FAIL(fmt, ...) \ +- do { printf ("FAIL: " fmt "\n", __VA_ARGS__); _exit (1); } while (0) +- +-#define FAIL_ERR(fmt, ...) \ +- do { printf ("FAIL: " fmt ": %m\n", __VA_ARGS__); _exit (1); } while (0) +- + /* True if x is not a successful return code from pthread_barrier_wait. */ + static inline bool + is_invalid_barrier_ret (int x) +@@ -45,10 +40,10 @@ thread_func (void *ctx __attribute__ ((unused))) + { + int ret = pthread_barrier_wait (&barrier1); + if (is_invalid_barrier_ret (ret)) +- FAIL ("pthread_barrier_wait (barrier1) (on thread): %d", ret); ++ FAIL_EXIT1 ("pthread_barrier_wait (barrier1) (on thread): %d", ret); + ret = pthread_barrier_wait (&barrier2); + if (is_invalid_barrier_ret (ret)) +- FAIL ("pthread_barrier_wait (barrier2) (on thread): %d", ret); ++ FAIL_EXIT1 ("pthread_barrier_wait (barrier2) (on thread): %d", ret); + return NULL; + } + +@@ -59,13 +54,13 @@ setuid_failure (int phase) + switch (ret) + { + case 0: +- FAIL ("setuid succeeded unexpectedly in phase %d", phase); ++ FAIL_EXIT1 ("setuid succeeded unexpectedly in phase %d", phase); + case -1: + if (errno != EPERM) +- FAIL_ERR ("setuid phase %d", phase); ++ FAIL_EXIT1 ("setuid phase %d: %m", phase); + break; + default: +- FAIL ("invalid setuid return value in phase %d: %d", phase, ret); ++ FAIL_EXIT1 ("invalid setuid return value in phase %d: %d", phase, ret); + } + } + +@@ -74,42 +69,42 @@ do_test (void) + { + if (getuid () == 0) + if (setuid (test_uid) != 0) +- FAIL_ERR ("setuid (%u)", (unsigned) test_uid); ++ FAIL_EXIT1 ("setuid (%u): %m", (unsigned) test_uid); + if (setuid (getuid ())) +- FAIL_ERR ("setuid (%s)", "getuid ()"); ++ FAIL_EXIT1 ("setuid (%s): %m", "getuid ()"); + setuid_failure (1); + + int ret = pthread_barrier_init (&barrier1, NULL, 2); + if (ret != 0) +- FAIL ("pthread_barrier_init (barrier1): %d", ret); ++ FAIL_EXIT1 ("pthread_barrier_init (barrier1): %d", ret); + ret = pthread_barrier_init (&barrier2, NULL, 2); + if (ret != 0) +- FAIL ("pthread_barrier_init (barrier2): %d", ret); ++ FAIL_EXIT1 ("pthread_barrier_init (barrier2): %d", ret); + + pthread_t thread; + ret = pthread_create (&thread, NULL, thread_func, NULL); + if (ret != 0) +- FAIL ("pthread_create: %d", ret); ++ FAIL_EXIT1 ("pthread_create: %d", ret); + + /* Ensure that the thread is running properly. */ + ret = pthread_barrier_wait (&barrier1); + if (is_invalid_barrier_ret (ret)) +- FAIL ("pthread_barrier_wait (barrier1): %d", ret); ++ FAIL_EXIT1 ("pthread_barrier_wait (barrier1): %d", ret); + + setuid_failure (2); + + /* Check success case. */ + if (setuid (getuid ()) != 0) +- FAIL_ERR ("setuid (%s)", "getuid ()"); ++ FAIL_EXIT1 ("setuid (%s): %m", "getuid ()"); + + /* Shutdown. */ + ret = pthread_barrier_wait (&barrier2); + if (is_invalid_barrier_ret (ret)) +- FAIL ("pthread_barrier_wait (barrier2): %d", ret); ++ FAIL_EXIT1 ("pthread_barrier_wait (barrier2): %d", ret); + + ret = pthread_join (thread, NULL); + if (ret != 0) +- FAIL ("pthread_join: %d", ret); ++ FAIL_EXIT1 ("pthread_join: %d", ret); + + return 0; + } diff --git a/SOURCES/glibc-RHEL-54447-9.patch b/SOURCES/glibc-RHEL-54447-9.patch new file mode 100644 index 0000000..18e63df --- /dev/null +++ b/SOURCES/glibc-RHEL-54447-9.patch @@ -0,0 +1,27 @@ +commit ae4d44b1d501421ad9a3af95279b8f4d1546f1ce +Author: Siddhesh Poyarekar +Date: Tue Sep 3 14:58:33 2024 -0400 + + libio: Attempt wide backup free only for non-legacy code + + _wide_data and _mode are not available in legacy code, so do not attempt + to free the wide backup buffer in legacy code. + + Resolves: BZ #32137 and BZ #27821 + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Florian Weimer + +diff --git a/libio/genops.c b/libio/genops.c +index b5fc53fd1ef6e911..99ef9d03505f3238 100644 +--- a/libio/genops.c ++++ b/libio/genops.c +@@ -799,7 +799,7 @@ _IO_unbuffer_all (void) + /* Free up the backup area if it was ever allocated. */ + if (_IO_have_backup (fp)) + _IO_free_backup_area (fp); +- if (fp->_mode > 0 && _IO_have_wbackup (fp)) ++ if (!legacy && fp->_mode > 0 && _IO_have_wbackup (fp)) + _IO_free_wbackup_area (fp); + + if (! (fp->_flags & _IO_UNBUFFERED)