Compare commits

...

No commits in common. 'c9' and 'c9-beta' have entirely different histories.
c9 ... c9-beta

@ -1,369 +0,0 @@
From 317f1c0a8a71a862b1e600ff5386b08e02cf4b95 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 26 Jan 2023 08:26:18 -0800
Subject: [PATCH] x86-64: Add glibc.cpu.prefer_map_32bit_exec [BZ #28656]
Content-type: text/plain; charset=UTF-8
Crossing 2GB boundaries with indirect calls and jumps can use more
branch prediction resources on Intel Golden Cove CPU (see the
"Misprediction for Branches >2GB" section in Intel 64 and IA-32
Architectures Optimization Reference Manual.) There is visible
performance improvement on workloads with many PLT calls when executable
and shared libraries are mmapped below 2GB. Add the Prefer_MAP_32BIT_EXEC
bit so that mmap will try to map executable or denywrite pages in shared
libraries with MAP_32BIT first.
NB: Prefer_MAP_32BIT_EXEC reduces bits available for address space
layout randomization (ASLR), which is always disabled for SUID programs
and can only be enabled by the tunable, glibc.cpu.prefer_map_32bit_exec,
or the environment variable, LD_PREFER_MAP_32BIT_EXEC. This works only
between shared libraries or between shared libraries and executables with
addresses below 2GB. PIEs are usually loaded at a random address above
4GB by the kernel.
Conflicts:
manual/tunables.texi
(line numbers)
sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
(merged local @order list)
sysdeps/x86/cpu-features.c
(line numbers)
---
manual/tunables.texi | 33 ++++++++++----
sysdeps/unix/sysv/linux/x86_64/64/Makefile | 25 +++++++++++
.../sysv/linux/x86_64/64/dl-tunables.list | 29 +++++++++++++
.../unix/sysv/linux/x86_64/64/mmap_internal.h | 43 +++++++++++++++++++
.../sysv/linux/x86_64/64/tst-map-32bit-1a.c | 34 +++++++++++++++
.../sysv/linux/x86_64/64/tst-map-32bit-1b.c | 1 +
.../sysv/linux/x86_64/64/tst-map-32bit-mod.c | 33 ++++++++++++++
sysdeps/x86/cpu-features.c | 15 +++++++
...cpu-features-preferred_feature_index_1.def | 1 +
9 files changed, 205 insertions(+), 9 deletions(-)
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c
diff --git a/manual/tunables.texi b/manual/tunables.texi
index 0be7231e36..c76c5c53cd 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -35,27 +35,32 @@ tunables with minimum and maximum values:
@example
$ /lib64/ld-linux-x86-64.so.2 --list-tunables
glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
-glibc.elision.skip_lock_after_retries: 3 (min: -2147483648, max: 2147483647)
+glibc.elision.skip_lock_after_retries: 3 (min: 0, max: 2147483647)
glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0xffffffffffffffff)
glibc.malloc.perturb: 0 (min: 0, max: 255)
glibc.cpu.x86_shared_cache_size: 0x100000 (min: 0x0, max: 0xffffffffffffffff)
+glibc.pthread.rseq: 1 (min: 0, max: 1)
+glibc.cpu.prefer_map_32bit_exec: 0 (min: 0, max: 1)
glibc.mem.tagging: 0 (min: 0, max: 255)
-glibc.elision.tries: 3 (min: -2147483648, max: 2147483647)
+glibc.elision.tries: 3 (min: 0, max: 2147483647)
glibc.elision.enable: 0 (min: 0, max: 1)
-glibc.cpu.x86_rep_movsb_threshold: 0x1000 (min: 0x100, max: 0xffffffffffffffff)
+glibc.malloc.hugetlb: 0x0 (min: 0x0, max: 0xffffffffffffffff)
+glibc.cpu.x86_rep_movsb_threshold: 0x2000 (min: 0x100, max: 0xffffffffffffffff)
glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0xffffffffffffffff)
-glibc.elision.skip_lock_busy: 3 (min: -2147483648, max: 2147483647)
-glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0xffffffffffffffff)
+glibc.rtld.dynamic_sort: 2 (min: 1, max: 2)
+glibc.elision.skip_lock_busy: 3 (min: 0, max: 2147483647)
+glibc.malloc.top_pad: 0x20000 (min: 0x0, max: 0xffffffffffffffff)
glibc.cpu.x86_rep_stosb_threshold: 0x800 (min: 0x1, max: 0xffffffffffffffff)
-glibc.cpu.x86_non_temporal_threshold: 0xc0000 (min: 0x4040, max: 0x0fffffffffffffff)
+glibc.cpu.x86_non_temporal_threshold: 0xc0000 (min: 0x4040, max: 0xfffffffffffffff)
glibc.cpu.x86_shstk:
+glibc.pthread.stack_cache_size: 0x2800000 (min: 0x0, max: 0xffffffffffffffff)
glibc.cpu.hwcap_mask: 0x6 (min: 0x0, max: 0xffffffffffffffff)
-glibc.malloc.mmap_max: 0 (min: -2147483648, max: 2147483647)
-glibc.elision.skip_trylock_internal_abort: 3 (min: -2147483648, max: 2147483647)
+glibc.malloc.mmap_max: 0 (min: 0, max: 2147483647)
+glibc.elision.skip_trylock_internal_abort: 3 (min: 0, max: 2147483647)
glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0xffffffffffffffff)
glibc.cpu.x86_ibt:
glibc.cpu.hwcaps:
-glibc.elision.skip_lock_internal_abort: 3 (min: -2147483648, max: 2147483647)
+glibc.elision.skip_lock_internal_abort: 3 (min: 0, max: 2147483647)
glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0xffffffffffffffff)
glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0xffffffffffffffff)
glibc.cpu.x86_data_cache_size: 0x8000 (min: 0x0, max: 0xffffffffffffffff)
@@ -569,6 +574,16 @@ instead.
This tunable is specific to i386 and x86-64.
@end deftp
+@deftp Tunable glibc.cpu.prefer_map_32bit_exec
+When this tunable is set to \code{1}, shared libraries of non-setuid
+programs will be loaded below 2GB with MAP_32BIT.
+
+Note that the @env{LD_PREFER_MAP_32BIT_EXEC} environment is an alias of
+this tunable.
+
+This tunable is specific to 64-bit x86-64.
+@end deftp
+
@node Memory Related Tunables
@section Memory Related Tunables
@cindex memory related tunables
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/Makefile b/sysdeps/unix/sysv/linux/x86_64/64/Makefile
index a7b6dc5a53..8ff4f27786 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/Makefile
+++ b/sysdeps/unix/sysv/linux/x86_64/64/Makefile
@@ -1,2 +1,27 @@
# The default ABI is 64.
default-abi := 64
+
+ifeq ($(subdir),elf)
+ifneq ($(have-tunables),no)
+
+tests-map-32bit = \
+ tst-map-32bit-1a \
+ tst-map-32bit-1b \
+# tests-map-32bit
+tst-map-32bit-1a-no-pie = yes
+tst-map-32bit-1b-no-pie = yes
+tests += $(tests-map-32bit)
+
+modules-map-32bit = \
+ tst-map-32bit-mod \
+# modules-map-32bit
+modules-names += $(modules-map-32bit)
+
+$(objpfx)tst-map-32bit-mod.so: $(libsupport)
+tst-map-32bit-1a-ENV = LD_PREFER_MAP_32BIT_EXEC=1
+$(objpfx)tst-map-32bit-1a: $(objpfx)tst-map-32bit-mod.so
+tst-map-32bit-1b-ENV = GLIBC_TUNABLES=glibc.cpu.prefer_map_32bit_exec=1
+$(objpfx)tst-map-32bit-1b: $(objpfx)tst-map-32bit-mod.so
+
+endif
+endif
diff -rup a/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
--- a/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list 2024-03-06 17:52:50.968514369 -0500
+++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list 2024-03-06 17:55:48.778264896 -0500
@@ -1,3 +1,33 @@
+# x86-64 specific tunables.
+# Copyright (C) 2023 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+glibc {
+ cpu {
+ prefer_map_32bit_exec {
+ type: INT_32
+ minval: 0
+ maxval: 1
+ env_alias: LD_PREFER_MAP_32BIT_EXEC
+ security_level: SXID_IGNORE
+ }
+ }
+}
+
# Order of tunables in RHEL 9.1.z.
@order glibc.rtld.nns
@order glibc.elision.skip_lock_after_retries
@@ -35,3 +65,5 @@
@order glibc.malloc.check
@order glibc.gmon.minarcs
@order glibc.gmon.maxarcs
+# Order of tunables in RHEL 9.5.z
+@order glibc.cpu.prefer_map_32bit_exec
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h b/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h
new file mode 100644
index 0000000000..33dec3f805
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h
@@ -0,0 +1,43 @@
+/* Linux mmap system call. x86-64 version.
+ Copyright (C) 2015-2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef MMAP_X86_64_INTERNAL_H
+#define MMAP_X86_64_INTERNAL_H
+
+#include <ldsodefs.h>
+
+/* If the Prefer_MAP_32BIT_EXEC bit is set, try to map executable or
+ denywrite pages with MAP_32BIT first. */
+#define MMAP_PREPARE(addr, len, prot, flags, fd, offset) \
+ if ((addr) == NULL \
+ && (((prot) & PROT_EXEC) != 0 \
+ || ((flags) & MAP_DENYWRITE) != 0) \
+ && HAS_ARCH_FEATURE (Prefer_MAP_32BIT_EXEC)) \
+ { \
+ void *ret = (void*) INLINE_SYSCALL_CALL (mmap, (addr), (len), \
+ (prot), \
+ (flags) | MAP_32BIT, \
+ (fd), (offset)); \
+ if (ret != MAP_FAILED) \
+ return ret; \
+ }
+
+#include_next <mmap_internal.h>
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c
new file mode 100644
index 0000000000..abc396589e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c
@@ -0,0 +1,34 @@
+/* Check that LD_PREFER_MAP_32BIT_EXEC works in PDE and shared library.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <support/check.h>
+
+extern void dso_check_map_32bit (void);
+
+static int
+do_test (void)
+{
+ printf ("do_test: %p\n", do_test);
+ TEST_VERIFY ((uintptr_t) do_test < 0xffffffffUL);
+ dso_check_map_32bit ();
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c
new file mode 100644
index 0000000000..34ab01c773
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c
@@ -0,0 +1 @@
+#include "tst-map-32bit-1a.c"
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c
new file mode 100644
index 0000000000..78d4b6133c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c
@@ -0,0 +1,33 @@
+/* Check that LD_PREFER_MAP_32BIT_EXEC works in shared library.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <support/check.h>
+
+static void
+dso_do_test (void)
+{
+}
+
+void
+dso_check_map_32bit (void)
+{
+ printf ("dso_do_test: %p\n", dso_do_test);
+ TEST_VERIFY ((uintptr_t) dso_do_test < 0xffffffffUL);
+}
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
index a2197ed211..822688e21f 100644
--- a/sysdeps/x86/cpu-features.c
+++ b/sysdeps/x86/cpu-features.c
@@ -27,6 +27,16 @@
extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *)
attribute_hidden;
+# ifdef __LP64__
+static void
+TUNABLE_CALLBACK (set_prefer_map_32bit_exec) (tunable_val_t *valp)
+{
+ if (valp->numval)
+ GLRO(dl_x86_cpu_features).preferred[index_arch_Prefer_MAP_32BIT_EXEC]
+ |= bit_arch_Prefer_MAP_32BIT_EXEC;
+}
+# endif
+
# if CET_ENABLED
extern void TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *)
attribute_hidden;
@@ -949,6 +959,11 @@ no_cpuid:
#if HAVE_TUNABLES
TUNABLE_GET (hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
+# ifdef __LP64__
+ TUNABLE_GET (prefer_map_32bit_exec, tunable_val_t *,
+ TUNABLE_CALLBACK (set_prefer_map_32bit_exec));
+# endif
+
bool disable_xsave_features = false;
if (!CPU_FEATURE_USABLE_P (cpu_features, OSXSAVE))
diff --git a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
index e45f9cb159..d20c5b3196 100644
--- a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
+++ b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
@@ -26,6 +26,7 @@ BIT (I586)
BIT (I686)
BIT (Slow_SSE4_2)
BIT (AVX_Fast_Unaligned_Load)
+BIT (Prefer_MAP_32BIT_EXEC)
BIT (Prefer_No_VZEROUPPER)
BIT (Prefer_ERMS)
BIT (Prefer_No_AVX512)
--
2.39.3

@ -1,29 +0,0 @@
From 188ecdb7774145050a6e167a277f45f03dac5fe8 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 22 Feb 2023 20:04:26 -0800
Subject: [PATCH] tunables.texi: Change \code{1} to @code{1}
Content-type: text/plain; charset=UTF-8
Update
317f1c0a8a x86-64: Add glibc.cpu.prefer_map_32bit_exec [BZ #28656]
---
manual/tunables.texi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/manual/tunables.texi b/manual/tunables.texi
index c76c5c53cd..70dd2264c5 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -589,7 +589,7 @@ This tunable is specific to i386 and x86-64.
@end deftp
@deftp Tunable glibc.cpu.prefer_map_32bit_exec
-When this tunable is set to \code{1}, shared libraries of non-setuid
+When this tunable is set to @code{1}, shared libraries of non-setuid
programs will be loaded below 2GB with MAP_32BIT.
Note that the @env{LD_PREFER_MAP_32BIT_EXEC} environment is an alias of
--
2.39.3

@ -1,73 +0,0 @@
commit 85860ad6eaf4c9739318f6b2a1ff7c2fa6b12ab5
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Aug 15 16:45:40 2022 +0200
malloc: Do not use MAP_NORESERVE to allocate heap segments
Address space for heap segments is reserved in a mmap call with
MAP_ANONYMOUS | MAP_PRIVATE and protection flags PROT_NONE. This
reservation does not count against the RSS limit of the process or
system. Backing memory is allocated using mprotect in alloc_new_heap
and grow_heap, and at this point, the allocator expects the kernel
to provide memory (subject to memory overcommit).
The SIGSEGV that might generate due to MAP_NORESERVE (according to
the mmap manual page) does not seem to occur in practice, it's always
SIGKILL from the OOM killer. Even if there is a way that SIGSEGV
could be generated, it is confusing to applications that this only
happens for secondary heaps, not for large mmap-based allocations,
and not for the main arena.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Conflicts:
malloc/arena.c
(huge page support was added upstream)
diff --git a/malloc/arena.c b/malloc/arena.c
index 667484630ed0afa5..2852783355d3d869 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -466,8 +466,7 @@ new_heap (size_t size, size_t top_pad)
p2 = MAP_FAILED;
if (aligned_heap_area)
{
- p2 = (char *) MMAP (aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE,
- MAP_NORESERVE);
+ p2 = (char *) MMAP (aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE, 0);
aligned_heap_area = NULL;
if (p2 != MAP_FAILED && ((unsigned long) p2 & (HEAP_MAX_SIZE - 1)))
{
@@ -477,7 +476,7 @@ new_heap (size_t size, size_t top_pad)
}
if (p2 == MAP_FAILED)
{
- p1 = (char *) MMAP (0, HEAP_MAX_SIZE << 1, PROT_NONE, MAP_NORESERVE);
+ p1 = (char *) MMAP (0, HEAP_MAX_SIZE << 1, PROT_NONE, 0);
if (p1 != MAP_FAILED)
{
p2 = (char *) (((unsigned long) p1 + (HEAP_MAX_SIZE - 1))
@@ -493,7 +492,7 @@ new_heap (size_t size, size_t top_pad)
{
/* Try to take the chance that an allocation of only HEAP_MAX_SIZE
is already aligned. */
- p2 = (char *) MMAP (0, HEAP_MAX_SIZE, PROT_NONE, MAP_NORESERVE);
+ p2 = (char *) MMAP (0, HEAP_MAX_SIZE, PROT_NONE, 0);
if (p2 == MAP_FAILED)
return 0;
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 375f50f5db13e234..fe80b8239756a7c9 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1112,10 +1112,6 @@ static mchunkptr mremap_chunk(mchunkptr p, size_t new_size);
# define MAP_ANONYMOUS MAP_ANON
#endif
-#ifndef MAP_NORESERVE
-# define MAP_NORESERVE 0
-#endif
-
#define MMAP(addr, size, prot, flags) \
__mmap((addr), (size), (prot), (flags)|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)

@ -1,229 +0,0 @@
commit f21962ddfc8bb23e92597da1f98e313dbde11cc1
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Aug 25 14:15:28 2023 +0200
manual: Document ld.so --list-diagnostics output
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/manual/dynlink.texi b/manual/dynlink.texi
index 45bf5a5b55..df41c56bfc 100644
--- a/manual/dynlink.texi
+++ b/manual/dynlink.texi
@@ -13,9 +13,216 @@ as plugins) later at run time.
Dynamic linkers are sometimes called @dfn{dynamic loaders}.
@menu
+* Dynamic Linker Invocation:: Explicit invocation of the dynamic linker.
* Dynamic Linker Introspection:: Interfaces for querying mapping information.
@end menu
+@node Dynamic Linker Invocation
+
+@cindex program interpreter
+When a dynamically linked program starts, the operating system
+automatically loads the dynamic linker along with the program.
+@Theglibc{} also supports invoking the dynamic linker explicitly to
+launch a program. This command uses the implied dynamic linker
+(also sometimes called the @dfn{program interpreter}):
+
+@smallexample
+sh -c 'echo "Hello, world!"'
+@end smallexample
+
+This command specifies the dynamic linker explicitly:
+
+@smallexample
+ld.so /bin/sh -c 'echo "Hello, world!"'
+@end smallexample
+
+Note that @command{ld.so} does not search the @env{PATH} environment
+variable, so the full file name of the executable needs to be specified.
+
+The @command{ld.so} program supports various options. Options start
+@samp{--} and need to come before the program that is being launched.
+Some of the supported options are listed below.
+
+@table @code
+@item --list-diagnostics
+Print system diagnostic information in a machine-readable format.
+@xref{Dynamic Linker Diagnostics}.
+@end table
+
+@menu
+* Dynamic Linker Diagnostics:: Obtaining system diagnostic information.
+@end menu
+
+@node Dynamic Linker Diagnostics
+@section Dynamic Linker Diagnostics
+@cindex diagnostics (dynamic linker)
+
+The @samp{ld.so --list-diagnostics} produces machine-readable
+diagnostics output. This output contains system data that affects the
+behavior of @theglibc{}, and potentially application behavior as well.
+
+The exact set of diagnostic items can change between releases of
+@theglibc{}. The output format itself is not expected to change
+radically.
+
+The following table shows some example lines that can be written by the
+diagnostics command.
+
+@table @code
+@item dl_pagesize=0x1000
+The system page size is 4096 bytes.
+
+@item env[0x14]="LANG=en_US.UTF-8"
+This item indicates that the 21st environment variable at process
+startup contains a setting for @code{LANG}.
+
+@item env_filtered[0x22]="DISPLAY"
+The 35th environment variable is @code{DISPLAY}. Its value is not
+included in the output for privacy reasons because it is not recognized
+as harmless by the diagnostics code.
+
+@item path.prefix="/usr"
+This means that @theglibc{} was configured with @code{--prefix=/usr}.
+
+@item path.system_dirs[0x0]="/lib64/"
+@itemx path.system_dirs[0x1]="/usr/lib64/"
+The built-in dynamic linker search path contains two directories,
+@code{/lib64} and @code{/usr/lib64}.
+@end table
+
+@subsection Dynamic Linker Diagnostics Output Format
+
+As seen above, diagnostic lines assign values (integers or strings) to a
+sequence of labeled subscripts, separated by @samp{.}. Some subscripts
+have integer indices associated with them. The subscript indices are
+not necessarily contiguous or small, so an associative array should be
+used to store them. Currently, all integers fit into the 64-bit
+unsigned integer range. Every access path to a value has a fixed type
+(string or integer) independent of subscript index values. Likewise,
+whether a subscript is indexed does not depend on previous indices (but
+may depend on previous subscript labels).
+
+A syntax description in ABNF (RFC 5234) follows. Note that
+@code{%x30-39} denotes the range of decimal digits. Diagnostic output
+lines are expected to match the @code{line} production.
+
+@c ABNF-START
+@smallexample
+HEXDIG = %x30-39 / %x61-6f ; lowercase a-f only
+ALPHA = %x41-5a / %x61-7a / %x7f ; letters and underscore
+ALPHA-NUMERIC = ALPHA / %x30-39 / "_"
+DQUOTE = %x22 ; "
+
+; Numbers are always hexadecimal and use a 0x prefix.
+hex-value-prefix = %x30 %x78
+hex-value = hex-value-prefix 1*HEXDIG
+
+; Strings use octal escape sequences and \\, \".
+string-char = %x20-21 / %x23-5c / %x5d-7e ; printable but not "\
+string-quoted-octal = %x30-33 2*2%x30-37
+string-quoted = "\" ("\" / DQUOTE / string-quoted-octal)
+string-value = DQUOTE *(string-char / string-quoted) DQUOTE
+
+value = hex-value / string-value
+
+label = ALPHA *ALPHA-NUMERIC
+index = "[" hex-value "]"
+subscript = label [index]
+
+line = subscript *("." subscript) "=" value
+@end smallexample
+
+@subsection Dynamic Linker Diagnostics Values
+
+As mentioned above, the set of diagnostics may change between
+@theglibc{} releases. Nevertheless, the following table documents a few
+common diagnostic items. All numbers are in hexadecimal, with a
+@samp{0x} prefix.
+
+@table @code
+@item dl_dst_lib=@var{string}
+The @code{$LIB} dynamic string token expands to @var{string}.
+
+@cindex HWCAP (diagnostics)
+@item dl_hwcap=@var{integer}
+@itemx dl_hwcap2=@var{integer}
+The HWCAP and HWCAP2 values, as returned for @code{getauxval}, and as
+used in other places depending on the architecture.
+
+@cindex page size (diagnostics)
+@item dl_pagesize=@var{integer}
+The system page size is @var{integer} bytes.
+
+@item dl_platform=@var{string}
+The @code{$PLATFORM} dynamic string token expands to @var{string}.
+
+@item dso.libc=@var{string}
+This is the soname of the shared @code{libc} object that is part of
+@theglibc{}. On most architectures, this is @code{libc.so.6}.
+
+@item env[@var{index}]=@var{string}
+@itemx env_filtered[@var{index}]=@var{string}
+An environment variable from the process environment. The integer
+@var{index} is the array index in the environment array. Variables
+under @code{env} include the variable value after the @samp{=} (assuming
+that it was present), variables under @code{env_filtered} do not.
+
+@item path.prefix=@var{string}
+This indicates that @theglibc{} was configured using
+@samp{--prefix=@var{string}}.
+
+@item path.sysconfdir=@var{string}
+@Theglibc{} was configured (perhaps implicitly) with
+@samp{--sysconfdir=@var{string}} (typically @code{/etc}).
+
+@item path.system_dirs[@var{index}]=@var{string}
+These items list the elements of the built-in array that describes the
+default library search path. The value @var{string} is a directory file
+name with a trailing @samp{/}.
+
+@item path.rtld=@var{string}
+This string indicates the application binary interface (ABI) file name
+of the run-time dynamic linker.
+
+@item version.release="stable"
+@itemx version.release="development"
+The value @code{"stable"} indicates that this build of @theglibc{} is
+from a release branch. Releases labeled as @code{"development"} are
+unreleased development versions.
+
+@cindex version (diagnostics)
+@item version.version="@var{major}.@var{minor}"
+@itemx version.version="@var{major}.@var{minor}.9000"
+@Theglibc{} version. Development releases end in @samp{.9000}.
+
+@cindex auxiliary vector (diagnostics)
+@item auxv[@var{index}].a_type=@var{type}
+@itemx auxv[@var{index}].a_val=@var{integer}
+@itemx auxv[@var{index}].a_val_string=@var{string}
+An entry in the auxiliary vector (specific to Linux). The values
+@var{type} (an integer) and @var{integer} correspond to the members of
+@code{struct auxv}. If the value is a string, @code{a_val_string} is
+used instead of @code{a_val}, so that values have consistent types.
+
+The @code{AT_HWCAP} and @code{AT_HWCAP2} values in this output do not
+reflect adjustment by @theglibc{}.
+
+@item uname.sysname=@var{string}
+@itemx uname.nodename=@var{string}
+@itemx uname.release=@var{string}
+@itemx uname.version=@var{string}
+@itemx uname.machine=@var{string}
+@itemx uname.domain=@var{string}
+These Linux-specific items show the values of @code{struct utsname}, as
+reported by the @code{uname} function. @xref{Platform Type}.
+
+@cindex CPUID (diagnostics)
+@item x86.cpu_features.@dots{}
+These items are specific to the i386 and x86-64 architectures. They
+reflect supported CPU features and information on cache geometry, mostly
+collected using the @code{CPUID} instruction.
+@end table
+
@node Dynamic Linker Introspection
@section Dynamic Linker Introspection

@ -1,74 +0,0 @@
commit d99609a3eb8bc96c3af841fd35294a679e0fea7f
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Sep 6 18:37:21 2023 +0200
manual: Fix ld.so diagnostics menu/section structure
And shorten the section/node names a bit, so that the menu
entries become easier to read.
Texinfo 6.5 fails to process the previous structure:
./dynlink.texi:56: warning: node `Dynamic Linker Introspection' is
next for `Dynamic Linker Diagnostics' in sectioning but not in menu
./dynlink.texi:56: warning: node up `Dynamic Linker Diagnostics'
in menu `Dynamic Linker Invocation' and
in sectioning `Dynamic Linker' differ
./dynlink.texi:1: node `Dynamic Linker' lacks menu item for
`Dynamic Linker Diagnostics' despite being its Up target
./dynlink.texi:226: warning: node prev `Dynamic Linker Introspection' in menu `Dynamic Linker Invocation'
and in sectioning `Dynamic Linker Diagnostics' differ
Texinfo 7.0.2 does not report an error.
This fixes commit f21962ddfc8bb23e92597da1f98e313dbde11cc1
("manual: Document ld.so --list-diagnostics output").
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
diff --git a/manual/dynlink.texi b/manual/dynlink.texi
index df41c56bfc..06a6c15533 100644
--- a/manual/dynlink.texi
+++ b/manual/dynlink.texi
@@ -18,6 +18,7 @@ Dynamic linkers are sometimes called @dfn{dynamic loaders}.
@end menu
@node Dynamic Linker Invocation
+@section Dynamic Linker Invocation
@cindex program interpreter
When a dynamically linked program starts, the operating system
@@ -54,7 +55,7 @@ Print system diagnostic information in a machine-readable format.
@end menu
@node Dynamic Linker Diagnostics
-@section Dynamic Linker Diagnostics
+@subsection Dynamic Linker Diagnostics
@cindex diagnostics (dynamic linker)
The @samp{ld.so --list-diagnostics} produces machine-readable
@@ -90,7 +91,13 @@ The built-in dynamic linker search path contains two directories,
@code{/lib64} and @code{/usr/lib64}.
@end table
-@subsection Dynamic Linker Diagnostics Output Format
+@menu
+* Dynamic Linker Diagnostics Format:: Format of ld.so output.
+* Dynamic Linker Diagnostics Values:: Data contain in ld.so output.
+@end menu
+
+@node Dynamic Linker Diagnostics Format
+@subsubsection Dynamic Linker Diagnostics Format
As seen above, diagnostic lines assign values (integers or strings) to a
sequence of labeled subscripts, separated by @samp{.}. Some subscripts
@@ -132,7 +139,8 @@ subscript = label [index]
line = subscript *("." subscript) "=" value
@end smallexample
-@subsection Dynamic Linker Diagnostics Values
+@node Dynamic Linker Diagnostics Values
+@subsubsection Dynamic Linker Diagnostics Values
As mentioned above, the set of diagnostics may change between
@theglibc{} releases. Nevertheless, the following table documents a few

@ -1,144 +0,0 @@
commit f8d8b1b1e6d3b8b93f224efc796b7ea083fdb83f
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Apr 8 16:48:55 2024 +0200
aarch64: Enhanced CPU diagnostics for ld.so
This prints some information from struct cpu_features, and the midr_el1
and dczid_el0 system register contents on every CPU.
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
Modified for RHEL by: Patsy Griffin <patsy@redhat.com>
Diagnostics for the cpu_features mops and prefer_sve_ifuncs are not
currently supported on aarch64.
diff -Nrup a/manual/dynlink.texi b/manual/dynlink.texi
--- a/manual/dynlink.texi 2024-05-31 20:55:08.238959456 -0400
+++ b/manual/dynlink.texi 2024-05-31 20:55:41.298121623 -0400
@@ -224,6 +224,40 @@ reflect adjustment by @theglibc{}.
These Linux-specific items show the values of @code{struct utsname}, as
reported by the @code{uname} function. @xref{Platform Type}.
+@item aarch64.cpu_features.@dots{}
+These items are specific to the AArch64 architectures. They report data
+@theglibc{} uses to activate conditionally supported features such as
+BTI and MTE, and to select alternative function implementations.
+
+@item aarch64.processor[@var{index}].@dots{}
+These are additional items for the AArch64 architecture and are
+described below.
+
+@item aarch64.processor[@var{index}].requested=@var{kernel-cpu}
+The kernel is told to run the subsequent probing on the CPU numbered
+@var{kernel-cpu}. The values @var{kernel-cpu} and @var{index} can be
+distinct if there are gaps in the process CPU affinity mask. This line
+is not included if CPU affinity mask information is not available.
+
+@item aarch64.processor[@var{index}].observed=@var{kernel-cpu}
+This line reports the kernel CPU number @var{kernel-cpu} on which the
+probing code initially ran. If the CPU number cannot be obtained,
+this line is not printed.
+
+@item aarch64.processor[@var{index}].observed_node=@var{node}
+This reports the observed NUMA node number, as reported by the
+@code{getcpu} system call. If this information cannot be obtained, this
+line is not printed.
+
+@item aarch64.processor[@var{index}].midr_el1=@var{value}
+The value of the @code{midr_el1} system register on the processor
+@var{index}. This line is only printed if the kernel indicates that
+this system register is supported.
+
+@item aarch64.processor[@var{index}].dczid_el0=@var{value}
+The value of the @code{dczid_el0} system register on the processor
+@var{index}.
+
@cindex CPUID (diagnostics)
@item x86.cpu_features.@dots{}
These items are specific to the i386 and x86-64 architectures. They
diff -Nrup a/sysdeps/aarch64/dl-diagnostics-cpu.c b/sysdeps/aarch64/dl-diagnostics-cpu.c
--- a/sysdeps/aarch64/dl-diagnostics-cpu.c 1969-12-31 19:00:00.000000000 -0500
+++ b/sysdeps/aarch64/dl-diagnostics-cpu.c 2024-05-31 20:57:23.536623129 -0400
@@ -0,0 +1,81 @@
+/* Print CPU diagnostics data in ld.so. AArch64 version.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <dl-diagnostics.h>
+
+#include <cpu-features.h>
+#include <dl-iterate_cpu.h>
+#include <ldsodefs.h>
+#include <sys/auxv.h>
+
+static void
+print_cpu_features_value (const char *label, uint64_t value)
+{
+ _dl_printf ("aarch64.cpu_features.");
+ _dl_diagnostics_print_labeled_value (label, value);
+}
+
+static void
+print_per_cpu_value (const struct dl_iterate_cpu *dic,
+ const char *label, uint64_t value)
+{
+ _dl_printf ("aarch64.processor[0x%x].", dic->processor_index);
+ _dl_diagnostics_print_labeled_value (label, value);
+}
+
+void
+_dl_diagnostics_cpu (void)
+{
+ print_cpu_features_value ("bti", GLRO (dl_aarch64_cpu_features).bti);
+ print_cpu_features_value ("midr_el1",
+ GLRO (dl_aarch64_cpu_features).midr_el1);
+ print_cpu_features_value ("mte_state",
+ GLRO (dl_aarch64_cpu_features).mte_state);
+ print_cpu_features_value ("sve", GLRO (dl_aarch64_cpu_features).sve);
+ print_cpu_features_value ("zva_size",
+ GLRO (dl_aarch64_cpu_features).zva_size);
+
+ struct dl_iterate_cpu dic;
+ _dl_iterate_cpu_init (&dic);
+
+ while (_dl_iterate_cpu_next (&dic))
+ {
+ if (dic.requested_cpu >= 0)
+ _dl_printf ("aarch64.processor[0x%x].requested=0x%x\n",
+ dic.processor_index, dic.requested_cpu);
+ if (dic.actual_cpu >= 0)
+ _dl_printf ("aarch64.processor[0x%x].observed=0x%x\n",
+ dic.processor_index, dic.actual_cpu);
+ if (dic.actual_node >= 0)
+ _dl_printf ("aarch64.processor[0x%x].observed_node=0x%x\n",
+ dic.processor_index, dic.actual_node);
+
+ if (GLRO (dl_hwcap) & HWCAP_CPUID)
+ {
+ uint64_t midr_el1;
+ asm ("mrs %0, midr_el1" : "=r" (midr_el1));
+ print_per_cpu_value (&dic, "midr_el1", midr_el1);
+ }
+
+ {
+ uint64_t dczid_el0;
+ asm ("mrs %0, dczid_el0" : "=r" (dczid_el0));
+ print_per_cpu_value (&dic, "dczid_el0", dczid_el0);
+ }
+ }
+}

@ -1,510 +0,0 @@
commit 7a430f40c46acfa7ce4c3bff193b278c190b2efc
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Apr 8 16:48:55 2024 +0200
x86: Add generic CPUID data dumper to ld.so --list-diagnostics
This is surprisingly difficult to implement if the goal is to produce
reasonably sized output. With the current approaches to output
compression (suppressing zeros and repeated results between CPUs,
folding ranges of identical subleaves, dealing with the %ecx
reflection issue), the output is less than 600 KiB even for systems
with 256 logical CPUs.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
diff -Nrup a/manual/dynlink.texi b/manual/dynlink.texi
--- a/manual/dynlink.texi 2024-06-03 08:42:17.011026573 -0400
+++ b/manual/dynlink.texi 2024-06-03 08:55:18.607771972 -0400
@@ -262,7 +262,90 @@ The value of the @code{dczid_el0} system
@item x86.cpu_features.@dots{}
These items are specific to the i386 and x86-64 architectures. They
reflect supported CPU features and information on cache geometry, mostly
-collected using the @code{CPUID} instruction.
+collected using the CPUID instruction.
+
+@item x86.processor[@var{index}].@dots{}
+These are additional items for the i386 and x86-64 architectures, as
+described below. They mostly contain raw data from the CPUID
+instruction. The probes are performed for each active CPU for the
+@code{ld.so} process, and data for different probed CPUs receives a
+uniqe @var{index} value. Some CPUID data is expected to differ from CPU
+core to CPU core. In some cases, CPUs are not correctly initialized and
+indicate the presence of different feature sets.
+
+@item x86.processor[@var{index}].requested=@var{kernel-cpu}
+The kernel is told to run the subsequent probing on the CPU numbered
+@var{kernel-cpu}. The values @var{kernel-cpu} and @var{index} can be
+distinct if there are gaps in the process CPU affinity mask. This line
+is not included if CPU affinity mask information is not available.
+
+@item x86.processor[@var{index}].observed=@var{kernel-cpu}
+This line reports the kernel CPU number @var{kernel-cpu} on which the
+probing code initially ran. If the CPU number cannot be obtained,
+this line is not printed.
+
+@item x86.processor[@var{index}].observed_node=@var{node}
+This reports the observed NUMA node number, as reported by the
+@code{getcpu} system call. If this information cannot be obtained, this
+line is not printed.
+
+@item x86.processor[@var{index}].cpuid_leaves=@var{count}
+This line indicates that @var{count} distinct CPUID leaves were
+encountered. (This reflects internal @code{ld.so} storage space, it
+does not directly correspond to @code{CPUID} enumeration ranges.)
+
+@item x86.processor[@var{index}].ecx_limit=@var{value}
+The CPUID data extraction code uses a brute-force approach to enumerate
+subleaves (see the @samp{.subleaf_eax} lines below). The last
+@code{%rcx} value used in a CPUID query on this probed CPU was
+@var{value}.
+
+@item x86.processor[@var{index}].cpuid.eax[@var{query_eax}].eax=@var{eax}
+@itemx x86.processor[@var{index}].cpuid.eax[@var{query_eax}].ebx=@var{ebx}
+@itemx x86.processor[@var{index}].cpuid.eax[@var{query_eax}].ecx=@var{ecx}
+@itemx x86.processor[@var{index}].cpuid.eax[@var{query_eax}].edx=@var{edx}
+These lines report the register contents after executing the CPUID
+instruction with @samp{%rax == @var{query_eax}} and @samp{%rcx == 0} (a
+@dfn{leaf}). For the first probed CPU (with a zero @var{index}), only
+leaves with non-zero register contents are reported. For subsequent
+CPUs, only leaves whose register contents differs from the previously
+probed CPUs (with @var{index} one less) are reported.
+
+Basic and extended leaves are reported using the same syntax. This
+means there is a large jump in @var{query_eax} for the first reported
+extended leaf.
+
+@item x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].eax=@var{eax}
+@itemx x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].ebx=@var{ebx}
+@itemx x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].ecx=@var{ecx}
+@itemx x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].edx=@var{edx}
+This is similar to the leaves above, but for a @dfn{subleaf}. For
+subleaves, the CPUID instruction is executed with @samp{%rax ==
+@var{query_eax}} and @samp{%rcx == @var{query_ecx}}, so the result
+depends on both register values. The same rules about filtering zero
+and identical results apply.
+
+@item x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].until_ecx=@var{ecx_limit}
+Some CPUID results are the same regardless the @var{query_ecx} value.
+If this situation is detected, a line with the @samp{.until_ecx}
+selector ins included, and this indicates that the CPUID register
+contents is the same for @code{%rcx} values between @var{query_ecx}
+and @var{ecx_limit} (inclusive).
+
+@item x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].ecx_query_mask=0xff
+This line indicates that in an @samp{.until_ecx} range, the CPUID
+instruction preserved the lowested 8 bits of the input @code{%rcx} in
+the output @code{%rcx} registers. Otherwise, the subleaves in the range
+have identical values. This special treatment is necessary to report
+compact range information in case such copying occurs (because the
+subleaves would otherwise be all different).
+
+@item x86.processor[@var{index}].xgetbv.ecx[@var{query_ecx}]=@var{result}
+This line shows the 64-bit @var{result} value in the @code{%rdx:%rax}
+register pair after executing the XGETBV instruction with @code{%rcx}
+set to @var{query_ecx}. Zero values and values matching the previously
+probed CPU are omitted. Nothing is printed if the system does not
+support the XGETBV instruction.
@end table
@node Dynamic Linker Introspection
diff -Nrup a/sysdeps/x86/dl-diagnostics-cpu.c b/sysdeps/x86/dl-diagnostics-cpu.c
--- a/sysdeps/x86/dl-diagnostics-cpu.c 2024-06-03 08:42:16.825025689 -0400
+++ b/sysdeps/x86/dl-diagnostics-cpu.c 2024-06-03 09:49:47.528510916 -0400
@@ -17,7 +17,18 @@
<https://www.gnu.org/licenses/>. */
#include <dl-diagnostics.h>
+
+#include <array_length.h>
+#include <cpu-features.h>
+#include <cpuid.h>
+#include <dl-iterate_cpu.h>
#include <ldsodefs.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sysdep.h>
+
+/* The generic CPUID dumping code. */
+static void _dl_diagnostics_cpuid (void);
static void
print_cpu_features_value (const char *label, uint64_t value)
@@ -119,4 +130,377 @@ _dl_diagnostics_cpu (void)
"last cpu_features field has been printed");
print_cpu_features_value ("cachesize_non_temporal_divisor",
__rtld_global_ro_cachesize_non_temporal_divisor);
+
+ _dl_diagnostics_cpuid ();
+}
+
+/* The following code implements a generic CPUID dumper that tries to
+ gather CPUID data without knowing about CPUID implementation
+ details. */
+
+/* Register arguments to CPUID. Multiple ECX subleaf values yielding
+ the same result are combined, to shorten the output. Both
+ identical matches (EAX to EDX are the same) and matches where EAX,
+ EBX, EDX, and ECX are equal except in the lower byte, which must
+ match the query ECX value. The latter is needed to compress ranges
+ on CPUs which preserve the lowest byte in ECX if an unknown leaf is
+ queried. */
+struct cpuid_query
+{
+ unsigned int eax;
+ unsigned ecx_first;
+ unsigned ecx_last;
+ bool ecx_preserves_query_byte;
+};
+
+/* Single integer value that can be used for sorting/ordering
+ comparisons. Uses Q->eax and Q->ecx_first only because ecx_last is
+ always greater than the previous ecx_first value and less than the
+ subsequent one. */
+static inline unsigned long long int
+cpuid_query_combined (struct cpuid_query *q)
+{
+ /* ecx can be -1 (that is, ~0U). If this happens, this the only ecx
+ value for this eax value, so the ordering does not matter. */
+ return ((unsigned long long int) q->eax << 32) | (unsigned int) q->ecx_first;
+};
+
+/* Used for differential reporting of zero/non-zero values. */
+static const struct cpuid_registers cpuid_registers_zero;
+
+/* Register arguments to CPUID paired with the results that came back. */
+struct cpuid_query_result
+{
+ struct cpuid_query q;
+ struct cpuid_registers r;
+};
+
+/* During a first enumeration pass, we try to collect data for
+ cpuid_initial_subleaf_limit subleaves per leaf/EAX value. If we run
+ out of space, we try once more with applying the lower limit. */
+enum { cpuid_main_leaf_limit = 128 };
+enum { cpuid_initial_subleaf_limit = 512 };
+enum { cpuid_subleaf_limit = 32 };
+
+/* Offset of the extended leaf area. */
+enum {cpuid_extended_leaf_offset = 0x80000000 };
+
+/* Collected CPUID data. Everything is stored in a statically sized
+ array that is sized so that the second pass will collect some data
+ for all leaves, after the limit is applied. On the second pass,
+ ecx_limit is set to cpuid_subleaf_limit. */
+struct cpuid_collected_data
+{
+ unsigned int used;
+ unsigned int ecx_limit;
+ uint64_t xgetbv_ecx_0;
+ struct cpuid_query_result qr[cpuid_main_leaf_limit
+ * 2 * cpuid_subleaf_limit];
+};
+
+/* Fill in the result of a CPUID query. Returns true if there is
+ room, false if nothing could be stored. */
+static bool
+_dl_diagnostics_cpuid_store (struct cpuid_collected_data *ccd,
+ unsigned eax, int ecx)
+{
+ if (ccd->used >= array_length (ccd->qr))
+ return false;
+
+ /* Tentatively fill in the next value. */
+ __cpuid_count (eax, ecx,
+ ccd->qr[ccd->used].r.eax,
+ ccd->qr[ccd->used].r.ebx,
+ ccd->qr[ccd->used].r.ecx,
+ ccd->qr[ccd->used].r.edx);
+
+ /* If the ECX subleaf is next subleaf after the previous one (for
+ the same leaf), and the values are the same, merge the result
+ with the already-stored one. Do this before skipping zero
+ leaves, which avoids artifiacts for ECX == 256 queries. */
+ if (ccd->used > 0
+ && ccd->qr[ccd->used - 1].q.eax == eax
+ && ccd->qr[ccd->used - 1].q.ecx_last + 1 == ecx)
+ {
+ /* Exact match of the previous result. Ignore the value of
+ ecx_preserves_query_byte if this is a singleton range so far
+ because we can treat ECX as fixed if the same value repeats. */
+ if ((!ccd->qr[ccd->used - 1].q.ecx_preserves_query_byte
+ || (ccd->qr[ccd->used - 1].q.ecx_first
+ == ccd->qr[ccd->used - 1].q.ecx_last))
+ && memcmp (&ccd->qr[ccd->used - 1].r, &ccd->qr[ccd->used].r,
+ sizeof (ccd->qr[ccd->used].r)) == 0)
+ {
+ ccd->qr[ccd->used - 1].q.ecx_last = ecx;
+ /* ECX is now fixed because the same value has been observed
+ twice, even if we had a low-byte match before. */
+ ccd->qr[ccd->used - 1].q.ecx_preserves_query_byte = false;
+ return true;
+ }
+ /* Match except for the low byte in ECX, which must match the
+ incoming ECX value. */
+ if (ccd->qr[ccd->used - 1].q.ecx_preserves_query_byte
+ && (ecx & 0xff) == (ccd->qr[ccd->used].r.ecx & 0xff)
+ && ccd->qr[ccd->used].r.eax == ccd->qr[ccd->used - 1].r.eax
+ && ccd->qr[ccd->used].r.ebx == ccd->qr[ccd->used - 1].r.ebx
+ && ((ccd->qr[ccd->used].r.ecx & 0xffffff00)
+ == (ccd->qr[ccd->used - 1].r.ecx & 0xffffff00))
+ && ccd->qr[ccd->used].r.edx == ccd->qr[ccd->used - 1].r.edx)
+ {
+ ccd->qr[ccd->used - 1].q.ecx_last = ecx;
+ return true;
+ }
+ }
+
+ /* Do not store zero results. All-zero values usually mean that the
+ subleaf is unsupported. */
+ if (ccd->qr[ccd->used].r.eax == 0
+ && ccd->qr[ccd->used].r.ebx == 0
+ && ccd->qr[ccd->used].r.ecx == 0
+ && ccd->qr[ccd->used].r.edx == 0)
+ return true;
+
+ /* The result needs to be stored. Fill in the query parameters and
+ consume the storage. */
+ ccd->qr[ccd->used].q.eax = eax;
+ ccd->qr[ccd->used].q.ecx_first = ecx;
+ ccd->qr[ccd->used].q.ecx_last = ecx;
+ ccd->qr[ccd->used].q.ecx_preserves_query_byte
+ = (ecx & 0xff) == (ccd->qr[ccd->used].r.ecx & 0xff);
+ ++ccd->used;
+ return true;
+}
+
+/* Collected CPUID data into *CCD. If LIMIT, apply per-leaf limits to
+ avoid exceeding the pre-allocated space. Return true if all data
+ could be stored, false if the retrying without a limit is
+ requested. */
+static bool
+_dl_diagnostics_cpuid_collect_1 (struct cpuid_collected_data *ccd, bool limit)
+{
+ ccd->used = 0;
+ ccd->ecx_limit
+ = (limit ? cpuid_subleaf_limit : cpuid_initial_subleaf_limit) - 1;
+ _dl_diagnostics_cpuid_store (ccd, 0x00, 0x00);
+ if (ccd->used == 0)
+ /* CPUID reported all 0. Should not happen. */
+ return true;
+ unsigned int maximum_leaf = ccd->qr[0x00].r.eax;
+ if (limit && maximum_leaf >= cpuid_main_leaf_limit)
+ maximum_leaf = cpuid_main_leaf_limit - 1;
+
+ for (unsigned int eax = 1; eax <= maximum_leaf; ++eax)
+ {
+ for (unsigned int ecx = 0; ecx <= ccd->ecx_limit; ++ecx)
+ if (!_dl_diagnostics_cpuid_store (ccd, eax, ecx))
+ return false;
+ }
+
+ if (!_dl_diagnostics_cpuid_store (ccd, cpuid_extended_leaf_offset, 0x00))
+ return false;
+ maximum_leaf = ccd->qr[ccd->used - 1].r.eax;
+ if (maximum_leaf < cpuid_extended_leaf_offset)
+ /* No extended CPUID information. */
+ return true;
+ if (limit
+ && maximum_leaf - cpuid_extended_leaf_offset >= cpuid_main_leaf_limit)
+ maximum_leaf = cpuid_extended_leaf_offset + cpuid_main_leaf_limit - 1;
+ for (unsigned int eax = cpuid_extended_leaf_offset + 1;
+ eax <= maximum_leaf; ++eax)
+ {
+ for (unsigned int ecx = 0; ecx <= ccd->ecx_limit; ++ecx)
+ if (!_dl_diagnostics_cpuid_store (ccd, eax, ecx))
+ return false;
+ }
+ return true;
+}
+
+/* Call _dl_diagnostics_cpuid_collect_1 twice if necessary, the
+ second time with the limit applied. */
+static void
+_dl_diagnostics_cpuid_collect (struct cpuid_collected_data *ccd)
+{
+ if (!_dl_diagnostics_cpuid_collect_1 (ccd, false))
+ _dl_diagnostics_cpuid_collect_1 (ccd, true);
+
+ /* Re-use the result of the official feature probing here. */
+ const struct cpu_features *cpu_features = __get_cpu_features ();
+ if (CPU_FEATURES_CPU_P (cpu_features, OSXSAVE))
+ {
+ unsigned int xcrlow;
+ unsigned int xcrhigh;
+ asm ("xgetbv" : "=a" (xcrlow), "=d" (xcrhigh) : "c" (0));
+ ccd->xgetbv_ecx_0 = ((uint64_t) xcrhigh << 32) + xcrlow;
+ }
+ else
+ ccd->xgetbv_ecx_0 = 0;
+}
+
+/* Print a CPUID register value (passed as REG_VALUE) if it differs
+ from the expected REG_REFERENCE value. PROCESSOR_INDEX is the
+ process sequence number (always starting at zero; not a kernel ID). */
+static void
+_dl_diagnostics_cpuid_print_reg (unsigned int processor_index,
+ const struct cpuid_query *q,
+ const char *reg_label, unsigned int reg_value,
+ bool subleaf)
+{
+ if (subleaf)
+ _dl_printf ("x86.processor[0x%x].cpuid.subleaf_eax[0x%x]"
+ ".ecx[0x%x].%s=0x%x\n",
+ processor_index, q->eax, q->ecx_first, reg_label, reg_value);
+ else
+ _dl_printf ("x86.processor[0x%x].cpuid.eax[0x%x].%s=0x%x\n",
+ processor_index, q->eax, reg_label, reg_value);
+}
+
+/* Print CPUID result values in *RESULT for the query in
+ CCD->qr[CCD_IDX]. PROCESSOR_INDEX is the process sequence number
+ (always starting at zero; not a kernel ID). */
+static void
+_dl_diagnostics_cpuid_print_query (unsigned int processor_index,
+ struct cpuid_collected_data *ccd,
+ unsigned int ccd_idx,
+ const struct cpuid_registers *result)
+{
+ /* Treat this as a value if subleaves if ecx isn't zero (maybe
+ within the [ecx_fist, ecx_last] range), or if eax matches its
+ neighbors. If the range is [0, ecx_limit], then the subleaves
+ are not distinct (independently of ecx_preserves_query_byte),
+ so do not report them separately. */
+ struct cpuid_query *q = &ccd->qr[ccd_idx].q;
+ bool subleaf = (q->ecx_first > 0
+ || (q->ecx_first != q->ecx_last
+ && !(q->ecx_first == 0 && q->ecx_last == ccd->ecx_limit))
+ || (ccd_idx > 0 && q->eax == ccd->qr[ccd_idx - 1].q.eax)
+ || (ccd_idx + 1 < ccd->used
+ && q->eax == ccd->qr[ccd_idx + 1].q.eax));
+ _dl_diagnostics_cpuid_print_reg (processor_index, q, "eax", result->eax,
+ subleaf);
+ _dl_diagnostics_cpuid_print_reg (processor_index, q, "ebx", result->ebx,
+ subleaf);
+ _dl_diagnostics_cpuid_print_reg (processor_index, q, "ecx", result->ecx,
+ subleaf);
+ _dl_diagnostics_cpuid_print_reg (processor_index, q, "edx", result->edx,
+ subleaf);
+
+ if (subleaf && q->ecx_first != q->ecx_last)
+ {
+ _dl_printf ("x86.processor[0x%x].cpuid.subleaf_eax[0x%x]"
+ ".ecx[0x%x].until_ecx=0x%x\n",
+ processor_index, q->eax, q->ecx_first, q->ecx_last);
+ if (q->ecx_preserves_query_byte)
+ _dl_printf ("x86.processor[0x%x].cpuid.subleaf_eax[0x%x]"
+ ".ecx[0x%x].ecx_query_mask=0xff\n",
+ processor_index, q->eax, q->ecx_first);
+ }
+}
+
+/* Perform differential reporting of the data in *CURRENT against
+ *BASE. REQUESTED_CPU is the kernel CPU ID the thread was
+ configured to run on, or -1 if no configuration was possible.
+ PROCESSOR_INDEX is the process sequence number (always starting at
+ zero; not a kernel ID). */
+static void
+_dl_diagnostics_cpuid_report (struct dl_iterate_cpu *dci,
+ struct cpuid_collected_data *current,
+ struct cpuid_collected_data *base)
+{
+ if (dci->requested_cpu >= 0)
+ _dl_printf ("x86.processor[0x%x].requested=0x%x\n",
+ dci->processor_index, dci->requested_cpu);
+ if (dci->actual_cpu >= 0)
+ _dl_printf ("x86.processor[0x%x].observed=0x%x\n",
+ dci->processor_index, dci->actual_cpu);
+ if (dci->actual_node >= 0)
+ _dl_printf ("x86.processor[0x%x].observed_node=0x%x\n",
+ dci->processor_index, dci->actual_node);
+
+ _dl_printf ("x86.processor[0x%x].cpuid_leaves=0x%x\n",
+ dci->processor_index, current->used);
+ _dl_printf ("x86.processor[0x%x].ecx_limit=0x%x\n",
+ dci->processor_index, current->ecx_limit);
+
+ unsigned int base_idx = 0;
+ for (unsigned int current_idx = 0; current_idx < current->used;
+ ++current_idx)
+ {
+ /* Report missing data on the current CPU as 0. */
+ unsigned long long int current_query
+ = cpuid_query_combined (&current->qr[current_idx].q);
+ while (base_idx < base->used
+ && cpuid_query_combined (&base->qr[base_idx].q) < current_query)
+ {
+ _dl_diagnostics_cpuid_print_query (dci->processor_index,
+ base, base_idx,
+ &cpuid_registers_zero);
+ ++base_idx;
+ }
+
+ if (base_idx < base->used
+ && cpuid_query_combined (&base->qr[base_idx].q) == current_query)
+ {
+ _Static_assert (sizeof (struct cpuid_registers) == 4 * 4,
+ "no padding in struct cpuid_registers");
+ if (current->qr[current_idx].q.ecx_last
+ != base->qr[base_idx].q.ecx_last
+ || memcmp (&current->qr[current_idx].r,
+ &base->qr[base_idx].r,
+ sizeof (struct cpuid_registers)) != 0)
+ /* The ECX range or the values have changed. Show the
+ new values. */
+ _dl_diagnostics_cpuid_print_query (dci->processor_index,
+ current, current_idx,
+ &current->qr[current_idx].r);
+ ++base_idx;
+ }
+ else
+ /* Data is absent in the base reference. Report the new data. */
+ _dl_diagnostics_cpuid_print_query (dci->processor_index,
+ current, current_idx,
+ &current->qr[current_idx].r);
+ }
+
+ if (current->xgetbv_ecx_0 != base->xgetbv_ecx_0)
+ {
+ /* Re-use the 64-bit printing routine. */
+ _dl_printf ("x86.processor[0x%x].", dci->processor_index);
+ _dl_diagnostics_print_labeled_value ("xgetbv.ecx[0x0]",
+ current->xgetbv_ecx_0);
+ }
+}
+
+static void
+_dl_diagnostics_cpuid (void)
+{
+#if !HAS_CPUID
+ /* CPUID is not supported, so there is nothing to dump. */
+ if (__get_cpuid_max (0, 0) == 0)
+ return;
+#endif
+
+ struct dl_iterate_cpu dic;
+ _dl_iterate_cpu_init (&dic);
+
+ /* Two copies of the data are used. Data is written to the index
+ (dic.processor_index & 1). The previous version against which the
+ data dump is reported is at index !(processor_index & 1). */
+ struct cpuid_collected_data ccd[2];
+
+ /* The initial data is presumed to be all zero. Zero results are
+ not recorded. */
+ ccd[1].used = 0;
+ ccd[1].xgetbv_ecx_0 = 0;
+
+ /* Run the CPUID probing on a specific CPU. There are expected
+ differences for encoding core IDs and topology information in
+ CPUID output, but some firmware/kernel bugs also may result in
+ asymmetric data across CPUs in some cases. */
+ while (_dl_iterate_cpu_next (&dic))
+ {
+ _dl_diagnostics_cpuid_collect (&ccd[dic.processor_index & 1]);
+ _dl_diagnostics_cpuid_report
+ (&dic, &ccd[dic.processor_index & 1],
+ &ccd[!(dic.processor_index & 1)]);
+ }
}

@ -1,262 +0,0 @@
commit 5653ccd847f0cd3a98906e44c97c71d68652d326
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Apr 8 16:48:55 2024 +0200
elf: Add CPU iteration support for future use in ld.so diagnostics
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
diff --git a/elf/dl-iterate_cpu.h b/elf/dl-iterate_cpu.h
new file mode 100644
index 0000000000..60db167b13
--- /dev/null
+++ b/elf/dl-iterate_cpu.h
@@ -0,0 +1,136 @@
+/* Iterate over all CPUs, for CPU-specific diagnostics.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef DL_ITERATE_CPU_H
+#define DL_ITERATE_CPU_H
+
+#include <dl-affinity.h>
+#include <stdbool.h>
+
+struct dl_iterate_cpu
+{
+ /* Sequential iteration count, starting at 0. */
+ unsigned int processor_index;
+
+ /* Requested CPU. Can be -1 if affinity could not be set. */
+ int requested_cpu;
+
+ /* Observed current CPU. -1 if unavailable. */
+ int actual_cpu;
+
+ /* Observed node ID for the CPU. -1 if unavailable. */
+ int actual_node;
+
+ /* Internal fields to implement the iteration. */
+
+ /* Affinity as obtained by _dl_iterate_cpu_init, using
+ _dl_getaffinity. Space for 8,192 CPUs. */
+ unsigned long int mask_reference[8192 / sizeof (unsigned long int) / 8];
+
+ /* This array is used by _dl_setaffinity calls. */
+ unsigned long int mask_request[8192 / sizeof (unsigned long int) / 8];
+
+ /* Return value from the initial _dl_getaffinity call. */
+ int length_reference;
+};
+
+static void
+_dl_iterate_cpu_init (struct dl_iterate_cpu *dic)
+{
+ dic->length_reference
+ = _dl_getaffinity (dic->mask_reference, sizeof (dic->mask_reference));
+ /* Prepare for the first _dl_iterate_cpu_next call. */
+ dic->processor_index = -1;
+ dic->requested_cpu = -1;
+}
+
+static bool
+_dl_iterate_cpu_next (struct dl_iterate_cpu *dic)
+{
+ ++dic->processor_index;
+
+ if (dic->length_reference > 0)
+ {
+ /* Search for the next CPU to switch to. */
+ while (true)
+ {
+ ++dic->requested_cpu;
+
+ /* Array index and bit number within the array. */
+ unsigned int long_index
+ = dic->requested_cpu / sizeof (unsigned long int) / 8;
+ unsigned int bit_index
+ = dic->requested_cpu % (sizeof (unsigned long int) * 8);
+
+ if (long_index * sizeof (unsigned long int) >= dic->length_reference)
+ /* All possible CPUs have been covered. */
+ return false;
+
+ unsigned long int bit = 1UL << bit_index;
+ if (dic->mask_reference[long_index] & bit)
+ {
+ /* The CPU is available. Try to select it. */
+ dic->mask_request[long_index] = bit;
+ if (_dl_setaffinity (dic->mask_request,
+ (long_index + 1)
+ * sizeof (unsigned long int)) < 0)
+ {
+ /* Record that we could not perform a CPU request. */
+ dic->length_reference = -1;
+
+ if (dic->processor_index > 0)
+ /* We already reported something. There is no need to
+ continue because the new data is probably not useful. */
+ return false;
+ }
+
+ /* Clear the bit in case the next iteration switches to the
+ next long value. */
+ dic->mask_request[long_index] = 0;
+
+ /* We found a CPU to run on. */
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* No way to set CPU affinity. Iterate just once. */
+ if (dic->processor_index > 0)
+ return false;
+ }
+
+ /* Fill in the actual CPU information. CPU pinning may not actually
+ be effective, depending on the container host. */
+ unsigned int cpu, node;
+ if (_dl_getcpu (&cpu, &node) < 0)
+ {
+ /* No CPU information available. */
+ dic->actual_cpu = -1;
+ dic->actual_node = -1;
+ }
+ else
+ {
+ dic->actual_cpu = cpu;
+ dic->actual_node = node;
+ }
+
+ return true;
+}
+
+#endif /* DL_ITERATE_CPU_H */
diff --git a/sysdeps/generic/dl-affinity.h b/sysdeps/generic/dl-affinity.h
new file mode 100644
index 0000000000..d117f737e9
--- /dev/null
+++ b/sysdeps/generic/dl-affinity.h
@@ -0,0 +1,54 @@
+/* CPU affinity handling for the dynamic linker. Stub version.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef DL_AFFINITY_H
+#define DL_AFFINITY_H
+
+#include <errno.h>
+#include <stddef.h>
+
+/* On success, write the current CPU ID to *CPU, and the current node
+ ID to *NODE, and return 0. Return a negative error code on
+ failure. */
+static inline int
+_dl_getcpu (unsigned int *cpu, unsigned int *node)
+{
+ return -ENOSYS;
+}
+
+/* On success, write CPU ID affinity bits for the current thread to
+ *BITS, which must be SIZE bytes long, and return the number of
+ bytes updated, a multiple of sizeof (unsigned long int). On
+ failure, return a negative error code. */
+static int
+_dl_getaffinity (unsigned long int *bits, size_t size)
+{
+ return -ENOSYS;
+}
+
+/* Set the CPU affinity mask for the current thread to *BITS, using
+ the SIZE bytes from that array, which should be a multiple of
+ sizeof (unsigned long int). Return 0 on success, and a negative
+ error code on failure. */
+static int
+_dl_setaffinity (const unsigned long int *bits, size_t size)
+{
+ return -ENOSYS;
+}
+
+#endif /* DL_AFFINITY_H */
diff --git a/sysdeps/unix/sysv/linux/dl-affinity.h b/sysdeps/unix/sysv/linux/dl-affinity.h
new file mode 100644
index 0000000000..bbfede7750
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/dl-affinity.h
@@ -0,0 +1,46 @@
+/* CPU affinity handling for the dynamic linker. Linux version.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* See sysdeps/generic/dl-affinity.h for documentation of these interfaces. */
+
+#ifndef DL_AFFINITY_H
+#define DL_AFFINITY_H
+
+#include <sysdep.h>
+#include <stddef.h>
+#include <unistd.h>
+
+static inline int
+_dl_getcpu (unsigned int *cpu, unsigned int *node)
+{
+ return INTERNAL_SYSCALL_CALL (getcpu, cpu, node);
+}
+
+static int
+_dl_getaffinity (unsigned long int *bits, size_t size)
+{
+ return INTERNAL_SYSCALL_CALL (sched_getaffinity, /* TID */ 0, size, bits);
+}
+
+static int
+_dl_setaffinity (const unsigned long int *bits, size_t size)
+{
+ return INTERNAL_SYSCALL_CALL (sched_setaffinity, /* TID */ 0, size, bits);
+}
+
+#endif /* DL_AFFINITY_H */

@ -1,140 +0,0 @@
commit 6a04404521ac4119ae36827eeb288ea84eee7cf6
Author: Florian Weimer <fweimer@redhat.com>
Date: Sat Feb 17 09:17:04 2024 +0100
Linux: Switch back to assembly syscall wrapper for prctl (bug 29770)
Commit ff026950e280bc3e9487b41b460fb31bc5b57721 ("Add a C wrapper for
prctl [BZ #25896]") replaced the assembler wrapper with a C function.
However, on powerpc64le-linux-gnu, the C variadic function
implementation requires extra work in the caller to set up the
parameter save area. Calling a function that needs a parameter save
area without one (because the prototype used indicates the function is
not variadic) corrupts the caller's stack. The Linux manual pages
project documents prctl as a non-variadic function. This has resulted
in various projects over the years using non-variadic prototypes,
including the sanitizer libraries in LLVm and GCC (GCC PR 113728).
This commit switches back to the assembler implementation on most
targets and only keeps the C implementation for x86-64 x32.
Also add the __prctl_time64 alias from commit
b39ffab860cd743a82c91946619f1b8158b0b65e ("Linux: Add time64 alias for
prctl") to sysdeps/unix/sysv/linux/syscalls.list; it was not yet
present in commit ff026950e280bc3e9487b41b460fb31bc5b57721.
This restores the old ABI on powerpc64le-linux-gnu, thus fixing
bug 29770.
Reviewed-By: Simon Chopin <simon.chopin@canonical.com>
Resolved conflicts:
sysdeps/unix/sysv/linux/syscalls.list
sysdeps/unix/sysv/linux/x86_64/x32/prctl.c
diff -Nrup a/sysdeps/unix/sysv/linux/prctl.c b/sysdeps/unix/sysv/linux/prctl.c
--- a/sysdeps/unix/sysv/linux/prctl.c 2021-08-01 21:33:43.000000000 -0400
+++ b/sysdeps/unix/sysv/linux/prctl.c 1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/* prctl - Linux specific syscall.
- Copyright (C) 2020-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-#include <stdarg.h>
-#include <sys/prctl.h>
-
-/* Unconditionally read all potential arguments. This may pass
- garbage values to the kernel, but avoids the need for teaching
- glibc the argument counts of individual options (including ones
- that are added to the kernel in the future). */
-
-int
-__prctl (int option, ...)
-{
- va_list arg;
- va_start (arg, option);
- unsigned long int arg2 = va_arg (arg, unsigned long int);
- unsigned long int arg3 = va_arg (arg, unsigned long int);
- unsigned long int arg4 = va_arg (arg, unsigned long int);
- unsigned long int arg5 = va_arg (arg, unsigned long int);
- va_end (arg);
- return INLINE_SYSCALL_CALL (prctl, option, arg2, arg3, arg4, arg5);
-}
-
-libc_hidden_def (__prctl)
-weak_alias (__prctl, prctl)
-#if __TIMESIZE != 64
-weak_alias (__prctl, __prctl_time64)
-#endif
diff -Nrup a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
--- a/sysdeps/unix/sysv/linux/syscalls.list 2021-08-01 21:33:43.000000000 -0400
+++ b/sysdeps/unix/sysv/linux/syscalls.list 2024-02-27 14:33:01.594782897 -0500
@@ -41,6 +41,7 @@ munlockall - munlockall i: munlockall
nfsservctl EXTRA nfsservctl i:ipp __compat_nfsservctl nfsservctl@GLIBC_2.0:GLIBC_2.28
pipe - pipe i:f __pipe pipe
pipe2 - pipe2 i:fi __pipe2 pipe2
+prctl EXTRA prctl i:iiiii __prctl prctl __prctl_time64
pivot_root EXTRA pivot_root i:ss pivot_root
query_module EXTRA query_module i:sipip __compat_query_module query_module@GLIBC_2.0:GLIBC_2.23
quotactl EXTRA quotactl i:isip quotactl
diff -Nrup a/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c b/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c
--- a/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c 1969-12-31 19:00:00.000000000 -0500
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c 2024-02-27 14:35:03.388602623 -0500
@@ -0,0 +1,42 @@
+/* prctl - Linux specific syscall. x86-64 x32 version.
+ Copyright (C) 2020-2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <stdarg.h>
+#include <sys/prctl.h>
+
+/* Unconditionally read all potential arguments. This may pass
+ garbage values to the kernel, but avoids the need for teaching
+ glibc the argument counts of individual options (including ones
+ that are added to the kernel in the future). */
+
+int
+__prctl (int option, ...)
+{
+ va_list arg;
+ va_start (arg, option);
+ unsigned long int arg2 = va_arg (arg, unsigned long int);
+ unsigned long int arg3 = va_arg (arg, unsigned long int);
+ unsigned long int arg4 = va_arg (arg, unsigned long int);
+ unsigned long int arg5 = va_arg (arg, unsigned long int);
+ va_end (arg);
+ return INLINE_SYSCALL_CALL (prctl, option, arg2, arg3, arg4, arg5);
+}
+
+libc_hidden_def (__prctl)
+weak_alias (__prctl, prctl)

@ -1,88 +0,0 @@
From dfb05f8e704edac70db38c4c8ee700769d91a413 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Fri, 16 Feb 2024 07:17:10 -0800
Subject: [PATCH] x86-64: Save APX registers in ld.so trampoline
Content-type: text/plain; charset=UTF-8
Add APX registers to STATE_SAVE_MASK so that APX registers are saved in
ld.so trampoline. This fixes BZ #31371.
Also update STATE_SAVE_OFFSET and STATE_SAVE_MASK for i386 which will
be used by i386 _dl_tlsdesc_dynamic.
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
Conflicts:
sysdeps/x86/sysdep.h
(rebased for context and line numbers)
---
sysdeps/x86/sysdep.h | 52 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 46 insertions(+), 6 deletions(-)
diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h
index 85d0a8c943..837fd28734 100644
--- a/sysdeps/x86/sysdep.h
+++ b/sysdeps/x86/sysdep.h
@@ -48,14 +48,54 @@
# define SHSTK_ENABLED 0
#endif
+/* The extended state feature IDs in the state component bitmap. */
+#define X86_XSTATE_X87_ID 0
+#define X86_XSTATE_SSE_ID 1
+#define X86_XSTATE_AVX_ID 2
+#define X86_XSTATE_BNDREGS_ID 3
+#define X86_XSTATE_BNDCFG_ID 4
+#define X86_XSTATE_K_ID 5
+#define X86_XSTATE_ZMM_H_ID 6
+#define X86_XSTATE_ZMM_ID 7
+#define X86_XSTATE_PKRU_ID 9
+#define X86_XSTATE_TILECFG_ID 17
+#define X86_XSTATE_TILEDATA_ID 18
+#define X86_XSTATE_APX_F_ID 19
+
+#ifdef __x86_64__
/* Offset for fxsave/xsave area used by _dl_runtime_resolve. Also need
space to preserve RCX, RDX, RSI, RDI, R8, R9 and RAX. It must be
- aligned to 16 bytes for fxsave and 64 bytes for xsave. */
-#define STATE_SAVE_OFFSET (8 * 7 + 8)
-
-/* Save SSE, AVX, AVX512, mask and bound registers. */
-#define STATE_SAVE_MASK \
- ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7))
+ aligned to 16 bytes for fxsave and 64 bytes for xsave.
+
+ NB: Is is non-zero because of the 128-byte red-zone. Some registers
+ are saved on stack without adjusting stack pointer first. When we
+ update stack pointer to allocate more space, we need to take the
+ red-zone into account. */
+# define STATE_SAVE_OFFSET (8 * 7 + 8)
+
+/* Save SSE, AVX, AVX512, mask, bound and APX registers. Bound and APX
+ registers are mutually exclusive. */
+# define STATE_SAVE_MASK \
+ ((1 << X86_XSTATE_SSE_ID) \
+ | (1 << X86_XSTATE_AVX_ID) \
+ | (1 << X86_XSTATE_BNDREGS_ID) \
+ | (1 << X86_XSTATE_K_ID) \
+ | (1 << X86_XSTATE_ZMM_H_ID) \
+ | (1 << X86_XSTATE_ZMM_ID) \
+ | (1 << X86_XSTATE_APX_F_ID))
+#else
+/* Offset for fxsave/xsave area used by _dl_tlsdesc_dynamic. Since i386
+ doesn't have red-zone, use 0 here. */
+# define STATE_SAVE_OFFSET 0
+
+/* Save SSE, AVX, AXV512, mask and bound registers. */
+# define STATE_SAVE_MASK \
+ ((1 << X86_XSTATE_SSE_ID) \
+ | (1 << X86_XSTATE_AVX_ID) \
+ | (1 << X86_XSTATE_BNDREGS_ID) \
+ | (1 << X86_XSTATE_K_ID) \
+ | (1 << X86_XSTATE_ZMM_H_ID))
+#endif
/* Constants for bits in __x86_string_control: */
--
2.39.3

@ -1,109 +0,0 @@
commit 127fc56152347d73cb7c1c283e60e1cb1f15e9f9
Author: sayan paul <saypaul@redhat.com>
Date: Wed May 29 15:31:04 2024 +0530
malloc: New test to check malloc alternate path using memory obstruction
The test aims to ensure that malloc uses the alternate path to
allocate memory when sbrk() or brk() fails.To achieve this,
the test first creates an obstruction at current program break,
tests that obstruction with a failing sbrk(), then checks if malloc
is still returning a valid ptr thus inferring that malloc() used
mmap() instead of brk() or sbrk() to allocate the memory.
Reviewed-by: Arjun Shankar <arjun@redhat.com>
Reviewed-by: Zack Weinberg <zack@owlfolio.org>
Conflicts:
malloc/Makefile
(usual tests conflict)
diff --git a/malloc/Makefile b/malloc/Makefile
index 9b70831d383cb522..cb4e027d28b179f0 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -43,6 +43,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
tst-tcfree1 tst-tcfree2 tst-tcfree3 \
tst-safe-linking \
tst-mallocalign1 \
+ tst-malloc-alternate-path \
tests-static := \
tst-interpose-static-nothread \
diff --git a/malloc/tst-malloc-alternate-path.c b/malloc/tst-malloc-alternate-path.c
new file mode 100644
index 0000000000000000..43ae916815d6ff47
--- /dev/null
+++ b/malloc/tst-malloc-alternate-path.c
@@ -0,0 +1,72 @@
+/* Test that malloc uses mmap when sbrk or brk fails.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* This test sets up an obstruction to ensure that brk/sbrk fails to
+ grow the heap, then verifies that malloc uses mmap for allocations
+ instead. */
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <libc-pointer-arith.h>
+#include <support/check.h>
+#include <stddef.h>
+#include <stdalign.h>
+
+#define LARGE_SIZE (10 * (1 << 20)) // 10 MB
+static long page_size;
+
+static int
+do_test (void)
+{
+ /* Get current program break. */
+ void *current_brk = sbrk (0);
+
+ page_size = sysconf (_SC_PAGESIZE);
+
+ /* Round up to the next page boundary. */
+ void *next_page_boundary = PTR_ALIGN_UP (current_brk, page_size);
+
+ /* Place a mapping using mmap at the next page boundary. */
+ void *obstruction_addr
+ = mmap (next_page_boundary, page_size, PROT_READ,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+
+ /* Check if memory obstruction is set up correctly. */
+ TEST_VERIFY_EXIT (obstruction_addr == next_page_boundary);
+
+ /* Try to extend the heap beyond the obstruction using sbrk */
+ int *ptr = sbrk (page_size);
+ TEST_VERIFY_EXIT (ptr == (void *) -1);
+
+ /* Attempt multiple small allocations using malloc. */
+ for (size_t i = 0; i < page_size / alignof (max_align_t); i++)
+ {
+ TEST_VERIFY (malloc (alignof (max_align_t)));
+ }
+
+ /* Attempt to allocate a large block of memory using malloc. */
+ TEST_VERIFY_EXIT (malloc (LARGE_SIZE) != NULL);
+
+ /* Check if malloc changed current program break. */
+ TEST_VERIFY_EXIT (current_brk == sbrk (0));
+
+ return 0;
+}
+
+#include <support/test-driver.c>

@ -1,26 +0,0 @@
From a07e000e82cb71238259e674529c37c12dc7d423 Mon Sep 17 00:00:00 2001
From: DJ Delorie <dj@redhat.com>
Date: Fri, 10 May 2024 17:34:29 -0400
Subject: manual: add dup3
Reviewed-by: Florian Weimer <fweimer@redhat.com>
diff --git a/manual/llio.texi b/manual/llio.texi
index fae49d1433..fe1807a849 100644
--- a/manual/llio.texi
+++ b/manual/llio.texi
@@ -3415,6 +3415,14 @@ middle of calling @code{dup2} at which @var{new} is closed and not yet a
duplicate of @var{old}.
@end deftypefun
+@deftypefun int dup3 (int @var{old}, int @var{new}, int @var{flags})
+@standards{Linux, unistd.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+This function is the same as @code{dup2} but creates the new
+descriptor as if it had been opened with flags @var{flags}. The only
+allowed flag is @code{O_CLOEXEC}.
+@end deftypefun
+
@deftypevr Macro int F_DUPFD
@standards{POSIX.1, fcntl.h}
This macro is used as the @var{command} argument to @code{fcntl}, to

@ -1,341 +0,0 @@
From 6c0be74305745c8f78bcfb69442c8c379459d99b Mon Sep 17 00:00:00 2001
From: DJ Delorie <dj@redhat.com>
Date: Mon, 8 Jul 2024 17:52:15 -0400
Subject: manual: add syscalls
The purpose of this patch is to add some system calls that (1) aren't
otherwise documented, and (2) are merely redirected to the kernel, so
can refer to their documentation; and define a standard way of doing
so in the future. A more detailed explaination of how system calls
are wrapped is added along with reference to the Linux Man-Pages
project.
Default version of man-pages is in configure.ac but can be overridden
by --with-man-pages=X.Y
Reviewed-by: Alejandro Colomar <alx@kernel.org>
diff --git a/config.make.in b/config.make.in
index 55e8b7563b..36096881b7 100644
--- a/config.make.in
+++ b/config.make.in
@@ -101,6 +101,7 @@ build-hardcoded-path-in-tests= @hardcode
build-pt-chown = @build_pt_chown@
have-tunables = @have_tunables@
pthread-in-libc = @pthread_in_libc@
+man-pages-version = @man_pages_version@
# Build tools.
CC = @CC@
diff --git a/configure b/configure
index 55e8b7563b..36096881b7 100644
--- a/configure 2024-07-17 15:45:55.033649362 -0400
+++ b/configure 2024-07-17 15:47:44.281886629 -0400
@@ -681,6 +681,7 @@ force_install
bindnow
hardcoded_path_in_tests
enable_timezone_tools
+man_pages_version
rtld_early_cflags
extra_nonshared_cflags
use_default_link
@@ -763,6 +764,7 @@ with_headers
with_default_link
with_nonshared_cflags
with_rtld_early_cflags
+with_man_pages
enable_sanity_checks
enable_shared
enable_profile
@@ -1483,6 +1485,8 @@ Optional Packages:
build nonshared libraries with additional CFLAGS
--with-rtld-early-cflags=CFLAGS
build early initialization with additional CFLAGS
+ --with-man-pages=VERSION
+ tie manual to a specific man-pages version
--with-cpu=CPU select code for CPU variant
Some influential environment variables:
@@ -3396,6 +3400,15 @@ fi
+man_pages_version=6.9.1
+
+
+# Check whether --with-man-pages was given.
+if test "${with_man_pages+set}" = set; then :
+ withval=$with_man_pages; man_pages_version=$withval
+fi
+
+
# Check whether --enable-sanity-checks was given.
if test "${enable_sanity_checks+set}" = set; then :
diff --git a/configure.ac b/configure.ac
index e48957f318..9cbc0bf68f 100644
--- a/configure.ac 2024-07-17 15:45:52.181538742 -0400
+++ b/configure.ac 2024-07-17 15:46:29.885001095 -0400
@@ -169,6 +169,15 @@ AC_ARG_WITH([rtld-early-cflags],
[rtld_early_cflags=])
AC_SUBST(rtld_early_cflags)
+man_pages_version=6.9.1
+
+AC_ARG_WITH([man-pages],
+ AS_HELP_STRING([--with-man-pages=VERSION],
+ [tie manual to a specific man-pages version]),
+ [man_pages_version=$withval],
+ [])
+AC_SUBST(man_pages_version)
+
AC_ARG_ENABLE([sanity-checks],
AS_HELP_STRING([--disable-sanity-checks],
[really do not use threads (should not be used except in special situations) @<:@default=yes@:>@]),
diff --git a/manual/Makefile b/manual/Makefile
index b5fda4a7ae..a6c05db540 100644
--- a/manual/Makefile
+++ b/manual/Makefile
@@ -117,6 +117,7 @@ $(objpfx)stamp-pkgvers: $(common-objpfx)config.make
echo "@set PKGVERSION_DEFAULT" >> $(objpfx)pkgvers-tmp; \
fi
echo "@set REPORT_BUGS_TO $(REPORT_BUGS_TEXI)" >> $(objpfx)pkgvers-tmp
+ echo "@set man_pages_version $(man-pages-version)" >> $(objpfx)pkgvers-tmp; \
echo "@end ifclear" >> $(objpfx)pkgvers-tmp
$(move-if-change) $(objpfx)pkgvers-tmp $(objpfx)pkgvers.texi
touch $@
diff --git a/manual/intro.texi b/manual/intro.texi
index ff43c5a7fb..879c1b38d9 100644
--- a/manual/intro.texi
+++ b/manual/intro.texi
@@ -85,6 +85,7 @@ standards each function or symbol comes from.
* Berkeley Unix:: BSD and SunOS.
* SVID:: The System V Interface Description.
* XPG:: The X/Open Portability Guide.
+* Linux Kernel:: The Linux kernel.
@end menu
@node ISO C, POSIX, , Standards and Portability
@@ -941,7 +942,7 @@ inter-process communication and shared memory, the @code{hsearch} and
@code{drand48} families of functions, @code{fmtmsg} and several of the
mathematical functions.
-@node XPG, , SVID, Standards and Portability
+@node XPG, Linux Kernel, SVID, Standards and Portability
@subsection XPG (The X/Open Portability Guide)
The X/Open Portability Guide, published by the X/Open Company, Ltd., is
@@ -960,6 +961,20 @@ fulfilling the XPG standard with the Unix extensions is a
precondition for getting the Unix brand chances are good that the
functionality is available on commercial systems.
+@node Linux Kernel, , XPG, Standards and Portability
+@subsection Linux (The Linux Kernel)
+
+@Theglibc{} includes by reference the Linux man-pages
+@value{man_pages_version} documentation to document the listed
+syscalls for the Linux kernel. For reference purposes only the latest
+@uref{https://www.kernel.org/doc/man-pages/,Linux man-pages Project}
+documentation can be accessed from the
+@uref{https://www.kernel.org,Linux kernel} website. Where the syscall
+has more specific documentation in this manual that more specific
+documentation is considered authoritative.
+
+Additional details on the Linux system call interface can be found in
+@xref{System Calls}.
@node Using the Library, Roadmap to the Manual, Standards and Portability, Introduction
@section Using the Library
diff --git a/manual/llio.texi b/manual/llio.texi
index 78c7c79913..6f0a48609b 100644
--- a/manual/llio.texi
+++ b/manual/llio.texi
@@ -65,6 +65,7 @@ directly.)
* Interrupt Input:: Getting an asynchronous signal when
input arrives.
* IOCTLs:: Generic I/O Control operations.
+* Other Low-Level I/O APIs:: Other low-level-I/O-related functions.
@end menu
@@ -2324,6 +2325,8 @@ file descriptor, or until the timeout period expires.
There is another example showing the use of @code{select} to multiplex
input from multiple sockets in @ref{Server Example}.
+For an alternate interface to this functionality, see @code{poll}
+(@pxref{Other Low-Level I/O APIs}).
@node Synchronizing I/O
@section Synchronizing I/O operations
@@ -3407,7 +3410,9 @@ require additional arguments to be supplied. These additional arguments
and the return value and error conditions are given in the detailed
descriptions of the individual commands.
-Briefly, here is a list of what the various commands are.
+Briefly, here is a list of what the various commands are. For an
+exhaustive list of kernel-specific options, please see @xref{System
+Calls}.
@vtable @code
@item F_DUPFD
@@ -4743,5 +4748,28 @@ Most IOCTLs are OS-specific and/or only used in special system utilities,
and are thus beyond the scope of this document. For an example of the use
of an IOCTL, see @ref{Out-of-Band Data}.
-@c FIXME this is undocumented:
-@c dup3
+@node Other Low-Level I/O APIs
+@section Other low-level-I/O-related functions
+
+@deftp {Data Type} {struct pollfd}
+@standards{POSIX.1,poll.h}
+@end deftp
+
+@deftp {Data Type} {struct epoll_event}
+@standards{Linux,sys/epoll.h}
+@end deftp
+
+@deftypefun int poll (struct pollfd *@var{fds}, nfds_t @var{nfds}, int @var{timeout})
+
+@manpagefunctionstub{poll,2}
+@end deftypefun
+
+@deftypefun int epoll_create(int @var{size})
+
+@manpagefunctionstub{epoll_create,2}
+@end deftypefun
+
+@deftypefun int epoll_wait(int @var{epfd}, struct epoll_event *@var{events}, int @var{maxevents}, int @var{timeout})
+
+@manpagefunctionstub{epoll_wait,2}
+@end deftypefun
diff --git a/manual/macros.texi b/manual/macros.texi
index 4a2e22f473..579da3fb81 100644
--- a/manual/macros.texi
+++ b/manual/macros.texi
@@ -282,4 +282,11 @@ cwd\comments\
@macro standardsx {element, standard, header}
@end macro
+@macro manpagefunctionstub {func,sec}
+This documentation is a stub. For additional information on this
+function, consult the manual page
+@url{https://man7.org/linux/man-pages/man\sec\/\func\.\sec\.html}.
+@xref{Linux Kernel}.
+@end macro
+
@end ifclear
diff --git a/manual/socket.texi b/manual/socket.texi
index f0e35d9e13..8708cbb07c 100644
--- a/manual/socket.texi
+++ b/manual/socket.texi
@@ -41,6 +41,7 @@ aren't documented either so far.
is to make it work with Inetd.
* Socket Options:: Miscellaneous low-level socket options.
* Networks Database:: Accessing the database of network names.
+* Other Socket APIs:: Other socket-related functions.
@end menu
@node Socket Concepts
@@ -3134,38 +3135,8 @@ You can use plain @code{recv} (@pxref{Receiving Data}) instead of
treat all possible senders alike). Even @code{read} can be used if
you don't want to specify @var{flags} (@pxref{I/O Primitives}).
-@ignore
-@c sendmsg and recvmsg are like readv and writev in that they
-@c use a series of buffers. It's not clear this is worth
-@c supporting or that we support them.
-@c !!! they can do more; it is hairy
-
-@deftp {Data Type} {struct msghdr}
-@standards{BSD, sys/socket.h}
-@end deftp
-
-@deftypefun ssize_t sendmsg (int @var{socket}, const struct msghdr *@var{message}, int @var{flags})
-@standards{BSD, sys/socket.h}
-@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
-
-This function is defined as a cancellation point in multi-threaded
-programs, so one has to be prepared for this and make sure that
-allocated resources (like memory, files descriptors, semaphores or
-whatever) are freed even if the thread is cancel.
-@c @xref{pthread_cleanup_push}, for a method how to do this.
-@end deftypefun
-
-@deftypefun ssize_t recvmsg (int @var{socket}, struct msghdr *@var{message}, int @var{flags})
-@standards{BSD, sys/socket.h}
-@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
-
-This function is defined as a cancellation point in multi-threaded
-programs, so one has to be prepared for this and make sure that
-allocated resources (like memory, files descriptors, semaphores or
-whatever) are freed even if the thread is canceled.
-@c @xref{pthread_cleanup_push}, for a method how to do this.
-@end deftypefun
-@end ignore
+If you need more flexibility and/or control over sending and receiving
+packets, see @code{sendmsg} and @code{recvmsg} (@pxref{Other Socket APIs}).
@node Datagram Example
@subsection Datagram Socket Example
@@ -3664,3 +3635,20 @@ returns a null pointer if there are no more entries.
@c libc_lock_unlock @aculock
This function closes the networks database.
@end deftypefun
+
+@node Other Socket APIs
+@section Other Socket APIs
+
+@deftp {Data Type} {struct msghdr}
+@standards{BSD, sys/socket.h}
+@end deftp
+
+@deftypefun ssize_t sendmsg (int @var{socket}, const struct msghdr *@var{message}, int @var{flags})
+
+@manpagefunctionstub{sendmsg,2}
+@end deftypefun
+
+@deftypefun ssize_t recvmsg (int @var{socket}, struct msghdr *@var{message}, int @var{flags})
+
+@manpagefunctionstub{recvmsg,2}
+@end deftypefun
diff --git a/manual/startup.texi b/manual/startup.texi
index 224dd98c1e..747beed4d9 100644
--- a/manual/startup.texi
+++ b/manual/startup.texi
@@ -689,7 +689,25 @@ you don't need to know about it because you can just use @theglibc{}'s
@code{chmod} function.
@cindex kernel call
-System calls are sometimes called kernel calls.
+System calls are sometimes called syscalls or kernel calls, and this
+interface is mostly a purely mechanical translation from the kernel's
+ABI to the C ABI. For the set of syscalls where we do not guarantee
+POSIX Thread cancellation the wrappers only organize the incoming
+arguments from the C calling convention to the calling convention of
+the target kernel. For the set of syscalls where we provided POSIX
+Thread cancellation the wrappers set some internal state in the
+library to support cancellation, but this does not impact the
+behaviour of the syscall provided by the kernel.
+
+In some cases, if @theglibc{} detects that a system call has been
+superseded by a more capable one, the wrapper may map the old call to
+the new one. For example, @code{dup2} is implemented via @code{dup3}
+by passing an additional empty flags argument, and @code{open} calls
+@code{openat} passing the additional @code{AT_FDCWD}. Sometimes even
+more is done, such as converting between 32-bit and 64-bit time
+values. In general, though, such processing is only to make the
+system call better match the C ABI, rather than change its
+functionality.
However, there are times when you want to make a system call explicitly,
and for that, @theglibc{} provides the @code{syscall} function.
@@ -711,6 +729,8 @@ we won't describe it here either because anyone who is coding
library source code as a specification of the interface between them
anyway.
+@code{syscall} does not provide cancellation logic, even if the system
+call you're calling is listed as cancellable above.
@code{syscall} is declared in @file{unistd.h}.

@ -1,188 +0,0 @@
From a4c3f5f46e850c977cda81c251036475aab8313c Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Thu, 23 Nov 2023 14:29:14 -0300
Subject: [PATCH] elf: Add a way to check if tunable is set (BZ 27069)
Content-type: text/plain; charset=UTF-8
The patch adds two new macros, TUNABLE_GET_DEFAULT and TUNABLE_IS_INITIALIZED,
here the former get the default value with a signature similar to
TUNABLE_GET, while the later returns whether the tunable was set by
the environment variable.
Checked on x86_64-linux-gnu.
Reviewed-by: DJ Delorie <dj@redhat.com>
Tested-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Conflicts:
elf/Versions
(removed to preserve ABI)
elf/dl-tunable-types.h
(line numbers)
scripts/gen-tunables.awk
(account for missing TUNABLE_SECLEVEL patch)
---
elf/dl-tunable-types.h | 1 +
elf/dl-tunables.c | 40 ++++++++++++++++++++++++++++++++++++++++
elf/dl-tunables.h | 28 ++++++++++++++++++++++++++++
elf/dl-tunables.list | 1 +
scripts/gen-tunables.awk | 4 ++--
6 files changed, 73 insertions(+), 2 deletions(-)
diff -rup a/elf/dl-tunable-types.h b/elf/dl-tunable-types.h
--- a/elf/dl-tunable-types.h 2021-08-01 21:33:43.000000000 -0400
+++ b/elf/dl-tunable-types.h 2024-03-26 18:23:22.211504813 -0400
@@ -61,6 +61,7 @@ struct _tunable
{
const char name[TUNABLE_NAME_MAX]; /* Internal name of the tunable. */
tunable_type_t type; /* Data type of the tunable. */
+ const tunable_val_t def; /* The value. */
tunable_val_t val; /* The value. */
bool initialized; /* Flag to indicate that the tunable is
initialized. */
diff -rup a/elf/dl-tunables.c b/elf/dl-tunables.c
--- a/elf/dl-tunables.c 2024-03-26 18:21:10.090681748 -0400
+++ b/elf/dl-tunables.c 2024-03-26 18:23:22.214504923 -0400
@@ -152,6 +152,13 @@ tunable_initialize (tunable_t *cur, cons
do_tunable_update_val (cur, &val, NULL, NULL);
}
+bool
+__tunable_is_initialized (tunable_id_t id)
+{
+ return tunable_list[id].initialized;
+}
+rtld_hidden_def (__tunable_is_initialized)
+
void
__tunable_set_val (tunable_id_t id, tunable_val_t *valp, tunable_num_t *minp,
tunable_num_t *maxp)
@@ -399,6 +406,39 @@ __tunables_print (void)
}
}
+void
+__tunable_get_default (tunable_id_t id, void *valp)
+{
+ tunable_t *cur = &tunable_list[id];
+
+ switch (cur->type.type_code)
+ {
+ case TUNABLE_TYPE_UINT_64:
+ {
+ *((uint64_t *) valp) = (uint64_t) cur->def.numval;
+ break;
+ }
+ case TUNABLE_TYPE_INT_32:
+ {
+ *((int32_t *) valp) = (int32_t) cur->def.numval;
+ break;
+ }
+ case TUNABLE_TYPE_SIZE_T:
+ {
+ *((size_t *) valp) = (size_t) cur->def.numval;
+ break;
+ }
+ case TUNABLE_TYPE_STRING:
+ {
+ *((const char **)valp) = cur->def.strval;
+ break;
+ }
+ default:
+ __builtin_unreachable ();
+ }
+}
+rtld_hidden_def (__tunable_get_default)
+
/* Set the tunable value. This is called by the module that the tunable exists
in. */
void
diff -rup a/elf/dl-tunables.h b/elf/dl-tunables.h
--- a/elf/dl-tunables.h 2021-08-01 21:33:43.000000000 -0400
+++ b/elf/dl-tunables.h 2024-03-26 18:23:22.217505032 -0400
@@ -53,18 +53,26 @@ typedef void (*tunable_callback_t) (tuna
extern void __tunables_init (char **);
extern void __tunables_print (void);
+extern bool __tunable_is_initialized (tunable_id_t);
extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
extern void __tunable_set_val (tunable_id_t, tunable_val_t *, tunable_num_t *,
tunable_num_t *);
+extern void __tunable_get_default (tunable_id_t id, void *valp);
rtld_hidden_proto (__tunables_init)
rtld_hidden_proto (__tunables_print)
+rtld_hidden_proto (__tunable_is_initialized)
rtld_hidden_proto (__tunable_get_val)
rtld_hidden_proto (__tunable_set_val)
+rtld_hidden_proto (__tunable_get_default)
/* Define TUNABLE_GET and TUNABLE_SET in short form if TOP_NAMESPACE and
TUNABLE_NAMESPACE are defined. This is useful shorthand to get and set
tunables within a module. */
#if defined TOP_NAMESPACE && defined TUNABLE_NAMESPACE
+# define TUNABLE_IS_INITIALIZED(__id) \
+ TUNABLE_IS_INITIALIZED_FULL(TOP_NAMESPACE, TUNABLE_NAMESPACE, __id)
+# define TUNABLE_GET_DEFAULT(__id, __type) \
+ TUNABLE_GET_DEFAULT_FULL(TOP_NAMESPACE, TUNABLE_NAMESPACE,__id, __type)
# define TUNABLE_GET(__id, __type, __cb) \
TUNABLE_GET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __cb)
# define TUNABLE_SET(__id, __val) \
@@ -73,6 +81,10 @@ rtld_hidden_proto (__tunable_set_val)
TUNABLE_SET_WITH_BOUNDS_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, \
__val, __min, __max)
#else
+# define TUNABLE_IS_INITIALIZED(__top, __ns, __id) \
+ TUNABLE_IS_INITIALIZED_FULL(__top, __ns, __id)
+# define TUNABLE_GET_DEFAULT(__top, __ns, __type) \
+ TUNABLE_GET_DEFAULT_FULL(__top, __ns, __id, __type)
# define TUNABLE_GET(__top, __ns, __id, __type, __cb) \
TUNABLE_GET_FULL (__top, __ns, __id, __type, __cb)
# define TUNABLE_SET(__top, __ns, __id, __val) \
@@ -81,6 +93,22 @@ rtld_hidden_proto (__tunable_set_val)
TUNABLE_SET_WITH_BOUNDS_FULL (__top, __ns, __id, __val, __min, __max)
#endif
+/* Return whether the tunable was initialized by the environment variable. */
+#define TUNABLE_IS_INITIALIZED_FULL(__top, __ns, __id) \
+({ \
+ tunable_id_t id = TUNABLE_ENUM_NAME (__top, __ns, __id); \
+ __tunable_is_initialized (id); \
+})
+
+/* Return the default value of the tunable. */
+#define TUNABLE_GET_DEFAULT_FULL(__top, __ns, __id, __type) \
+({ \
+ tunable_id_t id = TUNABLE_ENUM_NAME (__top, __ns, __id); \
+ __type __ret; \
+ __tunable_get_default (id, &__ret); \
+ __ret; \
+})
+
/* Get and return a tunable value. If the tunable was set externally and __CB
is defined then call __CB before returning the value. */
# define TUNABLE_GET_FULL(__top, __ns, __id, __type, __cb) \
diff -rup a/elf/dl-tunables.list b/elf/dl-tunables.list
--- a/elf/dl-tunables.list 2024-03-26 18:21:09.664666196 -0400
+++ b/elf/dl-tunables.list 2024-03-26 18:23:22.220505142 -0400
@@ -20,6 +20,7 @@
# type: Defaults to STRING
# minval: Optional minimum acceptable value
# maxval: Optional maximum acceptable value
+# default: Optional default value (if not specified it will be 0 or "")
# env_alias: An alias environment variable
# security_level: Specify security level of the tunable for AT_SECURE binaries.
# Valid values are:
diff -rup a/scripts/gen-tunables.awk b/scripts/gen-tunables.awk
--- a/scripts/gen-tunables.awk 2024-03-26 18:21:09.523661049 -0400
+++ b/scripts/gen-tunables.awk 2024-03-26 18:34:45.385462341 -0400
@@ -236,8 +236,8 @@ END {
n = indices[2];
m = indices[3];
printf (" {TUNABLE_NAME_S(%s, %s, %s)", t, n, m)
- printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, NULL, TUNABLE_SECLEVEL_%s, %s},\n",
- types[t,n,m], minvals[t,n,m], maxvals[t,n,m],
+ printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, {%s}, NULL, TUNABLE_SECLEVEL_%s, %s},\n",
+ types[t,n,m], minvals[t,n,m], maxvals[t,n,m],default_val[t,n,m],
default_val[t,n,m], security_level[t,n,m], env_alias[t,n,m]);
}
print "};"

@ -1,155 +0,0 @@
From 0c0d39fe4aeb0f69b26e76337c5dfd5530d5d44e Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Thu, 8 Feb 2024 10:08:38 -0300
Subject: [PATCH] x86: Fix Zen3/Zen4 ERMS selection (BZ 30994)
Content-type: text/plain; charset=UTF-8
The REP MOVSB usage on memcpy/memmove does not show much performance
improvement on Zen3/Zen4 cores compared to the vectorized loops. Also,
as from BZ 30994, if the source is aligned and the destination is not
the performance can be 20x slower.
The performance difference is noticeable with small buffer sizes, closer
to the lower bounds limits when memcpy/memmove starts to use ERMS. The
performance of REP MOVSB is similar to vectorized instruction on the
size limit (the L2 cache). Also, there is no drawback to multiple cores
sharing the cache.
Checked on x86_64-linux-gnu on Zen3.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Conflicts:
sysdeps/x86/dl-cacheinfo.h
(tweaked for changed context)
---
sysdeps/x86/dl-cacheinfo.h | 38 ++++++++++++++++++--------------------
1 file changed, 18 insertions(+), 20 deletions(-)
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
index d5101615e3..f34d12846c 100644
--- a/sysdeps/x86/dl-cacheinfo.h
+++ b/sysdeps/x86/dl-cacheinfo.h
@@ -791,7 +791,6 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
long int data = -1;
long int shared = -1;
long int shared_per_thread = -1;
- long int core = -1;
unsigned int threads = 0;
unsigned long int level1_icache_size = -1;
unsigned long int level1_icache_linesize = -1;
@@ -809,7 +808,6 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
if (cpu_features->basic.kind == arch_kind_intel)
{
data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features);
- core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features);
shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, cpu_features);
shared_per_thread = shared;
@@ -822,7 +820,8 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
= handle_intel (_SC_LEVEL1_DCACHE_ASSOC, cpu_features);
level1_dcache_linesize
= handle_intel (_SC_LEVEL1_DCACHE_LINESIZE, cpu_features);
- level2_cache_size = core;
+ level2_cache_size
+ = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features);
level2_cache_assoc
= handle_intel (_SC_LEVEL2_CACHE_ASSOC, cpu_features);
level2_cache_linesize
@@ -835,12 +834,12 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
level4_cache_size
= handle_intel (_SC_LEVEL4_CACHE_SIZE, cpu_features);
- get_common_cache_info (&shared, &shared_per_thread, &threads, core);
+ get_common_cache_info (&shared, &shared_per_thread, &threads,
+ level2_cache_size);
}
else if (cpu_features->basic.kind == arch_kind_zhaoxin)
{
data = handle_zhaoxin (_SC_LEVEL1_DCACHE_SIZE);
- core = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE);
shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE);
shared_per_thread = shared;
@@ -849,19 +848,19 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
level1_dcache_size = data;
level1_dcache_assoc = handle_zhaoxin (_SC_LEVEL1_DCACHE_ASSOC);
level1_dcache_linesize = handle_zhaoxin (_SC_LEVEL1_DCACHE_LINESIZE);
- level2_cache_size = core;
+ level2_cache_size = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE);
level2_cache_assoc = handle_zhaoxin (_SC_LEVEL2_CACHE_ASSOC);
level2_cache_linesize = handle_zhaoxin (_SC_LEVEL2_CACHE_LINESIZE);
level3_cache_size = shared;
level3_cache_assoc = handle_zhaoxin (_SC_LEVEL3_CACHE_ASSOC);
level3_cache_linesize = handle_zhaoxin (_SC_LEVEL3_CACHE_LINESIZE);
- get_common_cache_info (&shared, &shared_per_thread, &threads, core);
+ get_common_cache_info (&shared, &shared_per_thread, &threads,
+ level2_cache_size);
}
else if (cpu_features->basic.kind == arch_kind_amd)
{
data = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
- core = handle_amd (_SC_LEVEL2_CACHE_SIZE);
shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE);
@@ -869,7 +868,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
level1_dcache_size = data;
level1_dcache_assoc = handle_amd (_SC_LEVEL1_DCACHE_ASSOC);
level1_dcache_linesize = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE);
- level2_cache_size = core;
+ level2_cache_size = handle_amd (_SC_LEVEL2_CACHE_SIZE);;
level2_cache_assoc = handle_amd (_SC_LEVEL2_CACHE_ASSOC);
level2_cache_linesize = handle_amd (_SC_LEVEL2_CACHE_LINESIZE);
level3_cache_size = shared;
@@ -880,12 +879,12 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
if (shared <= 0)
{
/* No shared L3 cache. All we have is the L2 cache. */
- shared = core;
+ shared = level2_cache_size;
}
else if (cpu_features->basic.family < 0x17)
{
/* Account for exclusive L2 and L3 caches. */
- shared += core;
+ shared += level2_cache_size;
}
shared_per_thread = shared;
@@ -987,6 +986,12 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
if (CPU_FEATURE_USABLE_P (cpu_features, FSRM))
rep_movsb_threshold = 2112;
+ /* For AMD CPUs that support ERMS (Zen3+), REP MOVSB is in a lot of
+ cases slower than the vectorized path (and for some alignments,
+ it is really slow, check BZ #30994). */
+ if (cpu_features->basic.kind == arch_kind_amd)
+ rep_movsb_threshold = non_temporal_threshold;
+
/* The default threshold to use Enhanced REP STOSB. */
unsigned long int rep_stosb_threshold = 2048;
@@ -1028,15 +1033,8 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
#endif
unsigned long int rep_movsb_stop_threshold;
- /* ERMS feature is implemented from AMD Zen3 architecture and it is
- performing poorly for data above L2 cache size. Henceforth, adding
- an upper bound threshold parameter to limit the usage of Enhanced
- REP MOVSB operations and setting its value to L2 cache size. */
- if (cpu_features->basic.kind == arch_kind_amd)
- rep_movsb_stop_threshold = core;
/* Setting the upper bound of ERMS to the computed value of
- non-temporal threshold for architectures other than AMD. */
- else
- rep_movsb_stop_threshold = non_temporal_threshold;
+ non-temporal threshold for all architectures. */
+ rep_movsb_stop_threshold = non_temporal_threshold;
cpu_features->data_cache_size = data;
cpu_features->shared_cache_size = shared;
--
2.39.3

@ -1,34 +0,0 @@
From 272708884cb750f12f5c74a00e6620c19dc6d567 Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Thu, 8 Feb 2024 10:08:39 -0300
Subject: [PATCH] x86: Do not prefer ERMS for memset on Zen3+
Content-type: text/plain; charset=UTF-8
For AMD Zen3+ architecture, the performance of the vectorized loop is
slightly better than ERMS.
Checked on x86_64-linux-gnu on Zen3.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
---
sysdeps/x86/dl-cacheinfo.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
index f34d12846c..5a98f70364 100644
--- a/sysdeps/x86/dl-cacheinfo.h
+++ b/sysdeps/x86/dl-cacheinfo.h
@@ -1021,6 +1021,11 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
minimum value is fixed. */
rep_stosb_threshold = TUNABLE_GET (x86_rep_stosb_threshold,
long int, NULL);
+ if (cpu_features->basic.kind == arch_kind_amd
+ && !TUNABLE_IS_INITIALIZED (x86_rep_stosb_threshold))
+ /* For AMD Zen3+ architecture, the performance of the vectorized loop is
+ slightly better than ERMS. */
+ rep_stosb_threshold = SIZE_MAX;
TUNABLE_SET_WITH_BOUNDS (x86_data_cache_size, data, 0, SIZE_MAX);
TUNABLE_SET_WITH_BOUNDS (x86_shared_cache_size, shared, 0, SIZE_MAX);
--
2.39.3

@ -1,29 +0,0 @@
From 491e55beab7457ed310a4a47496f4a333c5d1032 Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Thu, 8 Feb 2024 10:08:40 -0300
Subject: [PATCH] x86: Expand the comment on when REP STOSB is used on memset
Content-type: text/plain; charset=UTF-8
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
---
sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
index 9984c3ca0f..97839a2248 100644
--- a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
+++ b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
@@ -21,7 +21,9 @@
2. If size is less than VEC, use integer register stores.
3. If size is from VEC_SIZE to 2 * VEC_SIZE, use 2 VEC stores.
4. If size is from 2 * VEC_SIZE to 4 * VEC_SIZE, use 4 VEC stores.
- 5. If size is more to 4 * VEC_SIZE, align to 4 * VEC_SIZE with
+ 5. On machines ERMS feature, if size is greater or equal than
+ __x86_rep_stosb_threshold then REP STOSB will be used.
+ 6. If size is more to 4 * VEC_SIZE, align to 4 * VEC_SIZE with
4 VEC stores and store 4 * VEC at a time until done. */
#include <sysdep.h>
--
2.39.3

@ -1,205 +0,0 @@
From dce754b1553b86fc6352636f1fa490a85b7cf0ff Mon Sep 17 00:00:00 2001
From: DJ Delorie <dj@redhat.com>
Date: Fri, 10 May 2024 14:52:09 -0400
Subject: Update mmap() flags and errors lists
Extend the list of MAP_* macros to include all macros available
to the average program (gcc -E -dM | grep MAP_*)
Extend the list of errno codes.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
diff --git a/manual/llio.texi b/manual/llio.texi
index fe1807a849..78c7c79913 100644
--- a/manual/llio.texi
+++ b/manual/llio.texi
@@ -1573,10 +1573,15 @@ permitted. They include @code{PROT_READ}, @code{PROT_WRITE}, and
of address space for future use. The @code{mprotect} function can be
used to change the protection flags. @xref{Memory Protection}.
-@var{flags} contains flags that control the nature of the map.
-One of @code{MAP_SHARED} or @code{MAP_PRIVATE} must be specified.
+The @var{flags} parameter contains flags that control the nature of
+the map. One of @code{MAP_SHARED}, @code{MAP_SHARED_VALIDATE}, or
+@code{MAP_PRIVATE} must be specified. Additional flags may be bitwise
+OR'd to further define the mapping.
-They include:
+Note that, aside from @code{MAP_PRIVATE} and @code{MAP_SHARED}, not
+all flags are supported on all versions of all operating systems.
+Consult the kernel-specific documentation for details. The flags
+include:
@vtable @code
@item MAP_PRIVATE
@@ -1598,9 +1603,19 @@ Note that actual writing may take place at any time. You need to use
@code{msync}, described below, if it is important that other processes
using conventional I/O get a consistent view of the file.
+@item MAP_SHARED_VALIDATE
+Similar to @code{MAP_SHARED} except that additional flags will be
+validated by the kernel, and the call will fail if an unrecognized
+flag is provided. With @code{MAP_SHARED} using a flag on a kernel
+that doesn't support it causes the flag to be ignored.
+@code{MAP_SHARED_VALIDATE} should be used when the behavior of all
+flags is required.
+
@item MAP_FIXED
This forces the system to use the exact mapping address specified in
-@var{address} and fail if it can't.
+@var{address} and fail if it can't. Note that if the new mapping
+would overlap an existing mapping, the overlapping portion of the
+existing map is unmapped.
@c One of these is official - the other is obviously an obsolete synonym
@c Which is which?
@@ -1641,10 +1656,73 @@ The @code{MAP_HUGETLB} flag is specific to Linux.
@c There is a mechanism to select different hugepage sizes; see
@c include/uapi/asm-generic/hugetlb_encode.h in the kernel sources.
-@c Linux has some other MAP_ options, which I have not discussed here.
-@c MAP_DENYWRITE, MAP_EXECUTABLE and MAP_GROWSDOWN don't seem applicable to
-@c user programs (and I don't understand the last two). MAP_LOCKED does
-@c not appear to be implemented.
+@item MAP_32BIT
+Require addresses that can be accessed with a signed 32 bit pointer,
+i.e., within the first 2 GiB. Ignored if MAP_FIXED is specified.
+
+@item MAP_DENYWRITE
+@itemx MAP_EXECUTABLE
+@itemx MAP_FILE
+
+Provided for compatibility. Ignored by the Linux kernel.
+
+@item MAP_FIXED_NOREPLACE
+Similar to @code{MAP_FIXED} except the call will fail with
+@code{EEXIST} if the new mapping would overwrite an existing mapping.
+To test for support for this flag, specify MAP_FIXED_NOREPLACE without
+MAP_FIXED, and (if the call was successful) check the actual address
+returned. If it does not match the address passed, then this flag is
+not supported.
+
+@item MAP_GROWSDOWN
+This flag is used to make stacks, and is typically only needed inside
+the program loader to set up the main stack for the running process.
+The mapping is created according to the other flags, except an
+additional page just prior to the mapping is marked as a ``guard
+page''. If a write is attempted inside this guard page, that page is
+mapped, the mapping is extended, and a new guard page is created.
+Thus, the mapping continues to grow towards lower addresses until it
+encounters some other mapping.
+
+Note that accessing memory beyond the guard page will not trigger this
+feature. In gcc, use @code{-fstack-clash-protection} to ensure the
+guard page is always touched.
+
+@item MAP_LOCKED
+A hint that requests that mapped pages are locked in memory (i.e. not
+paged out). Note that this is a request and not a requirement; use
+@code{mlock} if locking is required.
+
+@item MAP_POPULATE
+@itemx MAP_NONBLOCK
+@code{MAP_POPULATE} is a hint that requests that the kernel read-ahead
+a file-backed mapping, causing pages to be mapped before they're
+needed. @code{MAP_NONBLOCK} is a hint that requests that the kernel
+@emph{not} attempt such except for pages are already in memory. Note
+that neither of these hints affects future paging activity, use
+@code{mlock} if such needs to be controlled.
+
+@item MAP_NORESERVE
+Asks the kernel to not reserve physical backing (i.e. space in a swap
+device) for a mapping. This would be useful for, for example, a very
+large but sparsely used mapping which need not be limited in total
+length by available RAM, but with very few mapped pages. Note that
+writes to such a mapping may cause a @code{SIGSEGV} if the system is
+unable to map a page due to lack of resources.
+
+On Linux, this flag's behavior may be overwridden by
+@file{/proc/sys/vm/overcommit_memory} as documented in the proc(5) man
+page.
+
+@item MAP_STACK
+Ensures that the resulting mapping is suitable for use as a program
+stack. For example, the use of huge pages might be precluded.
+
+@item MAP_SYNC
+This is a special flag for DAX devices, which tells the kernel to
+write dirty metadata out whenever dirty data is written out. Unlike
+most other flags, this one will fail unless @code{MAP_SHARED_VALIDATE}
+is also given.
@end vtable
@@ -1655,6 +1733,24 @@ Possible errors include:
@table @code
+@item EACCES
+
+@var{filedes} was not open for the type of access specified in @var{protect}.
+
+@item EAGAIN
+
+The system has temporarily run out of resources.
+
+@item EBADF
+
+The @var{fd} passed is invalid, and a valid file descriptor is
+required (i.e. MAP_ANONYMOUS was not specified).
+
+@item EEXIST
+
+@code{MAP_FIXED_NOREPLACE} was specified and an existing mapping was
+found overlapping the requested address range.
+
@item EINVAL
Either @var{address} was unusable (because it is not a multiple of the
@@ -1663,23 +1759,37 @@ applicable page size), or inconsistent @var{flags} were given.
If @code{MAP_HUGETLB} was specified, the file or system does not support
large page sizes.
-@item EACCES
+@item ENODEV
-@var{filedes} was not open for the type of access specified in @var{protect}.
+This file is of a type that doesn't support mapping, the process has
+exceeded its data space limit, or the map request would exceed the
+process's virtual address space.
@item ENOMEM
-Either there is not enough memory for the operation, or the process is
-out of address space.
-
-@item ENODEV
-
-This file is of a type that doesn't support mapping.
+There is not enough memory for the operation, the process is out of
+address space, or there are too many mappings. On Linux, the maximum
+number of mappings can be controlled via
+@file{/proc/sys/vm/max_map_count} or, if your OS supports it, via
+the @code{vm.max_map_count} @code{sysctl} setting.
@item ENOEXEC
The file is on a filesystem that doesn't support mapping.
+@item EPERM
+
+@code{PROT_EXEC} was requested but the file is on a filesystem that
+was mounted with execution denied, a file seal prevented the mapping,
+or the caller set MAP_HUDETLB but does not have the required
+priviledges.
+
+@item EOVERFLOW
+
+Either the offset into the file plus the length of the mapping causes
+internal page counts to overflow, or the offset requested exceeds the
+length of the file.
+
@c On Linux, EAGAIN will appear if the file has a conflicting mandatory lock.
@c However mandatory locks are not discussed in this manual.
@c

@ -1,207 +0,0 @@
Author: Charles Fol <folcharles@gmail.com>
Date: Thu Mar 28 12:25:38 2024 -0300
iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence (CVE-2024-2961)
ISO-2022-CN-EXT uses escape sequences to indicate character set changes
(as specified by RFC 1922). While the SOdesignation has the expected
bounds checks, neither SS2designation nor SS3designation have its;
allowing a write overflow of 1, 2, or 3 bytes with fixed values:
'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'.
Checked on aarch64-linux-gnu.
Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
Conflicts:
iconvdata/Makefile
(usual tests conflict)
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
index d5507a048c6a6508..25bd004e7f92a994 100644
--- a/iconvdata/Makefile
+++ b/iconvdata/Makefile
@@ -75,7 +75,7 @@ ifeq (yes,$(build-shared))
tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
- bug-iconv13 bug-iconv14 bug-iconv15
+ bug-iconv13 bug-iconv14 bug-iconv15 tst-iconv-iso-2022-cn-ext
ifeq ($(have-thread-library),yes)
tests += bug-iconv3
endif
@@ -330,6 +330,8 @@ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
$(addprefix $(objpfx),$(modules.so))
$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
$(addprefix $(objpfx),$(modules.so))
+$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
+ $(addprefix $(objpfx),$(modules.so))
$(objpfx)iconv-test.out: run-iconv-test.sh \
$(addprefix $(objpfx), $(gconv-modules)) \
diff --git a/iconvdata/iso-2022-cn-ext.c b/iconvdata/iso-2022-cn-ext.c
index 2aca91c021f21ba0..c1339fe933d9d1c4 100644
--- a/iconvdata/iso-2022-cn-ext.c
+++ b/iconvdata/iso-2022-cn-ext.c
@@ -575,6 +575,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
{ \
const char *escseq; \
\
+ if (outptr + 4 > outend) \
+ { \
+ result = __GCONV_FULL_OUTPUT; \
+ break; \
+ } \
+ \
assert (used == CNS11643_2_set); /* XXX */ \
escseq = "*H"; \
*outptr++ = ESC; \
@@ -588,6 +594,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
{ \
const char *escseq; \
\
+ if (outptr + 4 > outend) \
+ { \
+ result = __GCONV_FULL_OUTPUT; \
+ break; \
+ } \
+ \
assert ((used >> 5) >= 3 && (used >> 5) <= 7); \
escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; \
*outptr++ = ESC; \
diff --git a/iconvdata/tst-iconv-iso-2022-cn-ext.c b/iconvdata/tst-iconv-iso-2022-cn-ext.c
new file mode 100644
index 0000000000000000..96a8765fd5369681
--- /dev/null
+++ b/iconvdata/tst-iconv-iso-2022-cn-ext.c
@@ -0,0 +1,128 @@
+/* Verify ISO-2022-CN-EXT does not write out of the bounds.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <errno.h>
+#include <iconv.h>
+#include <sys/mman.h>
+
+#include <support/xunistd.h>
+#include <support/check.h>
+#include <support/support.h>
+
+/* The test sets up a two memory page buffer with the second page marked
+ PROT_NONE to trigger a fault if the conversion writes beyond the exact
+ expected amount. Then we carry out various conversions and precisely
+ place the start of the output buffer in order to trigger a SIGSEGV if the
+ process writes anywhere between 1 and page sized bytes more (only one
+ PROT_NONE page is setup as a canary) than expected. These tests exercise
+ all three of the cases in ISO-2022-CN-EXT where the converter must switch
+ character sets and may run out of buffer space while doing the
+ operation. */
+
+static int
+do_test (void)
+{
+ iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8");
+ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
+
+ char *ntf;
+ size_t ntfsize;
+ char *outbufbase;
+ {
+ int pgz = getpagesize ();
+ TEST_VERIFY_EXIT (pgz > 0);
+ ntfsize = 2 * pgz;
+
+ ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE
+ | MAP_ANONYMOUS, -1);
+ xmprotect (ntf + pgz, pgz, PROT_NONE);
+
+ outbufbase = ntf + pgz;
+ }
+
+ /* Check if SOdesignation escape sequence does not trigger an OOB write. */
+ {
+ char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2";
+
+ for (int i = 0; i < 9; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ /* Same as before for SS2designation. */
+ {
+ char inbuf[] = "㴽 \xe3\xb4\xbd";
+
+ for (int i = 0; i < 14; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ /* Same as before for SS3designation. */
+ {
+ char inbuf[] = "劄 \xe5\x8a\x84";
+
+ for (int i = 0; i < 14; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ TEST_VERIFY_EXIT (iconv_close (cd) != -1);
+
+ xmunmap (ntf, ntfsize);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

@ -1,142 +0,0 @@
commit 3a83f79024cc023a74c3892a1673542e8e972485
Author: Sergey Kolosov <skolosov@redhat.com>
Date: Wed Apr 10 17:58:05 2024 +0200
socket: Add new test for connect
This commit adds a simple bind/accept/connect test for an IPv4 TCP
connection to a local process via the loopback interface.
Reviewed-by: Arjun Shankar <arjun@redhat.com>
diff -Nrup a/socket/Makefile b/socket/Makefile
--- a/socket/Makefile 2024-05-19 21:52:59.775055152 -0400
+++ b/socket/Makefile 2024-05-19 22:05:27.717703460 -0400
@@ -33,8 +33,9 @@ routines := accept bind connect getpeern
tests := \
tst-accept4 \
- tst-sockopt \
tst-cmsghdr \
+ tst-connect \
+ tst-sockopt \
# tests
tests-internal := \
diff -Nrup a/socket/tst-connect.c b/socket/tst-connect.c
--- a/socket/tst-connect.c 1969-12-31 19:00:00.000000000 -0500
+++ b/socket/tst-connect.c 2024-05-19 21:58:22.069058144 -0400
@@ -0,0 +1,113 @@
+/* Test the connect function.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <support/check.h>
+#include <support/xsocket.h>
+#include <support/xunistd.h>
+#include <sys/socket.h>
+#include <stdio.h>
+
+static struct sockaddr_in server_address;
+
+int
+open_socket_inet_tcp (void)
+{
+ int fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (fd < 0)
+ {
+ if (errno == EAFNOSUPPORT)
+ FAIL_UNSUPPORTED ("The host does not support IPv4");
+ else
+ FAIL_EXIT1 ("socket (AF_INET, SOCK_STREAM, IPPROTO_TCP): %m\n");
+ }
+ return fd;
+}
+
+static pid_t
+start_server (void)
+{
+ server_address.sin_family = AF_INET;
+ server_address.sin_port = 0;
+ server_address.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ int server_sock = open_socket_inet_tcp ();
+
+ xbind (server_sock, (struct sockaddr *) &server_address,
+ sizeof (server_address));
+
+ socklen_t sa_len = sizeof (server_address);
+ xgetsockname (server_sock, (struct sockaddr *) &server_address, &sa_len);
+ xlisten (server_sock, 5);
+
+ pid_t my_pid = xfork ();
+ if (my_pid > 0)
+ {
+ xclose (server_sock);
+ return my_pid;
+ }
+
+ struct sockaddr_in client_address;
+ socklen_t ca_len = sizeof (server_address);
+ int client_sock = xaccept (server_sock, (struct sockaddr *) &client_address,
+ &ca_len);
+ printf ("socket accepted %d\n", client_sock);
+
+ _exit (0);
+}
+
+static int
+do_test (void)
+{
+ pid_t serv_pid;
+ struct sockaddr_in peer;
+ socklen_t peer_len;
+
+ serv_pid = start_server ();
+ int client_sock = open_socket_inet_tcp ();
+ xconnect (client_sock, (const struct sockaddr *) &server_address,
+ sizeof (server_address));
+
+ /* A second connect with same arguments should fail with EISCONN. */
+ int result = connect (client_sock,
+ (const struct sockaddr *) &server_address,
+ sizeof (server_address));
+ if (result == 0 || errno != EISCONN)
+ FAIL_EXIT1 ("Second connect (%d), should fail with EISCONN: %m",
+ client_sock);
+
+ peer_len = sizeof (peer);
+ xgetpeername (client_sock, (struct sockaddr *) &peer, &peer_len);
+ TEST_COMPARE (peer_len, sizeof (peer));
+ TEST_COMPARE (peer.sin_port, server_address.sin_port);
+ TEST_COMPARE_BLOB (&peer.sin_addr, sizeof (peer.sin_addr),
+ &server_address.sin_addr,
+ sizeof (server_address.sin_addr));
+
+ int status;
+ xwaitpid (serv_pid, &status, 0);
+ TEST_COMPARE (status, 0);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

@ -1,66 +0,0 @@
commit 6687a6e3f962759536a8019d31c68c1009ccd6eb
Author: Sergey Kolosov <skolosov@redhat.com>
Date: Wed Apr 10 17:58:04 2024 +0200
libsupport: Add xgetpeername
The patch adds redirections for getpeername.
Reviewed-by: Arjun Shankar <arjun@redhat.com>
diff -Nrup a/support/Makefile b/support/Makefile
--- a/support/Makefile 2024-05-19 23:27:12.379362736 -0400
+++ b/support/Makefile 2024-05-19 23:29:28.668182089 -0400
@@ -126,6 +126,7 @@ libsupport-routines = \
xfork \
xftruncate \
xgetline \
+ xgetpeername \
xgetsockname \
xlisten \
xlseek \
diff -Nrup a/support/xgetpeername.c b/support/xgetpeername.c
--- a/support/xgetpeername.c 1969-12-31 19:00:00.000000000 -0500
+++ b/support/xgetpeername.c 2024-05-19 23:30:31.852561947 -0400
@@ -0,0 +1,30 @@
+/* getpeername with error checking.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/xsocket.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check.h>
+
+void
+xgetpeername (int fd, struct sockaddr *sa, socklen_t *plen)
+{
+ if (getpeername (fd, sa, plen) != 0)
+ FAIL_EXIT1 ("getpeername (%d): %m", fd);
+}
diff -Nrup a/support/xsocket.h b/support/xsocket.h
--- a/support/xsocket.h 2021-08-01 21:33:43.000000000 -0400
+++ b/support/xsocket.h 2024-05-19 23:31:24.541878715 -0400
@@ -26,6 +26,7 @@
int xsocket (int, int, int);
void xsetsockopt (int, int, int, const void *, socklen_t);
void xgetsockname (int, struct sockaddr *, socklen_t *);
+void xgetpeername (int, struct sockaddr *, socklen_t *);
void xconnect (int, const struct sockaddr *, socklen_t);
void xbind (int, const struct sockaddr *, socklen_t);
void xlisten (int, int);

@ -1,31 +0,0 @@
commit 87801a8fd06db1d654eea3e4f7626ff476a9bdaa
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 25 15:00:45 2024 +0200
CVE-2024-33599: nscd: Stack-based buffer overflow in netgroup cache (bug 31677)
Using alloca matches what other caches do. The request length is
bounded by MAXKEYLEN.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
index 0c6e46f15c..f227dc7fa2 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -502,12 +502,13 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
= (struct indataset *) mempool_alloc (db,
sizeof (*dataset) + req->key_len,
1);
- struct indataset dataset_mem;
bool cacheable = true;
if (__glibc_unlikely (dataset == NULL))
{
cacheable = false;
- dataset = &dataset_mem;
+ /* The alloca is safe because nscd_run_worker verfies that
+ key_len is not larger than MAXKEYLEN. */
+ dataset = alloca (sizeof (*dataset) + req->key_len);
}
datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,

@ -1,53 +0,0 @@
commit b048a482f088e53144d26a61c390bed0210f49f2
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 25 15:01:07 2024 +0200
CVE-2024-33600: nscd: Avoid null pointer crashes after notfound response (bug 31678)
The addgetnetgrentX call in addinnetgrX may have failed to produce
a result, so the result variable in addinnetgrX can be NULL.
Use db->negtimeout as the fallback value if there is no result data;
the timeout is also overwritten below.
Also avoid sending a second not-found response. (The client
disconnects after receiving the first response, so the data stream did
not go out of sync even without this fix.) It is still beneficial to
add the negative response to the mapping, so that the client can get
it from there in the future, instead of going through the socket.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
index c18fe111f3..e22ffa5884 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -511,14 +511,15 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
sizeof (innetgroup_response_header),
- he == NULL ? 0 : dh->nreloads + 1, result->head.ttl);
+ he == NULL ? 0 : dh->nreloads + 1,
+ result == NULL ? db->negtimeout : result->head.ttl);
/* Set the notfound status and timeout based on the result from
getnetgrent. */
- dataset->head.notfound = result->head.notfound;
+ dataset->head.notfound = result == NULL || result->head.notfound;
dataset->head.timeout = timeout;
dataset->resp.version = NSCD_VERSION;
- dataset->resp.found = result->resp.found;
+ dataset->resp.found = result != NULL && result->resp.found;
/* Until we find a matching entry the result is 0. */
dataset->resp.result = 0;
@@ -566,7 +567,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
goto out;
}
- if (he == NULL)
+ /* addgetnetgrentX may have already sent a notfound response. Do
+ not send another one. */
+ if (he == NULL && dataset->resp.found)
{
/* We write the dataset before inserting it to the database
since while inserting this thread might block and so would

@ -1,52 +0,0 @@
commit 7835b00dbce53c3c87bbbb1754a95fb5e58187aa
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 25 15:01:07 2024 +0200
CVE-2024-33600: nscd: Do not send missing not-found response in addgetnetgrentX (bug 31678)
If we failed to add a not-found response to the cache, the dataset
point can be null, resulting in a null pointer dereference.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
index f227dc7fa2..c18fe111f3 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -147,7 +147,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
/* No such service. */
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
&key_copy);
- goto writeout;
+ goto maybe_cache_add;
}
memset (&data, '\0', sizeof (data));
@@ -348,7 +348,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
{
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
&key_copy);
- goto writeout;
+ goto maybe_cache_add;
}
total = buffilled;
@@ -410,14 +410,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
}
if (he == NULL && fd != -1)
- {
- /* We write the dataset before inserting it to the database
- since while inserting this thread might block and so would
- unnecessarily let the receiver wait. */
- writeout:
+ /* We write the dataset before inserting it to the database since
+ while inserting this thread might block and so would
+ unnecessarily let the receiver wait. */
writeall (fd, &dataset->resp, dataset->head.recsize);
- }
+ maybe_cache_add:
if (cacheable)
{
/* If necessary, we also propagate the data to disk. */

@ -1,382 +0,0 @@
commit c04a21e050d64a1193a6daab872bca2528bda44b
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 25 15:01:07 2024 +0200
CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX (bug 31680)
This avoids potential memory corruption when the underlying NSS
callback function does not use the buffer space to store all strings
(e.g., for constant strings).
Instead of custom buffer management, two scratch buffers are used.
This increases stack usage somewhat.
Scratch buffer allocation failure is handled by return -1
(an invalid timeout value) instead of terminating the process.
This fixes bug 31679.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
diff -Nrup glibc-2.34/nscd/netgroupcache.c b/nscd/netgroupcache.c
--- glibc-2.34/nscd/netgroupcache.c 2024-06-13 13:55:16.406511485 -0400
+++ b/nscd/netgroupcache.c 2024-06-13 13:34:45.523345077 -0400
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <scratch_buffer.h>
#include "../inet/netgroup.h"
#include "nscd.h"
@@ -66,6 +67,16 @@ struct dataset
char strdata[0];
};
+/* Send a notfound response to FD. Always returns -1 to indicate an
+ ephemeral error. */
+static time_t
+send_notfound (int fd)
+{
+ if (fd != -1)
+ TEMP_FAILURE_RETRY (send (fd, &notfound, sizeof (notfound), MSG_NOSIGNAL));
+ return -1;
+}
+
/* Sends a notfound message and prepares a notfound dataset to write to the
cache. Returns true if there was enough memory to allocate the dataset and
returns the dataset in DATASETP, total bytes to write in TOTALP and the
@@ -84,8 +95,7 @@ do_notfound (struct database_dyn *db, in
total = sizeof (notfound);
timeout = time (NULL) + db->negtimeout;
- if (fd != -1)
- TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
+ send_notfound (fd);
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
/* If we cannot permanently store the result, so be it. */
@@ -110,11 +120,78 @@ do_notfound (struct database_dyn *db, in
return cacheable;
}
+struct addgetnetgrentX_scratch
+{
+ /* This is the result that the caller should use. It can be NULL,
+ point into buffer, or it can be in the cache. */
+ struct dataset *dataset;
+
+ struct scratch_buffer buffer;
+
+ /* Used internally in addgetnetgrentX as a staging area. */
+ struct scratch_buffer tmp;
+
+ /* Number of bytes in buffer that are actually used. */
+ size_t buffer_used;
+};
+
+static void
+addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch)
+{
+ scratch->dataset = NULL;
+ scratch_buffer_init (&scratch->buffer);
+ scratch_buffer_init (&scratch->tmp);
+
+ /* Reserve space for the header. */
+ scratch->buffer_used = sizeof (struct dataset);
+ static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space),
+ "initial buffer space");
+ memset (scratch->tmp.data, 0, sizeof (struct dataset));
+}
+
+static void
+addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch)
+{
+ scratch_buffer_free (&scratch->buffer);
+ scratch_buffer_free (&scratch->tmp);
+}
+
+/* Copy LENGTH bytes from S into SCRATCH. Returns NULL if SCRATCH
+ could not be resized, otherwise a pointer to the copy. */
+static char *
+addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch,
+ const char *s, size_t length)
+{
+ while (true)
+ {
+ size_t remaining = scratch->buffer.length - scratch->buffer_used;
+ if (remaining >= length)
+ break;
+ if (!scratch_buffer_grow_preserve (&scratch->buffer))
+ return NULL;
+ }
+ char *copy = scratch->buffer.data + scratch->buffer_used;
+ memcpy (copy, s, length);
+ scratch->buffer_used += length;
+ return copy;
+}
+
+/* Copy S into SCRATCH, including its null terminator. Returns false
+ if SCRATCH could not be resized. */
+static bool
+addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s)
+{
+ if (s == NULL)
+ s = "";
+ return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL;
+}
+
+/* Caller must initialize and free *SCRATCH. If the return value is
+ negative, this function has sent a notfound response. */
static time_t
addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
const char *key, uid_t uid, struct hashentry *he,
- struct datahead *dh, struct dataset **resultp,
- void **tofreep)
+ struct datahead *dh, struct addgetnetgrentX_scratch *scratch)
{
if (__glibc_unlikely (debug_level > 0))
{
@@ -133,14 +210,10 @@ addgetnetgrentX (struct database_dyn *db
char *key_copy = NULL;
struct __netgrent data;
- size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len);
- size_t buffilled = sizeof (*dataset);
- char *buffer = NULL;
size_t nentries = 0;
size_t group_len = strlen (key) + 1;
struct name_list *first_needed
= alloca (sizeof (struct name_list) + group_len);
- *tofreep = NULL;
if (netgroup_database == NULL
&& !__nss_database_get (nss_database_netgroup, &netgroup_database))
@@ -152,8 +225,6 @@ addgetnetgrentX (struct database_dyn *db
}
memset (&data, '\0', sizeof (data));
- buffer = xmalloc (buflen);
- *tofreep = buffer;
first_needed->next = first_needed;
memcpy (first_needed->name, key, group_len);
data.needed_groups = first_needed;
@@ -196,8 +267,8 @@ addgetnetgrentX (struct database_dyn *db
while (1)
{
int e;
- status = getfct.f (&data, buffer + buffilled,
- buflen - buffilled - req->key_len, &e);
+ status = getfct.f (&data, scratch->tmp.data,
+ scratch->tmp.length, &e);
if (status == NSS_STATUS_SUCCESS)
{
if (data.type == triple_val)
@@ -205,68 +276,10 @@ addgetnetgrentX (struct database_dyn *db
const char *nhost = data.val.triple.host;
const char *nuser = data.val.triple.user;
const char *ndomain = data.val.triple.domain;
-
- size_t hostlen = strlen (nhost ?: "") + 1;
- size_t userlen = strlen (nuser ?: "") + 1;
- size_t domainlen = strlen (ndomain ?: "") + 1;
-
- if (nhost == NULL || nuser == NULL || ndomain == NULL
- || nhost > nuser || nuser > ndomain)
- {
- const char *last = nhost;
- if (last == NULL
- || (nuser != NULL && nuser > last))
- last = nuser;
- if (last == NULL
- || (ndomain != NULL && ndomain > last))
- last = ndomain;
-
- size_t bufused
- = (last == NULL
- ? buffilled
- : last + strlen (last) + 1 - buffer);
-
- /* We have to make temporary copies. */
- size_t needed = hostlen + userlen + domainlen;
-
- if (buflen - req->key_len - bufused < needed)
- {
- buflen += MAX (buflen, 2 * needed);
- /* Save offset in the old buffer. We don't
- bother with the NULL check here since
- we'll do that later anyway. */
- size_t nhostdiff = nhost - buffer;
- size_t nuserdiff = nuser - buffer;
- size_t ndomaindiff = ndomain - buffer;
-
- char *newbuf = xrealloc (buffer, buflen);
- /* Fix up the triplet pointers into the new
- buffer. */
- nhost = (nhost ? newbuf + nhostdiff
- : NULL);
- nuser = (nuser ? newbuf + nuserdiff
- : NULL);
- ndomain = (ndomain ? newbuf + ndomaindiff
- : NULL);
- *tofreep = buffer = newbuf;
- }
-
- nhost = memcpy (buffer + bufused,
- nhost ?: "", hostlen);
- nuser = memcpy ((char *) nhost + hostlen,
- nuser ?: "", userlen);
- ndomain = memcpy ((char *) nuser + userlen,
- ndomain ?: "", domainlen);
- }
-
- char *wp = buffer + buffilled;
- wp = memmove (wp, nhost ?: "", hostlen);
- wp += hostlen;
- wp = memmove (wp, nuser ?: "", userlen);
- wp += userlen;
- wp = memmove (wp, ndomain ?: "", domainlen);
- wp += domainlen;
- buffilled = wp - buffer;
+ if (!(addgetnetgrentX_append (scratch, nhost)
+ && addgetnetgrentX_append (scratch, nuser)
+ && addgetnetgrentX_append (scratch, ndomain)))
+ return send_notfound (fd);
++nentries;
}
else
@@ -318,8 +331,8 @@ addgetnetgrentX (struct database_dyn *db
}
else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
{
- buflen *= 2;
- *tofreep = buffer = xrealloc (buffer, buflen);
+ if (!scratch_buffer_grow (&scratch->tmp))
+ return send_notfound (fd);
}
else if (status == NSS_STATUS_RETURN
|| status == NSS_STATUS_NOTFOUND
@@ -352,10 +365,17 @@ addgetnetgrentX (struct database_dyn *db
goto maybe_cache_add;
}
- total = buffilled;
+ /* Capture the result size without the key appended. */
+ total = scratch->buffer_used;
+
+ /* Make a copy of the key. The scratch buffer must not move after
+ this point. */
+ key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len);
+ if (key_copy == NULL)
+ return send_notfound (fd);
/* Fill in the dataset. */
- dataset = (struct dataset *) buffer;
+ dataset = scratch->buffer.data;
timeout = datahead_init_pos (&dataset->head, total + req->key_len,
total - offsetof (struct dataset, resp),
he == NULL ? 0 : dh->nreloads + 1,
@@ -364,11 +384,7 @@ addgetnetgrentX (struct database_dyn *db
dataset->resp.version = NSCD_VERSION;
dataset->resp.found = 1;
dataset->resp.nresults = nentries;
- dataset->resp.result_len = buffilled - sizeof (*dataset);
-
- assert (buflen - buffilled >= req->key_len);
- key_copy = memcpy (buffer + buffilled, key, req->key_len);
- buffilled += req->key_len;
+ dataset->resp.result_len = total - sizeof (*dataset);
/* Now we can determine whether on refill we have to create a new
record or not. */
@@ -399,7 +415,7 @@ addgetnetgrentX (struct database_dyn *db
if (__glibc_likely (newp != NULL))
{
/* Adjust pointer into the memory block. */
- key_copy = (char *) newp + (key_copy - buffer);
+ key_copy = (char *) newp + (key_copy - (char *) dataset);
dataset = memcpy (newp, dataset, total + req->key_len);
cacheable = true;
@@ -440,7 +456,7 @@ addgetnetgrentX (struct database_dyn *db
}
out:
- *resultp = dataset;
+ scratch->dataset = dataset;
return timeout;
}
@@ -461,6 +477,9 @@ addinnetgrX (struct database_dyn *db, in
if (user != NULL)
key = (char *) rawmemchr (key, '\0') + 1;
const char *domain = *key++ ? key : NULL;
+ struct addgetnetgrentX_scratch scratch;
+
+ addgetnetgrentX_scratch_init (&scratch);
if (__glibc_unlikely (debug_level > 0))
{
@@ -476,12 +495,8 @@ addinnetgrX (struct database_dyn *db, in
group, group_len,
db, uid);
time_t timeout;
- void *tofree;
if (result != NULL)
- {
- timeout = result->head.timeout;
- tofree = NULL;
- }
+ timeout = result->head.timeout;
else
{
request_header req_get =
@@ -490,7 +505,10 @@ addinnetgrX (struct database_dyn *db, in
.key_len = group_len
};
timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
- &result, &tofree);
+ &scratch);
+ result = scratch.dataset;
+ if (timeout < 0)
+ goto out;
}
struct indataset
@@ -604,7 +622,7 @@ addinnetgrX (struct database_dyn *db, in
}
out:
- free (tofree);
+ addgetnetgrentX_scratch_free (&scratch);
return timeout;
}
@@ -614,11 +632,12 @@ addgetnetgrentX_ignore (struct database_
const char *key, uid_t uid, struct hashentry *he,
struct datahead *dh)
{
- struct dataset *ignore;
- void *tofree;
- time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
- &ignore, &tofree);
- free (tofree);
+ struct addgetnetgrentX_scratch scratch;
+ addgetnetgrentX_scratch_init (&scratch);
+ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch);
+ addgetnetgrentX_scratch_free (&scratch);
+ if (timeout < 0)
+ timeout = 0;
return timeout;
}
@@ -662,5 +681,9 @@ readdinnetgr (struct database_dyn *db, s
.key_len = he->len
};
- return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh);
+ int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
+ he, dh);
+ if (timeout < 0)
+ timeout = 0;
+ return timeout;
}

@ -1,30 +0,0 @@
commit 4bbca1a44691a6e9adcee5c6798a707b626bc331
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu May 2 17:06:19 2024 +0200
nscd: Use time_t for return type of addgetnetgrentX
Using int may give false results for future dates (timeouts after the
year 2028).
Fixes commit 04a21e050d64a1193a6daab872bca2528bda44b ("CVE-2024-33601,
CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX
(bug 31680)").
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
index 4b35498e3f..5fdcf4204e 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -680,8 +680,8 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he,
.key_len = he->len
};
- int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
- he, dh);
+ time_t timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
+ he, dh);
if (timeout < 0)
timeout = 0;
return timeout;

@ -1,88 +0,0 @@
commit fe06fb313bddf7e4530056897d4a706606e49377
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Aug 1 23:31:23 2024 +0200
elf: Clarify and invert second argument of _dl_allocate_tls_init
Also remove an outdated comment: _dl_allocate_tls_init is
called as part of pthread_create.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff -Nrup a/elf/dl-tls.c b/elf/dl-tls.c
--- a/elf/dl-tls.c 2024-08-27 22:51:44.720953314 -0400
+++ b/elf/dl-tls.c 2024-08-27 22:51:07.686759191 -0400
@@ -558,9 +558,14 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_m
/* Allocate initial TLS. RESULT should be a non-NULL pointer to storage
for the TLS space. The DTV may be resized, and so this function may
call malloc to allocate that space. The loader's GL(dl_load_tls_lock)
- is taken when manipulating global TLS-related data in the loader. */
+ is taken when manipulating global TLS-related data in the loader.
+
+ If MAIN_THREAD, this is the first call during process
+ initialization. In this case, TLS initialization for secondary
+ (audit) namespaces is skipped because that has already been handled
+ by dlopen. */
void *
-_dl_allocate_tls_init (void *result, bool init_tls)
+_dl_allocate_tls_init (void *result, bool main_thread)
{
if (result == NULL)
/* The memory allocation failed. */
@@ -639,7 +644,7 @@ _dl_allocate_tls_init (void *result, boo
because it would already be set by the audit setup. However,
subsequent thread creation would need to follow the default
behaviour. */
- if (map->l_ns != LM_ID_BASE && !init_tls)
+ if (map->l_ns != LM_ID_BASE && main_thread)
continue;
memset (__mempcpy (dest, map->l_tls_initimage,
map->l_tls_initimage_size), '\0',
@@ -667,7 +672,7 @@ _dl_allocate_tls (void *mem)
{
return _dl_allocate_tls_init (mem == NULL
? _dl_allocate_tls_storage ()
- : allocate_dtv (mem), true);
+ : allocate_dtv (mem), false);
}
rtld_hidden_def (_dl_allocate_tls)
diff -Nrup a/elf/rtld.c b/elf/rtld.c
--- a/elf/rtld.c 2024-08-27 22:51:44.720953314 -0400
+++ b/elf/rtld.c 2024-08-27 22:54:51.136930475 -0400
@@ -2485,7 +2485,7 @@ dl_main (const ElfW(Phdr) *phdr,
into the main thread's TLS area, which we allocated above.
Note: thread-local variables must only be accessed after completing
the next step. */
- _dl_allocate_tls_init (tcbp, false);
+ _dl_allocate_tls_init (tcbp, true);
/* And finally install it for the main thread. */
if (! tls_init_tp_called)
diff -Nrup a/nptl/allocatestack.c b/nptl/allocatestack.c
--- a/nptl/allocatestack.c 2024-08-27 22:51:43.922949131 -0400
+++ b/nptl/allocatestack.c 2024-08-27 22:51:07.687759197 -0400
@@ -137,7 +137,7 @@ get_cached_stack (size_t *sizep, void **
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
/* Re-initialize the TLS. */
- _dl_allocate_tls_init (TLS_TPADJ (result), true);
+ _dl_allocate_tls_init (TLS_TPADJ (result), false);
return result;
}
diff -Nrup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
--- a/sysdeps/generic/ldsodefs.h 2024-08-27 22:51:44.720953314 -0400
+++ b/sysdeps/generic/ldsodefs.h 2024-08-27 22:56:44.425524320 -0400
@@ -1258,10 +1258,8 @@ extern void _dl_get_tls_static_info (siz
extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden;
-/* These are internal entry points to the two halves of _dl_allocate_tls,
- only used within rtld.c itself at startup time. */
extern void *_dl_allocate_tls_storage (void) attribute_hidden;
-extern void *_dl_allocate_tls_init (void *, bool);
+extern void *_dl_allocate_tls_init (void *result, bool main_thread);
rtld_hidden_proto (_dl_allocate_tls_init)
/* Deallocate memory allocated with _dl_allocate_tls. */

@ -1,520 +0,0 @@
commit 5097cd344fd243fb8deb6dec96e8073753f962f9
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Aug 1 23:31:30 2024 +0200
elf: Avoid re-initializing already allocated TLS in dlopen (bug 31717)
The old code used l_init_called as an indicator for whether TLS
initialization was complete. However, it is possible that
TLS for an object is initialized, written to, and then dlopen
for this object is called again, and l_init_called is not true at
this point. Previously, this resulted in TLS being initialized
twice, discarding any interim writes (technically introducing a
use-after-free bug even).
This commit introduces an explicit per-object flag, l_tls_in_slotinfo.
It indicates whether _dl_add_to_slotinfo has been called for this
object. This flag is used to avoid double-initialization of TLS.
In update_tls_slotinfo, the first_static_tls micro-optimization
is removed because preserving the initalization flag for subsequent
use by the second loop for static TLS is a bit complicated, and
another per-object flag does not seem to be worth it. Furthermore,
the l_init_called flag is dropped from the second loop (for static
TLS initialization) because l_need_tls_init on its own prevents
double-initialization.
The remaining l_init_called usage in resize_scopes and update_scopes
is just an optimization due to the use of scope_has_map, so it is
not changed in this commit.
The isupper check ensures that libc.so.6 is TLS is not reverted.
Such a revert happens if l_need_tls_init is not cleared in
_dl_allocate_tls_init for the main_thread case, now that
l_init_called is not checked anymore in update_tls_slotinfo
in elf/dl-open.c.
Reported-by: Jonathon Anderson <janderson@rice.edu>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff -Nrup a/elf/Makefile b/elf/Makefile
--- a/elf/Makefile 2024-08-27 23:25:59.327755050 -0400
+++ b/elf/Makefile 2024-08-27 23:16:50.456864065 -0400
@@ -399,6 +399,10 @@ tests += \
tst-dlmopen-dlerror \
tst-dlmopen-gethostbyname \
tst-dlmopen-twice \
+ tst-dlopen-tlsreinit1 \
+ tst-dlopen-tlsreinit2 \
+ tst-dlopen-tlsreinit3 \
+ tst-dlopen-tlsreinit4 \
tst-dlopenfail \
tst-dlopenfail-2 \
tst-dlopenrpath \
@@ -753,6 +757,9 @@ modules-names = \
tst-dlmopen-gethostbyname-mod \
tst-dlmopen-twice-mod1 \
tst-dlmopen-twice-mod2 \
+ tst-dlopen-tlsreinitmod1 \
+ tst-dlopen-tlsreinitmod2 \
+ tst-dlopen-tlsreinitmod3 \
tst-dlopenfaillinkmod \
tst-dlopenfailmod1 \
tst-dlopenfailmod2 \
@@ -2751,3 +2758,26 @@ $(objpfx)tst-recursive-tls.out: \
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
$(objpfx)tst-recursive-tlsmod%.os: tst-recursive-tlsmodN.c
$(compile-command.c) -DVAR=thread_$* -DFUNC=get_threadvar_$*
+
+# Order matters here. The test needs the constructor for
+# tst-dlopen-tlsreinitmod2.so to be called first.
+LDFLAGS-tst-dlopen-tlsreinitmod1.so = -Wl,--no-as-needed
+$(objpfx)tst-dlopen-tlsreinitmod1.so: \
+ $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
+LDFLAGS-tst-dlopen-tlsreinit2 = -Wl,--no-as-needed
+$(objpfx)tst-dlopen-tlsreinit2: \
+ $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
+LDFLAGS-tst-dlopen-tlsreinit4 = -Wl,--no-as-needed
+$(objpfx)tst-dlopen-tlsreinit4: \
+ $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so
+# tst-dlopen-tlsreinitmod2.so is underlinked and refers to
+# tst-dlopen-tlsreinitmod3.so. The dependency is provided via
+# $(objpfx)tst-dlopen-tlsreinitmod1.so.
+tst-dlopen-tlsreinitmod2.so-no-z-defs = yes
+$(objpfx)tst-dlopen-tlsreinit.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
+ $(objpfx)tst-dlopen-tlsreinitmod2.so $(objpfx)tst-dlopen-tlsreinitmod3.so
+# Reuse an audit module which provides ample debug logging.
+$(objpfx)tst-dlopen-tlsreinit3.out: $(objpfx)tst-auditmod1.so
+tst-dlopen-tlsreinit3-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
+$(objpfx)tst-dlopen-tlsreinit4.out: $(objpfx)tst-auditmod1.so
+tst-dlopen-tlsreinit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
diff -Nrup a/elf/dl-open.c b/elf/dl-open.c
--- a/elf/dl-open.c 2024-08-27 23:25:59.237754576 -0400
+++ b/elf/dl-open.c 2024-08-27 23:10:52.497978645 -0400
@@ -362,17 +362,8 @@ resize_tls_slotinfo (struct link_map *ne
{
bool any_tls = false;
for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
- {
- struct link_map *imap = new->l_searchlist.r_list[i];
-
- /* Only add TLS memory if this object is loaded now and
- therefore is not yet initialized. */
- if (! imap->l_init_called && imap->l_tls_blocksize > 0)
- {
- _dl_add_to_slotinfo (imap, false);
- any_tls = true;
- }
- }
+ if (_dl_add_to_slotinfo (new->l_searchlist.r_list[i], false))
+ any_tls = true;
return any_tls;
}
@@ -382,22 +373,8 @@ resize_tls_slotinfo (struct link_map *ne
static void
update_tls_slotinfo (struct link_map *new)
{
- unsigned int first_static_tls = new->l_searchlist.r_nlist;
for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
- {
- struct link_map *imap = new->l_searchlist.r_list[i];
-
- /* Only add TLS memory if this object is loaded now and
- therefore is not yet initialized. */
- if (! imap->l_init_called && imap->l_tls_blocksize > 0)
- {
- _dl_add_to_slotinfo (imap, true);
-
- if (imap->l_need_tls_init
- && first_static_tls == new->l_searchlist.r_nlist)
- first_static_tls = i;
- }
- }
+ _dl_add_to_slotinfo (new->l_searchlist.r_list[i], true);
size_t newgen = GL(dl_tls_generation) + 1;
if (__glibc_unlikely (newgen == 0))
@@ -409,13 +386,11 @@ TLS generation counter wrapped! Please
/* We need a second pass for static tls data, because
_dl_update_slotinfo must not be run while calls to
_dl_add_to_slotinfo are still pending. */
- for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i)
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
{
struct link_map *imap = new->l_searchlist.r_list[i];
- if (imap->l_need_tls_init
- && ! imap->l_init_called
- && imap->l_tls_blocksize > 0)
+ if (imap->l_need_tls_init && imap->l_tls_blocksize > 0)
{
/* For static TLS we have to allocate the memory here and
now, but we can delay updating the DTV. */
diff -Nrup a/elf/dl-tls.c b/elf/dl-tls.c
--- a/elf/dl-tls.c 2024-08-27 23:25:59.358755213 -0400
+++ b/elf/dl-tls.c 2024-08-27 23:21:04.960204566 -0400
@@ -638,17 +638,21 @@ _dl_allocate_tls_init (void *result, boo
some platforms use in static programs requires it. */
dtv[map->l_tls_modid].pointer.val = dest;
- /* Copy the initialization image and clear the BSS part. For
- audit modules or dependencies with initial-exec TLS, we can not
- set the initial TLS image on default loader initialization
- because it would already be set by the audit setup. However,
- subsequent thread creation would need to follow the default
- behaviour. */
+ /* Copy the initialization image and clear the BSS part.
+ For audit modules or dependencies with initial-exec TLS,
+ we can not set the initial TLS image on default loader
+ initialization because it would already be set by the
+ audit setup, which uses the dlopen code and already
+ clears l_need_tls_init. Calls with !main_thread from
+ pthread_create need to initialze TLS for the current
+ thread regardless of namespace. */
if (map->l_ns != LM_ID_BASE && main_thread)
continue;
memset (__mempcpy (dest, map->l_tls_initimage,
map->l_tls_initimage_size), '\0',
map->l_tls_blocksize - map->l_tls_initimage_size);
+ if (main_thread)
+ map->l_need_tls_init = 0;
}
total += cnt;
@@ -1105,9 +1109,32 @@ _dl_tls_initial_modid_limit_setup (void)
}
-void
+/* Add module to slot information data. If DO_ADD is false, only the
+ required memory is allocated. Must be called with
+ GL (dl_load_tls_lock) acquired. If the function has already been
+ called for the link map L with !DO_ADD, then this function will not
+ raise an exception, otherwise it is possible that it encounters a
+ memory allocation failure.
+
+ Return false if L has already been added to the slotinfo data, or
+ if L has no TLS data. If the returned value is true, L has been
+ added with this call (DO_ADD), or has been added in a previous call
+ (!DO_ADD).
+
+ The expected usage is as follows: Call _dl_add_to_slotinfo for
+ several link maps with DO_ADD set to false, and record if any calls
+ result in a true result. If there was a true result, call
+ _dl_add_to_slotinfo again, this time with DO_ADD set to true. (For
+ simplicity, it's possible to call the function for link maps where
+ the previous result was false.) The return value from the second
+ round of calls can be ignored. If there was true result initially,
+ call _dl_update_slotinfo to update the TLS generation counter. */
+bool
_dl_add_to_slotinfo (struct link_map *l, bool do_add)
{
+ if (l->l_tls_blocksize == 0 || l->l_tls_in_slotinfo)
+ return false;
+
/* Now that we know the object is loaded successfully add
modules containing TLS data to the dtv info table. We
might have to increase its size. */
@@ -1163,7 +1190,10 @@ cannot create TLS data structures"));
atomic_store_relaxed (&listp->slotinfo[idx].map, l);
atomic_store_relaxed (&listp->slotinfo[idx].gen,
GL(dl_tls_generation) + 1);
+ l->l_tls_in_slotinfo = true;
}
+
+ return true;
}
#if THREAD_GSCOPE_IN_TCB
diff -Nrup a/elf/tst-dlopen-tlsreinit1.c b/elf/tst-dlopen-tlsreinit1.c
--- a/elf/tst-dlopen-tlsreinit1.c 1969-12-31 19:00:00.000000000 -0500
+++ b/elf/tst-dlopen-tlsreinit1.c 2024-08-27 23:10:52.497978645 -0400
@@ -0,0 +1,40 @@
+/* Test that dlopen preserves already accessed TLS (bug 31717).
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdbool.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+#include <ctype.h>
+
+static int
+do_test (void)
+{
+ void *handle = xdlopen ("tst-dlopen-tlsreinitmod1.so", RTLD_NOW);
+
+ bool *tlsreinitmod3_tested = xdlsym (handle, "tlsreinitmod3_tested");
+ TEST_VERIFY (*tlsreinitmod3_tested);
+
+ xdlclose (handle);
+
+ /* This crashes if the libc.so.6 TLS image has been reverted. */
+ TEST_VERIFY (!isupper ('@'));
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff -Nrup a/elf/tst-dlopen-tlsreinit2.c b/elf/tst-dlopen-tlsreinit2.c
--- a/elf/tst-dlopen-tlsreinit2.c 1969-12-31 19:00:00.000000000 -0500
+++ b/elf/tst-dlopen-tlsreinit2.c 2024-08-27 23:10:52.497978645 -0400
@@ -0,0 +1,39 @@
+/* Test that dlopen preserves already accessed TLS (bug 31717).
+ Variant with initially-linked modules.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+
+static int
+do_test (void)
+{
+ /* Defined in tst-dlopen-tlsreinitmod3.so. */
+ extern bool tlsreinitmod3_tested;
+ TEST_VERIFY (tlsreinitmod3_tested);
+
+ /* This crashes if the libc.so.6 TLS image has been reverted. */
+ TEST_VERIFY (!isupper ('@'));
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff -Nrup a/elf/tst-dlopen-tlsreinit3.c b/elf/tst-dlopen-tlsreinit3.c
--- a/elf/tst-dlopen-tlsreinit3.c 1969-12-31 19:00:00.000000000 -0500
+++ b/elf/tst-dlopen-tlsreinit3.c 2024-08-27 23:10:52.497978645 -0400
@@ -0,0 +1,2 @@
+/* Same code, but run with LD_AUDIT=tst-auditmod1.so. */
+#include "tst-dlopen-tlsreinit1.c"
diff -Nrup a/elf/tst-dlopen-tlsreinit4.c b/elf/tst-dlopen-tlsreinit4.c
--- a/elf/tst-dlopen-tlsreinit4.c 1969-12-31 19:00:00.000000000 -0500
+++ b/elf/tst-dlopen-tlsreinit4.c 2024-08-27 23:10:52.497978645 -0400
@@ -0,0 +1,2 @@
+/* Same code, but run with LD_AUDIT=tst-auditmod1.so. */
+#include "tst-dlopen-tlsreinit2.c"
diff -Nrup a/elf/tst-dlopen-tlsreinitmod1.c b/elf/tst-dlopen-tlsreinitmod1.c
--- a/elf/tst-dlopen-tlsreinitmod1.c 1969-12-31 19:00:00.000000000 -0500
+++ b/elf/tst-dlopen-tlsreinitmod1.c 2024-08-27 23:10:52.497978645 -0400
@@ -0,0 +1,20 @@
+/* Test that dlopen preserves already accessed TLS (bug 31717), module 1.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* This module triggers loading of tst-dlopen-tlsreinitmod2.so and
+ tst-dlopen-tlsreinitmod3.so. */
diff -Nrup a/elf/tst-dlopen-tlsreinitmod2.c b/elf/tst-dlopen-tlsreinitmod2.c
--- a/elf/tst-dlopen-tlsreinitmod2.c 1969-12-31 19:00:00.000000000 -0500
+++ b/elf/tst-dlopen-tlsreinitmod2.c 2024-08-27 23:10:52.497978645 -0400
@@ -0,0 +1,30 @@
+/* Test that dlopen preserves already accessed TLS (bug 31717), module 2.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+
+/* Defined in tst-dlopen-tlsreinitmod3.so. This an underlinked symbol
+ dependency. */
+extern void call_tlsreinitmod3 (void);
+
+static void __attribute__ ((constructor))
+tlsreinitmod2_init (void)
+{
+ puts ("info: constructor of tst-dlopen-tlsreinitmod2.so invoked");
+ call_tlsreinitmod3 ();
+}
diff -Nrup a/elf/tst-dlopen-tlsreinitmod3.c b/elf/tst-dlopen-tlsreinitmod3.c
--- a/elf/tst-dlopen-tlsreinitmod3.c 1969-12-31 19:00:00.000000000 -0500
+++ b/elf/tst-dlopen-tlsreinitmod3.c 2024-08-27 23:10:52.498978651 -0400
@@ -0,0 +1,102 @@
+/* Test that dlopen preserves already accessed TLS (bug 31717), module 3.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/* Used to verify from the main program that the test ran. */
+bool tlsreinitmod3_tested;
+
+/* This TLS variable must not revert back to the initial state after
+ dlopen. */
+static __thread int tlsreinitmod3_state = 1;
+
+/* Set from the ELF constructor during dlopen. */
+static bool tlsreinitmod3_constructed;
+
+/* Second half of test, behind a compiler barrier. The compiler
+ barrier is necessary to prevent carrying over TLS address
+ information from call_tlsreinitmod3 to call_tlsreinitmod3_tail. */
+void call_tlsreinitmod3_tail (void *self) __attribute__ ((weak));
+
+/* Called from tst-dlopen-tlsreinitmod2.so. */
+void
+call_tlsreinitmod3 (void)
+{
+ printf ("info: call_tlsreinitmod3 invoked (state=%d)\n",
+ tlsreinitmod3_state);
+
+ if (tlsreinitmod3_constructed)
+ {
+ puts ("error: call_tlsreinitmod3 called after ELF constructor");
+ fflush (stdout);
+ /* Cannot rely on test harness due to dynamic linking. */
+ _exit (1);
+ }
+
+ tlsreinitmod3_state = 2;
+
+ /* Self-dlopen. This will run the ELF constructor. */
+ void *self = dlopen ("tst-dlopen-tlsreinitmod3.so", RTLD_NOW);
+ if (self == NULL)
+ {
+ printf ("error: dlopen: %s\n", dlerror ());
+ fflush (stdout);
+ /* Cannot rely on test harness due to dynamic linking. */
+ _exit (1);
+ }
+
+ call_tlsreinitmod3_tail (self);
+}
+
+void
+call_tlsreinitmod3_tail (void *self)
+{
+ printf ("info: dlopen returned in tlsreinitmod3 (state=%d)\n",
+ tlsreinitmod3_state);
+
+ if (!tlsreinitmod3_constructed)
+ {
+ puts ("error: dlopen did not call tlsreinitmod3 ELF constructor");
+ fflush (stdout);
+ /* Cannot rely on test harness due to dynamic linking. */
+ _exit (1);
+ }
+
+ if (tlsreinitmod3_state != 2)
+ {
+ puts ("error: TLS state reverted in tlsreinitmod3");
+ fflush (stdout);
+ /* Cannot rely on test harness due to dynamic linking. */
+ _exit (1);
+ }
+
+ dlclose (self);
+
+ /* Signal test completion to the main program. */
+ tlsreinitmod3_tested = true;
+}
+
+static void __attribute__ ((constructor))
+tlsreinitmod3_init (void)
+{
+ puts ("info: constructor of tst-dlopen-tlsreinitmod3.so invoked");
+ tlsreinitmod3_constructed = true;
+}
diff -Nrup a/include/link.h b/include/link.h
--- a/include/link.h 2024-08-27 23:25:58.503750710 -0400
+++ b/include/link.h 2024-08-27 23:23:42.209032820 -0400
@@ -211,6 +211,7 @@ struct link_map
freed, ie. not allocated with
the dummy malloc in ld.so. */
unsigned int l_ld_readonly:1; /* Nonzero if dynamic section is readonly. */
+ unsigned int l_tls_in_slotinfo:1; /* TLS slotinfo updated in dlopen. */
/* NODELETE status of the map. Only valid for maps of type
lt_loaded. Lazy binding sets l_nodelete_active directly,
diff -Nrup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
--- a/sysdeps/generic/ldsodefs.h 2024-08-27 23:25:59.359755218 -0400
+++ b/sysdeps/generic/ldsodefs.h 2024-08-27 23:10:52.498978651 -0400
@@ -1291,13 +1291,7 @@ extern void *_dl_open (const char *name,
extern int _dl_scope_free (void *) attribute_hidden;
-/* Add module to slot information data. If DO_ADD is false, only the
- required memory is allocated. Must be called with GL
- (dl_load_tls_lock) acquired. If the function has already been called
- for the link map L with !do_add, then this function will not raise
- an exception, otherwise it is possible that it encounters a memory
- allocation failure. */
-extern void _dl_add_to_slotinfo (struct link_map *l, bool do_add)
+extern bool _dl_add_to_slotinfo (struct link_map *l, bool do_add)
attribute_hidden;
/* Update slot information data for at least the generation of the

@ -1,16 +0,0 @@
Author: Patsy Griffin <patsy@redhat.com>
Fix a typo in naming tst-dlopen-tlsreinit1.out
diff -Nrup a/elf/Makefile b/elf/Makefile
--- a/elf/Makefile 2024-08-16 13:27:00.700921146 -0400
+++ b/elf/Makefile 2024-08-16 13:29:12.951628406 -0400
@@ -2802,7 +2802,7 @@ $(objpfx)tst-dlopen-tlsreinit4: \
# tst-dlopen-tlsreinitmod3.so. The dependency is provided via
# $(objpfx)tst-dlopen-tlsreinitmod1.so.
tst-dlopen-tlsreinitmod2.so-no-z-defs = yes
-$(objpfx)tst-dlopen-tlsreinit.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
+$(objpfx)tst-dlopen-tlsreinit1.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
$(objpfx)tst-dlopen-tlsreinitmod2.so $(objpfx)tst-dlopen-tlsreinitmod3.so
# Reuse an audit module which provides ample debug logging.
$(objpfx)tst-dlopen-tlsreinit3.out: $(objpfx)tst-auditmod1.so

@ -1,593 +0,0 @@
commit df11c05be91fda5ef490c76fd0d4a53821750116
Author: Joseph Myers <josmyers@redhat.com>
Date: Wed Jan 17 15:38:54 2024 +0000
Update syscall lists for Linux 6.7
Linux 6.7 adds the futex_requeue, futex_wait and futex_wake syscalls,
and enables map_shadow_stack for architectures previously missing it.
Update syscall-names.list and regenerate the arch-syscall.h headers
with build-many-glibcs.py update-syscalls.
Tested with build-many-glibcs.py.
Modified for RHEL by: Patsy Griffin <patsy@redhat.com>
diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
index 746991aa2f..1713897f85 100644
--- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
@@ -64,7 +64,10 @@
#define __NR_fsync 82
#define __NR_ftruncate 46
#define __NR_futex 98
+#define __NR_futex_requeue 456
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_get_mempolicy 236
#define __NR_get_robust_list 100
#define __NR_getcpu 168
@@ -126,6 +129,7 @@
#define __NR_lseek 62
#define __NR_lsetxattr 6
#define __NR_madvise 233
+#define __NR_map_shadow_stack 453
#define __NR_mbind 235
#define __NR_membarrier 283
#define __NR_memfd_create 279
diff --git a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
index 32efe51267..5457d2d8ae 100644
--- a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
@@ -80,7 +80,10 @@
#define __NR_fsync 95
#define __NR_ftruncate 130
#define __NR_futex 394
+#define __NR_futex_requeue 566
+#define __NR_futex_wait 565
#define __NR_futex_waitv 559
+#define __NR_futex_wake 564
#define __NR_futimesat 454
#define __NR_get_kernel_syms 309
#define __NR_get_mempolicy 430
@@ -156,6 +159,7 @@
#define __NR_lstat 68
#define __NR_lstat64 426
#define __NR_madvise 75
+#define __NR_map_shadow_stack 563
#define __NR_mbind 429
#define __NR_membarrier 517
#define __NR_memfd_create 512
diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
index 1d2879e877..a66471c83a 100644
--- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
@@ -66,8 +66,11 @@
#define __NR_fstatfs64 44
#define __NR_fsync 82
#define __NR_ftruncate64 46
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_get_mempolicy 236
#define __NR_get_robust_list 100
#define __NR_getcpu 168
@@ -130,6 +133,7 @@
#define __NR_lremovexattr 15
#define __NR_lsetxattr 6
#define __NR_madvise 233
+#define __NR_map_shadow_stack 453
#define __NR_mbind 235
#define __NR_membarrier 283
#define __NR_memfd_create 279
diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
index 6711981e78..74a57f4520 100644
--- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
@@ -91,8 +91,11 @@
#define __NR_ftruncate 93
#define __NR_ftruncate64 194
#define __NR_futex 240
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 326
#define __NR_get_mempolicy 320
#define __NR_get_robust_list 339
@@ -170,6 +173,7 @@
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 220
+#define __NR_map_shadow_stack 453
#define __NR_mbind 319
#define __NR_membarrier 389
#define __NR_memfd_create 385
diff --git a/sysdeps/unix/sysv/linux/csky/arch-syscall.h b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
index 92d9a703ea..ba7632e018 100644
--- a/sysdeps/unix/sysv/linux/csky/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
@@ -71,8 +71,11 @@
#define __NR_fsync 82
#define __NR_ftruncate64 46
#define __NR_futex 98
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_get_mempolicy 236
#define __NR_get_robust_list 100
#define __NR_getcpu 168
@@ -135,6 +138,7 @@
#define __NR_lremovexattr 15
#define __NR_lsetxattr 6
#define __NR_madvise 233
+#define __NR_map_shadow_stack 453
#define __NR_mbind 235
#define __NR_membarrier 283
#define __NR_memfd_create 279
diff --git a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
index fbac124b70..483706de9b 100644
--- a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
@@ -89,8 +89,11 @@
#define __NR_ftruncate 93
#define __NR_ftruncate64 200
#define __NR_futex 210
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 279
#define __NR_get_mempolicy 261
#define __NR_get_robust_list 290
@@ -161,6 +164,7 @@
#define __NR_lstat 84
#define __NR_lstat64 198
#define __NR_madvise 119
+#define __NR_map_shadow_stack 453
#define __NR_mbind 260
#define __NR_membarrier 343
#define __NR_memfd_create 340
diff --git a/sysdeps/unix/sysv/linux/i386/arch-syscall.h b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
index 8961788a96..21c1308bb3 100644
--- a/sysdeps/unix/sysv/linux/i386/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
@@ -95,8 +95,11 @@
#define __NR_ftruncate 93
#define __NR_ftruncate64 194
#define __NR_futex 240
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 299
#define __NR_get_kernel_syms 130
#define __NR_get_mempolicy 275
@@ -183,6 +186,7 @@
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 219
+#define __NR_map_shadow_stack 453
#define __NR_mbind 274
#define __NR_membarrier 375
#define __NR_memfd_create 356
diff --git a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
index 2053d5d392..6d788e3440 100644
--- a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
@@ -94,8 +94,11 @@
#define __NR_ftruncate 93
#define __NR_ftruncate64 194
#define __NR_futex 235
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 292
#define __NR_get_kernel_syms 130
#define __NR_get_mempolicy 269
@@ -177,6 +180,7 @@
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 238
+#define __NR_map_shadow_stack 453
#define __NR_mbind 268
#define __NR_membarrier 374
#define __NR_memfd_create 353
diff --git a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
index 6865b1693c..91e1630f7b 100644
--- a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
@@ -95,8 +95,11 @@
#define __NR_ftruncate 93
#define __NR_ftruncate64 194
#define __NR_futex 240
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 299
#define __NR_get_kernel_syms 130
#define __NR_get_mempolicy 275
@@ -183,6 +186,7 @@
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 219
+#define __NR_map_shadow_stack 453
#define __NR_mbind 274
#define __NR_membarrier 390
#define __NR_memfd_create 386
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
index b13ace8e1c..d75af97467 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
@@ -94,8 +94,11 @@
#define __NR_ftruncate 4093
#define __NR_ftruncate64 4212
#define __NR_futex 4238
+#define __NR_futex_requeue 4456
#define __NR_futex_time64 4422
+#define __NR_futex_wait 4455
#define __NR_futex_waitv 4449
+#define __NR_futex_wake 4454
#define __NR_futimesat 4292
#define __NR_get_kernel_syms 4130
#define __NR_get_mempolicy 4269
@@ -173,6 +176,7 @@
#define __NR_lstat 4107
#define __NR_lstat64 4214
#define __NR_madvise 4218
+#define __NR_map_shadow_stack 4453
#define __NR_mbind 4268
#define __NR_membarrier 4358
#define __NR_memfd_create 4354
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
index b7a7c0dfa7..05bf7d251d 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
@@ -87,8 +87,11 @@
#define __NR_fsync 6072
#define __NR_ftruncate 6075
#define __NR_futex 6194
+#define __NR_futex_requeue 6456
#define __NR_futex_time64 6422
+#define __NR_futex_wait 6455
#define __NR_futex_waitv 6449
+#define __NR_futex_wake 6454
#define __NR_futimesat 6255
#define __NR_get_kernel_syms 6170
#define __NR_get_mempolicy 6232
@@ -159,6 +162,7 @@
#define __NR_lsetxattr 6181
#define __NR_lstat 6006
#define __NR_madvise 6027
+#define __NR_map_shadow_stack 6453
#define __NR_mbind 6231
#define __NR_membarrier 6322
#define __NR_memfd_create 6318
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
index e5d7f91f48..41ffaf3255 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
@@ -80,7 +80,10 @@
#define __NR_fsync 5072
#define __NR_ftruncate 5075
#define __NR_futex 5194
+#define __NR_futex_requeue 5456
+#define __NR_futex_wait 5455
#define __NR_futex_waitv 5449
+#define __NR_futex_wake 5454
#define __NR_futimesat 5251
#define __NR_get_kernel_syms 5170
#define __NR_get_mempolicy 5228
@@ -150,6 +153,7 @@
#define __NR_lsetxattr 5181
#define __NR_lstat 5006
#define __NR_madvise 5027
+#define __NR_map_shadow_stack 5453
#define __NR_mbind 5227
#define __NR_membarrier 5318
#define __NR_memfd_create 5314
diff --git a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
index 89950cc33a..d94e7e9ee9 100644
--- a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
@@ -70,8 +70,11 @@
#define __NR_fsync 82
#define __NR_ftruncate64 46
#define __NR_futex 98
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_get_mempolicy 236
#define __NR_get_robust_list 100
#define __NR_getcpu 168
@@ -134,6 +137,7 @@
#define __NR_lremovexattr 15
#define __NR_lsetxattr 6
#define __NR_madvise 233
+#define __NR_map_shadow_stack 453
#define __NR_mbind 235
#define __NR_membarrier 283
#define __NR_memfd_create 279
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
index 64683bcb76..b5522e8889 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
@@ -93,8 +93,11 @@
#define __NR_ftruncate 93
#define __NR_ftruncate64 194
#define __NR_futex 221
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 290
#define __NR_get_kernel_syms 130
#define __NR_get_mempolicy 260
@@ -173,6 +176,7 @@
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 205
+#define __NR_map_shadow_stack 453
#define __NR_mbind 259
#define __NR_membarrier 365
#define __NR_memfd_create 360
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
index af1bbf32e8..162d782ae6 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
@@ -83,7 +83,10 @@
#define __NR_ftime 35
#define __NR_ftruncate 93
#define __NR_futex 221
+#define __NR_futex_requeue 456
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 290
#define __NR_get_kernel_syms 130
#define __NR_get_mempolicy 260
@@ -160,6 +163,7 @@
#define __NR_lsetxattr 210
#define __NR_lstat 107
#define __NR_madvise 205
+#define __NR_map_shadow_stack 453
#define __NR_mbind 259
#define __NR_membarrier 365
#define __NR_memfd_create 360
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
index 56e3088cbf..013222e5de 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
@@ -61,8 +61,11 @@
#define __NR_fstatfs64 44
#define __NR_fsync 82
#define __NR_ftruncate64 46
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_get_mempolicy 236
#define __NR_get_robust_list 100
#define __NR_getcpu 168
@@ -121,6 +124,7 @@
#define __NR_lremovexattr 15
#define __NR_lsetxattr 6
#define __NR_madvise 233
+#define __NR_map_shadow_stack 453
#define __NR_mbind 235
#define __NR_membarrier 283
#define __NR_memfd_create 279
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
index 508161b47a..d03dad8200 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
@@ -64,7 +64,10 @@
#define __NR_fsync 82
#define __NR_ftruncate 46
#define __NR_futex 98
+#define __NR_futex_requeue 456
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_get_mempolicy 236
#define __NR_get_robust_list 100
#define __NR_getcpu 168
@@ -126,6 +129,7 @@
#define __NR_lseek 62
#define __NR_lsetxattr 6
#define __NR_madvise 233
+#define __NR_map_shadow_stack 453
#define __NR_mbind 235
#define __NR_membarrier 283
#define __NR_memfd_create 279
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
index 1498ebf42e..98e6b68b31 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
@@ -92,8 +92,11 @@
#define __NR_ftruncate 93
#define __NR_ftruncate64 194
#define __NR_futex 238
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 292
#define __NR_get_kernel_syms 130
#define __NR_get_mempolicy 269
@@ -177,6 +180,7 @@
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 219
+#define __NR_map_shadow_stack 453
#define __NR_mbind 268
#define __NR_membarrier 356
#define __NR_memfd_create 350
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
index 624d71b56d..951fbd7c97 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
@@ -78,7 +78,10 @@
#define __NR_fsync 118
#define __NR_ftruncate 93
#define __NR_futex 238
+#define __NR_futex_requeue 456
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 292
#define __NR_get_kernel_syms 130
#define __NR_get_mempolicy 269
@@ -151,6 +154,7 @@
#define __NR_lsetxattr 225
#define __NR_lstat 107
#define __NR_madvise 219
+#define __NR_map_shadow_stack 453
#define __NR_mbind 268
#define __NR_membarrier 356
#define __NR_memfd_create 350
diff --git a/sysdeps/unix/sysv/linux/sh/arch-syscall.h b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
index 37211f5f8c..6b4418bcae 100644
--- a/sysdeps/unix/sysv/linux/sh/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
@@ -91,8 +91,11 @@
#define __NR_ftruncate 93
#define __NR_ftruncate64 194
#define __NR_futex 240
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 299
#define __NR_get_mempolicy 275
#define __NR_get_robust_list 312
@@ -170,6 +173,7 @@
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 219
+#define __NR_map_shadow_stack 453
#define __NR_mbind 274
#define __NR_membarrier 378
#define __NR_memfd_create 374
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
index 8093abcc9c..4f9460b1a3 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
@@ -93,8 +93,11 @@
#define __NR_ftruncate 130
#define __NR_ftruncate64 84
#define __NR_futex 142
+#define __NR_futex_requeue 456
#define __NR_futex_time64 422
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 288
#define __NR_get_kernel_syms 223
#define __NR_get_mempolicy 304
@@ -175,6 +178,7 @@
#define __NR_lstat 40
#define __NR_lstat64 132
#define __NR_madvise 75
+#define __NR_map_shadow_stack 453
#define __NR_mbind 303
#define __NR_membarrier 351
#define __NR_memfd_create 348
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
index d25ccfb571..129ce50646 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
@@ -84,7 +84,10 @@
#define __NR_fsync 95
#define __NR_ftruncate 130
#define __NR_futex 142
+#define __NR_futex_requeue 456
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 288
#define __NR_get_kernel_syms 223
#define __NR_get_mempolicy 304
@@ -158,6 +161,7 @@
#define __NR_lstat 40
#define __NR_lstat64 132
#define __NR_madvise 75
+#define __NR_map_shadow_stack 453
#define __NR_mbind 303
#define __NR_membarrier 351
#define __NR_memfd_create 348
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
index c039d5c37f..aac065e7b3 100644
--- a/sysdeps/unix/sysv/linux/syscall-names.list
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
@@ -21,8 +21,8 @@
# This file can list all potential system calls. The names are only
# used if the installed kernel headers also provide them.
-# The list of system calls is current as of Linux 6.6.
-kernel 6.6
+# The list of system calls is current as of Linux 6.7.
+kernel 6.7
FAST_atomic_update
FAST_cmpxchg
@@ -147,8 +147,11 @@ ftime
ftruncate
ftruncate64
futex
+futex_requeue
futex_time64
+futex_wait
futex_waitv
+futex_wake
futimesat
get_kernel_syms
get_mempolicy
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
index 5e4c9e901c..4fa5b942c5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
@@ -80,7 +80,10 @@
#define __NR_fsync 74
#define __NR_ftruncate 77
#define __NR_futex 202
+#define __NR_futex_requeue 456
+#define __NR_futex_wait 455
#define __NR_futex_waitv 449
+#define __NR_futex_wake 454
#define __NR_futimesat 261
#define __NR_get_kernel_syms 177
#define __NR_get_mempolicy 239
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
index dd5e196272..b9db8bc5be 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
@@ -76,7 +76,10 @@
#define __NR_fsync 1073741898
#define __NR_ftruncate 1073741901
#define __NR_futex 1073742026
+#define __NR_futex_requeue 1073742280
+#define __NR_futex_wait 1073742279
#define __NR_futex_waitv 1073742273
+#define __NR_futex_wake 1073742278
#define __NR_futimesat 1073742085
#define __NR_get_mempolicy 1073742063
#define __NR_get_robust_list 1073742355

@ -1,756 +0,0 @@
commit 3de2f8755c6c036dcd0b1f4acd6bcdefe0e775c0
Author: Joseph Myers <josmyers@redhat.com>
Date: Wed Mar 13 13:57:56 2024 +0000
Update syscall lists for Linux 6.8
Linux 6.8 adds five new syscalls. Update syscall-names.list and
regenerate the arch-syscall.h headers with build-many-glibcs.py
update-syscalls.
Tested with build-many-glibcs.py.
Modified for RHEL by: Patsy Griffin <patsy@redhat.com>
diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
index 1713897f85..7ee8a2167a 100644
--- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
@@ -122,12 +122,16 @@
#define __NR_lgetxattr 9
#define __NR_linkat 37
#define __NR_listen 201
+#define __NR_listmount 458
#define __NR_listxattr 11
#define __NR_llistxattr 12
#define __NR_lookup_dcookie 18
#define __NR_lremovexattr 15
#define __NR_lseek 62
#define __NR_lsetxattr 6
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_madvise 233
#define __NR_map_shadow_stack 453
#define __NR_mbind 235
@@ -276,6 +280,7 @@
#define __NR_socketpair 199
#define __NR_splice 76
#define __NR_statfs 43
+#define __NR_statmount 457
#define __NR_statx 291
#define __NR_swapoff 225
#define __NR_swapon 224
diff --git a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
index 5457d2d8ae..0f4ea7670b 100644
--- a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
@@ -150,12 +150,16 @@
#define __NR_link 9
#define __NR_linkat 458
#define __NR_listen 106
+#define __NR_listmount 568
#define __NR_listxattr 388
#define __NR_llistxattr 389
#define __NR_lookup_dcookie 406
#define __NR_lremovexattr 392
#define __NR_lseek 19
#define __NR_lsetxattr 383
+#define __NR_lsm_get_self_attr 569
+#define __NR_lsm_list_modules 571
+#define __NR_lsm_set_self_attr 570
#define __NR_lstat 68
#define __NR_lstat64 426
#define __NR_madvise 75
@@ -441,6 +445,7 @@
#define __NR_stat64 425
#define __NR_statfs 328
#define __NR_statfs64 528
+#define __NR_statmount 567
#define __NR_statx 522
#define __NR_swapoff 304
#define __NR_swapon 322
diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
index a66471c83a..90359482a8 100644
--- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
@@ -126,12 +126,16 @@
#define __NR_lgetxattr 9
#define __NR_linkat 37
#define __NR_listen 201
+#define __NR_listmount 458
#define __NR_listxattr 11
#define __NR_llistxattr 12
#define __NR_llseek 62
#define __NR_lookup_dcookie 18
#define __NR_lremovexattr 15
#define __NR_lsetxattr 6
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_madvise 233
#define __NR_map_shadow_stack 453
#define __NR_mbind 235
@@ -278,6 +282,7 @@
#define __NR_socketpair 199
#define __NR_splice 76
#define __NR_statfs64 43
+#define __NR_statmount 457
#define __NR_statx 291
#define __NR_swapoff 225
#define __NR_swapon 224
diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
index 74a57f4520..4930167a03 100644
--- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
@@ -164,12 +164,16 @@
#define __NR_link 9
#define __NR_linkat 330
#define __NR_listen 284
+#define __NR_listmount 458
#define __NR_listxattr 232
#define __NR_llistxattr 233
#define __NR_lookup_dcookie 249
#define __NR_lremovexattr 236
#define __NR_lseek 19
#define __NR_lsetxattr 227
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 220
@@ -361,6 +365,7 @@
#define __NR_stat64 195
#define __NR_statfs 99
#define __NR_statfs64 266
+#define __NR_statmount 457
#define __NR_statx 397
#define __NR_swapoff 115
#define __NR_swapon 87
diff --git a/sysdeps/unix/sysv/linux/csky/arch-syscall.h b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
index ba7632e018..3f16a29f57 100644
--- a/sysdeps/unix/sysv/linux/csky/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
@@ -131,12 +131,16 @@
#define __NR_lgetxattr 9
#define __NR_linkat 37
#define __NR_listen 201
+#define __NR_listmount 458
#define __NR_listxattr 11
#define __NR_llistxattr 12
#define __NR_llseek 62
#define __NR_lookup_dcookie 18
#define __NR_lremovexattr 15
#define __NR_lsetxattr 6
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_madvise 233
#define __NR_map_shadow_stack 453
#define __NR_mbind 235
@@ -291,6 +295,7 @@
#define __NR_socketpair 199
#define __NR_splice 76
#define __NR_statfs64 43
+#define __NR_statmount 457
#define __NR_statx 291
#define __NR_swapoff 225
#define __NR_swapon 224
diff --git a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
index 483706de9b..a1b2c819d6 100644
--- a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
@@ -155,12 +155,16 @@
#define __NR_link 9
#define __NR_linkat 283
#define __NR_listen 32
+#define __NR_listmount 458
#define __NR_listxattr 244
#define __NR_llistxattr 245
#define __NR_lookup_dcookie 223
#define __NR_lremovexattr 248
#define __NR_lseek 19
#define __NR_lsetxattr 239
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 84
#define __NR_lstat64 198
#define __NR_madvise 119
@@ -339,6 +343,7 @@
#define __NR_stat64 101
#define __NR_statfs 99
#define __NR_statfs64 298
+#define __NR_statmount 457
#define __NR_statx 349
#define __NR_stime 25
#define __NR_swapoff 115
diff --git a/sysdeps/unix/sysv/linux/i386/arch-syscall.h b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
index 21c1308bb3..cc775432d6 100644
--- a/sysdeps/unix/sysv/linux/i386/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
@@ -176,6 +176,7 @@
#define __NR_link 9
#define __NR_linkat 303
#define __NR_listen 363
+#define __NR_listmount 458
#define __NR_listxattr 232
#define __NR_llistxattr 233
#define __NR_lock 53
@@ -183,6 +184,9 @@
#define __NR_lremovexattr 236
#define __NR_lseek 19
#define __NR_lsetxattr 227
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 219
@@ -386,6 +390,7 @@
#define __NR_stat64 195
#define __NR_statfs 99
#define __NR_statfs64 268
+#define __NR_statmount 457
#define __NR_statx 383
#define __NR_stime 25
#define __NR_stty 31
diff --git a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
index 6d788e3440..79f277dd5b 100644
--- a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
@@ -171,12 +171,16 @@
#define __NR_link 9
#define __NR_linkat 296
#define __NR_listen 360
+#define __NR_listmount 458
#define __NR_listxattr 229
#define __NR_llistxattr 230
#define __NR_lookup_dcookie 248
#define __NR_lremovexattr 233
#define __NR_lseek 19
#define __NR_lsetxattr 224
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 238
@@ -373,6 +377,7 @@
#define __NR_stat64 195
#define __NR_statfs 99
#define __NR_statfs64 263
+#define __NR_statmount 457
#define __NR_statx 379
#define __NR_stime 25
#define __NR_swapoff 115
diff --git a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
index 91e1630f7b..779d5d5d70 100644
--- a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
@@ -176,6 +176,7 @@
#define __NR_link 9
#define __NR_linkat 303
#define __NR_listen 348
+#define __NR_listmount 458
#define __NR_listxattr 232
#define __NR_llistxattr 233
#define __NR_lock 53
@@ -183,6 +184,9 @@
#define __NR_lremovexattr 236
#define __NR_lseek 19
#define __NR_lsetxattr 227
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 219
@@ -389,6 +393,7 @@
#define __NR_stat64 195
#define __NR_statfs 99
#define __NR_statfs64 268
+#define __NR_statmount 457
#define __NR_statx 398
#define __NR_stime 25
#define __NR_stty 31
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
index d75af97467..86ffd5ce84 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
@@ -166,6 +166,7 @@
#define __NR_link 4009
#define __NR_linkat 4296
#define __NR_listen 4174
+#define __NR_listmount 4458
#define __NR_listxattr 4230
#define __NR_llistxattr 4231
#define __NR_lock 4053
@@ -173,6 +174,9 @@
#define __NR_lremovexattr 4234
#define __NR_lseek 4019
#define __NR_lsetxattr 4225
+#define __NR_lsm_get_self_attr 4459
+#define __NR_lsm_list_modules 4461
+#define __NR_lsm_set_self_attr 4460
#define __NR_lstat 4107
#define __NR_lstat64 4214
#define __NR_madvise 4218
@@ -362,6 +366,7 @@
#define __NR_stat64 4213
#define __NR_statfs 4099
#define __NR_statfs64 4255
+#define __NR_statmount 4457
#define __NR_statx 4366
#define __NR_stime 4025
#define __NR_stty 4031
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
index 05bf7d251d..5d37a686e5 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
@@ -154,12 +154,16 @@
#define __NR_link 6084
#define __NR_linkat 6259
#define __NR_listen 6049
+#define __NR_listmount 6458
#define __NR_listxattr 6186
#define __NR_llistxattr 6187
#define __NR_lookup_dcookie 6206
#define __NR_lremovexattr 6190
#define __NR_lseek 6008
#define __NR_lsetxattr 6181
+#define __NR_lsm_get_self_attr 6459
+#define __NR_lsm_list_modules 6461
+#define __NR_lsm_set_self_attr 6460
#define __NR_lstat 6006
#define __NR_madvise 6027
#define __NR_map_shadow_stack 6453
@@ -332,6 +336,7 @@
#define __NR_stat 6004
#define __NR_statfs 6134
#define __NR_statfs64 6217
+#define __NR_statmount 6457
#define __NR_statx 6330
#define __NR_swapoff 6163
#define __NR_swapon 6162
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
index 41ffaf3255..9b1e846e76 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
@@ -145,12 +145,16 @@
#define __NR_link 5084
#define __NR_linkat 5255
#define __NR_listen 5049
+#define __NR_listmount 5458
#define __NR_listxattr 5186
#define __NR_llistxattr 5187
#define __NR_lookup_dcookie 5206
#define __NR_lremovexattr 5190
#define __NR_lseek 5008
#define __NR_lsetxattr 5181
+#define __NR_lsm_get_self_attr 5459
+#define __NR_lsm_list_modules 5461
+#define __NR_lsm_set_self_attr 5460
#define __NR_lstat 5006
#define __NR_madvise 5027
#define __NR_map_shadow_stack 5453
@@ -313,6 +317,7 @@
#define __NR_splice 5263
#define __NR_stat 5004
#define __NR_statfs 5134
+#define __NR_statmount 5457
#define __NR_statx 5326
#define __NR_swapoff 5163
#define __NR_swapon 5162
diff --git a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
index d94e7e9ee9..abbc9ab6b0 100644
--- a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
@@ -130,12 +130,16 @@
#define __NR_lgetxattr 9
#define __NR_linkat 37
#define __NR_listen 201
+#define __NR_listmount 458
#define __NR_listxattr 11
#define __NR_llistxattr 12
#define __NR_llseek 62
#define __NR_lookup_dcookie 18
#define __NR_lremovexattr 15
#define __NR_lsetxattr 6
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_madvise 233
#define __NR_map_shadow_stack 453
#define __NR_mbind 235
@@ -290,6 +294,7 @@
#define __NR_socketpair 199
#define __NR_splice 76
#define __NR_statfs64 43
+#define __NR_statmount 457
#define __NR_statx 291
#define __NR_swapoff 225
#define __NR_swapon 224
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
index b5522e8889..af0d2b121e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
@@ -166,6 +166,7 @@
#define __NR_link 9
#define __NR_linkat 294
#define __NR_listen 329
+#define __NR_listmount 458
#define __NR_listxattr 215
#define __NR_llistxattr 216
#define __NR_lock 53
@@ -173,6 +174,9 @@
#define __NR_lremovexattr 219
#define __NR_lseek 19
#define __NR_lsetxattr 210
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 205
@@ -374,6 +378,7 @@
#define __NR_stat64 195
#define __NR_statfs 99
#define __NR_statfs64 252
+#define __NR_statmount 457
#define __NR_statx 383
#define __NR_stime 25
#define __NR_stty 31
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
index 162d782ae6..a4c70aa7fe 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
@@ -154,6 +154,7 @@
#define __NR_link 9
#define __NR_linkat 294
#define __NR_listen 329
+#define __NR_listmount 458
#define __NR_listxattr 215
#define __NR_llistxattr 216
#define __NR_lock 53
@@ -161,6 +162,9 @@
#define __NR_lremovexattr 219
#define __NR_lseek 19
#define __NR_lsetxattr 210
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 107
#define __NR_madvise 205
#define __NR_map_shadow_stack 453
@@ -352,6 +356,7 @@
#define __NR_stat 106
#define __NR_statfs 99
#define __NR_statfs64 252
+#define __NR_statmount 457
#define __NR_statx 383
#define __NR_stime 25
#define __NR_stty 31
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
index 013222e5de..7315d164d6 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
@@ -117,12 +117,16 @@
#define __NR_lgetxattr 9
#define __NR_linkat 37
#define __NR_listen 201
+#define __NR_listmount 458
#define __NR_listxattr 11
#define __NR_llistxattr 12
#define __NR_llseek 62
#define __NR_lookup_dcookie 18
#define __NR_lremovexattr 15
#define __NR_lsetxattr 6
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_madvise 233
#define __NR_map_shadow_stack 453
#define __NR_mbind 235
@@ -268,6 +272,7 @@
#define __NR_socketpair 199
#define __NR_splice 76
#define __NR_statfs64 43
+#define __NR_statmount 457
#define __NR_statx 291
#define __NR_swapoff 225
#define __NR_swapon 224
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
index d03dad8200..31a1130db9 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
@@ -122,12 +122,16 @@
#define __NR_lgetxattr 9
#define __NR_linkat 37
#define __NR_listen 201
+#define __NR_listmount 458
#define __NR_listxattr 11
#define __NR_llistxattr 12
#define __NR_lookup_dcookie 18
#define __NR_lremovexattr 15
#define __NR_lseek 62
#define __NR_lsetxattr 6
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_madvise 233
#define __NR_map_shadow_stack 453
#define __NR_mbind 235
@@ -277,6 +281,7 @@
#define __NR_socketpair 199
#define __NR_splice 76
#define __NR_statfs 43
+#define __NR_statmount 457
#define __NR_statx 291
#define __NR_swapoff 225
#define __NR_swapon 224
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
index 98e6b68b31..cf8569304d 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
@@ -171,12 +171,16 @@
#define __NR_link 9
#define __NR_linkat 296
#define __NR_listen 363
+#define __NR_listmount 458
#define __NR_listxattr 230
#define __NR_llistxattr 231
#define __NR_lookup_dcookie 110
#define __NR_lremovexattr 234
#define __NR_lseek 19
#define __NR_lsetxattr 225
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 219
@@ -372,6 +376,7 @@
#define __NR_stat64 195
#define __NR_statfs 99
#define __NR_statfs64 265
+#define __NR_statmount 457
#define __NR_statx 379
#define __NR_stime 25
#define __NR_swapoff 115
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
index 951fbd7c97..f3536ed03f 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
@@ -146,12 +146,16 @@
#define __NR_link 9
#define __NR_linkat 296
#define __NR_listen 363
+#define __NR_listmount 458
#define __NR_listxattr 230
#define __NR_llistxattr 231
#define __NR_lookup_dcookie 110
#define __NR_lremovexattr 234
#define __NR_lseek 19
#define __NR_lsetxattr 225
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 107
#define __NR_madvise 219
#define __NR_map_shadow_stack 453
@@ -329,6 +333,7 @@
#define __NR_stat 106
#define __NR_statfs 99
#define __NR_statfs64 265
+#define __NR_statmount 457
#define __NR_statx 379
#define __NR_swapoff 115
#define __NR_swapon 87
diff --git a/sysdeps/unix/sysv/linux/sh/arch-syscall.h b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
index 6b4418bcae..0c88bf10c7 100644
--- a/sysdeps/unix/sysv/linux/sh/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
@@ -164,12 +164,16 @@
#define __NR_link 9
#define __NR_linkat 303
#define __NR_listen 343
+#define __NR_listmount 458
#define __NR_listxattr 232
#define __NR_llistxattr 233
#define __NR_lookup_dcookie 253
#define __NR_lremovexattr 236
#define __NR_lseek 19
#define __NR_lsetxattr 227
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 107
#define __NR_lstat64 196
#define __NR_madvise 219
@@ -365,6 +369,7 @@
#define __NR_stat64 195
#define __NR_statfs 99
#define __NR_statfs64 268
+#define __NR_statmount 457
#define __NR_statx 383
#define __NR_stime 25
#define __NR_swapoff 115
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
index 4f9460b1a3..19fa614624 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
@@ -169,12 +169,16 @@
#define __NR_link 9
#define __NR_linkat 292
#define __NR_listen 354
+#define __NR_listmount 458
#define __NR_listxattr 178
#define __NR_llistxattr 179
#define __NR_lookup_dcookie 208
#define __NR_lremovexattr 182
#define __NR_lseek 19
#define __NR_lsetxattr 170
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 40
#define __NR_lstat64 132
#define __NR_madvise 75
@@ -370,6 +374,7 @@
#define __NR_stat64 139
#define __NR_statfs 157
#define __NR_statfs64 234
+#define __NR_statmount 457
#define __NR_statx 360
#define __NR_stime 233
#define __NR_swapoff 213
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
index 129ce50646..18516f20cb 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
@@ -152,12 +152,16 @@
#define __NR_link 9
#define __NR_linkat 292
#define __NR_listen 354
+#define __NR_listmount 458
#define __NR_listxattr 178
#define __NR_llistxattr 179
#define __NR_lookup_dcookie 208
#define __NR_lremovexattr 182
#define __NR_lseek 19
#define __NR_lsetxattr 170
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 40
#define __NR_lstat64 132
#define __NR_madvise 75
@@ -339,6 +343,7 @@
#define __NR_stat64 139
#define __NR_statfs 157
#define __NR_statfs64 234
+#define __NR_statmount 457
#define __NR_statx 360
#define __NR_stime 233
#define __NR_swapoff 213
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
index aac065e7b3..6557bcfde4 100644
--- a/sysdeps/unix/sysv/linux/syscall-names.list
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
@@ -21,8 +21,8 @@
# This file can list all potential system calls. The names are only
# used if the installed kernel headers also provide them.
-# The list of system calls is current as of Linux 6.7.
-kernel 6.7
+# The list of system calls is current as of Linux 6.8.
+kernel 6.8
FAST_atomic_update
FAST_cmpxchg
@@ -239,6 +239,7 @@ lgetxattr
link
linkat
listen
+listmount
listxattr
llistxattr
llseek
@@ -247,6 +248,9 @@ lookup_dcookie
lremovexattr
lseek
lsetxattr
+lsm_get_self_attr
+lsm_list_modules
+lsm_set_self_attr
lstat
lstat64
madvise
@@ -593,6 +597,7 @@ stat
stat64
statfs
statfs64
+statmount
statx
stime
stty
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
index 4fa5b942c5..b122216013 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
@@ -149,12 +149,16 @@
#define __NR_link 86
#define __NR_linkat 265
#define __NR_listen 50
+#define __NR_listmount 458
#define __NR_listxattr 194
#define __NR_llistxattr 195
#define __NR_lookup_dcookie 212
#define __NR_lremovexattr 198
#define __NR_lseek 8
#define __NR_lsetxattr 189
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_list_modules 461
+#define __NR_lsm_set_self_attr 460
#define __NR_lstat 6
#define __NR_madvise 28
#define __NR_map_shadow_stack 453
@@ -321,6 +325,7 @@
#define __NR_splice 275
#define __NR_stat 4
#define __NR_statfs 137
+#define __NR_statmount 457
#define __NR_statx 332
#define __NR_swapoff 168
#define __NR_swapon 167
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
index b9db8bc5be..3040a47d72 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
@@ -143,12 +143,16 @@
#define __NR_link 1073741910
#define __NR_linkat 1073742089
#define __NR_listen 1073741874
+#define __NR_listmount 1073742282
#define __NR_listxattr 1073742018
#define __NR_llistxattr 1073742019
#define __NR_lookup_dcookie 1073742036
#define __NR_lremovexattr 1073742022
#define __NR_lseek 1073741832
#define __NR_lsetxattr 1073742013
+#define __NR_lsm_get_self_attr 1073742283
+#define __NR_lsm_list_modules 1073742285
+#define __NR_lsm_set_self_attr 1073742284
#define __NR_lstat 1073741830
#define __NR_madvise 1073741852
#define __NR_mbind 1073742061
@@ -312,6 +316,7 @@
#define __NR_splice 1073742099
#define __NR_stat 1073741828
#define __NR_statfs 1073741961
+#define __NR_statmount 1073742281
#define __NR_statx 1073742156
#define __NR_swapoff 1073741992
#define __NR_swapon 1073741991

@ -1,28 +0,0 @@
commit cf0ca8d52e1653d4aa4311a4649af8dc541ce6b4
Author: Joseph Myers <josmyers@redhat.com>
Date: Mon May 20 13:10:31 2024 +0000
Update syscall lists for Linux 6.9
Linux 6.9 has no new syscalls. Update the version number in
syscall-names.list to reflect that it is still current for 6.9.
Tested with build-many-glibcs.py.
Modified for RHEL by: Patsy Griffin <patsy@redhat.com>
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
index 6557bcfde4..672d39eaad 100644
--- a/sysdeps/unix/sysv/linux/syscall-names.list
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
@@ -21,8 +21,8 @@
# This file can list all potential system calls. The names are only
# used if the installed kernel headers also provide them.
-# The list of system calls is current as of Linux 6.8.
-kernel 6.8
+# The list of system calls is current as of Linux 6.9.
+kernel 6.9
FAST_atomic_update
FAST_cmpxchg

@ -1,26 +0,0 @@
From cb8c78b2ffa0b77ae453b2d328d7e2fe5186ef2a Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Tue, 31 Oct 2023 13:32:35 -0300
Subject: linux: Add MMAP_ABOVE4G from Linux 6.6 to sys/mman.h
x86 added the flag (29f890d1050fc099f) for CET enabled.
Also update tst-mman-consts.py test.
Conflicts:
sysdeps/unix/sysv/linux/tst-mman-consts.py
(removed patch to keep alerting about kernel differences)
sysdeps/unix/sysv/linux/x86/bits/mman.h
(adapted to missing __USE_MISC conditional upstream)
diff -rup a/sysdeps/unix/sysv/linux/x86/bits/mman.h b/sysdeps/unix/sysv/linux/x86/bits/mman.h
--- a/sysdeps/unix/sysv/linux/x86/bits/mman.h 2021-08-01 21:33:43.000000000 -0400
+++ b/sysdeps/unix/sysv/linux/x86/bits/mman.h 2024-05-29 14:03:12.426182715 -0400
@@ -26,6 +26,7 @@
/* Other flags. */
#ifdef __USE_MISC
# define MAP_32BIT 0x40 /* Only give out 32-bit addresses. */
+# define MAP_ABOVE4G 0x80 /* Only map above 4GB. */
#endif
#include <bits/mman-map-flags-generic.h>

@ -1,43 +0,0 @@
commit afe42e935b3ee97bac9a7064157587777259c60e
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Jun 3 10:49:40 2024 +0200
elf: Avoid some free (NULL) calls in _dl_update_slotinfo
This has been confirmed to work around some interposed mallocs. Here
is a discussion of the impact test ust/libc-wrapper/test_libc-wrapper
in lttng-tools:
New TLS usage in libgcc_s.so.1, compatibility impact
<https://inbox.sourceware.org/libc-alpha/8734v1ieke.fsf@oldenburg.str.redhat.com/>
Reportedly, this patch also papers over a similar issue when tcmalloc
2.9.1 is not compiled with -ftls-model=initial-exec. Of course the
goal really should be to compile mallocs with the initial-exec TLS
model, but this commit appears to be a useful interim workaround.
Fixes commit d2123d68275acc0f061e73d5f86ca504e0d5a344 ("elf: Fix slow
tls access after dlopen [BZ #19924]").
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 7b3dd9ab60..670dbc42fc 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -819,7 +819,14 @@ _dl_update_slotinfo (unsigned long int req_modid, size_t new_gen)
dtv entry free it. Note: this is not AS-safe. */
/* XXX Ideally we will at some point create a memory
pool. */
- free (dtv[modid].pointer.to_free);
+ /* Avoid calling free on a null pointer. Some mallocs
+ incorrectly use dynamic TLS, and depending on how the
+ free function was compiled, it could call
+ __tls_get_addr before the null pointer check in the
+ free implementation. Checking here papers over at
+ least some dynamic TLS usage by interposed mallocs. */
+ if (dtv[modid].pointer.to_free != NULL)
+ free (dtv[modid].pointer.to_free);
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
dtv[modid].pointer.to_free = NULL;

@ -1,499 +0,0 @@
commit 018f0fc3b818d4d1460a4e2384c24802504b1d20
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Jul 1 17:42:04 2024 +0200
elf: Support recursive use of dynamic TLS in interposed malloc
It turns out that quite a few applications use bundled mallocs that
have been built to use global-dynamic TLS (instead of the recommended
initial-exec TLS). The previous workaround from
commit afe42e935b3ee97bac9a7064157587777259c60e ("elf: Avoid some
free (NULL) calls in _dl_update_slotinfo") does not fix all
encountered cases unfortunatelly.
This change avoids the TLS generation update for recursive use
of TLS from a malloc that was called during a TLS update. This
is possible because an interposed malloc has a fixed module ID and
TLS slot. (It cannot be unloaded.) If an initially-loaded module ID
is encountered in __tls_get_addr and the dynamic linker is already
in the middle of a TLS update, use the outdated DTV, thus avoiding
another call into malloc. It's still necessary to update the
DTV to the most recent generation, to get out of the slow path,
which is why the check for recursion is needed.
The bookkeeping is done using a global counter instead of per-thread
flag because TLS access in the dynamic linker is tricky.
All this will go away once the dynamic linker stops using malloc
for TLS, likely as part of a change that pre-allocates all TLS
during pthread_create/dlopen.
Fixes commit d2123d68275acc0f061e73d5f86ca504e0d5a344 ("elf: Fix slow
tls access after dlopen [BZ #19924]").
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
Reworked for RHEL by: Patsy Griffin <patsy@redhat.com>
diff -Nrup a/elf/Makefile b/elf/Makefile
--- a/elf/Makefile 2024-07-09 22:06:30.237752048 -0400
+++ b/elf/Makefile 2024-07-10 14:09:02.996759220 -0400
@@ -423,6 +423,7 @@ tests += \
tst-nodeps2 \
tst-noload \
tst-null-argv \
+ tst-recursive-tls \
tst-relsort1 \
tst-ro-dynamic \
tst-rtld-run-static \
@@ -783,6 +784,23 @@ modules-names = \
tst-nodeps1-mod \
tst-nodeps2-mod \
tst-null-argv-lib \
+ tst-recursive-tlsmallocmod \
+ tst-recursive-tlsmod0 \
+ tst-recursive-tlsmod1 \
+ tst-recursive-tlsmod2 \
+ tst-recursive-tlsmod3 \
+ tst-recursive-tlsmod4 \
+ tst-recursive-tlsmod5 \
+ tst-recursive-tlsmod6 \
+ tst-recursive-tlsmod7 \
+ tst-recursive-tlsmod8 \
+ tst-recursive-tlsmod9 \
+ tst-recursive-tlsmod10 \
+ tst-recursive-tlsmod11 \
+ tst-recursive-tlsmod12 \
+ tst-recursive-tlsmod13 \
+ tst-recursive-tlsmod14 \
+ tst-recursive-tlsmod15 \
tst-relsort1mod1 \
tst-relsort1mod2 \
tst-ro-dynamic-mod \
@@ -2725,3 +2743,11 @@ CFLAGS-tst-tlsgap-mod0.c += -mtls-dialec
CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=gnu2
CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2
endif
+
+$(objpfx)tst-recursive-tls: $(objpfx)tst-recursive-tlsmallocmod.so
+# More objects than DTV_SURPLUS, to trigger DTV reallocation.
+$(objpfx)tst-recursive-tls.out: \
+ $(patsubst %,$(objpfx)tst-recursive-tlsmod%.so, \
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
+$(objpfx)tst-recursive-tlsmod%.os: tst-recursive-tlsmodN.c
+ $(compile-command.c) -DVAR=thread_$* -DFUNC=get_threadvar_$*
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 670dbc42fc..3d221273f1 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -75,6 +75,31 @@
/* Default for dl_tls_static_optional. */
#define OPTIONAL_TLS 512
+/* Used to count the number of threads currently executing dynamic TLS
+ updates. Used to avoid recursive malloc calls in __tls_get_addr
+ for an interposed malloc that uses global-dynamic TLS (which is not
+ recommended); see _dl_tls_allocate_active checks. This could be a
+ per-thread flag, but would need TLS access in the dynamic linker. */
+unsigned int _dl_tls_threads_in_update;
+
+static inline void
+_dl_tls_allocate_begin (void)
+{
+ atomic_fetch_add_relaxed (&_dl_tls_threads_in_update, 1);
+}
+
+static inline void
+_dl_tls_allocate_end (void)
+{
+ atomic_fetch_add_relaxed (&_dl_tls_threads_in_update, -1);
+}
+
+static inline bool
+_dl_tls_allocate_active (void)
+{
+ return atomic_load_relaxed (&_dl_tls_threads_in_update) > 0;
+}
+
/* Compute the static TLS surplus based on the namespace count and the
TLS space that can be used for optimizations. */
static inline int
@@ -425,12 +450,18 @@ _dl_allocate_tls_storage (void)
size += TLS_PRE_TCB_SIZE;
#endif
- /* Perform the allocation. Reserve space for the required alignment
- and the pointer to the original allocation. */
+ /* Reserve space for the required alignment and the pointer to the
+ original allocation. */
size_t alignment = GLRO (dl_tls_static_align);
+
+ /* Perform the allocation. */
+ _dl_tls_allocate_begin ();
void *allocated = malloc (size + alignment + sizeof (void *));
if (__glibc_unlikely (allocated == NULL))
- return NULL;
+ {
+ _dl_tls_allocate_end ();
+ return NULL;
+ }
/* Perform alignment and allocate the DTV. */
#if TLS_TCB_AT_TP
@@ -466,6 +497,8 @@ _dl_allocate_tls_storage (void)
result = allocate_dtv (result);
if (result == NULL)
free (allocated);
+
+ _dl_tls_allocate_end ();
return result;
}
@@ -483,6 +516,7 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
size_t newsize = max_modid + DTV_SURPLUS;
size_t oldsize = dtv[-1].counter;
+ _dl_tls_allocate_begin ();
if (dtv == GL(dl_initial_dtv))
{
/* This is the initial dtv that was either statically allocated in
@@ -502,6 +536,7 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
if (newp == NULL)
oom ();
}
+ _dl_tls_allocate_end ();
newp[0].counter = newsize;
@@ -676,7 +711,9 @@ allocate_dtv_entry (size_t alignment, size_t size)
if (powerof2 (alignment) && alignment <= _Alignof (max_align_t))
{
/* The alignment is supported by malloc. */
+ _dl_tls_allocate_begin ();
void *ptr = malloc (size);
+ _dl_tls_allocate_end ();
return (struct dtv_pointer) { ptr, ptr };
}
@@ -688,7 +725,10 @@ allocate_dtv_entry (size_t alignment, size_t size)
/* Perform the allocation. This is the pointer we need to free
later. */
+ _dl_tls_allocate_begin ();
void *start = malloc (alloc_size);
+ _dl_tls_allocate_end ();
+
if (start == NULL)
return (struct dtv_pointer) {};
@@ -826,7 +866,11 @@ _dl_update_slotinfo (unsigned long int req_modid, size_t new_gen)
free implementation. Checking here papers over at
least some dynamic TLS usage by interposed mallocs. */
if (dtv[modid].pointer.to_free != NULL)
- free (dtv[modid].pointer.to_free);
+ {
+ _dl_tls_allocate_begin ();
+ free (dtv[modid].pointer.to_free);
+ _dl_tls_allocate_end ();
+ }
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
dtv[modid].pointer.to_free = NULL;
@@ -956,10 +1000,22 @@ __tls_get_addr (GET_ADDR_ARGS)
size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
if (__glibc_unlikely (dtv[0].counter != gen))
{
- /* Update DTV up to the global generation, see CONCURRENCY NOTES
- in _dl_update_slotinfo. */
- gen = atomic_load_acquire (&GL(dl_tls_generation));
- return update_get_addr (GET_ADDR_PARAM, gen);
+ if (_dl_tls_allocate_active ()
+ && GET_ADDR_MODULE < _dl_tls_initial_modid_limit)
+ /* This is a reentrant __tls_get_addr call, but we can
+ satisfy it because it's an initially-loaded module ID.
+ These TLS slotinfo slots do not change, so the
+ out-of-date generation counter does not matter. However,
+ if not in a TLS update, still update_get_addr below, to
+ get off the slow path eventually. */
+ ;
+ else
+ {
+ /* Update DTV up to the global generation, see CONCURRENCY NOTES
+ in _dl_update_slotinfo. */
+ gen = atomic_load_acquire (&GL(dl_tls_generation));
+ return update_get_addr (GET_ADDR_PARAM, gen);
+ }
}
void *p = dtv[GET_ADDR_MODULE].pointer.val;
@@ -969,7 +1025,7 @@ __tls_get_addr (GET_ADDR_ARGS)
return (char *) p + GET_ADDR_OFFSET;
}
-#endif
+#endif /* SHARED */
/* Look up the module's TLS block as for __tls_get_addr,
@@ -1018,6 +1074,25 @@ _dl_tls_get_addr_soft (struct link_map *l)
return data;
}
+size_t _dl_tls_initial_modid_limit;
+
+void
+_dl_tls_initial_modid_limit_setup (void)
+{
+ struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
+ size_t idx;
+ for (idx = 0; idx < listp->len; ++idx)
+ {
+ struct link_map *l = listp->slotinfo[idx].map;
+ if (l == NULL
+ /* The object can be unloaded, so its modid can be
+ reassociated. */
+ || !(l->l_type == lt_executable || l->l_type == lt_library))
+ break;
+ }
+ _dl_tls_initial_modid_limit = idx;
+}
+
void
_dl_add_to_slotinfo (struct link_map *l, bool do_add)
@@ -1050,9 +1125,11 @@ _dl_add_to_slotinfo (struct link_map *l, bool do_add)
the first slot. */
assert (idx == 0);
+ _dl_tls_allocate_begin ();
listp = (struct dtv_slotinfo_list *)
malloc (sizeof (struct dtv_slotinfo_list)
+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
+ _dl_tls_allocate_end ();
if (listp == NULL)
{
/* We ran out of memory while resizing the dtv slotinfo list. */
diff --git a/elf/rtld.c b/elf/rtld.c
index e9525ea987..6352ba76c5 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -788,6 +788,8 @@ init_tls (size_t naudit)
_dl_fatal_printf ("\
cannot allocate TLS data structures for initial thread\n");
+ _dl_tls_initial_modid_limit_setup ();
+
/* Store for detection of the special case by __tls_get_addr
so it knows not to pass this dtv to the normal realloc. */
GL(dl_initial_dtv) = GET_DTV (tcbp);
diff --git a/elf/tst-recursive-tls.c b/elf/tst-recursive-tls.c
new file mode 100644
index 0000000000..716d1f783a
--- /dev/null
+++ b/elf/tst-recursive-tls.c
@@ -0,0 +1,60 @@
+/* Test with interposed malloc with dynamic TLS.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+/* Defined in tst-recursive-tlsmallocmod.so. */
+extern __thread unsigned int malloc_subsytem_counter;
+
+static int
+do_test (void)
+{
+ /* 16 is large enough to exercise the DTV resizing case. */
+ void *handles[16];
+
+ for (unsigned int i = 0; i < array_length (handles); ++i)
+ {
+ /* Re-use the TLS slot for module 0. */
+ if (i > 0)
+ xdlclose (handles[0]);
+
+ char soname[30];
+ snprintf (soname, sizeof (soname), "tst-recursive-tlsmod%u.so", i);
+ handles[i] = xdlopen (soname, RTLD_NOW);
+
+ if (i > 0)
+ {
+ handles[0] = xdlopen ("tst-recursive-tlsmod0.so", RTLD_NOW);
+ int (*fptr) (void) = xdlsym (handles[0], "get_threadvar_0");
+ /* May trigger TLS storage allocation using malloc. */
+ TEST_COMPARE (fptr (), 0);
+ }
+ }
+
+ for (unsigned int i = 0; i < array_length (handles); ++i)
+ xdlclose (handles[i]);
+
+ printf ("info: malloc subsystem calls: %u\n", malloc_subsytem_counter);
+ TEST_VERIFY (malloc_subsytem_counter > 0);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-recursive-tlsmallocmod.c b/elf/tst-recursive-tlsmallocmod.c
new file mode 100644
index 0000000000..c24e9945d1
--- /dev/null
+++ b/elf/tst-recursive-tlsmallocmod.c
@@ -0,0 +1,64 @@
+/* Interposed malloc with dynamic TLS.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <dlfcn.h>
+
+__thread unsigned int malloc_subsytem_counter;
+
+static __typeof (malloc) *malloc_fptr;
+static __typeof (free) *free_fptr;
+static __typeof (calloc) *calloc_fptr;
+static __typeof (realloc) *realloc_fptr;
+
+static void __attribute__ ((constructor))
+init (void)
+{
+ malloc_fptr = dlsym (RTLD_NEXT, "malloc");
+ free_fptr = dlsym (RTLD_NEXT, "free");
+ calloc_fptr = dlsym (RTLD_NEXT, "calloc");
+ realloc_fptr = dlsym (RTLD_NEXT, "realloc");
+}
+
+void *
+malloc (size_t size)
+{
+ ++malloc_subsytem_counter;
+ return malloc_fptr (size);
+}
+
+void
+free (void *ptr)
+{
+ ++malloc_subsytem_counter;
+ return free_fptr (ptr);
+}
+
+void *
+calloc (size_t a, size_t b)
+{
+ ++malloc_subsytem_counter;
+ return calloc_fptr (a, b);
+}
+
+void *
+realloc (void *ptr, size_t size)
+{
+ ++malloc_subsytem_counter;
+ return realloc_fptr (ptr, size);
+}
diff --git a/elf/tst-recursive-tlsmodN.c b/elf/tst-recursive-tlsmodN.c
new file mode 100644
index 0000000000..bb7592aee6
--- /dev/null
+++ b/elf/tst-recursive-tlsmodN.c
@@ -0,0 +1,28 @@
+/* Test module with global-dynamic TLS. Used to trigger DTV reallocation.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Compiled with VAR and FUNC set via -D. FUNC requires some
+ relocation against TLS variable VAR. */
+
+__thread int VAR;
+
+int
+FUNC (void)
+{
+ return VAR;
+}
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 50f58a60e3..656e8a3fa0 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1256,6 +1256,20 @@ extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid,
size_t gen)
attribute_hidden;
+/* The last TLS module ID that is initially loaded, plus 1. TLS
+ addresses for modules with IDs lower than that can be obtained from
+ the DTV even if its generation is outdated. */
+extern size_t _dl_tls_initial_modid_limit attribute_hidden attribute_relro;
+
+/* Compute _dl_tls_initial_modid_limit. To be called after initial
+ relocation. */
+void _dl_tls_initial_modid_limit_setup (void) attribute_hidden;
+
+/* Number of threads currently in a TLS update. This is used to
+ detect reentrant __tls_get_addr calls without a per-thread
+ flag. */
+extern unsigned int _dl_tls_threads_in_update attribute_hidden;
+
/* Look up the module's TLS block as for __tls_get_addr,
but never touch anything. Return null if it's not allocated yet. */
extern void *_dl_tls_get_addr_soft (struct link_map *l) attribute_hidden;
diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c
index 869023bbba..b3c1e4fcd7 100644
--- a/sysdeps/x86_64/dl-tls.c
+++ b/sysdeps/x86_64/dl-tls.c
@@ -41,7 +41,10 @@ __tls_get_addr_slow (GET_ADDR_ARGS)
dtv_t *dtv = THREAD_DTV ();
size_t gen = atomic_load_acquire (&GL(dl_tls_generation));
- if (__glibc_unlikely (dtv[0].counter != gen))
+ if (__glibc_unlikely (dtv[0].counter != gen)
+ /* See comment in __tls_get_addr in elf/dl-tls.c. */
+ && !(_dl_tls_allocate_active ()
+ && GET_ADDR_MODULE < _dl_tls_initial_modid_limit))
return update_get_addr (GET_ADDR_PARAM, gen);
return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL);

@ -1,44 +0,0 @@
commit 0e16db440cc73d2cdd94e439c0efa1ec43d92b2a
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Aug 13 15:52:34 2024 +0200
manual: Document generic printf error codes
Describe EOVERFLOW, ENOMEN, EILSEQ.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/manual/stdio.texi b/manual/stdio.texi
index 567f6780011f9db1..41298b87a4a6c7d9 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -2318,6 +2318,29 @@ the easiest way to make sure you have all the right prototypes is to
just include @file{stdio.h}.
@pindex stdio.h
+The @code{printf} family shares the error codes listed below.
+Individual functions may report additional @code{errno} values if they
+fail.
+
+@table @code
+@item EOVERFLOW
+The number of written bytes would have exceeded @code{INT_MAX}, and thus
+could not be represented in the return type @code{int}.
+
+@item ENOMEM
+The function could not allocate memory during processing. Long argument
+lists and certain floating point conversions may require memory
+allocation, as does initialization of an output stream upon first use.
+
+@item EILSEQ
+POSIX specifies this error code should be used if a wide character is
+encountered that does not have a matching valid character. @Theglibc{}
+always performs transliteration, using a replacement character if
+necessary, so this error condition cannot occur on output. However,
+@theglibc{} uses @code{EILSEQ} to indicate that an input character
+sequence (wide or multi-byte) could not be converted successfully.
+@end table
+
@deftypefun int printf (const char *@var{template}, @dots{})
@standards{ISO, stdio.h}
@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}}

@ -1,53 +0,0 @@
commit 2be0572f3a41d5d5a8bb3b2b04244b7c01ac0f58
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Aug 13 15:52:34 2024 +0200
manual: Document dprintf and vdprintf
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/manual/stdio.texi b/manual/stdio.texi
index 41298b87a4a6c7d9..d3d855fc62b8768b 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -2483,6 +2483,26 @@ store the result in which case @code{-1} is returned. This was
changed in order to comply with the @w{ISO C99} standard.
@end deftypefun
+@deftypefun dprintf (int @var{fd}, @var{template}, ...)
+@standards{POSIX, stdio.h}
+@safety{@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
+This function formats its arguments according to @var{template} and
+writes the result to the file descriptor @var{fd}, using the
+@code{write} function. It returns the number of bytes written, or a
+negative value if there was an error. In the error case, @code{errno}
+is set appropriately. The possible @code{errno} values depend on the
+type of the file descriptor @var{fd}, in addition to the general
+@code{printf} error codes.
+
+The number of calls to @code{write} is unspecified, and some @code{write}
+calls may have happened even if @code{dprintf} returns with an error.
+
+@strong{Portability Note:} POSIX does not require that this function is
+async-signal-safe, and @theglibc{} implementation is not. However, some
+other systems offer this function as an async-signal-safe alternative to
+@code{fprintf}. @xref{POSIX Safety Concepts}.
+@end deftypefun
+
@node Dynamic Output
@subsection Dynamically Allocating Formatted Output
@@ -2696,6 +2716,13 @@ The @code{obstack_vprintf} function is the equivalent of
as for @code{vprintf}.@refill
@end deftypefun
+@deftypefun int vdprintf (int @var{fd}, const char *@var{template}, va_list @var{ap})
+@standards{POSIX, stdio.h}
+@safety{@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
+The @code{vdprintf} is the equivalent of @code{dprintf}, but processes
+an argument list.
+@end deftypefun
+
Here's an example showing how you might use @code{vfprintf}. This is a
function that prints error messages to the stream @code{stderr}, along
with a prefix indicating the name of the program

@ -1,50 +0,0 @@
commit 10de4a47ef3f481592e3c62eb07bcda23e9fde4d
Author: Arjun Shankar <arjun@redhat.com>
Date: Mon Jul 29 14:30:59 2024 +0200
manual/stdio: Clarify putc and putwc
The manual entry for `putc' described what "most systems" do instead of
describing the glibc implementation and its guarantees. This commit
fixes that by warning that putc may be implemented as a macro that
double-evaluates `stream', and removing the performance claim.
Even though the current `putc' implementation does not double-evaluate
`stream', offering this obscure guarantee as an extension to what
POSIX allows does not seem very useful.
The entry for `putwc' is also edited to bring it in line with `putc'.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
diff --git a/manual/stdio.texi b/manual/stdio.texi
index fd7ed0cedc7c1a59..0c9a7ce4a9df4c05 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -903,21 +903,21 @@ This function is a GNU extension.
@deftypefun int putc (int @var{c}, FILE *@var{stream})
@standards{ISO, stdio.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
-This is just like @code{fputc}, except that most systems implement it as
+This is just like @code{fputc}, except that it may be implemented as
a macro, making it faster. One consequence is that it may evaluate the
@var{stream} argument more than once, which is an exception to the
-general rule for macros. @code{putc} is usually the best function to
-use for writing a single character.
+general rule for macros. Therefore, @var{stream} should never be an
+expression with side-effects.
@end deftypefun
@deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream})
@standards{ISO, wchar.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
-This is just like @code{fputwc}, except that it can be implement as
+This is just like @code{fputwc}, except that it may be implemented as
a macro, making it faster. One consequence is that it may evaluate the
@var{stream} argument more than once, which is an exception to the
-general rule for macros. @code{putwc} is usually the best function to
-use for writing a single wide character.
+general rule for macros. Therefore, @var{stream} should never be an
+expression with side-effects.
@end deftypefun
@deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream})

@ -1,71 +0,0 @@
commit 942670c81dc8071dd75d6213e771daa5d2084cb6
Author: Arjun Shankar <arjun@redhat.com>
Date: Tue Jul 30 11:37:57 2024 +0200
manual/stdio: Further clarify putc, putwc, getc, and getwc
This is a follow-up to 10de4a47ef3f481592e3c62eb07bcda23e9fde4d that
reworded the manual entries for putc and putwc and removed any
performance claims.
This commit further clarifies these entries and brings getc and getwc in
line with the descriptions of putc and putwc, removing any performance
claims from them as well.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
diff --git a/manual/stdio.texi b/manual/stdio.texi
index 0c9a7ce4a9df4c05..567f6780011f9db1 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -904,20 +904,16 @@ This function is a GNU extension.
@standards{ISO, stdio.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
This is just like @code{fputc}, except that it may be implemented as
-a macro, making it faster. One consequence is that it may evaluate the
-@var{stream} argument more than once, which is an exception to the
-general rule for macros. Therefore, @var{stream} should never be an
-expression with side-effects.
+a macro and may evaluate the @var{stream} argument more than once.
+Therefore, @var{stream} should never be an expression with side-effects.
@end deftypefun
@deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream})
@standards{ISO, wchar.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
This is just like @code{fputwc}, except that it may be implemented as
-a macro, making it faster. One consequence is that it may evaluate the
-@var{stream} argument more than once, which is an exception to the
-general rule for macros. Therefore, @var{stream} should never be an
-expression with side-effects.
+a macro and may evaluate the @var{stream} argument more than once.
+Therefore, @var{stream} should never be an expression with side-effects.
@end deftypefun
@deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream})
@@ -1110,20 +1106,17 @@ This function is a GNU extension.
@deftypefun int getc (FILE *@var{stream})
@standards{ISO, stdio.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}}
-This is just like @code{fgetc}, except that it is permissible (and
-typical) for it to be implemented as a macro that evaluates the
-@var{stream} argument more than once. @code{getc} is often highly
-optimized, so it is usually the best function to use to read a single
-character.
+This is just like @code{fgetc}, except that it may be implemented as
+a macro and may evaluate the @var{stream} argument more than once.
+Therefore, @var{stream} should never be an expression with side-effects.
@end deftypefun
@deftypefun wint_t getwc (FILE *@var{stream})
@standards{ISO, wchar.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}}
-This is just like @code{fgetwc}, except that it is permissible for it to
-be implemented as a macro that evaluates the @var{stream} argument more
-than once. @code{getwc} can be highly optimized, so it is usually the
-best function to use to read a single wide character.
+This is just like @code{fgetwc}, except that it may be implemented as
+a macro and may evaluate the @var{stream} argument more than once.
+Therefore, @var{stream} should never be an expression with side-effects.
@end deftypefun
@deftypefun int getc_unlocked (FILE *@var{stream})

@ -1,83 +0,0 @@
From a65ff76c9a1811dd2396ab45563f645579c0e687 Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
Date: Thu, 27 Oct 2022 11:36:44 +0200
Subject: ld.so: Export tls_init_tp_called as __rtld_tls_init_tp_called
This allows the rest of dynamic loader to check whether the TCB
has been set up (and THREAD_GETMEM and THREAD_SETMEM will work).
Reviewed-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
Conflicts:
Regenerated for context changes.
diff -rup a/elf/rtld.c b/elf/rtld.c
--- a/elf/rtld.c 2024-08-22 17:57:02.000830481 -0400
+++ b/elf/rtld.c 2024-08-22 17:59:30.666562835 -0400
@@ -740,7 +740,7 @@ match_version (const char *string, struc
return 0;
}
-static bool tls_init_tp_called;
+bool __rtld_tls_init_tp_called;
static void *
init_tls (size_t naudit)
@@ -812,7 +812,7 @@ cannot allocate TLS data structures for
if (__glibc_unlikely (lossage != NULL))
_dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
__tls_init_tp ();
- tls_init_tp_called = true;
+ __rtld_tls_init_tp_called = true;
return tcbp;
}
@@ -2057,7 +2057,7 @@ dl_main (const ElfW(Phdr) *phdr,
an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever
used. Trying to do it lazily is too hairy to try when there could be
multiple threads (from a non-TLS-using libpthread). */
- bool was_tls_init_tp_called = tls_init_tp_called;
+ bool was_tls_init_tp_called = __rtld_tls_init_tp_called;
if (tcbp == NULL)
tcbp = init_tls (0);
@@ -2411,7 +2411,7 @@ dl_main (const ElfW(Phdr) *phdr,
_dl_protect_relro (l);
/* Add object to slot information data if necessasy. */
- if (l->l_tls_blocksize != 0 && tls_init_tp_called)
+ if (l->l_tls_blocksize != 0 && __rtld_tls_init_tp_called)
_dl_add_to_slotinfo (l, true);
}
}
@@ -2462,7 +2462,7 @@ dl_main (const ElfW(Phdr) *phdr,
consider_profiling);
/* Add object to slot information data if necessasy. */
- if (l->l_tls_blocksize != 0 && tls_init_tp_called)
+ if (l->l_tls_blocksize != 0 && __rtld_tls_init_tp_called)
_dl_add_to_slotinfo (l, true);
}
rtld_timer_stop (&relocate_time, start);
@@ -2488,7 +2488,7 @@ dl_main (const ElfW(Phdr) *phdr,
_dl_allocate_tls_init (tcbp, true);
/* And finally install it for the main thread. */
- if (! tls_init_tp_called)
+ if (! __rtld_tls_init_tp_called)
{
const char *lossage = TLS_INIT_TP (tcbp);
if (__glibc_unlikely (lossage != NULL))
diff -rup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
--- a/sysdeps/generic/ldsodefs.h 2024-08-22 17:57:02.011830906 -0400
+++ b/sysdeps/generic/ldsodefs.h 2024-08-22 17:58:10.900487160 -0400
@@ -1262,6 +1262,9 @@ extern void *_dl_allocate_tls_storage (v
extern void *_dl_allocate_tls_init (void *result, bool main_thread);
rtld_hidden_proto (_dl_allocate_tls_init)
+/* True if the TCB has been set up. */
+extern bool __rtld_tls_init_tp_called attribute_hidden;
+
/* Deallocate memory allocated with _dl_allocate_tls. */
extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb);
rtld_hidden_proto (_dl_deallocate_tls)

File diff suppressed because it is too large Load Diff

@ -1,82 +0,0 @@
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

@ -1,79 +0,0 @@
New test case to verify padding usage.
diff --git a/nptl/Makefile b/nptl/Makefile
index ff4d590f11c38277..9a56d34313d06444 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -319,6 +319,8 @@ tests-internal := tst-robustpi8 tst-rwlock19 tst-rwlock20 \
tst-barrier5 tst-signal7 tst-mutex8 tst-mutex8-static \
tst-mutexpi8 tst-mutexpi8-static \
tst-setgetname \
+ tst-nptl-padding \
+ # tests-internal
xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \
tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 tst-setgroups \
diff --git a/nptl/tst-nptl-padding.c b/nptl/tst-nptl-padding.c
new file mode 100644
index 0000000000000000..5bb64f4a54335e36
--- /dev/null
+++ b/nptl/tst-nptl-padding.c
@@ -0,0 +1,57 @@
+/* Downstream-only test for verifying that fields that have been
+ relocated into struct pthread padding actually use the padding.
+
+ At present, only rtld_catch (downstream: rtld_catch_f) has been
+ placed into padding. */
+
+#include <descr.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ struct pthread descr;
+
+ /* Mark the entire descriptor as used. */
+ memset (&descr, 0xff, sizeof (descr));
+
+ /* Mark the padding as unused. */
+#ifdef __x86_64__
+ /* Special case: Usable padding is in the header. */
+ memset (&descr.header.__padding, 0, sizeof (descr.header.__padding));
+#else
+ /* The padding should be directly adjacent to the first real
+ struct field. */
+ TEST_COMPARE (sizeof (descr.__padding), offsetof (struct pthread, list));
+
+ /* Clear the unused tail of the padding. */
+ {
+ char *base = (char *) &descr;
+ char *end_of_header = base + sizeof (descr.header);
+ char *end_of_padding = base + sizeof (descr.__padding);
+ memset (end_of_header, 0, end_of_padding - end_of_header);
+ }
+#endif
+
+ /* These fields are not in padding and should remain marked as used. */
+ TEST_COMPARE (descr.header.gscope_flag, -1);
+ TEST_COMPARE ((intptr_t) descr.list.next, -1);
+ TEST_COMPARE ((intptr_t) descr.list.prev, -1);
+
+ /* But this field remains in padding. */
+ TEST_COMPARE ((intptr_t) descr.rtld_catch_f, 0);
+
+ /* Write to all padding-relocated fields below to show that they
+ have independent locations. */
+ struct rtld_catch *rtld_catch_dummy = (void *) "rtld_catch_dummy";
+ descr.rtld_catch_f = rtld_catch_dummy;
+
+ TEST_VERIFY (descr.rtld_catch_f == rtld_catch_dummy);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

@ -1,51 +0,0 @@
commit 9b7651410375ec8848a1944992d663d514db4ba7
Author: Stefan Liebler <stli@linux.ibm.com>
Date: Thu Jul 11 11:28:53 2024 +0200
s390x: Fix segfault in wcsncmp [BZ #31934]
The z13/vector-optimized wcsncmp implementation segfaults if n=1
and there is only one character (equal on both strings) before
the page end. Then it loads and compares one character and misses
to check n again. The following load fails.
This patch removes the extra load and compare of the first character
and just start with the loop which uses vector-load-to-block-boundary.
This code-path also checks n.
With this patch both tests are passing:
- the simplified one mentioned in the bugzilla 31934
- the full one in Florian Weimer's patch:
"manual: Document a GNU extension for strncmp/wcsncmp"
(https://patchwork.sourceware.org/project/glibc/patch/874j9eml6y.fsf@oldenburg.str.redhat.com/):
On s390x-linux-gnu (z16), the new wcsncmp test fails due to bug 31934.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/sysdeps/s390/wcsncmp-vx.S b/sysdeps/s390/wcsncmp-vx.S
index bf6dfa6bc2..8b081567a2 100644
--- a/sysdeps/s390/wcsncmp-vx.S
+++ b/sysdeps/s390/wcsncmp-vx.S
@@ -59,14 +59,7 @@ ENTRY(WCSNCMP_Z13)
sllg %r4,%r4,2 /* Convert character-count to byte-count. */
locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */
- /* Check first character without vector load. */
- lghi %r5,4 /* current_len = 4 bytes. */
- /* Check s1/2[0]. */
- lt %r0,0(%r2)
- l %r1,0(%r3)
- je .Lend_cmp_one_char
- crjne %r0,%r1,.Lend_cmp_one_char
-
+ lghi %r5,0 /* current_len = 0 bytes. */
.Lloop:
vlbb %v17,0(%r5,%r3),6 /* Load s2 to block boundary. */
vlbb %v16,0(%r5,%r2),6 /* Load s1 to block boundary. */
@@ -167,7 +160,6 @@ ENTRY(WCSNCMP_Z13)
srl %r4,2 /* And convert it to character-index. */
vlgvf %r0,%v16,0(%r4) /* Load character-values. */
vlgvf %r1,%v17,0(%r4)
-.Lend_cmp_one_char:
cr %r0,%r1
je .Lend_equal
lghi %r2,1

@ -1,248 +0,0 @@
commit 54252394c25ddf0062e288d4a6ab7a885f8ae009
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Jun 27 16:26:56 2024 +0200
Enhanced test coverage for strncmp, wcsncmp
Add string/test-strncmp-nonarray and
wcsmbs/test-wcsncmp-nonarray.
This is the test that uncovered bug 31934. Test run time
is more than one minute on a fairly current system, so turn
these into xtests that do not run automatically.
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
diff -Nrup a/string/Makefile b/string/Makefile
--- a/string/Makefile 2024-09-03 11:42:30.396319962 -0400
+++ b/string/Makefile 2024-09-03 11:52:17.707438963 -0400
@@ -76,7 +76,10 @@ tests-unsupported += $(tests-translation
endif
# This test allocates a lot of memory and can run for a long time.
-xtests = tst-strcoll-overflow
+xtests += tst-strcoll-overflow
+
+# This test runs for a long time.
+xtests += test-strncmp-nonarray
# This test needs libdl.
ifeq (yes,$(build-shared))
diff -Nrup a/string/test-Xncmp-nonarray.c b/string/test-Xncmp-nonarray.c
--- a/string/test-Xncmp-nonarray.c 1969-12-31 19:00:00.000000000 -0500
+++ b/string/test-Xncmp-nonarray.c 2024-09-03 11:52:17.707438963 -0400
@@ -0,0 +1,183 @@
+/* Test non-array inputs to string comparison functions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* This skeleton file is included from string/test-strncmp-nonarray.c and
+ wcsmbs/test-wcsncmp-nonarray.c to test that reading of the arrays stops
+ at the first null character.
+
+ TEST_IDENTIFIER must be the test function identifier. TEST_NAME is
+ the same as a string.
+
+ CHAR must be defined as the character type. */
+
+#include <array_length.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/next_to_fault.h>
+#include <support/test-driver.h>
+#include <sys/param.h>
+#include <unistd.h>
+
+/* Much shorter than test-Xnlen-nonarray.c because of deeply nested loops. */
+enum { buffer_length = 80 };
+
+/* The test buffer layout follows what is described test-Xnlen-nonarray.c,
+ except that there two buffers, left and right. The variables
+ a_count, zero_count, start_offset are all duplicated. */
+
+/* Return the maximum string length for a string that starts at
+ start_offset. */
+static int
+string_length (int a_count, int start_offset)
+{
+ if (start_offset == buffer_length || start_offset >= a_count)
+ return 0;
+ else
+ return a_count - start_offset;
+}
+
+/* This is the valid maximum length argument computation for
+ strnlen/wcsnlen. See text-Xnlen-nonarray.c. */
+static int
+maximum_length (int start_offset, int zero_count)
+{
+ if (start_offset == buffer_length)
+ return 0;
+ else if (zero_count > 0)
+ /* Effectively unbounded, but we need to stop fairly low,
+ otherwise testing takes too long. */
+ return buffer_length + 32;
+ else
+ return buffer_length - start_offset;
+}
+
+typedef __typeof (TEST_IDENTIFIER) *proto_t;
+
+#define TEST_MAIN
+#include "test-string.h"
+
+IMPL (TEST_IDENTIFIER, 1)
+
+static int
+test_main (void)
+{
+ TEST_VERIFY_EXIT (sysconf (_SC_PAGESIZE) >= buffer_length);
+ test_init ();
+
+ struct support_next_to_fault left_ntf
+ = support_next_to_fault_allocate (buffer_length * sizeof (CHAR));
+ CHAR *left_buffer = (CHAR *) left_ntf.buffer;
+ struct support_next_to_fault right_ntf
+ = support_next_to_fault_allocate (buffer_length * sizeof (CHAR));
+ CHAR *right_buffer = (CHAR *) right_ntf.buffer;
+
+ FOR_EACH_IMPL (impl, 0)
+ {
+ printf ("info: testing %s\n", impl->name);
+ for (size_t i = 0; i < buffer_length; ++i)
+ left_buffer[i] = 'A';
+
+ for (int left_zero_count = 0; left_zero_count <= buffer_length;
+ ++left_zero_count)
+ {
+ if (left_zero_count > 0)
+ left_buffer[buffer_length - left_zero_count] = 0;
+ int left_a_count = buffer_length - left_zero_count;
+ for (size_t i = 0; i < buffer_length; ++i)
+ right_buffer[i] = 'A';
+ for (int right_zero_count = 0; right_zero_count <= buffer_length;
+ ++right_zero_count)
+ {
+ if (right_zero_count > 0)
+ right_buffer[buffer_length - right_zero_count] = 0;
+ int right_a_count = buffer_length - right_zero_count;
+ for (int left_start_offset = 0;
+ left_start_offset <= buffer_length;
+ ++left_start_offset)
+ {
+ CHAR *left_start_pointer = left_buffer + left_start_offset;
+ int left_maxlen
+ = maximum_length (left_start_offset, left_zero_count);
+ int left_length
+ = string_length (left_a_count, left_start_offset);
+ for (int right_start_offset = 0;
+ right_start_offset <= buffer_length;
+ ++right_start_offset)
+ {
+ CHAR *right_start_pointer
+ = right_buffer + right_start_offset;
+ int right_maxlen
+ = maximum_length (right_start_offset, right_zero_count);
+ int right_length
+ = string_length (right_a_count, right_start_offset);
+
+ /* Maximum length is modelled after strnlen/wcsnlen,
+ and must be valid for both pointer arguments at
+ the same time. */
+ int maxlen = MIN (left_maxlen, right_maxlen);
+
+ for (int length_argument = 0; length_argument <= maxlen;
+ ++length_argument)
+ {
+ if (test_verbose)
+ {
+ printf ("left: zero_count=%d"
+ " a_count=%d start_offset=%d\n",
+ left_zero_count, left_a_count,
+ left_start_offset);
+ printf ("right: zero_count=%d"
+ " a_count=%d start_offset=%d\n",
+ right_zero_count, right_a_count,
+ right_start_offset);
+ printf ("length argument: %d\n",
+ length_argument);
+ }
+
+ /* Effective lengths bounded by length argument.
+ The effective length determines the
+ outcome of the comparison. */
+ int left_effective
+ = MIN (left_length, length_argument);
+ int right_effective
+ = MIN (right_length, length_argument);
+ if (left_effective == right_effective)
+ TEST_COMPARE (CALL (impl,
+ left_start_pointer,
+ right_start_pointer,
+ length_argument), 0);
+ else if (left_effective < right_effective)
+ TEST_COMPARE (CALL (impl,
+ left_start_pointer,
+ right_start_pointer,
+ length_argument) < 0, 1);
+ else
+ TEST_COMPARE (CALL (impl,
+ left_start_pointer,
+ right_start_pointer,
+ length_argument) > 0, 1);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff -Nrup a/string/test-strncmp-nonarray.c b/string/test-strncmp-nonarray.c
--- a/string/test-strncmp-nonarray.c 1969-12-31 19:00:00.000000000 -0500
+++ b/string/test-strncmp-nonarray.c 2024-09-03 11:52:17.707438963 -0400
@@ -0,0 +1,4 @@
+#define TEST_IDENTIFIER strncmp
+#define TEST_NAME "strncmp"
+typedef char CHAR;
+#include "test-Xncmp-nonarray.c"
diff -Nrup a/wcsmbs/Makefile b/wcsmbs/Makefile
--- a/wcsmbs/Makefile 2024-09-03 11:42:30.398319976 -0400
+++ b/wcsmbs/Makefile 2024-09-03 11:53:44.806049806 -0400
@@ -56,6 +56,10 @@ tests := tst-wcstof wcsmbs-tst1 tst-wcsn
$(addprefix test-,$(strop-tests)) tst-mbstowcs \
test-wcsdup
+# This test runs for a long time.
+xtests += test-wcsncmp-nonarray
+
+
include ../Rules
ifeq ($(run-built-tests),yes)
diff -Nrup a/wcsmbs/test-wcsncmp-nonarray.c b/wcsmbs/test-wcsncmp-nonarray.c
--- a/wcsmbs/test-wcsncmp-nonarray.c 1969-12-31 19:00:00.000000000 -0500
+++ b/wcsmbs/test-wcsncmp-nonarray.c 2024-09-03 11:52:17.708438970 -0400
@@ -0,0 +1,5 @@
+#include <wchar.h>
+#define TEST_IDENTIFIER wcsncmp
+#define TEST_NAME "wcsncmp"
+typedef wchar_t CHAR;
+#include "../string/test-Xncmp-nonarray.c"

@ -1,327 +0,0 @@
commit 2f47198b04a02097f438ecb765306fa39568a006
Author: Rajalakshmi Srinivasaraghavan <rajis@linux.ibm.com>
Date: Fri Dec 2 14:26:41 2022 -0600
powerpc64: Remove old strncmp optimization
This patch cleans up the power4 strncmp optimization for powerpc64 which
is unlikely to be used anywhere.
Tested on ppc64le with and without --disable-multi-arch flag.
Reviewed-by: Paul E. Murphy <murphyp@linux.ibm.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Conflicts:
sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S
sysdeps/powerpc/powerpc64/power4/strncmp.S
(copyright year changes upstream)
diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile
index 626845a43c4e8ded..5b20dab108de14ab 100644
--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile
+++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile
@@ -12,8 +12,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \
strnlen-power8 strnlen-power7 strnlen-ppc64 \
strcasecmp-power7 strcasecmp_l-power7 \
strncase-power7 strncase_l-power7 \
- strncmp-power8 strncmp-power7 \
- strncmp-power4 strncmp-ppc64 \
+ strncmp-power8 strncmp-power7 strncmp-ppc64 \
strchr-power8 strchr-power7 strchr-ppc64 \
strchrnul-power8 strchrnul-power7 strchrnul-ppc64 \
strcpy-power8 strcpy-power7 strcpy-ppc64 stpcpy-power8 \
diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
index 7b83aa7b8ff28bb7..914e7d5e28a98b5d 100644
--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
@@ -177,8 +177,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
__strncmp_power8)
IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_ARCH_2_06,
__strncmp_power7)
- IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_POWER4,
- __strncmp_power4)
IFUNC_IMPL_ADD (array, i, strncmp, 1,
__strncmp_ppc))
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S
deleted file mode 100644
index 6ead3b6374749e6a..0000000000000000
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Copyright (C) 2013-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#define STRNCMP __strncmp_power4
-
-#undef libc_hidden_builtin_def
-#define libc_hidden_builtin_def(name)
-
-#include <sysdeps/powerpc/powerpc64/power4/strncmp.S>
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
index 2d2112285445a450..275a558e4afa7d61 100644
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
@@ -26,7 +26,6 @@
# include "init-arch.h"
extern __typeof (strncmp) __strncmp_ppc attribute_hidden;
-extern __typeof (strncmp) __strncmp_power4 attribute_hidden;
extern __typeof (strncmp) __strncmp_power7 attribute_hidden;
extern __typeof (strncmp) __strncmp_power8 attribute_hidden;
# ifdef __LITTLE_ENDIAN__
@@ -46,7 +45,5 @@ libc_ifunc_redirected (__redirect_strncmp, strncmp,
? __strncmp_power8
: (hwcap & PPC_FEATURE_ARCH_2_06)
? __strncmp_power7
- : (hwcap & PPC_FEATURE_POWER4)
- ? __strncmp_power4
- : __strncmp_ppc);
+ : __strncmp_ppc);
#endif
diff --git a/sysdeps/powerpc/powerpc64/power4/strncmp.S b/sysdeps/powerpc/powerpc64/power4/strncmp.S
deleted file mode 100644
index cf5f4e5fb8fb2522..0000000000000000
--- a/sysdeps/powerpc/powerpc64/power4/strncmp.S
+++ /dev/null
@@ -1,225 +0,0 @@
-/* Optimized strcmp implementation for PowerPC64.
- Copyright (C) 2003-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-
-#ifndef STRNCMP
-# define STRNCMP strncmp
-#endif
-
-/* See strlen.s for comments on how the end-of-string testing works. */
-
-/* int [r3] strncmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5]) */
-
-ENTRY_TOCLESS (STRNCMP, 4)
- CALL_MCOUNT 3
-
-#define rTMP2 r0
-#define rRTN r3
-#define rSTR1 r3 /* first string arg */
-#define rSTR2 r4 /* second string arg */
-#define rN r5 /* max string length */
-#define rWORD1 r6 /* current word in s1 */
-#define rWORD2 r7 /* current word in s2 */
-#define rWORD3 r10
-#define rWORD4 r11
-#define rFEFE r8 /* constant 0xfefefefefefefeff (-0x0101010101010101) */
-#define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */
-#define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
-#define rBITDIF r11 /* bits that differ in s1 & s2 words */
-#define rTMP r12
-
- dcbt 0,rSTR1
- or rTMP, rSTR2, rSTR1
- lis r7F7F, 0x7f7f
- dcbt 0,rSTR2
- clrldi. rTMP, rTMP, 61
- cmpldi cr1, rN, 0
- lis rFEFE, -0x101
- bne L(unaligned)
-/* We are doubleword aligned so set up for two loops. first a double word
- loop, then fall into the byte loop if any residual. */
- srdi. rTMP, rN, 3
- clrldi rN, rN, 61
- addi rFEFE, rFEFE, -0x101
- addi r7F7F, r7F7F, 0x7f7f
- cmpldi cr1, rN, 0
- beq L(unaligned)
-
- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group. */
- ld rWORD1, 0(rSTR1)
- ld rWORD2, 0(rSTR2)
- sldi rTMP, rFEFE, 32
- insrdi r7F7F, r7F7F, 32, 0
- add rFEFE, rFEFE, rTMP
- b L(g1)
-
-L(g0):
- ldu rWORD1, 8(rSTR1)
- bne- cr1, L(different)
- ldu rWORD2, 8(rSTR2)
-L(g1): add rTMP, rFEFE, rWORD1
- nor rNEG, r7F7F, rWORD1
- bdz L(tail)
- and. rTMP, rTMP, rNEG
- cmpd cr1, rWORD1, rWORD2
- beq+ L(g0)
-
-/* OK. We've hit the end of the string. We need to be careful that
- we don't compare two strings as different because of gunk beyond
- the end of the strings... */
-
-#ifdef __LITTLE_ENDIAN__
-L(endstring):
- addi rTMP2, rTMP, -1
- beq cr1, L(equal)
- andc rTMP2, rTMP2, rTMP
- rldimi rTMP2, rTMP2, 1, 0
- and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */
- and rWORD1, rWORD1, rTMP2
- cmpd cr1, rWORD1, rWORD2
- beq cr1, L(equal)
- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */
- neg rNEG, rBITDIF
- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */
- cntlzd rNEG, rNEG /* bitcount of the bit. */
- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */
- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */
- sld rWORD2, rWORD2, rNEG
- xor. rBITDIF, rWORD1, rWORD2
- sub rRTN, rWORD1, rWORD2
- blt- L(highbit)
- sradi rRTN, rRTN, 63 /* must return an int. */
- ori rRTN, rRTN, 1
- blr
-L(equal):
- li rRTN, 0
- blr
-
-L(different):
- ld rWORD1, -8(rSTR1)
- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */
- neg rNEG, rBITDIF
- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */
- cntlzd rNEG, rNEG /* bitcount of the bit. */
- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */
- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */
- sld rWORD2, rWORD2, rNEG
- xor. rBITDIF, rWORD1, rWORD2
- sub rRTN, rWORD1, rWORD2
- blt- L(highbit)
- sradi rRTN, rRTN, 63
- ori rRTN, rRTN, 1
- blr
-L(highbit):
- sradi rRTN, rWORD2, 63
- ori rRTN, rRTN, 1
- blr
-
-#else
-L(endstring):
- and rTMP, r7F7F, rWORD1
- beq cr1, L(equal)
- add rTMP, rTMP, r7F7F
- xor. rBITDIF, rWORD1, rWORD2
- andc rNEG, rNEG, rTMP
- blt- L(highbit)
- cntlzd rBITDIF, rBITDIF
- cntlzd rNEG, rNEG
- addi rNEG, rNEG, 7
- cmpd cr1, rNEG, rBITDIF
- sub rRTN, rWORD1, rWORD2
- blt- cr1, L(equal)
- sradi rRTN, rRTN, 63 /* must return an int. */
- ori rRTN, rRTN, 1
- blr
-L(equal):
- li rRTN, 0
- blr
-
-L(different):
- ld rWORD1, -8(rSTR1)
- xor. rBITDIF, rWORD1, rWORD2
- sub rRTN, rWORD1, rWORD2
- blt- L(highbit)
- sradi rRTN, rRTN, 63
- ori rRTN, rRTN, 1
- blr
-L(highbit):
- sradi rRTN, rWORD2, 63
- ori rRTN, rRTN, 1
- blr
-#endif
-
-/* Oh well. In this case, we just do a byte-by-byte comparison. */
- .align 4
-L(tail):
- and. rTMP, rTMP, rNEG
- cmpd cr1, rWORD1, rWORD2
- bne- L(endstring)
- addi rSTR1, rSTR1, 8
- bne- cr1, L(different)
- addi rSTR2, rSTR2, 8
- cmpldi cr1, rN, 0
-L(unaligned):
- mtctr rN /* Power4 wants mtctr 1st in dispatch group */
- ble cr1, L(ux)
-L(uz):
- lbz rWORD1, 0(rSTR1)
- lbz rWORD2, 0(rSTR2)
- .align 4
-L(u1):
- cmpdi cr1, rWORD1, 0
- bdz L(u4)
- cmpd rWORD1, rWORD2
- beq- cr1, L(u4)
- bne- L(u4)
- lbzu rWORD3, 1(rSTR1)
- lbzu rWORD4, 1(rSTR2)
- cmpdi cr1, rWORD3, 0
- bdz L(u3)
- cmpd rWORD3, rWORD4
- beq- cr1, L(u3)
- bne- L(u3)
- lbzu rWORD1, 1(rSTR1)
- lbzu rWORD2, 1(rSTR2)
- cmpdi cr1, rWORD1, 0
- bdz L(u4)
- cmpd rWORD1, rWORD2
- beq- cr1, L(u4)
- bne- L(u4)
- lbzu rWORD3, 1(rSTR1)
- lbzu rWORD4, 1(rSTR2)
- cmpdi cr1, rWORD3, 0
- bdz L(u3)
- cmpd rWORD3, rWORD4
- beq- cr1, L(u3)
- bne- L(u3)
- lbzu rWORD1, 1(rSTR1)
- lbzu rWORD2, 1(rSTR2)
- b L(u1)
-
-L(u3): sub rRTN, rWORD3, rWORD4
- blr
-L(u4): sub rRTN, rWORD1, rWORD2
- blr
-L(ux):
- li rRTN, 0
- blr
-END (STRNCMP)
-libc_hidden_builtin_def (strncmp)

@ -1,595 +0,0 @@
commit 92fdb11ae7aa1ab6b18622670ea702205cd6fdc5
Author: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
Date: Tue Feb 28 14:23:59 2023 -0300
powerpc: Remove powerpc64 strncmp variants
The default, and power7 implementation just adds word aligned
access when inputs have the same aligment. The unaligned case
is still done by byte operations.
This is already covered by the generic implementation, which also add
the unaligned input optimization.
Checked on powerpc64-linux-gnu built without multi-arch for powerpc64,
power7, power8, and power9 (build for le).
Reviewed-by: Rajalakshmi Srinivasaraghavan <rajis@linux.ibm.com>
Conflicts:
sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S
sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S
sysdeps/powerpc/powerpc64/power7/strncmp.S
sysdeps/powerpc/powerpc64/strncmp.S
(copyright year changes upstream)
diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile
index 5b20dab108de14ab..0ee7ce39d6470d80 100644
--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile
+++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile
@@ -12,7 +12,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \
strnlen-power8 strnlen-power7 strnlen-ppc64 \
strcasecmp-power7 strcasecmp_l-power7 \
strncase-power7 strncase_l-power7 \
- strncmp-power8 strncmp-power7 strncmp-ppc64 \
+ strncmp-power8 strncmp-ppc64 \
strchr-power8 strchr-power7 strchr-ppc64 \
strchrnul-power8 strchrnul-power7 strchrnul-ppc64 \
strcpy-power8 strcpy-power7 strcpy-ppc64 stpcpy-power8 \
diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
index 914e7d5e28a98b5d..2c84d287ee76a7ea 100644
--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
@@ -175,8 +175,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
#endif
IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_2_07,
__strncmp_power8)
- IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_ARCH_2_06,
- __strncmp_power7)
IFUNC_IMPL_ADD (array, i, strncmp, 1,
__strncmp_ppc))
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S
deleted file mode 100644
index 8282ff076c9e00ce..0000000000000000
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Copyright (C) 2013-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#define STRNCMP __strncmp_power7
-
-#undef libc_hidden_builtin_def
-#define libc_hidden_builtin_def(name)
-
-#include <sysdeps/powerpc/powerpc64/power7/strncmp.S>
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S
deleted file mode 100644
index c6f325650c9ace3b..0000000000000000
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright (C) 2013-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#if defined SHARED && IS_IN (libc)
-# define STRNCMP __strncmp_ppc
-
-# undef libc_hidden_builtin_def
-# define libc_hidden_builtin_def(name) \
- .globl __GI_strncmp; __GI_strncmp = __strncmp_ppc
-#endif
-
-#include <sysdeps/powerpc/powerpc64/strncmp.S>
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c
new file mode 100644
index 0000000000000000..09cc009a913ed169
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c
@@ -0,0 +1,7 @@
+#if defined SHARED && IS_IN (libc)
+# define STRNCMP __strncmp_ppc
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(name) \
+ __hidden_ver1 (__strncmp_ppc, __GI_strncmp, __strncmp_ppc);
+#endif
+#include <string/strncmp.c>
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
index 275a558e4afa7d61..df2c0707a919ad79 100644
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
@@ -26,7 +26,6 @@
# include "init-arch.h"
extern __typeof (strncmp) __strncmp_ppc attribute_hidden;
-extern __typeof (strncmp) __strncmp_power7 attribute_hidden;
extern __typeof (strncmp) __strncmp_power8 attribute_hidden;
# ifdef __LITTLE_ENDIAN__
extern __typeof (strncmp) __strncmp_power9 attribute_hidden;
@@ -43,7 +42,5 @@ libc_ifunc_redirected (__redirect_strncmp, strncmp,
# endif
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
? __strncmp_power8
- : (hwcap & PPC_FEATURE_ARCH_2_06)
- ? __strncmp_power7
- : __strncmp_ppc);
+ : __strncmp_ppc);
#endif
diff --git a/sysdeps/powerpc/powerpc64/power7/strncmp.S b/sysdeps/powerpc/powerpc64/power7/strncmp.S
deleted file mode 100644
index d91aeb6077a558f2..0000000000000000
--- a/sysdeps/powerpc/powerpc64/power7/strncmp.S
+++ /dev/null
@@ -1,228 +0,0 @@
-/* Optimized strcmp implementation for POWER7/PowerPC64.
- Copyright (C) 2010-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-
-#ifndef STRNCMP
-# define STRNCMP strncmp
-#endif
-
-/* See strlen.s for comments on how the end-of-string testing works. */
-
-/* int [r3] strncmp (const char *s1 [r3],
- const char *s2 [r4],
- size_t size [r5]) */
-
- .machine power7
-ENTRY_TOCLESS (STRNCMP, 5)
- CALL_MCOUNT 3
-
-#define rTMP2 r0
-#define rRTN r3
-#define rSTR1 r3 /* first string arg */
-#define rSTR2 r4 /* second string arg */
-#define rN r5 /* max string length */
-#define rWORD1 r6 /* current word in s1 */
-#define rWORD2 r7 /* current word in s2 */
-#define rWORD3 r10
-#define rWORD4 r11
-#define rFEFE r8 /* constant 0xfefefefefefefeff (-0x0101010101010101) */
-#define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */
-#define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
-#define rBITDIF r11 /* bits that differ in s1 & s2 words */
-#define rTMP r12
-
- dcbt 0,rSTR1
- nop
- or rTMP,rSTR2,rSTR1
- lis r7F7F,0x7f7f
- dcbt 0,rSTR2
- nop
- clrldi. rTMP,rTMP,61
- cmpldi cr1,rN,0
- lis rFEFE,-0x101
- bne L(unaligned)
-/* We are doubleword aligned so set up for two loops. first a double word
- loop, then fall into the byte loop if any residual. */
- srdi. rTMP,rN,3
- clrldi rN,rN,61
- addi rFEFE,rFEFE,-0x101
- addi r7F7F,r7F7F,0x7f7f
- cmpldi cr1,rN,0
- beq L(unaligned)
-
- mtctr rTMP
- ld rWORD1,0(rSTR1)
- ld rWORD2,0(rSTR2)
- sldi rTMP,rFEFE,32
- insrdi r7F7F,r7F7F,32,0
- add rFEFE,rFEFE,rTMP
- b L(g1)
-
-L(g0):
- ldu rWORD1,8(rSTR1)
- bne cr1,L(different)
- ldu rWORD2,8(rSTR2)
-L(g1): add rTMP,rFEFE,rWORD1
- nor rNEG,r7F7F,rWORD1
- bdz L(tail)
- and. rTMP,rTMP,rNEG
- cmpd cr1,rWORD1,rWORD2
- beq L(g0)
-
-/* OK. We've hit the end of the string. We need to be careful that
- we don't compare two strings as different because of gunk beyond
- the end of the strings... */
-
-#ifdef __LITTLE_ENDIAN__
-L(endstring):
- addi rTMP2, rTMP, -1
- beq cr1, L(equal)
- andc rTMP2, rTMP2, rTMP
- rldimi rTMP2, rTMP2, 1, 0
- and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */
- and rWORD1, rWORD1, rTMP2
- cmpd cr1, rWORD1, rWORD2
- beq cr1, L(equal)
- cmpb rBITDIF, rWORD1, rWORD2 /* 0xff on equal bytes. */
- addi rNEG, rBITDIF, 1
- orc rNEG, rNEG, rBITDIF /* 0's below LS differing byte. */
- sldi rNEG, rNEG, 8 /* 1's above LS differing byte. */
- andc rWORD1, rWORD1, rNEG /* mask off MS bytes. */
- andc rWORD2, rWORD2, rNEG
- xor. rBITDIF, rWORD1, rWORD2
- sub rRTN, rWORD1, rWORD2
- blt L(highbit)
- sradi rRTN, rRTN, 63 /* must return an int. */
- ori rRTN, rRTN, 1
- blr
-L(equal):
- li rRTN, 0
- blr
-
-L(different):
- ld rWORD1, -8(rSTR1)
- cmpb rBITDIF, rWORD1, rWORD2 /* 0xff on equal bytes. */
- addi rNEG, rBITDIF, 1
- orc rNEG, rNEG, rBITDIF /* 0's below LS differing byte. */
- sldi rNEG, rNEG, 8 /* 1's above LS differing byte. */
- andc rWORD1, rWORD1, rNEG /* mask off MS bytes. */
- andc rWORD2, rWORD2, rNEG
- xor. rBITDIF, rWORD1, rWORD2
- sub rRTN, rWORD1, rWORD2
- blt L(highbit)
- sradi rRTN, rRTN, 63
- ori rRTN, rRTN, 1
- blr
-L(highbit):
- sradi rRTN, rWORD2, 63
- ori rRTN, rRTN, 1
- blr
-
-#else
-L(endstring):
- and rTMP,r7F7F,rWORD1
- beq cr1,L(equal)
- add rTMP,rTMP,r7F7F
- xor. rBITDIF,rWORD1,rWORD2
- andc rNEG,rNEG,rTMP
- blt L(highbit)
- cntlzd rBITDIF,rBITDIF
- cntlzd rNEG,rNEG
- addi rNEG,rNEG,7
- cmpd cr1,rNEG,rBITDIF
- sub rRTN,rWORD1,rWORD2
- blt cr1,L(equal)
- sradi rRTN,rRTN,63 /* must return an int. */
- ori rRTN,rRTN,1
- blr
-L(equal):
- li rRTN,0
- blr
-
-L(different):
- ld rWORD1,-8(rSTR1)
- xor. rBITDIF,rWORD1,rWORD2
- sub rRTN,rWORD1,rWORD2
- blt L(highbit)
- sradi rRTN,rRTN,63
- ori rRTN,rRTN,1
- blr
-L(highbit):
- sradi rRTN,rWORD2,63
- ori rRTN,rRTN,1
- blr
-#endif
-
-/* Oh well. In this case, we just do a byte-by-byte comparison. */
- .align 4
-L(tail):
- and. rTMP,rTMP,rNEG
- cmpd cr1,rWORD1,rWORD2
- bne L(endstring)
- addi rSTR1,rSTR1,8
- bne cr1,L(different)
- addi rSTR2,rSTR2,8
- cmpldi cr1,rN,0
-L(unaligned):
- mtctr rN
- ble cr1,L(ux)
-L(uz):
- lbz rWORD1,0(rSTR1)
- lbz rWORD2,0(rSTR2)
- .align 4
-L(u1):
- cmpdi cr1,rWORD1,0
- bdz L(u4)
- cmpd rWORD1,rWORD2
- beq cr1,L(u4)
- bne L(u4)
- lbzu rWORD3,1(rSTR1)
- lbzu rWORD4,1(rSTR2)
- cmpdi cr1,rWORD3,0
- bdz L(u3)
- cmpd rWORD3,rWORD4
- beq cr1,L(u3)
- bne L(u3)
- lbzu rWORD1,1(rSTR1)
- lbzu rWORD2,1(rSTR2)
- cmpdi cr1,rWORD1,0
- bdz L(u4)
- cmpd rWORD1,rWORD2
- beq cr1,L(u4)
- bne L(u4)
- lbzu rWORD3,1(rSTR1)
- lbzu rWORD4,1(rSTR2)
- cmpdi cr1,rWORD3,0
- bdz L(u3)
- cmpd rWORD3,rWORD4
- beq cr1,L(u3)
- bne L(u3)
- lbzu rWORD1,1(rSTR1)
- lbzu rWORD2,1(rSTR2)
- b L(u1)
-
-L(u3): sub rRTN,rWORD3,rWORD4
- blr
-L(u4): sub rRTN,rWORD1,rWORD2
- blr
-L(ux):
- li rRTN,0
- blr
-END (STRNCMP)
-libc_hidden_builtin_def (strncmp)
diff --git a/sysdeps/powerpc/powerpc64/strncmp.S b/sysdeps/powerpc/powerpc64/strncmp.S
deleted file mode 100644
index 40a230242cbdf733..0000000000000000
--- a/sysdeps/powerpc/powerpc64/strncmp.S
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Optimized strcmp implementation for PowerPC64.
- Copyright (C) 2003-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-
-/* See strlen.s for comments on how the end-of-string testing works. */
-
-/* int [r3] strncmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5]) */
-
-#ifndef STRNCMP
-# define STRNCMP strncmp
-#endif
-
-ENTRY_TOCLESS (STRNCMP, 4)
- CALL_MCOUNT 3
-
-#define rTMP2 r0
-#define rRTN r3
-#define rSTR1 r3 /* first string arg */
-#define rSTR2 r4 /* second string arg */
-#define rN r5 /* max string length */
-#define rWORD1 r6 /* current word in s1 */
-#define rWORD2 r7 /* current word in s2 */
-#define rFEFE r8 /* constant 0xfefefefefefefeff (-0x0101010101010101) */
-#define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */
-#define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
-#define rBITDIF r11 /* bits that differ in s1 & s2 words */
-#define rTMP r12
-
- dcbt 0,rSTR1
- or rTMP, rSTR2, rSTR1
- lis r7F7F, 0x7f7f
- dcbt 0,rSTR2
- clrldi. rTMP, rTMP, 61
- cmpldi cr1, rN, 0
- lis rFEFE, -0x101
- bne L(unaligned)
-/* We are doubleword aligned so set up for two loops. first a double word
- loop, then fall into the byte loop if any residual. */
- srdi. rTMP, rN, 3
- clrldi rN, rN, 61
- addi rFEFE, rFEFE, -0x101
- addi r7F7F, r7F7F, 0x7f7f
- cmpldi cr1, rN, 0
- beq L(unaligned)
-
- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group. */
- ld rWORD1, 0(rSTR1)
- ld rWORD2, 0(rSTR2)
- sldi rTMP, rFEFE, 32
- insrdi r7F7F, r7F7F, 32, 0
- add rFEFE, rFEFE, rTMP
- b L(g1)
-
-L(g0):
- ldu rWORD1, 8(rSTR1)
- bne- cr1, L(different)
- ldu rWORD2, 8(rSTR2)
-L(g1): add rTMP, rFEFE, rWORD1
- nor rNEG, r7F7F, rWORD1
- bdz L(tail)
- and. rTMP, rTMP, rNEG
- cmpd cr1, rWORD1, rWORD2
- beq+ L(g0)
-
-/* OK. We've hit the end of the string. We need to be careful that
- we don't compare two strings as different because of gunk beyond
- the end of the strings... */
-
-#ifdef __LITTLE_ENDIAN__
-L(endstring):
- addi rTMP2, rTMP, -1
- beq cr1, L(equal)
- andc rTMP2, rTMP2, rTMP
- rldimi rTMP2, rTMP2, 1, 0
- and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */
- and rWORD1, rWORD1, rTMP2
- cmpd cr1, rWORD1, rWORD2
- beq cr1, L(equal)
- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */
- neg rNEG, rBITDIF
- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */
- cntlzd rNEG, rNEG /* bitcount of the bit. */
- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */
- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */
- sld rWORD2, rWORD2, rNEG
- xor. rBITDIF, rWORD1, rWORD2
- sub rRTN, rWORD1, rWORD2
- blt- L(highbit)
- sradi rRTN, rRTN, 63 /* must return an int. */
- ori rRTN, rRTN, 1
- blr
-L(equal):
- li rRTN, 0
- blr
-
-L(different):
- ld rWORD1, -8(rSTR1)
- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */
- neg rNEG, rBITDIF
- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */
- cntlzd rNEG, rNEG /* bitcount of the bit. */
- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */
- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */
- sld rWORD2, rWORD2, rNEG
- xor. rBITDIF, rWORD1, rWORD2
- sub rRTN, rWORD1, rWORD2
- blt- L(highbit)
- sradi rRTN, rRTN, 63
- ori rRTN, rRTN, 1
- blr
-L(highbit):
- sradi rRTN, rWORD2, 63
- ori rRTN, rRTN, 1
- blr
-
-#else
-L(endstring):
- and rTMP, r7F7F, rWORD1
- beq cr1, L(equal)
- add rTMP, rTMP, r7F7F
- xor. rBITDIF, rWORD1, rWORD2
- andc rNEG, rNEG, rTMP
- blt- L(highbit)
- cntlzd rBITDIF, rBITDIF
- cntlzd rNEG, rNEG
- addi rNEG, rNEG, 7
- cmpd cr1, rNEG, rBITDIF
- sub rRTN, rWORD1, rWORD2
- blt- cr1, L(equal)
- sradi rRTN, rRTN, 63 /* must return an int. */
- ori rRTN, rRTN, 1
- blr
-L(equal):
- li rRTN, 0
- blr
-
-L(different):
- ld rWORD1, -8(rSTR1)
- xor. rBITDIF, rWORD1, rWORD2
- sub rRTN, rWORD1, rWORD2
- blt- L(highbit)
- sradi rRTN, rRTN, 63
- ori rRTN, rRTN, 1
- blr
-L(highbit):
- sradi rRTN, rWORD2, 63
- ori rRTN, rRTN, 1
- blr
-#endif
-
-/* Oh well. In this case, we just do a byte-by-byte comparison. */
- .align 4
-L(tail):
- and. rTMP, rTMP, rNEG
- cmpd cr1, rWORD1, rWORD2
- bne- L(endstring)
- addi rSTR1, rSTR1, 8
- bne- cr1, L(different)
- addi rSTR2, rSTR2, 8
- cmpldi cr1, rN, 0
-L(unaligned):
- mtctr rN /* Power4 wants mtctr 1st in dispatch group */
- bgt cr1, L(uz)
-L(ux):
- li rRTN, 0
- blr
- .align 4
-L(uz):
- lbz rWORD1, 0(rSTR1)
- lbz rWORD2, 0(rSTR2)
- nop
- b L(u1)
-L(u0):
- lbzu rWORD2, 1(rSTR2)
-L(u1):
- bdz L(u3)
- cmpdi cr1, rWORD1, 0
- cmpd rWORD1, rWORD2
- beq- cr1, L(u3)
- lbzu rWORD1, 1(rSTR1)
- bne- L(u2)
- lbzu rWORD2, 1(rSTR2)
- bdz L(u3)
- cmpdi cr1, rWORD1, 0
- cmpd rWORD1, rWORD2
- bne- L(u3)
- lbzu rWORD1, 1(rSTR1)
- bne+ cr1, L(u0)
-
-L(u2): lbzu rWORD1, -1(rSTR1)
-L(u3): sub rRTN, rWORD1, rWORD2
- blr
-END (STRNCMP)
-libc_hidden_builtin_def (strncmp)

@ -1,240 +0,0 @@
commit 3395157ff2b0657d70c36169156f67440205c8bf
Author: Joe Simmons-Talbott <josimmon@redhat.com>
Date: Tue May 14 14:36:50 2024 +0000
malloc: Improve aligned_alloc and calloc test coverage.
Add a DSO (malloc/tst-aligned_alloc-lib.so) that can be used during
testing to interpose malloc with a call that randomly uses either
aligned_alloc, __libc_malloc, or __libc_calloc in the place of malloc.
Use LD_PRELOAD with the DSO to mirror malloc/tst-malloc.c testing as an
example in malloc/tst-malloc-random.c. Add malloc/tst-aligned-alloc-random.c
as another example that does a number of malloc calls with randomly sized,
but limited to 0xffff, requests.
The intention is to be able to utilize existing malloc testing to ensure
that similar allocation APIs are also exposed to the same rigors.
Reviewed-by: DJ Delorie <dj@redhat.com>
Conflicts:
malloc/Makefile
(usual tests conflict)
diff --git a/malloc/Makefile b/malloc/Makefile
index cb4e027d28b179f0..e0fb433a15bad2c2 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -44,6 +44,8 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
tst-safe-linking \
tst-mallocalign1 \
tst-malloc-alternate-path \
+ tst-aligned-alloc-random \
+ tst-malloc-random \
tests-static := \
tst-interpose-static-nothread \
@@ -123,6 +125,7 @@ extra-libs-others = $(extra-libs)
# Helper objects for some tests.
extra-tests-objs += \
+ tst-aligned_alloc-lib.so \
tst-interpose-aux-nothread.o \
tst-interpose-aux-thread.o \
@@ -130,6 +133,9 @@ test-extras = \
tst-interpose-aux-nothread \
tst-interpose-aux-thread \
+modules-names = \
+ tst-aligned_alloc-lib
+
libmemusage-routines = memusage
libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
@@ -328,3 +334,9 @@ tst-mallocstate-malloc-check-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
# libc_malloc_debug.so.
$(objpfx)tst-mallocstate: $(objpfx)libc_malloc_debug.so
$(objpfx)tst-mallocstate-malloc-check: $(objpfx)libc_malloc_debug.so
+
+$(objpfx)tst-aligned-alloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
+$(objpfx)tst-malloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
+
+tst-aligned-alloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+tst-malloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
diff --git a/malloc/tst-aligned-alloc-random.c b/malloc/tst-aligned-alloc-random.c
new file mode 100644
index 0000000000000000..f2825ce38f04e04e
--- /dev/null
+++ b/malloc/tst-aligned-alloc-random.c
@@ -0,0 +1,43 @@
+/* Test for randomized malloc that calls aligned_alloc
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <support/check.h>
+#include <time.h>
+
+static int
+do_test (void)
+{
+ void *p1;
+ int i;
+
+ srandom (time (NULL));
+
+ for (i = 0; i < 1024; i++)
+ {
+ size_t size = random () & 0xffff;
+
+ p1 = malloc (size);
+ TEST_VERIFY (p1 != NULL);
+ }
+
+ return 0;
+}
+
+
+#include <support/test-driver.c>
diff --git a/malloc/tst-aligned_alloc-lib.c b/malloc/tst-aligned_alloc-lib.c
new file mode 100644
index 0000000000000000..0205df5acf6297a5
--- /dev/null
+++ b/malloc/tst-aligned_alloc-lib.c
@@ -0,0 +1,72 @@
+/* Module used for improved aligned_alloc testing.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ Copyright The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <libc-symbols.h>
+#include <stdlib.h>
+
+extern void *__libc_malloc (size_t size);
+extern void *__libc_calloc (size_t n, size_t size);
+
+int aligned_alloc_count = 0;
+int libc_malloc_count = 0;
+int libc_calloc_count = 0;
+
+/* Get a random alignment value. Biased towards the smaller values. Must be
+ a power of 2. */
+static size_t get_random_alignment (void)
+{
+ size_t aligns[] = {
+ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384
+ };
+
+ return aligns[random () % array_length (aligns)];
+}
+
+static void *get_random_alloc (size_t size)
+{
+ void *retval;
+ size_t align;
+
+ switch (random() % 3)
+ {
+ case 1:
+ align = get_random_alignment ();
+ retval = aligned_alloc (align, size);
+ aligned_alloc_count++;
+ break;
+ case 2:
+ retval = __libc_calloc (1, size);
+ libc_calloc_count++;
+ break;
+ default:
+ retval = __libc_malloc (size);
+ libc_malloc_count++;
+ break;
+ }
+
+ return retval;
+}
+
+
+void * __random_malloc (size_t size)
+{
+ return get_random_alloc (size);
+}
+strong_alias (__random_malloc, malloc)
diff --git a/malloc/tst-malloc-random.c b/malloc/tst-malloc-random.c
new file mode 100644
index 0000000000000000..762b70c918cc6004
--- /dev/null
+++ b/malloc/tst-malloc-random.c
@@ -0,0 +1,20 @@
+/* Test malloc with random calls to aligned_alloc and calloc.
+
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include "tst-malloc.c"
diff --git a/malloc/tst-malloc.c b/malloc/tst-malloc.c
index a587cbded66039fb..98be3ee254d75d4e 100644
--- a/malloc/tst-malloc.c
+++ b/malloc/tst-malloc.c
@@ -19,7 +19,9 @@
#include <errno.h>
#include <malloc.h>
#include <stdio.h>
+#include <stdlib.h>
#include <libc-diag.h>
+#include <time.h>
static int errors = 0;
@@ -36,6 +38,8 @@ do_test (void)
void *p, *q;
int save;
+ srandom (time (NULL));
+
errno = 0;
DIAG_PUSH_NEEDS_COMMENT;

@ -1,86 +0,0 @@
commit 9a27b566b2048f599048f2f4afe1cce06c4ef43d
Author: Miguel Martín <mmartinv@redhat.com>
Date: Tue Jul 16 17:14:56 2024 +0200
malloc: avoid global locks in tst-aligned_alloc-lib.c
Make sure the DSO used by aligned_alloc/calloc/malloc tests does not get
a global lock on multithreaded tests.
Reviewed-by: Arjun Shankar <arjun@redhat.com>
diff --git a/malloc/tst-aligned_alloc-lib.c b/malloc/tst-aligned_alloc-lib.c
index 0205df5acf6297a5..9ef1f839c101a6ae 100644
--- a/malloc/tst-aligned_alloc-lib.c
+++ b/malloc/tst-aligned_alloc-lib.c
@@ -17,37 +17,38 @@
License along with the GNU C Library; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
-#include <array_length.h>
#include <libc-symbols.h>
#include <stdlib.h>
+#include <time.h>
extern void *__libc_malloc (size_t size);
extern void *__libc_calloc (size_t n, size_t size);
+__thread unsigned int seed = 0;
+
int aligned_alloc_count = 0;
int libc_malloc_count = 0;
int libc_calloc_count = 0;
-/* Get a random alignment value. Biased towards the smaller values. Must be
- a power of 2. */
-static size_t get_random_alignment (void)
-{
- size_t aligns[] = {
- 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384
- };
-
- return aligns[random () % array_length (aligns)];
-}
-
-static void *get_random_alloc (size_t size)
+static void *
+get_random_alloc (size_t size)
{
void *retval;
size_t align;
+ struct timespec tp;
+
+ if (seed == 0)
+ {
+ clock_gettime (CLOCK_REALTIME, &tp);
+ seed = tp.tv_nsec;
+ }
- switch (random() % 3)
- {
+ switch (rand_r (&seed) % 3)
+ {
case 1:
- align = get_random_alignment ();
+ /* Get a random alignment value. Biased towards the smaller
+ * values up to 16384. Must be a power of 2. */
+ align = 1 << rand_r (&seed) % 15;
retval = aligned_alloc (align, size);
aligned_alloc_count++;
break;
@@ -59,13 +60,13 @@ static void *get_random_alloc (size_t size)
retval = __libc_malloc (size);
libc_malloc_count++;
break;
- }
+ }
return retval;
}
-
-void * __random_malloc (size_t size)
+void *
+__random_malloc (size_t size)
{
return get_random_alloc (size);
}

@ -1,251 +0,0 @@
commit b0fbcb7d0051a68baf26b2aed51a8a31c34d68e5
Author: Miguel Martín <mmartinv@redhat.com>
Date: Tue Jul 16 17:14:57 2024 +0200
malloc: add multi-threaded tests for aligned_alloc/calloc/malloc
Improve aligned_alloc/calloc/malloc test coverage by adding
multi-threaded tests with random memory allocations and with/without
cross-thread memory deallocations.
Perform a number of memory allocation calls with random sizes limited
to 0xffff.
Use the existing DSO ('malloc/tst-aligned_alloc-lib.c') to randomize
allocator selection.
The multi-threaded allocation/deallocation is staged as described below:
- Stage 1: Half of the threads will be allocating memory and the
other half will be waiting for them to finish the allocation.
- Stage 2: Half of the threads will be allocating memory and the
other half will be deallocating memory.
- Stage 3: Half of the threads will be deallocating memory and the
second half waiting on them to finish.
Add 'malloc/tst-aligned-alloc-random-thread.c' where each thread will
deallocate only the memory that was previously allocated by itself.
Add 'malloc/tst-aligned-alloc-random-thread-cross.c' where each thread
will deallocate memory that was previously allocated by another thread.
The intention is to be able to utilize existing malloc testing to ensure
that similar allocation APIs are also exposed to the same rigors.
Reviewed-by: Arjun Shankar <arjun@redhat.com>
Conflicts:
malloc/Makefile
(usual tests conflict)
diff --git a/malloc/Makefile b/malloc/Makefile
index e0fb433a15bad2c2..9dc068f6b3a69caa 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -46,6 +46,8 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
tst-malloc-alternate-path \
tst-aligned-alloc-random \
tst-malloc-random \
+ tst-aligned-alloc-random-thread \
+ tst-aligned-alloc-random-thread-cross \
tests-static := \
tst-interpose-static-nothread \
@@ -96,7 +98,9 @@ tests-exclude-mcheck = tst-mallocstate \
tst-malloc-thread-fail \
tst-malloc-usable-tunables \
tst-malloc_info \
- tst-compathooks-off tst-compathooks-on
+ tst-compathooks-off tst-compathooks-on \
+ tst-aligned-alloc-random-thread \
+ tst-aligned-alloc-random-thread-cross \
tests-mcheck = $(filter-out $(tests-exclude-mcheck) $(tests-static), $(tests))
endif
@@ -336,7 +340,11 @@ $(objpfx)tst-mallocstate: $(objpfx)libc_malloc_debug.so
$(objpfx)tst-mallocstate-malloc-check: $(objpfx)libc_malloc_debug.so
$(objpfx)tst-aligned-alloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
+$(objpfx)tst-aligned-alloc-random-thread.out: $(objpfx)tst-aligned_alloc-lib.so
+$(objpfx)tst-aligned-alloc-random-thread-cross.out: $(objpfx)tst-aligned_alloc-lib.so
$(objpfx)tst-malloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
tst-aligned-alloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+tst-aligned-alloc-random-thread-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+tst-aligned-alloc-random-thread-cross-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
tst-malloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
diff --git a/malloc/tst-aligned-alloc-random-thread-cross.c b/malloc/tst-aligned-alloc-random-thread-cross.c
new file mode 100644
index 0000000000000000..360ecc56ee7c8c06
--- /dev/null
+++ b/malloc/tst-aligned-alloc-random-thread-cross.c
@@ -0,0 +1,19 @@
+/* multi-threaded memory allocation and cross-thread deallocation test.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <https://www.gnu.org/licenses/>. */
+#define CROSS_THREAD_DEALLOC
+#include "tst-aligned-alloc-random-thread.c"
diff --git a/malloc/tst-aligned-alloc-random-thread.c b/malloc/tst-aligned-alloc-random-thread.c
new file mode 100644
index 0000000000000000..e95f79250abec85e
--- /dev/null
+++ b/malloc/tst-aligned-alloc-random-thread.c
@@ -0,0 +1,145 @@
+/* multi-threaded memory allocation/deallocation test.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xthread.h>
+#include <support/test-driver.h>
+#include <sys/sysinfo.h>
+#include <unistd.h>
+
+#ifndef ITERATIONS
+# define ITERATIONS 16
+#endif
+
+#ifndef NUM_THREADS
+# define NUM_THREADS 8
+#endif
+
+#ifndef NUM_ALLOCATIONS
+# define NUM_ALLOCATIONS 2048
+#endif
+
+static pthread_barrier_t barrier;
+
+__thread unsigned int seed;
+
+typedef struct
+{
+ int id;
+ pthread_t thread;
+} thread;
+
+thread threads[NUM_THREADS];
+
+void *allocations[NUM_THREADS][NUM_ALLOCATIONS];
+
+void
+run_thread_dealloc (int id)
+{
+ for (int i = 0; i < NUM_ALLOCATIONS; i++)
+ {
+ free (allocations[id][i]);
+ allocations[id][i] = NULL;
+ }
+}
+
+void
+run_thread_alloc (int id)
+{
+ size_t msb, size;
+ for (int i = 0; i < NUM_ALLOCATIONS; i++)
+ {
+ msb = 1 << rand_r (&seed) % 16;
+ size = msb + rand_r (&seed) % msb;
+ allocations[id][i] = malloc (size);
+ TEST_VERIFY_EXIT (allocations[id][i] != NULL);
+ }
+}
+
+void *
+run_allocations (void *arg)
+{
+ int id = *((int *) arg);
+ seed = time (NULL) + id;
+
+ /* Stage 1: First half o the threads allocating memory and the second
+ * half waiting for them to finish
+ */
+ if (id < NUM_THREADS / 2)
+ run_thread_alloc (id);
+
+ xpthread_barrier_wait (&barrier);
+
+ /* Stage 2: Half of the threads allocationg memory and the other
+ * half deallocating:
+ * - In the non cross-thread dealloc scenario the first half will be
+ * deallocating the memory allocated by themselves in stage 1 and the
+ * second half will be allocating memory.
+ * - In the cross-thread dealloc scenario the first half will continue
+ * to allocate memory and the second half will deallocate the memory
+ * allocated by the first half in stage 1.
+ */
+ if (id < NUM_THREADS / 2)
+#ifndef CROSS_THREAD_DEALLOC
+ run_thread_dealloc (id);
+#else
+ run_thread_alloc (id + NUM_THREADS / 2);
+#endif
+ else
+#ifndef CROSS_THREAD_DEALLOC
+ run_thread_alloc (id);
+#else
+ run_thread_dealloc (id - NUM_THREADS / 2);
+#endif
+
+ xpthread_barrier_wait (&barrier);
+
+ // Stage 3: Second half of the threads deallocating and the first half
+ // waiting for them to finish.
+ if (id >= NUM_THREADS / 2)
+ run_thread_dealloc (id);
+
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ xpthread_barrier_init (&barrier, NULL, NUM_THREADS);
+
+ for (int i = 0; i < ITERATIONS; i++)
+ {
+ for (int t = 0; t < NUM_THREADS; t++)
+ {
+ threads[t].id = t;
+ threads[t].thread
+ = xpthread_create (NULL, run_allocations, &threads[t].id);
+ }
+
+ for (int t = 0; t < NUM_THREADS; t++)
+ xpthread_join (threads[t].thread);
+ }
+
+ return 0;
+}
+
+#include <support/test-driver.c>

@ -1,121 +0,0 @@
commit a09183aed7bb8ace211e042b2e6e982bcc004957
Author: Andreas Schwab <schwab@suse.de>
Date: Mon Dec 19 12:40:45 2022 +0100
getdelim: ensure error indicator is set on error (bug 29917)
POSIX requires that getdelim and getline set the error indicator on the
stream when an error occured, in addition to setting errno.
Conflicts:
libio/Makefile - Manual merge for the newly added test
diff --git a/libio/Makefile b/libio/Makefile
index 64398ab1ee..9c69a85c87 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -66,7 +66,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \
tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \
tst-sprintf-ub tst-sprintf-chk-ub tst-bz24051 tst-bz24153 \
- tst-wfile-sync
+ tst-wfile-sync tst-getdelim
tests-internal = tst-vtables tst-vtables-interposed
diff --git a/libio/iogetdelim.c b/libio/iogetdelim.c
index b6c4c07b45..591526e9c1 100644
--- a/libio/iogetdelim.c
+++ b/libio/iogetdelim.c
@@ -43,11 +43,6 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
ssize_t cur_len = 0;
ssize_t len;
- if (lineptr == NULL || n == NULL)
- {
- __set_errno (EINVAL);
- return -1;
- }
CHECK_FILE (fp, -1);
_IO_acquire_lock (fp);
if (_IO_ferror_unlocked (fp))
@@ -56,12 +51,21 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
goto unlock_return;
}
+ if (lineptr == NULL || n == NULL)
+ {
+ __set_errno (EINVAL);
+ fseterr_unlocked (fp);
+ result = -1;
+ goto unlock_return;
+ }
+
if (*lineptr == NULL || *n == 0)
{
*n = 120;
*lineptr = (char *) malloc (*n);
if (*lineptr == NULL)
{
+ fseterr_unlocked (fp);
result = -1;
goto unlock_return;
}
@@ -88,6 +92,7 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
if (__glibc_unlikely (len >= SSIZE_MAX - cur_len))
{
__set_errno (EOVERFLOW);
+ fseterr_unlocked (fp);
result = -1;
goto unlock_return;
}
@@ -102,6 +107,7 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
new_lineptr = (char *) realloc (*lineptr, needed);
if (new_lineptr == NULL)
{
+ fseterr_unlocked (fp);
result = -1;
goto unlock_return;
}
diff --git a/libio/tst-getdelim.c b/libio/tst-getdelim.c
new file mode 100644
index 0000000000..4443732669
--- /dev/null
+++ b/libio/tst-getdelim.c
@@ -0,0 +1,36 @@
+/* Check that getdelim sets error indicator on error (BZ #29917)
+
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ clearerr (stdin);
+ TEST_VERIFY (getdelim (0, 0, '\n', stdin) == -1);
+ TEST_VERIFY (ferror (stdin) != 0);
+ TEST_VERIFY (errno == EINVAL);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

@ -1,331 +0,0 @@
commit 5456af201d4c0a2950200ba756e5f8314ddbbccd
Author: Carlos O'Donell <carlos@redhat.com>
Date: Thu May 11 14:00:41 2023 -0400
stdio-common: Reformat Makefile.
Reflow Makefile.
Sort using scripts/sort-makefile-lines.py.
Code generation is changed as routines are linked in sorted order
as expected.
No regressions on x86_64 and i686.
(cherry picked from commit c3004417afc98585089a9282d1d4d60cdef5317a)
(cherry picked from commit 5b4e90230b8147e273585bf296bf1a9fb6e2b4c2)
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 803f16dae030cb72..76d1d0a1193aa109 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -22,82 +22,241 @@ subdir := stdio-common
include ../Makeconfig
-headers := stdio_ext.h printf.h bits/printf-ldbl.h bits/stdio_lim.h
-
-routines := \
- ctermid cuserid \
- _itoa _itowa itoa-digits itoa-udigits itowa-digits \
- vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex \
- reg-modifier reg-type \
- printf_size fprintf printf snprintf sprintf asprintf dprintf \
- vfwprintf vfscanf vfwscanf \
- fscanf scanf sscanf \
- perror psignal \
- tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \
- getline getw putw \
- remove rename renameat renameat2 \
- flockfile ftrylockfile funlockfile \
- isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \
- isoc99_vsscanf \
- psiginfo gentempfd \
- vfscanf-internal vfwscanf-internal iovfscanf \
- vfprintf-internal vfwprintf-internal
-
-aux := errlist siglist printf-parsemb printf-parsewc fxprintf
-
-tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
- temptest tst-fileno test-fwrite tst-ungetc tst-ferror \
- xbug errnobug \
- bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 \
- tfformat tiformat tllformat tstdiomisc tst-printfsz tst-wc-printf \
- scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \
- scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \
- tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \
- tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 \
- tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \
- tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \
- bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \
- scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \
- bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \
- bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 tst-fmemopen3 \
- tst-printf-bz18872 tst-vfprintf-width-prec tst-fmemopen4 \
- tst-vfprintf-user-type \
- tst-vfprintf-mbs-prec \
- tst-scanf-round \
- tst-renameat2 tst-bz11319 tst-bz11319-fortify2 \
- scanf14a scanf16a \
- tst-printf-bz25691 \
- tst-vfprintf-width-prec-alloc \
- tst-printf-fp-free \
- tst-printf-fp-leak \
- test-strerr
-
-
-test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble
+headers := \
+ bits/printf-ldbl.h \
+ bits/stdio_lim.h \
+ printf.h \
+ stdio_ext.h \
+ # headers
+
+routines := \
+ _itoa \
+ _itowa \
+ asprintf \
+ ctermid \
+ cuserid \
+ dprintf \
+ flockfile \
+ fprintf \
+ fscanf \
+ ftrylockfile \
+ funlockfile \
+ gentempfd \
+ getline \
+ getw \
+ iovfscanf \
+ isoc99_fscanf \
+ isoc99_scanf \
+ isoc99_sscanf \
+ isoc99_vfscanf \
+ isoc99_vscanf \
+ isoc99_vsscanf \
+ itoa-digits \
+ itoa-udigits \
+ itowa-digits \
+ perror \
+ printf \
+ printf-prs \
+ printf_fp \
+ printf_fphex \
+ printf_size \
+ psiginfo \
+ psignal \
+ putw \
+ reg-modifier \
+ reg-printf \
+ reg-type \
+ remove \
+ rename \
+ renameat \
+ renameat2 \
+ scanf \
+ snprintf \
+ sprintf \
+ sscanf \
+ tempnam \
+ tempname \
+ tmpfile \
+ tmpfile64 tmpnam \
+ tmpnam_r \
+ vfprintf \
+ vfprintf-internal \
+ vfscanf \
+ vfscanf-internal \
+ vfwprintf \
+ vfwprintf-internal \
+ vfwscanf \
+ vfwscanf-internal \
+ vprintf \
+ # routines
+
+aux := \
+ errlist \
+ fxprintf \
+ printf-parsemb \
+ printf-parsewc \
+ siglist \
+ # aux
+
+tests := \
+ bug-vfprintf-nargs \
+ bug1 \
+ bug10 \
+ bug11 \
+ bug12 \
+ bug13 \
+ bug14 \
+ bug16 \
+ bug17 \
+ bug18 \
+ bug18a \
+ bug19 \
+ bug19a \
+ bug2 \
+ bug20 \
+ bug21 \
+ bug22 \
+ bug23 \
+ bug23-2 \
+ bug23-3 \
+ bug23-4 \
+ bug24 \
+ bug25 \
+ bug26 \
+ bug3 \
+ bug4 \
+ bug5 \
+ bug6 \
+ bug7 \
+ bug8 \
+ bug9 \
+ errnobug \
+ scanf1 \
+ scanf10 \
+ scanf11 \
+ scanf12 \
+ scanf13 \
+ scanf14 \
+ scanf14a \
+ scanf15 \
+ scanf16 \
+ scanf16a \
+ scanf17 \
+ scanf2 \
+ scanf3 \
+ scanf4 \
+ scanf5 \
+ scanf7 \
+ scanf8 \
+ scanf9 \
+ temptest \
+ test-fseek \
+ test-fwrite \
+ test-popen \
+ test-strerr \
+ test-vfprintf \
+ test_rdwr \
+ tfformat \
+ tiformat \
+ tllformat \
+ tst-bz11319 \
+ tst-bz11319-fortify2 \
+ tst-cookie \
+ tst-fdopen \
+ tst-ferror \
+ tst-fgets \
+ tst-fileno \
+ tst-fmemopen \
+ tst-fmemopen2 \
+ tst-fmemopen3 \
+ tst-fmemopen4 \
+ tst-fphex \
+ tst-fphex-wide \
+ tst-fseek \
+ tst-fwrite \
+ tst-gets \
+ tst-grouping \
+ tst-long-dbl-fphex \
+ tst-obprintf \
+ tst-perror \
+ tst-popen \
+ tst-popen2 \
+ tst-printf-bz18872 \
+ tst-printf-bz25691 \
+ tst-printf-fp-free \
+ tst-printf-fp-leak \
+ tst-printf-round \
+ tst-printfsz \
+ tst-put-error \
+ tst-renameat2 \
+ tst-rndseek \
+ tst-scanf-round \
+ tst-setvbuf1 \
+ tst-sprintf \
+ tst-sprintf2 \
+ tst-sprintf3 \
+ tst-sscanf \
+ tst-swprintf \
+ tst-swscanf \
+ tst-tmpnam \
+ tst-ungetc \
+ tst-unlockedio \
+ tst-vfprintf-mbs-prec \
+ tst-vfprintf-user-type \
+ tst-vfprintf-width-prec \
+ tst-vfprintf-width-prec-alloc \
+ tst-wc-printf \
+ tstdiomisc \
+ tstgetln \
+ tstscanf \
+ xbug \
+ # tests
+
+test-srcs = \
+ tst-printf \
+ tst-printfsz-islongdouble \
+ tst-unbputc \
+ # test-srcs
ifeq ($(run-built-tests),yes)
-tests-special += $(objpfx)tst-unbputc.out $(objpfx)tst-printf.out \
- $(objpfx)tst-printf-bz18872-mem.out \
- $(objpfx)tst-setvbuf1-cmp.out \
- $(objpfx)tst-vfprintf-width-prec-mem.out \
- $(objpfx)tst-printfsz-islongdouble.out \
- $(objpfx)tst-printf-bz25691-mem.out \
- $(objpfx)tst-printf-fp-free-mem.out \
- $(objpfx)tst-printf-fp-leak-mem.out
-generated += tst-printf-bz18872.c tst-printf-bz18872.mtrace \
- tst-printf-bz18872-mem.out \
- tst-vfprintf-width-prec.mtrace tst-vfprintf-width-prec-mem.out \
- tst-printf-bz25691.mtrace tst-printf-bz25691-mem.out \
- tst-printf-fp-free.mtrace tst-printf-fp-free-mem.out \
- tst-printf-fp-leak.mtrace tst-printf-fp-leak-mem.out
-endif
+tests-special += \
+ $(objpfx)tst-printf-bz18872-mem.out \
+ $(objpfx)tst-printf-bz25691-mem.out \
+ $(objpfx)tst-printf-fp-free-mem.out \
+ $(objpfx)tst-printf-fp-leak-mem.out \
+ $(objpfx)tst-printf.out \
+ $(objpfx)tst-printfsz-islongdouble.out \
+ $(objpfx)tst-setvbuf1-cmp.out \
+ $(objpfx)tst-unbputc.out \
+ $(objpfx)tst-vfprintf-width-prec-mem.out \
+ # tests-special
+
+generated += \
+ tst-printf-bz18872-mem.out \
+ tst-printf-bz18872.c \
+ tst-printf-bz18872.mtrace \
+ tst-printf-bz25691-mem.out \
+ tst-printf-bz25691.mtrace \
+ tst-printf-fp-free-mem.out \
+ tst-printf-fp-free.mtrace \
+ tst-printf-fp-leak-mem.out \
+ tst-printf-fp-leak.mtrace \
+ tst-vfprintf-width-prec-mem.out \
+ tst-vfprintf-width-prec.mtrace \
+ # generated
+endif # $(run-built-tests)
tests-special += $(objpfx)tst-errno-manual.out
include ../Rules
ifeq ($(run-built-tests),yes)
-LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ISO-8859-1 ja_JP.EUC-JP
+LOCALES := \
+ de_DE.ISO-8859-1 \
+ de_DE.UTF-8 \
+ en_US.ISO-8859-1 \
+ ja_JP.EUC-JP \
+ # LOCALES
include ../gen-locales.mk
$(objpfx)bug14.out: $(gen-locales)

@ -1,201 +0,0 @@
commit 9556acd249687ac562deb6309503165d66eb06fa
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Thu Dec 21 15:59:15 2023 -0300
debug: Adapt fortify tests to libsupport
Checked on aarch64, armhf, x86_64, and i686.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
diff --git a/debug/test-stpcpy_chk.c b/debug/test-stpcpy_chk.c
index 96ad600bc2760cbd..c3cb52d987f9db4f 100644
--- a/debug/test-stpcpy_chk.c
+++ b/debug/test-stpcpy_chk.c
@@ -20,7 +20,7 @@
#define STRCPY_RESULT(dst, len) ((dst) + (len))
#define TEST_MAIN
#define TEST_NAME "stpcpy_chk"
-#include "../string/test-string.h"
+#include <string/test-string.h>
extern void __attribute__ ((noreturn)) __chk_fail (void);
char *simple_stpcpy_chk (char *, const char *, size_t);
diff --git a/debug/test-strcpy_chk.c b/debug/test-strcpy_chk.c
index 80c07482aaa54e3b..bb89e342caef470b 100644
--- a/debug/test-strcpy_chk.c
+++ b/debug/test-strcpy_chk.c
@@ -21,7 +21,7 @@
# define STRCPY_RESULT(dst, len) dst
# define TEST_MAIN
# define TEST_NAME "strcpy_chk"
-# include "../string/test-string.h"
+# include <string/test-string.h>
/* This test case implicitly tests the availability of the __chk_fail
symbol, which is part of the public ABI and may be used
diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c
index fb02452f5993c594..01a8703de1e6e09a 100644
--- a/debug/tst-fortify.c
+++ b/debug/tst-fortify.c
@@ -24,6 +24,7 @@
#include <assert.h>
#include <fcntl.h>
+#include <limits.h>
#include <locale.h>
#include <obstack.h>
#include <setjmp.h>
@@ -37,6 +38,10 @@
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <paths.h>
+
+#include <support/temp_file.h>
+#include <support/support.h>
#ifndef _GNU_SOURCE
# define MEMPCPY memcpy
@@ -53,15 +58,10 @@
#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
-char *temp_filename;
-static void do_prepare (void);
-static int do_test (void);
-#define PREPARE(argc, argv) do_prepare ()
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
+static char *temp_filename;
static void
-do_prepare (void)
+do_prepare (int argc, char *argv[])
{
int temp_fd = create_temp_file ("tst-chk1.", &temp_filename);
if (temp_fd == -1)
@@ -78,10 +78,11 @@ do_prepare (void)
exit (1);
}
}
+#define PREPARE do_prepare
-volatile int chk_fail_ok;
-volatile int ret;
-jmp_buf chk_fail_buf;
+static volatile int chk_fail_ok;
+static volatile int ret;
+static jmp_buf chk_fail_buf;
static void
handler (int sig)
@@ -103,22 +104,22 @@ wchar_t wbuf[10];
#define buf_size sizeof (buf)
#endif
-volatile size_t l0;
-volatile char *p;
-volatile wchar_t *wp;
-const char *str1 = "JIHGFEDCBA";
-const char *str2 = "F";
-const char *str3 = "%s%n%s%n";
-const char *str4 = "Hello, ";
-const char *str5 = "World!\n";
-const wchar_t *wstr1 = L"JIHGFEDCBA";
-const wchar_t *wstr2 = L"F";
-const wchar_t *wstr3 = L"%s%n%s%n";
-const wchar_t *wstr4 = L"Hello, ";
-const wchar_t *wstr5 = L"World!\n";
-char buf2[10] = "%s";
-int num1 = 67;
-int num2 = 987654;
+static volatile size_t l0;
+static volatile char *p;
+static volatile wchar_t *wp;
+static const char *str1 = "JIHGFEDCBA";
+static const char *str2 = "F";
+static const char *str3 = "%s%n%s%n";
+static const char *str4 = "Hello, ";
+static const char *str5 = "World!\n";
+static const wchar_t *wstr1 = L"JIHGFEDCBA";
+static const wchar_t *wstr2 = L"F";
+static const wchar_t *wstr3 = L"%s%n%s%n";
+static const wchar_t *wstr4 = L"Hello, ";
+static const wchar_t *wstr5 = L"World!\n";
+static char buf2[10] = "%s";
+static int num1 = 67;
+static int num2 = 987654;
#define FAIL() \
do { printf ("Failure on line %d\n", __LINE__); ret = 1; } while (0)
@@ -1763,3 +1764,5 @@ do_test (void)
return ret;
}
+
+#include <support/test-driver.c>
diff --git a/debug/tst-longjmp_chk.c b/debug/tst-longjmp_chk.c
index e4e93d2a36b537d9..37f858606be4c4a2 100644
--- a/debug/tst-longjmp_chk.c
+++ b/debug/tst-longjmp_chk.c
@@ -10,11 +10,7 @@
#include <stdlib.h>
#include <unistd.h>
-
-static int do_test(void);
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
-
+#include <support/support.h>
static jmp_buf b;
@@ -76,3 +72,5 @@ do_test (void)
puts ("second longjmp returned");
return 1;
}
+
+#include <support/test-driver.c>
diff --git a/debug/tst-longjmp_chk2.c b/debug/tst-longjmp_chk2.c
index 23d3436d1d26d2d1..69c1ab9db73f14ae 100644
--- a/debug/tst-longjmp_chk2.c
+++ b/debug/tst-longjmp_chk2.c
@@ -12,9 +12,7 @@
#include <sys/resource.h>
#include <unistd.h>
-static int do_test (void);
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
+#include <support/support.h>
static jmp_buf mainloop;
static sigset_t mainsigset;
@@ -128,3 +126,5 @@ do_test (void)
return 0;
}
+
+#include <support/test-driver.c>
diff --git a/debug/tst-longjmp_chk3.c b/debug/tst-longjmp_chk3.c
index 3155c7769fcbd83f..4434937c597dbe10 100644
--- a/debug/tst-longjmp_chk3.c
+++ b/debug/tst-longjmp_chk3.c
@@ -20,10 +20,6 @@
#include <signal.h>
#include <string.h>
-static int do_test (void);
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
-
static char buf[SIGSTKSZ * 4];
static jmp_buf jb;
@@ -83,3 +79,5 @@ do_test (void)
puts ("longjmp returned and shouldn't");
return 1;
}
+
+#include <support/test-driver.c>

@ -1,195 +0,0 @@
commit 388c9d7294e5ee3b741aef2e8af63eb1f76ace86
Author: Maciej W. Rozycki <macro@redhat.com>
Date: Fri Jul 26 13:21:34 2024 +0100
support: Add FAIL test failure helper
Add a FAIL test failure helper analogous to FAIL_RET, that does not
cause the current function to return, providing a standardized way to
report a test failure with a message supplied while permitting the
caller to continue executing, for further reporting, cleaning up, etc.
Update existing test cases that provide a conflicting definition of FAIL
by removing the local FAIL definition and then as follows:
- tst-fortify-syslog: provide a meaningful message in addition to the
file name already added by <support/check.h>; 'support_record_failure'
is already called by 'support_print_failure_impl' invoked by the new
FAIL test failure helper.
- tst-ctype: no update to FAIL calls required, with the name of the file
and the line number within of the failure site additionally included
by the new FAIL test failure helper, and error counting plus count
reporting upon test program termination also already provided by
'support_record_failure' and 'support_report_failure' respectively,
called by 'support_print_failure_impl' and 'adjust_exit_status' also
respectively. However in a number of places 'printf' is called and
the error count adjusted by hand, so update these places to make use
of FAIL instead. And last but not least adjust the final summary just
to report completion, with any error count following as reported by
the test driver.
- test-tgmath2: no update to FAIL calls required, with the name of the
file of the failure site additionally included by the new FAIL test
failure helper. Also there is no need to track the return status by
hand as any call to FAIL will eventually cause the test case to return
an unsuccesful exit status regardless of the return status from the
test function, via a call to 'adjust_exit_status' made by the test
driver.
Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 1b97a9f23bf605ca608162089c94187573fb2a9e)
(cherry picked from commit 28f358bc4209ab0425170cdccf65bb1fe861148f)
diff --git a/localedata/tst-ctype.c b/localedata/tst-ctype.c
index 1e4fa132bb4e17c6..f8645e31db8a1691 100644
--- a/localedata/tst-ctype.c
+++ b/localedata/tst-ctype.c
@@ -22,6 +22,8 @@
#include <stdio.h>
#include <string.h>
+#include <support/check.h>
+
static const char lower[] = "abcdefghijklmnopqrstuvwxyz";
static const char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -54,19 +56,11 @@ static struct classes
#define nclasses (sizeof (classes) / sizeof (classes[0]))
-#define FAIL(str, args...) \
- { \
- printf (" " str "\n", ##args); \
- ++errors; \
- }
-
-
static int
do_test (void)
{
const char *cp;
const char *cp2;
- int errors = 0;
char *inpline = NULL;
size_t inplinelen = 0;
char *resline = NULL;
@@ -395,11 +389,8 @@ punct = %04x alnum = %04x\n",
{
if (((__ctype_b[(unsigned int) *inp] & classes[n].mask) != 0)
!= (*resp != '0'))
- {
- printf (" is%s('%c' = '\\x%02x') %s true\n", inpline,
- *inp, *inp, *resp == '1' ? "not" : "is");
- ++errors;
- }
+ FAIL (" is%s('%c' = '\\x%02x') %s true\n", inpline,
+ *inp, *inp, *resp == '1' ? "not" : "is");
++inp;
++resp;
}
@@ -409,11 +400,8 @@ punct = %04x alnum = %04x\n",
while (*inp != '\0')
{
if (tolower (*inp) != *resp)
- {
- printf (" tolower('%c' = '\\x%02x') != '%c'\n",
- *inp, *inp, *resp);
- ++errors;
- }
+ FAIL (" tolower('%c' = '\\x%02x') != '%c'\n",
+ *inp, *inp, *resp);
++inp;
++resp;
}
@@ -423,11 +411,8 @@ punct = %04x alnum = %04x\n",
while (*inp != '\0')
{
if (toupper (*inp) != *resp)
- {
- printf (" toupper('%c' = '\\x%02x') != '%c'\n",
- *inp, *inp, *resp);
- ++errors;
- }
+ FAIL (" toupper('%c' = '\\x%02x') != '%c'\n",
+ *inp, *inp, *resp);
++inp;
++resp;
}
@@ -437,14 +422,7 @@ punct = %04x alnum = %04x\n",
}
- if (errors != 0)
- {
- printf (" %d error%s for `%s' locale\n\n\n", errors,
- errors == 1 ? "" : "s", setlocale (LC_ALL, NULL));
- return 1;
- }
-
- printf (" No errors for `%s' locale\n\n\n", setlocale (LC_ALL, NULL));
+ printf ("Completed testing for `%s' locale\n\n\n", setlocale (LC_ALL, NULL));
return 0;
}
diff --git a/math/test-tgmath2.c b/math/test-tgmath2.c
index b8fb00c566439ab0..e3b7a3a3615e083a 100644
--- a/math/test-tgmath2.c
+++ b/math/test-tgmath2.c
@@ -25,6 +25,8 @@
#include <string.h>
#include <tgmath.h>
+#include <support/check.h>
+
//#define DEBUG
typedef complex float cfloat;
@@ -88,13 +90,6 @@ enum
int count;
int counts[Tlast][C_last];
-#define FAIL(str) \
- do \
- { \
- printf ("%s failure on line %d\n", (str), __LINE__); \
- result = 1; \
- } \
- while (0)
#define TEST_TYPE_ONLY(expr, rettype) \
do \
{ \
@@ -134,8 +129,6 @@ int counts[Tlast][C_last];
int
test_cos (const int Vint4, const long long int Vllong4)
{
- int result = 0;
-
TEST (cos (vfloat1), float, cos);
TEST (cos (vdouble1), double, cos);
TEST (cos (vldouble1), ldouble, cos);
@@ -153,7 +146,7 @@ test_cos (const int Vint4, const long long int Vllong4)
TEST (cos (Vcdouble1), cdouble, cos);
TEST (cos (Vcldouble1), cldouble, cos);
- return result;
+ return 0;
}
int
diff --git a/support/check.h b/support/check.h
index 9b1844352f32513a..8e045dd9c0c36b4c 100644
--- a/support/check.h
+++ b/support/check.h
@@ -24,6 +24,11 @@
__BEGIN_DECLS
+/* Record a test failure, print the failure message to standard output
+ and pass the result of 1 through. */
+#define FAIL(...) \
+ support_print_failure_impl (__FILE__, __LINE__, __VA_ARGS__)
+
/* Record a test failure, print the failure message to standard output
and return 1. */
#define FAIL_RET(...) \

@ -1,169 +0,0 @@
commit 86f5cfe77d60ca4f78f270adc7ae2c15a1d8d4bc
Author: Maciej W. Rozycki <macro@redhat.com>
Date: Fri Jul 26 13:21:34 2024 +0100
stdio-common: Add test for vfscanf with matches longer than INT_MAX [BZ #27650]
Complement commit b03e4d7bd25b ("stdio: fix vfscanf with matches longer
than INT_MAX (bug 27650)") and add a test case for the issue, inspired
by the reproducer provided with the bug report.
This has been verified to succeed as from the commit referred and fail
beforehand.
As the test requires 2GiB of data to be passed around its performance
has been evaluated using a choice of systems and the execution time
determined to be respectively in the range of 9s for POWER9@2.166GHz,
24s for FU740@1.2GHz, and 40s for 74Kf@950MHz. As this is on the verge
of and beyond the default timeout it has been increased by the factor of
8. Regardless, following recent practice the test has been added to the
standard rather than extended set.
Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 89cddc8a7096f3d9225868304d2bc0a1aaf07d63)
(cherry picked from commit 99ffa84bdcdc3d81e82f448279f0c8278dd30964)
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 76d1d0a1193aa109..08bedd01be61a55d 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -190,6 +190,7 @@ tests := \
tst-put-error \
tst-renameat2 \
tst-rndseek \
+ tst-scanf-bz27650 \
tst-scanf-round \
tst-setvbuf1 \
tst-sprintf \
@@ -241,6 +242,7 @@ generated += \
tst-printf-fp-free.mtrace \
tst-printf-fp-leak-mem.out \
tst-printf-fp-leak.mtrace \
+ tst-scanf-bz27650.mtrace \
tst-vfprintf-width-prec-mem.out \
tst-vfprintf-width-prec.mtrace \
# generated
@@ -283,6 +285,9 @@ tst-printf-fp-free-ENV = \
tst-printf-fp-leak-ENV = \
MALLOC_TRACE=$(objpfx)tst-printf-fp-leak.mtrace \
LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+tst-scanf-bz27650-ENV = \
+ MALLOC_TRACE=$(objpfx)tst-scanf-bz27650.mtrace \
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
diff --git a/stdio-common/tst-scanf-bz27650.c b/stdio-common/tst-scanf-bz27650.c
new file mode 100644
index 0000000000000000..3a742bc86556908c
--- /dev/null
+++ b/stdio-common/tst-scanf-bz27650.c
@@ -0,0 +1,108 @@
+/* Test for BZ #27650, formatted input matching beyond INT_MAX.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <error.h>
+#include <errno.h>
+#include <limits.h>
+#include <mcheck.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+#include <support/check.h>
+#include <support/test-driver.h>
+
+/* Produce a stream of more than INT_MAX characters via buffer BUF of
+ size SIZE according to bookkeeping in COOKIE and then return EOF. */
+
+static ssize_t
+io_read (void *cookie, char *buf, size_t size)
+{
+ unsigned int *written = cookie;
+ unsigned int w = *written;
+
+ if (w > INT_MAX)
+ return 0;
+
+ memset (buf, 'a', size);
+ *written = w + size;
+ return size;
+}
+
+/* Consume a stream of more than INT_MAX characters from an artificial
+ input stream of which none is the new line character. The call to
+ fscanf is supposed to complete upon the EOF condition of input,
+ however in the presence of BZ #27650 it will terminate prematurely
+ with characters still outstanding in input. Diagnose the condition
+ and return status accordingly. */
+
+int
+do_test (void)
+{
+ static cookie_io_functions_t io_funcs = { .read = io_read };
+ unsigned int written = 0;
+ FILE *in;
+ int v;
+
+ mtrace ();
+
+ in = fopencookie (&written, "r", io_funcs);
+ if (in == NULL)
+ {
+ FAIL ("fopencookie: %m");
+ goto out;
+ }
+
+ v = fscanf (in, "%*[^\n]");
+ if (ferror (in))
+ {
+ FAIL ("fscanf: input failure, at %u: %m", written);
+ goto out_close;
+ }
+ else if (v == EOF)
+ {
+ FAIL ("fscanf: unexpected end of file, at %u", written);
+ goto out_close;
+ }
+
+ if (!feof (in))
+ {
+ v = fgetc (in);
+ if (ferror (in))
+ FAIL ("fgetc: input failure: %m");
+ else if (v == EOF)
+ FAIL ("fgetc: unexpected end of file after missing end of file");
+ else if (v == '\n')
+ FAIL ("unexpected new line character received");
+ else
+ FAIL ("character received after end of file expected: \\x%02x", v);
+ }
+
+out_close:
+ if (fclose (in) != 0)
+ FAIL ("fclose: %m");
+
+out:
+ return EXIT_SUCCESS;
+}
+
+#define TIMEOUT (DEFAULT_TIMEOUT * 8)
+#include <support/test-driver.c>

@ -1,143 +0,0 @@
commit af68f0f6755c3b82ecef6dd67079df64eee8d946
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Wed Aug 14 19:20:04 2024 -0400
Make tst-ungetc use libsupport
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 3f7df7e757f4efec38e45d4068e5492efcac4856)
(cherry picked from commit 87a1968a72e4b4e5436f3e2be1ed8a8d5a5862c7)
diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c
index 1344b2b591e3d6b1..5c808f073419f00b 100644
--- a/stdio-common/tst-ungetc.c
+++ b/stdio-common/tst-ungetc.c
@@ -1,70 +1,72 @@
-/* Test for ungetc bugs. */
+/* Test for ungetc bugs.
+ Copyright (C) 1996-2024 Free Software Foundation, Inc.
+ Copyright The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-
-#undef assert
-#define assert(x) \
- if (!(x)) \
- { \
- fputs ("test failed: " #x "\n", stderr); \
- retval = 1; \
- goto the_end; \
- }
+#include <support/check.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/xstdio.h>
+#include <support/xunistd.h>
-int
-main (int argc, char *argv[])
+static int
+do_test (void)
{
- char name[] = "/tmp/tst-ungetc.XXXXXX";
+ char *name = NULL;
FILE *fp = NULL;
- int retval = 0;
int c;
char buffer[64];
- int fd = mkstemp (name);
+ int fd = create_temp_file ("tst-ungetc.", &name);
if (fd == -1)
- {
- printf ("mkstemp failed: %m\n");
- return 1;
- }
- close (fd);
- fp = fopen (name, "w");
- assert (fp != NULL)
- fputs ("bla", fp);
- fclose (fp);
- fp = NULL;
+ FAIL_EXIT1 ("cannot create temporary file: %m");
+ xclose (fd);
- fp = fopen (name, "r");
- assert (fp != NULL);
- assert (ungetc ('z', fp) == 'z');
- assert (getc (fp) == 'z');
- assert (getc (fp) == 'b');
- assert (getc (fp) == 'l');
- assert (ungetc ('m', fp) == 'm');
- assert (getc (fp) == 'm');
- assert ((c = getc (fp)) == 'a');
- assert (getc (fp) == EOF);
- assert (ungetc (c, fp) == c);
- assert (feof (fp) == 0);
- assert (getc (fp) == c);
- assert (getc (fp) == EOF);
- fclose (fp);
- fp = NULL;
+ fp = xfopen (name, "w");
+ fputs ("bla", fp);
+ xfclose (fp);
- fp = fopen (name, "r");
- assert (fp != NULL);
- assert (getc (fp) == 'b');
- assert (getc (fp) == 'l');
- assert (ungetc ('b', fp) == 'b');
- assert (fread (buffer, 1, 64, fp) == 2);
- assert (buffer[0] == 'b');
- assert (buffer[1] == 'a');
+ fp = xfopen (name, "r");
+ TEST_VERIFY_EXIT (ungetc ('z', fp) == 'z');
+ TEST_VERIFY_EXIT (getc (fp) == 'z');
+ TEST_VERIFY_EXIT (getc (fp) == 'b');
+ TEST_VERIFY_EXIT (getc (fp) == 'l');
+ TEST_VERIFY_EXIT (ungetc ('m', fp) == 'm');
+ TEST_VERIFY_EXIT (getc (fp) == 'm');
+ TEST_VERIFY_EXIT ((c = getc (fp)) == 'a');
+ TEST_VERIFY_EXIT (getc (fp) == EOF);
+ TEST_VERIFY_EXIT (ungetc (c, fp) == c);
+ TEST_VERIFY_EXIT (feof (fp) == 0);
+ TEST_VERIFY_EXIT (getc (fp) == c);
+ TEST_VERIFY_EXIT (getc (fp) == EOF);
+ xfclose (fp);
-the_end:
- if (fp != NULL)
- fclose (fp);
- unlink (name);
+ fp = xfopen (name, "r");
+ TEST_VERIFY_EXIT (getc (fp) == 'b');
+ TEST_VERIFY_EXIT (getc (fp) == 'l');
+ TEST_VERIFY_EXIT (ungetc ('b', fp) == 'b');
+ TEST_VERIFY_EXIT (fread (buffer, 1, 64, fp) == 2);
+ TEST_VERIFY_EXIT (buffer[0] == 'b');
+ TEST_VERIFY_EXIT (buffer[1] == 'a');
+ xfclose (fp);
- return retval;
+ return 0;
}
+
+#include <support/test-driver.c>

@ -1,71 +0,0 @@
commit 01a731da41a6d47cdd6b90f0da1d89dd8cf2b9cd
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Tue Aug 13 21:00:06 2024 -0400
ungetc: Fix uninitialized read when putting into unused streams [BZ #27821]
When ungetc is called on an unused stream, the backup buffer is
allocated without the main get area being present. This results in
every subsequent ungetc (as the stream remains in the backup area)
checking uninitialized memory in the backup buffer when trying to put a
character back into the stream.
Avoid comparing the input character with buffer contents when in backup
to avoid this uninitialized read. The uninitialized read is harmless in
this context since the location is promptly overwritten with the input
character, thus fulfilling ungetc functionality.
Also adjust wording in the manual to drop the paragraph that says glibc
cannot do multiple ungetc back to back since with this change, ungetc
can actually do this.
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit cdf0f88f97b0aaceb894cc02b21159d148d7065c)
(cherry picked from commit 804d3c8db79db204154dcf5e11a76f14fdddc570)
diff --git a/libio/genops.c b/libio/genops.c
index fa509f6219abaf23..a5dd6a06d9e259d8 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -635,7 +635,7 @@ _IO_sputbackc (FILE *fp, int c)
{
int result;
- if (fp->_IO_read_ptr > fp->_IO_read_base
+ if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp)
&& (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
{
fp->_IO_read_ptr--;
diff --git a/manual/stdio.texi b/manual/stdio.texi
index d3d855fc62b8768b..60ab7e7a5d505bb6 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -1467,11 +1467,9 @@ program; usually @code{ungetc} is used only to unread a character that
was just read from the same stream. @Theglibc{} supports this
even on files opened in binary mode, but other systems might not.
-@Theglibc{} only supports one character of pushback---in other
-words, it does not work to call @code{ungetc} twice without doing input
-in between. Other systems might let you push back multiple characters;
-then reading from the stream retrieves the characters in the reverse
-order that they were pushed.
+@Theglibc{} supports pushing back multiple characters; subsequently
+reading from the stream retrieves the characters in the reverse order
+that they were pushed.
Pushing back characters doesn't alter the file; only the internal
buffering for the stream is affected. If a file positioning function
diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c
index 5c808f073419f00b..388b202493ddd586 100644
--- a/stdio-common/tst-ungetc.c
+++ b/stdio-common/tst-ungetc.c
@@ -48,6 +48,8 @@ do_test (void)
TEST_VERIFY_EXIT (getc (fp) == 'b');
TEST_VERIFY_EXIT (getc (fp) == 'l');
TEST_VERIFY_EXIT (ungetc ('m', fp) == 'm');
+ TEST_VERIFY_EXIT (ungetc ('n', fp) == 'n');
+ TEST_VERIFY_EXIT (getc (fp) == 'n');
TEST_VERIFY_EXIT (getc (fp) == 'm');
TEST_VERIFY_EXIT ((c = getc (fp)) == 'a');
TEST_VERIFY_EXIT (getc (fp) == EOF);

@ -1,136 +0,0 @@
commit a5cd39541396b91d90cc611858ee7b3355fcfe47
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Tue Aug 13 21:08:49 2024 -0400
ungetc: Fix backup buffer leak on program exit [BZ #27821]
If a file descriptor is left unclosed and is cleaned up by _IO_cleanup
on exit, its backup buffer remains unfreed, registering as a leak in
valgrind. This is not strictly an issue since (1) the program should
ideally be closing the stream once it's not in use and (2) the program
is about to exit anyway, so keeping the backup buffer around a wee bit
longer isn't a real problem. Free it anyway to keep valgrind happy
when the streams in question are the standard ones, i.e. stdout, stdin
or stderr.
Also, the _IO_have_backup macro checks for _IO_save_base,
which is a roundabout way to check for a backup buffer instead of
directly looking for _IO_backup_base. The roundabout check breaks when
the main get area has not been used and user pushes a char into the
backup buffer with ungetc. Fix this to use the _IO_backup_base
directly.
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 3e1d8d1d1dca24ae90df2ea826a8916896fc7e77)
(cherry picked from commit b9f72bd5de931eac39219018c2fa319a449bb2cf)
diff --git a/libio/genops.c b/libio/genops.c
index a5dd6a06d9e259d8..b5fc53fd1ef6e911 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -796,6 +796,12 @@ _IO_unbuffer_all (void)
legacy = 1;
#endif
+ /* Free up the backup area if it was ever allocated. */
+ if (_IO_have_backup (fp))
+ _IO_free_backup_area (fp);
+ if (fp->_mode > 0 && _IO_have_wbackup (fp))
+ _IO_free_wbackup_area (fp);
+
if (! (fp->_flags & _IO_UNBUFFERED)
/* Iff stream is un-orientated, it wasn't used. */
&& (legacy || fp->_mode != 0))
diff --git a/libio/libioP.h b/libio/libioP.h
index dc9a2ce9c8d7744c..bab5f3770f0760c4 100644
--- a/libio/libioP.h
+++ b/libio/libioP.h
@@ -529,8 +529,8 @@ extern void _IO_old_init (FILE *fp, int flags) __THROW;
((__fp)->_wide_data->_IO_write_base \
= (__fp)->_wide_data->_IO_write_ptr = __p, \
(__fp)->_wide_data->_IO_write_end = (__ep))
-#define _IO_have_backup(fp) ((fp)->_IO_save_base != NULL)
-#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_save_base != NULL)
+#define _IO_have_backup(fp) ((fp)->_IO_backup_base != NULL)
+#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_backup_base != NULL)
#define _IO_in_backup(fp) ((fp)->_flags & _IO_IN_BACKUP)
#define _IO_have_markers(fp) ((fp)->_markers != NULL)
#define _IO_blen(fp) ((fp)->_IO_buf_end - (fp)->_IO_buf_base)
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 08bedd01be61a55d..f10bf28878e0aebc 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -201,6 +201,7 @@ tests := \
tst-swscanf \
tst-tmpnam \
tst-ungetc \
+ tst-ungetc-leak \
tst-unlockedio \
tst-vfprintf-mbs-prec \
tst-vfprintf-user-type \
@@ -229,6 +230,7 @@ tests-special += \
$(objpfx)tst-printfsz-islongdouble.out \
$(objpfx)tst-setvbuf1-cmp.out \
$(objpfx)tst-unbputc.out \
+ $(objpfx)tst-ungetc-leak-mem.out \
$(objpfx)tst-vfprintf-width-prec-mem.out \
# tests-special
@@ -243,6 +245,8 @@ generated += \
tst-printf-fp-leak-mem.out \
tst-printf-fp-leak.mtrace \
tst-scanf-bz27650.mtrace \
+ tst-ungetc-leak-mem.out \
+ tst-ungetc-leak.mtrace \
tst-vfprintf-width-prec-mem.out \
tst-vfprintf-width-prec.mtrace \
# generated
@@ -288,6 +292,9 @@ tst-printf-fp-leak-ENV = \
tst-scanf-bz27650-ENV = \
MALLOC_TRACE=$(objpfx)tst-scanf-bz27650.mtrace \
LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
+tst-ungetc-leak-ENV = \
+ MALLOC_TRACE=$(objpfx)tst-ungetc-leak.mtrace \
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
diff --git a/stdio-common/tst-ungetc-leak.c b/stdio-common/tst-ungetc-leak.c
new file mode 100644
index 0000000000000000..6c5152b43f80b217
--- /dev/null
+++ b/stdio-common/tst-ungetc-leak.c
@@ -0,0 +1,32 @@
+/* Test for memory leak with ungetc when stream is unused.
+ Copyright The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <mcheck.h>
+#include <support/check.h>
+#include <support/support.h>
+
+static int
+do_test (void)
+{
+ mtrace ();
+ TEST_COMPARE (ungetc('y', stdin), 'y');
+ return 0;
+}
+
+#include <support/test-driver.c>

@ -1,83 +0,0 @@
commit 9d26e50364def249e483b1601beb6ecf9141ecc7
Author: Maciej W. Rozycki <macro@redhat.com>
Date: Fri Jul 26 13:21:34 2024 +0100
posix: Use <support/check.h> facilities in tst-truncate and tst-truncate64
Remove local FAIL macro in favor to FAIL_RET from <support/check.h>,
which provides equivalent reporting, with the name of the file of the
failure site additionally included, for the tst-truncate-common core
shared between the tst-truncate and tst-truncate64 tests.
Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit fe47595504a55e7bb992f8928533df154b510383)
diff --git a/posix/tst-truncate-common.c b/posix/tst-truncate-common.c
index 00c999d372693bfa..1f6c4bd256a638f9 100644
--- a/posix/tst-truncate-common.c
+++ b/posix/tst-truncate-common.c
@@ -21,6 +21,8 @@
#include <sys/stat.h>
#include <unistd.h>
+#include <support/check.h>
+
static void do_prepare (void);
#define PREPARE(argc, argv) do_prepare ()
static int do_test (void);
@@ -42,9 +44,6 @@ do_prepare (void)
}
}
-#define FAIL(str) \
- do { printf ("error: %s (line %d)\n", str, __LINE__); return 1; } while (0)
-
static int
do_test_with_offset (off_t offset)
{
@@ -54,35 +53,35 @@ do_test_with_offset (off_t offset)
memset (buf, 0xcf, sizeof (buf));
if (pwrite (temp_fd, buf, sizeof (buf), offset) != sizeof (buf))
- FAIL ("write failed");
+ FAIL_RET ("write failed");
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + sizeof (buf)))
- FAIL ("initial size wrong");
+ FAIL_RET ("initial size wrong");
if (ftruncate (temp_fd, offset + 800) < 0)
- FAIL ("size reduction with ftruncate failed");
+ FAIL_RET ("size reduction with ftruncate failed");
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800))
- FAIL ("size after reduction with ftruncate is incorrect");
+ FAIL_RET ("size after reduction with ftruncate is incorrect");
/* The following test covers more than POSIX. POSIX does not require
that ftruncate() can increase the file size. But we are testing
Unix systems. */
if (ftruncate (temp_fd, offset + 1200) < 0)
- FAIL ("size increate with ftruncate failed");
+ FAIL_RET ("size increate with ftruncate failed");
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200))
- FAIL ("size after increase is incorrect");
+ FAIL_RET ("size after increase is incorrect");
if (truncate (temp_filename, offset + 800) < 0)
- FAIL ("size reduction with truncate failed");
+ FAIL_RET ("size reduction with truncate failed");
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800))
- FAIL ("size after reduction with truncate incorrect");
+ FAIL_RET ("size after reduction with truncate incorrect");
/* The following test covers more than POSIX. POSIX does not require
that truncate() can increase the file size. But we are testing
Unix systems. */
if (truncate (temp_filename, (offset + 1200)) < 0)
- FAIL ("size increase with truncate failed");
+ FAIL_RET ("size increase with truncate failed");
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200))
- FAIL ("size increase with truncate is incorrect");
+ FAIL_RET ("size increase with truncate is incorrect");
return 0;
}

@ -1,129 +0,0 @@
commit c21ca2a696c03ff3f3931768a3ada234eebf6337
Author: Maciej W. Rozycki <macro@redhat.com>
Date: Fri Jul 26 13:21:34 2024 +0100
nptl: Use <support/check.h> facilities in tst-setuid3
Remove local FAIL macro in favor to FAIL_EXIT1 from <support/check.h>,
which provides equivalent reporting, with the name of the file and the
line number within of the failure site additionally included. Remove
FAIL_ERR altogether and include ": %m" explicitly with the format string
supplied to FAIL_EXIT1 as there seems little value to have a separate
macro just for this.
Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 8c98195af6e6f1ce21743fc26c723e0f7e45bcf2)
diff --git a/sysdeps/pthread/tst-setuid3.c b/sysdeps/pthread/tst-setuid3.c
index 254555960e1ffe74..88a2a3ef20e273f7 100644
--- a/sysdeps/pthread/tst-setuid3.c
+++ b/sysdeps/pthread/tst-setuid3.c
@@ -15,24 +15,19 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <stdbool.h>
#include <unistd.h>
+#include <support/check.h>
+
/* The test must run under a non-privileged user ID. */
static const uid_t test_uid = 1;
static pthread_barrier_t barrier1;
static pthread_barrier_t barrier2;
-#define FAIL(fmt, ...) \
- do { printf ("FAIL: " fmt "\n", __VA_ARGS__); _exit (1); } while (0)
-
-#define FAIL_ERR(fmt, ...) \
- do { printf ("FAIL: " fmt ": %m\n", __VA_ARGS__); _exit (1); } while (0)
-
/* True if x is not a successful return code from pthread_barrier_wait. */
static inline bool
is_invalid_barrier_ret (int x)
@@ -45,10 +40,10 @@ thread_func (void *ctx __attribute__ ((unused)))
{
int ret = pthread_barrier_wait (&barrier1);
if (is_invalid_barrier_ret (ret))
- FAIL ("pthread_barrier_wait (barrier1) (on thread): %d", ret);
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier1) (on thread): %d", ret);
ret = pthread_barrier_wait (&barrier2);
if (is_invalid_barrier_ret (ret))
- FAIL ("pthread_barrier_wait (barrier2) (on thread): %d", ret);
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier2) (on thread): %d", ret);
return NULL;
}
@@ -59,13 +54,13 @@ setuid_failure (int phase)
switch (ret)
{
case 0:
- FAIL ("setuid succeeded unexpectedly in phase %d", phase);
+ FAIL_EXIT1 ("setuid succeeded unexpectedly in phase %d", phase);
case -1:
if (errno != EPERM)
- FAIL_ERR ("setuid phase %d", phase);
+ FAIL_EXIT1 ("setuid phase %d: %m", phase);
break;
default:
- FAIL ("invalid setuid return value in phase %d: %d", phase, ret);
+ FAIL_EXIT1 ("invalid setuid return value in phase %d: %d", phase, ret);
}
}
@@ -74,42 +69,42 @@ do_test (void)
{
if (getuid () == 0)
if (setuid (test_uid) != 0)
- FAIL_ERR ("setuid (%u)", (unsigned) test_uid);
+ FAIL_EXIT1 ("setuid (%u): %m", (unsigned) test_uid);
if (setuid (getuid ()))
- FAIL_ERR ("setuid (%s)", "getuid ()");
+ FAIL_EXIT1 ("setuid (%s): %m", "getuid ()");
setuid_failure (1);
int ret = pthread_barrier_init (&barrier1, NULL, 2);
if (ret != 0)
- FAIL ("pthread_barrier_init (barrier1): %d", ret);
+ FAIL_EXIT1 ("pthread_barrier_init (barrier1): %d", ret);
ret = pthread_barrier_init (&barrier2, NULL, 2);
if (ret != 0)
- FAIL ("pthread_barrier_init (barrier2): %d", ret);
+ FAIL_EXIT1 ("pthread_barrier_init (barrier2): %d", ret);
pthread_t thread;
ret = pthread_create (&thread, NULL, thread_func, NULL);
if (ret != 0)
- FAIL ("pthread_create: %d", ret);
+ FAIL_EXIT1 ("pthread_create: %d", ret);
/* Ensure that the thread is running properly. */
ret = pthread_barrier_wait (&barrier1);
if (is_invalid_barrier_ret (ret))
- FAIL ("pthread_barrier_wait (barrier1): %d", ret);
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier1): %d", ret);
setuid_failure (2);
/* Check success case. */
if (setuid (getuid ()) != 0)
- FAIL_ERR ("setuid (%s)", "getuid ()");
+ FAIL_EXIT1 ("setuid (%s): %m", "getuid ()");
/* Shutdown. */
ret = pthread_barrier_wait (&barrier2);
if (is_invalid_barrier_ret (ret))
- FAIL ("pthread_barrier_wait (barrier2): %d", ret);
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier2): %d", ret);
ret = pthread_join (thread, NULL);
if (ret != 0)
- FAIL ("pthread_join: %d", ret);
+ FAIL_EXIT1 ("pthread_join: %d", ret);
return 0;
}

@ -1,27 +0,0 @@
commit ae4d44b1d501421ad9a3af95279b8f4d1546f1ce
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Tue Sep 3 14:58:33 2024 -0400
libio: Attempt wide backup free only for non-legacy code
_wide_data and _mode are not available in legacy code, so do not attempt
to free the wide backup buffer in legacy code.
Resolves: BZ #32137 and BZ #27821
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
diff --git a/libio/genops.c b/libio/genops.c
index b5fc53fd1ef6e911..99ef9d03505f3238 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -799,7 +799,7 @@ _IO_unbuffer_all (void)
/* Free up the backup area if it was ever allocated. */
if (_IO_have_backup (fp))
_IO_free_backup_area (fp);
- if (fp->_mode > 0 && _IO_have_wbackup (fp))
+ if (!legacy && fp->_mode > 0 && _IO_have_wbackup (fp))
_IO_free_wbackup_area (fp);
if (! (fp->_flags & _IO_UNBUFFERED)

@ -84,8 +84,6 @@
%undefine _annotated_build
%endif
%define man_pages_version 6.04-1.el9
##############################################################################
# Any architecture/kernel combination that supports running 32-bit and 64-bit
# code in userspace is considered a biarch arch.
@ -157,7 +155,7 @@ end \
Summary: The GNU libc libraries
Name: glibc
Version: %{glibcversion}
Release: 125%{?dist}.1
Release: 100%{?dist}
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
# libraries.
@ -810,67 +808,6 @@ Patch571: glibc-RHEL-16643-5.patch
Patch572: glibc-RHEL-16643-6.patch
Patch573: glibc-RHEL-19444.patch
Patch574: glibc-RHEL-21556.patch
Patch575: glibc-RHEL-23472.patch
Patch576: glibc-RHEL-20172-1.patch
Patch577: glibc-RHEL-20172-2.patch
Patch578: glibc-RHEL-21884.patch
Patch579: glibc-RHEL-25531-1.patch
Patch580: glibc-RHEL-25531-2.patch
Patch581: glibc-RHEL-25531-3.patch
Patch582: glibc-RHEL-25531-4.patch
Patch583: glibc-RHEL-25046.patch
Patch584: glibc-RHEL-32681-1.patch
Patch585: glibc-RHEL-32681-2.patch
Patch586: glibc-RHEL-39006.patch
Patch587: glibc-RHEL-22165-1.patch
Patch588: glibc-RHEL-22165-2.patch
Patch589: glibc-RHEL-22165-3.patch
Patch590: glibc-RHEL-22165-4.patch
Patch591: glibc-RHEL-22165-5.patch
Patch592: glibc-RHEL-31805.patch
Patch593: glibc-RHEL-25063.patch
Patch594: glibc-RHEL-34265.patch
Patch595: glibc-RHEL-34268-1.patch
Patch596: glibc-RHEL-34268-2.patch
Patch597: glibc-RHEL-34272-1.patch
Patch598: glibc-RHEL-34272-2.patch
Patch599: glibc-RHEL-39000-1.patch
Patch600: glibc-RHEL-39000-2.patch
Patch601: glibc-RHEL-39000-3.patch
Patch602: glibc-RHEL-39992-1.patch
Patch603: glibc-RHEL-39992-2.patch
Patch604: glibc-RHEL-30823.patch
Patch605: glibc-RHEL-25257-1.patch
Patch606: glibc-RHEL-25257-2.patch
Patch607: glibc-RHEL-46741-1.patch
Patch608: glibc-RHEL-46741-2.patch
Patch609: glibc-RHEL-50101-1.patch
Patch610: glibc-RHEL-50101-2.patch
Patch611: glibc-RHEL-50101-3.patch
Patch612: glibc-RHEL-54007.patch
Patch613: glibc-RHEL-46723-1.patch
Patch614: glibc-RHEL-46723-2.patch
Patch615: glibc-RHEL-36148-1.patch
Patch616: glibc-RHEL-36148-2.patch
Patch617: glibc-RHEL-36148-3.patch
Patch618: glibc-RHEL-49489-1.patch
Patch619: glibc-RHEL-49489-2.patch
Patch620: glibc-RHEL-54447-1.patch
Patch621: glibc-RHEL-54447-2.patch
Patch622: glibc-RHEL-54447-3.patch
Patch623: glibc-RHEL-54447-4.patch
Patch624: glibc-RHEL-54447-5.patch
Patch625: glibc-RHEL-54447-6.patch
Patch626: glibc-RHEL-54447-7.patch
Patch627: glibc-RHEL-54447-8.patch
Patch628: glibc-RHEL-54447-9.patch
Patch629: glibc-RHEL-54447-10.patch
Patch630: glibc-RHEL-46979-1.patch
Patch631: glibc-RHEL-46979-2.patch
Patch632: glibc-RHEL-46979-3.patch
Patch633: glibc-RHEL-46979-4.patch
Patch634: glibc-RHEL-49489-3.patch
Patch635: glibc-RHEL-49489-4.patch
##############################################################################
# Continued list of core "glibc" package information:
@ -1879,7 +1816,6 @@ build()
%ifarch aarch64
--enable-memory-tagging \
%endif
--with-man-pages=%{man_pages_version} \
--disable-crypt ||
{ cat config.log; false; }
@ -3030,93 +2966,6 @@ update_gconv_modules_cache ()
%endif
%changelog
* Fri Sep 27 2024 Florian Weimer <fweimer@redhat.com> - 2.34-125.1
- Remove some unused ppc64le string functions (RHEL-49489)
* Thu Sep 5 2024 DJ Delorie <dj@redhat.com> - 2.34-125
- elf: Rework exception handling in the dynamic loader (RHEL-46979)
* Thu Sep 5 2024 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.34-124
- Fix ungetc leak and invalid read (RHEL-54447)
* Tue Sep 03 2024 Patsy Griffin <patsy@redhat.com> - 2.34-123
- s390x: Fix segfault in wcsncmp
- Enhanced test coverage for strncmp, wcsncmp (RHEL-49489)
* Wed Aug 28 2024 Patsy Griffin <patsy@redhat.com> - 2.34-122
- elf: Clarify and invert second argument of _dl_allocate_tls_init
- elf: Avoid re-initializing already allocated TLS in dlopen (RHEL-36148)
* Thu Aug 15 2024 Florian Weimer <fweimer@redhat.com> - 2.34-121
- Document dprintf, vdprintf in the manual (RHEL-46723)
* Tue Aug 13 2024 Frédéric Bérat <fberat@redhat.com> - 2.34-120
- getdelim: ensure error indicator is set on error (RHEL-54007)
* Tue Aug 06 2024 Arjun Shankar <arjun@redhat.com> - 2.34-119
- Add new tests for aligned_alloc (RHEL-50101)
* Tue Aug 06 2024 Arjun Shankar <arjun@redhat.com> - 2.34-118
- manual: Improve documentation of putc, putwc, getc, and getwc (RHEL-46741)
* Wed Jul 17 2024 DJ Delorie <dj@redhat.com> - 2.34-117
- manual: add syscalls (RHEL-25257)
* Fri Jul 12 2024 DJ Delorie <dj@redhat.com> - 2.34-116
- Update mmap() flags and errors lists (RHEL-30823)
* Wed Jul 03 2024 Patsy Griffin <patsy@redhat.com> - 2.34-115
- elf: Avoid some free (NULL) calls in _dl_update_slotinfo
- elf: Support recursive use of dynamic TLS in interposed malloc (RHEL-39992)
* Wed Jun 26 2024 Patsy Griffin <patsy@redhat.com> - 2.34-114
- Update syscall list for Linux 6.9. (RHEL-39000)
* Thu Jun 13 2024 Patsy Griffin <patsy@redhat.com> - 2.34-113
- CVE-2024-33601 glibc: netgroup cache may terminate daemon on
memory allocation failure (RHEL-34272)
- CVE-2024-33602 glibc: netgroup cache assumes NSS callback
uses in-buffer strings (RHEL-34274)
* Tue Jun 11 2024 Patsy Griffin <patsy@redhat.com> - 2.34-112
- CVE-2024-33600: nscd: Avoid null pointer crashes after notfound
response (RHEL-34268)
* Mon Jun 10 2024 Patsy Griffin <patsy@redhat.com> - 2.34-111
- CVE-2024-33599: nscd: buffer overflow in netgroup cache (RHEL-34265)
* Mon Jun 10 2024 Arjun Shankar <arjun@redhat.com> - 2.34-110
- Add new test for malloc mmap fall-back path upon sbrk failure (RHEL-25063)
* Thu Jun 06 2024 Patsy Griffin <patsy@redhat.com> - 2.34-109
- CVE-2024-2961: Out of bounds write in iconv conversion to
ISO-2022-CN-EXT (RHEL-31805)
* Thu Jun 06 2024 Patsy Griffin <patsy@redhat.com> - 2.34-108
- aarch64: enhance ld.so --list-diagnostics on aarch64 similar
to x86_64 (RHEL-22165)
* Tue May 28 2024 <dj@redhat.com> - 2.34-107
- Add MMAP_ABOVE4G from Linux 6.6 to sys/mman.h (RHEL-39006)
* Sun May 19 2024 Patsy Griffin <patsy@redhat.com> - 2.34-106
- Improve test coverage for connect() (RHEL-32681)
* Wed Apr 3 2024 DJ Delorie <dj@redhat.com> - 2.34-105
- x86-64: Save APX registers in ld.so trampoline (RHEL-25046)
* Tue Mar 26 2024 DJ Delorie <dj@redhat.com> - 2.34-104
- x86: Fix Zen3/Zen4 ERMS selection (RHEL-25531)
* Tue Mar 12 2024 Arjun Shankar <arjun@redhat.com> - 2.34-103
- malloc: Do not use MAP_NORESERVE to allocate heap segments (RHEL-21884)
* Fri Mar 8 2024 DJ Delorie <dj@redhat.com> - 2.34-102
- Add glibc.cpu.prefer_map_32bit_exec tunable (RHEL-20172)
* Tue Feb 27 2024 Patsy Griffin <patsy@redhat.com> - 2.34-101
- Switch back to assembly syscall wrapper for prctl (RHEL-23472)
* Wed Jan 24 2024 Patsy Griffin <patsy@redhat.com> - 2.34-100
- manual: fix order of arguments of memalign and aligned_alloc (RHEL-21556)

Loading…
Cancel
Save