Toshaan Bharvani
2 weeks ago
61 changed files with 11433 additions and 0 deletions
@ -0,0 +1,369 @@
@@ -0,0 +1,369 @@
|
||||
From 317f1c0a8a71a862b1e600ff5386b08e02cf4b95 Mon Sep 17 00:00:00 2001 |
||||
From: "H.J. Lu" <hjl.tools@gmail.com> |
||||
Date: Thu, 26 Jan 2023 08:26:18 -0800 |
||||
Subject: [PATCH] x86-64: Add glibc.cpu.prefer_map_32bit_exec [BZ #28656] |
||||
Content-type: text/plain; charset=UTF-8 |
||||
|
||||
Crossing 2GB boundaries with indirect calls and jumps can use more |
||||
branch prediction resources on Intel Golden Cove CPU (see the |
||||
"Misprediction for Branches >2GB" section in Intel 64 and IA-32 |
||||
Architectures Optimization Reference Manual.) There is visible |
||||
performance improvement on workloads with many PLT calls when executable |
||||
and shared libraries are mmapped below 2GB. Add the Prefer_MAP_32BIT_EXEC |
||||
bit so that mmap will try to map executable or denywrite pages in shared |
||||
libraries with MAP_32BIT first. |
||||
|
||||
NB: Prefer_MAP_32BIT_EXEC reduces bits available for address space |
||||
layout randomization (ASLR), which is always disabled for SUID programs |
||||
and can only be enabled by the tunable, glibc.cpu.prefer_map_32bit_exec, |
||||
or the environment variable, LD_PREFER_MAP_32BIT_EXEC. This works only |
||||
between shared libraries or between shared libraries and executables with |
||||
addresses below 2GB. PIEs are usually loaded at a random address above |
||||
4GB by the kernel. |
||||
|
||||
Conflicts: |
||||
manual/tunables.texi |
||||
(line numbers) |
||||
sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list |
||||
(merged local @order list) |
||||
sysdeps/x86/cpu-features.c |
||||
(line numbers) |
||||
|
||||
--- |
||||
manual/tunables.texi | 33 ++++++++++---- |
||||
sysdeps/unix/sysv/linux/x86_64/64/Makefile | 25 +++++++++++ |
||||
.../sysv/linux/x86_64/64/dl-tunables.list | 29 +++++++++++++ |
||||
.../unix/sysv/linux/x86_64/64/mmap_internal.h | 43 +++++++++++++++++++ |
||||
.../sysv/linux/x86_64/64/tst-map-32bit-1a.c | 34 +++++++++++++++ |
||||
.../sysv/linux/x86_64/64/tst-map-32bit-1b.c | 1 + |
||||
.../sysv/linux/x86_64/64/tst-map-32bit-mod.c | 33 ++++++++++++++ |
||||
sysdeps/x86/cpu-features.c | 15 +++++++ |
||||
...cpu-features-preferred_feature_index_1.def | 1 + |
||||
9 files changed, 205 insertions(+), 9 deletions(-) |
||||
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list |
||||
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h |
||||
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c |
||||
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c |
||||
create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c |
||||
|
||||
diff --git a/manual/tunables.texi b/manual/tunables.texi |
||||
index 0be7231e36..c76c5c53cd 100644 |
||||
--- a/manual/tunables.texi |
||||
+++ b/manual/tunables.texi |
||||
@@ -35,27 +35,32 @@ tunables with minimum and maximum values: |
||||
@example |
||||
$ /lib64/ld-linux-x86-64.so.2 --list-tunables |
||||
glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10) |
||||
-glibc.elision.skip_lock_after_retries: 3 (min: -2147483648, max: 2147483647) |
||||
+glibc.elision.skip_lock_after_retries: 3 (min: 0, max: 2147483647) |
||||
glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0xffffffffffffffff) |
||||
glibc.malloc.perturb: 0 (min: 0, max: 255) |
||||
glibc.cpu.x86_shared_cache_size: 0x100000 (min: 0x0, max: 0xffffffffffffffff) |
||||
+glibc.pthread.rseq: 1 (min: 0, max: 1) |
||||
+glibc.cpu.prefer_map_32bit_exec: 0 (min: 0, max: 1) |
||||
glibc.mem.tagging: 0 (min: 0, max: 255) |
||||
-glibc.elision.tries: 3 (min: -2147483648, max: 2147483647) |
||||
+glibc.elision.tries: 3 (min: 0, max: 2147483647) |
||||
glibc.elision.enable: 0 (min: 0, max: 1) |
||||
-glibc.cpu.x86_rep_movsb_threshold: 0x1000 (min: 0x100, max: 0xffffffffffffffff) |
||||
+glibc.malloc.hugetlb: 0x0 (min: 0x0, max: 0xffffffffffffffff) |
||||
+glibc.cpu.x86_rep_movsb_threshold: 0x2000 (min: 0x100, max: 0xffffffffffffffff) |
||||
glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0xffffffffffffffff) |
||||
-glibc.elision.skip_lock_busy: 3 (min: -2147483648, max: 2147483647) |
||||
-glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0xffffffffffffffff) |
||||
+glibc.rtld.dynamic_sort: 2 (min: 1, max: 2) |
||||
+glibc.elision.skip_lock_busy: 3 (min: 0, max: 2147483647) |
||||
+glibc.malloc.top_pad: 0x20000 (min: 0x0, max: 0xffffffffffffffff) |
||||
glibc.cpu.x86_rep_stosb_threshold: 0x800 (min: 0x1, max: 0xffffffffffffffff) |
||||
-glibc.cpu.x86_non_temporal_threshold: 0xc0000 (min: 0x4040, max: 0x0fffffffffffffff) |
||||
+glibc.cpu.x86_non_temporal_threshold: 0xc0000 (min: 0x4040, max: 0xfffffffffffffff) |
||||
glibc.cpu.x86_shstk: |
||||
+glibc.pthread.stack_cache_size: 0x2800000 (min: 0x0, max: 0xffffffffffffffff) |
||||
glibc.cpu.hwcap_mask: 0x6 (min: 0x0, max: 0xffffffffffffffff) |
||||
-glibc.malloc.mmap_max: 0 (min: -2147483648, max: 2147483647) |
||||
-glibc.elision.skip_trylock_internal_abort: 3 (min: -2147483648, max: 2147483647) |
||||
+glibc.malloc.mmap_max: 0 (min: 0, max: 2147483647) |
||||
+glibc.elision.skip_trylock_internal_abort: 3 (min: 0, max: 2147483647) |
||||
glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0xffffffffffffffff) |
||||
glibc.cpu.x86_ibt: |
||||
glibc.cpu.hwcaps: |
||||
-glibc.elision.skip_lock_internal_abort: 3 (min: -2147483648, max: 2147483647) |
||||
+glibc.elision.skip_lock_internal_abort: 3 (min: 0, max: 2147483647) |
||||
glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0xffffffffffffffff) |
||||
glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0xffffffffffffffff) |
||||
glibc.cpu.x86_data_cache_size: 0x8000 (min: 0x0, max: 0xffffffffffffffff) |
||||
@@ -569,6 +574,16 @@ instead. |
||||
This tunable is specific to i386 and x86-64. |
||||
@end deftp |
||||
|
||||
+@deftp Tunable glibc.cpu.prefer_map_32bit_exec |
||||
+When this tunable is set to \code{1}, shared libraries of non-setuid |
||||
+programs will be loaded below 2GB with MAP_32BIT. |
||||
+ |
||||
+Note that the @env{LD_PREFER_MAP_32BIT_EXEC} environment is an alias of |
||||
+this tunable. |
||||
+ |
||||
+This tunable is specific to 64-bit x86-64. |
||||
+@end deftp |
||||
+ |
||||
@node Memory Related Tunables |
||||
@section Memory Related Tunables |
||||
@cindex memory related tunables |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/Makefile b/sysdeps/unix/sysv/linux/x86_64/64/Makefile |
||||
index a7b6dc5a53..8ff4f27786 100644 |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/Makefile |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/Makefile |
||||
@@ -1,2 +1,27 @@ |
||||
# The default ABI is 64. |
||||
default-abi := 64 |
||||
+ |
||||
+ifeq ($(subdir),elf) |
||||
+ifneq ($(have-tunables),no) |
||||
+ |
||||
+tests-map-32bit = \ |
||||
+ tst-map-32bit-1a \ |
||||
+ tst-map-32bit-1b \ |
||||
+# tests-map-32bit |
||||
+tst-map-32bit-1a-no-pie = yes |
||||
+tst-map-32bit-1b-no-pie = yes |
||||
+tests += $(tests-map-32bit) |
||||
+ |
||||
+modules-map-32bit = \ |
||||
+ tst-map-32bit-mod \ |
||||
+# modules-map-32bit |
||||
+modules-names += $(modules-map-32bit) |
||||
+ |
||||
+$(objpfx)tst-map-32bit-mod.so: $(libsupport) |
||||
+tst-map-32bit-1a-ENV = LD_PREFER_MAP_32BIT_EXEC=1 |
||||
+$(objpfx)tst-map-32bit-1a: $(objpfx)tst-map-32bit-mod.so |
||||
+tst-map-32bit-1b-ENV = GLIBC_TUNABLES=glibc.cpu.prefer_map_32bit_exec=1 |
||||
+$(objpfx)tst-map-32bit-1b: $(objpfx)tst-map-32bit-mod.so |
||||
+ |
||||
+endif |
||||
+endif |
||||
diff -rup a/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list 2024-03-06 17:52:50.968514369 -0500 |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list 2024-03-06 17:55:48.778264896 -0500 |
||||
@@ -1,3 +1,33 @@ |
||||
+# x86-64 specific tunables. |
||||
+# Copyright (C) 2023 Free Software Foundation, Inc. |
||||
+# This file is part of the GNU C Library. |
||||
+ |
||||
+# The GNU C Library is free software; you can redistribute it and/or |
||||
+# modify it under the terms of the GNU Lesser General Public |
||||
+# License as published by the Free Software Foundation; either |
||||
+# version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+# The GNU C Library is distributed in the hope that it will be useful, |
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+# Lesser General Public License for more details. |
||||
+ |
||||
+# You should have received a copy of the GNU Lesser General Public |
||||
+# License along with the GNU C Library; if not, see |
||||
+# <https://www.gnu.org/licenses/>. |
||||
+ |
||||
+glibc { |
||||
+ cpu { |
||||
+ prefer_map_32bit_exec { |
||||
+ type: INT_32 |
||||
+ minval: 0 |
||||
+ maxval: 1 |
||||
+ env_alias: LD_PREFER_MAP_32BIT_EXEC |
||||
+ security_level: SXID_IGNORE |
||||
+ } |
||||
+ } |
||||
+} |
||||
+ |
||||
# Order of tunables in RHEL 9.1.z. |
||||
@order glibc.rtld.nns |
||||
@order glibc.elision.skip_lock_after_retries |
||||
@@ -35,3 +65,5 @@ |
||||
@order glibc.malloc.check |
||||
@order glibc.gmon.minarcs |
||||
@order glibc.gmon.maxarcs |
||||
+# Order of tunables in RHEL 9.5.z |
||||
+@order glibc.cpu.prefer_map_32bit_exec |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h b/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h |
||||
new file mode 100644 |
||||
index 0000000000..33dec3f805 |
||||
--- /dev/null |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h |
||||
@@ -0,0 +1,43 @@ |
||||
+/* Linux mmap system call. x86-64 version. |
||||
+ Copyright (C) 2015-2023 Free Software Foundation, Inc. |
||||
+ |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public License as |
||||
+ published by the Free Software Foundation; either version 2.1 of the |
||||
+ License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#ifndef MMAP_X86_64_INTERNAL_H |
||||
+#define MMAP_X86_64_INTERNAL_H |
||||
+ |
||||
+#include <ldsodefs.h> |
||||
+ |
||||
+/* If the Prefer_MAP_32BIT_EXEC bit is set, try to map executable or |
||||
+ denywrite pages with MAP_32BIT first. */ |
||||
+#define MMAP_PREPARE(addr, len, prot, flags, fd, offset) \ |
||||
+ if ((addr) == NULL \ |
||||
+ && (((prot) & PROT_EXEC) != 0 \ |
||||
+ || ((flags) & MAP_DENYWRITE) != 0) \ |
||||
+ && HAS_ARCH_FEATURE (Prefer_MAP_32BIT_EXEC)) \ |
||||
+ { \ |
||||
+ void *ret = (void*) INLINE_SYSCALL_CALL (mmap, (addr), (len), \ |
||||
+ (prot), \ |
||||
+ (flags) | MAP_32BIT, \ |
||||
+ (fd), (offset)); \ |
||||
+ if (ret != MAP_FAILED) \ |
||||
+ return ret; \ |
||||
+ } |
||||
+ |
||||
+#include_next <mmap_internal.h> |
||||
+ |
||||
+#endif |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c |
||||
new file mode 100644 |
||||
index 0000000000..abc396589e |
||||
--- /dev/null |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1a.c |
||||
@@ -0,0 +1,34 @@ |
||||
+/* Check that LD_PREFER_MAP_32BIT_EXEC works in PDE and shared library. |
||||
+ Copyright (C) 2023 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <stdio.h> |
||||
+#include <stdint.h> |
||||
+#include <support/check.h> |
||||
+ |
||||
+extern void dso_check_map_32bit (void); |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ printf ("do_test: %p\n", do_test); |
||||
+ TEST_VERIFY ((uintptr_t) do_test < 0xffffffffUL); |
||||
+ dso_check_map_32bit (); |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c |
||||
new file mode 100644 |
||||
index 0000000000..34ab01c773 |
||||
--- /dev/null |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-1b.c |
||||
@@ -0,0 +1 @@ |
||||
+#include "tst-map-32bit-1a.c" |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c |
||||
new file mode 100644 |
||||
index 0000000000..78d4b6133c |
||||
--- /dev/null |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/tst-map-32bit-mod.c |
||||
@@ -0,0 +1,33 @@ |
||||
+/* Check that LD_PREFER_MAP_32BIT_EXEC works in shared library. |
||||
+ Copyright (C) 2023 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <stdio.h> |
||||
+#include <stdint.h> |
||||
+#include <support/check.h> |
||||
+ |
||||
+static void |
||||
+dso_do_test (void) |
||||
+{ |
||||
+} |
||||
+ |
||||
+void |
||||
+dso_check_map_32bit (void) |
||||
+{ |
||||
+ printf ("dso_do_test: %p\n", dso_do_test); |
||||
+ TEST_VERIFY ((uintptr_t) dso_do_test < 0xffffffffUL); |
||||
+} |
||||
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c |
||||
index a2197ed211..822688e21f 100644 |
||||
--- a/sysdeps/x86/cpu-features.c |
||||
+++ b/sysdeps/x86/cpu-features.c |
||||
@@ -27,6 +27,16 @@ |
||||
extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) |
||||
attribute_hidden; |
||||
|
||||
+# ifdef __LP64__ |
||||
+static void |
||||
+TUNABLE_CALLBACK (set_prefer_map_32bit_exec) (tunable_val_t *valp) |
||||
+{ |
||||
+ if (valp->numval) |
||||
+ GLRO(dl_x86_cpu_features).preferred[index_arch_Prefer_MAP_32BIT_EXEC] |
||||
+ |= bit_arch_Prefer_MAP_32BIT_EXEC; |
||||
+} |
||||
+# endif |
||||
+ |
||||
# if CET_ENABLED |
||||
extern void TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *) |
||||
attribute_hidden; |
||||
@@ -949,6 +959,11 @@ no_cpuid: |
||||
#if HAVE_TUNABLES |
||||
TUNABLE_GET (hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps)); |
||||
|
||||
+# ifdef __LP64__ |
||||
+ TUNABLE_GET (prefer_map_32bit_exec, tunable_val_t *, |
||||
+ TUNABLE_CALLBACK (set_prefer_map_32bit_exec)); |
||||
+# endif |
||||
+ |
||||
bool disable_xsave_features = false; |
||||
|
||||
if (!CPU_FEATURE_USABLE_P (cpu_features, OSXSAVE)) |
||||
diff --git a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def |
||||
index e45f9cb159..d20c5b3196 100644 |
||||
--- a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def |
||||
+++ b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def |
||||
@@ -26,6 +26,7 @@ BIT (I586) |
||||
BIT (I686) |
||||
BIT (Slow_SSE4_2) |
||||
BIT (AVX_Fast_Unaligned_Load) |
||||
+BIT (Prefer_MAP_32BIT_EXEC) |
||||
BIT (Prefer_No_VZEROUPPER) |
||||
BIT (Prefer_ERMS) |
||||
BIT (Prefer_No_AVX512) |
||||
-- |
||||
2.39.3 |
||||
|
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
From 188ecdb7774145050a6e167a277f45f03dac5fe8 Mon Sep 17 00:00:00 2001 |
||||
From: "H.J. Lu" <hjl.tools@gmail.com> |
||||
Date: Wed, 22 Feb 2023 20:04:26 -0800 |
||||
Subject: [PATCH] tunables.texi: Change \code{1} to @code{1} |
||||
Content-type: text/plain; charset=UTF-8 |
||||
|
||||
Update |
||||
|
||||
317f1c0a8a x86-64: Add glibc.cpu.prefer_map_32bit_exec [BZ #28656] |
||||
--- |
||||
manual/tunables.texi | 2 +- |
||||
1 file changed, 1 insertion(+), 1 deletion(-) |
||||
|
||||
diff --git a/manual/tunables.texi b/manual/tunables.texi |
||||
index c76c5c53cd..70dd2264c5 100644 |
||||
--- a/manual/tunables.texi |
||||
+++ b/manual/tunables.texi |
||||
@@ -589,7 +589,7 @@ This tunable is specific to i386 and x86-64. |
||||
@end deftp |
||||
|
||||
@deftp Tunable glibc.cpu.prefer_map_32bit_exec |
||||
-When this tunable is set to \code{1}, shared libraries of non-setuid |
||||
+When this tunable is set to @code{1}, shared libraries of non-setuid |
||||
programs will be loaded below 2GB with MAP_32BIT. |
||||
|
||||
Note that the @env{LD_PREFER_MAP_32BIT_EXEC} environment is an alias of |
||||
-- |
||||
2.39.3 |
||||
|
@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
|
||||
commit 85860ad6eaf4c9739318f6b2a1ff7c2fa6b12ab5 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Mon Aug 15 16:45:40 2022 +0200 |
||||
|
||||
malloc: Do not use MAP_NORESERVE to allocate heap segments |
||||
|
||||
Address space for heap segments is reserved in a mmap call with |
||||
MAP_ANONYMOUS | MAP_PRIVATE and protection flags PROT_NONE. This |
||||
reservation does not count against the RSS limit of the process or |
||||
system. Backing memory is allocated using mprotect in alloc_new_heap |
||||
and grow_heap, and at this point, the allocator expects the kernel |
||||
to provide memory (subject to memory overcommit). |
||||
|
||||
The SIGSEGV that might generate due to MAP_NORESERVE (according to |
||||
the mmap manual page) does not seem to occur in practice, it's always |
||||
SIGKILL from the OOM killer. Even if there is a way that SIGSEGV |
||||
could be generated, it is confusing to applications that this only |
||||
happens for secondary heaps, not for large mmap-based allocations, |
||||
and not for the main arena. |
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
|
||||
Conflicts: |
||||
malloc/arena.c |
||||
(huge page support was added upstream) |
||||
|
||||
diff --git a/malloc/arena.c b/malloc/arena.c |
||||
index 667484630ed0afa5..2852783355d3d869 100644 |
||||
--- a/malloc/arena.c |
||||
+++ b/malloc/arena.c |
||||
@@ -466,8 +466,7 @@ new_heap (size_t size, size_t top_pad) |
||||
p2 = MAP_FAILED; |
||||
if (aligned_heap_area) |
||||
{ |
||||
- p2 = (char *) MMAP (aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE, |
||||
- MAP_NORESERVE); |
||||
+ p2 = (char *) MMAP (aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE, 0); |
||||
aligned_heap_area = NULL; |
||||
if (p2 != MAP_FAILED && ((unsigned long) p2 & (HEAP_MAX_SIZE - 1))) |
||||
{ |
||||
@@ -477,7 +476,7 @@ new_heap (size_t size, size_t top_pad) |
||||
} |
||||
if (p2 == MAP_FAILED) |
||||
{ |
||||
- p1 = (char *) MMAP (0, HEAP_MAX_SIZE << 1, PROT_NONE, MAP_NORESERVE); |
||||
+ p1 = (char *) MMAP (0, HEAP_MAX_SIZE << 1, PROT_NONE, 0); |
||||
if (p1 != MAP_FAILED) |
||||
{ |
||||
p2 = (char *) (((unsigned long) p1 + (HEAP_MAX_SIZE - 1)) |
||||
@@ -493,7 +492,7 @@ new_heap (size_t size, size_t top_pad) |
||||
{ |
||||
/* Try to take the chance that an allocation of only HEAP_MAX_SIZE |
||||
is already aligned. */ |
||||
- p2 = (char *) MMAP (0, HEAP_MAX_SIZE, PROT_NONE, MAP_NORESERVE); |
||||
+ p2 = (char *) MMAP (0, HEAP_MAX_SIZE, PROT_NONE, 0); |
||||
if (p2 == MAP_FAILED) |
||||
return 0; |
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c |
||||
index 375f50f5db13e234..fe80b8239756a7c9 100644 |
||||
--- a/malloc/malloc.c |
||||
+++ b/malloc/malloc.c |
||||
@@ -1112,10 +1112,6 @@ static mchunkptr mremap_chunk(mchunkptr p, size_t new_size); |
||||
# define MAP_ANONYMOUS MAP_ANON |
||||
#endif |
||||
|
||||
-#ifndef MAP_NORESERVE |
||||
-# define MAP_NORESERVE 0 |
||||
-#endif |
||||
- |
||||
#define MMAP(addr, size, prot, flags) \ |
||||
__mmap((addr), (size), (prot), (flags)|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0) |
||||
|
@ -0,0 +1,229 @@
@@ -0,0 +1,229 @@
|
||||
commit f21962ddfc8bb23e92597da1f98e313dbde11cc1 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Fri Aug 25 14:15:28 2023 +0200 |
||||
|
||||
manual: Document ld.so --list-diagnostics output |
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
|
||||
diff --git a/manual/dynlink.texi b/manual/dynlink.texi |
||||
index 45bf5a5b55..df41c56bfc 100644 |
||||
--- a/manual/dynlink.texi |
||||
+++ b/manual/dynlink.texi |
||||
@@ -13,9 +13,216 @@ as plugins) later at run time. |
||||
Dynamic linkers are sometimes called @dfn{dynamic loaders}. |
||||
|
||||
@menu |
||||
+* Dynamic Linker Invocation:: Explicit invocation of the dynamic linker. |
||||
* Dynamic Linker Introspection:: Interfaces for querying mapping information. |
||||
@end menu |
||||
|
||||
+@node Dynamic Linker Invocation |
||||
+ |
||||
+@cindex program interpreter |
||||
+When a dynamically linked program starts, the operating system |
||||
+automatically loads the dynamic linker along with the program. |
||||
+@Theglibc{} also supports invoking the dynamic linker explicitly to |
||||
+launch a program. This command uses the implied dynamic linker |
||||
+(also sometimes called the @dfn{program interpreter}): |
||||
+ |
||||
+@smallexample |
||||
+sh -c 'echo "Hello, world!"' |
||||
+@end smallexample |
||||
+ |
||||
+This command specifies the dynamic linker explicitly: |
||||
+ |
||||
+@smallexample |
||||
+ld.so /bin/sh -c 'echo "Hello, world!"' |
||||
+@end smallexample |
||||
+ |
||||
+Note that @command{ld.so} does not search the @env{PATH} environment |
||||
+variable, so the full file name of the executable needs to be specified. |
||||
+ |
||||
+The @command{ld.so} program supports various options. Options start |
||||
+@samp{--} and need to come before the program that is being launched. |
||||
+Some of the supported options are listed below. |
||||
+ |
||||
+@table @code |
||||
+@item --list-diagnostics |
||||
+Print system diagnostic information in a machine-readable format. |
||||
+@xref{Dynamic Linker Diagnostics}. |
||||
+@end table |
||||
+ |
||||
+@menu |
||||
+* Dynamic Linker Diagnostics:: Obtaining system diagnostic information. |
||||
+@end menu |
||||
+ |
||||
+@node Dynamic Linker Diagnostics |
||||
+@section Dynamic Linker Diagnostics |
||||
+@cindex diagnostics (dynamic linker) |
||||
+ |
||||
+The @samp{ld.so --list-diagnostics} produces machine-readable |
||||
+diagnostics output. This output contains system data that affects the |
||||
+behavior of @theglibc{}, and potentially application behavior as well. |
||||
+ |
||||
+The exact set of diagnostic items can change between releases of |
||||
+@theglibc{}. The output format itself is not expected to change |
||||
+radically. |
||||
+ |
||||
+The following table shows some example lines that can be written by the |
||||
+diagnostics command. |
||||
+ |
||||
+@table @code |
||||
+@item dl_pagesize=0x1000 |
||||
+The system page size is 4096 bytes. |
||||
+ |
||||
+@item env[0x14]="LANG=en_US.UTF-8" |
||||
+This item indicates that the 21st environment variable at process |
||||
+startup contains a setting for @code{LANG}. |
||||
+ |
||||
+@item env_filtered[0x22]="DISPLAY" |
||||
+The 35th environment variable is @code{DISPLAY}. Its value is not |
||||
+included in the output for privacy reasons because it is not recognized |
||||
+as harmless by the diagnostics code. |
||||
+ |
||||
+@item path.prefix="/usr" |
||||
+This means that @theglibc{} was configured with @code{--prefix=/usr}. |
||||
+ |
||||
+@item path.system_dirs[0x0]="/lib64/" |
||||
+@itemx path.system_dirs[0x1]="/usr/lib64/" |
||||
+The built-in dynamic linker search path contains two directories, |
||||
+@code{/lib64} and @code{/usr/lib64}. |
||||
+@end table |
||||
+ |
||||
+@subsection Dynamic Linker Diagnostics Output Format |
||||
+ |
||||
+As seen above, diagnostic lines assign values (integers or strings) to a |
||||
+sequence of labeled subscripts, separated by @samp{.}. Some subscripts |
||||
+have integer indices associated with them. The subscript indices are |
||||
+not necessarily contiguous or small, so an associative array should be |
||||
+used to store them. Currently, all integers fit into the 64-bit |
||||
+unsigned integer range. Every access path to a value has a fixed type |
||||
+(string or integer) independent of subscript index values. Likewise, |
||||
+whether a subscript is indexed does not depend on previous indices (but |
||||
+may depend on previous subscript labels). |
||||
+ |
||||
+A syntax description in ABNF (RFC 5234) follows. Note that |
||||
+@code{%x30-39} denotes the range of decimal digits. Diagnostic output |
||||
+lines are expected to match the @code{line} production. |
||||
+ |
||||
+@c ABNF-START |
||||
+@smallexample |
||||
+HEXDIG = %x30-39 / %x61-6f ; lowercase a-f only |
||||
+ALPHA = %x41-5a / %x61-7a / %x7f ; letters and underscore |
||||
+ALPHA-NUMERIC = ALPHA / %x30-39 / "_" |
||||
+DQUOTE = %x22 ; " |
||||
+ |
||||
+; Numbers are always hexadecimal and use a 0x prefix. |
||||
+hex-value-prefix = %x30 %x78 |
||||
+hex-value = hex-value-prefix 1*HEXDIG |
||||
+ |
||||
+; Strings use octal escape sequences and \\, \". |
||||
+string-char = %x20-21 / %x23-5c / %x5d-7e ; printable but not "\ |
||||
+string-quoted-octal = %x30-33 2*2%x30-37 |
||||
+string-quoted = "\" ("\" / DQUOTE / string-quoted-octal) |
||||
+string-value = DQUOTE *(string-char / string-quoted) DQUOTE |
||||
+ |
||||
+value = hex-value / string-value |
||||
+ |
||||
+label = ALPHA *ALPHA-NUMERIC |
||||
+index = "[" hex-value "]" |
||||
+subscript = label [index] |
||||
+ |
||||
+line = subscript *("." subscript) "=" value |
||||
+@end smallexample |
||||
+ |
||||
+@subsection Dynamic Linker Diagnostics Values |
||||
+ |
||||
+As mentioned above, the set of diagnostics may change between |
||||
+@theglibc{} releases. Nevertheless, the following table documents a few |
||||
+common diagnostic items. All numbers are in hexadecimal, with a |
||||
+@samp{0x} prefix. |
||||
+ |
||||
+@table @code |
||||
+@item dl_dst_lib=@var{string} |
||||
+The @code{$LIB} dynamic string token expands to @var{string}. |
||||
+ |
||||
+@cindex HWCAP (diagnostics) |
||||
+@item dl_hwcap=@var{integer} |
||||
+@itemx dl_hwcap2=@var{integer} |
||||
+The HWCAP and HWCAP2 values, as returned for @code{getauxval}, and as |
||||
+used in other places depending on the architecture. |
||||
+ |
||||
+@cindex page size (diagnostics) |
||||
+@item dl_pagesize=@var{integer} |
||||
+The system page size is @var{integer} bytes. |
||||
+ |
||||
+@item dl_platform=@var{string} |
||||
+The @code{$PLATFORM} dynamic string token expands to @var{string}. |
||||
+ |
||||
+@item dso.libc=@var{string} |
||||
+This is the soname of the shared @code{libc} object that is part of |
||||
+@theglibc{}. On most architectures, this is @code{libc.so.6}. |
||||
+ |
||||
+@item env[@var{index}]=@var{string} |
||||
+@itemx env_filtered[@var{index}]=@var{string} |
||||
+An environment variable from the process environment. The integer |
||||
+@var{index} is the array index in the environment array. Variables |
||||
+under @code{env} include the variable value after the @samp{=} (assuming |
||||
+that it was present), variables under @code{env_filtered} do not. |
||||
+ |
||||
+@item path.prefix=@var{string} |
||||
+This indicates that @theglibc{} was configured using |
||||
+@samp{--prefix=@var{string}}. |
||||
+ |
||||
+@item path.sysconfdir=@var{string} |
||||
+@Theglibc{} was configured (perhaps implicitly) with |
||||
+@samp{--sysconfdir=@var{string}} (typically @code{/etc}). |
||||
+ |
||||
+@item path.system_dirs[@var{index}]=@var{string} |
||||
+These items list the elements of the built-in array that describes the |
||||
+default library search path. The value @var{string} is a directory file |
||||
+name with a trailing @samp{/}. |
||||
+ |
||||
+@item path.rtld=@var{string} |
||||
+This string indicates the application binary interface (ABI) file name |
||||
+of the run-time dynamic linker. |
||||
+ |
||||
+@item version.release="stable" |
||||
+@itemx version.release="development" |
||||
+The value @code{"stable"} indicates that this build of @theglibc{} is |
||||
+from a release branch. Releases labeled as @code{"development"} are |
||||
+unreleased development versions. |
||||
+ |
||||
+@cindex version (diagnostics) |
||||
+@item version.version="@var{major}.@var{minor}" |
||||
+@itemx version.version="@var{major}.@var{minor}.9000" |
||||
+@Theglibc{} version. Development releases end in @samp{.9000}. |
||||
+ |
||||
+@cindex auxiliary vector (diagnostics) |
||||
+@item auxv[@var{index}].a_type=@var{type} |
||||
+@itemx auxv[@var{index}].a_val=@var{integer} |
||||
+@itemx auxv[@var{index}].a_val_string=@var{string} |
||||
+An entry in the auxiliary vector (specific to Linux). The values |
||||
+@var{type} (an integer) and @var{integer} correspond to the members of |
||||
+@code{struct auxv}. If the value is a string, @code{a_val_string} is |
||||
+used instead of @code{a_val}, so that values have consistent types. |
||||
+ |
||||
+The @code{AT_HWCAP} and @code{AT_HWCAP2} values in this output do not |
||||
+reflect adjustment by @theglibc{}. |
||||
+ |
||||
+@item uname.sysname=@var{string} |
||||
+@itemx uname.nodename=@var{string} |
||||
+@itemx uname.release=@var{string} |
||||
+@itemx uname.version=@var{string} |
||||
+@itemx uname.machine=@var{string} |
||||
+@itemx uname.domain=@var{string} |
||||
+These Linux-specific items show the values of @code{struct utsname}, as |
||||
+reported by the @code{uname} function. @xref{Platform Type}. |
||||
+ |
||||
+@cindex CPUID (diagnostics) |
||||
+@item x86.cpu_features.@dots{} |
||||
+These items are specific to the i386 and x86-64 architectures. They |
||||
+reflect supported CPU features and information on cache geometry, mostly |
||||
+collected using the @code{CPUID} instruction. |
||||
+@end table |
||||
+ |
||||
@node Dynamic Linker Introspection |
||||
@section Dynamic Linker Introspection |
||||
|
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
commit d99609a3eb8bc96c3af841fd35294a679e0fea7f |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Wed Sep 6 18:37:21 2023 +0200 |
||||
|
||||
manual: Fix ld.so diagnostics menu/section structure |
||||
|
||||
And shorten the section/node names a bit, so that the menu |
||||
entries become easier to read. |
||||
|
||||
Texinfo 6.5 fails to process the previous structure: |
||||
|
||||
./dynlink.texi:56: warning: node `Dynamic Linker Introspection' is |
||||
next for `Dynamic Linker Diagnostics' in sectioning but not in menu |
||||
./dynlink.texi:56: warning: node up `Dynamic Linker Diagnostics' |
||||
in menu `Dynamic Linker Invocation' and |
||||
in sectioning `Dynamic Linker' differ |
||||
./dynlink.texi:1: node `Dynamic Linker' lacks menu item for |
||||
`Dynamic Linker Diagnostics' despite being its Up target |
||||
./dynlink.texi:226: warning: node prev `Dynamic Linker Introspection' in menu `Dynamic Linker Invocation' |
||||
and in sectioning `Dynamic Linker Diagnostics' differ |
||||
|
||||
Texinfo 7.0.2 does not report an error. |
||||
|
||||
This fixes commit f21962ddfc8bb23e92597da1f98e313dbde11cc1 |
||||
("manual: Document ld.so --list-diagnostics output"). |
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> |
||||
|
||||
diff --git a/manual/dynlink.texi b/manual/dynlink.texi |
||||
index df41c56bfc..06a6c15533 100644 |
||||
--- a/manual/dynlink.texi |
||||
+++ b/manual/dynlink.texi |
||||
@@ -18,6 +18,7 @@ Dynamic linkers are sometimes called @dfn{dynamic loaders}. |
||||
@end menu |
||||
|
||||
@node Dynamic Linker Invocation |
||||
+@section Dynamic Linker Invocation |
||||
|
||||
@cindex program interpreter |
||||
When a dynamically linked program starts, the operating system |
||||
@@ -54,7 +55,7 @@ Print system diagnostic information in a machine-readable format. |
||||
@end menu |
||||
|
||||
@node Dynamic Linker Diagnostics |
||||
-@section Dynamic Linker Diagnostics |
||||
+@subsection Dynamic Linker Diagnostics |
||||
@cindex diagnostics (dynamic linker) |
||||
|
||||
The @samp{ld.so --list-diagnostics} produces machine-readable |
||||
@@ -90,7 +91,13 @@ The built-in dynamic linker search path contains two directories, |
||||
@code{/lib64} and @code{/usr/lib64}. |
||||
@end table |
||||
|
||||
-@subsection Dynamic Linker Diagnostics Output Format |
||||
+@menu |
||||
+* Dynamic Linker Diagnostics Format:: Format of ld.so output. |
||||
+* Dynamic Linker Diagnostics Values:: Data contain in ld.so output. |
||||
+@end menu |
||||
+ |
||||
+@node Dynamic Linker Diagnostics Format |
||||
+@subsubsection Dynamic Linker Diagnostics Format |
||||
|
||||
As seen above, diagnostic lines assign values (integers or strings) to a |
||||
sequence of labeled subscripts, separated by @samp{.}. Some subscripts |
||||
@@ -132,7 +139,8 @@ subscript = label [index] |
||||
line = subscript *("." subscript) "=" value |
||||
@end smallexample |
||||
|
||||
-@subsection Dynamic Linker Diagnostics Values |
||||
+@node Dynamic Linker Diagnostics Values |
||||
+@subsubsection Dynamic Linker Diagnostics Values |
||||
|
||||
As mentioned above, the set of diagnostics may change between |
||||
@theglibc{} releases. Nevertheless, the following table documents a few |
@ -0,0 +1,144 @@
@@ -0,0 +1,144 @@
|
||||
commit f8d8b1b1e6d3b8b93f224efc796b7ea083fdb83f |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Mon Apr 8 16:48:55 2024 +0200 |
||||
|
||||
aarch64: Enhanced CPU diagnostics for ld.so |
||||
|
||||
This prints some information from struct cpu_features, and the midr_el1 |
||||
and dczid_el0 system register contents on every CPU. |
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> |
||||
|
||||
Modified for RHEL by: Patsy Griffin <patsy@redhat.com> |
||||
Diagnostics for the cpu_features mops and prefer_sve_ifuncs are not |
||||
currently supported on aarch64. |
||||
|
||||
diff -Nrup a/manual/dynlink.texi b/manual/dynlink.texi |
||||
--- a/manual/dynlink.texi 2024-05-31 20:55:08.238959456 -0400 |
||||
+++ b/manual/dynlink.texi 2024-05-31 20:55:41.298121623 -0400 |
||||
@@ -224,6 +224,40 @@ reflect adjustment by @theglibc{}. |
||||
These Linux-specific items show the values of @code{struct utsname}, as |
||||
reported by the @code{uname} function. @xref{Platform Type}. |
||||
|
||||
+@item aarch64.cpu_features.@dots{} |
||||
+These items are specific to the AArch64 architectures. They report data |
||||
+@theglibc{} uses to activate conditionally supported features such as |
||||
+BTI and MTE, and to select alternative function implementations. |
||||
+ |
||||
+@item aarch64.processor[@var{index}].@dots{} |
||||
+These are additional items for the AArch64 architecture and are |
||||
+described below. |
||||
+ |
||||
+@item aarch64.processor[@var{index}].requested=@var{kernel-cpu} |
||||
+The kernel is told to run the subsequent probing on the CPU numbered |
||||
+@var{kernel-cpu}. The values @var{kernel-cpu} and @var{index} can be |
||||
+distinct if there are gaps in the process CPU affinity mask. This line |
||||
+is not included if CPU affinity mask information is not available. |
||||
+ |
||||
+@item aarch64.processor[@var{index}].observed=@var{kernel-cpu} |
||||
+This line reports the kernel CPU number @var{kernel-cpu} on which the |
||||
+probing code initially ran. If the CPU number cannot be obtained, |
||||
+this line is not printed. |
||||
+ |
||||
+@item aarch64.processor[@var{index}].observed_node=@var{node} |
||||
+This reports the observed NUMA node number, as reported by the |
||||
+@code{getcpu} system call. If this information cannot be obtained, this |
||||
+line is not printed. |
||||
+ |
||||
+@item aarch64.processor[@var{index}].midr_el1=@var{value} |
||||
+The value of the @code{midr_el1} system register on the processor |
||||
+@var{index}. This line is only printed if the kernel indicates that |
||||
+this system register is supported. |
||||
+ |
||||
+@item aarch64.processor[@var{index}].dczid_el0=@var{value} |
||||
+The value of the @code{dczid_el0} system register on the processor |
||||
+@var{index}. |
||||
+ |
||||
@cindex CPUID (diagnostics) |
||||
@item x86.cpu_features.@dots{} |
||||
These items are specific to the i386 and x86-64 architectures. They |
||||
diff -Nrup a/sysdeps/aarch64/dl-diagnostics-cpu.c b/sysdeps/aarch64/dl-diagnostics-cpu.c |
||||
--- a/sysdeps/aarch64/dl-diagnostics-cpu.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/sysdeps/aarch64/dl-diagnostics-cpu.c 2024-05-31 20:57:23.536623129 -0400 |
||||
@@ -0,0 +1,81 @@ |
||||
+/* Print CPU diagnostics data in ld.so. AArch64 version. |
||||
+ Copyright (C) 2021-2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <dl-diagnostics.h> |
||||
+ |
||||
+#include <cpu-features.h> |
||||
+#include <dl-iterate_cpu.h> |
||||
+#include <ldsodefs.h> |
||||
+#include <sys/auxv.h> |
||||
+ |
||||
+static void |
||||
+print_cpu_features_value (const char *label, uint64_t value) |
||||
+{ |
||||
+ _dl_printf ("aarch64.cpu_features."); |
||||
+ _dl_diagnostics_print_labeled_value (label, value); |
||||
+} |
||||
+ |
||||
+static void |
||||
+print_per_cpu_value (const struct dl_iterate_cpu *dic, |
||||
+ const char *label, uint64_t value) |
||||
+{ |
||||
+ _dl_printf ("aarch64.processor[0x%x].", dic->processor_index); |
||||
+ _dl_diagnostics_print_labeled_value (label, value); |
||||
+} |
||||
+ |
||||
+void |
||||
+_dl_diagnostics_cpu (void) |
||||
+{ |
||||
+ print_cpu_features_value ("bti", GLRO (dl_aarch64_cpu_features).bti); |
||||
+ print_cpu_features_value ("midr_el1", |
||||
+ GLRO (dl_aarch64_cpu_features).midr_el1); |
||||
+ print_cpu_features_value ("mte_state", |
||||
+ GLRO (dl_aarch64_cpu_features).mte_state); |
||||
+ print_cpu_features_value ("sve", GLRO (dl_aarch64_cpu_features).sve); |
||||
+ print_cpu_features_value ("zva_size", |
||||
+ GLRO (dl_aarch64_cpu_features).zva_size); |
||||
+ |
||||
+ struct dl_iterate_cpu dic; |
||||
+ _dl_iterate_cpu_init (&dic); |
||||
+ |
||||
+ while (_dl_iterate_cpu_next (&dic)) |
||||
+ { |
||||
+ if (dic.requested_cpu >= 0) |
||||
+ _dl_printf ("aarch64.processor[0x%x].requested=0x%x\n", |
||||
+ dic.processor_index, dic.requested_cpu); |
||||
+ if (dic.actual_cpu >= 0) |
||||
+ _dl_printf ("aarch64.processor[0x%x].observed=0x%x\n", |
||||
+ dic.processor_index, dic.actual_cpu); |
||||
+ if (dic.actual_node >= 0) |
||||
+ _dl_printf ("aarch64.processor[0x%x].observed_node=0x%x\n", |
||||
+ dic.processor_index, dic.actual_node); |
||||
+ |
||||
+ if (GLRO (dl_hwcap) & HWCAP_CPUID) |
||||
+ { |
||||
+ uint64_t midr_el1; |
||||
+ asm ("mrs %0, midr_el1" : "=r" (midr_el1)); |
||||
+ print_per_cpu_value (&dic, "midr_el1", midr_el1); |
||||
+ } |
||||
+ |
||||
+ { |
||||
+ uint64_t dczid_el0; |
||||
+ asm ("mrs %0, dczid_el0" : "=r" (dczid_el0)); |
||||
+ print_per_cpu_value (&dic, "dczid_el0", dczid_el0); |
||||
+ } |
||||
+ } |
||||
+} |
@ -0,0 +1,510 @@
@@ -0,0 +1,510 @@
|
||||
commit 7a430f40c46acfa7ce4c3bff193b278c190b2efc |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Mon Apr 8 16:48:55 2024 +0200 |
||||
|
||||
x86: Add generic CPUID data dumper to ld.so --list-diagnostics |
||||
|
||||
This is surprisingly difficult to implement if the goal is to produce |
||||
reasonably sized output. With the current approaches to output |
||||
compression (suppressing zeros and repeated results between CPUs, |
||||
folding ranges of identical subleaves, dealing with the %ecx |
||||
reflection issue), the output is less than 600 KiB even for systems |
||||
with 256 logical CPUs. |
||||
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
|
||||
diff -Nrup a/manual/dynlink.texi b/manual/dynlink.texi |
||||
--- a/manual/dynlink.texi 2024-06-03 08:42:17.011026573 -0400 |
||||
+++ b/manual/dynlink.texi 2024-06-03 08:55:18.607771972 -0400 |
||||
@@ -262,7 +262,90 @@ The value of the @code{dczid_el0} system |
||||
@item x86.cpu_features.@dots{} |
||||
These items are specific to the i386 and x86-64 architectures. They |
||||
reflect supported CPU features and information on cache geometry, mostly |
||||
-collected using the @code{CPUID} instruction. |
||||
+collected using the CPUID instruction. |
||||
+ |
||||
+@item x86.processor[@var{index}].@dots{} |
||||
+These are additional items for the i386 and x86-64 architectures, as |
||||
+described below. They mostly contain raw data from the CPUID |
||||
+instruction. The probes are performed for each active CPU for the |
||||
+@code{ld.so} process, and data for different probed CPUs receives a |
||||
+uniqe @var{index} value. Some CPUID data is expected to differ from CPU |
||||
+core to CPU core. In some cases, CPUs are not correctly initialized and |
||||
+indicate the presence of different feature sets. |
||||
+ |
||||
+@item x86.processor[@var{index}].requested=@var{kernel-cpu} |
||||
+The kernel is told to run the subsequent probing on the CPU numbered |
||||
+@var{kernel-cpu}. The values @var{kernel-cpu} and @var{index} can be |
||||
+distinct if there are gaps in the process CPU affinity mask. This line |
||||
+is not included if CPU affinity mask information is not available. |
||||
+ |
||||
+@item x86.processor[@var{index}].observed=@var{kernel-cpu} |
||||
+This line reports the kernel CPU number @var{kernel-cpu} on which the |
||||
+probing code initially ran. If the CPU number cannot be obtained, |
||||
+this line is not printed. |
||||
+ |
||||
+@item x86.processor[@var{index}].observed_node=@var{node} |
||||
+This reports the observed NUMA node number, as reported by the |
||||
+@code{getcpu} system call. If this information cannot be obtained, this |
||||
+line is not printed. |
||||
+ |
||||
+@item x86.processor[@var{index}].cpuid_leaves=@var{count} |
||||
+This line indicates that @var{count} distinct CPUID leaves were |
||||
+encountered. (This reflects internal @code{ld.so} storage space, it |
||||
+does not directly correspond to @code{CPUID} enumeration ranges.) |
||||
+ |
||||
+@item x86.processor[@var{index}].ecx_limit=@var{value} |
||||
+The CPUID data extraction code uses a brute-force approach to enumerate |
||||
+subleaves (see the @samp{.subleaf_eax} lines below). The last |
||||
+@code{%rcx} value used in a CPUID query on this probed CPU was |
||||
+@var{value}. |
||||
+ |
||||
+@item x86.processor[@var{index}].cpuid.eax[@var{query_eax}].eax=@var{eax} |
||||
+@itemx x86.processor[@var{index}].cpuid.eax[@var{query_eax}].ebx=@var{ebx} |
||||
+@itemx x86.processor[@var{index}].cpuid.eax[@var{query_eax}].ecx=@var{ecx} |
||||
+@itemx x86.processor[@var{index}].cpuid.eax[@var{query_eax}].edx=@var{edx} |
||||
+These lines report the register contents after executing the CPUID |
||||
+instruction with @samp{%rax == @var{query_eax}} and @samp{%rcx == 0} (a |
||||
+@dfn{leaf}). For the first probed CPU (with a zero @var{index}), only |
||||
+leaves with non-zero register contents are reported. For subsequent |
||||
+CPUs, only leaves whose register contents differs from the previously |
||||
+probed CPUs (with @var{index} one less) are reported. |
||||
+ |
||||
+Basic and extended leaves are reported using the same syntax. This |
||||
+means there is a large jump in @var{query_eax} for the first reported |
||||
+extended leaf. |
||||
+ |
||||
+@item x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].eax=@var{eax} |
||||
+@itemx x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].ebx=@var{ebx} |
||||
+@itemx x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].ecx=@var{ecx} |
||||
+@itemx x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].edx=@var{edx} |
||||
+This is similar to the leaves above, but for a @dfn{subleaf}. For |
||||
+subleaves, the CPUID instruction is executed with @samp{%rax == |
||||
+@var{query_eax}} and @samp{%rcx == @var{query_ecx}}, so the result |
||||
+depends on both register values. The same rules about filtering zero |
||||
+and identical results apply. |
||||
+ |
||||
+@item x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].until_ecx=@var{ecx_limit} |
||||
+Some CPUID results are the same regardless the @var{query_ecx} value. |
||||
+If this situation is detected, a line with the @samp{.until_ecx} |
||||
+selector ins included, and this indicates that the CPUID register |
||||
+contents is the same for @code{%rcx} values between @var{query_ecx} |
||||
+and @var{ecx_limit} (inclusive). |
||||
+ |
||||
+@item x86.processor[@var{index}].cpuid.subleaf_eax[@var{query_eax}].ecx[@var{query_ecx}].ecx_query_mask=0xff |
||||
+This line indicates that in an @samp{.until_ecx} range, the CPUID |
||||
+instruction preserved the lowested 8 bits of the input @code{%rcx} in |
||||
+the output @code{%rcx} registers. Otherwise, the subleaves in the range |
||||
+have identical values. This special treatment is necessary to report |
||||
+compact range information in case such copying occurs (because the |
||||
+subleaves would otherwise be all different). |
||||
+ |
||||
+@item x86.processor[@var{index}].xgetbv.ecx[@var{query_ecx}]=@var{result} |
||||
+This line shows the 64-bit @var{result} value in the @code{%rdx:%rax} |
||||
+register pair after executing the XGETBV instruction with @code{%rcx} |
||||
+set to @var{query_ecx}. Zero values and values matching the previously |
||||
+probed CPU are omitted. Nothing is printed if the system does not |
||||
+support the XGETBV instruction. |
||||
@end table |
||||
|
||||
@node Dynamic Linker Introspection |
||||
diff -Nrup a/sysdeps/x86/dl-diagnostics-cpu.c b/sysdeps/x86/dl-diagnostics-cpu.c |
||||
--- a/sysdeps/x86/dl-diagnostics-cpu.c 2024-06-03 08:42:16.825025689 -0400 |
||||
+++ b/sysdeps/x86/dl-diagnostics-cpu.c 2024-06-03 09:49:47.528510916 -0400 |
||||
@@ -17,7 +17,18 @@ |
||||
<https://www.gnu.org/licenses/>. */ |
||||
|
||||
#include <dl-diagnostics.h> |
||||
+ |
||||
+#include <array_length.h> |
||||
+#include <cpu-features.h> |
||||
+#include <cpuid.h> |
||||
+#include <dl-iterate_cpu.h> |
||||
#include <ldsodefs.h> |
||||
+#include <stdbool.h> |
||||
+#include <string.h> |
||||
+#include <sysdep.h> |
||||
+ |
||||
+/* The generic CPUID dumping code. */ |
||||
+static void _dl_diagnostics_cpuid (void); |
||||
|
||||
static void |
||||
print_cpu_features_value (const char *label, uint64_t value) |
||||
@@ -119,4 +130,377 @@ _dl_diagnostics_cpu (void) |
||||
"last cpu_features field has been printed"); |
||||
print_cpu_features_value ("cachesize_non_temporal_divisor", |
||||
__rtld_global_ro_cachesize_non_temporal_divisor); |
||||
+ |
||||
+ _dl_diagnostics_cpuid (); |
||||
+} |
||||
+ |
||||
+/* The following code implements a generic CPUID dumper that tries to |
||||
+ gather CPUID data without knowing about CPUID implementation |
||||
+ details. */ |
||||
+ |
||||
+/* Register arguments to CPUID. Multiple ECX subleaf values yielding |
||||
+ the same result are combined, to shorten the output. Both |
||||
+ identical matches (EAX to EDX are the same) and matches where EAX, |
||||
+ EBX, EDX, and ECX are equal except in the lower byte, which must |
||||
+ match the query ECX value. The latter is needed to compress ranges |
||||
+ on CPUs which preserve the lowest byte in ECX if an unknown leaf is |
||||
+ queried. */ |
||||
+struct cpuid_query |
||||
+{ |
||||
+ unsigned int eax; |
||||
+ unsigned ecx_first; |
||||
+ unsigned ecx_last; |
||||
+ bool ecx_preserves_query_byte; |
||||
+}; |
||||
+ |
||||
+/* Single integer value that can be used for sorting/ordering |
||||
+ comparisons. Uses Q->eax and Q->ecx_first only because ecx_last is |
||||
+ always greater than the previous ecx_first value and less than the |
||||
+ subsequent one. */ |
||||
+static inline unsigned long long int |
||||
+cpuid_query_combined (struct cpuid_query *q) |
||||
+{ |
||||
+ /* ecx can be -1 (that is, ~0U). If this happens, this the only ecx |
||||
+ value for this eax value, so the ordering does not matter. */ |
||||
+ return ((unsigned long long int) q->eax << 32) | (unsigned int) q->ecx_first; |
||||
+}; |
||||
+ |
||||
+/* Used for differential reporting of zero/non-zero values. */ |
||||
+static const struct cpuid_registers cpuid_registers_zero; |
||||
+ |
||||
+/* Register arguments to CPUID paired with the results that came back. */ |
||||
+struct cpuid_query_result |
||||
+{ |
||||
+ struct cpuid_query q; |
||||
+ struct cpuid_registers r; |
||||
+}; |
||||
+ |
||||
+/* During a first enumeration pass, we try to collect data for |
||||
+ cpuid_initial_subleaf_limit subleaves per leaf/EAX value. If we run |
||||
+ out of space, we try once more with applying the lower limit. */ |
||||
+enum { cpuid_main_leaf_limit = 128 }; |
||||
+enum { cpuid_initial_subleaf_limit = 512 }; |
||||
+enum { cpuid_subleaf_limit = 32 }; |
||||
+ |
||||
+/* Offset of the extended leaf area. */ |
||||
+enum {cpuid_extended_leaf_offset = 0x80000000 }; |
||||
+ |
||||
+/* Collected CPUID data. Everything is stored in a statically sized |
||||
+ array that is sized so that the second pass will collect some data |
||||
+ for all leaves, after the limit is applied. On the second pass, |
||||
+ ecx_limit is set to cpuid_subleaf_limit. */ |
||||
+struct cpuid_collected_data |
||||
+{ |
||||
+ unsigned int used; |
||||
+ unsigned int ecx_limit; |
||||
+ uint64_t xgetbv_ecx_0; |
||||
+ struct cpuid_query_result qr[cpuid_main_leaf_limit |
||||
+ * 2 * cpuid_subleaf_limit]; |
||||
+}; |
||||
+ |
||||
+/* Fill in the result of a CPUID query. Returns true if there is |
||||
+ room, false if nothing could be stored. */ |
||||
+static bool |
||||
+_dl_diagnostics_cpuid_store (struct cpuid_collected_data *ccd, |
||||
+ unsigned eax, int ecx) |
||||
+{ |
||||
+ if (ccd->used >= array_length (ccd->qr)) |
||||
+ return false; |
||||
+ |
||||
+ /* Tentatively fill in the next value. */ |
||||
+ __cpuid_count (eax, ecx, |
||||
+ ccd->qr[ccd->used].r.eax, |
||||
+ ccd->qr[ccd->used].r.ebx, |
||||
+ ccd->qr[ccd->used].r.ecx, |
||||
+ ccd->qr[ccd->used].r.edx); |
||||
+ |
||||
+ /* If the ECX subleaf is next subleaf after the previous one (for |
||||
+ the same leaf), and the values are the same, merge the result |
||||
+ with the already-stored one. Do this before skipping zero |
||||
+ leaves, which avoids artifiacts for ECX == 256 queries. */ |
||||
+ if (ccd->used > 0 |
||||
+ && ccd->qr[ccd->used - 1].q.eax == eax |
||||
+ && ccd->qr[ccd->used - 1].q.ecx_last + 1 == ecx) |
||||
+ { |
||||
+ /* Exact match of the previous result. Ignore the value of |
||||
+ ecx_preserves_query_byte if this is a singleton range so far |
||||
+ because we can treat ECX as fixed if the same value repeats. */ |
||||
+ if ((!ccd->qr[ccd->used - 1].q.ecx_preserves_query_byte |
||||
+ || (ccd->qr[ccd->used - 1].q.ecx_first |
||||
+ == ccd->qr[ccd->used - 1].q.ecx_last)) |
||||
+ && memcmp (&ccd->qr[ccd->used - 1].r, &ccd->qr[ccd->used].r, |
||||
+ sizeof (ccd->qr[ccd->used].r)) == 0) |
||||
+ { |
||||
+ ccd->qr[ccd->used - 1].q.ecx_last = ecx; |
||||
+ /* ECX is now fixed because the same value has been observed |
||||
+ twice, even if we had a low-byte match before. */ |
||||
+ ccd->qr[ccd->used - 1].q.ecx_preserves_query_byte = false; |
||||
+ return true; |
||||
+ } |
||||
+ /* Match except for the low byte in ECX, which must match the |
||||
+ incoming ECX value. */ |
||||
+ if (ccd->qr[ccd->used - 1].q.ecx_preserves_query_byte |
||||
+ && (ecx & 0xff) == (ccd->qr[ccd->used].r.ecx & 0xff) |
||||
+ && ccd->qr[ccd->used].r.eax == ccd->qr[ccd->used - 1].r.eax |
||||
+ && ccd->qr[ccd->used].r.ebx == ccd->qr[ccd->used - 1].r.ebx |
||||
+ && ((ccd->qr[ccd->used].r.ecx & 0xffffff00) |
||||
+ == (ccd->qr[ccd->used - 1].r.ecx & 0xffffff00)) |
||||
+ && ccd->qr[ccd->used].r.edx == ccd->qr[ccd->used - 1].r.edx) |
||||
+ { |
||||
+ ccd->qr[ccd->used - 1].q.ecx_last = ecx; |
||||
+ return true; |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ /* Do not store zero results. All-zero values usually mean that the |
||||
+ subleaf is unsupported. */ |
||||
+ if (ccd->qr[ccd->used].r.eax == 0 |
||||
+ && ccd->qr[ccd->used].r.ebx == 0 |
||||
+ && ccd->qr[ccd->used].r.ecx == 0 |
||||
+ && ccd->qr[ccd->used].r.edx == 0) |
||||
+ return true; |
||||
+ |
||||
+ /* The result needs to be stored. Fill in the query parameters and |
||||
+ consume the storage. */ |
||||
+ ccd->qr[ccd->used].q.eax = eax; |
||||
+ ccd->qr[ccd->used].q.ecx_first = ecx; |
||||
+ ccd->qr[ccd->used].q.ecx_last = ecx; |
||||
+ ccd->qr[ccd->used].q.ecx_preserves_query_byte |
||||
+ = (ecx & 0xff) == (ccd->qr[ccd->used].r.ecx & 0xff); |
||||
+ ++ccd->used; |
||||
+ return true; |
||||
+} |
||||
+ |
||||
+/* Collected CPUID data into *CCD. If LIMIT, apply per-leaf limits to |
||||
+ avoid exceeding the pre-allocated space. Return true if all data |
||||
+ could be stored, false if the retrying without a limit is |
||||
+ requested. */ |
||||
+static bool |
||||
+_dl_diagnostics_cpuid_collect_1 (struct cpuid_collected_data *ccd, bool limit) |
||||
+{ |
||||
+ ccd->used = 0; |
||||
+ ccd->ecx_limit |
||||
+ = (limit ? cpuid_subleaf_limit : cpuid_initial_subleaf_limit) - 1; |
||||
+ _dl_diagnostics_cpuid_store (ccd, 0x00, 0x00); |
||||
+ if (ccd->used == 0) |
||||
+ /* CPUID reported all 0. Should not happen. */ |
||||
+ return true; |
||||
+ unsigned int maximum_leaf = ccd->qr[0x00].r.eax; |
||||
+ if (limit && maximum_leaf >= cpuid_main_leaf_limit) |
||||
+ maximum_leaf = cpuid_main_leaf_limit - 1; |
||||
+ |
||||
+ for (unsigned int eax = 1; eax <= maximum_leaf; ++eax) |
||||
+ { |
||||
+ for (unsigned int ecx = 0; ecx <= ccd->ecx_limit; ++ecx) |
||||
+ if (!_dl_diagnostics_cpuid_store (ccd, eax, ecx)) |
||||
+ return false; |
||||
+ } |
||||
+ |
||||
+ if (!_dl_diagnostics_cpuid_store (ccd, cpuid_extended_leaf_offset, 0x00)) |
||||
+ return false; |
||||
+ maximum_leaf = ccd->qr[ccd->used - 1].r.eax; |
||||
+ if (maximum_leaf < cpuid_extended_leaf_offset) |
||||
+ /* No extended CPUID information. */ |
||||
+ return true; |
||||
+ if (limit |
||||
+ && maximum_leaf - cpuid_extended_leaf_offset >= cpuid_main_leaf_limit) |
||||
+ maximum_leaf = cpuid_extended_leaf_offset + cpuid_main_leaf_limit - 1; |
||||
+ for (unsigned int eax = cpuid_extended_leaf_offset + 1; |
||||
+ eax <= maximum_leaf; ++eax) |
||||
+ { |
||||
+ for (unsigned int ecx = 0; ecx <= ccd->ecx_limit; ++ecx) |
||||
+ if (!_dl_diagnostics_cpuid_store (ccd, eax, ecx)) |
||||
+ return false; |
||||
+ } |
||||
+ return true; |
||||
+} |
||||
+ |
||||
+/* Call _dl_diagnostics_cpuid_collect_1 twice if necessary, the |
||||
+ second time with the limit applied. */ |
||||
+static void |
||||
+_dl_diagnostics_cpuid_collect (struct cpuid_collected_data *ccd) |
||||
+{ |
||||
+ if (!_dl_diagnostics_cpuid_collect_1 (ccd, false)) |
||||
+ _dl_diagnostics_cpuid_collect_1 (ccd, true); |
||||
+ |
||||
+ /* Re-use the result of the official feature probing here. */ |
||||
+ const struct cpu_features *cpu_features = __get_cpu_features (); |
||||
+ if (CPU_FEATURES_CPU_P (cpu_features, OSXSAVE)) |
||||
+ { |
||||
+ unsigned int xcrlow; |
||||
+ unsigned int xcrhigh; |
||||
+ asm ("xgetbv" : "=a" (xcrlow), "=d" (xcrhigh) : "c" (0)); |
||||
+ ccd->xgetbv_ecx_0 = ((uint64_t) xcrhigh << 32) + xcrlow; |
||||
+ } |
||||
+ else |
||||
+ ccd->xgetbv_ecx_0 = 0; |
||||
+} |
||||
+ |
||||
+/* Print a CPUID register value (passed as REG_VALUE) if it differs |
||||
+ from the expected REG_REFERENCE value. PROCESSOR_INDEX is the |
||||
+ process sequence number (always starting at zero; not a kernel ID). */ |
||||
+static void |
||||
+_dl_diagnostics_cpuid_print_reg (unsigned int processor_index, |
||||
+ const struct cpuid_query *q, |
||||
+ const char *reg_label, unsigned int reg_value, |
||||
+ bool subleaf) |
||||
+{ |
||||
+ if (subleaf) |
||||
+ _dl_printf ("x86.processor[0x%x].cpuid.subleaf_eax[0x%x]" |
||||
+ ".ecx[0x%x].%s=0x%x\n", |
||||
+ processor_index, q->eax, q->ecx_first, reg_label, reg_value); |
||||
+ else |
||||
+ _dl_printf ("x86.processor[0x%x].cpuid.eax[0x%x].%s=0x%x\n", |
||||
+ processor_index, q->eax, reg_label, reg_value); |
||||
+} |
||||
+ |
||||
+/* Print CPUID result values in *RESULT for the query in |
||||
+ CCD->qr[CCD_IDX]. PROCESSOR_INDEX is the process sequence number |
||||
+ (always starting at zero; not a kernel ID). */ |
||||
+static void |
||||
+_dl_diagnostics_cpuid_print_query (unsigned int processor_index, |
||||
+ struct cpuid_collected_data *ccd, |
||||
+ unsigned int ccd_idx, |
||||
+ const struct cpuid_registers *result) |
||||
+{ |
||||
+ /* Treat this as a value if subleaves if ecx isn't zero (maybe |
||||
+ within the [ecx_fist, ecx_last] range), or if eax matches its |
||||
+ neighbors. If the range is [0, ecx_limit], then the subleaves |
||||
+ are not distinct (independently of ecx_preserves_query_byte), |
||||
+ so do not report them separately. */ |
||||
+ struct cpuid_query *q = &ccd->qr[ccd_idx].q; |
||||
+ bool subleaf = (q->ecx_first > 0 |
||||
+ || (q->ecx_first != q->ecx_last |
||||
+ && !(q->ecx_first == 0 && q->ecx_last == ccd->ecx_limit)) |
||||
+ || (ccd_idx > 0 && q->eax == ccd->qr[ccd_idx - 1].q.eax) |
||||
+ || (ccd_idx + 1 < ccd->used |
||||
+ && q->eax == ccd->qr[ccd_idx + 1].q.eax)); |
||||
+ _dl_diagnostics_cpuid_print_reg (processor_index, q, "eax", result->eax, |
||||
+ subleaf); |
||||
+ _dl_diagnostics_cpuid_print_reg (processor_index, q, "ebx", result->ebx, |
||||
+ subleaf); |
||||
+ _dl_diagnostics_cpuid_print_reg (processor_index, q, "ecx", result->ecx, |
||||
+ subleaf); |
||||
+ _dl_diagnostics_cpuid_print_reg (processor_index, q, "edx", result->edx, |
||||
+ subleaf); |
||||
+ |
||||
+ if (subleaf && q->ecx_first != q->ecx_last) |
||||
+ { |
||||
+ _dl_printf ("x86.processor[0x%x].cpuid.subleaf_eax[0x%x]" |
||||
+ ".ecx[0x%x].until_ecx=0x%x\n", |
||||
+ processor_index, q->eax, q->ecx_first, q->ecx_last); |
||||
+ if (q->ecx_preserves_query_byte) |
||||
+ _dl_printf ("x86.processor[0x%x].cpuid.subleaf_eax[0x%x]" |
||||
+ ".ecx[0x%x].ecx_query_mask=0xff\n", |
||||
+ processor_index, q->eax, q->ecx_first); |
||||
+ } |
||||
+} |
||||
+ |
||||
+/* Perform differential reporting of the data in *CURRENT against |
||||
+ *BASE. REQUESTED_CPU is the kernel CPU ID the thread was |
||||
+ configured to run on, or -1 if no configuration was possible. |
||||
+ PROCESSOR_INDEX is the process sequence number (always starting at |
||||
+ zero; not a kernel ID). */ |
||||
+static void |
||||
+_dl_diagnostics_cpuid_report (struct dl_iterate_cpu *dci, |
||||
+ struct cpuid_collected_data *current, |
||||
+ struct cpuid_collected_data *base) |
||||
+{ |
||||
+ if (dci->requested_cpu >= 0) |
||||
+ _dl_printf ("x86.processor[0x%x].requested=0x%x\n", |
||||
+ dci->processor_index, dci->requested_cpu); |
||||
+ if (dci->actual_cpu >= 0) |
||||
+ _dl_printf ("x86.processor[0x%x].observed=0x%x\n", |
||||
+ dci->processor_index, dci->actual_cpu); |
||||
+ if (dci->actual_node >= 0) |
||||
+ _dl_printf ("x86.processor[0x%x].observed_node=0x%x\n", |
||||
+ dci->processor_index, dci->actual_node); |
||||
+ |
||||
+ _dl_printf ("x86.processor[0x%x].cpuid_leaves=0x%x\n", |
||||
+ dci->processor_index, current->used); |
||||
+ _dl_printf ("x86.processor[0x%x].ecx_limit=0x%x\n", |
||||
+ dci->processor_index, current->ecx_limit); |
||||
+ |
||||
+ unsigned int base_idx = 0; |
||||
+ for (unsigned int current_idx = 0; current_idx < current->used; |
||||
+ ++current_idx) |
||||
+ { |
||||
+ /* Report missing data on the current CPU as 0. */ |
||||
+ unsigned long long int current_query |
||||
+ = cpuid_query_combined (¤t->qr[current_idx].q); |
||||
+ while (base_idx < base->used |
||||
+ && cpuid_query_combined (&base->qr[base_idx].q) < current_query) |
||||
+ { |
||||
+ _dl_diagnostics_cpuid_print_query (dci->processor_index, |
||||
+ base, base_idx, |
||||
+ &cpuid_registers_zero); |
||||
+ ++base_idx; |
||||
+ } |
||||
+ |
||||
+ if (base_idx < base->used |
||||
+ && cpuid_query_combined (&base->qr[base_idx].q) == current_query) |
||||
+ { |
||||
+ _Static_assert (sizeof (struct cpuid_registers) == 4 * 4, |
||||
+ "no padding in struct cpuid_registers"); |
||||
+ if (current->qr[current_idx].q.ecx_last |
||||
+ != base->qr[base_idx].q.ecx_last |
||||
+ || memcmp (¤t->qr[current_idx].r, |
||||
+ &base->qr[base_idx].r, |
||||
+ sizeof (struct cpuid_registers)) != 0) |
||||
+ /* The ECX range or the values have changed. Show the |
||||
+ new values. */ |
||||
+ _dl_diagnostics_cpuid_print_query (dci->processor_index, |
||||
+ current, current_idx, |
||||
+ ¤t->qr[current_idx].r); |
||||
+ ++base_idx; |
||||
+ } |
||||
+ else |
||||
+ /* Data is absent in the base reference. Report the new data. */ |
||||
+ _dl_diagnostics_cpuid_print_query (dci->processor_index, |
||||
+ current, current_idx, |
||||
+ ¤t->qr[current_idx].r); |
||||
+ } |
||||
+ |
||||
+ if (current->xgetbv_ecx_0 != base->xgetbv_ecx_0) |
||||
+ { |
||||
+ /* Re-use the 64-bit printing routine. */ |
||||
+ _dl_printf ("x86.processor[0x%x].", dci->processor_index); |
||||
+ _dl_diagnostics_print_labeled_value ("xgetbv.ecx[0x0]", |
||||
+ current->xgetbv_ecx_0); |
||||
+ } |
||||
+} |
||||
+ |
||||
+static void |
||||
+_dl_diagnostics_cpuid (void) |
||||
+{ |
||||
+#if !HAS_CPUID |
||||
+ /* CPUID is not supported, so there is nothing to dump. */ |
||||
+ if (__get_cpuid_max (0, 0) == 0) |
||||
+ return; |
||||
+#endif |
||||
+ |
||||
+ struct dl_iterate_cpu dic; |
||||
+ _dl_iterate_cpu_init (&dic); |
||||
+ |
||||
+ /* Two copies of the data are used. Data is written to the index |
||||
+ (dic.processor_index & 1). The previous version against which the |
||||
+ data dump is reported is at index !(processor_index & 1). */ |
||||
+ struct cpuid_collected_data ccd[2]; |
||||
+ |
||||
+ /* The initial data is presumed to be all zero. Zero results are |
||||
+ not recorded. */ |
||||
+ ccd[1].used = 0; |
||||
+ ccd[1].xgetbv_ecx_0 = 0; |
||||
+ |
||||
+ /* Run the CPUID probing on a specific CPU. There are expected |
||||
+ differences for encoding core IDs and topology information in |
||||
+ CPUID output, but some firmware/kernel bugs also may result in |
||||
+ asymmetric data across CPUs in some cases. */ |
||||
+ while (_dl_iterate_cpu_next (&dic)) |
||||
+ { |
||||
+ _dl_diagnostics_cpuid_collect (&ccd[dic.processor_index & 1]); |
||||
+ _dl_diagnostics_cpuid_report |
||||
+ (&dic, &ccd[dic.processor_index & 1], |
||||
+ &ccd[!(dic.processor_index & 1)]); |
||||
+ } |
||||
} |
@ -0,0 +1,262 @@
@@ -0,0 +1,262 @@
|
||||
commit 5653ccd847f0cd3a98906e44c97c71d68652d326 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Mon Apr 8 16:48:55 2024 +0200 |
||||
|
||||
elf: Add CPU iteration support for future use in ld.so diagnostics |
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> |
||||
|
||||
diff --git a/elf/dl-iterate_cpu.h b/elf/dl-iterate_cpu.h |
||||
new file mode 100644 |
||||
index 0000000000..60db167b13 |
||||
--- /dev/null |
||||
+++ b/elf/dl-iterate_cpu.h |
||||
@@ -0,0 +1,136 @@ |
||||
+/* Iterate over all CPUs, for CPU-specific diagnostics. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#ifndef DL_ITERATE_CPU_H |
||||
+#define DL_ITERATE_CPU_H |
||||
+ |
||||
+#include <dl-affinity.h> |
||||
+#include <stdbool.h> |
||||
+ |
||||
+struct dl_iterate_cpu |
||||
+{ |
||||
+ /* Sequential iteration count, starting at 0. */ |
||||
+ unsigned int processor_index; |
||||
+ |
||||
+ /* Requested CPU. Can be -1 if affinity could not be set. */ |
||||
+ int requested_cpu; |
||||
+ |
||||
+ /* Observed current CPU. -1 if unavailable. */ |
||||
+ int actual_cpu; |
||||
+ |
||||
+ /* Observed node ID for the CPU. -1 if unavailable. */ |
||||
+ int actual_node; |
||||
+ |
||||
+ /* Internal fields to implement the iteration. */ |
||||
+ |
||||
+ /* Affinity as obtained by _dl_iterate_cpu_init, using |
||||
+ _dl_getaffinity. Space for 8,192 CPUs. */ |
||||
+ unsigned long int mask_reference[8192 / sizeof (unsigned long int) / 8]; |
||||
+ |
||||
+ /* This array is used by _dl_setaffinity calls. */ |
||||
+ unsigned long int mask_request[8192 / sizeof (unsigned long int) / 8]; |
||||
+ |
||||
+ /* Return value from the initial _dl_getaffinity call. */ |
||||
+ int length_reference; |
||||
+}; |
||||
+ |
||||
+static void |
||||
+_dl_iterate_cpu_init (struct dl_iterate_cpu *dic) |
||||
+{ |
||||
+ dic->length_reference |
||||
+ = _dl_getaffinity (dic->mask_reference, sizeof (dic->mask_reference)); |
||||
+ /* Prepare for the first _dl_iterate_cpu_next call. */ |
||||
+ dic->processor_index = -1; |
||||
+ dic->requested_cpu = -1; |
||||
+} |
||||
+ |
||||
+static bool |
||||
+_dl_iterate_cpu_next (struct dl_iterate_cpu *dic) |
||||
+{ |
||||
+ ++dic->processor_index; |
||||
+ |
||||
+ if (dic->length_reference > 0) |
||||
+ { |
||||
+ /* Search for the next CPU to switch to. */ |
||||
+ while (true) |
||||
+ { |
||||
+ ++dic->requested_cpu; |
||||
+ |
||||
+ /* Array index and bit number within the array. */ |
||||
+ unsigned int long_index |
||||
+ = dic->requested_cpu / sizeof (unsigned long int) / 8; |
||||
+ unsigned int bit_index |
||||
+ = dic->requested_cpu % (sizeof (unsigned long int) * 8); |
||||
+ |
||||
+ if (long_index * sizeof (unsigned long int) >= dic->length_reference) |
||||
+ /* All possible CPUs have been covered. */ |
||||
+ return false; |
||||
+ |
||||
+ unsigned long int bit = 1UL << bit_index; |
||||
+ if (dic->mask_reference[long_index] & bit) |
||||
+ { |
||||
+ /* The CPU is available. Try to select it. */ |
||||
+ dic->mask_request[long_index] = bit; |
||||
+ if (_dl_setaffinity (dic->mask_request, |
||||
+ (long_index + 1) |
||||
+ * sizeof (unsigned long int)) < 0) |
||||
+ { |
||||
+ /* Record that we could not perform a CPU request. */ |
||||
+ dic->length_reference = -1; |
||||
+ |
||||
+ if (dic->processor_index > 0) |
||||
+ /* We already reported something. There is no need to |
||||
+ continue because the new data is probably not useful. */ |
||||
+ return false; |
||||
+ } |
||||
+ |
||||
+ /* Clear the bit in case the next iteration switches to the |
||||
+ next long value. */ |
||||
+ dic->mask_request[long_index] = 0; |
||||
+ |
||||
+ /* We found a CPU to run on. */ |
||||
+ break; |
||||
+ } |
||||
+ } |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ /* No way to set CPU affinity. Iterate just once. */ |
||||
+ if (dic->processor_index > 0) |
||||
+ return false; |
||||
+ } |
||||
+ |
||||
+ /* Fill in the actual CPU information. CPU pinning may not actually |
||||
+ be effective, depending on the container host. */ |
||||
+ unsigned int cpu, node; |
||||
+ if (_dl_getcpu (&cpu, &node) < 0) |
||||
+ { |
||||
+ /* No CPU information available. */ |
||||
+ dic->actual_cpu = -1; |
||||
+ dic->actual_node = -1; |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ dic->actual_cpu = cpu; |
||||
+ dic->actual_node = node; |
||||
+ } |
||||
+ |
||||
+ return true; |
||||
+} |
||||
+ |
||||
+#endif /* DL_ITERATE_CPU_H */ |
||||
diff --git a/sysdeps/generic/dl-affinity.h b/sysdeps/generic/dl-affinity.h |
||||
new file mode 100644 |
||||
index 0000000000..d117f737e9 |
||||
--- /dev/null |
||||
+++ b/sysdeps/generic/dl-affinity.h |
||||
@@ -0,0 +1,54 @@ |
||||
+/* CPU affinity handling for the dynamic linker. Stub version. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#ifndef DL_AFFINITY_H |
||||
+#define DL_AFFINITY_H |
||||
+ |
||||
+#include <errno.h> |
||||
+#include <stddef.h> |
||||
+ |
||||
+/* On success, write the current CPU ID to *CPU, and the current node |
||||
+ ID to *NODE, and return 0. Return a negative error code on |
||||
+ failure. */ |
||||
+static inline int |
||||
+_dl_getcpu (unsigned int *cpu, unsigned int *node) |
||||
+{ |
||||
+ return -ENOSYS; |
||||
+} |
||||
+ |
||||
+/* On success, write CPU ID affinity bits for the current thread to |
||||
+ *BITS, which must be SIZE bytes long, and return the number of |
||||
+ bytes updated, a multiple of sizeof (unsigned long int). On |
||||
+ failure, return a negative error code. */ |
||||
+static int |
||||
+_dl_getaffinity (unsigned long int *bits, size_t size) |
||||
+{ |
||||
+ return -ENOSYS; |
||||
+} |
||||
+ |
||||
+/* Set the CPU affinity mask for the current thread to *BITS, using |
||||
+ the SIZE bytes from that array, which should be a multiple of |
||||
+ sizeof (unsigned long int). Return 0 on success, and a negative |
||||
+ error code on failure. */ |
||||
+static int |
||||
+_dl_setaffinity (const unsigned long int *bits, size_t size) |
||||
+{ |
||||
+ return -ENOSYS; |
||||
+} |
||||
+ |
||||
+#endif /* DL_AFFINITY_H */ |
||||
diff --git a/sysdeps/unix/sysv/linux/dl-affinity.h b/sysdeps/unix/sysv/linux/dl-affinity.h |
||||
new file mode 100644 |
||||
index 0000000000..bbfede7750 |
||||
--- /dev/null |
||||
+++ b/sysdeps/unix/sysv/linux/dl-affinity.h |
||||
@@ -0,0 +1,46 @@ |
||||
+/* CPU affinity handling for the dynamic linker. Linux version. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+/* See sysdeps/generic/dl-affinity.h for documentation of these interfaces. */ |
||||
+ |
||||
+#ifndef DL_AFFINITY_H |
||||
+#define DL_AFFINITY_H |
||||
+ |
||||
+#include <sysdep.h> |
||||
+#include <stddef.h> |
||||
+#include <unistd.h> |
||||
+ |
||||
+static inline int |
||||
+_dl_getcpu (unsigned int *cpu, unsigned int *node) |
||||
+{ |
||||
+ return INTERNAL_SYSCALL_CALL (getcpu, cpu, node); |
||||
+} |
||||
+ |
||||
+static int |
||||
+_dl_getaffinity (unsigned long int *bits, size_t size) |
||||
+{ |
||||
+ return INTERNAL_SYSCALL_CALL (sched_getaffinity, /* TID */ 0, size, bits); |
||||
+} |
||||
+ |
||||
+static int |
||||
+_dl_setaffinity (const unsigned long int *bits, size_t size) |
||||
+{ |
||||
+ return INTERNAL_SYSCALL_CALL (sched_setaffinity, /* TID */ 0, size, bits); |
||||
+} |
||||
+ |
||||
+#endif /* DL_AFFINITY_H */ |
@ -0,0 +1,140 @@
@@ -0,0 +1,140 @@
|
||||
commit 6a04404521ac4119ae36827eeb288ea84eee7cf6 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Sat Feb 17 09:17:04 2024 +0100 |
||||
|
||||
Linux: Switch back to assembly syscall wrapper for prctl (bug 29770) |
||||
|
||||
Commit ff026950e280bc3e9487b41b460fb31bc5b57721 ("Add a C wrapper for |
||||
prctl [BZ #25896]") replaced the assembler wrapper with a C function. |
||||
However, on powerpc64le-linux-gnu, the C variadic function |
||||
implementation requires extra work in the caller to set up the |
||||
parameter save area. Calling a function that needs a parameter save |
||||
area without one (because the prototype used indicates the function is |
||||
not variadic) corrupts the caller's stack. The Linux manual pages |
||||
project documents prctl as a non-variadic function. This has resulted |
||||
in various projects over the years using non-variadic prototypes, |
||||
including the sanitizer libraries in LLVm and GCC (GCC PR 113728). |
||||
|
||||
This commit switches back to the assembler implementation on most |
||||
targets and only keeps the C implementation for x86-64 x32. |
||||
|
||||
Also add the __prctl_time64 alias from commit |
||||
b39ffab860cd743a82c91946619f1b8158b0b65e ("Linux: Add time64 alias for |
||||
prctl") to sysdeps/unix/sysv/linux/syscalls.list; it was not yet |
||||
present in commit ff026950e280bc3e9487b41b460fb31bc5b57721. |
||||
|
||||
This restores the old ABI on powerpc64le-linux-gnu, thus fixing |
||||
bug 29770. |
||||
|
||||
Reviewed-By: Simon Chopin <simon.chopin@canonical.com> |
||||
|
||||
Resolved conflicts: |
||||
sysdeps/unix/sysv/linux/syscalls.list |
||||
sysdeps/unix/sysv/linux/x86_64/x32/prctl.c |
||||
|
||||
diff -Nrup a/sysdeps/unix/sysv/linux/prctl.c b/sysdeps/unix/sysv/linux/prctl.c |
||||
--- a/sysdeps/unix/sysv/linux/prctl.c 2021-08-01 21:33:43.000000000 -0400 |
||||
+++ b/sysdeps/unix/sysv/linux/prctl.c 1969-12-31 19:00:00.000000000 -0500 |
||||
@@ -1,45 +0,0 @@ |
||||
-/* prctl - Linux specific syscall. |
||||
- Copyright (C) 2020-2021 Free Software Foundation, Inc. |
||||
- This file is part of the GNU C Library. |
||||
- |
||||
- The GNU C Library is free software; you can redistribute it and/or |
||||
- modify it under the terms of the GNU Lesser General Public |
||||
- License as published by the Free Software Foundation; either |
||||
- version 2.1 of the License, or (at your option) any later version. |
||||
- |
||||
- The GNU C Library is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
- Lesser General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Lesser General Public |
||||
- License along with the GNU C Library; if not, see |
||||
- <https://www.gnu.org/licenses/>. */ |
||||
- |
||||
-#include <sysdep.h> |
||||
-#include <stdarg.h> |
||||
-#include <sys/prctl.h> |
||||
- |
||||
-/* Unconditionally read all potential arguments. This may pass |
||||
- garbage values to the kernel, but avoids the need for teaching |
||||
- glibc the argument counts of individual options (including ones |
||||
- that are added to the kernel in the future). */ |
||||
- |
||||
-int |
||||
-__prctl (int option, ...) |
||||
-{ |
||||
- va_list arg; |
||||
- va_start (arg, option); |
||||
- unsigned long int arg2 = va_arg (arg, unsigned long int); |
||||
- unsigned long int arg3 = va_arg (arg, unsigned long int); |
||||
- unsigned long int arg4 = va_arg (arg, unsigned long int); |
||||
- unsigned long int arg5 = va_arg (arg, unsigned long int); |
||||
- va_end (arg); |
||||
- return INLINE_SYSCALL_CALL (prctl, option, arg2, arg3, arg4, arg5); |
||||
-} |
||||
- |
||||
-libc_hidden_def (__prctl) |
||||
-weak_alias (__prctl, prctl) |
||||
-#if __TIMESIZE != 64 |
||||
-weak_alias (__prctl, __prctl_time64) |
||||
-#endif |
||||
diff -Nrup a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list |
||||
--- a/sysdeps/unix/sysv/linux/syscalls.list 2021-08-01 21:33:43.000000000 -0400 |
||||
+++ b/sysdeps/unix/sysv/linux/syscalls.list 2024-02-27 14:33:01.594782897 -0500 |
||||
@@ -41,6 +41,7 @@ munlockall - munlockall i: munlockall |
||||
nfsservctl EXTRA nfsservctl i:ipp __compat_nfsservctl nfsservctl@GLIBC_2.0:GLIBC_2.28 |
||||
pipe - pipe i:f __pipe pipe |
||||
pipe2 - pipe2 i:fi __pipe2 pipe2 |
||||
+prctl EXTRA prctl i:iiiii __prctl prctl __prctl_time64 |
||||
pivot_root EXTRA pivot_root i:ss pivot_root |
||||
query_module EXTRA query_module i:sipip __compat_query_module query_module@GLIBC_2.0:GLIBC_2.23 |
||||
quotactl EXTRA quotactl i:isip quotactl |
||||
diff -Nrup a/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c b/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/prctl.c 2024-02-27 14:35:03.388602623 -0500 |
||||
@@ -0,0 +1,42 @@ |
||||
+/* prctl - Linux specific syscall. x86-64 x32 version. |
||||
+ Copyright (C) 2020-2021 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <sysdep.h> |
||||
+#include <stdarg.h> |
||||
+#include <sys/prctl.h> |
||||
+ |
||||
+/* Unconditionally read all potential arguments. This may pass |
||||
+ garbage values to the kernel, but avoids the need for teaching |
||||
+ glibc the argument counts of individual options (including ones |
||||
+ that are added to the kernel in the future). */ |
||||
+ |
||||
+int |
||||
+__prctl (int option, ...) |
||||
+{ |
||||
+ va_list arg; |
||||
+ va_start (arg, option); |
||||
+ unsigned long int arg2 = va_arg (arg, unsigned long int); |
||||
+ unsigned long int arg3 = va_arg (arg, unsigned long int); |
||||
+ unsigned long int arg4 = va_arg (arg, unsigned long int); |
||||
+ unsigned long int arg5 = va_arg (arg, unsigned long int); |
||||
+ va_end (arg); |
||||
+ return INLINE_SYSCALL_CALL (prctl, option, arg2, arg3, arg4, arg5); |
||||
+} |
||||
+ |
||||
+libc_hidden_def (__prctl) |
||||
+weak_alias (__prctl, prctl) |
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
From dfb05f8e704edac70db38c4c8ee700769d91a413 Mon Sep 17 00:00:00 2001 |
||||
From: "H.J. Lu" <hjl.tools@gmail.com> |
||||
Date: Fri, 16 Feb 2024 07:17:10 -0800 |
||||
Subject: [PATCH] x86-64: Save APX registers in ld.so trampoline |
||||
Content-type: text/plain; charset=UTF-8 |
||||
|
||||
Add APX registers to STATE_SAVE_MASK so that APX registers are saved in |
||||
ld.so trampoline. This fixes BZ #31371. |
||||
|
||||
Also update STATE_SAVE_OFFSET and STATE_SAVE_MASK for i386 which will |
||||
be used by i386 _dl_tlsdesc_dynamic. |
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
|
||||
Conflicts: |
||||
sysdeps/x86/sysdep.h |
||||
(rebased for context and line numbers) |
||||
--- |
||||
sysdeps/x86/sysdep.h | 52 +++++++++++++++++++++++++++++++++++++++----- |
||||
1 file changed, 46 insertions(+), 6 deletions(-) |
||||
|
||||
diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h |
||||
index 85d0a8c943..837fd28734 100644 |
||||
--- a/sysdeps/x86/sysdep.h |
||||
+++ b/sysdeps/x86/sysdep.h |
||||
@@ -48,14 +48,54 @@ |
||||
# define SHSTK_ENABLED 0 |
||||
#endif |
||||
|
||||
+/* The extended state feature IDs in the state component bitmap. */ |
||||
+#define X86_XSTATE_X87_ID 0 |
||||
+#define X86_XSTATE_SSE_ID 1 |
||||
+#define X86_XSTATE_AVX_ID 2 |
||||
+#define X86_XSTATE_BNDREGS_ID 3 |
||||
+#define X86_XSTATE_BNDCFG_ID 4 |
||||
+#define X86_XSTATE_K_ID 5 |
||||
+#define X86_XSTATE_ZMM_H_ID 6 |
||||
+#define X86_XSTATE_ZMM_ID 7 |
||||
+#define X86_XSTATE_PKRU_ID 9 |
||||
+#define X86_XSTATE_TILECFG_ID 17 |
||||
+#define X86_XSTATE_TILEDATA_ID 18 |
||||
+#define X86_XSTATE_APX_F_ID 19 |
||||
+ |
||||
+#ifdef __x86_64__ |
||||
/* Offset for fxsave/xsave area used by _dl_runtime_resolve. Also need |
||||
space to preserve RCX, RDX, RSI, RDI, R8, R9 and RAX. It must be |
||||
- aligned to 16 bytes for fxsave and 64 bytes for xsave. */ |
||||
-#define STATE_SAVE_OFFSET (8 * 7 + 8) |
||||
- |
||||
-/* Save SSE, AVX, AVX512, mask and bound registers. */ |
||||
-#define STATE_SAVE_MASK \ |
||||
- ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7)) |
||||
+ aligned to 16 bytes for fxsave and 64 bytes for xsave. |
||||
+ |
||||
+ NB: Is is non-zero because of the 128-byte red-zone. Some registers |
||||
+ are saved on stack without adjusting stack pointer first. When we |
||||
+ update stack pointer to allocate more space, we need to take the |
||||
+ red-zone into account. */ |
||||
+# define STATE_SAVE_OFFSET (8 * 7 + 8) |
||||
+ |
||||
+/* Save SSE, AVX, AVX512, mask, bound and APX registers. Bound and APX |
||||
+ registers are mutually exclusive. */ |
||||
+# define STATE_SAVE_MASK \ |
||||
+ ((1 << X86_XSTATE_SSE_ID) \ |
||||
+ | (1 << X86_XSTATE_AVX_ID) \ |
||||
+ | (1 << X86_XSTATE_BNDREGS_ID) \ |
||||
+ | (1 << X86_XSTATE_K_ID) \ |
||||
+ | (1 << X86_XSTATE_ZMM_H_ID) \ |
||||
+ | (1 << X86_XSTATE_ZMM_ID) \ |
||||
+ | (1 << X86_XSTATE_APX_F_ID)) |
||||
+#else |
||||
+/* Offset for fxsave/xsave area used by _dl_tlsdesc_dynamic. Since i386 |
||||
+ doesn't have red-zone, use 0 here. */ |
||||
+# define STATE_SAVE_OFFSET 0 |
||||
+ |
||||
+/* Save SSE, AVX, AXV512, mask and bound registers. */ |
||||
+# define STATE_SAVE_MASK \ |
||||
+ ((1 << X86_XSTATE_SSE_ID) \ |
||||
+ | (1 << X86_XSTATE_AVX_ID) \ |
||||
+ | (1 << X86_XSTATE_BNDREGS_ID) \ |
||||
+ | (1 << X86_XSTATE_K_ID) \ |
||||
+ | (1 << X86_XSTATE_ZMM_H_ID)) |
||||
+#endif |
||||
|
||||
/* Constants for bits in __x86_string_control: */ |
||||
|
||||
-- |
||||
2.39.3 |
||||
|
@ -0,0 +1,109 @@
@@ -0,0 +1,109 @@
|
||||
commit 127fc56152347d73cb7c1c283e60e1cb1f15e9f9 |
||||
Author: sayan paul <saypaul@redhat.com> |
||||
Date: Wed May 29 15:31:04 2024 +0530 |
||||
|
||||
malloc: New test to check malloc alternate path using memory obstruction |
||||
|
||||
The test aims to ensure that malloc uses the alternate path to |
||||
allocate memory when sbrk() or brk() fails.To achieve this, |
||||
the test first creates an obstruction at current program break, |
||||
tests that obstruction with a failing sbrk(), then checks if malloc |
||||
is still returning a valid ptr thus inferring that malloc() used |
||||
mmap() instead of brk() or sbrk() to allocate the memory. |
||||
Reviewed-by: Arjun Shankar <arjun@redhat.com> |
||||
Reviewed-by: Zack Weinberg <zack@owlfolio.org> |
||||
|
||||
Conflicts: |
||||
malloc/Makefile |
||||
(usual tests conflict) |
||||
|
||||
diff --git a/malloc/Makefile b/malloc/Makefile |
||||
index 9b70831d383cb522..cb4e027d28b179f0 100644 |
||||
--- a/malloc/Makefile |
||||
+++ b/malloc/Makefile |
||||
@@ -43,6 +43,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ |
||||
tst-tcfree1 tst-tcfree2 tst-tcfree3 \ |
||||
tst-safe-linking \ |
||||
tst-mallocalign1 \ |
||||
+ tst-malloc-alternate-path \ |
||||
|
||||
tests-static := \ |
||||
tst-interpose-static-nothread \ |
||||
diff --git a/malloc/tst-malloc-alternate-path.c b/malloc/tst-malloc-alternate-path.c |
||||
new file mode 100644 |
||||
index 0000000000000000..43ae916815d6ff47 |
||||
--- /dev/null |
||||
+++ b/malloc/tst-malloc-alternate-path.c |
||||
@@ -0,0 +1,72 @@ |
||||
+/* Test that malloc uses mmap when sbrk or brk fails. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+/* This test sets up an obstruction to ensure that brk/sbrk fails to |
||||
+ grow the heap, then verifies that malloc uses mmap for allocations |
||||
+ instead. */ |
||||
+ |
||||
+#include <unistd.h> |
||||
+#include <sys/mman.h> |
||||
+#include <stdlib.h> |
||||
+#include <libc-pointer-arith.h> |
||||
+#include <support/check.h> |
||||
+#include <stddef.h> |
||||
+#include <stdalign.h> |
||||
+ |
||||
+#define LARGE_SIZE (10 * (1 << 20)) // 10 MB |
||||
+static long page_size; |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ /* Get current program break. */ |
||||
+ void *current_brk = sbrk (0); |
||||
+ |
||||
+ page_size = sysconf (_SC_PAGESIZE); |
||||
+ |
||||
+ /* Round up to the next page boundary. */ |
||||
+ void *next_page_boundary = PTR_ALIGN_UP (current_brk, page_size); |
||||
+ |
||||
+ /* Place a mapping using mmap at the next page boundary. */ |
||||
+ void *obstruction_addr |
||||
+ = mmap (next_page_boundary, page_size, PROT_READ, |
||||
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); |
||||
+ |
||||
+ /* Check if memory obstruction is set up correctly. */ |
||||
+ TEST_VERIFY_EXIT (obstruction_addr == next_page_boundary); |
||||
+ |
||||
+ /* Try to extend the heap beyond the obstruction using sbrk */ |
||||
+ int *ptr = sbrk (page_size); |
||||
+ TEST_VERIFY_EXIT (ptr == (void *) -1); |
||||
+ |
||||
+ /* Attempt multiple small allocations using malloc. */ |
||||
+ for (size_t i = 0; i < page_size / alignof (max_align_t); i++) |
||||
+ { |
||||
+ TEST_VERIFY (malloc (alignof (max_align_t))); |
||||
+ } |
||||
+ |
||||
+ /* Attempt to allocate a large block of memory using malloc. */ |
||||
+ TEST_VERIFY_EXIT (malloc (LARGE_SIZE) != NULL); |
||||
+ |
||||
+ /* Check if malloc changed current program break. */ |
||||
+ TEST_VERIFY_EXIT (current_brk == sbrk (0)); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
From a07e000e82cb71238259e674529c37c12dc7d423 Mon Sep 17 00:00:00 2001 |
||||
From: DJ Delorie <dj@redhat.com> |
||||
Date: Fri, 10 May 2024 17:34:29 -0400 |
||||
Subject: manual: add dup3 |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
|
||||
diff --git a/manual/llio.texi b/manual/llio.texi |
||||
index fae49d1433..fe1807a849 100644 |
||||
--- a/manual/llio.texi |
||||
+++ b/manual/llio.texi |
||||
@@ -3415,6 +3415,14 @@ middle of calling @code{dup2} at which @var{new} is closed and not yet a |
||||
duplicate of @var{old}. |
||||
@end deftypefun |
||||
|
||||
+@deftypefun int dup3 (int @var{old}, int @var{new}, int @var{flags}) |
||||
+@standards{Linux, unistd.h} |
||||
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} |
||||
+This function is the same as @code{dup2} but creates the new |
||||
+descriptor as if it had been opened with flags @var{flags}. The only |
||||
+allowed flag is @code{O_CLOEXEC}. |
||||
+@end deftypefun |
||||
+ |
||||
@deftypevr Macro int F_DUPFD |
||||
@standards{POSIX.1, fcntl.h} |
||||
This macro is used as the @var{command} argument to @code{fcntl}, to |
@ -0,0 +1,341 @@
@@ -0,0 +1,341 @@
|
||||
From 6c0be74305745c8f78bcfb69442c8c379459d99b Mon Sep 17 00:00:00 2001 |
||||
From: DJ Delorie <dj@redhat.com> |
||||
Date: Mon, 8 Jul 2024 17:52:15 -0400 |
||||
Subject: manual: add syscalls |
||||
|
||||
The purpose of this patch is to add some system calls that (1) aren't |
||||
otherwise documented, and (2) are merely redirected to the kernel, so |
||||
can refer to their documentation; and define a standard way of doing |
||||
so in the future. A more detailed explaination of how system calls |
||||
are wrapped is added along with reference to the Linux Man-Pages |
||||
project. |
||||
|
||||
Default version of man-pages is in configure.ac but can be overridden |
||||
by --with-man-pages=X.Y |
||||
|
||||
Reviewed-by: Alejandro Colomar <alx@kernel.org> |
||||
|
||||
diff --git a/config.make.in b/config.make.in |
||||
index 55e8b7563b..36096881b7 100644 |
||||
--- a/config.make.in |
||||
+++ b/config.make.in |
||||
@@ -101,6 +101,7 @@ build-hardcoded-path-in-tests= @hardcode |
||||
build-pt-chown = @build_pt_chown@ |
||||
have-tunables = @have_tunables@ |
||||
pthread-in-libc = @pthread_in_libc@ |
||||
+man-pages-version = @man_pages_version@ |
||||
|
||||
# Build tools. |
||||
CC = @CC@ |
||||
diff --git a/configure b/configure |
||||
index 55e8b7563b..36096881b7 100644 |
||||
--- a/configure 2024-07-17 15:45:55.033649362 -0400 |
||||
+++ b/configure 2024-07-17 15:47:44.281886629 -0400 |
||||
@@ -681,6 +681,7 @@ force_install |
||||
bindnow |
||||
hardcoded_path_in_tests |
||||
enable_timezone_tools |
||||
+man_pages_version |
||||
rtld_early_cflags |
||||
extra_nonshared_cflags |
||||
use_default_link |
||||
@@ -763,6 +764,7 @@ with_headers |
||||
with_default_link |
||||
with_nonshared_cflags |
||||
with_rtld_early_cflags |
||||
+with_man_pages |
||||
enable_sanity_checks |
||||
enable_shared |
||||
enable_profile |
||||
@@ -1483,6 +1485,8 @@ Optional Packages: |
||||
build nonshared libraries with additional CFLAGS |
||||
--with-rtld-early-cflags=CFLAGS |
||||
build early initialization with additional CFLAGS |
||||
+ --with-man-pages=VERSION |
||||
+ tie manual to a specific man-pages version |
||||
--with-cpu=CPU select code for CPU variant |
||||
|
||||
Some influential environment variables: |
||||
@@ -3396,6 +3400,15 @@ fi |
||||
|
||||
|
||||
|
||||
+man_pages_version=6.9.1 |
||||
+ |
||||
+ |
||||
+# Check whether --with-man-pages was given. |
||||
+if test "${with_man_pages+set}" = set; then : |
||||
+ withval=$with_man_pages; man_pages_version=$withval |
||||
+fi |
||||
+ |
||||
+ |
||||
|
||||
# Check whether --enable-sanity-checks was given. |
||||
if test "${enable_sanity_checks+set}" = set; then : |
||||
diff --git a/configure.ac b/configure.ac |
||||
index e48957f318..9cbc0bf68f 100644 |
||||
--- a/configure.ac 2024-07-17 15:45:52.181538742 -0400 |
||||
+++ b/configure.ac 2024-07-17 15:46:29.885001095 -0400 |
||||
@@ -169,6 +169,15 @@ AC_ARG_WITH([rtld-early-cflags], |
||||
[rtld_early_cflags=]) |
||||
AC_SUBST(rtld_early_cflags) |
||||
|
||||
+man_pages_version=6.9.1 |
||||
+ |
||||
+AC_ARG_WITH([man-pages], |
||||
+ AS_HELP_STRING([--with-man-pages=VERSION], |
||||
+ [tie manual to a specific man-pages version]), |
||||
+ [man_pages_version=$withval], |
||||
+ []) |
||||
+AC_SUBST(man_pages_version) |
||||
+ |
||||
AC_ARG_ENABLE([sanity-checks], |
||||
AS_HELP_STRING([--disable-sanity-checks], |
||||
[really do not use threads (should not be used except in special situations) @<:@default=yes@:>@]), |
||||
diff --git a/manual/Makefile b/manual/Makefile |
||||
index b5fda4a7ae..a6c05db540 100644 |
||||
--- a/manual/Makefile |
||||
+++ b/manual/Makefile |
||||
@@ -117,6 +117,7 @@ $(objpfx)stamp-pkgvers: $(common-objpfx)config.make |
||||
echo "@set PKGVERSION_DEFAULT" >> $(objpfx)pkgvers-tmp; \ |
||||
fi |
||||
echo "@set REPORT_BUGS_TO $(REPORT_BUGS_TEXI)" >> $(objpfx)pkgvers-tmp |
||||
+ echo "@set man_pages_version $(man-pages-version)" >> $(objpfx)pkgvers-tmp; \ |
||||
echo "@end ifclear" >> $(objpfx)pkgvers-tmp |
||||
$(move-if-change) $(objpfx)pkgvers-tmp $(objpfx)pkgvers.texi |
||||
touch $@ |
||||
diff --git a/manual/intro.texi b/manual/intro.texi |
||||
index ff43c5a7fb..879c1b38d9 100644 |
||||
--- a/manual/intro.texi |
||||
+++ b/manual/intro.texi |
||||
@@ -85,6 +85,7 @@ standards each function or symbol comes from. |
||||
* Berkeley Unix:: BSD and SunOS. |
||||
* SVID:: The System V Interface Description. |
||||
* XPG:: The X/Open Portability Guide. |
||||
+* Linux Kernel:: The Linux kernel. |
||||
@end menu |
||||
|
||||
@node ISO C, POSIX, , Standards and Portability |
||||
@@ -941,7 +942,7 @@ inter-process communication and shared memory, the @code{hsearch} and |
||||
@code{drand48} families of functions, @code{fmtmsg} and several of the |
||||
mathematical functions. |
||||
|
||||
-@node XPG, , SVID, Standards and Portability |
||||
+@node XPG, Linux Kernel, SVID, Standards and Portability |
||||
@subsection XPG (The X/Open Portability Guide) |
||||
|
||||
The X/Open Portability Guide, published by the X/Open Company, Ltd., is |
||||
@@ -960,6 +961,20 @@ fulfilling the XPG standard with the Unix extensions is a |
||||
precondition for getting the Unix brand chances are good that the |
||||
functionality is available on commercial systems. |
||||
|
||||
+@node Linux Kernel, , XPG, Standards and Portability |
||||
+@subsection Linux (The Linux Kernel) |
||||
+ |
||||
+@Theglibc{} includes by reference the Linux man-pages |
||||
+@value{man_pages_version} documentation to document the listed |
||||
+syscalls for the Linux kernel. For reference purposes only the latest |
||||
+@uref{https://www.kernel.org/doc/man-pages/,Linux man-pages Project} |
||||
+documentation can be accessed from the |
||||
+@uref{https://www.kernel.org,Linux kernel} website. Where the syscall |
||||
+has more specific documentation in this manual that more specific |
||||
+documentation is considered authoritative. |
||||
+ |
||||
+Additional details on the Linux system call interface can be found in |
||||
+@xref{System Calls}. |
||||
|
||||
@node Using the Library, Roadmap to the Manual, Standards and Portability, Introduction |
||||
@section Using the Library |
||||
diff --git a/manual/llio.texi b/manual/llio.texi |
||||
index 78c7c79913..6f0a48609b 100644 |
||||
--- a/manual/llio.texi |
||||
+++ b/manual/llio.texi |
||||
@@ -65,6 +65,7 @@ directly.) |
||||
* Interrupt Input:: Getting an asynchronous signal when |
||||
input arrives. |
||||
* IOCTLs:: Generic I/O Control operations. |
||||
+* Other Low-Level I/O APIs:: Other low-level-I/O-related functions. |
||||
@end menu |
||||
|
||||
|
||||
@@ -2324,6 +2325,8 @@ file descriptor, or until the timeout period expires. |
||||
There is another example showing the use of @code{select} to multiplex |
||||
input from multiple sockets in @ref{Server Example}. |
||||
|
||||
+For an alternate interface to this functionality, see @code{poll} |
||||
+(@pxref{Other Low-Level I/O APIs}). |
||||
|
||||
@node Synchronizing I/O |
||||
@section Synchronizing I/O operations |
||||
@@ -3407,7 +3410,9 @@ require additional arguments to be supplied. These additional arguments |
||||
and the return value and error conditions are given in the detailed |
||||
descriptions of the individual commands. |
||||
|
||||
-Briefly, here is a list of what the various commands are. |
||||
+Briefly, here is a list of what the various commands are. For an |
||||
+exhaustive list of kernel-specific options, please see @xref{System |
||||
+Calls}. |
||||
|
||||
@vtable @code |
||||
@item F_DUPFD |
||||
@@ -4743,5 +4748,28 @@ Most IOCTLs are OS-specific and/or only used in special system utilities, |
||||
and are thus beyond the scope of this document. For an example of the use |
||||
of an IOCTL, see @ref{Out-of-Band Data}. |
||||
|
||||
-@c FIXME this is undocumented: |
||||
-@c dup3 |
||||
+@node Other Low-Level I/O APIs |
||||
+@section Other low-level-I/O-related functions |
||||
+ |
||||
+@deftp {Data Type} {struct pollfd} |
||||
+@standards{POSIX.1,poll.h} |
||||
+@end deftp |
||||
+ |
||||
+@deftp {Data Type} {struct epoll_event} |
||||
+@standards{Linux,sys/epoll.h} |
||||
+@end deftp |
||||
+ |
||||
+@deftypefun int poll (struct pollfd *@var{fds}, nfds_t @var{nfds}, int @var{timeout}) |
||||
+ |
||||
+@manpagefunctionstub{poll,2} |
||||
+@end deftypefun |
||||
+ |
||||
+@deftypefun int epoll_create(int @var{size}) |
||||
+ |
||||
+@manpagefunctionstub{epoll_create,2} |
||||
+@end deftypefun |
||||
+ |
||||
+@deftypefun int epoll_wait(int @var{epfd}, struct epoll_event *@var{events}, int @var{maxevents}, int @var{timeout}) |
||||
+ |
||||
+@manpagefunctionstub{epoll_wait,2} |
||||
+@end deftypefun |
||||
diff --git a/manual/macros.texi b/manual/macros.texi |
||||
index 4a2e22f473..579da3fb81 100644 |
||||
--- a/manual/macros.texi |
||||
+++ b/manual/macros.texi |
||||
@@ -282,4 +282,11 @@ cwd\comments\ |
||||
@macro standardsx {element, standard, header} |
||||
@end macro |
||||
|
||||
+@macro manpagefunctionstub {func,sec} |
||||
+This documentation is a stub. For additional information on this |
||||
+function, consult the manual page |
||||
+@url{https://man7.org/linux/man-pages/man\sec\/\func\.\sec\.html}. |
||||
+@xref{Linux Kernel}. |
||||
+@end macro |
||||
+ |
||||
@end ifclear |
||||
diff --git a/manual/socket.texi b/manual/socket.texi |
||||
index f0e35d9e13..8708cbb07c 100644 |
||||
--- a/manual/socket.texi |
||||
+++ b/manual/socket.texi |
||||
@@ -41,6 +41,7 @@ aren't documented either so far. |
||||
is to make it work with Inetd. |
||||
* Socket Options:: Miscellaneous low-level socket options. |
||||
* Networks Database:: Accessing the database of network names. |
||||
+* Other Socket APIs:: Other socket-related functions. |
||||
@end menu |
||||
|
||||
@node Socket Concepts |
||||
@@ -3134,38 +3135,8 @@ You can use plain @code{recv} (@pxref{Receiving Data}) instead of |
||||
treat all possible senders alike). Even @code{read} can be used if |
||||
you don't want to specify @var{flags} (@pxref{I/O Primitives}). |
||||
|
||||
-@ignore |
||||
-@c sendmsg and recvmsg are like readv and writev in that they |
||||
-@c use a series of buffers. It's not clear this is worth |
||||
-@c supporting or that we support them. |
||||
-@c !!! they can do more; it is hairy |
||||
- |
||||
-@deftp {Data Type} {struct msghdr} |
||||
-@standards{BSD, sys/socket.h} |
||||
-@end deftp |
||||
- |
||||
-@deftypefun ssize_t sendmsg (int @var{socket}, const struct msghdr *@var{message}, int @var{flags}) |
||||
-@standards{BSD, sys/socket.h} |
||||
-@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} |
||||
- |
||||
-This function is defined as a cancellation point in multi-threaded |
||||
-programs, so one has to be prepared for this and make sure that |
||||
-allocated resources (like memory, files descriptors, semaphores or |
||||
-whatever) are freed even if the thread is cancel. |
||||
-@c @xref{pthread_cleanup_push}, for a method how to do this. |
||||
-@end deftypefun |
||||
- |
||||
-@deftypefun ssize_t recvmsg (int @var{socket}, struct msghdr *@var{message}, int @var{flags}) |
||||
-@standards{BSD, sys/socket.h} |
||||
-@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} |
||||
- |
||||
-This function is defined as a cancellation point in multi-threaded |
||||
-programs, so one has to be prepared for this and make sure that |
||||
-allocated resources (like memory, files descriptors, semaphores or |
||||
-whatever) are freed even if the thread is canceled. |
||||
-@c @xref{pthread_cleanup_push}, for a method how to do this. |
||||
-@end deftypefun |
||||
-@end ignore |
||||
+If you need more flexibility and/or control over sending and receiving |
||||
+packets, see @code{sendmsg} and @code{recvmsg} (@pxref{Other Socket APIs}). |
||||
|
||||
@node Datagram Example |
||||
@subsection Datagram Socket Example |
||||
@@ -3664,3 +3635,20 @@ returns a null pointer if there are no more entries. |
||||
@c libc_lock_unlock @aculock |
||||
This function closes the networks database. |
||||
@end deftypefun |
||||
+ |
||||
+@node Other Socket APIs |
||||
+@section Other Socket APIs |
||||
+ |
||||
+@deftp {Data Type} {struct msghdr} |
||||
+@standards{BSD, sys/socket.h} |
||||
+@end deftp |
||||
+ |
||||
+@deftypefun ssize_t sendmsg (int @var{socket}, const struct msghdr *@var{message}, int @var{flags}) |
||||
+ |
||||
+@manpagefunctionstub{sendmsg,2} |
||||
+@end deftypefun |
||||
+ |
||||
+@deftypefun ssize_t recvmsg (int @var{socket}, struct msghdr *@var{message}, int @var{flags}) |
||||
+ |
||||
+@manpagefunctionstub{recvmsg,2} |
||||
+@end deftypefun |
||||
diff --git a/manual/startup.texi b/manual/startup.texi |
||||
index 224dd98c1e..747beed4d9 100644 |
||||
--- a/manual/startup.texi |
||||
+++ b/manual/startup.texi |
||||
@@ -689,7 +689,25 @@ you don't need to know about it because you can just use @theglibc{}'s |
||||
@code{chmod} function. |
||||
|
||||
@cindex kernel call |
||||
-System calls are sometimes called kernel calls. |
||||
+System calls are sometimes called syscalls or kernel calls, and this |
||||
+interface is mostly a purely mechanical translation from the kernel's |
||||
+ABI to the C ABI. For the set of syscalls where we do not guarantee |
||||
+POSIX Thread cancellation the wrappers only organize the incoming |
||||
+arguments from the C calling convention to the calling convention of |
||||
+the target kernel. For the set of syscalls where we provided POSIX |
||||
+Thread cancellation the wrappers set some internal state in the |
||||
+library to support cancellation, but this does not impact the |
||||
+behaviour of the syscall provided by the kernel. |
||||
+ |
||||
+In some cases, if @theglibc{} detects that a system call has been |
||||
+superseded by a more capable one, the wrapper may map the old call to |
||||
+the new one. For example, @code{dup2} is implemented via @code{dup3} |
||||
+by passing an additional empty flags argument, and @code{open} calls |
||||
+@code{openat} passing the additional @code{AT_FDCWD}. Sometimes even |
||||
+more is done, such as converting between 32-bit and 64-bit time |
||||
+values. In general, though, such processing is only to make the |
||||
+system call better match the C ABI, rather than change its |
||||
+functionality. |
||||
|
||||
However, there are times when you want to make a system call explicitly, |
||||
and for that, @theglibc{} provides the @code{syscall} function. |
||||
@@ -711,6 +729,8 @@ we won't describe it here either because anyone who is coding |
||||
library source code as a specification of the interface between them |
||||
anyway. |
||||
|
||||
+@code{syscall} does not provide cancellation logic, even if the system |
||||
+call you're calling is listed as cancellable above. |
||||
|
||||
@code{syscall} is declared in @file{unistd.h}. |
||||
|
@ -0,0 +1,188 @@
@@ -0,0 +1,188 @@
|
||||
From a4c3f5f46e850c977cda81c251036475aab8313c Mon Sep 17 00:00:00 2001 |
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Thu, 23 Nov 2023 14:29:14 -0300 |
||||
Subject: [PATCH] elf: Add a way to check if tunable is set (BZ 27069) |
||||
Content-type: text/plain; charset=UTF-8 |
||||
|
||||
The patch adds two new macros, TUNABLE_GET_DEFAULT and TUNABLE_IS_INITIALIZED, |
||||
here the former get the default value with a signature similar to |
||||
TUNABLE_GET, while the later returns whether the tunable was set by |
||||
the environment variable. |
||||
|
||||
Checked on x86_64-linux-gnu. |
||||
Reviewed-by: DJ Delorie <dj@redhat.com> |
||||
Tested-by: Zhangfei Gao <zhangfei.gao@linaro.org> |
||||
|
||||
Conflicts: |
||||
elf/Versions |
||||
(removed to preserve ABI) |
||||
elf/dl-tunable-types.h |
||||
(line numbers) |
||||
scripts/gen-tunables.awk |
||||
(account for missing TUNABLE_SECLEVEL patch) |
||||
|
||||
--- |
||||
elf/dl-tunable-types.h | 1 + |
||||
elf/dl-tunables.c | 40 ++++++++++++++++++++++++++++++++++++++++ |
||||
elf/dl-tunables.h | 28 ++++++++++++++++++++++++++++ |
||||
elf/dl-tunables.list | 1 + |
||||
scripts/gen-tunables.awk | 4 ++-- |
||||
6 files changed, 73 insertions(+), 2 deletions(-) |
||||
|
||||
diff -rup a/elf/dl-tunable-types.h b/elf/dl-tunable-types.h |
||||
--- a/elf/dl-tunable-types.h 2021-08-01 21:33:43.000000000 -0400 |
||||
+++ b/elf/dl-tunable-types.h 2024-03-26 18:23:22.211504813 -0400 |
||||
@@ -61,6 +61,7 @@ struct _tunable |
||||
{ |
||||
const char name[TUNABLE_NAME_MAX]; /* Internal name of the tunable. */ |
||||
tunable_type_t type; /* Data type of the tunable. */ |
||||
+ const tunable_val_t def; /* The value. */ |
||||
tunable_val_t val; /* The value. */ |
||||
bool initialized; /* Flag to indicate that the tunable is |
||||
initialized. */ |
||||
diff -rup a/elf/dl-tunables.c b/elf/dl-tunables.c |
||||
--- a/elf/dl-tunables.c 2024-03-26 18:21:10.090681748 -0400 |
||||
+++ b/elf/dl-tunables.c 2024-03-26 18:23:22.214504923 -0400 |
||||
@@ -152,6 +152,13 @@ tunable_initialize (tunable_t *cur, cons |
||||
do_tunable_update_val (cur, &val, NULL, NULL); |
||||
} |
||||
|
||||
+bool |
||||
+__tunable_is_initialized (tunable_id_t id) |
||||
+{ |
||||
+ return tunable_list[id].initialized; |
||||
+} |
||||
+rtld_hidden_def (__tunable_is_initialized) |
||||
+ |
||||
void |
||||
__tunable_set_val (tunable_id_t id, tunable_val_t *valp, tunable_num_t *minp, |
||||
tunable_num_t *maxp) |
||||
@@ -399,6 +406,39 @@ __tunables_print (void) |
||||
} |
||||
} |
||||
|
||||
+void |
||||
+__tunable_get_default (tunable_id_t id, void *valp) |
||||
+{ |
||||
+ tunable_t *cur = &tunable_list[id]; |
||||
+ |
||||
+ switch (cur->type.type_code) |
||||
+ { |
||||
+ case TUNABLE_TYPE_UINT_64: |
||||
+ { |
||||
+ *((uint64_t *) valp) = (uint64_t) cur->def.numval; |
||||
+ break; |
||||
+ } |
||||
+ case TUNABLE_TYPE_INT_32: |
||||
+ { |
||||
+ *((int32_t *) valp) = (int32_t) cur->def.numval; |
||||
+ break; |
||||
+ } |
||||
+ case TUNABLE_TYPE_SIZE_T: |
||||
+ { |
||||
+ *((size_t *) valp) = (size_t) cur->def.numval; |
||||
+ break; |
||||
+ } |
||||
+ case TUNABLE_TYPE_STRING: |
||||
+ { |
||||
+ *((const char **)valp) = cur->def.strval; |
||||
+ break; |
||||
+ } |
||||
+ default: |
||||
+ __builtin_unreachable (); |
||||
+ } |
||||
+} |
||||
+rtld_hidden_def (__tunable_get_default) |
||||
+ |
||||
/* Set the tunable value. This is called by the module that the tunable exists |
||||
in. */ |
||||
void |
||||
diff -rup a/elf/dl-tunables.h b/elf/dl-tunables.h |
||||
--- a/elf/dl-tunables.h 2021-08-01 21:33:43.000000000 -0400 |
||||
+++ b/elf/dl-tunables.h 2024-03-26 18:23:22.217505032 -0400 |
||||
@@ -53,18 +53,26 @@ typedef void (*tunable_callback_t) (tuna |
||||
|
||||
extern void __tunables_init (char **); |
||||
extern void __tunables_print (void); |
||||
+extern bool __tunable_is_initialized (tunable_id_t); |
||||
extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t); |
||||
extern void __tunable_set_val (tunable_id_t, tunable_val_t *, tunable_num_t *, |
||||
tunable_num_t *); |
||||
+extern void __tunable_get_default (tunable_id_t id, void *valp); |
||||
rtld_hidden_proto (__tunables_init) |
||||
rtld_hidden_proto (__tunables_print) |
||||
+rtld_hidden_proto (__tunable_is_initialized) |
||||
rtld_hidden_proto (__tunable_get_val) |
||||
rtld_hidden_proto (__tunable_set_val) |
||||
+rtld_hidden_proto (__tunable_get_default) |
||||
|
||||
/* Define TUNABLE_GET and TUNABLE_SET in short form if TOP_NAMESPACE and |
||||
TUNABLE_NAMESPACE are defined. This is useful shorthand to get and set |
||||
tunables within a module. */ |
||||
#if defined TOP_NAMESPACE && defined TUNABLE_NAMESPACE |
||||
+# define TUNABLE_IS_INITIALIZED(__id) \ |
||||
+ TUNABLE_IS_INITIALIZED_FULL(TOP_NAMESPACE, TUNABLE_NAMESPACE, __id) |
||||
+# define TUNABLE_GET_DEFAULT(__id, __type) \ |
||||
+ TUNABLE_GET_DEFAULT_FULL(TOP_NAMESPACE, TUNABLE_NAMESPACE,__id, __type) |
||||
# define TUNABLE_GET(__id, __type, __cb) \ |
||||
TUNABLE_GET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __cb) |
||||
# define TUNABLE_SET(__id, __val) \ |
||||
@@ -73,6 +81,10 @@ rtld_hidden_proto (__tunable_set_val) |
||||
TUNABLE_SET_WITH_BOUNDS_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, \ |
||||
__val, __min, __max) |
||||
#else |
||||
+# define TUNABLE_IS_INITIALIZED(__top, __ns, __id) \ |
||||
+ TUNABLE_IS_INITIALIZED_FULL(__top, __ns, __id) |
||||
+# define TUNABLE_GET_DEFAULT(__top, __ns, __type) \ |
||||
+ TUNABLE_GET_DEFAULT_FULL(__top, __ns, __id, __type) |
||||
# define TUNABLE_GET(__top, __ns, __id, __type, __cb) \ |
||||
TUNABLE_GET_FULL (__top, __ns, __id, __type, __cb) |
||||
# define TUNABLE_SET(__top, __ns, __id, __val) \ |
||||
@@ -81,6 +93,22 @@ rtld_hidden_proto (__tunable_set_val) |
||||
TUNABLE_SET_WITH_BOUNDS_FULL (__top, __ns, __id, __val, __min, __max) |
||||
#endif |
||||
|
||||
+/* Return whether the tunable was initialized by the environment variable. */ |
||||
+#define TUNABLE_IS_INITIALIZED_FULL(__top, __ns, __id) \ |
||||
+({ \ |
||||
+ tunable_id_t id = TUNABLE_ENUM_NAME (__top, __ns, __id); \ |
||||
+ __tunable_is_initialized (id); \ |
||||
+}) |
||||
+ |
||||
+/* Return the default value of the tunable. */ |
||||
+#define TUNABLE_GET_DEFAULT_FULL(__top, __ns, __id, __type) \ |
||||
+({ \ |
||||
+ tunable_id_t id = TUNABLE_ENUM_NAME (__top, __ns, __id); \ |
||||
+ __type __ret; \ |
||||
+ __tunable_get_default (id, &__ret); \ |
||||
+ __ret; \ |
||||
+}) |
||||
+ |
||||
/* Get and return a tunable value. If the tunable was set externally and __CB |
||||
is defined then call __CB before returning the value. */ |
||||
# define TUNABLE_GET_FULL(__top, __ns, __id, __type, __cb) \ |
||||
diff -rup a/elf/dl-tunables.list b/elf/dl-tunables.list |
||||
--- a/elf/dl-tunables.list 2024-03-26 18:21:09.664666196 -0400 |
||||
+++ b/elf/dl-tunables.list 2024-03-26 18:23:22.220505142 -0400 |
||||
@@ -20,6 +20,7 @@ |
||||
# type: Defaults to STRING |
||||
# minval: Optional minimum acceptable value |
||||
# maxval: Optional maximum acceptable value |
||||
+# default: Optional default value (if not specified it will be 0 or "") |
||||
# env_alias: An alias environment variable |
||||
# security_level: Specify security level of the tunable for AT_SECURE binaries. |
||||
# Valid values are: |
||||
diff -rup a/scripts/gen-tunables.awk b/scripts/gen-tunables.awk |
||||
--- a/scripts/gen-tunables.awk 2024-03-26 18:21:09.523661049 -0400 |
||||
+++ b/scripts/gen-tunables.awk 2024-03-26 18:34:45.385462341 -0400 |
||||
@@ -236,8 +236,8 @@ END { |
||||
n = indices[2]; |
||||
m = indices[3]; |
||||
printf (" {TUNABLE_NAME_S(%s, %s, %s)", t, n, m) |
||||
- printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, NULL, TUNABLE_SECLEVEL_%s, %s},\n", |
||||
- types[t,n,m], minvals[t,n,m], maxvals[t,n,m], |
||||
+ printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, {%s}, NULL, TUNABLE_SECLEVEL_%s, %s},\n", |
||||
+ types[t,n,m], minvals[t,n,m], maxvals[t,n,m],default_val[t,n,m], |
||||
default_val[t,n,m], security_level[t,n,m], env_alias[t,n,m]); |
||||
} |
||||
print "};" |
@ -0,0 +1,155 @@
@@ -0,0 +1,155 @@
|
||||
From 0c0d39fe4aeb0f69b26e76337c5dfd5530d5d44e Mon Sep 17 00:00:00 2001 |
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Thu, 8 Feb 2024 10:08:38 -0300 |
||||
Subject: [PATCH] x86: Fix Zen3/Zen4 ERMS selection (BZ 30994) |
||||
Content-type: text/plain; charset=UTF-8 |
||||
|
||||
The REP MOVSB usage on memcpy/memmove does not show much performance |
||||
improvement on Zen3/Zen4 cores compared to the vectorized loops. Also, |
||||
as from BZ 30994, if the source is aligned and the destination is not |
||||
the performance can be 20x slower. |
||||
|
||||
The performance difference is noticeable with small buffer sizes, closer |
||||
to the lower bounds limits when memcpy/memmove starts to use ERMS. The |
||||
performance of REP MOVSB is similar to vectorized instruction on the |
||||
size limit (the L2 cache). Also, there is no drawback to multiple cores |
||||
sharing the cache. |
||||
|
||||
Checked on x86_64-linux-gnu on Zen3. |
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
|
||||
Conflicts: |
||||
sysdeps/x86/dl-cacheinfo.h |
||||
(tweaked for changed context) |
||||
|
||||
--- |
||||
sysdeps/x86/dl-cacheinfo.h | 38 ++++++++++++++++++-------------------- |
||||
1 file changed, 18 insertions(+), 20 deletions(-) |
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h |
||||
index d5101615e3..f34d12846c 100644 |
||||
--- a/sysdeps/x86/dl-cacheinfo.h |
||||
+++ b/sysdeps/x86/dl-cacheinfo.h |
||||
@@ -791,7 +791,6 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
long int data = -1; |
||||
long int shared = -1; |
||||
long int shared_per_thread = -1; |
||||
- long int core = -1; |
||||
unsigned int threads = 0; |
||||
unsigned long int level1_icache_size = -1; |
||||
unsigned long int level1_icache_linesize = -1; |
||||
@@ -809,7 +808,6 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
if (cpu_features->basic.kind == arch_kind_intel) |
||||
{ |
||||
data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features); |
||||
- core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features); |
||||
shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, cpu_features); |
||||
shared_per_thread = shared; |
||||
|
||||
@@ -822,7 +820,8 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
= handle_intel (_SC_LEVEL1_DCACHE_ASSOC, cpu_features); |
||||
level1_dcache_linesize |
||||
= handle_intel (_SC_LEVEL1_DCACHE_LINESIZE, cpu_features); |
||||
- level2_cache_size = core; |
||||
+ level2_cache_size |
||||
+ = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features); |
||||
level2_cache_assoc |
||||
= handle_intel (_SC_LEVEL2_CACHE_ASSOC, cpu_features); |
||||
level2_cache_linesize |
||||
@@ -835,12 +834,12 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
level4_cache_size |
||||
= handle_intel (_SC_LEVEL4_CACHE_SIZE, cpu_features); |
||||
|
||||
- get_common_cache_info (&shared, &shared_per_thread, &threads, core); |
||||
+ get_common_cache_info (&shared, &shared_per_thread, &threads, |
||||
+ level2_cache_size); |
||||
} |
||||
else if (cpu_features->basic.kind == arch_kind_zhaoxin) |
||||
{ |
||||
data = handle_zhaoxin (_SC_LEVEL1_DCACHE_SIZE); |
||||
- core = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE); |
||||
shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE); |
||||
shared_per_thread = shared; |
||||
|
||||
@@ -849,19 +848,19 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
level1_dcache_size = data; |
||||
level1_dcache_assoc = handle_zhaoxin (_SC_LEVEL1_DCACHE_ASSOC); |
||||
level1_dcache_linesize = handle_zhaoxin (_SC_LEVEL1_DCACHE_LINESIZE); |
||||
- level2_cache_size = core; |
||||
+ level2_cache_size = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE); |
||||
level2_cache_assoc = handle_zhaoxin (_SC_LEVEL2_CACHE_ASSOC); |
||||
level2_cache_linesize = handle_zhaoxin (_SC_LEVEL2_CACHE_LINESIZE); |
||||
level3_cache_size = shared; |
||||
level3_cache_assoc = handle_zhaoxin (_SC_LEVEL3_CACHE_ASSOC); |
||||
level3_cache_linesize = handle_zhaoxin (_SC_LEVEL3_CACHE_LINESIZE); |
||||
|
||||
- get_common_cache_info (&shared, &shared_per_thread, &threads, core); |
||||
+ get_common_cache_info (&shared, &shared_per_thread, &threads, |
||||
+ level2_cache_size); |
||||
} |
||||
else if (cpu_features->basic.kind == arch_kind_amd) |
||||
{ |
||||
data = handle_amd (_SC_LEVEL1_DCACHE_SIZE); |
||||
- core = handle_amd (_SC_LEVEL2_CACHE_SIZE); |
||||
shared = handle_amd (_SC_LEVEL3_CACHE_SIZE); |
||||
|
||||
level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE); |
||||
@@ -869,7 +868,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
level1_dcache_size = data; |
||||
level1_dcache_assoc = handle_amd (_SC_LEVEL1_DCACHE_ASSOC); |
||||
level1_dcache_linesize = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE); |
||||
- level2_cache_size = core; |
||||
+ level2_cache_size = handle_amd (_SC_LEVEL2_CACHE_SIZE);; |
||||
level2_cache_assoc = handle_amd (_SC_LEVEL2_CACHE_ASSOC); |
||||
level2_cache_linesize = handle_amd (_SC_LEVEL2_CACHE_LINESIZE); |
||||
level3_cache_size = shared; |
||||
@@ -880,12 +879,12 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
if (shared <= 0) |
||||
{ |
||||
/* No shared L3 cache. All we have is the L2 cache. */ |
||||
- shared = core; |
||||
+ shared = level2_cache_size; |
||||
} |
||||
else if (cpu_features->basic.family < 0x17) |
||||
{ |
||||
/* Account for exclusive L2 and L3 caches. */ |
||||
- shared += core; |
||||
+ shared += level2_cache_size; |
||||
} |
||||
|
||||
shared_per_thread = shared; |
||||
@@ -987,6 +986,12 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
if (CPU_FEATURE_USABLE_P (cpu_features, FSRM)) |
||||
rep_movsb_threshold = 2112; |
||||
|
||||
+ /* For AMD CPUs that support ERMS (Zen3+), REP MOVSB is in a lot of |
||||
+ cases slower than the vectorized path (and for some alignments, |
||||
+ it is really slow, check BZ #30994). */ |
||||
+ if (cpu_features->basic.kind == arch_kind_amd) |
||||
+ rep_movsb_threshold = non_temporal_threshold; |
||||
+ |
||||
/* The default threshold to use Enhanced REP STOSB. */ |
||||
unsigned long int rep_stosb_threshold = 2048; |
||||
|
||||
@@ -1028,15 +1033,8 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
#endif |
||||
|
||||
unsigned long int rep_movsb_stop_threshold; |
||||
- /* ERMS feature is implemented from AMD Zen3 architecture and it is |
||||
- performing poorly for data above L2 cache size. Henceforth, adding |
||||
- an upper bound threshold parameter to limit the usage of Enhanced |
||||
- REP MOVSB operations and setting its value to L2 cache size. */ |
||||
- if (cpu_features->basic.kind == arch_kind_amd) |
||||
- rep_movsb_stop_threshold = core; |
||||
/* Setting the upper bound of ERMS to the computed value of |
||||
- non-temporal threshold for architectures other than AMD. */ |
||||
- else |
||||
- rep_movsb_stop_threshold = non_temporal_threshold; |
||||
+ non-temporal threshold for all architectures. */ |
||||
+ rep_movsb_stop_threshold = non_temporal_threshold; |
||||
|
||||
cpu_features->data_cache_size = data; |
||||
cpu_features->shared_cache_size = shared; |
||||
-- |
||||
2.39.3 |
||||
|
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
From 272708884cb750f12f5c74a00e6620c19dc6d567 Mon Sep 17 00:00:00 2001 |
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Thu, 8 Feb 2024 10:08:39 -0300 |
||||
Subject: [PATCH] x86: Do not prefer ERMS for memset on Zen3+ |
||||
Content-type: text/plain; charset=UTF-8 |
||||
|
||||
For AMD Zen3+ architecture, the performance of the vectorized loop is |
||||
slightly better than ERMS. |
||||
|
||||
Checked on x86_64-linux-gnu on Zen3. |
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
--- |
||||
sysdeps/x86/dl-cacheinfo.h | 5 +++++ |
||||
1 file changed, 5 insertions(+) |
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h |
||||
index f34d12846c..5a98f70364 100644 |
||||
--- a/sysdeps/x86/dl-cacheinfo.h |
||||
+++ b/sysdeps/x86/dl-cacheinfo.h |
||||
@@ -1021,6 +1021,11 @@ dl_init_cacheinfo (struct cpu_features *cpu_features) |
||||
minimum value is fixed. */ |
||||
rep_stosb_threshold = TUNABLE_GET (x86_rep_stosb_threshold, |
||||
long int, NULL); |
||||
+ if (cpu_features->basic.kind == arch_kind_amd |
||||
+ && !TUNABLE_IS_INITIALIZED (x86_rep_stosb_threshold)) |
||||
+ /* For AMD Zen3+ architecture, the performance of the vectorized loop is |
||||
+ slightly better than ERMS. */ |
||||
+ rep_stosb_threshold = SIZE_MAX; |
||||
|
||||
TUNABLE_SET_WITH_BOUNDS (x86_data_cache_size, data, 0, SIZE_MAX); |
||||
TUNABLE_SET_WITH_BOUNDS (x86_shared_cache_size, shared, 0, SIZE_MAX); |
||||
-- |
||||
2.39.3 |
||||
|
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
From 491e55beab7457ed310a4a47496f4a333c5d1032 Mon Sep 17 00:00:00 2001 |
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Thu, 8 Feb 2024 10:08:40 -0300 |
||||
Subject: [PATCH] x86: Expand the comment on when REP STOSB is used on memset |
||||
Content-type: text/plain; charset=UTF-8 |
||||
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
||||
--- |
||||
sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S | 4 +++- |
||||
1 file changed, 3 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S |
||||
index 9984c3ca0f..97839a2248 100644 |
||||
--- a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S |
||||
+++ b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S |
||||
@@ -21,7 +21,9 @@ |
||||
2. If size is less than VEC, use integer register stores. |
||||
3. If size is from VEC_SIZE to 2 * VEC_SIZE, use 2 VEC stores. |
||||
4. If size is from 2 * VEC_SIZE to 4 * VEC_SIZE, use 4 VEC stores. |
||||
- 5. If size is more to 4 * VEC_SIZE, align to 4 * VEC_SIZE with |
||||
+ 5. On machines ERMS feature, if size is greater or equal than |
||||
+ __x86_rep_stosb_threshold then REP STOSB will be used. |
||||
+ 6. If size is more to 4 * VEC_SIZE, align to 4 * VEC_SIZE with |
||||
4 VEC stores and store 4 * VEC at a time until done. */ |
||||
|
||||
#include <sysdep.h> |
||||
-- |
||||
2.39.3 |
||||
|
@ -0,0 +1,205 @@
@@ -0,0 +1,205 @@
|
||||
From dce754b1553b86fc6352636f1fa490a85b7cf0ff Mon Sep 17 00:00:00 2001 |
||||
From: DJ Delorie <dj@redhat.com> |
||||
Date: Fri, 10 May 2024 14:52:09 -0400 |
||||
Subject: Update mmap() flags and errors lists |
||||
|
||||
Extend the list of MAP_* macros to include all macros available |
||||
to the average program (gcc -E -dM | grep MAP_*) |
||||
|
||||
Extend the list of errno codes. |
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
|
||||
diff --git a/manual/llio.texi b/manual/llio.texi |
||||
index fe1807a849..78c7c79913 100644 |
||||
--- a/manual/llio.texi |
||||
+++ b/manual/llio.texi |
||||
@@ -1573,10 +1573,15 @@ permitted. They include @code{PROT_READ}, @code{PROT_WRITE}, and |
||||
of address space for future use. The @code{mprotect} function can be |
||||
used to change the protection flags. @xref{Memory Protection}. |
||||
|
||||
-@var{flags} contains flags that control the nature of the map. |
||||
-One of @code{MAP_SHARED} or @code{MAP_PRIVATE} must be specified. |
||||
+The @var{flags} parameter contains flags that control the nature of |
||||
+the map. One of @code{MAP_SHARED}, @code{MAP_SHARED_VALIDATE}, or |
||||
+@code{MAP_PRIVATE} must be specified. Additional flags may be bitwise |
||||
+OR'd to further define the mapping. |
||||
|
||||
-They include: |
||||
+Note that, aside from @code{MAP_PRIVATE} and @code{MAP_SHARED}, not |
||||
+all flags are supported on all versions of all operating systems. |
||||
+Consult the kernel-specific documentation for details. The flags |
||||
+include: |
||||
|
||||
@vtable @code |
||||
@item MAP_PRIVATE |
||||
@@ -1598,9 +1603,19 @@ Note that actual writing may take place at any time. You need to use |
||||
@code{msync}, described below, if it is important that other processes |
||||
using conventional I/O get a consistent view of the file. |
||||
|
||||
+@item MAP_SHARED_VALIDATE |
||||
+Similar to @code{MAP_SHARED} except that additional flags will be |
||||
+validated by the kernel, and the call will fail if an unrecognized |
||||
+flag is provided. With @code{MAP_SHARED} using a flag on a kernel |
||||
+that doesn't support it causes the flag to be ignored. |
||||
+@code{MAP_SHARED_VALIDATE} should be used when the behavior of all |
||||
+flags is required. |
||||
+ |
||||
@item MAP_FIXED |
||||
This forces the system to use the exact mapping address specified in |
||||
-@var{address} and fail if it can't. |
||||
+@var{address} and fail if it can't. Note that if the new mapping |
||||
+would overlap an existing mapping, the overlapping portion of the |
||||
+existing map is unmapped. |
||||
|
||||
@c One of these is official - the other is obviously an obsolete synonym |
||||
@c Which is which? |
||||
@@ -1641,10 +1656,73 @@ The @code{MAP_HUGETLB} flag is specific to Linux. |
||||
@c There is a mechanism to select different hugepage sizes; see |
||||
@c include/uapi/asm-generic/hugetlb_encode.h in the kernel sources. |
||||
|
||||
-@c Linux has some other MAP_ options, which I have not discussed here. |
||||
-@c MAP_DENYWRITE, MAP_EXECUTABLE and MAP_GROWSDOWN don't seem applicable to |
||||
-@c user programs (and I don't understand the last two). MAP_LOCKED does |
||||
-@c not appear to be implemented. |
||||
+@item MAP_32BIT |
||||
+Require addresses that can be accessed with a signed 32 bit pointer, |
||||
+i.e., within the first 2 GiB. Ignored if MAP_FIXED is specified. |
||||
+ |
||||
+@item MAP_DENYWRITE |
||||
+@itemx MAP_EXECUTABLE |
||||
+@itemx MAP_FILE |
||||
+ |
||||
+Provided for compatibility. Ignored by the Linux kernel. |
||||
+ |
||||
+@item MAP_FIXED_NOREPLACE |
||||
+Similar to @code{MAP_FIXED} except the call will fail with |
||||
+@code{EEXIST} if the new mapping would overwrite an existing mapping. |
||||
+To test for support for this flag, specify MAP_FIXED_NOREPLACE without |
||||
+MAP_FIXED, and (if the call was successful) check the actual address |
||||
+returned. If it does not match the address passed, then this flag is |
||||
+not supported. |
||||
+ |
||||
+@item MAP_GROWSDOWN |
||||
+This flag is used to make stacks, and is typically only needed inside |
||||
+the program loader to set up the main stack for the running process. |
||||
+The mapping is created according to the other flags, except an |
||||
+additional page just prior to the mapping is marked as a ``guard |
||||
+page''. If a write is attempted inside this guard page, that page is |
||||
+mapped, the mapping is extended, and a new guard page is created. |
||||
+Thus, the mapping continues to grow towards lower addresses until it |
||||
+encounters some other mapping. |
||||
+ |
||||
+Note that accessing memory beyond the guard page will not trigger this |
||||
+feature. In gcc, use @code{-fstack-clash-protection} to ensure the |
||||
+guard page is always touched. |
||||
+ |
||||
+@item MAP_LOCKED |
||||
+A hint that requests that mapped pages are locked in memory (i.e. not |
||||
+paged out). Note that this is a request and not a requirement; use |
||||
+@code{mlock} if locking is required. |
||||
+ |
||||
+@item MAP_POPULATE |
||||
+@itemx MAP_NONBLOCK |
||||
+@code{MAP_POPULATE} is a hint that requests that the kernel read-ahead |
||||
+a file-backed mapping, causing pages to be mapped before they're |
||||
+needed. @code{MAP_NONBLOCK} is a hint that requests that the kernel |
||||
+@emph{not} attempt such except for pages are already in memory. Note |
||||
+that neither of these hints affects future paging activity, use |
||||
+@code{mlock} if such needs to be controlled. |
||||
+ |
||||
+@item MAP_NORESERVE |
||||
+Asks the kernel to not reserve physical backing (i.e. space in a swap |
||||
+device) for a mapping. This would be useful for, for example, a very |
||||
+large but sparsely used mapping which need not be limited in total |
||||
+length by available RAM, but with very few mapped pages. Note that |
||||
+writes to such a mapping may cause a @code{SIGSEGV} if the system is |
||||
+unable to map a page due to lack of resources. |
||||
+ |
||||
+On Linux, this flag's behavior may be overwridden by |
||||
+@file{/proc/sys/vm/overcommit_memory} as documented in the proc(5) man |
||||
+page. |
||||
+ |
||||
+@item MAP_STACK |
||||
+Ensures that the resulting mapping is suitable for use as a program |
||||
+stack. For example, the use of huge pages might be precluded. |
||||
+ |
||||
+@item MAP_SYNC |
||||
+This is a special flag for DAX devices, which tells the kernel to |
||||
+write dirty metadata out whenever dirty data is written out. Unlike |
||||
+most other flags, this one will fail unless @code{MAP_SHARED_VALIDATE} |
||||
+is also given. |
||||
|
||||
@end vtable |
||||
|
||||
@@ -1655,6 +1733,24 @@ Possible errors include: |
||||
|
||||
@table @code |
||||
|
||||
+@item EACCES |
||||
+ |
||||
+@var{filedes} was not open for the type of access specified in @var{protect}. |
||||
+ |
||||
+@item EAGAIN |
||||
+ |
||||
+The system has temporarily run out of resources. |
||||
+ |
||||
+@item EBADF |
||||
+ |
||||
+The @var{fd} passed is invalid, and a valid file descriptor is |
||||
+required (i.e. MAP_ANONYMOUS was not specified). |
||||
+ |
||||
+@item EEXIST |
||||
+ |
||||
+@code{MAP_FIXED_NOREPLACE} was specified and an existing mapping was |
||||
+found overlapping the requested address range. |
||||
+ |
||||
@item EINVAL |
||||
|
||||
Either @var{address} was unusable (because it is not a multiple of the |
||||
@@ -1663,23 +1759,37 @@ applicable page size), or inconsistent @var{flags} were given. |
||||
If @code{MAP_HUGETLB} was specified, the file or system does not support |
||||
large page sizes. |
||||
|
||||
-@item EACCES |
||||
+@item ENODEV |
||||
|
||||
-@var{filedes} was not open for the type of access specified in @var{protect}. |
||||
+This file is of a type that doesn't support mapping, the process has |
||||
+exceeded its data space limit, or the map request would exceed the |
||||
+process's virtual address space. |
||||
|
||||
@item ENOMEM |
||||
|
||||
-Either there is not enough memory for the operation, or the process is |
||||
-out of address space. |
||||
- |
||||
-@item ENODEV |
||||
- |
||||
-This file is of a type that doesn't support mapping. |
||||
+There is not enough memory for the operation, the process is out of |
||||
+address space, or there are too many mappings. On Linux, the maximum |
||||
+number of mappings can be controlled via |
||||
+@file{/proc/sys/vm/max_map_count} or, if your OS supports it, via |
||||
+the @code{vm.max_map_count} @code{sysctl} setting. |
||||
|
||||
@item ENOEXEC |
||||
|
||||
The file is on a filesystem that doesn't support mapping. |
||||
|
||||
+@item EPERM |
||||
+ |
||||
+@code{PROT_EXEC} was requested but the file is on a filesystem that |
||||
+was mounted with execution denied, a file seal prevented the mapping, |
||||
+or the caller set MAP_HUDETLB but does not have the required |
||||
+priviledges. |
||||
+ |
||||
+@item EOVERFLOW |
||||
+ |
||||
+Either the offset into the file plus the length of the mapping causes |
||||
+internal page counts to overflow, or the offset requested exceeds the |
||||
+length of the file. |
||||
+ |
||||
@c On Linux, EAGAIN will appear if the file has a conflicting mandatory lock. |
||||
@c However mandatory locks are not discussed in this manual. |
||||
@c |
@ -0,0 +1,207 @@
@@ -0,0 +1,207 @@
|
||||
Author: Charles Fol <folcharles@gmail.com> |
||||
Date: Thu Mar 28 12:25:38 2024 -0300 |
||||
|
||||
iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence (CVE-2024-2961) |
||||
|
||||
ISO-2022-CN-EXT uses escape sequences to indicate character set changes |
||||
(as specified by RFC 1922). While the SOdesignation has the expected |
||||
bounds checks, neither SS2designation nor SS3designation have its; |
||||
allowing a write overflow of 1, 2, or 3 bytes with fixed values: |
||||
'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'. |
||||
|
||||
Checked on aarch64-linux-gnu. |
||||
|
||||
Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
Tested-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
Conflicts: |
||||
iconvdata/Makefile |
||||
(usual tests conflict) |
||||
|
||||
diff --git a/iconvdata/Makefile b/iconvdata/Makefile |
||||
index d5507a048c6a6508..25bd004e7f92a994 100644 |
||||
--- a/iconvdata/Makefile |
||||
+++ b/iconvdata/Makefile |
||||
@@ -75,7 +75,7 @@ ifeq (yes,$(build-shared)) |
||||
tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ |
||||
tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ |
||||
bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \ |
||||
- bug-iconv13 bug-iconv14 bug-iconv15 |
||||
+ bug-iconv13 bug-iconv14 bug-iconv15 tst-iconv-iso-2022-cn-ext |
||||
ifeq ($(have-thread-library),yes) |
||||
tests += bug-iconv3 |
||||
endif |
||||
@@ -330,6 +330,8 @@ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \ |
||||
$(addprefix $(objpfx),$(modules.so)) |
||||
$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \ |
||||
$(addprefix $(objpfx),$(modules.so)) |
||||
+$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \ |
||||
+ $(addprefix $(objpfx),$(modules.so)) |
||||
|
||||
$(objpfx)iconv-test.out: run-iconv-test.sh \ |
||||
$(addprefix $(objpfx), $(gconv-modules)) \ |
||||
diff --git a/iconvdata/iso-2022-cn-ext.c b/iconvdata/iso-2022-cn-ext.c |
||||
index 2aca91c021f21ba0..c1339fe933d9d1c4 100644 |
||||
--- a/iconvdata/iso-2022-cn-ext.c |
||||
+++ b/iconvdata/iso-2022-cn-ext.c |
||||
@@ -575,6 +575,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); |
||||
{ \ |
||||
const char *escseq; \ |
||||
\ |
||||
+ if (outptr + 4 > outend) \ |
||||
+ { \ |
||||
+ result = __GCONV_FULL_OUTPUT; \ |
||||
+ break; \ |
||||
+ } \ |
||||
+ \ |
||||
assert (used == CNS11643_2_set); /* XXX */ \ |
||||
escseq = "*H"; \ |
||||
*outptr++ = ESC; \ |
||||
@@ -588,6 +594,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); |
||||
{ \ |
||||
const char *escseq; \ |
||||
\ |
||||
+ if (outptr + 4 > outend) \ |
||||
+ { \ |
||||
+ result = __GCONV_FULL_OUTPUT; \ |
||||
+ break; \ |
||||
+ } \ |
||||
+ \ |
||||
assert ((used >> 5) >= 3 && (used >> 5) <= 7); \ |
||||
escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; \ |
||||
*outptr++ = ESC; \ |
||||
diff --git a/iconvdata/tst-iconv-iso-2022-cn-ext.c b/iconvdata/tst-iconv-iso-2022-cn-ext.c |
||||
new file mode 100644 |
||||
index 0000000000000000..96a8765fd5369681 |
||||
--- /dev/null |
||||
+++ b/iconvdata/tst-iconv-iso-2022-cn-ext.c |
||||
@@ -0,0 +1,128 @@ |
||||
+/* Verify ISO-2022-CN-EXT does not write out of the bounds. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <stdio.h> |
||||
+#include <string.h> |
||||
+ |
||||
+#include <errno.h> |
||||
+#include <iconv.h> |
||||
+#include <sys/mman.h> |
||||
+ |
||||
+#include <support/xunistd.h> |
||||
+#include <support/check.h> |
||||
+#include <support/support.h> |
||||
+ |
||||
+/* The test sets up a two memory page buffer with the second page marked |
||||
+ PROT_NONE to trigger a fault if the conversion writes beyond the exact |
||||
+ expected amount. Then we carry out various conversions and precisely |
||||
+ place the start of the output buffer in order to trigger a SIGSEGV if the |
||||
+ process writes anywhere between 1 and page sized bytes more (only one |
||||
+ PROT_NONE page is setup as a canary) than expected. These tests exercise |
||||
+ all three of the cases in ISO-2022-CN-EXT where the converter must switch |
||||
+ character sets and may run out of buffer space while doing the |
||||
+ operation. */ |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8"); |
||||
+ TEST_VERIFY_EXIT (cd != (iconv_t) -1); |
||||
+ |
||||
+ char *ntf; |
||||
+ size_t ntfsize; |
||||
+ char *outbufbase; |
||||
+ { |
||||
+ int pgz = getpagesize (); |
||||
+ TEST_VERIFY_EXIT (pgz > 0); |
||||
+ ntfsize = 2 * pgz; |
||||
+ |
||||
+ ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE |
||||
+ | MAP_ANONYMOUS, -1); |
||||
+ xmprotect (ntf + pgz, pgz, PROT_NONE); |
||||
+ |
||||
+ outbufbase = ntf + pgz; |
||||
+ } |
||||
+ |
||||
+ /* Check if SOdesignation escape sequence does not trigger an OOB write. */ |
||||
+ { |
||||
+ char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2"; |
||||
+ |
||||
+ for (int i = 0; i < 9; i++) |
||||
+ { |
||||
+ char *inp = inbuf; |
||||
+ size_t inleft = sizeof (inbuf) - 1; |
||||
+ |
||||
+ char *outp = outbufbase - i; |
||||
+ size_t outleft = i; |
||||
+ |
||||
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft) |
||||
+ == (size_t) -1); |
||||
+ TEST_COMPARE (errno, E2BIG); |
||||
+ |
||||
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0); |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ /* Same as before for SS2designation. */ |
||||
+ { |
||||
+ char inbuf[] = "㴽 \xe3\xb4\xbd"; |
||||
+ |
||||
+ for (int i = 0; i < 14; i++) |
||||
+ { |
||||
+ char *inp = inbuf; |
||||
+ size_t inleft = sizeof (inbuf) - 1; |
||||
+ |
||||
+ char *outp = outbufbase - i; |
||||
+ size_t outleft = i; |
||||
+ |
||||
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft) |
||||
+ == (size_t) -1); |
||||
+ TEST_COMPARE (errno, E2BIG); |
||||
+ |
||||
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0); |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ /* Same as before for SS3designation. */ |
||||
+ { |
||||
+ char inbuf[] = "劄 \xe5\x8a\x84"; |
||||
+ |
||||
+ for (int i = 0; i < 14; i++) |
||||
+ { |
||||
+ char *inp = inbuf; |
||||
+ size_t inleft = sizeof (inbuf) - 1; |
||||
+ |
||||
+ char *outp = outbufbase - i; |
||||
+ size_t outleft = i; |
||||
+ |
||||
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft) |
||||
+ == (size_t) -1); |
||||
+ TEST_COMPARE (errno, E2BIG); |
||||
+ |
||||
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0); |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ TEST_VERIFY_EXIT (iconv_close (cd) != -1); |
||||
+ |
||||
+ xmunmap (ntf, ntfsize); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
@ -0,0 +1,142 @@
@@ -0,0 +1,142 @@
|
||||
commit 3a83f79024cc023a74c3892a1673542e8e972485 |
||||
Author: Sergey Kolosov <skolosov@redhat.com> |
||||
Date: Wed Apr 10 17:58:05 2024 +0200 |
||||
|
||||
socket: Add new test for connect |
||||
|
||||
This commit adds a simple bind/accept/connect test for an IPv4 TCP |
||||
connection to a local process via the loopback interface. |
||||
|
||||
Reviewed-by: Arjun Shankar <arjun@redhat.com> |
||||
|
||||
diff -Nrup a/socket/Makefile b/socket/Makefile |
||||
--- a/socket/Makefile 2024-05-19 21:52:59.775055152 -0400 |
||||
+++ b/socket/Makefile 2024-05-19 22:05:27.717703460 -0400 |
||||
@@ -33,8 +33,9 @@ routines := accept bind connect getpeern |
||||
|
||||
tests := \ |
||||
tst-accept4 \ |
||||
- tst-sockopt \ |
||||
tst-cmsghdr \ |
||||
+ tst-connect \ |
||||
+ tst-sockopt \ |
||||
# tests |
||||
|
||||
tests-internal := \ |
||||
diff -Nrup a/socket/tst-connect.c b/socket/tst-connect.c |
||||
--- a/socket/tst-connect.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/socket/tst-connect.c 2024-05-19 21:58:22.069058144 -0400 |
||||
@@ -0,0 +1,113 @@ |
||||
+/* Test the connect function. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <arpa/inet.h> |
||||
+#include <errno.h> |
||||
+#include <fcntl.h> |
||||
+#include <signal.h> |
||||
+#include <stdbool.h> |
||||
+#include <support/check.h> |
||||
+#include <support/xsocket.h> |
||||
+#include <support/xunistd.h> |
||||
+#include <sys/socket.h> |
||||
+#include <stdio.h> |
||||
+ |
||||
+static struct sockaddr_in server_address; |
||||
+ |
||||
+int |
||||
+open_socket_inet_tcp (void) |
||||
+{ |
||||
+ int fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); |
||||
+ if (fd < 0) |
||||
+ { |
||||
+ if (errno == EAFNOSUPPORT) |
||||
+ FAIL_UNSUPPORTED ("The host does not support IPv4"); |
||||
+ else |
||||
+ FAIL_EXIT1 ("socket (AF_INET, SOCK_STREAM, IPPROTO_TCP): %m\n"); |
||||
+ } |
||||
+ return fd; |
||||
+} |
||||
+ |
||||
+static pid_t |
||||
+start_server (void) |
||||
+{ |
||||
+ server_address.sin_family = AF_INET; |
||||
+ server_address.sin_port = 0; |
||||
+ server_address.sin_addr.s_addr = htonl (INADDR_LOOPBACK); |
||||
+ |
||||
+ int server_sock = open_socket_inet_tcp (); |
||||
+ |
||||
+ xbind (server_sock, (struct sockaddr *) &server_address, |
||||
+ sizeof (server_address)); |
||||
+ |
||||
+ socklen_t sa_len = sizeof (server_address); |
||||
+ xgetsockname (server_sock, (struct sockaddr *) &server_address, &sa_len); |
||||
+ xlisten (server_sock, 5); |
||||
+ |
||||
+ pid_t my_pid = xfork (); |
||||
+ if (my_pid > 0) |
||||
+ { |
||||
+ xclose (server_sock); |
||||
+ return my_pid; |
||||
+ } |
||||
+ |
||||
+ struct sockaddr_in client_address; |
||||
+ socklen_t ca_len = sizeof (server_address); |
||||
+ int client_sock = xaccept (server_sock, (struct sockaddr *) &client_address, |
||||
+ &ca_len); |
||||
+ printf ("socket accepted %d\n", client_sock); |
||||
+ |
||||
+ _exit (0); |
||||
+} |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ pid_t serv_pid; |
||||
+ struct sockaddr_in peer; |
||||
+ socklen_t peer_len; |
||||
+ |
||||
+ serv_pid = start_server (); |
||||
+ int client_sock = open_socket_inet_tcp (); |
||||
+ xconnect (client_sock, (const struct sockaddr *) &server_address, |
||||
+ sizeof (server_address)); |
||||
+ |
||||
+ /* A second connect with same arguments should fail with EISCONN. */ |
||||
+ int result = connect (client_sock, |
||||
+ (const struct sockaddr *) &server_address, |
||||
+ sizeof (server_address)); |
||||
+ if (result == 0 || errno != EISCONN) |
||||
+ FAIL_EXIT1 ("Second connect (%d), should fail with EISCONN: %m", |
||||
+ client_sock); |
||||
+ |
||||
+ peer_len = sizeof (peer); |
||||
+ xgetpeername (client_sock, (struct sockaddr *) &peer, &peer_len); |
||||
+ TEST_COMPARE (peer_len, sizeof (peer)); |
||||
+ TEST_COMPARE (peer.sin_port, server_address.sin_port); |
||||
+ TEST_COMPARE_BLOB (&peer.sin_addr, sizeof (peer.sin_addr), |
||||
+ &server_address.sin_addr, |
||||
+ sizeof (server_address.sin_addr)); |
||||
+ |
||||
+ int status; |
||||
+ xwaitpid (serv_pid, &status, 0); |
||||
+ TEST_COMPARE (status, 0); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
commit 6687a6e3f962759536a8019d31c68c1009ccd6eb |
||||
Author: Sergey Kolosov <skolosov@redhat.com> |
||||
Date: Wed Apr 10 17:58:04 2024 +0200 |
||||
|
||||
libsupport: Add xgetpeername |
||||
|
||||
The patch adds redirections for getpeername. |
||||
|
||||
Reviewed-by: Arjun Shankar <arjun@redhat.com> |
||||
|
||||
diff -Nrup a/support/Makefile b/support/Makefile |
||||
--- a/support/Makefile 2024-05-19 23:27:12.379362736 -0400 |
||||
+++ b/support/Makefile 2024-05-19 23:29:28.668182089 -0400 |
||||
@@ -126,6 +126,7 @@ libsupport-routines = \ |
||||
xfork \ |
||||
xftruncate \ |
||||
xgetline \ |
||||
+ xgetpeername \ |
||||
xgetsockname \ |
||||
xlisten \ |
||||
xlseek \ |
||||
diff -Nrup a/support/xgetpeername.c b/support/xgetpeername.c |
||||
--- a/support/xgetpeername.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/support/xgetpeername.c 2024-05-19 23:30:31.852561947 -0400 |
||||
@@ -0,0 +1,30 @@ |
||||
+/* getpeername with error checking. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <support/xsocket.h> |
||||
+ |
||||
+#include <stdio.h> |
||||
+#include <stdlib.h> |
||||
+#include <support/check.h> |
||||
+ |
||||
+void |
||||
+xgetpeername (int fd, struct sockaddr *sa, socklen_t *plen) |
||||
+{ |
||||
+ if (getpeername (fd, sa, plen) != 0) |
||||
+ FAIL_EXIT1 ("getpeername (%d): %m", fd); |
||||
+} |
||||
diff -Nrup a/support/xsocket.h b/support/xsocket.h |
||||
--- a/support/xsocket.h 2021-08-01 21:33:43.000000000 -0400 |
||||
+++ b/support/xsocket.h 2024-05-19 23:31:24.541878715 -0400 |
||||
@@ -26,6 +26,7 @@ |
||||
int xsocket (int, int, int); |
||||
void xsetsockopt (int, int, int, const void *, socklen_t); |
||||
void xgetsockname (int, struct sockaddr *, socklen_t *); |
||||
+void xgetpeername (int, struct sockaddr *, socklen_t *); |
||||
void xconnect (int, const struct sockaddr *, socklen_t); |
||||
void xbind (int, const struct sockaddr *, socklen_t); |
||||
void xlisten (int, int); |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
commit 87801a8fd06db1d654eea3e4f7626ff476a9bdaa |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Thu Apr 25 15:00:45 2024 +0200 |
||||
|
||||
CVE-2024-33599: nscd: Stack-based buffer overflow in netgroup cache (bug 31677) |
||||
|
||||
Using alloca matches what other caches do. The request length is |
||||
bounded by MAXKEYLEN. |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c |
||||
index 0c6e46f15c..f227dc7fa2 100644 |
||||
--- a/nscd/netgroupcache.c |
||||
+++ b/nscd/netgroupcache.c |
||||
@@ -502,12 +502,13 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, |
||||
= (struct indataset *) mempool_alloc (db, |
||||
sizeof (*dataset) + req->key_len, |
||||
1); |
||||
- struct indataset dataset_mem; |
||||
bool cacheable = true; |
||||
if (__glibc_unlikely (dataset == NULL)) |
||||
{ |
||||
cacheable = false; |
||||
- dataset = &dataset_mem; |
||||
+ /* The alloca is safe because nscd_run_worker verfies that |
||||
+ key_len is not larger than MAXKEYLEN. */ |
||||
+ dataset = alloca (sizeof (*dataset) + req->key_len); |
||||
} |
||||
|
||||
datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len, |
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
commit b048a482f088e53144d26a61c390bed0210f49f2 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Thu Apr 25 15:01:07 2024 +0200 |
||||
|
||||
CVE-2024-33600: nscd: Avoid null pointer crashes after notfound response (bug 31678) |
||||
|
||||
The addgetnetgrentX call in addinnetgrX may have failed to produce |
||||
a result, so the result variable in addinnetgrX can be NULL. |
||||
Use db->negtimeout as the fallback value if there is no result data; |
||||
the timeout is also overwritten below. |
||||
|
||||
Also avoid sending a second not-found response. (The client |
||||
disconnects after receiving the first response, so the data stream did |
||||
not go out of sync even without this fix.) It is still beneficial to |
||||
add the negative response to the mapping, so that the client can get |
||||
it from there in the future, instead of going through the socket. |
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
|
||||
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c |
||||
index c18fe111f3..e22ffa5884 100644 |
||||
--- a/nscd/netgroupcache.c |
||||
+++ b/nscd/netgroupcache.c |
||||
@@ -511,14 +511,15 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, |
||||
|
||||
datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len, |
||||
sizeof (innetgroup_response_header), |
||||
- he == NULL ? 0 : dh->nreloads + 1, result->head.ttl); |
||||
+ he == NULL ? 0 : dh->nreloads + 1, |
||||
+ result == NULL ? db->negtimeout : result->head.ttl); |
||||
/* Set the notfound status and timeout based on the result from |
||||
getnetgrent. */ |
||||
- dataset->head.notfound = result->head.notfound; |
||||
+ dataset->head.notfound = result == NULL || result->head.notfound; |
||||
dataset->head.timeout = timeout; |
||||
|
||||
dataset->resp.version = NSCD_VERSION; |
||||
- dataset->resp.found = result->resp.found; |
||||
+ dataset->resp.found = result != NULL && result->resp.found; |
||||
/* Until we find a matching entry the result is 0. */ |
||||
dataset->resp.result = 0; |
||||
|
||||
@@ -566,7 +567,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, |
||||
goto out; |
||||
} |
||||
|
||||
- if (he == NULL) |
||||
+ /* addgetnetgrentX may have already sent a notfound response. Do |
||||
+ not send another one. */ |
||||
+ if (he == NULL && dataset->resp.found) |
||||
{ |
||||
/* We write the dataset before inserting it to the database |
||||
since while inserting this thread might block and so would |
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
commit 7835b00dbce53c3c87bbbb1754a95fb5e58187aa |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Thu Apr 25 15:01:07 2024 +0200 |
||||
|
||||
CVE-2024-33600: nscd: Do not send missing not-found response in addgetnetgrentX (bug 31678) |
||||
|
||||
If we failed to add a not-found response to the cache, the dataset |
||||
point can be null, resulting in a null pointer dereference. |
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
|
||||
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c |
||||
index f227dc7fa2..c18fe111f3 100644 |
||||
--- a/nscd/netgroupcache.c |
||||
+++ b/nscd/netgroupcache.c |
||||
@@ -147,7 +147,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, |
||||
/* No such service. */ |
||||
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, |
||||
&key_copy); |
||||
- goto writeout; |
||||
+ goto maybe_cache_add; |
||||
} |
||||
|
||||
memset (&data, '\0', sizeof (data)); |
||||
@@ -348,7 +348,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, |
||||
{ |
||||
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, |
||||
&key_copy); |
||||
- goto writeout; |
||||
+ goto maybe_cache_add; |
||||
} |
||||
|
||||
total = buffilled; |
||||
@@ -410,14 +410,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, |
||||
} |
||||
|
||||
if (he == NULL && fd != -1) |
||||
- { |
||||
- /* We write the dataset before inserting it to the database |
||||
- since while inserting this thread might block and so would |
||||
- unnecessarily let the receiver wait. */ |
||||
- writeout: |
||||
+ /* We write the dataset before inserting it to the database since |
||||
+ while inserting this thread might block and so would |
||||
+ unnecessarily let the receiver wait. */ |
||||
writeall (fd, &dataset->resp, dataset->head.recsize); |
||||
- } |
||||
|
||||
+ maybe_cache_add: |
||||
if (cacheable) |
||||
{ |
||||
/* If necessary, we also propagate the data to disk. */ |
@ -0,0 +1,382 @@
@@ -0,0 +1,382 @@
|
||||
commit c04a21e050d64a1193a6daab872bca2528bda44b |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Thu Apr 25 15:01:07 2024 +0200 |
||||
|
||||
CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX (bug 31680) |
||||
|
||||
This avoids potential memory corruption when the underlying NSS |
||||
callback function does not use the buffer space to store all strings |
||||
(e.g., for constant strings). |
||||
|
||||
Instead of custom buffer management, two scratch buffers are used. |
||||
This increases stack usage somewhat. |
||||
|
||||
Scratch buffer allocation failure is handled by return -1 |
||||
(an invalid timeout value) instead of terminating the process. |
||||
This fixes bug 31679. |
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
|
||||
diff -Nrup glibc-2.34/nscd/netgroupcache.c b/nscd/netgroupcache.c |
||||
--- glibc-2.34/nscd/netgroupcache.c 2024-06-13 13:55:16.406511485 -0400 |
||||
+++ b/nscd/netgroupcache.c 2024-06-13 13:34:45.523345077 -0400 |
||||
@@ -24,6 +24,7 @@ |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
#include <sys/mman.h> |
||||
+#include <scratch_buffer.h> |
||||
|
||||
#include "../inet/netgroup.h" |
||||
#include "nscd.h" |
||||
@@ -66,6 +67,16 @@ struct dataset |
||||
char strdata[0]; |
||||
}; |
||||
|
||||
+/* Send a notfound response to FD. Always returns -1 to indicate an |
||||
+ ephemeral error. */ |
||||
+static time_t |
||||
+send_notfound (int fd) |
||||
+{ |
||||
+ if (fd != -1) |
||||
+ TEMP_FAILURE_RETRY (send (fd, ¬found, sizeof (notfound), MSG_NOSIGNAL)); |
||||
+ return -1; |
||||
+} |
||||
+ |
||||
/* Sends a notfound message and prepares a notfound dataset to write to the |
||||
cache. Returns true if there was enough memory to allocate the dataset and |
||||
returns the dataset in DATASETP, total bytes to write in TOTALP and the |
||||
@@ -84,8 +95,7 @@ do_notfound (struct database_dyn *db, in |
||||
total = sizeof (notfound); |
||||
timeout = time (NULL) + db->negtimeout; |
||||
|
||||
- if (fd != -1) |
||||
- TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); |
||||
+ send_notfound (fd); |
||||
|
||||
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1); |
||||
/* If we cannot permanently store the result, so be it. */ |
||||
@@ -110,11 +120,78 @@ do_notfound (struct database_dyn *db, in |
||||
return cacheable; |
||||
} |
||||
|
||||
+struct addgetnetgrentX_scratch |
||||
+{ |
||||
+ /* This is the result that the caller should use. It can be NULL, |
||||
+ point into buffer, or it can be in the cache. */ |
||||
+ struct dataset *dataset; |
||||
+ |
||||
+ struct scratch_buffer buffer; |
||||
+ |
||||
+ /* Used internally in addgetnetgrentX as a staging area. */ |
||||
+ struct scratch_buffer tmp; |
||||
+ |
||||
+ /* Number of bytes in buffer that are actually used. */ |
||||
+ size_t buffer_used; |
||||
+}; |
||||
+ |
||||
+static void |
||||
+addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch) |
||||
+{ |
||||
+ scratch->dataset = NULL; |
||||
+ scratch_buffer_init (&scratch->buffer); |
||||
+ scratch_buffer_init (&scratch->tmp); |
||||
+ |
||||
+ /* Reserve space for the header. */ |
||||
+ scratch->buffer_used = sizeof (struct dataset); |
||||
+ static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space), |
||||
+ "initial buffer space"); |
||||
+ memset (scratch->tmp.data, 0, sizeof (struct dataset)); |
||||
+} |
||||
+ |
||||
+static void |
||||
+addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch) |
||||
+{ |
||||
+ scratch_buffer_free (&scratch->buffer); |
||||
+ scratch_buffer_free (&scratch->tmp); |
||||
+} |
||||
+ |
||||
+/* Copy LENGTH bytes from S into SCRATCH. Returns NULL if SCRATCH |
||||
+ could not be resized, otherwise a pointer to the copy. */ |
||||
+static char * |
||||
+addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch, |
||||
+ const char *s, size_t length) |
||||
+{ |
||||
+ while (true) |
||||
+ { |
||||
+ size_t remaining = scratch->buffer.length - scratch->buffer_used; |
||||
+ if (remaining >= length) |
||||
+ break; |
||||
+ if (!scratch_buffer_grow_preserve (&scratch->buffer)) |
||||
+ return NULL; |
||||
+ } |
||||
+ char *copy = scratch->buffer.data + scratch->buffer_used; |
||||
+ memcpy (copy, s, length); |
||||
+ scratch->buffer_used += length; |
||||
+ return copy; |
||||
+} |
||||
+ |
||||
+/* Copy S into SCRATCH, including its null terminator. Returns false |
||||
+ if SCRATCH could not be resized. */ |
||||
+static bool |
||||
+addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s) |
||||
+{ |
||||
+ if (s == NULL) |
||||
+ s = ""; |
||||
+ return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL; |
||||
+} |
||||
+ |
||||
+/* Caller must initialize and free *SCRATCH. If the return value is |
||||
+ negative, this function has sent a notfound response. */ |
||||
static time_t |
||||
addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, |
||||
const char *key, uid_t uid, struct hashentry *he, |
||||
- struct datahead *dh, struct dataset **resultp, |
||||
- void **tofreep) |
||||
+ struct datahead *dh, struct addgetnetgrentX_scratch *scratch) |
||||
{ |
||||
if (__glibc_unlikely (debug_level > 0)) |
||||
{ |
||||
@@ -133,14 +210,10 @@ addgetnetgrentX (struct database_dyn *db |
||||
|
||||
char *key_copy = NULL; |
||||
struct __netgrent data; |
||||
- size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len); |
||||
- size_t buffilled = sizeof (*dataset); |
||||
- char *buffer = NULL; |
||||
size_t nentries = 0; |
||||
size_t group_len = strlen (key) + 1; |
||||
struct name_list *first_needed |
||||
= alloca (sizeof (struct name_list) + group_len); |
||||
- *tofreep = NULL; |
||||
|
||||
if (netgroup_database == NULL |
||||
&& !__nss_database_get (nss_database_netgroup, &netgroup_database)) |
||||
@@ -152,8 +225,6 @@ addgetnetgrentX (struct database_dyn *db |
||||
} |
||||
|
||||
memset (&data, '\0', sizeof (data)); |
||||
- buffer = xmalloc (buflen); |
||||
- *tofreep = buffer; |
||||
first_needed->next = first_needed; |
||||
memcpy (first_needed->name, key, group_len); |
||||
data.needed_groups = first_needed; |
||||
@@ -196,8 +267,8 @@ addgetnetgrentX (struct database_dyn *db |
||||
while (1) |
||||
{ |
||||
int e; |
||||
- status = getfct.f (&data, buffer + buffilled, |
||||
- buflen - buffilled - req->key_len, &e); |
||||
+ status = getfct.f (&data, scratch->tmp.data, |
||||
+ scratch->tmp.length, &e); |
||||
if (status == NSS_STATUS_SUCCESS) |
||||
{ |
||||
if (data.type == triple_val) |
||||
@@ -205,68 +276,10 @@ addgetnetgrentX (struct database_dyn *db |
||||
const char *nhost = data.val.triple.host; |
||||
const char *nuser = data.val.triple.user; |
||||
const char *ndomain = data.val.triple.domain; |
||||
- |
||||
- size_t hostlen = strlen (nhost ?: "") + 1; |
||||
- size_t userlen = strlen (nuser ?: "") + 1; |
||||
- size_t domainlen = strlen (ndomain ?: "") + 1; |
||||
- |
||||
- if (nhost == NULL || nuser == NULL || ndomain == NULL |
||||
- || nhost > nuser || nuser > ndomain) |
||||
- { |
||||
- const char *last = nhost; |
||||
- if (last == NULL |
||||
- || (nuser != NULL && nuser > last)) |
||||
- last = nuser; |
||||
- if (last == NULL |
||||
- || (ndomain != NULL && ndomain > last)) |
||||
- last = ndomain; |
||||
- |
||||
- size_t bufused |
||||
- = (last == NULL |
||||
- ? buffilled |
||||
- : last + strlen (last) + 1 - buffer); |
||||
- |
||||
- /* We have to make temporary copies. */ |
||||
- size_t needed = hostlen + userlen + domainlen; |
||||
- |
||||
- if (buflen - req->key_len - bufused < needed) |
||||
- { |
||||
- buflen += MAX (buflen, 2 * needed); |
||||
- /* Save offset in the old buffer. We don't |
||||
- bother with the NULL check here since |
||||
- we'll do that later anyway. */ |
||||
- size_t nhostdiff = nhost - buffer; |
||||
- size_t nuserdiff = nuser - buffer; |
||||
- size_t ndomaindiff = ndomain - buffer; |
||||
- |
||||
- char *newbuf = xrealloc (buffer, buflen); |
||||
- /* Fix up the triplet pointers into the new |
||||
- buffer. */ |
||||
- nhost = (nhost ? newbuf + nhostdiff |
||||
- : NULL); |
||||
- nuser = (nuser ? newbuf + nuserdiff |
||||
- : NULL); |
||||
- ndomain = (ndomain ? newbuf + ndomaindiff |
||||
- : NULL); |
||||
- *tofreep = buffer = newbuf; |
||||
- } |
||||
- |
||||
- nhost = memcpy (buffer + bufused, |
||||
- nhost ?: "", hostlen); |
||||
- nuser = memcpy ((char *) nhost + hostlen, |
||||
- nuser ?: "", userlen); |
||||
- ndomain = memcpy ((char *) nuser + userlen, |
||||
- ndomain ?: "", domainlen); |
||||
- } |
||||
- |
||||
- char *wp = buffer + buffilled; |
||||
- wp = memmove (wp, nhost ?: "", hostlen); |
||||
- wp += hostlen; |
||||
- wp = memmove (wp, nuser ?: "", userlen); |
||||
- wp += userlen; |
||||
- wp = memmove (wp, ndomain ?: "", domainlen); |
||||
- wp += domainlen; |
||||
- buffilled = wp - buffer; |
||||
+ if (!(addgetnetgrentX_append (scratch, nhost) |
||||
+ && addgetnetgrentX_append (scratch, nuser) |
||||
+ && addgetnetgrentX_append (scratch, ndomain))) |
||||
+ return send_notfound (fd); |
||||
++nentries; |
||||
} |
||||
else |
||||
@@ -318,8 +331,8 @@ addgetnetgrentX (struct database_dyn *db |
||||
} |
||||
else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE) |
||||
{ |
||||
- buflen *= 2; |
||||
- *tofreep = buffer = xrealloc (buffer, buflen); |
||||
+ if (!scratch_buffer_grow (&scratch->tmp)) |
||||
+ return send_notfound (fd); |
||||
} |
||||
else if (status == NSS_STATUS_RETURN |
||||
|| status == NSS_STATUS_NOTFOUND |
||||
@@ -352,10 +365,17 @@ addgetnetgrentX (struct database_dyn *db |
||||
goto maybe_cache_add; |
||||
} |
||||
|
||||
- total = buffilled; |
||||
+ /* Capture the result size without the key appended. */ |
||||
+ total = scratch->buffer_used; |
||||
+ |
||||
+ /* Make a copy of the key. The scratch buffer must not move after |
||||
+ this point. */ |
||||
+ key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len); |
||||
+ if (key_copy == NULL) |
||||
+ return send_notfound (fd); |
||||
|
||||
/* Fill in the dataset. */ |
||||
- dataset = (struct dataset *) buffer; |
||||
+ dataset = scratch->buffer.data; |
||||
timeout = datahead_init_pos (&dataset->head, total + req->key_len, |
||||
total - offsetof (struct dataset, resp), |
||||
he == NULL ? 0 : dh->nreloads + 1, |
||||
@@ -364,11 +384,7 @@ addgetnetgrentX (struct database_dyn *db |
||||
dataset->resp.version = NSCD_VERSION; |
||||
dataset->resp.found = 1; |
||||
dataset->resp.nresults = nentries; |
||||
- dataset->resp.result_len = buffilled - sizeof (*dataset); |
||||
- |
||||
- assert (buflen - buffilled >= req->key_len); |
||||
- key_copy = memcpy (buffer + buffilled, key, req->key_len); |
||||
- buffilled += req->key_len; |
||||
+ dataset->resp.result_len = total - sizeof (*dataset); |
||||
|
||||
/* Now we can determine whether on refill we have to create a new |
||||
record or not. */ |
||||
@@ -399,7 +415,7 @@ addgetnetgrentX (struct database_dyn *db |
||||
if (__glibc_likely (newp != NULL)) |
||||
{ |
||||
/* Adjust pointer into the memory block. */ |
||||
- key_copy = (char *) newp + (key_copy - buffer); |
||||
+ key_copy = (char *) newp + (key_copy - (char *) dataset); |
||||
|
||||
dataset = memcpy (newp, dataset, total + req->key_len); |
||||
cacheable = true; |
||||
@@ -440,7 +456,7 @@ addgetnetgrentX (struct database_dyn *db |
||||
} |
||||
|
||||
out: |
||||
- *resultp = dataset; |
||||
+ scratch->dataset = dataset; |
||||
|
||||
return timeout; |
||||
} |
||||
@@ -461,6 +477,9 @@ addinnetgrX (struct database_dyn *db, in |
||||
if (user != NULL) |
||||
key = (char *) rawmemchr (key, '\0') + 1; |
||||
const char *domain = *key++ ? key : NULL; |
||||
+ struct addgetnetgrentX_scratch scratch; |
||||
+ |
||||
+ addgetnetgrentX_scratch_init (&scratch); |
||||
|
||||
if (__glibc_unlikely (debug_level > 0)) |
||||
{ |
||||
@@ -476,12 +495,8 @@ addinnetgrX (struct database_dyn *db, in |
||||
group, group_len, |
||||
db, uid); |
||||
time_t timeout; |
||||
- void *tofree; |
||||
if (result != NULL) |
||||
- { |
||||
- timeout = result->head.timeout; |
||||
- tofree = NULL; |
||||
- } |
||||
+ timeout = result->head.timeout; |
||||
else |
||||
{ |
||||
request_header req_get = |
||||
@@ -490,7 +505,10 @@ addinnetgrX (struct database_dyn *db, in |
||||
.key_len = group_len |
||||
}; |
||||
timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL, |
||||
- &result, &tofree); |
||||
+ &scratch); |
||||
+ result = scratch.dataset; |
||||
+ if (timeout < 0) |
||||
+ goto out; |
||||
} |
||||
|
||||
struct indataset |
||||
@@ -604,7 +622,7 @@ addinnetgrX (struct database_dyn *db, in |
||||
} |
||||
|
||||
out: |
||||
- free (tofree); |
||||
+ addgetnetgrentX_scratch_free (&scratch); |
||||
return timeout; |
||||
} |
||||
|
||||
@@ -614,11 +632,12 @@ addgetnetgrentX_ignore (struct database_ |
||||
const char *key, uid_t uid, struct hashentry *he, |
||||
struct datahead *dh) |
||||
{ |
||||
- struct dataset *ignore; |
||||
- void *tofree; |
||||
- time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, |
||||
- &ignore, &tofree); |
||||
- free (tofree); |
||||
+ struct addgetnetgrentX_scratch scratch; |
||||
+ addgetnetgrentX_scratch_init (&scratch); |
||||
+ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch); |
||||
+ addgetnetgrentX_scratch_free (&scratch); |
||||
+ if (timeout < 0) |
||||
+ timeout = 0; |
||||
return timeout; |
||||
} |
||||
|
||||
@@ -662,5 +681,9 @@ readdinnetgr (struct database_dyn *db, s |
||||
.key_len = he->len |
||||
}; |
||||
|
||||
- return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh); |
||||
+ int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner, |
||||
+ he, dh); |
||||
+ if (timeout < 0) |
||||
+ timeout = 0; |
||||
+ return timeout; |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
commit 4bbca1a44691a6e9adcee5c6798a707b626bc331 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Thu May 2 17:06:19 2024 +0200 |
||||
|
||||
nscd: Use time_t for return type of addgetnetgrentX |
||||
|
||||
Using int may give false results for future dates (timeouts after the |
||||
year 2028). |
||||
|
||||
Fixes commit 04a21e050d64a1193a6daab872bca2528bda44b ("CVE-2024-33601, |
||||
CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX |
||||
(bug 31680)"). |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c |
||||
index 4b35498e3f..5fdcf4204e 100644 |
||||
--- a/nscd/netgroupcache.c |
||||
+++ b/nscd/netgroupcache.c |
||||
@@ -680,8 +680,8 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he, |
||||
.key_len = he->len |
||||
}; |
||||
|
||||
- int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner, |
||||
- he, dh); |
||||
+ time_t timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner, |
||||
+ he, dh); |
||||
if (timeout < 0) |
||||
timeout = 0; |
||||
return timeout; |
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
commit fe06fb313bddf7e4530056897d4a706606e49377 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Thu Aug 1 23:31:23 2024 +0200 |
||||
|
||||
elf: Clarify and invert second argument of _dl_allocate_tls_init |
||||
|
||||
Also remove an outdated comment: _dl_allocate_tls_init is |
||||
called as part of pthread_create. |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff -Nrup a/elf/dl-tls.c b/elf/dl-tls.c |
||||
--- a/elf/dl-tls.c 2024-08-27 22:51:44.720953314 -0400 |
||||
+++ b/elf/dl-tls.c 2024-08-27 22:51:07.686759191 -0400 |
||||
@@ -558,9 +558,14 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_m |
||||
/* Allocate initial TLS. RESULT should be a non-NULL pointer to storage |
||||
for the TLS space. The DTV may be resized, and so this function may |
||||
call malloc to allocate that space. The loader's GL(dl_load_tls_lock) |
||||
- is taken when manipulating global TLS-related data in the loader. */ |
||||
+ is taken when manipulating global TLS-related data in the loader. |
||||
+ |
||||
+ If MAIN_THREAD, this is the first call during process |
||||
+ initialization. In this case, TLS initialization for secondary |
||||
+ (audit) namespaces is skipped because that has already been handled |
||||
+ by dlopen. */ |
||||
void * |
||||
-_dl_allocate_tls_init (void *result, bool init_tls) |
||||
+_dl_allocate_tls_init (void *result, bool main_thread) |
||||
{ |
||||
if (result == NULL) |
||||
/* The memory allocation failed. */ |
||||
@@ -639,7 +644,7 @@ _dl_allocate_tls_init (void *result, boo |
||||
because it would already be set by the audit setup. However, |
||||
subsequent thread creation would need to follow the default |
||||
behaviour. */ |
||||
- if (map->l_ns != LM_ID_BASE && !init_tls) |
||||
+ if (map->l_ns != LM_ID_BASE && main_thread) |
||||
continue; |
||||
memset (__mempcpy (dest, map->l_tls_initimage, |
||||
map->l_tls_initimage_size), '\0', |
||||
@@ -667,7 +672,7 @@ _dl_allocate_tls (void *mem) |
||||
{ |
||||
return _dl_allocate_tls_init (mem == NULL |
||||
? _dl_allocate_tls_storage () |
||||
- : allocate_dtv (mem), true); |
||||
+ : allocate_dtv (mem), false); |
||||
} |
||||
rtld_hidden_def (_dl_allocate_tls) |
||||
|
||||
diff -Nrup a/elf/rtld.c b/elf/rtld.c |
||||
--- a/elf/rtld.c 2024-08-27 22:51:44.720953314 -0400 |
||||
+++ b/elf/rtld.c 2024-08-27 22:54:51.136930475 -0400 |
||||
@@ -2485,7 +2485,7 @@ dl_main (const ElfW(Phdr) *phdr, |
||||
into the main thread's TLS area, which we allocated above. |
||||
Note: thread-local variables must only be accessed after completing |
||||
the next step. */ |
||||
- _dl_allocate_tls_init (tcbp, false); |
||||
+ _dl_allocate_tls_init (tcbp, true); |
||||
|
||||
/* And finally install it for the main thread. */ |
||||
if (! tls_init_tp_called) |
||||
diff -Nrup a/nptl/allocatestack.c b/nptl/allocatestack.c |
||||
--- a/nptl/allocatestack.c 2024-08-27 22:51:43.922949131 -0400 |
||||
+++ b/nptl/allocatestack.c 2024-08-27 22:51:07.687759197 -0400 |
||||
@@ -137,7 +137,7 @@ get_cached_stack (size_t *sizep, void ** |
||||
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t)); |
||||
|
||||
/* Re-initialize the TLS. */ |
||||
- _dl_allocate_tls_init (TLS_TPADJ (result), true); |
||||
+ _dl_allocate_tls_init (TLS_TPADJ (result), false); |
||||
|
||||
return result; |
||||
} |
||||
diff -Nrup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
--- a/sysdeps/generic/ldsodefs.h 2024-08-27 22:51:44.720953314 -0400 |
||||
+++ b/sysdeps/generic/ldsodefs.h 2024-08-27 22:56:44.425524320 -0400 |
||||
@@ -1258,10 +1258,8 @@ extern void _dl_get_tls_static_info (siz |
||||
|
||||
extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden; |
||||
|
||||
-/* These are internal entry points to the two halves of _dl_allocate_tls, |
||||
- only used within rtld.c itself at startup time. */ |
||||
extern void *_dl_allocate_tls_storage (void) attribute_hidden; |
||||
-extern void *_dl_allocate_tls_init (void *, bool); |
||||
+extern void *_dl_allocate_tls_init (void *result, bool main_thread); |
||||
rtld_hidden_proto (_dl_allocate_tls_init) |
||||
|
||||
/* Deallocate memory allocated with _dl_allocate_tls. */ |
@ -0,0 +1,520 @@
@@ -0,0 +1,520 @@
|
||||
commit 5097cd344fd243fb8deb6dec96e8073753f962f9 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Thu Aug 1 23:31:30 2024 +0200 |
||||
|
||||
elf: Avoid re-initializing already allocated TLS in dlopen (bug 31717) |
||||
|
||||
The old code used l_init_called as an indicator for whether TLS |
||||
initialization was complete. However, it is possible that |
||||
TLS for an object is initialized, written to, and then dlopen |
||||
for this object is called again, and l_init_called is not true at |
||||
this point. Previously, this resulted in TLS being initialized |
||||
twice, discarding any interim writes (technically introducing a |
||||
use-after-free bug even). |
||||
|
||||
This commit introduces an explicit per-object flag, l_tls_in_slotinfo. |
||||
It indicates whether _dl_add_to_slotinfo has been called for this |
||||
object. This flag is used to avoid double-initialization of TLS. |
||||
In update_tls_slotinfo, the first_static_tls micro-optimization |
||||
is removed because preserving the initalization flag for subsequent |
||||
use by the second loop for static TLS is a bit complicated, and |
||||
another per-object flag does not seem to be worth it. Furthermore, |
||||
the l_init_called flag is dropped from the second loop (for static |
||||
TLS initialization) because l_need_tls_init on its own prevents |
||||
double-initialization. |
||||
|
||||
The remaining l_init_called usage in resize_scopes and update_scopes |
||||
is just an optimization due to the use of scope_has_map, so it is |
||||
not changed in this commit. |
||||
|
||||
The isupper check ensures that libc.so.6 is TLS is not reverted. |
||||
Such a revert happens if l_need_tls_init is not cleared in |
||||
_dl_allocate_tls_init for the main_thread case, now that |
||||
l_init_called is not checked anymore in update_tls_slotinfo |
||||
in elf/dl-open.c. |
||||
|
||||
Reported-by: Jonathon Anderson <janderson@rice.edu> |
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff -Nrup a/elf/Makefile b/elf/Makefile |
||||
--- a/elf/Makefile 2024-08-27 23:25:59.327755050 -0400 |
||||
+++ b/elf/Makefile 2024-08-27 23:16:50.456864065 -0400 |
||||
@@ -399,6 +399,10 @@ tests += \ |
||||
tst-dlmopen-dlerror \ |
||||
tst-dlmopen-gethostbyname \ |
||||
tst-dlmopen-twice \ |
||||
+ tst-dlopen-tlsreinit1 \ |
||||
+ tst-dlopen-tlsreinit2 \ |
||||
+ tst-dlopen-tlsreinit3 \ |
||||
+ tst-dlopen-tlsreinit4 \ |
||||
tst-dlopenfail \ |
||||
tst-dlopenfail-2 \ |
||||
tst-dlopenrpath \ |
||||
@@ -753,6 +757,9 @@ modules-names = \ |
||||
tst-dlmopen-gethostbyname-mod \ |
||||
tst-dlmopen-twice-mod1 \ |
||||
tst-dlmopen-twice-mod2 \ |
||||
+ tst-dlopen-tlsreinitmod1 \ |
||||
+ tst-dlopen-tlsreinitmod2 \ |
||||
+ tst-dlopen-tlsreinitmod3 \ |
||||
tst-dlopenfaillinkmod \ |
||||
tst-dlopenfailmod1 \ |
||||
tst-dlopenfailmod2 \ |
||||
@@ -2751,3 +2758,26 @@ $(objpfx)tst-recursive-tls.out: \ |
||||
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) |
||||
$(objpfx)tst-recursive-tlsmod%.os: tst-recursive-tlsmodN.c |
||||
$(compile-command.c) -DVAR=thread_$* -DFUNC=get_threadvar_$* |
||||
+ |
||||
+# Order matters here. The test needs the constructor for |
||||
+# tst-dlopen-tlsreinitmod2.so to be called first. |
||||
+LDFLAGS-tst-dlopen-tlsreinitmod1.so = -Wl,--no-as-needed |
||||
+$(objpfx)tst-dlopen-tlsreinitmod1.so: \ |
||||
+ $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so |
||||
+LDFLAGS-tst-dlopen-tlsreinit2 = -Wl,--no-as-needed |
||||
+$(objpfx)tst-dlopen-tlsreinit2: \ |
||||
+ $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so |
||||
+LDFLAGS-tst-dlopen-tlsreinit4 = -Wl,--no-as-needed |
||||
+$(objpfx)tst-dlopen-tlsreinit4: \ |
||||
+ $(objpfx)tst-dlopen-tlsreinitmod3.so $(objpfx)tst-dlopen-tlsreinitmod2.so |
||||
+# tst-dlopen-tlsreinitmod2.so is underlinked and refers to |
||||
+# tst-dlopen-tlsreinitmod3.so. The dependency is provided via |
||||
+# $(objpfx)tst-dlopen-tlsreinitmod1.so. |
||||
+tst-dlopen-tlsreinitmod2.so-no-z-defs = yes |
||||
+$(objpfx)tst-dlopen-tlsreinit.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \ |
||||
+ $(objpfx)tst-dlopen-tlsreinitmod2.so $(objpfx)tst-dlopen-tlsreinitmod3.so |
||||
+# Reuse an audit module which provides ample debug logging. |
||||
+$(objpfx)tst-dlopen-tlsreinit3.out: $(objpfx)tst-auditmod1.so |
||||
+tst-dlopen-tlsreinit3-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so |
||||
+$(objpfx)tst-dlopen-tlsreinit4.out: $(objpfx)tst-auditmod1.so |
||||
+tst-dlopen-tlsreinit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so |
||||
diff -Nrup a/elf/dl-open.c b/elf/dl-open.c |
||||
--- a/elf/dl-open.c 2024-08-27 23:25:59.237754576 -0400 |
||||
+++ b/elf/dl-open.c 2024-08-27 23:10:52.497978645 -0400 |
||||
@@ -362,17 +362,8 @@ resize_tls_slotinfo (struct link_map *ne |
||||
{ |
||||
bool any_tls = false; |
||||
for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) |
||||
- { |
||||
- struct link_map *imap = new->l_searchlist.r_list[i]; |
||||
- |
||||
- /* Only add TLS memory if this object is loaded now and |
||||
- therefore is not yet initialized. */ |
||||
- if (! imap->l_init_called && imap->l_tls_blocksize > 0) |
||||
- { |
||||
- _dl_add_to_slotinfo (imap, false); |
||||
- any_tls = true; |
||||
- } |
||||
- } |
||||
+ if (_dl_add_to_slotinfo (new->l_searchlist.r_list[i], false)) |
||||
+ any_tls = true; |
||||
return any_tls; |
||||
} |
||||
|
||||
@@ -382,22 +373,8 @@ resize_tls_slotinfo (struct link_map *ne |
||||
static void |
||||
update_tls_slotinfo (struct link_map *new) |
||||
{ |
||||
- unsigned int first_static_tls = new->l_searchlist.r_nlist; |
||||
for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) |
||||
- { |
||||
- struct link_map *imap = new->l_searchlist.r_list[i]; |
||||
- |
||||
- /* Only add TLS memory if this object is loaded now and |
||||
- therefore is not yet initialized. */ |
||||
- if (! imap->l_init_called && imap->l_tls_blocksize > 0) |
||||
- { |
||||
- _dl_add_to_slotinfo (imap, true); |
||||
- |
||||
- if (imap->l_need_tls_init |
||||
- && first_static_tls == new->l_searchlist.r_nlist) |
||||
- first_static_tls = i; |
||||
- } |
||||
- } |
||||
+ _dl_add_to_slotinfo (new->l_searchlist.r_list[i], true); |
||||
|
||||
size_t newgen = GL(dl_tls_generation) + 1; |
||||
if (__glibc_unlikely (newgen == 0)) |
||||
@@ -409,13 +386,11 @@ TLS generation counter wrapped! Please |
||||
/* We need a second pass for static tls data, because |
||||
_dl_update_slotinfo must not be run while calls to |
||||
_dl_add_to_slotinfo are still pending. */ |
||||
- for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i) |
||||
+ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) |
||||
{ |
||||
struct link_map *imap = new->l_searchlist.r_list[i]; |
||||
|
||||
- if (imap->l_need_tls_init |
||||
- && ! imap->l_init_called |
||||
- && imap->l_tls_blocksize > 0) |
||||
+ if (imap->l_need_tls_init && imap->l_tls_blocksize > 0) |
||||
{ |
||||
/* For static TLS we have to allocate the memory here and |
||||
now, but we can delay updating the DTV. */ |
||||
diff -Nrup a/elf/dl-tls.c b/elf/dl-tls.c |
||||
--- a/elf/dl-tls.c 2024-08-27 23:25:59.358755213 -0400 |
||||
+++ b/elf/dl-tls.c 2024-08-27 23:21:04.960204566 -0400 |
||||
@@ -638,17 +638,21 @@ _dl_allocate_tls_init (void *result, boo |
||||
some platforms use in static programs requires it. */ |
||||
dtv[map->l_tls_modid].pointer.val = dest; |
||||
|
||||
- /* Copy the initialization image and clear the BSS part. For |
||||
- audit modules or dependencies with initial-exec TLS, we can not |
||||
- set the initial TLS image on default loader initialization |
||||
- because it would already be set by the audit setup. However, |
||||
- subsequent thread creation would need to follow the default |
||||
- behaviour. */ |
||||
+ /* Copy the initialization image and clear the BSS part. |
||||
+ For audit modules or dependencies with initial-exec TLS, |
||||
+ we can not set the initial TLS image on default loader |
||||
+ initialization because it would already be set by the |
||||
+ audit setup, which uses the dlopen code and already |
||||
+ clears l_need_tls_init. Calls with !main_thread from |
||||
+ pthread_create need to initialze TLS for the current |
||||
+ thread regardless of namespace. */ |
||||
if (map->l_ns != LM_ID_BASE && main_thread) |
||||
continue; |
||||
memset (__mempcpy (dest, map->l_tls_initimage, |
||||
map->l_tls_initimage_size), '\0', |
||||
map->l_tls_blocksize - map->l_tls_initimage_size); |
||||
+ if (main_thread) |
||||
+ map->l_need_tls_init = 0; |
||||
} |
||||
|
||||
total += cnt; |
||||
@@ -1105,9 +1109,32 @@ _dl_tls_initial_modid_limit_setup (void) |
||||
} |
||||
|
||||
|
||||
-void |
||||
+/* Add module to slot information data. If DO_ADD is false, only the |
||||
+ required memory is allocated. Must be called with |
||||
+ GL (dl_load_tls_lock) acquired. If the function has already been |
||||
+ called for the link map L with !DO_ADD, then this function will not |
||||
+ raise an exception, otherwise it is possible that it encounters a |
||||
+ memory allocation failure. |
||||
+ |
||||
+ Return false if L has already been added to the slotinfo data, or |
||||
+ if L has no TLS data. If the returned value is true, L has been |
||||
+ added with this call (DO_ADD), or has been added in a previous call |
||||
+ (!DO_ADD). |
||||
+ |
||||
+ The expected usage is as follows: Call _dl_add_to_slotinfo for |
||||
+ several link maps with DO_ADD set to false, and record if any calls |
||||
+ result in a true result. If there was a true result, call |
||||
+ _dl_add_to_slotinfo again, this time with DO_ADD set to true. (For |
||||
+ simplicity, it's possible to call the function for link maps where |
||||
+ the previous result was false.) The return value from the second |
||||
+ round of calls can be ignored. If there was true result initially, |
||||
+ call _dl_update_slotinfo to update the TLS generation counter. */ |
||||
+bool |
||||
_dl_add_to_slotinfo (struct link_map *l, bool do_add) |
||||
{ |
||||
+ if (l->l_tls_blocksize == 0 || l->l_tls_in_slotinfo) |
||||
+ return false; |
||||
+ |
||||
/* Now that we know the object is loaded successfully add |
||||
modules containing TLS data to the dtv info table. We |
||||
might have to increase its size. */ |
||||
@@ -1163,7 +1190,10 @@ cannot create TLS data structures")); |
||||
atomic_store_relaxed (&listp->slotinfo[idx].map, l); |
||||
atomic_store_relaxed (&listp->slotinfo[idx].gen, |
||||
GL(dl_tls_generation) + 1); |
||||
+ l->l_tls_in_slotinfo = true; |
||||
} |
||||
+ |
||||
+ return true; |
||||
} |
||||
|
||||
#if THREAD_GSCOPE_IN_TCB |
||||
diff -Nrup a/elf/tst-dlopen-tlsreinit1.c b/elf/tst-dlopen-tlsreinit1.c |
||||
--- a/elf/tst-dlopen-tlsreinit1.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/elf/tst-dlopen-tlsreinit1.c 2024-08-27 23:10:52.497978645 -0400 |
||||
@@ -0,0 +1,40 @@ |
||||
+/* Test that dlopen preserves already accessed TLS (bug 31717). |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <stdbool.h> |
||||
+#include <support/check.h> |
||||
+#include <support/xdlfcn.h> |
||||
+#include <ctype.h> |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ void *handle = xdlopen ("tst-dlopen-tlsreinitmod1.so", RTLD_NOW); |
||||
+ |
||||
+ bool *tlsreinitmod3_tested = xdlsym (handle, "tlsreinitmod3_tested"); |
||||
+ TEST_VERIFY (*tlsreinitmod3_tested); |
||||
+ |
||||
+ xdlclose (handle); |
||||
+ |
||||
+ /* This crashes if the libc.so.6 TLS image has been reverted. */ |
||||
+ TEST_VERIFY (!isupper ('@')); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff -Nrup a/elf/tst-dlopen-tlsreinit2.c b/elf/tst-dlopen-tlsreinit2.c |
||||
--- a/elf/tst-dlopen-tlsreinit2.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/elf/tst-dlopen-tlsreinit2.c 2024-08-27 23:10:52.497978645 -0400 |
||||
@@ -0,0 +1,39 @@ |
||||
+/* Test that dlopen preserves already accessed TLS (bug 31717). |
||||
+ Variant with initially-linked modules. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <ctype.h> |
||||
+#include <stdbool.h> |
||||
+#include <support/check.h> |
||||
+#include <support/xdlfcn.h> |
||||
+ |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ /* Defined in tst-dlopen-tlsreinitmod3.so. */ |
||||
+ extern bool tlsreinitmod3_tested; |
||||
+ TEST_VERIFY (tlsreinitmod3_tested); |
||||
+ |
||||
+ /* This crashes if the libc.so.6 TLS image has been reverted. */ |
||||
+ TEST_VERIFY (!isupper ('@')); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff -Nrup a/elf/tst-dlopen-tlsreinit3.c b/elf/tst-dlopen-tlsreinit3.c |
||||
--- a/elf/tst-dlopen-tlsreinit3.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/elf/tst-dlopen-tlsreinit3.c 2024-08-27 23:10:52.497978645 -0400 |
||||
@@ -0,0 +1,2 @@ |
||||
+/* Same code, but run with LD_AUDIT=tst-auditmod1.so. */ |
||||
+#include "tst-dlopen-tlsreinit1.c" |
||||
diff -Nrup a/elf/tst-dlopen-tlsreinit4.c b/elf/tst-dlopen-tlsreinit4.c |
||||
--- a/elf/tst-dlopen-tlsreinit4.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/elf/tst-dlopen-tlsreinit4.c 2024-08-27 23:10:52.497978645 -0400 |
||||
@@ -0,0 +1,2 @@ |
||||
+/* Same code, but run with LD_AUDIT=tst-auditmod1.so. */ |
||||
+#include "tst-dlopen-tlsreinit2.c" |
||||
diff -Nrup a/elf/tst-dlopen-tlsreinitmod1.c b/elf/tst-dlopen-tlsreinitmod1.c |
||||
--- a/elf/tst-dlopen-tlsreinitmod1.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/elf/tst-dlopen-tlsreinitmod1.c 2024-08-27 23:10:52.497978645 -0400 |
||||
@@ -0,0 +1,20 @@ |
||||
+/* Test that dlopen preserves already accessed TLS (bug 31717), module 1. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+/* This module triggers loading of tst-dlopen-tlsreinitmod2.so and |
||||
+ tst-dlopen-tlsreinitmod3.so. */ |
||||
diff -Nrup a/elf/tst-dlopen-tlsreinitmod2.c b/elf/tst-dlopen-tlsreinitmod2.c |
||||
--- a/elf/tst-dlopen-tlsreinitmod2.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/elf/tst-dlopen-tlsreinitmod2.c 2024-08-27 23:10:52.497978645 -0400 |
||||
@@ -0,0 +1,30 @@ |
||||
+/* Test that dlopen preserves already accessed TLS (bug 31717), module 2. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <stdio.h> |
||||
+ |
||||
+/* Defined in tst-dlopen-tlsreinitmod3.so. This an underlinked symbol |
||||
+ dependency. */ |
||||
+extern void call_tlsreinitmod3 (void); |
||||
+ |
||||
+static void __attribute__ ((constructor)) |
||||
+tlsreinitmod2_init (void) |
||||
+{ |
||||
+ puts ("info: constructor of tst-dlopen-tlsreinitmod2.so invoked"); |
||||
+ call_tlsreinitmod3 (); |
||||
+} |
||||
diff -Nrup a/elf/tst-dlopen-tlsreinitmod3.c b/elf/tst-dlopen-tlsreinitmod3.c |
||||
--- a/elf/tst-dlopen-tlsreinitmod3.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/elf/tst-dlopen-tlsreinitmod3.c 2024-08-27 23:10:52.498978651 -0400 |
||||
@@ -0,0 +1,102 @@ |
||||
+/* Test that dlopen preserves already accessed TLS (bug 31717), module 3. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <dlfcn.h> |
||||
+#include <stdbool.h> |
||||
+#include <stdio.h> |
||||
+#include <unistd.h> |
||||
+ |
||||
+/* Used to verify from the main program that the test ran. */ |
||||
+bool tlsreinitmod3_tested; |
||||
+ |
||||
+/* This TLS variable must not revert back to the initial state after |
||||
+ dlopen. */ |
||||
+static __thread int tlsreinitmod3_state = 1; |
||||
+ |
||||
+/* Set from the ELF constructor during dlopen. */ |
||||
+static bool tlsreinitmod3_constructed; |
||||
+ |
||||
+/* Second half of test, behind a compiler barrier. The compiler |
||||
+ barrier is necessary to prevent carrying over TLS address |
||||
+ information from call_tlsreinitmod3 to call_tlsreinitmod3_tail. */ |
||||
+void call_tlsreinitmod3_tail (void *self) __attribute__ ((weak)); |
||||
+ |
||||
+/* Called from tst-dlopen-tlsreinitmod2.so. */ |
||||
+void |
||||
+call_tlsreinitmod3 (void) |
||||
+{ |
||||
+ printf ("info: call_tlsreinitmod3 invoked (state=%d)\n", |
||||
+ tlsreinitmod3_state); |
||||
+ |
||||
+ if (tlsreinitmod3_constructed) |
||||
+ { |
||||
+ puts ("error: call_tlsreinitmod3 called after ELF constructor"); |
||||
+ fflush (stdout); |
||||
+ /* Cannot rely on test harness due to dynamic linking. */ |
||||
+ _exit (1); |
||||
+ } |
||||
+ |
||||
+ tlsreinitmod3_state = 2; |
||||
+ |
||||
+ /* Self-dlopen. This will run the ELF constructor. */ |
||||
+ void *self = dlopen ("tst-dlopen-tlsreinitmod3.so", RTLD_NOW); |
||||
+ if (self == NULL) |
||||
+ { |
||||
+ printf ("error: dlopen: %s\n", dlerror ()); |
||||
+ fflush (stdout); |
||||
+ /* Cannot rely on test harness due to dynamic linking. */ |
||||
+ _exit (1); |
||||
+ } |
||||
+ |
||||
+ call_tlsreinitmod3_tail (self); |
||||
+} |
||||
+ |
||||
+void |
||||
+call_tlsreinitmod3_tail (void *self) |
||||
+{ |
||||
+ printf ("info: dlopen returned in tlsreinitmod3 (state=%d)\n", |
||||
+ tlsreinitmod3_state); |
||||
+ |
||||
+ if (!tlsreinitmod3_constructed) |
||||
+ { |
||||
+ puts ("error: dlopen did not call tlsreinitmod3 ELF constructor"); |
||||
+ fflush (stdout); |
||||
+ /* Cannot rely on test harness due to dynamic linking. */ |
||||
+ _exit (1); |
||||
+ } |
||||
+ |
||||
+ if (tlsreinitmod3_state != 2) |
||||
+ { |
||||
+ puts ("error: TLS state reverted in tlsreinitmod3"); |
||||
+ fflush (stdout); |
||||
+ /* Cannot rely on test harness due to dynamic linking. */ |
||||
+ _exit (1); |
||||
+ } |
||||
+ |
||||
+ dlclose (self); |
||||
+ |
||||
+ /* Signal test completion to the main program. */ |
||||
+ tlsreinitmod3_tested = true; |
||||
+} |
||||
+ |
||||
+static void __attribute__ ((constructor)) |
||||
+tlsreinitmod3_init (void) |
||||
+{ |
||||
+ puts ("info: constructor of tst-dlopen-tlsreinitmod3.so invoked"); |
||||
+ tlsreinitmod3_constructed = true; |
||||
+} |
||||
diff -Nrup a/include/link.h b/include/link.h |
||||
--- a/include/link.h 2024-08-27 23:25:58.503750710 -0400 |
||||
+++ b/include/link.h 2024-08-27 23:23:42.209032820 -0400 |
||||
@@ -211,6 +211,7 @@ struct link_map |
||||
freed, ie. not allocated with |
||||
the dummy malloc in ld.so. */ |
||||
unsigned int l_ld_readonly:1; /* Nonzero if dynamic section is readonly. */ |
||||
+ unsigned int l_tls_in_slotinfo:1; /* TLS slotinfo updated in dlopen. */ |
||||
|
||||
/* NODELETE status of the map. Only valid for maps of type |
||||
lt_loaded. Lazy binding sets l_nodelete_active directly, |
||||
diff -Nrup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
--- a/sysdeps/generic/ldsodefs.h 2024-08-27 23:25:59.359755218 -0400 |
||||
+++ b/sysdeps/generic/ldsodefs.h 2024-08-27 23:10:52.498978651 -0400 |
||||
@@ -1291,13 +1291,7 @@ extern void *_dl_open (const char *name, |
||||
extern int _dl_scope_free (void *) attribute_hidden; |
||||
|
||||
|
||||
-/* Add module to slot information data. If DO_ADD is false, only the |
||||
- required memory is allocated. Must be called with GL |
||||
- (dl_load_tls_lock) acquired. If the function has already been called |
||||
- for the link map L with !do_add, then this function will not raise |
||||
- an exception, otherwise it is possible that it encounters a memory |
||||
- allocation failure. */ |
||||
-extern void _dl_add_to_slotinfo (struct link_map *l, bool do_add) |
||||
+extern bool _dl_add_to_slotinfo (struct link_map *l, bool do_add) |
||||
attribute_hidden; |
||||
|
||||
/* Update slot information data for at least the generation of the |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
Author: Patsy Griffin <patsy@redhat.com> |
||||
|
||||
Fix a typo in naming tst-dlopen-tlsreinit1.out |
||||
|
||||
diff -Nrup a/elf/Makefile b/elf/Makefile |
||||
--- a/elf/Makefile 2024-08-16 13:27:00.700921146 -0400 |
||||
+++ b/elf/Makefile 2024-08-16 13:29:12.951628406 -0400 |
||||
@@ -2802,7 +2802,7 @@ $(objpfx)tst-dlopen-tlsreinit4: \ |
||||
# tst-dlopen-tlsreinitmod3.so. The dependency is provided via |
||||
# $(objpfx)tst-dlopen-tlsreinitmod1.so. |
||||
tst-dlopen-tlsreinitmod2.so-no-z-defs = yes |
||||
-$(objpfx)tst-dlopen-tlsreinit.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \ |
||||
+$(objpfx)tst-dlopen-tlsreinit1.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \ |
||||
$(objpfx)tst-dlopen-tlsreinitmod2.so $(objpfx)tst-dlopen-tlsreinitmod3.so |
||||
# Reuse an audit module which provides ample debug logging. |
||||
$(objpfx)tst-dlopen-tlsreinit3.out: $(objpfx)tst-auditmod1.so |
@ -0,0 +1,593 @@
@@ -0,0 +1,593 @@
|
||||
commit df11c05be91fda5ef490c76fd0d4a53821750116 |
||||
Author: Joseph Myers <josmyers@redhat.com> |
||||
Date: Wed Jan 17 15:38:54 2024 +0000 |
||||
|
||||
Update syscall lists for Linux 6.7 |
||||
|
||||
Linux 6.7 adds the futex_requeue, futex_wait and futex_wake syscalls, |
||||
and enables map_shadow_stack for architectures previously missing it. |
||||
Update syscall-names.list and regenerate the arch-syscall.h headers |
||||
with build-many-glibcs.py update-syscalls. |
||||
|
||||
Tested with build-many-glibcs.py. |
||||
|
||||
Modified for RHEL by: Patsy Griffin <patsy@redhat.com> |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h |
||||
index 746991aa2f..1713897f85 100644 |
||||
--- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h |
||||
@@ -64,7 +64,10 @@ |
||||
#define __NR_fsync 82 |
||||
#define __NR_ftruncate 46 |
||||
#define __NR_futex 98 |
||||
+#define __NR_futex_requeue 456 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_get_mempolicy 236 |
||||
#define __NR_get_robust_list 100 |
||||
#define __NR_getcpu 168 |
||||
@@ -126,6 +129,7 @@ |
||||
#define __NR_lseek 62 |
||||
#define __NR_lsetxattr 6 |
||||
#define __NR_madvise 233 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
#define __NR_membarrier 283 |
||||
#define __NR_memfd_create 279 |
||||
diff --git a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h |
||||
index 32efe51267..5457d2d8ae 100644 |
||||
--- a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h |
||||
@@ -80,7 +80,10 @@ |
||||
#define __NR_fsync 95 |
||||
#define __NR_ftruncate 130 |
||||
#define __NR_futex 394 |
||||
+#define __NR_futex_requeue 566 |
||||
+#define __NR_futex_wait 565 |
||||
#define __NR_futex_waitv 559 |
||||
+#define __NR_futex_wake 564 |
||||
#define __NR_futimesat 454 |
||||
#define __NR_get_kernel_syms 309 |
||||
#define __NR_get_mempolicy 430 |
||||
@@ -156,6 +159,7 @@ |
||||
#define __NR_lstat 68 |
||||
#define __NR_lstat64 426 |
||||
#define __NR_madvise 75 |
||||
+#define __NR_map_shadow_stack 563 |
||||
#define __NR_mbind 429 |
||||
#define __NR_membarrier 517 |
||||
#define __NR_memfd_create 512 |
||||
diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arch-syscall.h |
||||
index 1d2879e877..a66471c83a 100644 |
||||
--- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/arc/arch-syscall.h |
||||
@@ -66,8 +66,11 @@ |
||||
#define __NR_fstatfs64 44 |
||||
#define __NR_fsync 82 |
||||
#define __NR_ftruncate64 46 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_get_mempolicy 236 |
||||
#define __NR_get_robust_list 100 |
||||
#define __NR_getcpu 168 |
||||
@@ -130,6 +133,7 @@ |
||||
#define __NR_lremovexattr 15 |
||||
#define __NR_lsetxattr 6 |
||||
#define __NR_madvise 233 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
#define __NR_membarrier 283 |
||||
#define __NR_memfd_create 279 |
||||
diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h |
||||
index 6711981e78..74a57f4520 100644 |
||||
--- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h |
||||
@@ -91,8 +91,11 @@ |
||||
#define __NR_ftruncate 93 |
||||
#define __NR_ftruncate64 194 |
||||
#define __NR_futex 240 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 326 |
||||
#define __NR_get_mempolicy 320 |
||||
#define __NR_get_robust_list 339 |
||||
@@ -170,6 +173,7 @@ |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 220 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 319 |
||||
#define __NR_membarrier 389 |
||||
#define __NR_memfd_create 385 |
||||
diff --git a/sysdeps/unix/sysv/linux/csky/arch-syscall.h b/sysdeps/unix/sysv/linux/csky/arch-syscall.h |
||||
index 92d9a703ea..ba7632e018 100644 |
||||
--- a/sysdeps/unix/sysv/linux/csky/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/csky/arch-syscall.h |
||||
@@ -71,8 +71,11 @@ |
||||
#define __NR_fsync 82 |
||||
#define __NR_ftruncate64 46 |
||||
#define __NR_futex 98 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_get_mempolicy 236 |
||||
#define __NR_get_robust_list 100 |
||||
#define __NR_getcpu 168 |
||||
@@ -135,6 +138,7 @@ |
||||
#define __NR_lremovexattr 15 |
||||
#define __NR_lsetxattr 6 |
||||
#define __NR_madvise 233 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
#define __NR_membarrier 283 |
||||
#define __NR_memfd_create 279 |
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h |
||||
index fbac124b70..483706de9b 100644 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h |
||||
@@ -89,8 +89,11 @@ |
||||
#define __NR_ftruncate 93 |
||||
#define __NR_ftruncate64 200 |
||||
#define __NR_futex 210 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 279 |
||||
#define __NR_get_mempolicy 261 |
||||
#define __NR_get_robust_list 290 |
||||
@@ -161,6 +164,7 @@ |
||||
#define __NR_lstat 84 |
||||
#define __NR_lstat64 198 |
||||
#define __NR_madvise 119 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 260 |
||||
#define __NR_membarrier 343 |
||||
#define __NR_memfd_create 340 |
||||
diff --git a/sysdeps/unix/sysv/linux/i386/arch-syscall.h b/sysdeps/unix/sysv/linux/i386/arch-syscall.h |
||||
index 8961788a96..21c1308bb3 100644 |
||||
--- a/sysdeps/unix/sysv/linux/i386/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/i386/arch-syscall.h |
||||
@@ -95,8 +95,11 @@ |
||||
#define __NR_ftruncate 93 |
||||
#define __NR_ftruncate64 194 |
||||
#define __NR_futex 240 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 299 |
||||
#define __NR_get_kernel_syms 130 |
||||
#define __NR_get_mempolicy 275 |
||||
@@ -183,6 +186,7 @@ |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 219 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 274 |
||||
#define __NR_membarrier 375 |
||||
#define __NR_memfd_create 356 |
||||
diff --git a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h |
||||
index 2053d5d392..6d788e3440 100644 |
||||
--- a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h |
||||
@@ -94,8 +94,11 @@ |
||||
#define __NR_ftruncate 93 |
||||
#define __NR_ftruncate64 194 |
||||
#define __NR_futex 235 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 292 |
||||
#define __NR_get_kernel_syms 130 |
||||
#define __NR_get_mempolicy 269 |
||||
@@ -177,6 +180,7 @@ |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 238 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 268 |
||||
#define __NR_membarrier 374 |
||||
#define __NR_memfd_create 353 |
||||
diff --git a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h |
||||
index 6865b1693c..91e1630f7b 100644 |
||||
--- a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h |
||||
@@ -95,8 +95,11 @@ |
||||
#define __NR_ftruncate 93 |
||||
#define __NR_ftruncate64 194 |
||||
#define __NR_futex 240 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 299 |
||||
#define __NR_get_kernel_syms 130 |
||||
#define __NR_get_mempolicy 275 |
||||
@@ -183,6 +186,7 @@ |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 219 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 274 |
||||
#define __NR_membarrier 390 |
||||
#define __NR_memfd_create 386 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h |
||||
index b13ace8e1c..d75af97467 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h |
||||
@@ -94,8 +94,11 @@ |
||||
#define __NR_ftruncate 4093 |
||||
#define __NR_ftruncate64 4212 |
||||
#define __NR_futex 4238 |
||||
+#define __NR_futex_requeue 4456 |
||||
#define __NR_futex_time64 4422 |
||||
+#define __NR_futex_wait 4455 |
||||
#define __NR_futex_waitv 4449 |
||||
+#define __NR_futex_wake 4454 |
||||
#define __NR_futimesat 4292 |
||||
#define __NR_get_kernel_syms 4130 |
||||
#define __NR_get_mempolicy 4269 |
||||
@@ -173,6 +176,7 @@ |
||||
#define __NR_lstat 4107 |
||||
#define __NR_lstat64 4214 |
||||
#define __NR_madvise 4218 |
||||
+#define __NR_map_shadow_stack 4453 |
||||
#define __NR_mbind 4268 |
||||
#define __NR_membarrier 4358 |
||||
#define __NR_memfd_create 4354 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h |
||||
index b7a7c0dfa7..05bf7d251d 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h |
||||
@@ -87,8 +87,11 @@ |
||||
#define __NR_fsync 6072 |
||||
#define __NR_ftruncate 6075 |
||||
#define __NR_futex 6194 |
||||
+#define __NR_futex_requeue 6456 |
||||
#define __NR_futex_time64 6422 |
||||
+#define __NR_futex_wait 6455 |
||||
#define __NR_futex_waitv 6449 |
||||
+#define __NR_futex_wake 6454 |
||||
#define __NR_futimesat 6255 |
||||
#define __NR_get_kernel_syms 6170 |
||||
#define __NR_get_mempolicy 6232 |
||||
@@ -159,6 +162,7 @@ |
||||
#define __NR_lsetxattr 6181 |
||||
#define __NR_lstat 6006 |
||||
#define __NR_madvise 6027 |
||||
+#define __NR_map_shadow_stack 6453 |
||||
#define __NR_mbind 6231 |
||||
#define __NR_membarrier 6322 |
||||
#define __NR_memfd_create 6318 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h |
||||
index e5d7f91f48..41ffaf3255 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h |
||||
@@ -80,7 +80,10 @@ |
||||
#define __NR_fsync 5072 |
||||
#define __NR_ftruncate 5075 |
||||
#define __NR_futex 5194 |
||||
+#define __NR_futex_requeue 5456 |
||||
+#define __NR_futex_wait 5455 |
||||
#define __NR_futex_waitv 5449 |
||||
+#define __NR_futex_wake 5454 |
||||
#define __NR_futimesat 5251 |
||||
#define __NR_get_kernel_syms 5170 |
||||
#define __NR_get_mempolicy 5228 |
||||
@@ -150,6 +153,7 @@ |
||||
#define __NR_lsetxattr 5181 |
||||
#define __NR_lstat 5006 |
||||
#define __NR_madvise 5027 |
||||
+#define __NR_map_shadow_stack 5453 |
||||
#define __NR_mbind 5227 |
||||
#define __NR_membarrier 5318 |
||||
#define __NR_memfd_create 5314 |
||||
diff --git a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h |
||||
index 89950cc33a..d94e7e9ee9 100644 |
||||
--- a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h |
||||
@@ -70,8 +70,11 @@ |
||||
#define __NR_fsync 82 |
||||
#define __NR_ftruncate64 46 |
||||
#define __NR_futex 98 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_get_mempolicy 236 |
||||
#define __NR_get_robust_list 100 |
||||
#define __NR_getcpu 168 |
||||
@@ -134,6 +137,7 @@ |
||||
#define __NR_lremovexattr 15 |
||||
#define __NR_lsetxattr 6 |
||||
#define __NR_madvise 233 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
#define __NR_membarrier 283 |
||||
#define __NR_memfd_create 279 |
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h |
||||
index 64683bcb76..b5522e8889 100644 |
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h |
||||
@@ -93,8 +93,11 @@ |
||||
#define __NR_ftruncate 93 |
||||
#define __NR_ftruncate64 194 |
||||
#define __NR_futex 221 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 290 |
||||
#define __NR_get_kernel_syms 130 |
||||
#define __NR_get_mempolicy 260 |
||||
@@ -173,6 +176,7 @@ |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 205 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 259 |
||||
#define __NR_membarrier 365 |
||||
#define __NR_memfd_create 360 |
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h |
||||
index af1bbf32e8..162d782ae6 100644 |
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h |
||||
@@ -83,7 +83,10 @@ |
||||
#define __NR_ftime 35 |
||||
#define __NR_ftruncate 93 |
||||
#define __NR_futex 221 |
||||
+#define __NR_futex_requeue 456 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 290 |
||||
#define __NR_get_kernel_syms 130 |
||||
#define __NR_get_mempolicy 260 |
||||
@@ -160,6 +163,7 @@ |
||||
#define __NR_lsetxattr 210 |
||||
#define __NR_lstat 107 |
||||
#define __NR_madvise 205 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 259 |
||||
#define __NR_membarrier 365 |
||||
#define __NR_memfd_create 360 |
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h |
||||
index 56e3088cbf..013222e5de 100644 |
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h |
||||
@@ -61,8 +61,11 @@ |
||||
#define __NR_fstatfs64 44 |
||||
#define __NR_fsync 82 |
||||
#define __NR_ftruncate64 46 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_get_mempolicy 236 |
||||
#define __NR_get_robust_list 100 |
||||
#define __NR_getcpu 168 |
||||
@@ -121,6 +124,7 @@ |
||||
#define __NR_lremovexattr 15 |
||||
#define __NR_lsetxattr 6 |
||||
#define __NR_madvise 233 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
#define __NR_membarrier 283 |
||||
#define __NR_memfd_create 279 |
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h |
||||
index 508161b47a..d03dad8200 100644 |
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h |
||||
@@ -64,7 +64,10 @@ |
||||
#define __NR_fsync 82 |
||||
#define __NR_ftruncate 46 |
||||
#define __NR_futex 98 |
||||
+#define __NR_futex_requeue 456 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_get_mempolicy 236 |
||||
#define __NR_get_robust_list 100 |
||||
#define __NR_getcpu 168 |
||||
@@ -126,6 +129,7 @@ |
||||
#define __NR_lseek 62 |
||||
#define __NR_lsetxattr 6 |
||||
#define __NR_madvise 233 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
#define __NR_membarrier 283 |
||||
#define __NR_memfd_create 279 |
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h |
||||
index 1498ebf42e..98e6b68b31 100644 |
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h |
||||
@@ -92,8 +92,11 @@ |
||||
#define __NR_ftruncate 93 |
||||
#define __NR_ftruncate64 194 |
||||
#define __NR_futex 238 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 292 |
||||
#define __NR_get_kernel_syms 130 |
||||
#define __NR_get_mempolicy 269 |
||||
@@ -177,6 +180,7 @@ |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 219 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 268 |
||||
#define __NR_membarrier 356 |
||||
#define __NR_memfd_create 350 |
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h |
||||
index 624d71b56d..951fbd7c97 100644 |
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h |
||||
@@ -78,7 +78,10 @@ |
||||
#define __NR_fsync 118 |
||||
#define __NR_ftruncate 93 |
||||
#define __NR_futex 238 |
||||
+#define __NR_futex_requeue 456 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 292 |
||||
#define __NR_get_kernel_syms 130 |
||||
#define __NR_get_mempolicy 269 |
||||
@@ -151,6 +154,7 @@ |
||||
#define __NR_lsetxattr 225 |
||||
#define __NR_lstat 107 |
||||
#define __NR_madvise 219 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 268 |
||||
#define __NR_membarrier 356 |
||||
#define __NR_memfd_create 350 |
||||
diff --git a/sysdeps/unix/sysv/linux/sh/arch-syscall.h b/sysdeps/unix/sysv/linux/sh/arch-syscall.h |
||||
index 37211f5f8c..6b4418bcae 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sh/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/sh/arch-syscall.h |
||||
@@ -91,8 +91,11 @@ |
||||
#define __NR_ftruncate 93 |
||||
#define __NR_ftruncate64 194 |
||||
#define __NR_futex 240 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 299 |
||||
#define __NR_get_mempolicy 275 |
||||
#define __NR_get_robust_list 312 |
||||
@@ -170,6 +173,7 @@ |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 219 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 274 |
||||
#define __NR_membarrier 378 |
||||
#define __NR_memfd_create 374 |
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h |
||||
index 8093abcc9c..4f9460b1a3 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h |
||||
@@ -93,8 +93,11 @@ |
||||
#define __NR_ftruncate 130 |
||||
#define __NR_ftruncate64 84 |
||||
#define __NR_futex 142 |
||||
+#define __NR_futex_requeue 456 |
||||
#define __NR_futex_time64 422 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 288 |
||||
#define __NR_get_kernel_syms 223 |
||||
#define __NR_get_mempolicy 304 |
||||
@@ -175,6 +178,7 @@ |
||||
#define __NR_lstat 40 |
||||
#define __NR_lstat64 132 |
||||
#define __NR_madvise 75 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 303 |
||||
#define __NR_membarrier 351 |
||||
#define __NR_memfd_create 348 |
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h |
||||
index d25ccfb571..129ce50646 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h |
||||
@@ -84,7 +84,10 @@ |
||||
#define __NR_fsync 95 |
||||
#define __NR_ftruncate 130 |
||||
#define __NR_futex 142 |
||||
+#define __NR_futex_requeue 456 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 288 |
||||
#define __NR_get_kernel_syms 223 |
||||
#define __NR_get_mempolicy 304 |
||||
@@ -158,6 +161,7 @@ |
||||
#define __NR_lstat 40 |
||||
#define __NR_lstat64 132 |
||||
#define __NR_madvise 75 |
||||
+#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 303 |
||||
#define __NR_membarrier 351 |
||||
#define __NR_memfd_create 348 |
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list |
||||
index c039d5c37f..aac065e7b3 100644 |
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list |
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list |
||||
@@ -21,8 +21,8 @@ |
||||
# This file can list all potential system calls. The names are only |
||||
# used if the installed kernel headers also provide them. |
||||
|
||||
-# The list of system calls is current as of Linux 6.6. |
||||
-kernel 6.6 |
||||
+# The list of system calls is current as of Linux 6.7. |
||||
+kernel 6.7 |
||||
|
||||
FAST_atomic_update |
||||
FAST_cmpxchg |
||||
@@ -147,8 +147,11 @@ ftime |
||||
ftruncate |
||||
ftruncate64 |
||||
futex |
||||
+futex_requeue |
||||
futex_time64 |
||||
+futex_wait |
||||
futex_waitv |
||||
+futex_wake |
||||
futimesat |
||||
get_kernel_syms |
||||
get_mempolicy |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h |
||||
index 5e4c9e901c..4fa5b942c5 100644 |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h |
||||
@@ -80,7 +80,10 @@ |
||||
#define __NR_fsync 74 |
||||
#define __NR_ftruncate 77 |
||||
#define __NR_futex 202 |
||||
+#define __NR_futex_requeue 456 |
||||
+#define __NR_futex_wait 455 |
||||
#define __NR_futex_waitv 449 |
||||
+#define __NR_futex_wake 454 |
||||
#define __NR_futimesat 261 |
||||
#define __NR_get_kernel_syms 177 |
||||
#define __NR_get_mempolicy 239 |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h |
||||
index dd5e196272..b9db8bc5be 100644 |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h |
||||
@@ -76,7 +76,10 @@ |
||||
#define __NR_fsync 1073741898 |
||||
#define __NR_ftruncate 1073741901 |
||||
#define __NR_futex 1073742026 |
||||
+#define __NR_futex_requeue 1073742280 |
||||
+#define __NR_futex_wait 1073742279 |
||||
#define __NR_futex_waitv 1073742273 |
||||
+#define __NR_futex_wake 1073742278 |
||||
#define __NR_futimesat 1073742085 |
||||
#define __NR_get_mempolicy 1073742063 |
||||
#define __NR_get_robust_list 1073742355 |
@ -0,0 +1,756 @@
@@ -0,0 +1,756 @@
|
||||
commit 3de2f8755c6c036dcd0b1f4acd6bcdefe0e775c0 |
||||
Author: Joseph Myers <josmyers@redhat.com> |
||||
Date: Wed Mar 13 13:57:56 2024 +0000 |
||||
|
||||
Update syscall lists for Linux 6.8 |
||||
|
||||
Linux 6.8 adds five new syscalls. Update syscall-names.list and |
||||
regenerate the arch-syscall.h headers with build-many-glibcs.py |
||||
update-syscalls. |
||||
|
||||
Tested with build-many-glibcs.py. |
||||
|
||||
Modified for RHEL by: Patsy Griffin <patsy@redhat.com> |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h |
||||
index 1713897f85..7ee8a2167a 100644 |
||||
--- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h |
||||
@@ -122,12 +122,16 @@ |
||||
#define __NR_lgetxattr 9 |
||||
#define __NR_linkat 37 |
||||
#define __NR_listen 201 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 11 |
||||
#define __NR_llistxattr 12 |
||||
#define __NR_lookup_dcookie 18 |
||||
#define __NR_lremovexattr 15 |
||||
#define __NR_lseek 62 |
||||
#define __NR_lsetxattr 6 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_madvise 233 |
||||
#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
@@ -276,6 +280,7 @@ |
||||
#define __NR_socketpair 199 |
||||
#define __NR_splice 76 |
||||
#define __NR_statfs 43 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 291 |
||||
#define __NR_swapoff 225 |
||||
#define __NR_swapon 224 |
||||
diff --git a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h |
||||
index 5457d2d8ae..0f4ea7670b 100644 |
||||
--- a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h |
||||
@@ -150,12 +150,16 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 458 |
||||
#define __NR_listen 106 |
||||
+#define __NR_listmount 568 |
||||
#define __NR_listxattr 388 |
||||
#define __NR_llistxattr 389 |
||||
#define __NR_lookup_dcookie 406 |
||||
#define __NR_lremovexattr 392 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 383 |
||||
+#define __NR_lsm_get_self_attr 569 |
||||
+#define __NR_lsm_list_modules 571 |
||||
+#define __NR_lsm_set_self_attr 570 |
||||
#define __NR_lstat 68 |
||||
#define __NR_lstat64 426 |
||||
#define __NR_madvise 75 |
||||
@@ -441,6 +445,7 @@ |
||||
#define __NR_stat64 425 |
||||
#define __NR_statfs 328 |
||||
#define __NR_statfs64 528 |
||||
+#define __NR_statmount 567 |
||||
#define __NR_statx 522 |
||||
#define __NR_swapoff 304 |
||||
#define __NR_swapon 322 |
||||
diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arch-syscall.h |
||||
index a66471c83a..90359482a8 100644 |
||||
--- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/arc/arch-syscall.h |
||||
@@ -126,12 +126,16 @@ |
||||
#define __NR_lgetxattr 9 |
||||
#define __NR_linkat 37 |
||||
#define __NR_listen 201 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 11 |
||||
#define __NR_llistxattr 12 |
||||
#define __NR_llseek 62 |
||||
#define __NR_lookup_dcookie 18 |
||||
#define __NR_lremovexattr 15 |
||||
#define __NR_lsetxattr 6 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_madvise 233 |
||||
#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
@@ -278,6 +282,7 @@ |
||||
#define __NR_socketpair 199 |
||||
#define __NR_splice 76 |
||||
#define __NR_statfs64 43 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 291 |
||||
#define __NR_swapoff 225 |
||||
#define __NR_swapon 224 |
||||
diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h |
||||
index 74a57f4520..4930167a03 100644 |
||||
--- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h |
||||
@@ -164,12 +164,16 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 330 |
||||
#define __NR_listen 284 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 232 |
||||
#define __NR_llistxattr 233 |
||||
#define __NR_lookup_dcookie 249 |
||||
#define __NR_lremovexattr 236 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 227 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 220 |
||||
@@ -361,6 +365,7 @@ |
||||
#define __NR_stat64 195 |
||||
#define __NR_statfs 99 |
||||
#define __NR_statfs64 266 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 397 |
||||
#define __NR_swapoff 115 |
||||
#define __NR_swapon 87 |
||||
diff --git a/sysdeps/unix/sysv/linux/csky/arch-syscall.h b/sysdeps/unix/sysv/linux/csky/arch-syscall.h |
||||
index ba7632e018..3f16a29f57 100644 |
||||
--- a/sysdeps/unix/sysv/linux/csky/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/csky/arch-syscall.h |
||||
@@ -131,12 +131,16 @@ |
||||
#define __NR_lgetxattr 9 |
||||
#define __NR_linkat 37 |
||||
#define __NR_listen 201 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 11 |
||||
#define __NR_llistxattr 12 |
||||
#define __NR_llseek 62 |
||||
#define __NR_lookup_dcookie 18 |
||||
#define __NR_lremovexattr 15 |
||||
#define __NR_lsetxattr 6 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_madvise 233 |
||||
#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
@@ -291,6 +295,7 @@ |
||||
#define __NR_socketpair 199 |
||||
#define __NR_splice 76 |
||||
#define __NR_statfs64 43 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 291 |
||||
#define __NR_swapoff 225 |
||||
#define __NR_swapon 224 |
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h |
||||
index 483706de9b..a1b2c819d6 100644 |
||||
--- a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h |
||||
@@ -155,12 +155,16 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 283 |
||||
#define __NR_listen 32 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 244 |
||||
#define __NR_llistxattr 245 |
||||
#define __NR_lookup_dcookie 223 |
||||
#define __NR_lremovexattr 248 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 239 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 84 |
||||
#define __NR_lstat64 198 |
||||
#define __NR_madvise 119 |
||||
@@ -339,6 +343,7 @@ |
||||
#define __NR_stat64 101 |
||||
#define __NR_statfs 99 |
||||
#define __NR_statfs64 298 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 349 |
||||
#define __NR_stime 25 |
||||
#define __NR_swapoff 115 |
||||
diff --git a/sysdeps/unix/sysv/linux/i386/arch-syscall.h b/sysdeps/unix/sysv/linux/i386/arch-syscall.h |
||||
index 21c1308bb3..cc775432d6 100644 |
||||
--- a/sysdeps/unix/sysv/linux/i386/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/i386/arch-syscall.h |
||||
@@ -176,6 +176,7 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 303 |
||||
#define __NR_listen 363 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 232 |
||||
#define __NR_llistxattr 233 |
||||
#define __NR_lock 53 |
||||
@@ -183,6 +184,9 @@ |
||||
#define __NR_lremovexattr 236 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 227 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 219 |
||||
@@ -386,6 +390,7 @@ |
||||
#define __NR_stat64 195 |
||||
#define __NR_statfs 99 |
||||
#define __NR_statfs64 268 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 383 |
||||
#define __NR_stime 25 |
||||
#define __NR_stty 31 |
||||
diff --git a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h |
||||
index 6d788e3440..79f277dd5b 100644 |
||||
--- a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h |
||||
@@ -171,12 +171,16 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 296 |
||||
#define __NR_listen 360 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 229 |
||||
#define __NR_llistxattr 230 |
||||
#define __NR_lookup_dcookie 248 |
||||
#define __NR_lremovexattr 233 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 224 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 238 |
||||
@@ -373,6 +377,7 @@ |
||||
#define __NR_stat64 195 |
||||
#define __NR_statfs 99 |
||||
#define __NR_statfs64 263 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 379 |
||||
#define __NR_stime 25 |
||||
#define __NR_swapoff 115 |
||||
diff --git a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h |
||||
index 91e1630f7b..779d5d5d70 100644 |
||||
--- a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h |
||||
@@ -176,6 +176,7 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 303 |
||||
#define __NR_listen 348 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 232 |
||||
#define __NR_llistxattr 233 |
||||
#define __NR_lock 53 |
||||
@@ -183,6 +184,9 @@ |
||||
#define __NR_lremovexattr 236 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 227 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 219 |
||||
@@ -389,6 +393,7 @@ |
||||
#define __NR_stat64 195 |
||||
#define __NR_statfs 99 |
||||
#define __NR_statfs64 268 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 398 |
||||
#define __NR_stime 25 |
||||
#define __NR_stty 31 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h |
||||
index d75af97467..86ffd5ce84 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h |
||||
@@ -166,6 +166,7 @@ |
||||
#define __NR_link 4009 |
||||
#define __NR_linkat 4296 |
||||
#define __NR_listen 4174 |
||||
+#define __NR_listmount 4458 |
||||
#define __NR_listxattr 4230 |
||||
#define __NR_llistxattr 4231 |
||||
#define __NR_lock 4053 |
||||
@@ -173,6 +174,9 @@ |
||||
#define __NR_lremovexattr 4234 |
||||
#define __NR_lseek 4019 |
||||
#define __NR_lsetxattr 4225 |
||||
+#define __NR_lsm_get_self_attr 4459 |
||||
+#define __NR_lsm_list_modules 4461 |
||||
+#define __NR_lsm_set_self_attr 4460 |
||||
#define __NR_lstat 4107 |
||||
#define __NR_lstat64 4214 |
||||
#define __NR_madvise 4218 |
||||
@@ -362,6 +366,7 @@ |
||||
#define __NR_stat64 4213 |
||||
#define __NR_statfs 4099 |
||||
#define __NR_statfs64 4255 |
||||
+#define __NR_statmount 4457 |
||||
#define __NR_statx 4366 |
||||
#define __NR_stime 4025 |
||||
#define __NR_stty 4031 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h |
||||
index 05bf7d251d..5d37a686e5 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h |
||||
@@ -154,12 +154,16 @@ |
||||
#define __NR_link 6084 |
||||
#define __NR_linkat 6259 |
||||
#define __NR_listen 6049 |
||||
+#define __NR_listmount 6458 |
||||
#define __NR_listxattr 6186 |
||||
#define __NR_llistxattr 6187 |
||||
#define __NR_lookup_dcookie 6206 |
||||
#define __NR_lremovexattr 6190 |
||||
#define __NR_lseek 6008 |
||||
#define __NR_lsetxattr 6181 |
||||
+#define __NR_lsm_get_self_attr 6459 |
||||
+#define __NR_lsm_list_modules 6461 |
||||
+#define __NR_lsm_set_self_attr 6460 |
||||
#define __NR_lstat 6006 |
||||
#define __NR_madvise 6027 |
||||
#define __NR_map_shadow_stack 6453 |
||||
@@ -332,6 +336,7 @@ |
||||
#define __NR_stat 6004 |
||||
#define __NR_statfs 6134 |
||||
#define __NR_statfs64 6217 |
||||
+#define __NR_statmount 6457 |
||||
#define __NR_statx 6330 |
||||
#define __NR_swapoff 6163 |
||||
#define __NR_swapon 6162 |
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h |
||||
index 41ffaf3255..9b1e846e76 100644 |
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h |
||||
@@ -145,12 +145,16 @@ |
||||
#define __NR_link 5084 |
||||
#define __NR_linkat 5255 |
||||
#define __NR_listen 5049 |
||||
+#define __NR_listmount 5458 |
||||
#define __NR_listxattr 5186 |
||||
#define __NR_llistxattr 5187 |
||||
#define __NR_lookup_dcookie 5206 |
||||
#define __NR_lremovexattr 5190 |
||||
#define __NR_lseek 5008 |
||||
#define __NR_lsetxattr 5181 |
||||
+#define __NR_lsm_get_self_attr 5459 |
||||
+#define __NR_lsm_list_modules 5461 |
||||
+#define __NR_lsm_set_self_attr 5460 |
||||
#define __NR_lstat 5006 |
||||
#define __NR_madvise 5027 |
||||
#define __NR_map_shadow_stack 5453 |
||||
@@ -313,6 +317,7 @@ |
||||
#define __NR_splice 5263 |
||||
#define __NR_stat 5004 |
||||
#define __NR_statfs 5134 |
||||
+#define __NR_statmount 5457 |
||||
#define __NR_statx 5326 |
||||
#define __NR_swapoff 5163 |
||||
#define __NR_swapon 5162 |
||||
diff --git a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h |
||||
index d94e7e9ee9..abbc9ab6b0 100644 |
||||
--- a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h |
||||
@@ -130,12 +130,16 @@ |
||||
#define __NR_lgetxattr 9 |
||||
#define __NR_linkat 37 |
||||
#define __NR_listen 201 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 11 |
||||
#define __NR_llistxattr 12 |
||||
#define __NR_llseek 62 |
||||
#define __NR_lookup_dcookie 18 |
||||
#define __NR_lremovexattr 15 |
||||
#define __NR_lsetxattr 6 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_madvise 233 |
||||
#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
@@ -290,6 +294,7 @@ |
||||
#define __NR_socketpair 199 |
||||
#define __NR_splice 76 |
||||
#define __NR_statfs64 43 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 291 |
||||
#define __NR_swapoff 225 |
||||
#define __NR_swapon 224 |
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h |
||||
index b5522e8889..af0d2b121e 100644 |
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h |
||||
@@ -166,6 +166,7 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 294 |
||||
#define __NR_listen 329 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 215 |
||||
#define __NR_llistxattr 216 |
||||
#define __NR_lock 53 |
||||
@@ -173,6 +174,9 @@ |
||||
#define __NR_lremovexattr 219 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 210 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 205 |
||||
@@ -374,6 +378,7 @@ |
||||
#define __NR_stat64 195 |
||||
#define __NR_statfs 99 |
||||
#define __NR_statfs64 252 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 383 |
||||
#define __NR_stime 25 |
||||
#define __NR_stty 31 |
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h |
||||
index 162d782ae6..a4c70aa7fe 100644 |
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h |
||||
@@ -154,6 +154,7 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 294 |
||||
#define __NR_listen 329 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 215 |
||||
#define __NR_llistxattr 216 |
||||
#define __NR_lock 53 |
||||
@@ -161,6 +162,9 @@ |
||||
#define __NR_lremovexattr 219 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 210 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 107 |
||||
#define __NR_madvise 205 |
||||
#define __NR_map_shadow_stack 453 |
||||
@@ -352,6 +356,7 @@ |
||||
#define __NR_stat 106 |
||||
#define __NR_statfs 99 |
||||
#define __NR_statfs64 252 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 383 |
||||
#define __NR_stime 25 |
||||
#define __NR_stty 31 |
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h |
||||
index 013222e5de..7315d164d6 100644 |
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h |
||||
@@ -117,12 +117,16 @@ |
||||
#define __NR_lgetxattr 9 |
||||
#define __NR_linkat 37 |
||||
#define __NR_listen 201 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 11 |
||||
#define __NR_llistxattr 12 |
||||
#define __NR_llseek 62 |
||||
#define __NR_lookup_dcookie 18 |
||||
#define __NR_lremovexattr 15 |
||||
#define __NR_lsetxattr 6 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_madvise 233 |
||||
#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
@@ -268,6 +272,7 @@ |
||||
#define __NR_socketpair 199 |
||||
#define __NR_splice 76 |
||||
#define __NR_statfs64 43 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 291 |
||||
#define __NR_swapoff 225 |
||||
#define __NR_swapon 224 |
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h |
||||
index d03dad8200..31a1130db9 100644 |
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h |
||||
@@ -122,12 +122,16 @@ |
||||
#define __NR_lgetxattr 9 |
||||
#define __NR_linkat 37 |
||||
#define __NR_listen 201 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 11 |
||||
#define __NR_llistxattr 12 |
||||
#define __NR_lookup_dcookie 18 |
||||
#define __NR_lremovexattr 15 |
||||
#define __NR_lseek 62 |
||||
#define __NR_lsetxattr 6 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_madvise 233 |
||||
#define __NR_map_shadow_stack 453 |
||||
#define __NR_mbind 235 |
||||
@@ -277,6 +281,7 @@ |
||||
#define __NR_socketpair 199 |
||||
#define __NR_splice 76 |
||||
#define __NR_statfs 43 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 291 |
||||
#define __NR_swapoff 225 |
||||
#define __NR_swapon 224 |
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h |
||||
index 98e6b68b31..cf8569304d 100644 |
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h |
||||
@@ -171,12 +171,16 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 296 |
||||
#define __NR_listen 363 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 230 |
||||
#define __NR_llistxattr 231 |
||||
#define __NR_lookup_dcookie 110 |
||||
#define __NR_lremovexattr 234 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 225 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 219 |
||||
@@ -372,6 +376,7 @@ |
||||
#define __NR_stat64 195 |
||||
#define __NR_statfs 99 |
||||
#define __NR_statfs64 265 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 379 |
||||
#define __NR_stime 25 |
||||
#define __NR_swapoff 115 |
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h |
||||
index 951fbd7c97..f3536ed03f 100644 |
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h |
||||
@@ -146,12 +146,16 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 296 |
||||
#define __NR_listen 363 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 230 |
||||
#define __NR_llistxattr 231 |
||||
#define __NR_lookup_dcookie 110 |
||||
#define __NR_lremovexattr 234 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 225 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 107 |
||||
#define __NR_madvise 219 |
||||
#define __NR_map_shadow_stack 453 |
||||
@@ -329,6 +333,7 @@ |
||||
#define __NR_stat 106 |
||||
#define __NR_statfs 99 |
||||
#define __NR_statfs64 265 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 379 |
||||
#define __NR_swapoff 115 |
||||
#define __NR_swapon 87 |
||||
diff --git a/sysdeps/unix/sysv/linux/sh/arch-syscall.h b/sysdeps/unix/sysv/linux/sh/arch-syscall.h |
||||
index 6b4418bcae..0c88bf10c7 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sh/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/sh/arch-syscall.h |
||||
@@ -164,12 +164,16 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 303 |
||||
#define __NR_listen 343 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 232 |
||||
#define __NR_llistxattr 233 |
||||
#define __NR_lookup_dcookie 253 |
||||
#define __NR_lremovexattr 236 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 227 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 107 |
||||
#define __NR_lstat64 196 |
||||
#define __NR_madvise 219 |
||||
@@ -365,6 +369,7 @@ |
||||
#define __NR_stat64 195 |
||||
#define __NR_statfs 99 |
||||
#define __NR_statfs64 268 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 383 |
||||
#define __NR_stime 25 |
||||
#define __NR_swapoff 115 |
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h |
||||
index 4f9460b1a3..19fa614624 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h |
||||
@@ -169,12 +169,16 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 292 |
||||
#define __NR_listen 354 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 178 |
||||
#define __NR_llistxattr 179 |
||||
#define __NR_lookup_dcookie 208 |
||||
#define __NR_lremovexattr 182 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 170 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 40 |
||||
#define __NR_lstat64 132 |
||||
#define __NR_madvise 75 |
||||
@@ -370,6 +374,7 @@ |
||||
#define __NR_stat64 139 |
||||
#define __NR_statfs 157 |
||||
#define __NR_statfs64 234 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 360 |
||||
#define __NR_stime 233 |
||||
#define __NR_swapoff 213 |
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h |
||||
index 129ce50646..18516f20cb 100644 |
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h |
||||
@@ -152,12 +152,16 @@ |
||||
#define __NR_link 9 |
||||
#define __NR_linkat 292 |
||||
#define __NR_listen 354 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 178 |
||||
#define __NR_llistxattr 179 |
||||
#define __NR_lookup_dcookie 208 |
||||
#define __NR_lremovexattr 182 |
||||
#define __NR_lseek 19 |
||||
#define __NR_lsetxattr 170 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 40 |
||||
#define __NR_lstat64 132 |
||||
#define __NR_madvise 75 |
||||
@@ -339,6 +343,7 @@ |
||||
#define __NR_stat64 139 |
||||
#define __NR_statfs 157 |
||||
#define __NR_statfs64 234 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 360 |
||||
#define __NR_stime 233 |
||||
#define __NR_swapoff 213 |
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list |
||||
index aac065e7b3..6557bcfde4 100644 |
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list |
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list |
||||
@@ -21,8 +21,8 @@ |
||||
# This file can list all potential system calls. The names are only |
||||
# used if the installed kernel headers also provide them. |
||||
|
||||
-# The list of system calls is current as of Linux 6.7. |
||||
-kernel 6.7 |
||||
+# The list of system calls is current as of Linux 6.8. |
||||
+kernel 6.8 |
||||
|
||||
FAST_atomic_update |
||||
FAST_cmpxchg |
||||
@@ -239,6 +239,7 @@ lgetxattr |
||||
link |
||||
linkat |
||||
listen |
||||
+listmount |
||||
listxattr |
||||
llistxattr |
||||
llseek |
||||
@@ -247,6 +248,9 @@ lookup_dcookie |
||||
lremovexattr |
||||
lseek |
||||
lsetxattr |
||||
+lsm_get_self_attr |
||||
+lsm_list_modules |
||||
+lsm_set_self_attr |
||||
lstat |
||||
lstat64 |
||||
madvise |
||||
@@ -593,6 +597,7 @@ stat |
||||
stat64 |
||||
statfs |
||||
statfs64 |
||||
+statmount |
||||
statx |
||||
stime |
||||
stty |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h |
||||
index 4fa5b942c5..b122216013 100644 |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h |
||||
@@ -149,12 +149,16 @@ |
||||
#define __NR_link 86 |
||||
#define __NR_linkat 265 |
||||
#define __NR_listen 50 |
||||
+#define __NR_listmount 458 |
||||
#define __NR_listxattr 194 |
||||
#define __NR_llistxattr 195 |
||||
#define __NR_lookup_dcookie 212 |
||||
#define __NR_lremovexattr 198 |
||||
#define __NR_lseek 8 |
||||
#define __NR_lsetxattr 189 |
||||
+#define __NR_lsm_get_self_attr 459 |
||||
+#define __NR_lsm_list_modules 461 |
||||
+#define __NR_lsm_set_self_attr 460 |
||||
#define __NR_lstat 6 |
||||
#define __NR_madvise 28 |
||||
#define __NR_map_shadow_stack 453 |
||||
@@ -321,6 +325,7 @@ |
||||
#define __NR_splice 275 |
||||
#define __NR_stat 4 |
||||
#define __NR_statfs 137 |
||||
+#define __NR_statmount 457 |
||||
#define __NR_statx 332 |
||||
#define __NR_swapoff 168 |
||||
#define __NR_swapon 167 |
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h |
||||
index b9db8bc5be..3040a47d72 100644 |
||||
--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h |
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h |
||||
@@ -143,12 +143,16 @@ |
||||
#define __NR_link 1073741910 |
||||
#define __NR_linkat 1073742089 |
||||
#define __NR_listen 1073741874 |
||||
+#define __NR_listmount 1073742282 |
||||
#define __NR_listxattr 1073742018 |
||||
#define __NR_llistxattr 1073742019 |
||||
#define __NR_lookup_dcookie 1073742036 |
||||
#define __NR_lremovexattr 1073742022 |
||||
#define __NR_lseek 1073741832 |
||||
#define __NR_lsetxattr 1073742013 |
||||
+#define __NR_lsm_get_self_attr 1073742283 |
||||
+#define __NR_lsm_list_modules 1073742285 |
||||
+#define __NR_lsm_set_self_attr 1073742284 |
||||
#define __NR_lstat 1073741830 |
||||
#define __NR_madvise 1073741852 |
||||
#define __NR_mbind 1073742061 |
||||
@@ -312,6 +316,7 @@ |
||||
#define __NR_splice 1073742099 |
||||
#define __NR_stat 1073741828 |
||||
#define __NR_statfs 1073741961 |
||||
+#define __NR_statmount 1073742281 |
||||
#define __NR_statx 1073742156 |
||||
#define __NR_swapoff 1073741992 |
||||
#define __NR_swapon 1073741991 |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
commit cf0ca8d52e1653d4aa4311a4649af8dc541ce6b4 |
||||
Author: Joseph Myers <josmyers@redhat.com> |
||||
Date: Mon May 20 13:10:31 2024 +0000 |
||||
|
||||
Update syscall lists for Linux 6.9 |
||||
|
||||
Linux 6.9 has no new syscalls. Update the version number in |
||||
syscall-names.list to reflect that it is still current for 6.9. |
||||
|
||||
Tested with build-many-glibcs.py. |
||||
|
||||
Modified for RHEL by: Patsy Griffin <patsy@redhat.com> |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list |
||||
index 6557bcfde4..672d39eaad 100644 |
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list |
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list |
||||
@@ -21,8 +21,8 @@ |
||||
# This file can list all potential system calls. The names are only |
||||
# used if the installed kernel headers also provide them. |
||||
|
||||
-# The list of system calls is current as of Linux 6.8. |
||||
-kernel 6.8 |
||||
+# The list of system calls is current as of Linux 6.9. |
||||
+kernel 6.9 |
||||
|
||||
FAST_atomic_update |
||||
FAST_cmpxchg |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
From cb8c78b2ffa0b77ae453b2d328d7e2fe5186ef2a Mon Sep 17 00:00:00 2001 |
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Tue, 31 Oct 2023 13:32:35 -0300 |
||||
Subject: linux: Add MMAP_ABOVE4G from Linux 6.6 to sys/mman.h |
||||
|
||||
x86 added the flag (29f890d1050fc099f) for CET enabled. |
||||
|
||||
Also update tst-mman-consts.py test. |
||||
|
||||
Conflicts: |
||||
sysdeps/unix/sysv/linux/tst-mman-consts.py |
||||
(removed patch to keep alerting about kernel differences) |
||||
sysdeps/unix/sysv/linux/x86/bits/mman.h |
||||
(adapted to missing __USE_MISC conditional upstream) |
||||
|
||||
diff -rup a/sysdeps/unix/sysv/linux/x86/bits/mman.h b/sysdeps/unix/sysv/linux/x86/bits/mman.h |
||||
--- a/sysdeps/unix/sysv/linux/x86/bits/mman.h 2021-08-01 21:33:43.000000000 -0400 |
||||
+++ b/sysdeps/unix/sysv/linux/x86/bits/mman.h 2024-05-29 14:03:12.426182715 -0400 |
||||
@@ -26,6 +26,7 @@ |
||||
/* Other flags. */ |
||||
#ifdef __USE_MISC |
||||
# define MAP_32BIT 0x40 /* Only give out 32-bit addresses. */ |
||||
+# define MAP_ABOVE4G 0x80 /* Only map above 4GB. */ |
||||
#endif |
||||
|
||||
#include <bits/mman-map-flags-generic.h> |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
commit afe42e935b3ee97bac9a7064157587777259c60e |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Mon Jun 3 10:49:40 2024 +0200 |
||||
|
||||
elf: Avoid some free (NULL) calls in _dl_update_slotinfo |
||||
|
||||
This has been confirmed to work around some interposed mallocs. Here |
||||
is a discussion of the impact test ust/libc-wrapper/test_libc-wrapper |
||||
in lttng-tools: |
||||
|
||||
New TLS usage in libgcc_s.so.1, compatibility impact |
||||
<https://inbox.sourceware.org/libc-alpha/8734v1ieke.fsf@oldenburg.str.redhat.com/> |
||||
|
||||
Reportedly, this patch also papers over a similar issue when tcmalloc |
||||
2.9.1 is not compiled with -ftls-model=initial-exec. Of course the |
||||
goal really should be to compile mallocs with the initial-exec TLS |
||||
model, but this commit appears to be a useful interim workaround. |
||||
|
||||
Fixes commit d2123d68275acc0f061e73d5f86ca504e0d5a344 ("elf: Fix slow |
||||
tls access after dlopen [BZ #19924]"). |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c |
||||
index 7b3dd9ab60..670dbc42fc 100644 |
||||
--- a/elf/dl-tls.c |
||||
+++ b/elf/dl-tls.c |
||||
@@ -819,7 +819,14 @@ _dl_update_slotinfo (unsigned long int req_modid, size_t new_gen) |
||||
dtv entry free it. Note: this is not AS-safe. */ |
||||
/* XXX Ideally we will at some point create a memory |
||||
pool. */ |
||||
- free (dtv[modid].pointer.to_free); |
||||
+ /* Avoid calling free on a null pointer. Some mallocs |
||||
+ incorrectly use dynamic TLS, and depending on how the |
||||
+ free function was compiled, it could call |
||||
+ __tls_get_addr before the null pointer check in the |
||||
+ free implementation. Checking here papers over at |
||||
+ least some dynamic TLS usage by interposed mallocs. */ |
||||
+ if (dtv[modid].pointer.to_free != NULL) |
||||
+ free (dtv[modid].pointer.to_free); |
||||
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED; |
||||
dtv[modid].pointer.to_free = NULL; |
||||
|
@ -0,0 +1,499 @@
@@ -0,0 +1,499 @@
|
||||
commit 018f0fc3b818d4d1460a4e2384c24802504b1d20 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Mon Jul 1 17:42:04 2024 +0200 |
||||
|
||||
elf: Support recursive use of dynamic TLS in interposed malloc |
||||
|
||||
It turns out that quite a few applications use bundled mallocs that |
||||
have been built to use global-dynamic TLS (instead of the recommended |
||||
initial-exec TLS). The previous workaround from |
||||
commit afe42e935b3ee97bac9a7064157587777259c60e ("elf: Avoid some |
||||
free (NULL) calls in _dl_update_slotinfo") does not fix all |
||||
encountered cases unfortunatelly. |
||||
|
||||
This change avoids the TLS generation update for recursive use |
||||
of TLS from a malloc that was called during a TLS update. This |
||||
is possible because an interposed malloc has a fixed module ID and |
||||
TLS slot. (It cannot be unloaded.) If an initially-loaded module ID |
||||
is encountered in __tls_get_addr and the dynamic linker is already |
||||
in the middle of a TLS update, use the outdated DTV, thus avoiding |
||||
another call into malloc. It's still necessary to update the |
||||
DTV to the most recent generation, to get out of the slow path, |
||||
which is why the check for recursion is needed. |
||||
|
||||
The bookkeeping is done using a global counter instead of per-thread |
||||
flag because TLS access in the dynamic linker is tricky. |
||||
|
||||
All this will go away once the dynamic linker stops using malloc |
||||
for TLS, likely as part of a change that pre-allocates all TLS |
||||
during pthread_create/dlopen. |
||||
|
||||
Fixes commit d2123d68275acc0f061e73d5f86ca504e0d5a344 ("elf: Fix slow |
||||
tls access after dlopen [BZ #19924]"). |
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> |
||||
|
||||
Reworked for RHEL by: Patsy Griffin <patsy@redhat.com> |
||||
|
||||
diff -Nrup a/elf/Makefile b/elf/Makefile |
||||
--- a/elf/Makefile 2024-07-09 22:06:30.237752048 -0400 |
||||
+++ b/elf/Makefile 2024-07-10 14:09:02.996759220 -0400 |
||||
@@ -423,6 +423,7 @@ tests += \ |
||||
tst-nodeps2 \ |
||||
tst-noload \ |
||||
tst-null-argv \ |
||||
+ tst-recursive-tls \ |
||||
tst-relsort1 \ |
||||
tst-ro-dynamic \ |
||||
tst-rtld-run-static \ |
||||
@@ -783,6 +784,23 @@ modules-names = \ |
||||
tst-nodeps1-mod \ |
||||
tst-nodeps2-mod \ |
||||
tst-null-argv-lib \ |
||||
+ tst-recursive-tlsmallocmod \ |
||||
+ tst-recursive-tlsmod0 \ |
||||
+ tst-recursive-tlsmod1 \ |
||||
+ tst-recursive-tlsmod2 \ |
||||
+ tst-recursive-tlsmod3 \ |
||||
+ tst-recursive-tlsmod4 \ |
||||
+ tst-recursive-tlsmod5 \ |
||||
+ tst-recursive-tlsmod6 \ |
||||
+ tst-recursive-tlsmod7 \ |
||||
+ tst-recursive-tlsmod8 \ |
||||
+ tst-recursive-tlsmod9 \ |
||||
+ tst-recursive-tlsmod10 \ |
||||
+ tst-recursive-tlsmod11 \ |
||||
+ tst-recursive-tlsmod12 \ |
||||
+ tst-recursive-tlsmod13 \ |
||||
+ tst-recursive-tlsmod14 \ |
||||
+ tst-recursive-tlsmod15 \ |
||||
tst-relsort1mod1 \ |
||||
tst-relsort1mod2 \ |
||||
tst-ro-dynamic-mod \ |
||||
@@ -2725,3 +2743,11 @@ CFLAGS-tst-tlsgap-mod0.c += -mtls-dialec |
||||
CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=gnu2 |
||||
CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2 |
||||
endif |
||||
+ |
||||
+$(objpfx)tst-recursive-tls: $(objpfx)tst-recursive-tlsmallocmod.so |
||||
+# More objects than DTV_SURPLUS, to trigger DTV reallocation. |
||||
+$(objpfx)tst-recursive-tls.out: \ |
||||
+ $(patsubst %,$(objpfx)tst-recursive-tlsmod%.so, \ |
||||
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) |
||||
+$(objpfx)tst-recursive-tlsmod%.os: tst-recursive-tlsmodN.c |
||||
+ $(compile-command.c) -DVAR=thread_$* -DFUNC=get_threadvar_$* |
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c |
||||
index 670dbc42fc..3d221273f1 100644 |
||||
--- a/elf/dl-tls.c |
||||
+++ b/elf/dl-tls.c |
||||
@@ -75,6 +75,31 @@ |
||||
/* Default for dl_tls_static_optional. */ |
||||
#define OPTIONAL_TLS 512 |
||||
|
||||
+/* Used to count the number of threads currently executing dynamic TLS |
||||
+ updates. Used to avoid recursive malloc calls in __tls_get_addr |
||||
+ for an interposed malloc that uses global-dynamic TLS (which is not |
||||
+ recommended); see _dl_tls_allocate_active checks. This could be a |
||||
+ per-thread flag, but would need TLS access in the dynamic linker. */ |
||||
+unsigned int _dl_tls_threads_in_update; |
||||
+ |
||||
+static inline void |
||||
+_dl_tls_allocate_begin (void) |
||||
+{ |
||||
+ atomic_fetch_add_relaxed (&_dl_tls_threads_in_update, 1); |
||||
+} |
||||
+ |
||||
+static inline void |
||||
+_dl_tls_allocate_end (void) |
||||
+{ |
||||
+ atomic_fetch_add_relaxed (&_dl_tls_threads_in_update, -1); |
||||
+} |
||||
+ |
||||
+static inline bool |
||||
+_dl_tls_allocate_active (void) |
||||
+{ |
||||
+ return atomic_load_relaxed (&_dl_tls_threads_in_update) > 0; |
||||
+} |
||||
+ |
||||
/* Compute the static TLS surplus based on the namespace count and the |
||||
TLS space that can be used for optimizations. */ |
||||
static inline int |
||||
@@ -425,12 +450,18 @@ _dl_allocate_tls_storage (void) |
||||
size += TLS_PRE_TCB_SIZE; |
||||
#endif |
||||
|
||||
- /* Perform the allocation. Reserve space for the required alignment |
||||
- and the pointer to the original allocation. */ |
||||
+ /* Reserve space for the required alignment and the pointer to the |
||||
+ original allocation. */ |
||||
size_t alignment = GLRO (dl_tls_static_align); |
||||
+ |
||||
+ /* Perform the allocation. */ |
||||
+ _dl_tls_allocate_begin (); |
||||
void *allocated = malloc (size + alignment + sizeof (void *)); |
||||
if (__glibc_unlikely (allocated == NULL)) |
||||
- return NULL; |
||||
+ { |
||||
+ _dl_tls_allocate_end (); |
||||
+ return NULL; |
||||
+ } |
||||
|
||||
/* Perform alignment and allocate the DTV. */ |
||||
#if TLS_TCB_AT_TP |
||||
@@ -466,6 +497,8 @@ _dl_allocate_tls_storage (void) |
||||
result = allocate_dtv (result); |
||||
if (result == NULL) |
||||
free (allocated); |
||||
+ |
||||
+ _dl_tls_allocate_end (); |
||||
return result; |
||||
} |
||||
|
||||
@@ -483,6 +516,7 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid) |
||||
size_t newsize = max_modid + DTV_SURPLUS; |
||||
size_t oldsize = dtv[-1].counter; |
||||
|
||||
+ _dl_tls_allocate_begin (); |
||||
if (dtv == GL(dl_initial_dtv)) |
||||
{ |
||||
/* This is the initial dtv that was either statically allocated in |
||||
@@ -502,6 +536,7 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid) |
||||
if (newp == NULL) |
||||
oom (); |
||||
} |
||||
+ _dl_tls_allocate_end (); |
||||
|
||||
newp[0].counter = newsize; |
||||
|
||||
@@ -676,7 +711,9 @@ allocate_dtv_entry (size_t alignment, size_t size) |
||||
if (powerof2 (alignment) && alignment <= _Alignof (max_align_t)) |
||||
{ |
||||
/* The alignment is supported by malloc. */ |
||||
+ _dl_tls_allocate_begin (); |
||||
void *ptr = malloc (size); |
||||
+ _dl_tls_allocate_end (); |
||||
return (struct dtv_pointer) { ptr, ptr }; |
||||
} |
||||
|
||||
@@ -688,7 +725,10 @@ allocate_dtv_entry (size_t alignment, size_t size) |
||||
|
||||
/* Perform the allocation. This is the pointer we need to free |
||||
later. */ |
||||
+ _dl_tls_allocate_begin (); |
||||
void *start = malloc (alloc_size); |
||||
+ _dl_tls_allocate_end (); |
||||
+ |
||||
if (start == NULL) |
||||
return (struct dtv_pointer) {}; |
||||
|
||||
@@ -826,7 +866,11 @@ _dl_update_slotinfo (unsigned long int req_modid, size_t new_gen) |
||||
free implementation. Checking here papers over at |
||||
least some dynamic TLS usage by interposed mallocs. */ |
||||
if (dtv[modid].pointer.to_free != NULL) |
||||
- free (dtv[modid].pointer.to_free); |
||||
+ { |
||||
+ _dl_tls_allocate_begin (); |
||||
+ free (dtv[modid].pointer.to_free); |
||||
+ _dl_tls_allocate_end (); |
||||
+ } |
||||
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED; |
||||
dtv[modid].pointer.to_free = NULL; |
||||
|
||||
@@ -956,10 +1000,22 @@ __tls_get_addr (GET_ADDR_ARGS) |
||||
size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); |
||||
if (__glibc_unlikely (dtv[0].counter != gen)) |
||||
{ |
||||
- /* Update DTV up to the global generation, see CONCURRENCY NOTES |
||||
- in _dl_update_slotinfo. */ |
||||
- gen = atomic_load_acquire (&GL(dl_tls_generation)); |
||||
- return update_get_addr (GET_ADDR_PARAM, gen); |
||||
+ if (_dl_tls_allocate_active () |
||||
+ && GET_ADDR_MODULE < _dl_tls_initial_modid_limit) |
||||
+ /* This is a reentrant __tls_get_addr call, but we can |
||||
+ satisfy it because it's an initially-loaded module ID. |
||||
+ These TLS slotinfo slots do not change, so the |
||||
+ out-of-date generation counter does not matter. However, |
||||
+ if not in a TLS update, still update_get_addr below, to |
||||
+ get off the slow path eventually. */ |
||||
+ ; |
||||
+ else |
||||
+ { |
||||
+ /* Update DTV up to the global generation, see CONCURRENCY NOTES |
||||
+ in _dl_update_slotinfo. */ |
||||
+ gen = atomic_load_acquire (&GL(dl_tls_generation)); |
||||
+ return update_get_addr (GET_ADDR_PARAM, gen); |
||||
+ } |
||||
} |
||||
|
||||
void *p = dtv[GET_ADDR_MODULE].pointer.val; |
||||
@@ -969,7 +1025,7 @@ __tls_get_addr (GET_ADDR_ARGS) |
||||
|
||||
return (char *) p + GET_ADDR_OFFSET; |
||||
} |
||||
-#endif |
||||
+#endif /* SHARED */ |
||||
|
||||
|
||||
/* Look up the module's TLS block as for __tls_get_addr, |
||||
@@ -1018,6 +1074,25 @@ _dl_tls_get_addr_soft (struct link_map *l) |
||||
return data; |
||||
} |
||||
|
||||
+size_t _dl_tls_initial_modid_limit; |
||||
+ |
||||
+void |
||||
+_dl_tls_initial_modid_limit_setup (void) |
||||
+{ |
||||
+ struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list); |
||||
+ size_t idx; |
||||
+ for (idx = 0; idx < listp->len; ++idx) |
||||
+ { |
||||
+ struct link_map *l = listp->slotinfo[idx].map; |
||||
+ if (l == NULL |
||||
+ /* The object can be unloaded, so its modid can be |
||||
+ reassociated. */ |
||||
+ || !(l->l_type == lt_executable || l->l_type == lt_library)) |
||||
+ break; |
||||
+ } |
||||
+ _dl_tls_initial_modid_limit = idx; |
||||
+} |
||||
+ |
||||
|
||||
void |
||||
_dl_add_to_slotinfo (struct link_map *l, bool do_add) |
||||
@@ -1050,9 +1125,11 @@ _dl_add_to_slotinfo (struct link_map *l, bool do_add) |
||||
the first slot. */ |
||||
assert (idx == 0); |
||||
|
||||
+ _dl_tls_allocate_begin (); |
||||
listp = (struct dtv_slotinfo_list *) |
||||
malloc (sizeof (struct dtv_slotinfo_list) |
||||
+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); |
||||
+ _dl_tls_allocate_end (); |
||||
if (listp == NULL) |
||||
{ |
||||
/* We ran out of memory while resizing the dtv slotinfo list. */ |
||||
diff --git a/elf/rtld.c b/elf/rtld.c |
||||
index e9525ea987..6352ba76c5 100644 |
||||
--- a/elf/rtld.c |
||||
+++ b/elf/rtld.c |
||||
@@ -788,6 +788,8 @@ init_tls (size_t naudit) |
||||
_dl_fatal_printf ("\ |
||||
cannot allocate TLS data structures for initial thread\n"); |
||||
|
||||
+ _dl_tls_initial_modid_limit_setup (); |
||||
+ |
||||
/* Store for detection of the special case by __tls_get_addr |
||||
so it knows not to pass this dtv to the normal realloc. */ |
||||
GL(dl_initial_dtv) = GET_DTV (tcbp); |
||||
diff --git a/elf/tst-recursive-tls.c b/elf/tst-recursive-tls.c |
||||
new file mode 100644 |
||||
index 0000000000..716d1f783a |
||||
--- /dev/null |
||||
+++ b/elf/tst-recursive-tls.c |
||||
@@ -0,0 +1,60 @@ |
||||
+/* Test with interposed malloc with dynamic TLS. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <array_length.h> |
||||
+#include <stdio.h> |
||||
+#include <support/check.h> |
||||
+#include <support/xdlfcn.h> |
||||
+ |
||||
+/* Defined in tst-recursive-tlsmallocmod.so. */ |
||||
+extern __thread unsigned int malloc_subsytem_counter; |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ /* 16 is large enough to exercise the DTV resizing case. */ |
||||
+ void *handles[16]; |
||||
+ |
||||
+ for (unsigned int i = 0; i < array_length (handles); ++i) |
||||
+ { |
||||
+ /* Re-use the TLS slot for module 0. */ |
||||
+ if (i > 0) |
||||
+ xdlclose (handles[0]); |
||||
+ |
||||
+ char soname[30]; |
||||
+ snprintf (soname, sizeof (soname), "tst-recursive-tlsmod%u.so", i); |
||||
+ handles[i] = xdlopen (soname, RTLD_NOW); |
||||
+ |
||||
+ if (i > 0) |
||||
+ { |
||||
+ handles[0] = xdlopen ("tst-recursive-tlsmod0.so", RTLD_NOW); |
||||
+ int (*fptr) (void) = xdlsym (handles[0], "get_threadvar_0"); |
||||
+ /* May trigger TLS storage allocation using malloc. */ |
||||
+ TEST_COMPARE (fptr (), 0); |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ for (unsigned int i = 0; i < array_length (handles); ++i) |
||||
+ xdlclose (handles[i]); |
||||
+ |
||||
+ printf ("info: malloc subsystem calls: %u\n", malloc_subsytem_counter); |
||||
+ TEST_VERIFY (malloc_subsytem_counter > 0); |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/elf/tst-recursive-tlsmallocmod.c b/elf/tst-recursive-tlsmallocmod.c |
||||
new file mode 100644 |
||||
index 0000000000..c24e9945d1 |
||||
--- /dev/null |
||||
+++ b/elf/tst-recursive-tlsmallocmod.c |
||||
@@ -0,0 +1,64 @@ |
||||
+/* Interposed malloc with dynamic TLS. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <stdlib.h> |
||||
+#include <dlfcn.h> |
||||
+ |
||||
+__thread unsigned int malloc_subsytem_counter; |
||||
+ |
||||
+static __typeof (malloc) *malloc_fptr; |
||||
+static __typeof (free) *free_fptr; |
||||
+static __typeof (calloc) *calloc_fptr; |
||||
+static __typeof (realloc) *realloc_fptr; |
||||
+ |
||||
+static void __attribute__ ((constructor)) |
||||
+init (void) |
||||
+{ |
||||
+ malloc_fptr = dlsym (RTLD_NEXT, "malloc"); |
||||
+ free_fptr = dlsym (RTLD_NEXT, "free"); |
||||
+ calloc_fptr = dlsym (RTLD_NEXT, "calloc"); |
||||
+ realloc_fptr = dlsym (RTLD_NEXT, "realloc"); |
||||
+} |
||||
+ |
||||
+void * |
||||
+malloc (size_t size) |
||||
+{ |
||||
+ ++malloc_subsytem_counter; |
||||
+ return malloc_fptr (size); |
||||
+} |
||||
+ |
||||
+void |
||||
+free (void *ptr) |
||||
+{ |
||||
+ ++malloc_subsytem_counter; |
||||
+ return free_fptr (ptr); |
||||
+} |
||||
+ |
||||
+void * |
||||
+calloc (size_t a, size_t b) |
||||
+{ |
||||
+ ++malloc_subsytem_counter; |
||||
+ return calloc_fptr (a, b); |
||||
+} |
||||
+ |
||||
+void * |
||||
+realloc (void *ptr, size_t size) |
||||
+{ |
||||
+ ++malloc_subsytem_counter; |
||||
+ return realloc_fptr (ptr, size); |
||||
+} |
||||
diff --git a/elf/tst-recursive-tlsmodN.c b/elf/tst-recursive-tlsmodN.c |
||||
new file mode 100644 |
||||
index 0000000000..bb7592aee6 |
||||
--- /dev/null |
||||
+++ b/elf/tst-recursive-tlsmodN.c |
||||
@@ -0,0 +1,28 @@ |
||||
+/* Test module with global-dynamic TLS. Used to trigger DTV reallocation. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+/* Compiled with VAR and FUNC set via -D. FUNC requires some |
||||
+ relocation against TLS variable VAR. */ |
||||
+ |
||||
+__thread int VAR; |
||||
+ |
||||
+int |
||||
+FUNC (void) |
||||
+{ |
||||
+ return VAR; |
||||
+} |
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
index 50f58a60e3..656e8a3fa0 100644 |
||||
--- a/sysdeps/generic/ldsodefs.h |
||||
+++ b/sysdeps/generic/ldsodefs.h |
||||
@@ -1256,6 +1256,20 @@ extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid, |
||||
size_t gen) |
||||
attribute_hidden; |
||||
|
||||
+/* The last TLS module ID that is initially loaded, plus 1. TLS |
||||
+ addresses for modules with IDs lower than that can be obtained from |
||||
+ the DTV even if its generation is outdated. */ |
||||
+extern size_t _dl_tls_initial_modid_limit attribute_hidden attribute_relro; |
||||
+ |
||||
+/* Compute _dl_tls_initial_modid_limit. To be called after initial |
||||
+ relocation. */ |
||||
+void _dl_tls_initial_modid_limit_setup (void) attribute_hidden; |
||||
+ |
||||
+/* Number of threads currently in a TLS update. This is used to |
||||
+ detect reentrant __tls_get_addr calls without a per-thread |
||||
+ flag. */ |
||||
+extern unsigned int _dl_tls_threads_in_update attribute_hidden; |
||||
+ |
||||
/* Look up the module's TLS block as for __tls_get_addr, |
||||
but never touch anything. Return null if it's not allocated yet. */ |
||||
extern void *_dl_tls_get_addr_soft (struct link_map *l) attribute_hidden; |
||||
diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c |
||||
index 869023bbba..b3c1e4fcd7 100644 |
||||
--- a/sysdeps/x86_64/dl-tls.c |
||||
+++ b/sysdeps/x86_64/dl-tls.c |
||||
@@ -41,7 +41,10 @@ __tls_get_addr_slow (GET_ADDR_ARGS) |
||||
dtv_t *dtv = THREAD_DTV (); |
||||
|
||||
size_t gen = atomic_load_acquire (&GL(dl_tls_generation)); |
||||
- if (__glibc_unlikely (dtv[0].counter != gen)) |
||||
+ if (__glibc_unlikely (dtv[0].counter != gen) |
||||
+ /* See comment in __tls_get_addr in elf/dl-tls.c. */ |
||||
+ && !(_dl_tls_allocate_active () |
||||
+ && GET_ADDR_MODULE < _dl_tls_initial_modid_limit)) |
||||
return update_get_addr (GET_ADDR_PARAM, gen); |
||||
|
||||
return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL); |
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
commit 0e16db440cc73d2cdd94e439c0efa1ec43d92b2a |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Tue Aug 13 15:52:34 2024 +0200 |
||||
|
||||
manual: Document generic printf error codes |
||||
|
||||
Describe EOVERFLOW, ENOMEN, EILSEQ. |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff --git a/manual/stdio.texi b/manual/stdio.texi |
||||
index 567f6780011f9db1..41298b87a4a6c7d9 100644 |
||||
--- a/manual/stdio.texi |
||||
+++ b/manual/stdio.texi |
||||
@@ -2318,6 +2318,29 @@ the easiest way to make sure you have all the right prototypes is to |
||||
just include @file{stdio.h}. |
||||
@pindex stdio.h |
||||
|
||||
+The @code{printf} family shares the error codes listed below. |
||||
+Individual functions may report additional @code{errno} values if they |
||||
+fail. |
||||
+ |
||||
+@table @code |
||||
+@item EOVERFLOW |
||||
+The number of written bytes would have exceeded @code{INT_MAX}, and thus |
||||
+could not be represented in the return type @code{int}. |
||||
+ |
||||
+@item ENOMEM |
||||
+The function could not allocate memory during processing. Long argument |
||||
+lists and certain floating point conversions may require memory |
||||
+allocation, as does initialization of an output stream upon first use. |
||||
+ |
||||
+@item EILSEQ |
||||
+POSIX specifies this error code should be used if a wide character is |
||||
+encountered that does not have a matching valid character. @Theglibc{} |
||||
+always performs transliteration, using a replacement character if |
||||
+necessary, so this error condition cannot occur on output. However, |
||||
+@theglibc{} uses @code{EILSEQ} to indicate that an input character |
||||
+sequence (wide or multi-byte) could not be converted successfully. |
||||
+@end table |
||||
+ |
||||
@deftypefun int printf (const char *@var{template}, @dots{}) |
||||
@standards{ISO, stdio.h} |
||||
@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}} |
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
commit 2be0572f3a41d5d5a8bb3b2b04244b7c01ac0f58 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Tue Aug 13 15:52:34 2024 +0200 |
||||
|
||||
manual: Document dprintf and vdprintf |
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff --git a/manual/stdio.texi b/manual/stdio.texi |
||||
index 41298b87a4a6c7d9..d3d855fc62b8768b 100644 |
||||
--- a/manual/stdio.texi |
||||
+++ b/manual/stdio.texi |
||||
@@ -2483,6 +2483,26 @@ store the result in which case @code{-1} is returned. This was |
||||
changed in order to comply with the @w{ISO C99} standard. |
||||
@end deftypefun |
||||
|
||||
+@deftypefun dprintf (int @var{fd}, @var{template}, ...) |
||||
+@standards{POSIX, stdio.h} |
||||
+@safety{@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} |
||||
+This function formats its arguments according to @var{template} and |
||||
+writes the result to the file descriptor @var{fd}, using the |
||||
+@code{write} function. It returns the number of bytes written, or a |
||||
+negative value if there was an error. In the error case, @code{errno} |
||||
+is set appropriately. The possible @code{errno} values depend on the |
||||
+type of the file descriptor @var{fd}, in addition to the general |
||||
+@code{printf} error codes. |
||||
+ |
||||
+The number of calls to @code{write} is unspecified, and some @code{write} |
||||
+calls may have happened even if @code{dprintf} returns with an error. |
||||
+ |
||||
+@strong{Portability Note:} POSIX does not require that this function is |
||||
+async-signal-safe, and @theglibc{} implementation is not. However, some |
||||
+other systems offer this function as an async-signal-safe alternative to |
||||
+@code{fprintf}. @xref{POSIX Safety Concepts}. |
||||
+@end deftypefun |
||||
+ |
||||
@node Dynamic Output |
||||
@subsection Dynamically Allocating Formatted Output |
||||
|
||||
@@ -2696,6 +2716,13 @@ The @code{obstack_vprintf} function is the equivalent of |
||||
as for @code{vprintf}.@refill |
||||
@end deftypefun |
||||
|
||||
+@deftypefun int vdprintf (int @var{fd}, const char *@var{template}, va_list @var{ap}) |
||||
+@standards{POSIX, stdio.h} |
||||
+@safety{@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}} |
||||
+The @code{vdprintf} is the equivalent of @code{dprintf}, but processes |
||||
+an argument list. |
||||
+@end deftypefun |
||||
+ |
||||
Here's an example showing how you might use @code{vfprintf}. This is a |
||||
function that prints error messages to the stream @code{stderr}, along |
||||
with a prefix indicating the name of the program |
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
commit 10de4a47ef3f481592e3c62eb07bcda23e9fde4d |
||||
Author: Arjun Shankar <arjun@redhat.com> |
||||
Date: Mon Jul 29 14:30:59 2024 +0200 |
||||
|
||||
manual/stdio: Clarify putc and putwc |
||||
|
||||
The manual entry for `putc' described what "most systems" do instead of |
||||
describing the glibc implementation and its guarantees. This commit |
||||
fixes that by warning that putc may be implemented as a macro that |
||||
double-evaluates `stream', and removing the performance claim. |
||||
|
||||
Even though the current `putc' implementation does not double-evaluate |
||||
`stream', offering this obscure guarantee as an extension to what |
||||
POSIX allows does not seem very useful. |
||||
|
||||
The entry for `putwc' is also edited to bring it in line with `putc'. |
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
|
||||
diff --git a/manual/stdio.texi b/manual/stdio.texi |
||||
index fd7ed0cedc7c1a59..0c9a7ce4a9df4c05 100644 |
||||
--- a/manual/stdio.texi |
||||
+++ b/manual/stdio.texi |
||||
@@ -903,21 +903,21 @@ This function is a GNU extension. |
||||
@deftypefun int putc (int @var{c}, FILE *@var{stream}) |
||||
@standards{ISO, stdio.h} |
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} |
||||
-This is just like @code{fputc}, except that most systems implement it as |
||||
+This is just like @code{fputc}, except that it may be implemented as |
||||
a macro, making it faster. One consequence is that it may evaluate the |
||||
@var{stream} argument more than once, which is an exception to the |
||||
-general rule for macros. @code{putc} is usually the best function to |
||||
-use for writing a single character. |
||||
+general rule for macros. Therefore, @var{stream} should never be an |
||||
+expression with side-effects. |
||||
@end deftypefun |
||||
|
||||
@deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream}) |
||||
@standards{ISO, wchar.h} |
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} |
||||
-This is just like @code{fputwc}, except that it can be implement as |
||||
+This is just like @code{fputwc}, except that it may be implemented as |
||||
a macro, making it faster. One consequence is that it may evaluate the |
||||
@var{stream} argument more than once, which is an exception to the |
||||
-general rule for macros. @code{putwc} is usually the best function to |
||||
-use for writing a single wide character. |
||||
+general rule for macros. Therefore, @var{stream} should never be an |
||||
+expression with side-effects. |
||||
@end deftypefun |
||||
|
||||
@deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream}) |
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
commit 942670c81dc8071dd75d6213e771daa5d2084cb6 |
||||
Author: Arjun Shankar <arjun@redhat.com> |
||||
Date: Tue Jul 30 11:37:57 2024 +0200 |
||||
|
||||
manual/stdio: Further clarify putc, putwc, getc, and getwc |
||||
|
||||
This is a follow-up to 10de4a47ef3f481592e3c62eb07bcda23e9fde4d that |
||||
reworded the manual entries for putc and putwc and removed any |
||||
performance claims. |
||||
|
||||
This commit further clarifies these entries and brings getc and getwc in |
||||
line with the descriptions of putc and putwc, removing any performance |
||||
claims from them as well. |
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
|
||||
diff --git a/manual/stdio.texi b/manual/stdio.texi |
||||
index 0c9a7ce4a9df4c05..567f6780011f9db1 100644 |
||||
--- a/manual/stdio.texi |
||||
+++ b/manual/stdio.texi |
||||
@@ -904,20 +904,16 @@ This function is a GNU extension. |
||||
@standards{ISO, stdio.h} |
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} |
||||
This is just like @code{fputc}, except that it may be implemented as |
||||
-a macro, making it faster. One consequence is that it may evaluate the |
||||
-@var{stream} argument more than once, which is an exception to the |
||||
-general rule for macros. Therefore, @var{stream} should never be an |
||||
-expression with side-effects. |
||||
+a macro and may evaluate the @var{stream} argument more than once. |
||||
+Therefore, @var{stream} should never be an expression with side-effects. |
||||
@end deftypefun |
||||
|
||||
@deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream}) |
||||
@standards{ISO, wchar.h} |
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}} |
||||
This is just like @code{fputwc}, except that it may be implemented as |
||||
-a macro, making it faster. One consequence is that it may evaluate the |
||||
-@var{stream} argument more than once, which is an exception to the |
||||
-general rule for macros. Therefore, @var{stream} should never be an |
||||
-expression with side-effects. |
||||
+a macro and may evaluate the @var{stream} argument more than once. |
||||
+Therefore, @var{stream} should never be an expression with side-effects. |
||||
@end deftypefun |
||||
|
||||
@deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream}) |
||||
@@ -1110,20 +1106,17 @@ This function is a GNU extension. |
||||
@deftypefun int getc (FILE *@var{stream}) |
||||
@standards{ISO, stdio.h} |
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} |
||||
-This is just like @code{fgetc}, except that it is permissible (and |
||||
-typical) for it to be implemented as a macro that evaluates the |
||||
-@var{stream} argument more than once. @code{getc} is often highly |
||||
-optimized, so it is usually the best function to use to read a single |
||||
-character. |
||||
+This is just like @code{fgetc}, except that it may be implemented as |
||||
+a macro and may evaluate the @var{stream} argument more than once. |
||||
+Therefore, @var{stream} should never be an expression with side-effects. |
||||
@end deftypefun |
||||
|
||||
@deftypefun wint_t getwc (FILE *@var{stream}) |
||||
@standards{ISO, wchar.h} |
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}} |
||||
-This is just like @code{fgetwc}, except that it is permissible for it to |
||||
-be implemented as a macro that evaluates the @var{stream} argument more |
||||
-than once. @code{getwc} can be highly optimized, so it is usually the |
||||
-best function to use to read a single wide character. |
||||
+This is just like @code{fgetwc}, except that it may be implemented as |
||||
+a macro and may evaluate the @var{stream} argument more than once. |
||||
+Therefore, @var{stream} should never be an expression with side-effects. |
||||
@end deftypefun |
||||
|
||||
@deftypefun int getc_unlocked (FILE *@var{stream}) |
@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
|
||||
From a65ff76c9a1811dd2396ab45563f645579c0e687 Mon Sep 17 00:00:00 2001 |
||||
From: Florian Weimer <fweimer@redhat.com> |
||||
Date: Thu, 27 Oct 2022 11:36:44 +0200 |
||||
Subject: ld.so: Export tls_init_tp_called as __rtld_tls_init_tp_called |
||||
|
||||
This allows the rest of dynamic loader to check whether the TCB |
||||
has been set up (and THREAD_GETMEM and THREAD_SETMEM will work). |
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@gotplt.org> |
||||
|
||||
Conflicts: |
||||
Regenerated for context changes. |
||||
|
||||
diff -rup a/elf/rtld.c b/elf/rtld.c |
||||
--- a/elf/rtld.c 2024-08-22 17:57:02.000830481 -0400 |
||||
+++ b/elf/rtld.c 2024-08-22 17:59:30.666562835 -0400 |
||||
@@ -740,7 +740,7 @@ match_version (const char *string, struc |
||||
return 0; |
||||
} |
||||
|
||||
-static bool tls_init_tp_called; |
||||
+bool __rtld_tls_init_tp_called; |
||||
|
||||
static void * |
||||
init_tls (size_t naudit) |
||||
@@ -812,7 +812,7 @@ cannot allocate TLS data structures for |
||||
if (__glibc_unlikely (lossage != NULL)) |
||||
_dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage); |
||||
__tls_init_tp (); |
||||
- tls_init_tp_called = true; |
||||
+ __rtld_tls_init_tp_called = true; |
||||
|
||||
return tcbp; |
||||
} |
||||
@@ -2057,7 +2057,7 @@ dl_main (const ElfW(Phdr) *phdr, |
||||
an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever |
||||
used. Trying to do it lazily is too hairy to try when there could be |
||||
multiple threads (from a non-TLS-using libpthread). */ |
||||
- bool was_tls_init_tp_called = tls_init_tp_called; |
||||
+ bool was_tls_init_tp_called = __rtld_tls_init_tp_called; |
||||
if (tcbp == NULL) |
||||
tcbp = init_tls (0); |
||||
|
||||
@@ -2411,7 +2411,7 @@ dl_main (const ElfW(Phdr) *phdr, |
||||
_dl_protect_relro (l); |
||||
|
||||
/* Add object to slot information data if necessasy. */ |
||||
- if (l->l_tls_blocksize != 0 && tls_init_tp_called) |
||||
+ if (l->l_tls_blocksize != 0 && __rtld_tls_init_tp_called) |
||||
_dl_add_to_slotinfo (l, true); |
||||
} |
||||
} |
||||
@@ -2462,7 +2462,7 @@ dl_main (const ElfW(Phdr) *phdr, |
||||
consider_profiling); |
||||
|
||||
/* Add object to slot information data if necessasy. */ |
||||
- if (l->l_tls_blocksize != 0 && tls_init_tp_called) |
||||
+ if (l->l_tls_blocksize != 0 && __rtld_tls_init_tp_called) |
||||
_dl_add_to_slotinfo (l, true); |
||||
} |
||||
rtld_timer_stop (&relocate_time, start); |
||||
@@ -2488,7 +2488,7 @@ dl_main (const ElfW(Phdr) *phdr, |
||||
_dl_allocate_tls_init (tcbp, true); |
||||
|
||||
/* And finally install it for the main thread. */ |
||||
- if (! tls_init_tp_called) |
||||
+ if (! __rtld_tls_init_tp_called) |
||||
{ |
||||
const char *lossage = TLS_INIT_TP (tcbp); |
||||
if (__glibc_unlikely (lossage != NULL)) |
||||
diff -rup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h |
||||
--- a/sysdeps/generic/ldsodefs.h 2024-08-22 17:57:02.011830906 -0400 |
||||
+++ b/sysdeps/generic/ldsodefs.h 2024-08-22 17:58:10.900487160 -0400 |
||||
@@ -1262,6 +1262,9 @@ extern void *_dl_allocate_tls_storage (v |
||||
extern void *_dl_allocate_tls_init (void *result, bool main_thread); |
||||
rtld_hidden_proto (_dl_allocate_tls_init) |
||||
|
||||
+/* True if the TCB has been set up. */ |
||||
+extern bool __rtld_tls_init_tp_called attribute_hidden; |
||||
+ |
||||
/* Deallocate memory allocated with _dl_allocate_tls. */ |
||||
extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb); |
||||
rtld_hidden_proto (_dl_deallocate_tls) |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,82 @@
@@ -0,0 +1,82 @@
|
||||
Extra changes needed for backport: |
||||
|
||||
* rename field "rtld_catch" to "rtld_catch_f" to avoid conflict |
||||
between "struct rtld-catch" and rtld_catch macro |
||||
|
||||
* move rtld_catch into one of the unused padding fields to preserve |
||||
ABI |
||||
|
||||
* Validate that the padding fields used don't overlap other fields. |
||||
|
||||
diff -rup a/elf/dl-catch.c b/elf/dl-catch.c |
||||
--- a/elf/dl-catch.c 2024-09-04 16:30:02.086402568 -0400 |
||||
+++ b/elf/dl-catch.c 2024-09-04 16:55:01.933440181 -0400 |
||||
@@ -59,7 +59,7 @@ get_catch (void) |
||||
return rtld_catch_notls; |
||||
else |
||||
#endif |
||||
- return THREAD_GETMEM (THREAD_SELF, rtld_catch); |
||||
+ return THREAD_GETMEM (THREAD_SELF, rtld_catch_f); |
||||
} |
||||
|
||||
static void |
||||
@@ -70,7 +70,7 @@ set_catch (struct rtld_catch *catch) |
||||
rtld_catch_notls = catch; |
||||
else |
||||
#endif |
||||
- THREAD_SETMEM (THREAD_SELF, rtld_catch, catch); |
||||
+ THREAD_SETMEM (THREAD_SELF, rtld_catch_f, catch); |
||||
} |
||||
|
||||
/* Lossage while resolving the program's own symbols is always fatal. */ |
||||
diff -rup a/nptl/descr.h b/nptl/descr.h |
||||
--- a/nptl/descr.h 2024-08-29 11:29:16.801811033 -0400 |
||||
+++ b/nptl/descr.h 2024-08-29 11:48:56.547644398 -0400 |
||||
@@ -164,6 +164,12 @@ struct pthread |
||||
void *__padding[24]; |
||||
}; |
||||
|
||||
+#ifdef __x86_64__ |
||||
+#define rtld_catch_f header.__padding[7] |
||||
+#else |
||||
+#define rtld_catch_f __padding[23] |
||||
+#endif |
||||
+ |
||||
/* This descriptor's link on the GL (dl_stack_used) or |
||||
GL (dl_stack_user) list. */ |
||||
list_t list; |
||||
@@ -396,9 +402,6 @@ struct pthread |
||||
masked.) */ |
||||
sigset_t sigmask; |
||||
|
||||
- /* Used by the exception handling implementation in the dynamic loader. */ |
||||
- struct rtld_catch *rtld_catch; |
||||
- |
||||
/* Indicates whether is a C11 thread created by thrd_creat. */ |
||||
bool c11; |
||||
|
||||
@@ -432,6 +435,12 @@ struct pthread |
||||
+ sizeof ((struct pthread) {}.rseq_area)) |
||||
} __attribute ((aligned (TCB_ALIGNMENT))); |
||||
|
||||
+#ifdef __x86_64__ |
||||
+_Static_assert (sizeof ((*(struct pthread *)0).header) > sizeof ((*(struct pthread *)0).__padding), "rtld_catch"); |
||||
+#else |
||||
+_Static_assert (sizeof ((*(struct pthread *)0).header) < sizeof ((*(struct pthread *)0).__padding), "rtld_catch"); |
||||
+#endif |
||||
+ |
||||
static inline bool |
||||
cancel_enabled_and_canceled (int value) |
||||
{ |
||||
diff -rup a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h |
||||
--- a/sysdeps/mach/hurd/i386/tls.h 2024-08-29 11:29:16.810811382 -0400 |
||||
+++ b/sysdeps/mach/hurd/i386/tls.h 2024-08-29 11:35:45.262899113 -0400 |
||||
@@ -50,7 +50,7 @@ typedef struct |
||||
struct hurd_sigstate *_hurd_sigstate; |
||||
|
||||
/* Used by the exception handling implementation in the dynamic loader. */ |
||||
- struct rtld_catch *rtld_catch; |
||||
+ struct rtld_catch *rtld_catch_f; |
||||
} tcbhead_t; |
||||
#endif |
||||
|
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
New test case to verify padding usage. |
||||
|
||||
diff --git a/nptl/Makefile b/nptl/Makefile |
||||
index ff4d590f11c38277..9a56d34313d06444 100644 |
||||
--- a/nptl/Makefile |
||||
+++ b/nptl/Makefile |
||||
@@ -319,6 +319,8 @@ tests-internal := tst-robustpi8 tst-rwlock19 tst-rwlock20 \ |
||||
tst-barrier5 tst-signal7 tst-mutex8 tst-mutex8-static \ |
||||
tst-mutexpi8 tst-mutexpi8-static \ |
||||
tst-setgetname \ |
||||
+ tst-nptl-padding \ |
||||
+ # tests-internal |
||||
|
||||
xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \ |
||||
tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 tst-setgroups \ |
||||
diff --git a/nptl/tst-nptl-padding.c b/nptl/tst-nptl-padding.c |
||||
new file mode 100644 |
||||
index 0000000000000000..5bb64f4a54335e36 |
||||
--- /dev/null |
||||
+++ b/nptl/tst-nptl-padding.c |
||||
@@ -0,0 +1,57 @@ |
||||
+/* Downstream-only test for verifying that fields that have been |
||||
+ relocated into struct pthread padding actually use the padding. |
||||
+ |
||||
+ At present, only rtld_catch (downstream: rtld_catch_f) has been |
||||
+ placed into padding. */ |
||||
+ |
||||
+#include <descr.h> |
||||
+#include <stddef.h> |
||||
+#include <stdint.h> |
||||
+#include <string.h> |
||||
+#include <support/check.h> |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ struct pthread descr; |
||||
+ |
||||
+ /* Mark the entire descriptor as used. */ |
||||
+ memset (&descr, 0xff, sizeof (descr)); |
||||
+ |
||||
+ /* Mark the padding as unused. */ |
||||
+#ifdef __x86_64__ |
||||
+ /* Special case: Usable padding is in the header. */ |
||||
+ memset (&descr.header.__padding, 0, sizeof (descr.header.__padding)); |
||||
+#else |
||||
+ /* The padding should be directly adjacent to the first real |
||||
+ struct field. */ |
||||
+ TEST_COMPARE (sizeof (descr.__padding), offsetof (struct pthread, list)); |
||||
+ |
||||
+ /* Clear the unused tail of the padding. */ |
||||
+ { |
||||
+ char *base = (char *) &descr; |
||||
+ char *end_of_header = base + sizeof (descr.header); |
||||
+ char *end_of_padding = base + sizeof (descr.__padding); |
||||
+ memset (end_of_header, 0, end_of_padding - end_of_header); |
||||
+ } |
||||
+#endif |
||||
+ |
||||
+ /* These fields are not in padding and should remain marked as used. */ |
||||
+ TEST_COMPARE (descr.header.gscope_flag, -1); |
||||
+ TEST_COMPARE ((intptr_t) descr.list.next, -1); |
||||
+ TEST_COMPARE ((intptr_t) descr.list.prev, -1); |
||||
+ |
||||
+ /* But this field remains in padding. */ |
||||
+ TEST_COMPARE ((intptr_t) descr.rtld_catch_f, 0); |
||||
+ |
||||
+ /* Write to all padding-relocated fields below to show that they |
||||
+ have independent locations. */ |
||||
+ struct rtld_catch *rtld_catch_dummy = (void *) "rtld_catch_dummy"; |
||||
+ descr.rtld_catch_f = rtld_catch_dummy; |
||||
+ |
||||
+ TEST_VERIFY (descr.rtld_catch_f == rtld_catch_dummy); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
|
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
commit 9b7651410375ec8848a1944992d663d514db4ba7 |
||||
Author: Stefan Liebler <stli@linux.ibm.com> |
||||
Date: Thu Jul 11 11:28:53 2024 +0200 |
||||
|
||||
s390x: Fix segfault in wcsncmp [BZ #31934] |
||||
|
||||
The z13/vector-optimized wcsncmp implementation segfaults if n=1 |
||||
and there is only one character (equal on both strings) before |
||||
the page end. Then it loads and compares one character and misses |
||||
to check n again. The following load fails. |
||||
|
||||
This patch removes the extra load and compare of the first character |
||||
and just start with the loop which uses vector-load-to-block-boundary. |
||||
This code-path also checks n. |
||||
|
||||
With this patch both tests are passing: |
||||
- the simplified one mentioned in the bugzilla 31934 |
||||
- the full one in Florian Weimer's patch: |
||||
"manual: Document a GNU extension for strncmp/wcsncmp" |
||||
(https://patchwork.sourceware.org/project/glibc/patch/874j9eml6y.fsf@oldenburg.str.redhat.com/): |
||||
On s390x-linux-gnu (z16), the new wcsncmp test fails due to bug 31934. |
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
|
||||
diff --git a/sysdeps/s390/wcsncmp-vx.S b/sysdeps/s390/wcsncmp-vx.S |
||||
index bf6dfa6bc2..8b081567a2 100644 |
||||
--- a/sysdeps/s390/wcsncmp-vx.S |
||||
+++ b/sysdeps/s390/wcsncmp-vx.S |
||||
@@ -59,14 +59,7 @@ ENTRY(WCSNCMP_Z13) |
||||
sllg %r4,%r4,2 /* Convert character-count to byte-count. */ |
||||
locgrne %r4,%r1 /* Use max byte-count, if bit 0/1 was one. */ |
||||
|
||||
- /* Check first character without vector load. */ |
||||
- lghi %r5,4 /* current_len = 4 bytes. */ |
||||
- /* Check s1/2[0]. */ |
||||
- lt %r0,0(%r2) |
||||
- l %r1,0(%r3) |
||||
- je .Lend_cmp_one_char |
||||
- crjne %r0,%r1,.Lend_cmp_one_char |
||||
- |
||||
+ lghi %r5,0 /* current_len = 0 bytes. */ |
||||
.Lloop: |
||||
vlbb %v17,0(%r5,%r3),6 /* Load s2 to block boundary. */ |
||||
vlbb %v16,0(%r5,%r2),6 /* Load s1 to block boundary. */ |
||||
@@ -167,7 +160,6 @@ ENTRY(WCSNCMP_Z13) |
||||
srl %r4,2 /* And convert it to character-index. */ |
||||
vlgvf %r0,%v16,0(%r4) /* Load character-values. */ |
||||
vlgvf %r1,%v17,0(%r4) |
||||
-.Lend_cmp_one_char: |
||||
cr %r0,%r1 |
||||
je .Lend_equal |
||||
lghi %r2,1 |
@ -0,0 +1,248 @@
@@ -0,0 +1,248 @@
|
||||
commit 54252394c25ddf0062e288d4a6ab7a885f8ae009 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Thu Jun 27 16:26:56 2024 +0200 |
||||
|
||||
Enhanced test coverage for strncmp, wcsncmp |
||||
|
||||
Add string/test-strncmp-nonarray and |
||||
wcsmbs/test-wcsncmp-nonarray. |
||||
|
||||
This is the test that uncovered bug 31934. Test run time |
||||
is more than one minute on a fairly current system, so turn |
||||
these into xtests that do not run automatically. |
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com> |
||||
|
||||
diff -Nrup a/string/Makefile b/string/Makefile |
||||
--- a/string/Makefile 2024-09-03 11:42:30.396319962 -0400 |
||||
+++ b/string/Makefile 2024-09-03 11:52:17.707438963 -0400 |
||||
@@ -76,7 +76,10 @@ tests-unsupported += $(tests-translation |
||||
endif |
||||
|
||||
# This test allocates a lot of memory and can run for a long time. |
||||
-xtests = tst-strcoll-overflow |
||||
+xtests += tst-strcoll-overflow |
||||
+ |
||||
+# This test runs for a long time. |
||||
+xtests += test-strncmp-nonarray |
||||
|
||||
# This test needs libdl. |
||||
ifeq (yes,$(build-shared)) |
||||
diff -Nrup a/string/test-Xncmp-nonarray.c b/string/test-Xncmp-nonarray.c |
||||
--- a/string/test-Xncmp-nonarray.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/string/test-Xncmp-nonarray.c 2024-09-03 11:52:17.707438963 -0400 |
||||
@@ -0,0 +1,183 @@ |
||||
+/* Test non-array inputs to string comparison functions. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+/* This skeleton file is included from string/test-strncmp-nonarray.c and |
||||
+ wcsmbs/test-wcsncmp-nonarray.c to test that reading of the arrays stops |
||||
+ at the first null character. |
||||
+ |
||||
+ TEST_IDENTIFIER must be the test function identifier. TEST_NAME is |
||||
+ the same as a string. |
||||
+ |
||||
+ CHAR must be defined as the character type. */ |
||||
+ |
||||
+#include <array_length.h> |
||||
+#include <string.h> |
||||
+#include <support/check.h> |
||||
+#include <support/next_to_fault.h> |
||||
+#include <support/test-driver.h> |
||||
+#include <sys/param.h> |
||||
+#include <unistd.h> |
||||
+ |
||||
+/* Much shorter than test-Xnlen-nonarray.c because of deeply nested loops. */ |
||||
+enum { buffer_length = 80 }; |
||||
+ |
||||
+/* The test buffer layout follows what is described test-Xnlen-nonarray.c, |
||||
+ except that there two buffers, left and right. The variables |
||||
+ a_count, zero_count, start_offset are all duplicated. */ |
||||
+ |
||||
+/* Return the maximum string length for a string that starts at |
||||
+ start_offset. */ |
||||
+static int |
||||
+string_length (int a_count, int start_offset) |
||||
+{ |
||||
+ if (start_offset == buffer_length || start_offset >= a_count) |
||||
+ return 0; |
||||
+ else |
||||
+ return a_count - start_offset; |
||||
+} |
||||
+ |
||||
+/* This is the valid maximum length argument computation for |
||||
+ strnlen/wcsnlen. See text-Xnlen-nonarray.c. */ |
||||
+static int |
||||
+maximum_length (int start_offset, int zero_count) |
||||
+{ |
||||
+ if (start_offset == buffer_length) |
||||
+ return 0; |
||||
+ else if (zero_count > 0) |
||||
+ /* Effectively unbounded, but we need to stop fairly low, |
||||
+ otherwise testing takes too long. */ |
||||
+ return buffer_length + 32; |
||||
+ else |
||||
+ return buffer_length - start_offset; |
||||
+} |
||||
+ |
||||
+typedef __typeof (TEST_IDENTIFIER) *proto_t; |
||||
+ |
||||
+#define TEST_MAIN |
||||
+#include "test-string.h" |
||||
+ |
||||
+IMPL (TEST_IDENTIFIER, 1) |
||||
+ |
||||
+static int |
||||
+test_main (void) |
||||
+{ |
||||
+ TEST_VERIFY_EXIT (sysconf (_SC_PAGESIZE) >= buffer_length); |
||||
+ test_init (); |
||||
+ |
||||
+ struct support_next_to_fault left_ntf |
||||
+ = support_next_to_fault_allocate (buffer_length * sizeof (CHAR)); |
||||
+ CHAR *left_buffer = (CHAR *) left_ntf.buffer; |
||||
+ struct support_next_to_fault right_ntf |
||||
+ = support_next_to_fault_allocate (buffer_length * sizeof (CHAR)); |
||||
+ CHAR *right_buffer = (CHAR *) right_ntf.buffer; |
||||
+ |
||||
+ FOR_EACH_IMPL (impl, 0) |
||||
+ { |
||||
+ printf ("info: testing %s\n", impl->name); |
||||
+ for (size_t i = 0; i < buffer_length; ++i) |
||||
+ left_buffer[i] = 'A'; |
||||
+ |
||||
+ for (int left_zero_count = 0; left_zero_count <= buffer_length; |
||||
+ ++left_zero_count) |
||||
+ { |
||||
+ if (left_zero_count > 0) |
||||
+ left_buffer[buffer_length - left_zero_count] = 0; |
||||
+ int left_a_count = buffer_length - left_zero_count; |
||||
+ for (size_t i = 0; i < buffer_length; ++i) |
||||
+ right_buffer[i] = 'A'; |
||||
+ for (int right_zero_count = 0; right_zero_count <= buffer_length; |
||||
+ ++right_zero_count) |
||||
+ { |
||||
+ if (right_zero_count > 0) |
||||
+ right_buffer[buffer_length - right_zero_count] = 0; |
||||
+ int right_a_count = buffer_length - right_zero_count; |
||||
+ for (int left_start_offset = 0; |
||||
+ left_start_offset <= buffer_length; |
||||
+ ++left_start_offset) |
||||
+ { |
||||
+ CHAR *left_start_pointer = left_buffer + left_start_offset; |
||||
+ int left_maxlen |
||||
+ = maximum_length (left_start_offset, left_zero_count); |
||||
+ int left_length |
||||
+ = string_length (left_a_count, left_start_offset); |
||||
+ for (int right_start_offset = 0; |
||||
+ right_start_offset <= buffer_length; |
||||
+ ++right_start_offset) |
||||
+ { |
||||
+ CHAR *right_start_pointer |
||||
+ = right_buffer + right_start_offset; |
||||
+ int right_maxlen |
||||
+ = maximum_length (right_start_offset, right_zero_count); |
||||
+ int right_length |
||||
+ = string_length (right_a_count, right_start_offset); |
||||
+ |
||||
+ /* Maximum length is modelled after strnlen/wcsnlen, |
||||
+ and must be valid for both pointer arguments at |
||||
+ the same time. */ |
||||
+ int maxlen = MIN (left_maxlen, right_maxlen); |
||||
+ |
||||
+ for (int length_argument = 0; length_argument <= maxlen; |
||||
+ ++length_argument) |
||||
+ { |
||||
+ if (test_verbose) |
||||
+ { |
||||
+ printf ("left: zero_count=%d" |
||||
+ " a_count=%d start_offset=%d\n", |
||||
+ left_zero_count, left_a_count, |
||||
+ left_start_offset); |
||||
+ printf ("right: zero_count=%d" |
||||
+ " a_count=%d start_offset=%d\n", |
||||
+ right_zero_count, right_a_count, |
||||
+ right_start_offset); |
||||
+ printf ("length argument: %d\n", |
||||
+ length_argument); |
||||
+ } |
||||
+ |
||||
+ /* Effective lengths bounded by length argument. |
||||
+ The effective length determines the |
||||
+ outcome of the comparison. */ |
||||
+ int left_effective |
||||
+ = MIN (left_length, length_argument); |
||||
+ int right_effective |
||||
+ = MIN (right_length, length_argument); |
||||
+ if (left_effective == right_effective) |
||||
+ TEST_COMPARE (CALL (impl, |
||||
+ left_start_pointer, |
||||
+ right_start_pointer, |
||||
+ length_argument), 0); |
||||
+ else if (left_effective < right_effective) |
||||
+ TEST_COMPARE (CALL (impl, |
||||
+ left_start_pointer, |
||||
+ right_start_pointer, |
||||
+ length_argument) < 0, 1); |
||||
+ else |
||||
+ TEST_COMPARE (CALL (impl, |
||||
+ left_start_pointer, |
||||
+ right_start_pointer, |
||||
+ length_argument) > 0, 1); |
||||
+ } |
||||
+ } |
||||
+ } |
||||
+ } |
||||
+ } |
||||
+ } |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff -Nrup a/string/test-strncmp-nonarray.c b/string/test-strncmp-nonarray.c |
||||
--- a/string/test-strncmp-nonarray.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/string/test-strncmp-nonarray.c 2024-09-03 11:52:17.707438963 -0400 |
||||
@@ -0,0 +1,4 @@ |
||||
+#define TEST_IDENTIFIER strncmp |
||||
+#define TEST_NAME "strncmp" |
||||
+typedef char CHAR; |
||||
+#include "test-Xncmp-nonarray.c" |
||||
diff -Nrup a/wcsmbs/Makefile b/wcsmbs/Makefile |
||||
--- a/wcsmbs/Makefile 2024-09-03 11:42:30.398319976 -0400 |
||||
+++ b/wcsmbs/Makefile 2024-09-03 11:53:44.806049806 -0400 |
||||
@@ -56,6 +56,10 @@ tests := tst-wcstof wcsmbs-tst1 tst-wcsn |
||||
$(addprefix test-,$(strop-tests)) tst-mbstowcs \ |
||||
test-wcsdup |
||||
|
||||
+# This test runs for a long time. |
||||
+xtests += test-wcsncmp-nonarray |
||||
+ |
||||
+ |
||||
include ../Rules |
||||
|
||||
ifeq ($(run-built-tests),yes) |
||||
diff -Nrup a/wcsmbs/test-wcsncmp-nonarray.c b/wcsmbs/test-wcsncmp-nonarray.c |
||||
--- a/wcsmbs/test-wcsncmp-nonarray.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ b/wcsmbs/test-wcsncmp-nonarray.c 2024-09-03 11:52:17.708438970 -0400 |
||||
@@ -0,0 +1,5 @@ |
||||
+#include <wchar.h> |
||||
+#define TEST_IDENTIFIER wcsncmp |
||||
+#define TEST_NAME "wcsncmp" |
||||
+typedef wchar_t CHAR; |
||||
+#include "../string/test-Xncmp-nonarray.c" |
@ -0,0 +1,327 @@
@@ -0,0 +1,327 @@
|
||||
commit 2f47198b04a02097f438ecb765306fa39568a006 |
||||
Author: Rajalakshmi Srinivasaraghavan <rajis@linux.ibm.com> |
||||
Date: Fri Dec 2 14:26:41 2022 -0600 |
||||
|
||||
powerpc64: Remove old strncmp optimization |
||||
|
||||
This patch cleans up the power4 strncmp optimization for powerpc64 which |
||||
is unlikely to be used anywhere. |
||||
|
||||
Tested on ppc64le with and without --disable-multi-arch flag. |
||||
|
||||
Reviewed-by: Paul E. Murphy <murphyp@linux.ibm.com> |
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
|
||||
Conflicts: |
||||
sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S |
||||
sysdeps/powerpc/powerpc64/power4/strncmp.S |
||||
(copyright year changes upstream) |
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile |
||||
index 626845a43c4e8ded..5b20dab108de14ab 100644 |
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile |
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile |
||||
@@ -12,8 +12,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ |
||||
strnlen-power8 strnlen-power7 strnlen-ppc64 \ |
||||
strcasecmp-power7 strcasecmp_l-power7 \ |
||||
strncase-power7 strncase_l-power7 \ |
||||
- strncmp-power8 strncmp-power7 \ |
||||
- strncmp-power4 strncmp-ppc64 \ |
||||
+ strncmp-power8 strncmp-power7 strncmp-ppc64 \ |
||||
strchr-power8 strchr-power7 strchr-ppc64 \ |
||||
strchrnul-power8 strchrnul-power7 strchrnul-ppc64 \ |
||||
strcpy-power8 strcpy-power7 strcpy-ppc64 stpcpy-power8 \ |
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c |
||||
index 7b83aa7b8ff28bb7..914e7d5e28a98b5d 100644 |
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c |
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c |
||||
@@ -177,8 +177,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, |
||||
__strncmp_power8) |
||||
IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_ARCH_2_06, |
||||
__strncmp_power7) |
||||
- IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_POWER4, |
||||
- __strncmp_power4) |
||||
IFUNC_IMPL_ADD (array, i, strncmp, 1, |
||||
__strncmp_ppc)) |
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S |
||||
deleted file mode 100644 |
||||
index 6ead3b6374749e6a..0000000000000000 |
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power4.S |
||||
+++ /dev/null |
||||
@@ -1,23 +0,0 @@ |
||||
-/* Copyright (C) 2013-2021 Free Software Foundation, Inc. |
||||
- This file is part of the GNU C Library. |
||||
- |
||||
- The GNU C Library is free software; you can redistribute it and/or |
||||
- modify it under the terms of the GNU Lesser General Public |
||||
- License as published by the Free Software Foundation; either |
||||
- version 2.1 of the License, or (at your option) any later version. |
||||
- |
||||
- The GNU C Library is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
- Lesser General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Lesser General Public |
||||
- License along with the GNU C Library; if not, see |
||||
- <https://www.gnu.org/licenses/>. */ |
||||
- |
||||
-#define STRNCMP __strncmp_power4 |
||||
- |
||||
-#undef libc_hidden_builtin_def |
||||
-#define libc_hidden_builtin_def(name) |
||||
- |
||||
-#include <sysdeps/powerpc/powerpc64/power4/strncmp.S> |
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c |
||||
index 2d2112285445a450..275a558e4afa7d61 100644 |
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c |
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c |
||||
@@ -26,7 +26,6 @@ |
||||
# include "init-arch.h" |
||||
|
||||
extern __typeof (strncmp) __strncmp_ppc attribute_hidden; |
||||
-extern __typeof (strncmp) __strncmp_power4 attribute_hidden; |
||||
extern __typeof (strncmp) __strncmp_power7 attribute_hidden; |
||||
extern __typeof (strncmp) __strncmp_power8 attribute_hidden; |
||||
# ifdef __LITTLE_ENDIAN__ |
||||
@@ -46,7 +45,5 @@ libc_ifunc_redirected (__redirect_strncmp, strncmp, |
||||
? __strncmp_power8 |
||||
: (hwcap & PPC_FEATURE_ARCH_2_06) |
||||
? __strncmp_power7 |
||||
- : (hwcap & PPC_FEATURE_POWER4) |
||||
- ? __strncmp_power4 |
||||
- : __strncmp_ppc); |
||||
+ : __strncmp_ppc); |
||||
#endif |
||||
diff --git a/sysdeps/powerpc/powerpc64/power4/strncmp.S b/sysdeps/powerpc/powerpc64/power4/strncmp.S |
||||
deleted file mode 100644 |
||||
index cf5f4e5fb8fb2522..0000000000000000 |
||||
--- a/sysdeps/powerpc/powerpc64/power4/strncmp.S |
||||
+++ /dev/null |
||||
@@ -1,225 +0,0 @@ |
||||
-/* Optimized strcmp implementation for PowerPC64. |
||||
- Copyright (C) 2003-2021 Free Software Foundation, Inc. |
||||
- This file is part of the GNU C Library. |
||||
- |
||||
- The GNU C Library is free software; you can redistribute it and/or |
||||
- modify it under the terms of the GNU Lesser General Public |
||||
- License as published by the Free Software Foundation; either |
||||
- version 2.1 of the License, or (at your option) any later version. |
||||
- |
||||
- The GNU C Library is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
- Lesser General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Lesser General Public |
||||
- License along with the GNU C Library; if not, see |
||||
- <https://www.gnu.org/licenses/>. */ |
||||
- |
||||
-#include <sysdep.h> |
||||
- |
||||
-#ifndef STRNCMP |
||||
-# define STRNCMP strncmp |
||||
-#endif |
||||
- |
||||
-/* See strlen.s for comments on how the end-of-string testing works. */ |
||||
- |
||||
-/* int [r3] strncmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5]) */ |
||||
- |
||||
-ENTRY_TOCLESS (STRNCMP, 4) |
||||
- CALL_MCOUNT 3 |
||||
- |
||||
-#define rTMP2 r0 |
||||
-#define rRTN r3 |
||||
-#define rSTR1 r3 /* first string arg */ |
||||
-#define rSTR2 r4 /* second string arg */ |
||||
-#define rN r5 /* max string length */ |
||||
-#define rWORD1 r6 /* current word in s1 */ |
||||
-#define rWORD2 r7 /* current word in s2 */ |
||||
-#define rWORD3 r10 |
||||
-#define rWORD4 r11 |
||||
-#define rFEFE r8 /* constant 0xfefefefefefefeff (-0x0101010101010101) */ |
||||
-#define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */ |
||||
-#define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ |
||||
-#define rBITDIF r11 /* bits that differ in s1 & s2 words */ |
||||
-#define rTMP r12 |
||||
- |
||||
- dcbt 0,rSTR1 |
||||
- or rTMP, rSTR2, rSTR1 |
||||
- lis r7F7F, 0x7f7f |
||||
- dcbt 0,rSTR2 |
||||
- clrldi. rTMP, rTMP, 61 |
||||
- cmpldi cr1, rN, 0 |
||||
- lis rFEFE, -0x101 |
||||
- bne L(unaligned) |
||||
-/* We are doubleword aligned so set up for two loops. first a double word |
||||
- loop, then fall into the byte loop if any residual. */ |
||||
- srdi. rTMP, rN, 3 |
||||
- clrldi rN, rN, 61 |
||||
- addi rFEFE, rFEFE, -0x101 |
||||
- addi r7F7F, r7F7F, 0x7f7f |
||||
- cmpldi cr1, rN, 0 |
||||
- beq L(unaligned) |
||||
- |
||||
- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group. */ |
||||
- ld rWORD1, 0(rSTR1) |
||||
- ld rWORD2, 0(rSTR2) |
||||
- sldi rTMP, rFEFE, 32 |
||||
- insrdi r7F7F, r7F7F, 32, 0 |
||||
- add rFEFE, rFEFE, rTMP |
||||
- b L(g1) |
||||
- |
||||
-L(g0): |
||||
- ldu rWORD1, 8(rSTR1) |
||||
- bne- cr1, L(different) |
||||
- ldu rWORD2, 8(rSTR2) |
||||
-L(g1): add rTMP, rFEFE, rWORD1 |
||||
- nor rNEG, r7F7F, rWORD1 |
||||
- bdz L(tail) |
||||
- and. rTMP, rTMP, rNEG |
||||
- cmpd cr1, rWORD1, rWORD2 |
||||
- beq+ L(g0) |
||||
- |
||||
-/* OK. We've hit the end of the string. We need to be careful that |
||||
- we don't compare two strings as different because of gunk beyond |
||||
- the end of the strings... */ |
||||
- |
||||
-#ifdef __LITTLE_ENDIAN__ |
||||
-L(endstring): |
||||
- addi rTMP2, rTMP, -1 |
||||
- beq cr1, L(equal) |
||||
- andc rTMP2, rTMP2, rTMP |
||||
- rldimi rTMP2, rTMP2, 1, 0 |
||||
- and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ |
||||
- and rWORD1, rWORD1, rTMP2 |
||||
- cmpd cr1, rWORD1, rWORD2 |
||||
- beq cr1, L(equal) |
||||
- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ |
||||
- neg rNEG, rBITDIF |
||||
- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ |
||||
- cntlzd rNEG, rNEG /* bitcount of the bit. */ |
||||
- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ |
||||
- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ |
||||
- sld rWORD2, rWORD2, rNEG |
||||
- xor. rBITDIF, rWORD1, rWORD2 |
||||
- sub rRTN, rWORD1, rWORD2 |
||||
- blt- L(highbit) |
||||
- sradi rRTN, rRTN, 63 /* must return an int. */ |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-L(equal): |
||||
- li rRTN, 0 |
||||
- blr |
||||
- |
||||
-L(different): |
||||
- ld rWORD1, -8(rSTR1) |
||||
- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ |
||||
- neg rNEG, rBITDIF |
||||
- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ |
||||
- cntlzd rNEG, rNEG /* bitcount of the bit. */ |
||||
- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ |
||||
- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ |
||||
- sld rWORD2, rWORD2, rNEG |
||||
- xor. rBITDIF, rWORD1, rWORD2 |
||||
- sub rRTN, rWORD1, rWORD2 |
||||
- blt- L(highbit) |
||||
- sradi rRTN, rRTN, 63 |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-L(highbit): |
||||
- sradi rRTN, rWORD2, 63 |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
- |
||||
-#else |
||||
-L(endstring): |
||||
- and rTMP, r7F7F, rWORD1 |
||||
- beq cr1, L(equal) |
||||
- add rTMP, rTMP, r7F7F |
||||
- xor. rBITDIF, rWORD1, rWORD2 |
||||
- andc rNEG, rNEG, rTMP |
||||
- blt- L(highbit) |
||||
- cntlzd rBITDIF, rBITDIF |
||||
- cntlzd rNEG, rNEG |
||||
- addi rNEG, rNEG, 7 |
||||
- cmpd cr1, rNEG, rBITDIF |
||||
- sub rRTN, rWORD1, rWORD2 |
||||
- blt- cr1, L(equal) |
||||
- sradi rRTN, rRTN, 63 /* must return an int. */ |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-L(equal): |
||||
- li rRTN, 0 |
||||
- blr |
||||
- |
||||
-L(different): |
||||
- ld rWORD1, -8(rSTR1) |
||||
- xor. rBITDIF, rWORD1, rWORD2 |
||||
- sub rRTN, rWORD1, rWORD2 |
||||
- blt- L(highbit) |
||||
- sradi rRTN, rRTN, 63 |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-L(highbit): |
||||
- sradi rRTN, rWORD2, 63 |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-#endif |
||||
- |
||||
-/* Oh well. In this case, we just do a byte-by-byte comparison. */ |
||||
- .align 4 |
||||
-L(tail): |
||||
- and. rTMP, rTMP, rNEG |
||||
- cmpd cr1, rWORD1, rWORD2 |
||||
- bne- L(endstring) |
||||
- addi rSTR1, rSTR1, 8 |
||||
- bne- cr1, L(different) |
||||
- addi rSTR2, rSTR2, 8 |
||||
- cmpldi cr1, rN, 0 |
||||
-L(unaligned): |
||||
- mtctr rN /* Power4 wants mtctr 1st in dispatch group */ |
||||
- ble cr1, L(ux) |
||||
-L(uz): |
||||
- lbz rWORD1, 0(rSTR1) |
||||
- lbz rWORD2, 0(rSTR2) |
||||
- .align 4 |
||||
-L(u1): |
||||
- cmpdi cr1, rWORD1, 0 |
||||
- bdz L(u4) |
||||
- cmpd rWORD1, rWORD2 |
||||
- beq- cr1, L(u4) |
||||
- bne- L(u4) |
||||
- lbzu rWORD3, 1(rSTR1) |
||||
- lbzu rWORD4, 1(rSTR2) |
||||
- cmpdi cr1, rWORD3, 0 |
||||
- bdz L(u3) |
||||
- cmpd rWORD3, rWORD4 |
||||
- beq- cr1, L(u3) |
||||
- bne- L(u3) |
||||
- lbzu rWORD1, 1(rSTR1) |
||||
- lbzu rWORD2, 1(rSTR2) |
||||
- cmpdi cr1, rWORD1, 0 |
||||
- bdz L(u4) |
||||
- cmpd rWORD1, rWORD2 |
||||
- beq- cr1, L(u4) |
||||
- bne- L(u4) |
||||
- lbzu rWORD3, 1(rSTR1) |
||||
- lbzu rWORD4, 1(rSTR2) |
||||
- cmpdi cr1, rWORD3, 0 |
||||
- bdz L(u3) |
||||
- cmpd rWORD3, rWORD4 |
||||
- beq- cr1, L(u3) |
||||
- bne- L(u3) |
||||
- lbzu rWORD1, 1(rSTR1) |
||||
- lbzu rWORD2, 1(rSTR2) |
||||
- b L(u1) |
||||
- |
||||
-L(u3): sub rRTN, rWORD3, rWORD4 |
||||
- blr |
||||
-L(u4): sub rRTN, rWORD1, rWORD2 |
||||
- blr |
||||
-L(ux): |
||||
- li rRTN, 0 |
||||
- blr |
||||
-END (STRNCMP) |
||||
-libc_hidden_builtin_def (strncmp) |
@ -0,0 +1,595 @@
@@ -0,0 +1,595 @@
|
||||
commit 92fdb11ae7aa1ab6b18622670ea702205cd6fdc5 |
||||
Author: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> |
||||
Date: Tue Feb 28 14:23:59 2023 -0300 |
||||
|
||||
powerpc: Remove powerpc64 strncmp variants |
||||
|
||||
The default, and power7 implementation just adds word aligned |
||||
access when inputs have the same aligment. The unaligned case |
||||
is still done by byte operations. |
||||
|
||||
This is already covered by the generic implementation, which also add |
||||
the unaligned input optimization. |
||||
|
||||
Checked on powerpc64-linux-gnu built without multi-arch for powerpc64, |
||||
power7, power8, and power9 (build for le). |
||||
Reviewed-by: Rajalakshmi Srinivasaraghavan <rajis@linux.ibm.com> |
||||
|
||||
Conflicts: |
||||
sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S |
||||
sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S |
||||
sysdeps/powerpc/powerpc64/power7/strncmp.S |
||||
sysdeps/powerpc/powerpc64/strncmp.S |
||||
(copyright year changes upstream) |
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile |
||||
index 5b20dab108de14ab..0ee7ce39d6470d80 100644 |
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile |
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile |
||||
@@ -12,7 +12,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ |
||||
strnlen-power8 strnlen-power7 strnlen-ppc64 \ |
||||
strcasecmp-power7 strcasecmp_l-power7 \ |
||||
strncase-power7 strncase_l-power7 \ |
||||
- strncmp-power8 strncmp-power7 strncmp-ppc64 \ |
||||
+ strncmp-power8 strncmp-ppc64 \ |
||||
strchr-power8 strchr-power7 strchr-ppc64 \ |
||||
strchrnul-power8 strchrnul-power7 strchrnul-ppc64 \ |
||||
strcpy-power8 strcpy-power7 strcpy-ppc64 stpcpy-power8 \ |
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c |
||||
index 914e7d5e28a98b5d..2c84d287ee76a7ea 100644 |
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c |
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c |
||||
@@ -175,8 +175,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, |
||||
#endif |
||||
IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_2_07, |
||||
__strncmp_power8) |
||||
- IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_ARCH_2_06, |
||||
- __strncmp_power7) |
||||
IFUNC_IMPL_ADD (array, i, strncmp, 1, |
||||
__strncmp_ppc)) |
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S |
||||
deleted file mode 100644 |
||||
index 8282ff076c9e00ce..0000000000000000 |
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power7.S |
||||
+++ /dev/null |
||||
@@ -1,23 +0,0 @@ |
||||
-/* Copyright (C) 2013-2021 Free Software Foundation, Inc. |
||||
- This file is part of the GNU C Library. |
||||
- |
||||
- The GNU C Library is free software; you can redistribute it and/or |
||||
- modify it under the terms of the GNU Lesser General Public |
||||
- License as published by the Free Software Foundation; either |
||||
- version 2.1 of the License, or (at your option) any later version. |
||||
- |
||||
- The GNU C Library is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
- Lesser General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Lesser General Public |
||||
- License along with the GNU C Library; if not, see |
||||
- <https://www.gnu.org/licenses/>. */ |
||||
- |
||||
-#define STRNCMP __strncmp_power7 |
||||
- |
||||
-#undef libc_hidden_builtin_def |
||||
-#define libc_hidden_builtin_def(name) |
||||
- |
||||
-#include <sysdeps/powerpc/powerpc64/power7/strncmp.S> |
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S |
||||
deleted file mode 100644 |
||||
index c6f325650c9ace3b..0000000000000000 |
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.S |
||||
+++ /dev/null |
||||
@@ -1,26 +0,0 @@ |
||||
-/* Copyright (C) 2013-2021 Free Software Foundation, Inc. |
||||
- This file is part of the GNU C Library. |
||||
- |
||||
- The GNU C Library is free software; you can redistribute it and/or |
||||
- modify it under the terms of the GNU Lesser General Public |
||||
- License as published by the Free Software Foundation; either |
||||
- version 2.1 of the License, or (at your option) any later version. |
||||
- |
||||
- The GNU C Library is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
- Lesser General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Lesser General Public |
||||
- License along with the GNU C Library; if not, see |
||||
- <https://www.gnu.org/licenses/>. */ |
||||
- |
||||
-#if defined SHARED && IS_IN (libc) |
||||
-# define STRNCMP __strncmp_ppc |
||||
- |
||||
-# undef libc_hidden_builtin_def |
||||
-# define libc_hidden_builtin_def(name) \ |
||||
- .globl __GI_strncmp; __GI_strncmp = __strncmp_ppc |
||||
-#endif |
||||
- |
||||
-#include <sysdeps/powerpc/powerpc64/strncmp.S> |
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c |
||||
new file mode 100644 |
||||
index 0000000000000000..09cc009a913ed169 |
||||
--- /dev/null |
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp-ppc64.c |
||||
@@ -0,0 +1,7 @@ |
||||
+#if defined SHARED && IS_IN (libc) |
||||
+# define STRNCMP __strncmp_ppc |
||||
+# undef libc_hidden_builtin_def |
||||
+# define libc_hidden_builtin_def(name) \ |
||||
+ __hidden_ver1 (__strncmp_ppc, __GI_strncmp, __strncmp_ppc); |
||||
+#endif |
||||
+#include <string/strncmp.c> |
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c |
||||
index 275a558e4afa7d61..df2c0707a919ad79 100644 |
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c |
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c |
||||
@@ -26,7 +26,6 @@ |
||||
# include "init-arch.h" |
||||
|
||||
extern __typeof (strncmp) __strncmp_ppc attribute_hidden; |
||||
-extern __typeof (strncmp) __strncmp_power7 attribute_hidden; |
||||
extern __typeof (strncmp) __strncmp_power8 attribute_hidden; |
||||
# ifdef __LITTLE_ENDIAN__ |
||||
extern __typeof (strncmp) __strncmp_power9 attribute_hidden; |
||||
@@ -43,7 +42,5 @@ libc_ifunc_redirected (__redirect_strncmp, strncmp, |
||||
# endif |
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07) |
||||
? __strncmp_power8 |
||||
- : (hwcap & PPC_FEATURE_ARCH_2_06) |
||||
- ? __strncmp_power7 |
||||
- : __strncmp_ppc); |
||||
+ : __strncmp_ppc); |
||||
#endif |
||||
diff --git a/sysdeps/powerpc/powerpc64/power7/strncmp.S b/sysdeps/powerpc/powerpc64/power7/strncmp.S |
||||
deleted file mode 100644 |
||||
index d91aeb6077a558f2..0000000000000000 |
||||
--- a/sysdeps/powerpc/powerpc64/power7/strncmp.S |
||||
+++ /dev/null |
||||
@@ -1,228 +0,0 @@ |
||||
-/* Optimized strcmp implementation for POWER7/PowerPC64. |
||||
- Copyright (C) 2010-2021 Free Software Foundation, Inc. |
||||
- This file is part of the GNU C Library. |
||||
- |
||||
- The GNU C Library is free software; you can redistribute it and/or |
||||
- modify it under the terms of the GNU Lesser General Public |
||||
- License as published by the Free Software Foundation; either |
||||
- version 2.1 of the License, or (at your option) any later version. |
||||
- |
||||
- The GNU C Library is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
- Lesser General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Lesser General Public |
||||
- License along with the GNU C Library; if not, see |
||||
- <https://www.gnu.org/licenses/>. */ |
||||
- |
||||
-#include <sysdep.h> |
||||
- |
||||
-#ifndef STRNCMP |
||||
-# define STRNCMP strncmp |
||||
-#endif |
||||
- |
||||
-/* See strlen.s for comments on how the end-of-string testing works. */ |
||||
- |
||||
-/* int [r3] strncmp (const char *s1 [r3], |
||||
- const char *s2 [r4], |
||||
- size_t size [r5]) */ |
||||
- |
||||
- .machine power7 |
||||
-ENTRY_TOCLESS (STRNCMP, 5) |
||||
- CALL_MCOUNT 3 |
||||
- |
||||
-#define rTMP2 r0 |
||||
-#define rRTN r3 |
||||
-#define rSTR1 r3 /* first string arg */ |
||||
-#define rSTR2 r4 /* second string arg */ |
||||
-#define rN r5 /* max string length */ |
||||
-#define rWORD1 r6 /* current word in s1 */ |
||||
-#define rWORD2 r7 /* current word in s2 */ |
||||
-#define rWORD3 r10 |
||||
-#define rWORD4 r11 |
||||
-#define rFEFE r8 /* constant 0xfefefefefefefeff (-0x0101010101010101) */ |
||||
-#define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */ |
||||
-#define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ |
||||
-#define rBITDIF r11 /* bits that differ in s1 & s2 words */ |
||||
-#define rTMP r12 |
||||
- |
||||
- dcbt 0,rSTR1 |
||||
- nop |
||||
- or rTMP,rSTR2,rSTR1 |
||||
- lis r7F7F,0x7f7f |
||||
- dcbt 0,rSTR2 |
||||
- nop |
||||
- clrldi. rTMP,rTMP,61 |
||||
- cmpldi cr1,rN,0 |
||||
- lis rFEFE,-0x101 |
||||
- bne L(unaligned) |
||||
-/* We are doubleword aligned so set up for two loops. first a double word |
||||
- loop, then fall into the byte loop if any residual. */ |
||||
- srdi. rTMP,rN,3 |
||||
- clrldi rN,rN,61 |
||||
- addi rFEFE,rFEFE,-0x101 |
||||
- addi r7F7F,r7F7F,0x7f7f |
||||
- cmpldi cr1,rN,0 |
||||
- beq L(unaligned) |
||||
- |
||||
- mtctr rTMP |
||||
- ld rWORD1,0(rSTR1) |
||||
- ld rWORD2,0(rSTR2) |
||||
- sldi rTMP,rFEFE,32 |
||||
- insrdi r7F7F,r7F7F,32,0 |
||||
- add rFEFE,rFEFE,rTMP |
||||
- b L(g1) |
||||
- |
||||
-L(g0): |
||||
- ldu rWORD1,8(rSTR1) |
||||
- bne cr1,L(different) |
||||
- ldu rWORD2,8(rSTR2) |
||||
-L(g1): add rTMP,rFEFE,rWORD1 |
||||
- nor rNEG,r7F7F,rWORD1 |
||||
- bdz L(tail) |
||||
- and. rTMP,rTMP,rNEG |
||||
- cmpd cr1,rWORD1,rWORD2 |
||||
- beq L(g0) |
||||
- |
||||
-/* OK. We've hit the end of the string. We need to be careful that |
||||
- we don't compare two strings as different because of gunk beyond |
||||
- the end of the strings... */ |
||||
- |
||||
-#ifdef __LITTLE_ENDIAN__ |
||||
-L(endstring): |
||||
- addi rTMP2, rTMP, -1 |
||||
- beq cr1, L(equal) |
||||
- andc rTMP2, rTMP2, rTMP |
||||
- rldimi rTMP2, rTMP2, 1, 0 |
||||
- and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ |
||||
- and rWORD1, rWORD1, rTMP2 |
||||
- cmpd cr1, rWORD1, rWORD2 |
||||
- beq cr1, L(equal) |
||||
- cmpb rBITDIF, rWORD1, rWORD2 /* 0xff on equal bytes. */ |
||||
- addi rNEG, rBITDIF, 1 |
||||
- orc rNEG, rNEG, rBITDIF /* 0's below LS differing byte. */ |
||||
- sldi rNEG, rNEG, 8 /* 1's above LS differing byte. */ |
||||
- andc rWORD1, rWORD1, rNEG /* mask off MS bytes. */ |
||||
- andc rWORD2, rWORD2, rNEG |
||||
- xor. rBITDIF, rWORD1, rWORD2 |
||||
- sub rRTN, rWORD1, rWORD2 |
||||
- blt L(highbit) |
||||
- sradi rRTN, rRTN, 63 /* must return an int. */ |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-L(equal): |
||||
- li rRTN, 0 |
||||
- blr |
||||
- |
||||
-L(different): |
||||
- ld rWORD1, -8(rSTR1) |
||||
- cmpb rBITDIF, rWORD1, rWORD2 /* 0xff on equal bytes. */ |
||||
- addi rNEG, rBITDIF, 1 |
||||
- orc rNEG, rNEG, rBITDIF /* 0's below LS differing byte. */ |
||||
- sldi rNEG, rNEG, 8 /* 1's above LS differing byte. */ |
||||
- andc rWORD1, rWORD1, rNEG /* mask off MS bytes. */ |
||||
- andc rWORD2, rWORD2, rNEG |
||||
- xor. rBITDIF, rWORD1, rWORD2 |
||||
- sub rRTN, rWORD1, rWORD2 |
||||
- blt L(highbit) |
||||
- sradi rRTN, rRTN, 63 |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-L(highbit): |
||||
- sradi rRTN, rWORD2, 63 |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
- |
||||
-#else |
||||
-L(endstring): |
||||
- and rTMP,r7F7F,rWORD1 |
||||
- beq cr1,L(equal) |
||||
- add rTMP,rTMP,r7F7F |
||||
- xor. rBITDIF,rWORD1,rWORD2 |
||||
- andc rNEG,rNEG,rTMP |
||||
- blt L(highbit) |
||||
- cntlzd rBITDIF,rBITDIF |
||||
- cntlzd rNEG,rNEG |
||||
- addi rNEG,rNEG,7 |
||||
- cmpd cr1,rNEG,rBITDIF |
||||
- sub rRTN,rWORD1,rWORD2 |
||||
- blt cr1,L(equal) |
||||
- sradi rRTN,rRTN,63 /* must return an int. */ |
||||
- ori rRTN,rRTN,1 |
||||
- blr |
||||
-L(equal): |
||||
- li rRTN,0 |
||||
- blr |
||||
- |
||||
-L(different): |
||||
- ld rWORD1,-8(rSTR1) |
||||
- xor. rBITDIF,rWORD1,rWORD2 |
||||
- sub rRTN,rWORD1,rWORD2 |
||||
- blt L(highbit) |
||||
- sradi rRTN,rRTN,63 |
||||
- ori rRTN,rRTN,1 |
||||
- blr |
||||
-L(highbit): |
||||
- sradi rRTN,rWORD2,63 |
||||
- ori rRTN,rRTN,1 |
||||
- blr |
||||
-#endif |
||||
- |
||||
-/* Oh well. In this case, we just do a byte-by-byte comparison. */ |
||||
- .align 4 |
||||
-L(tail): |
||||
- and. rTMP,rTMP,rNEG |
||||
- cmpd cr1,rWORD1,rWORD2 |
||||
- bne L(endstring) |
||||
- addi rSTR1,rSTR1,8 |
||||
- bne cr1,L(different) |
||||
- addi rSTR2,rSTR2,8 |
||||
- cmpldi cr1,rN,0 |
||||
-L(unaligned): |
||||
- mtctr rN |
||||
- ble cr1,L(ux) |
||||
-L(uz): |
||||
- lbz rWORD1,0(rSTR1) |
||||
- lbz rWORD2,0(rSTR2) |
||||
- .align 4 |
||||
-L(u1): |
||||
- cmpdi cr1,rWORD1,0 |
||||
- bdz L(u4) |
||||
- cmpd rWORD1,rWORD2 |
||||
- beq cr1,L(u4) |
||||
- bne L(u4) |
||||
- lbzu rWORD3,1(rSTR1) |
||||
- lbzu rWORD4,1(rSTR2) |
||||
- cmpdi cr1,rWORD3,0 |
||||
- bdz L(u3) |
||||
- cmpd rWORD3,rWORD4 |
||||
- beq cr1,L(u3) |
||||
- bne L(u3) |
||||
- lbzu rWORD1,1(rSTR1) |
||||
- lbzu rWORD2,1(rSTR2) |
||||
- cmpdi cr1,rWORD1,0 |
||||
- bdz L(u4) |
||||
- cmpd rWORD1,rWORD2 |
||||
- beq cr1,L(u4) |
||||
- bne L(u4) |
||||
- lbzu rWORD3,1(rSTR1) |
||||
- lbzu rWORD4,1(rSTR2) |
||||
- cmpdi cr1,rWORD3,0 |
||||
- bdz L(u3) |
||||
- cmpd rWORD3,rWORD4 |
||||
- beq cr1,L(u3) |
||||
- bne L(u3) |
||||
- lbzu rWORD1,1(rSTR1) |
||||
- lbzu rWORD2,1(rSTR2) |
||||
- b L(u1) |
||||
- |
||||
-L(u3): sub rRTN,rWORD3,rWORD4 |
||||
- blr |
||||
-L(u4): sub rRTN,rWORD1,rWORD2 |
||||
- blr |
||||
-L(ux): |
||||
- li rRTN,0 |
||||
- blr |
||||
-END (STRNCMP) |
||||
-libc_hidden_builtin_def (strncmp) |
||||
diff --git a/sysdeps/powerpc/powerpc64/strncmp.S b/sysdeps/powerpc/powerpc64/strncmp.S |
||||
deleted file mode 100644 |
||||
index 40a230242cbdf733..0000000000000000 |
||||
--- a/sysdeps/powerpc/powerpc64/strncmp.S |
||||
+++ /dev/null |
||||
@@ -1,210 +0,0 @@ |
||||
-/* Optimized strcmp implementation for PowerPC64. |
||||
- Copyright (C) 2003-2021 Free Software Foundation, Inc. |
||||
- This file is part of the GNU C Library. |
||||
- |
||||
- The GNU C Library is free software; you can redistribute it and/or |
||||
- modify it under the terms of the GNU Lesser General Public |
||||
- License as published by the Free Software Foundation; either |
||||
- version 2.1 of the License, or (at your option) any later version. |
||||
- |
||||
- The GNU C Library is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
- Lesser General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Lesser General Public |
||||
- License along with the GNU C Library; if not, see |
||||
- <https://www.gnu.org/licenses/>. */ |
||||
- |
||||
-#include <sysdep.h> |
||||
- |
||||
-/* See strlen.s for comments on how the end-of-string testing works. */ |
||||
- |
||||
-/* int [r3] strncmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5]) */ |
||||
- |
||||
-#ifndef STRNCMP |
||||
-# define STRNCMP strncmp |
||||
-#endif |
||||
- |
||||
-ENTRY_TOCLESS (STRNCMP, 4) |
||||
- CALL_MCOUNT 3 |
||||
- |
||||
-#define rTMP2 r0 |
||||
-#define rRTN r3 |
||||
-#define rSTR1 r3 /* first string arg */ |
||||
-#define rSTR2 r4 /* second string arg */ |
||||
-#define rN r5 /* max string length */ |
||||
-#define rWORD1 r6 /* current word in s1 */ |
||||
-#define rWORD2 r7 /* current word in s2 */ |
||||
-#define rFEFE r8 /* constant 0xfefefefefefefeff (-0x0101010101010101) */ |
||||
-#define r7F7F r9 /* constant 0x7f7f7f7f7f7f7f7f */ |
||||
-#define rNEG r10 /* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */ |
||||
-#define rBITDIF r11 /* bits that differ in s1 & s2 words */ |
||||
-#define rTMP r12 |
||||
- |
||||
- dcbt 0,rSTR1 |
||||
- or rTMP, rSTR2, rSTR1 |
||||
- lis r7F7F, 0x7f7f |
||||
- dcbt 0,rSTR2 |
||||
- clrldi. rTMP, rTMP, 61 |
||||
- cmpldi cr1, rN, 0 |
||||
- lis rFEFE, -0x101 |
||||
- bne L(unaligned) |
||||
-/* We are doubleword aligned so set up for two loops. first a double word |
||||
- loop, then fall into the byte loop if any residual. */ |
||||
- srdi. rTMP, rN, 3 |
||||
- clrldi rN, rN, 61 |
||||
- addi rFEFE, rFEFE, -0x101 |
||||
- addi r7F7F, r7F7F, 0x7f7f |
||||
- cmpldi cr1, rN, 0 |
||||
- beq L(unaligned) |
||||
- |
||||
- mtctr rTMP /* Power4 wants mtctr 1st in dispatch group. */ |
||||
- ld rWORD1, 0(rSTR1) |
||||
- ld rWORD2, 0(rSTR2) |
||||
- sldi rTMP, rFEFE, 32 |
||||
- insrdi r7F7F, r7F7F, 32, 0 |
||||
- add rFEFE, rFEFE, rTMP |
||||
- b L(g1) |
||||
- |
||||
-L(g0): |
||||
- ldu rWORD1, 8(rSTR1) |
||||
- bne- cr1, L(different) |
||||
- ldu rWORD2, 8(rSTR2) |
||||
-L(g1): add rTMP, rFEFE, rWORD1 |
||||
- nor rNEG, r7F7F, rWORD1 |
||||
- bdz L(tail) |
||||
- and. rTMP, rTMP, rNEG |
||||
- cmpd cr1, rWORD1, rWORD2 |
||||
- beq+ L(g0) |
||||
- |
||||
-/* OK. We've hit the end of the string. We need to be careful that |
||||
- we don't compare two strings as different because of gunk beyond |
||||
- the end of the strings... */ |
||||
- |
||||
-#ifdef __LITTLE_ENDIAN__ |
||||
-L(endstring): |
||||
- addi rTMP2, rTMP, -1 |
||||
- beq cr1, L(equal) |
||||
- andc rTMP2, rTMP2, rTMP |
||||
- rldimi rTMP2, rTMP2, 1, 0 |
||||
- and rWORD2, rWORD2, rTMP2 /* Mask off gunk. */ |
||||
- and rWORD1, rWORD1, rTMP2 |
||||
- cmpd cr1, rWORD1, rWORD2 |
||||
- beq cr1, L(equal) |
||||
- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ |
||||
- neg rNEG, rBITDIF |
||||
- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ |
||||
- cntlzd rNEG, rNEG /* bitcount of the bit. */ |
||||
- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ |
||||
- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ |
||||
- sld rWORD2, rWORD2, rNEG |
||||
- xor. rBITDIF, rWORD1, rWORD2 |
||||
- sub rRTN, rWORD1, rWORD2 |
||||
- blt- L(highbit) |
||||
- sradi rRTN, rRTN, 63 /* must return an int. */ |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-L(equal): |
||||
- li rRTN, 0 |
||||
- blr |
||||
- |
||||
-L(different): |
||||
- ld rWORD1, -8(rSTR1) |
||||
- xor rBITDIF, rWORD1, rWORD2 /* rBITDIF has bits that differ. */ |
||||
- neg rNEG, rBITDIF |
||||
- and rNEG, rNEG, rBITDIF /* rNEG has LS bit that differs. */ |
||||
- cntlzd rNEG, rNEG /* bitcount of the bit. */ |
||||
- andi. rNEG, rNEG, 56 /* bitcount to LS byte that differs. */ |
||||
- sld rWORD1, rWORD1, rNEG /* shift left to clear MS bytes. */ |
||||
- sld rWORD2, rWORD2, rNEG |
||||
- xor. rBITDIF, rWORD1, rWORD2 |
||||
- sub rRTN, rWORD1, rWORD2 |
||||
- blt- L(highbit) |
||||
- sradi rRTN, rRTN, 63 |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-L(highbit): |
||||
- sradi rRTN, rWORD2, 63 |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
- |
||||
-#else |
||||
-L(endstring): |
||||
- and rTMP, r7F7F, rWORD1 |
||||
- beq cr1, L(equal) |
||||
- add rTMP, rTMP, r7F7F |
||||
- xor. rBITDIF, rWORD1, rWORD2 |
||||
- andc rNEG, rNEG, rTMP |
||||
- blt- L(highbit) |
||||
- cntlzd rBITDIF, rBITDIF |
||||
- cntlzd rNEG, rNEG |
||||
- addi rNEG, rNEG, 7 |
||||
- cmpd cr1, rNEG, rBITDIF |
||||
- sub rRTN, rWORD1, rWORD2 |
||||
- blt- cr1, L(equal) |
||||
- sradi rRTN, rRTN, 63 /* must return an int. */ |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-L(equal): |
||||
- li rRTN, 0 |
||||
- blr |
||||
- |
||||
-L(different): |
||||
- ld rWORD1, -8(rSTR1) |
||||
- xor. rBITDIF, rWORD1, rWORD2 |
||||
- sub rRTN, rWORD1, rWORD2 |
||||
- blt- L(highbit) |
||||
- sradi rRTN, rRTN, 63 |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-L(highbit): |
||||
- sradi rRTN, rWORD2, 63 |
||||
- ori rRTN, rRTN, 1 |
||||
- blr |
||||
-#endif |
||||
- |
||||
-/* Oh well. In this case, we just do a byte-by-byte comparison. */ |
||||
- .align 4 |
||||
-L(tail): |
||||
- and. rTMP, rTMP, rNEG |
||||
- cmpd cr1, rWORD1, rWORD2 |
||||
- bne- L(endstring) |
||||
- addi rSTR1, rSTR1, 8 |
||||
- bne- cr1, L(different) |
||||
- addi rSTR2, rSTR2, 8 |
||||
- cmpldi cr1, rN, 0 |
||||
-L(unaligned): |
||||
- mtctr rN /* Power4 wants mtctr 1st in dispatch group */ |
||||
- bgt cr1, L(uz) |
||||
-L(ux): |
||||
- li rRTN, 0 |
||||
- blr |
||||
- .align 4 |
||||
-L(uz): |
||||
- lbz rWORD1, 0(rSTR1) |
||||
- lbz rWORD2, 0(rSTR2) |
||||
- nop |
||||
- b L(u1) |
||||
-L(u0): |
||||
- lbzu rWORD2, 1(rSTR2) |
||||
-L(u1): |
||||
- bdz L(u3) |
||||
- cmpdi cr1, rWORD1, 0 |
||||
- cmpd rWORD1, rWORD2 |
||||
- beq- cr1, L(u3) |
||||
- lbzu rWORD1, 1(rSTR1) |
||||
- bne- L(u2) |
||||
- lbzu rWORD2, 1(rSTR2) |
||||
- bdz L(u3) |
||||
- cmpdi cr1, rWORD1, 0 |
||||
- cmpd rWORD1, rWORD2 |
||||
- bne- L(u3) |
||||
- lbzu rWORD1, 1(rSTR1) |
||||
- bne+ cr1, L(u0) |
||||
- |
||||
-L(u2): lbzu rWORD1, -1(rSTR1) |
||||
-L(u3): sub rRTN, rWORD1, rWORD2 |
||||
- blr |
||||
-END (STRNCMP) |
||||
-libc_hidden_builtin_def (strncmp) |
@ -0,0 +1,240 @@
@@ -0,0 +1,240 @@
|
||||
commit 3395157ff2b0657d70c36169156f67440205c8bf |
||||
Author: Joe Simmons-Talbott <josimmon@redhat.com> |
||||
Date: Tue May 14 14:36:50 2024 +0000 |
||||
|
||||
malloc: Improve aligned_alloc and calloc test coverage. |
||||
|
||||
Add a DSO (malloc/tst-aligned_alloc-lib.so) that can be used during |
||||
testing to interpose malloc with a call that randomly uses either |
||||
aligned_alloc, __libc_malloc, or __libc_calloc in the place of malloc. |
||||
Use LD_PRELOAD with the DSO to mirror malloc/tst-malloc.c testing as an |
||||
example in malloc/tst-malloc-random.c. Add malloc/tst-aligned-alloc-random.c |
||||
as another example that does a number of malloc calls with randomly sized, |
||||
but limited to 0xffff, requests. |
||||
|
||||
The intention is to be able to utilize existing malloc testing to ensure |
||||
that similar allocation APIs are also exposed to the same rigors. |
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com> |
||||
|
||||
Conflicts: |
||||
malloc/Makefile |
||||
(usual tests conflict) |
||||
|
||||
diff --git a/malloc/Makefile b/malloc/Makefile |
||||
index cb4e027d28b179f0..e0fb433a15bad2c2 100644 |
||||
--- a/malloc/Makefile |
||||
+++ b/malloc/Makefile |
||||
@@ -44,6 +44,8 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ |
||||
tst-safe-linking \ |
||||
tst-mallocalign1 \ |
||||
tst-malloc-alternate-path \ |
||||
+ tst-aligned-alloc-random \ |
||||
+ tst-malloc-random \ |
||||
|
||||
tests-static := \ |
||||
tst-interpose-static-nothread \ |
||||
@@ -123,6 +125,7 @@ extra-libs-others = $(extra-libs) |
||||
|
||||
# Helper objects for some tests. |
||||
extra-tests-objs += \ |
||||
+ tst-aligned_alloc-lib.so \ |
||||
tst-interpose-aux-nothread.o \ |
||||
tst-interpose-aux-thread.o \ |
||||
|
||||
@@ -130,6 +133,9 @@ test-extras = \ |
||||
tst-interpose-aux-nothread \ |
||||
tst-interpose-aux-thread \ |
||||
|
||||
+modules-names = \ |
||||
+ tst-aligned_alloc-lib |
||||
+ |
||||
libmemusage-routines = memusage |
||||
libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes)) |
||||
|
||||
@@ -328,3 +334,9 @@ tst-mallocstate-malloc-check-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so |
||||
# libc_malloc_debug.so. |
||||
$(objpfx)tst-mallocstate: $(objpfx)libc_malloc_debug.so |
||||
$(objpfx)tst-mallocstate-malloc-check: $(objpfx)libc_malloc_debug.so |
||||
+ |
||||
+$(objpfx)tst-aligned-alloc-random.out: $(objpfx)tst-aligned_alloc-lib.so |
||||
+$(objpfx)tst-malloc-random.out: $(objpfx)tst-aligned_alloc-lib.so |
||||
+ |
||||
+tst-aligned-alloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so |
||||
+tst-malloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so |
||||
diff --git a/malloc/tst-aligned-alloc-random.c b/malloc/tst-aligned-alloc-random.c |
||||
new file mode 100644 |
||||
index 0000000000000000..f2825ce38f04e04e |
||||
--- /dev/null |
||||
+++ b/malloc/tst-aligned-alloc-random.c |
||||
@@ -0,0 +1,43 @@ |
||||
+/* Test for randomized malloc that calls aligned_alloc |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <stdlib.h> |
||||
+#include <support/check.h> |
||||
+#include <time.h> |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ void *p1; |
||||
+ int i; |
||||
+ |
||||
+ srandom (time (NULL)); |
||||
+ |
||||
+ for (i = 0; i < 1024; i++) |
||||
+ { |
||||
+ size_t size = random () & 0xffff; |
||||
+ |
||||
+ p1 = malloc (size); |
||||
+ TEST_VERIFY (p1 != NULL); |
||||
+ } |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/malloc/tst-aligned_alloc-lib.c b/malloc/tst-aligned_alloc-lib.c |
||||
new file mode 100644 |
||||
index 0000000000000000..0205df5acf6297a5 |
||||
--- /dev/null |
||||
+++ b/malloc/tst-aligned_alloc-lib.c |
||||
@@ -0,0 +1,72 @@ |
||||
+/* Module used for improved aligned_alloc testing. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ Copyright The GNU Toolchain Authors. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public License as |
||||
+ published by the Free Software Foundation; either version 2.1 of the |
||||
+ License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; see the file COPYING.LIB. If |
||||
+ not, see <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <array_length.h> |
||||
+#include <libc-symbols.h> |
||||
+#include <stdlib.h> |
||||
+ |
||||
+extern void *__libc_malloc (size_t size); |
||||
+extern void *__libc_calloc (size_t n, size_t size); |
||||
+ |
||||
+int aligned_alloc_count = 0; |
||||
+int libc_malloc_count = 0; |
||||
+int libc_calloc_count = 0; |
||||
+ |
||||
+/* Get a random alignment value. Biased towards the smaller values. Must be |
||||
+ a power of 2. */ |
||||
+static size_t get_random_alignment (void) |
||||
+{ |
||||
+ size_t aligns[] = { |
||||
+ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384 |
||||
+ }; |
||||
+ |
||||
+ return aligns[random () % array_length (aligns)]; |
||||
+} |
||||
+ |
||||
+static void *get_random_alloc (size_t size) |
||||
+{ |
||||
+ void *retval; |
||||
+ size_t align; |
||||
+ |
||||
+ switch (random() % 3) |
||||
+ { |
||||
+ case 1: |
||||
+ align = get_random_alignment (); |
||||
+ retval = aligned_alloc (align, size); |
||||
+ aligned_alloc_count++; |
||||
+ break; |
||||
+ case 2: |
||||
+ retval = __libc_calloc (1, size); |
||||
+ libc_calloc_count++; |
||||
+ break; |
||||
+ default: |
||||
+ retval = __libc_malloc (size); |
||||
+ libc_malloc_count++; |
||||
+ break; |
||||
+ } |
||||
+ |
||||
+ return retval; |
||||
+} |
||||
+ |
||||
+ |
||||
+void * __random_malloc (size_t size) |
||||
+{ |
||||
+ return get_random_alloc (size); |
||||
+} |
||||
+strong_alias (__random_malloc, malloc) |
||||
diff --git a/malloc/tst-malloc-random.c b/malloc/tst-malloc-random.c |
||||
new file mode 100644 |
||||
index 0000000000000000..762b70c918cc6004 |
||||
--- /dev/null |
||||
+++ b/malloc/tst-malloc-random.c |
||||
@@ -0,0 +1,20 @@ |
||||
+/* Test malloc with random calls to aligned_alloc and calloc. |
||||
+ |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include "tst-malloc.c" |
||||
diff --git a/malloc/tst-malloc.c b/malloc/tst-malloc.c |
||||
index a587cbded66039fb..98be3ee254d75d4e 100644 |
||||
--- a/malloc/tst-malloc.c |
||||
+++ b/malloc/tst-malloc.c |
||||
@@ -19,7 +19,9 @@ |
||||
#include <errno.h> |
||||
#include <malloc.h> |
||||
#include <stdio.h> |
||||
+#include <stdlib.h> |
||||
#include <libc-diag.h> |
||||
+#include <time.h> |
||||
|
||||
static int errors = 0; |
||||
|
||||
@@ -36,6 +38,8 @@ do_test (void) |
||||
void *p, *q; |
||||
int save; |
||||
|
||||
+ srandom (time (NULL)); |
||||
+ |
||||
errno = 0; |
||||
|
||||
DIAG_PUSH_NEEDS_COMMENT; |
@ -0,0 +1,86 @@
@@ -0,0 +1,86 @@
|
||||
commit 9a27b566b2048f599048f2f4afe1cce06c4ef43d |
||||
Author: Miguel Martín <mmartinv@redhat.com> |
||||
Date: Tue Jul 16 17:14:56 2024 +0200 |
||||
|
||||
malloc: avoid global locks in tst-aligned_alloc-lib.c |
||||
|
||||
Make sure the DSO used by aligned_alloc/calloc/malloc tests does not get |
||||
a global lock on multithreaded tests. |
||||
Reviewed-by: Arjun Shankar <arjun@redhat.com> |
||||
|
||||
diff --git a/malloc/tst-aligned_alloc-lib.c b/malloc/tst-aligned_alloc-lib.c |
||||
index 0205df5acf6297a5..9ef1f839c101a6ae 100644 |
||||
--- a/malloc/tst-aligned_alloc-lib.c |
||||
+++ b/malloc/tst-aligned_alloc-lib.c |
||||
@@ -17,37 +17,38 @@ |
||||
License along with the GNU C Library; see the file COPYING.LIB. If |
||||
not, see <https://www.gnu.org/licenses/>. */ |
||||
|
||||
-#include <array_length.h> |
||||
#include <libc-symbols.h> |
||||
#include <stdlib.h> |
||||
+#include <time.h> |
||||
|
||||
extern void *__libc_malloc (size_t size); |
||||
extern void *__libc_calloc (size_t n, size_t size); |
||||
|
||||
+__thread unsigned int seed = 0; |
||||
+ |
||||
int aligned_alloc_count = 0; |
||||
int libc_malloc_count = 0; |
||||
int libc_calloc_count = 0; |
||||
|
||||
-/* Get a random alignment value. Biased towards the smaller values. Must be |
||||
- a power of 2. */ |
||||
-static size_t get_random_alignment (void) |
||||
-{ |
||||
- size_t aligns[] = { |
||||
- 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384 |
||||
- }; |
||||
- |
||||
- return aligns[random () % array_length (aligns)]; |
||||
-} |
||||
- |
||||
-static void *get_random_alloc (size_t size) |
||||
+static void * |
||||
+get_random_alloc (size_t size) |
||||
{ |
||||
void *retval; |
||||
size_t align; |
||||
+ struct timespec tp; |
||||
+ |
||||
+ if (seed == 0) |
||||
+ { |
||||
+ clock_gettime (CLOCK_REALTIME, &tp); |
||||
+ seed = tp.tv_nsec; |
||||
+ } |
||||
|
||||
- switch (random() % 3) |
||||
- { |
||||
+ switch (rand_r (&seed) % 3) |
||||
+ { |
||||
case 1: |
||||
- align = get_random_alignment (); |
||||
+ /* Get a random alignment value. Biased towards the smaller |
||||
+ * values up to 16384. Must be a power of 2. */ |
||||
+ align = 1 << rand_r (&seed) % 15; |
||||
retval = aligned_alloc (align, size); |
||||
aligned_alloc_count++; |
||||
break; |
||||
@@ -59,13 +60,13 @@ static void *get_random_alloc (size_t size) |
||||
retval = __libc_malloc (size); |
||||
libc_malloc_count++; |
||||
break; |
||||
- } |
||||
+ } |
||||
|
||||
return retval; |
||||
} |
||||
|
||||
- |
||||
-void * __random_malloc (size_t size) |
||||
+void * |
||||
+__random_malloc (size_t size) |
||||
{ |
||||
return get_random_alloc (size); |
||||
} |
@ -0,0 +1,251 @@
@@ -0,0 +1,251 @@
|
||||
commit b0fbcb7d0051a68baf26b2aed51a8a31c34d68e5 |
||||
Author: Miguel Martín <mmartinv@redhat.com> |
||||
Date: Tue Jul 16 17:14:57 2024 +0200 |
||||
|
||||
malloc: add multi-threaded tests for aligned_alloc/calloc/malloc |
||||
|
||||
Improve aligned_alloc/calloc/malloc test coverage by adding |
||||
multi-threaded tests with random memory allocations and with/without |
||||
cross-thread memory deallocations. |
||||
|
||||
Perform a number of memory allocation calls with random sizes limited |
||||
to 0xffff. |
||||
|
||||
Use the existing DSO ('malloc/tst-aligned_alloc-lib.c') to randomize |
||||
allocator selection. |
||||
|
||||
The multi-threaded allocation/deallocation is staged as described below: |
||||
|
||||
- Stage 1: Half of the threads will be allocating memory and the |
||||
other half will be waiting for them to finish the allocation. |
||||
- Stage 2: Half of the threads will be allocating memory and the |
||||
other half will be deallocating memory. |
||||
- Stage 3: Half of the threads will be deallocating memory and the |
||||
second half waiting on them to finish. |
||||
|
||||
Add 'malloc/tst-aligned-alloc-random-thread.c' where each thread will |
||||
deallocate only the memory that was previously allocated by itself. |
||||
|
||||
Add 'malloc/tst-aligned-alloc-random-thread-cross.c' where each thread |
||||
will deallocate memory that was previously allocated by another thread. |
||||
|
||||
The intention is to be able to utilize existing malloc testing to ensure |
||||
that similar allocation APIs are also exposed to the same rigors. |
||||
Reviewed-by: Arjun Shankar <arjun@redhat.com> |
||||
|
||||
Conflicts: |
||||
malloc/Makefile |
||||
(usual tests conflict) |
||||
|
||||
diff --git a/malloc/Makefile b/malloc/Makefile |
||||
index e0fb433a15bad2c2..9dc068f6b3a69caa 100644 |
||||
--- a/malloc/Makefile |
||||
+++ b/malloc/Makefile |
||||
@@ -46,6 +46,8 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ |
||||
tst-malloc-alternate-path \ |
||||
tst-aligned-alloc-random \ |
||||
tst-malloc-random \ |
||||
+ tst-aligned-alloc-random-thread \ |
||||
+ tst-aligned-alloc-random-thread-cross \ |
||||
|
||||
tests-static := \ |
||||
tst-interpose-static-nothread \ |
||||
@@ -96,7 +98,9 @@ tests-exclude-mcheck = tst-mallocstate \ |
||||
tst-malloc-thread-fail \ |
||||
tst-malloc-usable-tunables \ |
||||
tst-malloc_info \ |
||||
- tst-compathooks-off tst-compathooks-on |
||||
+ tst-compathooks-off tst-compathooks-on \ |
||||
+ tst-aligned-alloc-random-thread \ |
||||
+ tst-aligned-alloc-random-thread-cross \ |
||||
|
||||
tests-mcheck = $(filter-out $(tests-exclude-mcheck) $(tests-static), $(tests)) |
||||
endif |
||||
@@ -336,7 +340,11 @@ $(objpfx)tst-mallocstate: $(objpfx)libc_malloc_debug.so |
||||
$(objpfx)tst-mallocstate-malloc-check: $(objpfx)libc_malloc_debug.so |
||||
|
||||
$(objpfx)tst-aligned-alloc-random.out: $(objpfx)tst-aligned_alloc-lib.so |
||||
+$(objpfx)tst-aligned-alloc-random-thread.out: $(objpfx)tst-aligned_alloc-lib.so |
||||
+$(objpfx)tst-aligned-alloc-random-thread-cross.out: $(objpfx)tst-aligned_alloc-lib.so |
||||
$(objpfx)tst-malloc-random.out: $(objpfx)tst-aligned_alloc-lib.so |
||||
|
||||
tst-aligned-alloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so |
||||
+tst-aligned-alloc-random-thread-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so |
||||
+tst-aligned-alloc-random-thread-cross-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so |
||||
tst-malloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so |
||||
diff --git a/malloc/tst-aligned-alloc-random-thread-cross.c b/malloc/tst-aligned-alloc-random-thread-cross.c |
||||
new file mode 100644 |
||||
index 0000000000000000..360ecc56ee7c8c06 |
||||
--- /dev/null |
||||
+++ b/malloc/tst-aligned-alloc-random-thread-cross.c |
||||
@@ -0,0 +1,19 @@ |
||||
+/* multi-threaded memory allocation and cross-thread deallocation test. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public License as |
||||
+ published by the Free Software Foundation; either version 2.1 of the |
||||
+ License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; see the file COPYING.LIB. If |
||||
+ not, see <https://www.gnu.org/licenses/>. */ |
||||
+#define CROSS_THREAD_DEALLOC |
||||
+#include "tst-aligned-alloc-random-thread.c" |
||||
diff --git a/malloc/tst-aligned-alloc-random-thread.c b/malloc/tst-aligned-alloc-random-thread.c |
||||
new file mode 100644 |
||||
index 0000000000000000..e95f79250abec85e |
||||
--- /dev/null |
||||
+++ b/malloc/tst-aligned-alloc-random-thread.c |
||||
@@ -0,0 +1,145 @@ |
||||
+/* multi-threaded memory allocation/deallocation test. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public License as |
||||
+ published by the Free Software Foundation; either version 2.1 of the |
||||
+ License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; see the file COPYING.LIB. If |
||||
+ not, see <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <stdio.h> |
||||
+#include <stdlib.h> |
||||
+#include <string.h> |
||||
+#include <support/check.h> |
||||
+#include <support/support.h> |
||||
+#include <support/xthread.h> |
||||
+#include <support/test-driver.h> |
||||
+#include <sys/sysinfo.h> |
||||
+#include <unistd.h> |
||||
+ |
||||
+#ifndef ITERATIONS |
||||
+# define ITERATIONS 16 |
||||
+#endif |
||||
+ |
||||
+#ifndef NUM_THREADS |
||||
+# define NUM_THREADS 8 |
||||
+#endif |
||||
+ |
||||
+#ifndef NUM_ALLOCATIONS |
||||
+# define NUM_ALLOCATIONS 2048 |
||||
+#endif |
||||
+ |
||||
+static pthread_barrier_t barrier; |
||||
+ |
||||
+__thread unsigned int seed; |
||||
+ |
||||
+typedef struct |
||||
+{ |
||||
+ int id; |
||||
+ pthread_t thread; |
||||
+} thread; |
||||
+ |
||||
+thread threads[NUM_THREADS]; |
||||
+ |
||||
+void *allocations[NUM_THREADS][NUM_ALLOCATIONS]; |
||||
+ |
||||
+void |
||||
+run_thread_dealloc (int id) |
||||
+{ |
||||
+ for (int i = 0; i < NUM_ALLOCATIONS; i++) |
||||
+ { |
||||
+ free (allocations[id][i]); |
||||
+ allocations[id][i] = NULL; |
||||
+ } |
||||
+} |
||||
+ |
||||
+void |
||||
+run_thread_alloc (int id) |
||||
+{ |
||||
+ size_t msb, size; |
||||
+ for (int i = 0; i < NUM_ALLOCATIONS; i++) |
||||
+ { |
||||
+ msb = 1 << rand_r (&seed) % 16; |
||||
+ size = msb + rand_r (&seed) % msb; |
||||
+ allocations[id][i] = malloc (size); |
||||
+ TEST_VERIFY_EXIT (allocations[id][i] != NULL); |
||||
+ } |
||||
+} |
||||
+ |
||||
+void * |
||||
+run_allocations (void *arg) |
||||
+{ |
||||
+ int id = *((int *) arg); |
||||
+ seed = time (NULL) + id; |
||||
+ |
||||
+ /* Stage 1: First half o the threads allocating memory and the second |
||||
+ * half waiting for them to finish |
||||
+ */ |
||||
+ if (id < NUM_THREADS / 2) |
||||
+ run_thread_alloc (id); |
||||
+ |
||||
+ xpthread_barrier_wait (&barrier); |
||||
+ |
||||
+ /* Stage 2: Half of the threads allocationg memory and the other |
||||
+ * half deallocating: |
||||
+ * - In the non cross-thread dealloc scenario the first half will be |
||||
+ * deallocating the memory allocated by themselves in stage 1 and the |
||||
+ * second half will be allocating memory. |
||||
+ * - In the cross-thread dealloc scenario the first half will continue |
||||
+ * to allocate memory and the second half will deallocate the memory |
||||
+ * allocated by the first half in stage 1. |
||||
+ */ |
||||
+ if (id < NUM_THREADS / 2) |
||||
+#ifndef CROSS_THREAD_DEALLOC |
||||
+ run_thread_dealloc (id); |
||||
+#else |
||||
+ run_thread_alloc (id + NUM_THREADS / 2); |
||||
+#endif |
||||
+ else |
||||
+#ifndef CROSS_THREAD_DEALLOC |
||||
+ run_thread_alloc (id); |
||||
+#else |
||||
+ run_thread_dealloc (id - NUM_THREADS / 2); |
||||
+#endif |
||||
+ |
||||
+ xpthread_barrier_wait (&barrier); |
||||
+ |
||||
+ // Stage 3: Second half of the threads deallocating and the first half |
||||
+ // waiting for them to finish. |
||||
+ if (id >= NUM_THREADS / 2) |
||||
+ run_thread_dealloc (id); |
||||
+ |
||||
+ return NULL; |
||||
+} |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ xpthread_barrier_init (&barrier, NULL, NUM_THREADS); |
||||
+ |
||||
+ for (int i = 0; i < ITERATIONS; i++) |
||||
+ { |
||||
+ for (int t = 0; t < NUM_THREADS; t++) |
||||
+ { |
||||
+ threads[t].id = t; |
||||
+ threads[t].thread |
||||
+ = xpthread_create (NULL, run_allocations, &threads[t].id); |
||||
+ } |
||||
+ |
||||
+ for (int t = 0; t < NUM_THREADS; t++) |
||||
+ xpthread_join (threads[t].thread); |
||||
+ } |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
@ -0,0 +1,121 @@
@@ -0,0 +1,121 @@
|
||||
commit a09183aed7bb8ace211e042b2e6e982bcc004957 |
||||
Author: Andreas Schwab <schwab@suse.de> |
||||
Date: Mon Dec 19 12:40:45 2022 +0100 |
||||
|
||||
getdelim: ensure error indicator is set on error (bug 29917) |
||||
|
||||
POSIX requires that getdelim and getline set the error indicator on the |
||||
stream when an error occured, in addition to setting errno. |
||||
|
||||
Conflicts: |
||||
libio/Makefile - Manual merge for the newly added test |
||||
|
||||
diff --git a/libio/Makefile b/libio/Makefile |
||||
index 64398ab1ee..9c69a85c87 100644 |
||||
--- a/libio/Makefile |
||||
+++ b/libio/Makefile |
||||
@@ -66,7 +66,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ |
||||
tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \ |
||||
tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \ |
||||
tst-sprintf-ub tst-sprintf-chk-ub tst-bz24051 tst-bz24153 \ |
||||
- tst-wfile-sync |
||||
+ tst-wfile-sync tst-getdelim |
||||
|
||||
tests-internal = tst-vtables tst-vtables-interposed |
||||
|
||||
diff --git a/libio/iogetdelim.c b/libio/iogetdelim.c |
||||
index b6c4c07b45..591526e9c1 100644 |
||||
--- a/libio/iogetdelim.c |
||||
+++ b/libio/iogetdelim.c |
||||
@@ -43,11 +43,6 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) |
||||
ssize_t cur_len = 0; |
||||
ssize_t len; |
||||
|
||||
- if (lineptr == NULL || n == NULL) |
||||
- { |
||||
- __set_errno (EINVAL); |
||||
- return -1; |
||||
- } |
||||
CHECK_FILE (fp, -1); |
||||
_IO_acquire_lock (fp); |
||||
if (_IO_ferror_unlocked (fp)) |
||||
@@ -56,12 +51,21 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) |
||||
goto unlock_return; |
||||
} |
||||
|
||||
+ if (lineptr == NULL || n == NULL) |
||||
+ { |
||||
+ __set_errno (EINVAL); |
||||
+ fseterr_unlocked (fp); |
||||
+ result = -1; |
||||
+ goto unlock_return; |
||||
+ } |
||||
+ |
||||
if (*lineptr == NULL || *n == 0) |
||||
{ |
||||
*n = 120; |
||||
*lineptr = (char *) malloc (*n); |
||||
if (*lineptr == NULL) |
||||
{ |
||||
+ fseterr_unlocked (fp); |
||||
result = -1; |
||||
goto unlock_return; |
||||
} |
||||
@@ -88,6 +92,7 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) |
||||
if (__glibc_unlikely (len >= SSIZE_MAX - cur_len)) |
||||
{ |
||||
__set_errno (EOVERFLOW); |
||||
+ fseterr_unlocked (fp); |
||||
result = -1; |
||||
goto unlock_return; |
||||
} |
||||
@@ -102,6 +107,7 @@ __getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) |
||||
new_lineptr = (char *) realloc (*lineptr, needed); |
||||
if (new_lineptr == NULL) |
||||
{ |
||||
+ fseterr_unlocked (fp); |
||||
result = -1; |
||||
goto unlock_return; |
||||
} |
||||
diff --git a/libio/tst-getdelim.c b/libio/tst-getdelim.c |
||||
new file mode 100644 |
||||
index 0000000000..4443732669 |
||||
--- /dev/null |
||||
+++ b/libio/tst-getdelim.c |
||||
@@ -0,0 +1,36 @@ |
||||
+/* Check that getdelim sets error indicator on error (BZ #29917) |
||||
+ |
||||
+ Copyright (C) 2023 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <stdio.h> |
||||
+#include <errno.h> |
||||
+ |
||||
+#include <support/check.h> |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ clearerr (stdin); |
||||
+ TEST_VERIFY (getdelim (0, 0, '\n', stdin) == -1); |
||||
+ TEST_VERIFY (ferror (stdin) != 0); |
||||
+ TEST_VERIFY (errno == EINVAL); |
||||
+ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
@ -0,0 +1,331 @@
@@ -0,0 +1,331 @@
|
||||
commit 5456af201d4c0a2950200ba756e5f8314ddbbccd |
||||
Author: Carlos O'Donell <carlos@redhat.com> |
||||
Date: Thu May 11 14:00:41 2023 -0400 |
||||
|
||||
stdio-common: Reformat Makefile. |
||||
|
||||
Reflow Makefile. |
||||
Sort using scripts/sort-makefile-lines.py. |
||||
|
||||
Code generation is changed as routines are linked in sorted order |
||||
as expected. |
||||
|
||||
No regressions on x86_64 and i686. |
||||
|
||||
(cherry picked from commit c3004417afc98585089a9282d1d4d60cdef5317a) |
||||
(cherry picked from commit 5b4e90230b8147e273585bf296bf1a9fb6e2b4c2) |
||||
|
||||
diff --git a/stdio-common/Makefile b/stdio-common/Makefile |
||||
index 803f16dae030cb72..76d1d0a1193aa109 100644 |
||||
--- a/stdio-common/Makefile |
||||
+++ b/stdio-common/Makefile |
||||
@@ -22,82 +22,241 @@ subdir := stdio-common |
||||
|
||||
include ../Makeconfig |
||||
|
||||
-headers := stdio_ext.h printf.h bits/printf-ldbl.h bits/stdio_lim.h |
||||
- |
||||
-routines := \ |
||||
- ctermid cuserid \ |
||||
- _itoa _itowa itoa-digits itoa-udigits itowa-digits \ |
||||
- vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex \ |
||||
- reg-modifier reg-type \ |
||||
- printf_size fprintf printf snprintf sprintf asprintf dprintf \ |
||||
- vfwprintf vfscanf vfwscanf \ |
||||
- fscanf scanf sscanf \ |
||||
- perror psignal \ |
||||
- tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \ |
||||
- getline getw putw \ |
||||
- remove rename renameat renameat2 \ |
||||
- flockfile ftrylockfile funlockfile \ |
||||
- isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \ |
||||
- isoc99_vsscanf \ |
||||
- psiginfo gentempfd \ |
||||
- vfscanf-internal vfwscanf-internal iovfscanf \ |
||||
- vfprintf-internal vfwprintf-internal |
||||
- |
||||
-aux := errlist siglist printf-parsemb printf-parsewc fxprintf |
||||
- |
||||
-tests := tstscanf test_rdwr test-popen tstgetln test-fseek \ |
||||
- temptest tst-fileno test-fwrite tst-ungetc tst-ferror \ |
||||
- xbug errnobug \ |
||||
- bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 \ |
||||
- tfformat tiformat tllformat tstdiomisc tst-printfsz tst-wc-printf \ |
||||
- scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \ |
||||
- scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \ |
||||
- tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \ |
||||
- tst-perror tst-sprintf tst-rndseek tst-fdopen tst-fphex bug14 \ |
||||
- tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \ |
||||
- tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \ |
||||
- bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \ |
||||
- scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \ |
||||
- bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \ |
||||
- bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 tst-fmemopen3 \ |
||||
- tst-printf-bz18872 tst-vfprintf-width-prec tst-fmemopen4 \ |
||||
- tst-vfprintf-user-type \ |
||||
- tst-vfprintf-mbs-prec \ |
||||
- tst-scanf-round \ |
||||
- tst-renameat2 tst-bz11319 tst-bz11319-fortify2 \ |
||||
- scanf14a scanf16a \ |
||||
- tst-printf-bz25691 \ |
||||
- tst-vfprintf-width-prec-alloc \ |
||||
- tst-printf-fp-free \ |
||||
- tst-printf-fp-leak \ |
||||
- test-strerr |
||||
- |
||||
- |
||||
-test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble |
||||
+headers := \ |
||||
+ bits/printf-ldbl.h \ |
||||
+ bits/stdio_lim.h \ |
||||
+ printf.h \ |
||||
+ stdio_ext.h \ |
||||
+ # headers |
||||
+ |
||||
+routines := \ |
||||
+ _itoa \ |
||||
+ _itowa \ |
||||
+ asprintf \ |
||||
+ ctermid \ |
||||
+ cuserid \ |
||||
+ dprintf \ |
||||
+ flockfile \ |
||||
+ fprintf \ |
||||
+ fscanf \ |
||||
+ ftrylockfile \ |
||||
+ funlockfile \ |
||||
+ gentempfd \ |
||||
+ getline \ |
||||
+ getw \ |
||||
+ iovfscanf \ |
||||
+ isoc99_fscanf \ |
||||
+ isoc99_scanf \ |
||||
+ isoc99_sscanf \ |
||||
+ isoc99_vfscanf \ |
||||
+ isoc99_vscanf \ |
||||
+ isoc99_vsscanf \ |
||||
+ itoa-digits \ |
||||
+ itoa-udigits \ |
||||
+ itowa-digits \ |
||||
+ perror \ |
||||
+ printf \ |
||||
+ printf-prs \ |
||||
+ printf_fp \ |
||||
+ printf_fphex \ |
||||
+ printf_size \ |
||||
+ psiginfo \ |
||||
+ psignal \ |
||||
+ putw \ |
||||
+ reg-modifier \ |
||||
+ reg-printf \ |
||||
+ reg-type \ |
||||
+ remove \ |
||||
+ rename \ |
||||
+ renameat \ |
||||
+ renameat2 \ |
||||
+ scanf \ |
||||
+ snprintf \ |
||||
+ sprintf \ |
||||
+ sscanf \ |
||||
+ tempnam \ |
||||
+ tempname \ |
||||
+ tmpfile \ |
||||
+ tmpfile64 tmpnam \ |
||||
+ tmpnam_r \ |
||||
+ vfprintf \ |
||||
+ vfprintf-internal \ |
||||
+ vfscanf \ |
||||
+ vfscanf-internal \ |
||||
+ vfwprintf \ |
||||
+ vfwprintf-internal \ |
||||
+ vfwscanf \ |
||||
+ vfwscanf-internal \ |
||||
+ vprintf \ |
||||
+ # routines |
||||
+ |
||||
+aux := \ |
||||
+ errlist \ |
||||
+ fxprintf \ |
||||
+ printf-parsemb \ |
||||
+ printf-parsewc \ |
||||
+ siglist \ |
||||
+ # aux |
||||
+ |
||||
+tests := \ |
||||
+ bug-vfprintf-nargs \ |
||||
+ bug1 \ |
||||
+ bug10 \ |
||||
+ bug11 \ |
||||
+ bug12 \ |
||||
+ bug13 \ |
||||
+ bug14 \ |
||||
+ bug16 \ |
||||
+ bug17 \ |
||||
+ bug18 \ |
||||
+ bug18a \ |
||||
+ bug19 \ |
||||
+ bug19a \ |
||||
+ bug2 \ |
||||
+ bug20 \ |
||||
+ bug21 \ |
||||
+ bug22 \ |
||||
+ bug23 \ |
||||
+ bug23-2 \ |
||||
+ bug23-3 \ |
||||
+ bug23-4 \ |
||||
+ bug24 \ |
||||
+ bug25 \ |
||||
+ bug26 \ |
||||
+ bug3 \ |
||||
+ bug4 \ |
||||
+ bug5 \ |
||||
+ bug6 \ |
||||
+ bug7 \ |
||||
+ bug8 \ |
||||
+ bug9 \ |
||||
+ errnobug \ |
||||
+ scanf1 \ |
||||
+ scanf10 \ |
||||
+ scanf11 \ |
||||
+ scanf12 \ |
||||
+ scanf13 \ |
||||
+ scanf14 \ |
||||
+ scanf14a \ |
||||
+ scanf15 \ |
||||
+ scanf16 \ |
||||
+ scanf16a \ |
||||
+ scanf17 \ |
||||
+ scanf2 \ |
||||
+ scanf3 \ |
||||
+ scanf4 \ |
||||
+ scanf5 \ |
||||
+ scanf7 \ |
||||
+ scanf8 \ |
||||
+ scanf9 \ |
||||
+ temptest \ |
||||
+ test-fseek \ |
||||
+ test-fwrite \ |
||||
+ test-popen \ |
||||
+ test-strerr \ |
||||
+ test-vfprintf \ |
||||
+ test_rdwr \ |
||||
+ tfformat \ |
||||
+ tiformat \ |
||||
+ tllformat \ |
||||
+ tst-bz11319 \ |
||||
+ tst-bz11319-fortify2 \ |
||||
+ tst-cookie \ |
||||
+ tst-fdopen \ |
||||
+ tst-ferror \ |
||||
+ tst-fgets \ |
||||
+ tst-fileno \ |
||||
+ tst-fmemopen \ |
||||
+ tst-fmemopen2 \ |
||||
+ tst-fmemopen3 \ |
||||
+ tst-fmemopen4 \ |
||||
+ tst-fphex \ |
||||
+ tst-fphex-wide \ |
||||
+ tst-fseek \ |
||||
+ tst-fwrite \ |
||||
+ tst-gets \ |
||||
+ tst-grouping \ |
||||
+ tst-long-dbl-fphex \ |
||||
+ tst-obprintf \ |
||||
+ tst-perror \ |
||||
+ tst-popen \ |
||||
+ tst-popen2 \ |
||||
+ tst-printf-bz18872 \ |
||||
+ tst-printf-bz25691 \ |
||||
+ tst-printf-fp-free \ |
||||
+ tst-printf-fp-leak \ |
||||
+ tst-printf-round \ |
||||
+ tst-printfsz \ |
||||
+ tst-put-error \ |
||||
+ tst-renameat2 \ |
||||
+ tst-rndseek \ |
||||
+ tst-scanf-round \ |
||||
+ tst-setvbuf1 \ |
||||
+ tst-sprintf \ |
||||
+ tst-sprintf2 \ |
||||
+ tst-sprintf3 \ |
||||
+ tst-sscanf \ |
||||
+ tst-swprintf \ |
||||
+ tst-swscanf \ |
||||
+ tst-tmpnam \ |
||||
+ tst-ungetc \ |
||||
+ tst-unlockedio \ |
||||
+ tst-vfprintf-mbs-prec \ |
||||
+ tst-vfprintf-user-type \ |
||||
+ tst-vfprintf-width-prec \ |
||||
+ tst-vfprintf-width-prec-alloc \ |
||||
+ tst-wc-printf \ |
||||
+ tstdiomisc \ |
||||
+ tstgetln \ |
||||
+ tstscanf \ |
||||
+ xbug \ |
||||
+ # tests |
||||
+ |
||||
+test-srcs = \ |
||||
+ tst-printf \ |
||||
+ tst-printfsz-islongdouble \ |
||||
+ tst-unbputc \ |
||||
+ # test-srcs |
||||
|
||||
ifeq ($(run-built-tests),yes) |
||||
-tests-special += $(objpfx)tst-unbputc.out $(objpfx)tst-printf.out \ |
||||
- $(objpfx)tst-printf-bz18872-mem.out \ |
||||
- $(objpfx)tst-setvbuf1-cmp.out \ |
||||
- $(objpfx)tst-vfprintf-width-prec-mem.out \ |
||||
- $(objpfx)tst-printfsz-islongdouble.out \ |
||||
- $(objpfx)tst-printf-bz25691-mem.out \ |
||||
- $(objpfx)tst-printf-fp-free-mem.out \ |
||||
- $(objpfx)tst-printf-fp-leak-mem.out |
||||
-generated += tst-printf-bz18872.c tst-printf-bz18872.mtrace \ |
||||
- tst-printf-bz18872-mem.out \ |
||||
- tst-vfprintf-width-prec.mtrace tst-vfprintf-width-prec-mem.out \ |
||||
- tst-printf-bz25691.mtrace tst-printf-bz25691-mem.out \ |
||||
- tst-printf-fp-free.mtrace tst-printf-fp-free-mem.out \ |
||||
- tst-printf-fp-leak.mtrace tst-printf-fp-leak-mem.out |
||||
-endif |
||||
+tests-special += \ |
||||
+ $(objpfx)tst-printf-bz18872-mem.out \ |
||||
+ $(objpfx)tst-printf-bz25691-mem.out \ |
||||
+ $(objpfx)tst-printf-fp-free-mem.out \ |
||||
+ $(objpfx)tst-printf-fp-leak-mem.out \ |
||||
+ $(objpfx)tst-printf.out \ |
||||
+ $(objpfx)tst-printfsz-islongdouble.out \ |
||||
+ $(objpfx)tst-setvbuf1-cmp.out \ |
||||
+ $(objpfx)tst-unbputc.out \ |
||||
+ $(objpfx)tst-vfprintf-width-prec-mem.out \ |
||||
+ # tests-special |
||||
+ |
||||
+generated += \ |
||||
+ tst-printf-bz18872-mem.out \ |
||||
+ tst-printf-bz18872.c \ |
||||
+ tst-printf-bz18872.mtrace \ |
||||
+ tst-printf-bz25691-mem.out \ |
||||
+ tst-printf-bz25691.mtrace \ |
||||
+ tst-printf-fp-free-mem.out \ |
||||
+ tst-printf-fp-free.mtrace \ |
||||
+ tst-printf-fp-leak-mem.out \ |
||||
+ tst-printf-fp-leak.mtrace \ |
||||
+ tst-vfprintf-width-prec-mem.out \ |
||||
+ tst-vfprintf-width-prec.mtrace \ |
||||
+ # generated |
||||
+endif # $(run-built-tests) |
||||
|
||||
tests-special += $(objpfx)tst-errno-manual.out |
||||
|
||||
include ../Rules |
||||
|
||||
ifeq ($(run-built-tests),yes) |
||||
-LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ISO-8859-1 ja_JP.EUC-JP |
||||
+LOCALES := \ |
||||
+ de_DE.ISO-8859-1 \ |
||||
+ de_DE.UTF-8 \ |
||||
+ en_US.ISO-8859-1 \ |
||||
+ ja_JP.EUC-JP \ |
||||
+ # LOCALES |
||||
include ../gen-locales.mk |
||||
|
||||
$(objpfx)bug14.out: $(gen-locales) |
@ -0,0 +1,201 @@
@@ -0,0 +1,201 @@
|
||||
commit 9556acd249687ac562deb6309503165d66eb06fa |
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
Date: Thu Dec 21 15:59:15 2023 -0300 |
||||
|
||||
debug: Adapt fortify tests to libsupport |
||||
|
||||
Checked on aarch64, armhf, x86_64, and i686. |
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
|
||||
diff --git a/debug/test-stpcpy_chk.c b/debug/test-stpcpy_chk.c |
||||
index 96ad600bc2760cbd..c3cb52d987f9db4f 100644 |
||||
--- a/debug/test-stpcpy_chk.c |
||||
+++ b/debug/test-stpcpy_chk.c |
||||
@@ -20,7 +20,7 @@ |
||||
#define STRCPY_RESULT(dst, len) ((dst) + (len)) |
||||
#define TEST_MAIN |
||||
#define TEST_NAME "stpcpy_chk" |
||||
-#include "../string/test-string.h" |
||||
+#include <string/test-string.h> |
||||
|
||||
extern void __attribute__ ((noreturn)) __chk_fail (void); |
||||
char *simple_stpcpy_chk (char *, const char *, size_t); |
||||
diff --git a/debug/test-strcpy_chk.c b/debug/test-strcpy_chk.c |
||||
index 80c07482aaa54e3b..bb89e342caef470b 100644 |
||||
--- a/debug/test-strcpy_chk.c |
||||
+++ b/debug/test-strcpy_chk.c |
||||
@@ -21,7 +21,7 @@ |
||||
# define STRCPY_RESULT(dst, len) dst |
||||
# define TEST_MAIN |
||||
# define TEST_NAME "strcpy_chk" |
||||
-# include "../string/test-string.h" |
||||
+# include <string/test-string.h> |
||||
|
||||
/* This test case implicitly tests the availability of the __chk_fail |
||||
symbol, which is part of the public ABI and may be used |
||||
diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c |
||||
index fb02452f5993c594..01a8703de1e6e09a 100644 |
||||
--- a/debug/tst-fortify.c |
||||
+++ b/debug/tst-fortify.c |
||||
@@ -24,6 +24,7 @@ |
||||
|
||||
#include <assert.h> |
||||
#include <fcntl.h> |
||||
+#include <limits.h> |
||||
#include <locale.h> |
||||
#include <obstack.h> |
||||
#include <setjmp.h> |
||||
@@ -37,6 +38,10 @@ |
||||
#include <sys/select.h> |
||||
#include <sys/socket.h> |
||||
#include <sys/un.h> |
||||
+#include <paths.h> |
||||
+ |
||||
+#include <support/temp_file.h> |
||||
+#include <support/support.h> |
||||
|
||||
#ifndef _GNU_SOURCE |
||||
# define MEMPCPY memcpy |
||||
@@ -53,15 +58,10 @@ |
||||
#define obstack_chunk_alloc malloc |
||||
#define obstack_chunk_free free |
||||
|
||||
-char *temp_filename; |
||||
-static void do_prepare (void); |
||||
-static int do_test (void); |
||||
-#define PREPARE(argc, argv) do_prepare () |
||||
-#define TEST_FUNCTION do_test () |
||||
-#include "../test-skeleton.c" |
||||
+static char *temp_filename; |
||||
|
||||
static void |
||||
-do_prepare (void) |
||||
+do_prepare (int argc, char *argv[]) |
||||
{ |
||||
int temp_fd = create_temp_file ("tst-chk1.", &temp_filename); |
||||
if (temp_fd == -1) |
||||
@@ -78,10 +78,11 @@ do_prepare (void) |
||||
exit (1); |
||||
} |
||||
} |
||||
+#define PREPARE do_prepare |
||||
|
||||
-volatile int chk_fail_ok; |
||||
-volatile int ret; |
||||
-jmp_buf chk_fail_buf; |
||||
+static volatile int chk_fail_ok; |
||||
+static volatile int ret; |
||||
+static jmp_buf chk_fail_buf; |
||||
|
||||
static void |
||||
handler (int sig) |
||||
@@ -103,22 +104,22 @@ wchar_t wbuf[10]; |
||||
#define buf_size sizeof (buf) |
||||
#endif |
||||
|
||||
-volatile size_t l0; |
||||
-volatile char *p; |
||||
-volatile wchar_t *wp; |
||||
-const char *str1 = "JIHGFEDCBA"; |
||||
-const char *str2 = "F"; |
||||
-const char *str3 = "%s%n%s%n"; |
||||
-const char *str4 = "Hello, "; |
||||
-const char *str5 = "World!\n"; |
||||
-const wchar_t *wstr1 = L"JIHGFEDCBA"; |
||||
-const wchar_t *wstr2 = L"F"; |
||||
-const wchar_t *wstr3 = L"%s%n%s%n"; |
||||
-const wchar_t *wstr4 = L"Hello, "; |
||||
-const wchar_t *wstr5 = L"World!\n"; |
||||
-char buf2[10] = "%s"; |
||||
-int num1 = 67; |
||||
-int num2 = 987654; |
||||
+static volatile size_t l0; |
||||
+static volatile char *p; |
||||
+static volatile wchar_t *wp; |
||||
+static const char *str1 = "JIHGFEDCBA"; |
||||
+static const char *str2 = "F"; |
||||
+static const char *str3 = "%s%n%s%n"; |
||||
+static const char *str4 = "Hello, "; |
||||
+static const char *str5 = "World!\n"; |
||||
+static const wchar_t *wstr1 = L"JIHGFEDCBA"; |
||||
+static const wchar_t *wstr2 = L"F"; |
||||
+static const wchar_t *wstr3 = L"%s%n%s%n"; |
||||
+static const wchar_t *wstr4 = L"Hello, "; |
||||
+static const wchar_t *wstr5 = L"World!\n"; |
||||
+static char buf2[10] = "%s"; |
||||
+static int num1 = 67; |
||||
+static int num2 = 987654; |
||||
|
||||
#define FAIL() \ |
||||
do { printf ("Failure on line %d\n", __LINE__); ret = 1; } while (0) |
||||
@@ -1763,3 +1764,5 @@ do_test (void) |
||||
|
||||
return ret; |
||||
} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/debug/tst-longjmp_chk.c b/debug/tst-longjmp_chk.c |
||||
index e4e93d2a36b537d9..37f858606be4c4a2 100644 |
||||
--- a/debug/tst-longjmp_chk.c |
||||
+++ b/debug/tst-longjmp_chk.c |
||||
@@ -10,11 +10,7 @@ |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
|
||||
- |
||||
-static int do_test(void); |
||||
-#define TEST_FUNCTION do_test () |
||||
-#include "../test-skeleton.c" |
||||
- |
||||
+#include <support/support.h> |
||||
|
||||
static jmp_buf b; |
||||
|
||||
@@ -76,3 +72,5 @@ do_test (void) |
||||
puts ("second longjmp returned"); |
||||
return 1; |
||||
} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/debug/tst-longjmp_chk2.c b/debug/tst-longjmp_chk2.c |
||||
index 23d3436d1d26d2d1..69c1ab9db73f14ae 100644 |
||||
--- a/debug/tst-longjmp_chk2.c |
||||
+++ b/debug/tst-longjmp_chk2.c |
||||
@@ -12,9 +12,7 @@ |
||||
#include <sys/resource.h> |
||||
#include <unistd.h> |
||||
|
||||
-static int do_test (void); |
||||
-#define TEST_FUNCTION do_test () |
||||
-#include "../test-skeleton.c" |
||||
+#include <support/support.h> |
||||
|
||||
static jmp_buf mainloop; |
||||
static sigset_t mainsigset; |
||||
@@ -128,3 +126,5 @@ do_test (void) |
||||
|
||||
return 0; |
||||
} |
||||
+ |
||||
+#include <support/test-driver.c> |
||||
diff --git a/debug/tst-longjmp_chk3.c b/debug/tst-longjmp_chk3.c |
||||
index 3155c7769fcbd83f..4434937c597dbe10 100644 |
||||
--- a/debug/tst-longjmp_chk3.c |
||||
+++ b/debug/tst-longjmp_chk3.c |
||||
@@ -20,10 +20,6 @@ |
||||
#include <signal.h> |
||||
#include <string.h> |
||||
|
||||
-static int do_test (void); |
||||
-#define TEST_FUNCTION do_test () |
||||
-#include "../test-skeleton.c" |
||||
- |
||||
static char buf[SIGSTKSZ * 4]; |
||||
static jmp_buf jb; |
||||
|
||||
@@ -83,3 +79,5 @@ do_test (void) |
||||
puts ("longjmp returned and shouldn't"); |
||||
return 1; |
||||
} |
||||
+ |
||||
+#include <support/test-driver.c> |
@ -0,0 +1,195 @@
@@ -0,0 +1,195 @@
|
||||
commit 388c9d7294e5ee3b741aef2e8af63eb1f76ace86 |
||||
Author: Maciej W. Rozycki <macro@redhat.com> |
||||
Date: Fri Jul 26 13:21:34 2024 +0100 |
||||
|
||||
support: Add FAIL test failure helper |
||||
|
||||
Add a FAIL test failure helper analogous to FAIL_RET, that does not |
||||
cause the current function to return, providing a standardized way to |
||||
report a test failure with a message supplied while permitting the |
||||
caller to continue executing, for further reporting, cleaning up, etc. |
||||
|
||||
Update existing test cases that provide a conflicting definition of FAIL |
||||
by removing the local FAIL definition and then as follows: |
||||
|
||||
- tst-fortify-syslog: provide a meaningful message in addition to the |
||||
file name already added by <support/check.h>; 'support_record_failure' |
||||
is already called by 'support_print_failure_impl' invoked by the new |
||||
FAIL test failure helper. |
||||
|
||||
- tst-ctype: no update to FAIL calls required, with the name of the file |
||||
and the line number within of the failure site additionally included |
||||
by the new FAIL test failure helper, and error counting plus count |
||||
reporting upon test program termination also already provided by |
||||
'support_record_failure' and 'support_report_failure' respectively, |
||||
called by 'support_print_failure_impl' and 'adjust_exit_status' also |
||||
respectively. However in a number of places 'printf' is called and |
||||
the error count adjusted by hand, so update these places to make use |
||||
of FAIL instead. And last but not least adjust the final summary just |
||||
to report completion, with any error count following as reported by |
||||
the test driver. |
||||
|
||||
- test-tgmath2: no update to FAIL calls required, with the name of the |
||||
file of the failure site additionally included by the new FAIL test |
||||
failure helper. Also there is no need to track the return status by |
||||
hand as any call to FAIL will eventually cause the test case to return |
||||
an unsuccesful exit status regardless of the return status from the |
||||
test function, via a call to 'adjust_exit_status' made by the test |
||||
driver. |
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com> |
||||
(cherry picked from commit 1b97a9f23bf605ca608162089c94187573fb2a9e) |
||||
(cherry picked from commit 28f358bc4209ab0425170cdccf65bb1fe861148f) |
||||
|
||||
diff --git a/localedata/tst-ctype.c b/localedata/tst-ctype.c |
||||
index 1e4fa132bb4e17c6..f8645e31db8a1691 100644 |
||||
--- a/localedata/tst-ctype.c |
||||
+++ b/localedata/tst-ctype.c |
||||
@@ -22,6 +22,8 @@ |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
|
||||
+#include <support/check.h> |
||||
+ |
||||
|
||||
static const char lower[] = "abcdefghijklmnopqrstuvwxyz"; |
||||
static const char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
||||
@@ -54,19 +56,11 @@ static struct classes |
||||
#define nclasses (sizeof (classes) / sizeof (classes[0])) |
||||
|
||||
|
||||
-#define FAIL(str, args...) \ |
||||
- { \ |
||||
- printf (" " str "\n", ##args); \ |
||||
- ++errors; \ |
||||
- } |
||||
- |
||||
- |
||||
static int |
||||
do_test (void) |
||||
{ |
||||
const char *cp; |
||||
const char *cp2; |
||||
- int errors = 0; |
||||
char *inpline = NULL; |
||||
size_t inplinelen = 0; |
||||
char *resline = NULL; |
||||
@@ -395,11 +389,8 @@ punct = %04x alnum = %04x\n", |
||||
{ |
||||
if (((__ctype_b[(unsigned int) *inp] & classes[n].mask) != 0) |
||||
!= (*resp != '0')) |
||||
- { |
||||
- printf (" is%s('%c' = '\\x%02x') %s true\n", inpline, |
||||
- *inp, *inp, *resp == '1' ? "not" : "is"); |
||||
- ++errors; |
||||
- } |
||||
+ FAIL (" is%s('%c' = '\\x%02x') %s true\n", inpline, |
||||
+ *inp, *inp, *resp == '1' ? "not" : "is"); |
||||
++inp; |
||||
++resp; |
||||
} |
||||
@@ -409,11 +400,8 @@ punct = %04x alnum = %04x\n", |
||||
while (*inp != '\0') |
||||
{ |
||||
if (tolower (*inp) != *resp) |
||||
- { |
||||
- printf (" tolower('%c' = '\\x%02x') != '%c'\n", |
||||
- *inp, *inp, *resp); |
||||
- ++errors; |
||||
- } |
||||
+ FAIL (" tolower('%c' = '\\x%02x') != '%c'\n", |
||||
+ *inp, *inp, *resp); |
||||
++inp; |
||||
++resp; |
||||
} |
||||
@@ -423,11 +411,8 @@ punct = %04x alnum = %04x\n", |
||||
while (*inp != '\0') |
||||
{ |
||||
if (toupper (*inp) != *resp) |
||||
- { |
||||
- printf (" toupper('%c' = '\\x%02x') != '%c'\n", |
||||
- *inp, *inp, *resp); |
||||
- ++errors; |
||||
- } |
||||
+ FAIL (" toupper('%c' = '\\x%02x') != '%c'\n", |
||||
+ *inp, *inp, *resp); |
||||
++inp; |
||||
++resp; |
||||
} |
||||
@@ -437,14 +422,7 @@ punct = %04x alnum = %04x\n", |
||||
} |
||||
|
||||
|
||||
- if (errors != 0) |
||||
- { |
||||
- printf (" %d error%s for `%s' locale\n\n\n", errors, |
||||
- errors == 1 ? "" : "s", setlocale (LC_ALL, NULL)); |
||||
- return 1; |
||||
- } |
||||
- |
||||
- printf (" No errors for `%s' locale\n\n\n", setlocale (LC_ALL, NULL)); |
||||
+ printf ("Completed testing for `%s' locale\n\n\n", setlocale (LC_ALL, NULL)); |
||||
return 0; |
||||
} |
||||
|
||||
diff --git a/math/test-tgmath2.c b/math/test-tgmath2.c |
||||
index b8fb00c566439ab0..e3b7a3a3615e083a 100644 |
||||
--- a/math/test-tgmath2.c |
||||
+++ b/math/test-tgmath2.c |
||||
@@ -25,6 +25,8 @@ |
||||
#include <string.h> |
||||
#include <tgmath.h> |
||||
|
||||
+#include <support/check.h> |
||||
+ |
||||
//#define DEBUG |
||||
|
||||
typedef complex float cfloat; |
||||
@@ -88,13 +90,6 @@ enum |
||||
int count; |
||||
int counts[Tlast][C_last]; |
||||
|
||||
-#define FAIL(str) \ |
||||
- do \ |
||||
- { \ |
||||
- printf ("%s failure on line %d\n", (str), __LINE__); \ |
||||
- result = 1; \ |
||||
- } \ |
||||
- while (0) |
||||
#define TEST_TYPE_ONLY(expr, rettype) \ |
||||
do \ |
||||
{ \ |
||||
@@ -134,8 +129,6 @@ int counts[Tlast][C_last]; |
||||
int |
||||
test_cos (const int Vint4, const long long int Vllong4) |
||||
{ |
||||
- int result = 0; |
||||
- |
||||
TEST (cos (vfloat1), float, cos); |
||||
TEST (cos (vdouble1), double, cos); |
||||
TEST (cos (vldouble1), ldouble, cos); |
||||
@@ -153,7 +146,7 @@ test_cos (const int Vint4, const long long int Vllong4) |
||||
TEST (cos (Vcdouble1), cdouble, cos); |
||||
TEST (cos (Vcldouble1), cldouble, cos); |
||||
|
||||
- return result; |
||||
+ return 0; |
||||
} |
||||
|
||||
int |
||||
diff --git a/support/check.h b/support/check.h |
||||
index 9b1844352f32513a..8e045dd9c0c36b4c 100644 |
||||
--- a/support/check.h |
||||
+++ b/support/check.h |
||||
@@ -24,6 +24,11 @@ |
||||
|
||||
__BEGIN_DECLS |
||||
|
||||
+/* Record a test failure, print the failure message to standard output |
||||
+ and pass the result of 1 through. */ |
||||
+#define FAIL(...) \ |
||||
+ support_print_failure_impl (__FILE__, __LINE__, __VA_ARGS__) |
||||
+ |
||||
/* Record a test failure, print the failure message to standard output |
||||
and return 1. */ |
||||
#define FAIL_RET(...) \ |
@ -0,0 +1,169 @@
@@ -0,0 +1,169 @@
|
||||
commit 86f5cfe77d60ca4f78f270adc7ae2c15a1d8d4bc |
||||
Author: Maciej W. Rozycki <macro@redhat.com> |
||||
Date: Fri Jul 26 13:21:34 2024 +0100 |
||||
|
||||
stdio-common: Add test for vfscanf with matches longer than INT_MAX [BZ #27650] |
||||
|
||||
Complement commit b03e4d7bd25b ("stdio: fix vfscanf with matches longer |
||||
than INT_MAX (bug 27650)") and add a test case for the issue, inspired |
||||
by the reproducer provided with the bug report. |
||||
|
||||
This has been verified to succeed as from the commit referred and fail |
||||
beforehand. |
||||
|
||||
As the test requires 2GiB of data to be passed around its performance |
||||
has been evaluated using a choice of systems and the execution time |
||||
determined to be respectively in the range of 9s for POWER9@2.166GHz, |
||||
24s for FU740@1.2GHz, and 40s for 74Kf@950MHz. As this is on the verge |
||||
of and beyond the default timeout it has been increased by the factor of |
||||
8. Regardless, following recent practice the test has been added to the |
||||
standard rather than extended set. |
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com> |
||||
(cherry picked from commit 89cddc8a7096f3d9225868304d2bc0a1aaf07d63) |
||||
(cherry picked from commit 99ffa84bdcdc3d81e82f448279f0c8278dd30964) |
||||
|
||||
diff --git a/stdio-common/Makefile b/stdio-common/Makefile |
||||
index 76d1d0a1193aa109..08bedd01be61a55d 100644 |
||||
--- a/stdio-common/Makefile |
||||
+++ b/stdio-common/Makefile |
||||
@@ -190,6 +190,7 @@ tests := \ |
||||
tst-put-error \ |
||||
tst-renameat2 \ |
||||
tst-rndseek \ |
||||
+ tst-scanf-bz27650 \ |
||||
tst-scanf-round \ |
||||
tst-setvbuf1 \ |
||||
tst-sprintf \ |
||||
@@ -241,6 +242,7 @@ generated += \ |
||||
tst-printf-fp-free.mtrace \ |
||||
tst-printf-fp-leak-mem.out \ |
||||
tst-printf-fp-leak.mtrace \ |
||||
+ tst-scanf-bz27650.mtrace \ |
||||
tst-vfprintf-width-prec-mem.out \ |
||||
tst-vfprintf-width-prec.mtrace \ |
||||
# generated |
||||
@@ -283,6 +285,9 @@ tst-printf-fp-free-ENV = \ |
||||
tst-printf-fp-leak-ENV = \ |
||||
MALLOC_TRACE=$(objpfx)tst-printf-fp-leak.mtrace \ |
||||
LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so |
||||
+tst-scanf-bz27650-ENV = \ |
||||
+ MALLOC_TRACE=$(objpfx)tst-scanf-bz27650.mtrace \ |
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so |
||||
|
||||
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc |
||||
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \ |
||||
diff --git a/stdio-common/tst-scanf-bz27650.c b/stdio-common/tst-scanf-bz27650.c |
||||
new file mode 100644 |
||||
index 0000000000000000..3a742bc86556908c |
||||
--- /dev/null |
||||
+++ b/stdio-common/tst-scanf-bz27650.c |
||||
@@ -0,0 +1,108 @@ |
||||
+/* Test for BZ #27650, formatted input matching beyond INT_MAX. |
||||
+ Copyright (C) 2024 Free Software Foundation, Inc. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <error.h> |
||||
+#include <errno.h> |
||||
+#include <limits.h> |
||||
+#include <mcheck.h> |
||||
+#include <stddef.h> |
||||
+#include <stdio.h> |
||||
+#include <stdlib.h> |
||||
+#include <string.h> |
||||
+ |
||||
+#include <sys/types.h> |
||||
+ |
||||
+#include <support/check.h> |
||||
+#include <support/test-driver.h> |
||||
+ |
||||
+/* Produce a stream of more than INT_MAX characters via buffer BUF of |
||||
+ size SIZE according to bookkeeping in COOKIE and then return EOF. */ |
||||
+ |
||||
+static ssize_t |
||||
+io_read (void *cookie, char *buf, size_t size) |
||||
+{ |
||||
+ unsigned int *written = cookie; |
||||
+ unsigned int w = *written; |
||||
+ |
||||
+ if (w > INT_MAX) |
||||
+ return 0; |
||||
+ |
||||
+ memset (buf, 'a', size); |
||||
+ *written = w + size; |
||||
+ return size; |
||||
+} |
||||
+ |
||||
+/* Consume a stream of more than INT_MAX characters from an artificial |
||||
+ input stream of which none is the new line character. The call to |
||||
+ fscanf is supposed to complete upon the EOF condition of input, |
||||
+ however in the presence of BZ #27650 it will terminate prematurely |
||||
+ with characters still outstanding in input. Diagnose the condition |
||||
+ and return status accordingly. */ |
||||
+ |
||||
+int |
||||
+do_test (void) |
||||
+{ |
||||
+ static cookie_io_functions_t io_funcs = { .read = io_read }; |
||||
+ unsigned int written = 0; |
||||
+ FILE *in; |
||||
+ int v; |
||||
+ |
||||
+ mtrace (); |
||||
+ |
||||
+ in = fopencookie (&written, "r", io_funcs); |
||||
+ if (in == NULL) |
||||
+ { |
||||
+ FAIL ("fopencookie: %m"); |
||||
+ goto out; |
||||
+ } |
||||
+ |
||||
+ v = fscanf (in, "%*[^\n]"); |
||||
+ if (ferror (in)) |
||||
+ { |
||||
+ FAIL ("fscanf: input failure, at %u: %m", written); |
||||
+ goto out_close; |
||||
+ } |
||||
+ else if (v == EOF) |
||||
+ { |
||||
+ FAIL ("fscanf: unexpected end of file, at %u", written); |
||||
+ goto out_close; |
||||
+ } |
||||
+ |
||||
+ if (!feof (in)) |
||||
+ { |
||||
+ v = fgetc (in); |
||||
+ if (ferror (in)) |
||||
+ FAIL ("fgetc: input failure: %m"); |
||||
+ else if (v == EOF) |
||||
+ FAIL ("fgetc: unexpected end of file after missing end of file"); |
||||
+ else if (v == '\n') |
||||
+ FAIL ("unexpected new line character received"); |
||||
+ else |
||||
+ FAIL ("character received after end of file expected: \\x%02x", v); |
||||
+ } |
||||
+ |
||||
+out_close: |
||||
+ if (fclose (in) != 0) |
||||
+ FAIL ("fclose: %m"); |
||||
+ |
||||
+out: |
||||
+ return EXIT_SUCCESS; |
||||
+} |
||||
+ |
||||
+#define TIMEOUT (DEFAULT_TIMEOUT * 8) |
||||
+#include <support/test-driver.c> |
@ -0,0 +1,143 @@
@@ -0,0 +1,143 @@
|
||||
commit af68f0f6755c3b82ecef6dd67079df64eee8d946 |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Wed Aug 14 19:20:04 2024 -0400 |
||||
|
||||
Make tst-ungetc use libsupport |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
(cherry picked from commit 3f7df7e757f4efec38e45d4068e5492efcac4856) |
||||
(cherry picked from commit 87a1968a72e4b4e5436f3e2be1ed8a8d5a5862c7) |
||||
|
||||
diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c |
||||
index 1344b2b591e3d6b1..5c808f073419f00b 100644 |
||||
--- a/stdio-common/tst-ungetc.c |
||||
+++ b/stdio-common/tst-ungetc.c |
||||
@@ -1,70 +1,72 @@ |
||||
-/* Test for ungetc bugs. */ |
||||
+/* Test for ungetc bugs. |
||||
+ Copyright (C) 1996-2024 Free Software Foundation, Inc. |
||||
+ Copyright The GNU Toolchain Authors. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
-#include <unistd.h> |
||||
- |
||||
-#undef assert |
||||
-#define assert(x) \ |
||||
- if (!(x)) \ |
||||
- { \ |
||||
- fputs ("test failed: " #x "\n", stderr); \ |
||||
- retval = 1; \ |
||||
- goto the_end; \ |
||||
- } |
||||
+#include <support/check.h> |
||||
+#include <support/support.h> |
||||
+#include <support/temp_file.h> |
||||
+#include <support/xstdio.h> |
||||
+#include <support/xunistd.h> |
||||
|
||||
-int |
||||
-main (int argc, char *argv[]) |
||||
+static int |
||||
+do_test (void) |
||||
{ |
||||
- char name[] = "/tmp/tst-ungetc.XXXXXX"; |
||||
+ char *name = NULL; |
||||
FILE *fp = NULL; |
||||
- int retval = 0; |
||||
int c; |
||||
char buffer[64]; |
||||
|
||||
- int fd = mkstemp (name); |
||||
+ int fd = create_temp_file ("tst-ungetc.", &name); |
||||
if (fd == -1) |
||||
- { |
||||
- printf ("mkstemp failed: %m\n"); |
||||
- return 1; |
||||
- } |
||||
- close (fd); |
||||
- fp = fopen (name, "w"); |
||||
- assert (fp != NULL) |
||||
- fputs ("bla", fp); |
||||
- fclose (fp); |
||||
- fp = NULL; |
||||
+ FAIL_EXIT1 ("cannot create temporary file: %m"); |
||||
+ xclose (fd); |
||||
|
||||
- fp = fopen (name, "r"); |
||||
- assert (fp != NULL); |
||||
- assert (ungetc ('z', fp) == 'z'); |
||||
- assert (getc (fp) == 'z'); |
||||
- assert (getc (fp) == 'b'); |
||||
- assert (getc (fp) == 'l'); |
||||
- assert (ungetc ('m', fp) == 'm'); |
||||
- assert (getc (fp) == 'm'); |
||||
- assert ((c = getc (fp)) == 'a'); |
||||
- assert (getc (fp) == EOF); |
||||
- assert (ungetc (c, fp) == c); |
||||
- assert (feof (fp) == 0); |
||||
- assert (getc (fp) == c); |
||||
- assert (getc (fp) == EOF); |
||||
- fclose (fp); |
||||
- fp = NULL; |
||||
+ fp = xfopen (name, "w"); |
||||
+ fputs ("bla", fp); |
||||
+ xfclose (fp); |
||||
|
||||
- fp = fopen (name, "r"); |
||||
- assert (fp != NULL); |
||||
- assert (getc (fp) == 'b'); |
||||
- assert (getc (fp) == 'l'); |
||||
- assert (ungetc ('b', fp) == 'b'); |
||||
- assert (fread (buffer, 1, 64, fp) == 2); |
||||
- assert (buffer[0] == 'b'); |
||||
- assert (buffer[1] == 'a'); |
||||
+ fp = xfopen (name, "r"); |
||||
+ TEST_VERIFY_EXIT (ungetc ('z', fp) == 'z'); |
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'z'); |
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'b'); |
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'l'); |
||||
+ TEST_VERIFY_EXIT (ungetc ('m', fp) == 'm'); |
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'm'); |
||||
+ TEST_VERIFY_EXIT ((c = getc (fp)) == 'a'); |
||||
+ TEST_VERIFY_EXIT (getc (fp) == EOF); |
||||
+ TEST_VERIFY_EXIT (ungetc (c, fp) == c); |
||||
+ TEST_VERIFY_EXIT (feof (fp) == 0); |
||||
+ TEST_VERIFY_EXIT (getc (fp) == c); |
||||
+ TEST_VERIFY_EXIT (getc (fp) == EOF); |
||||
+ xfclose (fp); |
||||
|
||||
-the_end: |
||||
- if (fp != NULL) |
||||
- fclose (fp); |
||||
- unlink (name); |
||||
+ fp = xfopen (name, "r"); |
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'b'); |
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'l'); |
||||
+ TEST_VERIFY_EXIT (ungetc ('b', fp) == 'b'); |
||||
+ TEST_VERIFY_EXIT (fread (buffer, 1, 64, fp) == 2); |
||||
+ TEST_VERIFY_EXIT (buffer[0] == 'b'); |
||||
+ TEST_VERIFY_EXIT (buffer[1] == 'a'); |
||||
+ xfclose (fp); |
||||
|
||||
- return retval; |
||||
+ return 0; |
||||
} |
||||
+ |
||||
+#include <support/test-driver.c> |
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
commit 01a731da41a6d47cdd6b90f0da1d89dd8cf2b9cd |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Tue Aug 13 21:00:06 2024 -0400 |
||||
|
||||
ungetc: Fix uninitialized read when putting into unused streams [BZ #27821] |
||||
|
||||
When ungetc is called on an unused stream, the backup buffer is |
||||
allocated without the main get area being present. This results in |
||||
every subsequent ungetc (as the stream remains in the backup area) |
||||
checking uninitialized memory in the backup buffer when trying to put a |
||||
character back into the stream. |
||||
|
||||
Avoid comparing the input character with buffer contents when in backup |
||||
to avoid this uninitialized read. The uninitialized read is harmless in |
||||
this context since the location is promptly overwritten with the input |
||||
character, thus fulfilling ungetc functionality. |
||||
|
||||
Also adjust wording in the manual to drop the paragraph that says glibc |
||||
cannot do multiple ungetc back to back since with this change, ungetc |
||||
can actually do this. |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
(cherry picked from commit cdf0f88f97b0aaceb894cc02b21159d148d7065c) |
||||
(cherry picked from commit 804d3c8db79db204154dcf5e11a76f14fdddc570) |
||||
|
||||
diff --git a/libio/genops.c b/libio/genops.c |
||||
index fa509f6219abaf23..a5dd6a06d9e259d8 100644 |
||||
--- a/libio/genops.c |
||||
+++ b/libio/genops.c |
||||
@@ -635,7 +635,7 @@ _IO_sputbackc (FILE *fp, int c) |
||||
{ |
||||
int result; |
||||
|
||||
- if (fp->_IO_read_ptr > fp->_IO_read_base |
||||
+ if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp) |
||||
&& (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c) |
||||
{ |
||||
fp->_IO_read_ptr--; |
||||
diff --git a/manual/stdio.texi b/manual/stdio.texi |
||||
index d3d855fc62b8768b..60ab7e7a5d505bb6 100644 |
||||
--- a/manual/stdio.texi |
||||
+++ b/manual/stdio.texi |
||||
@@ -1467,11 +1467,9 @@ program; usually @code{ungetc} is used only to unread a character that |
||||
was just read from the same stream. @Theglibc{} supports this |
||||
even on files opened in binary mode, but other systems might not. |
||||
|
||||
-@Theglibc{} only supports one character of pushback---in other |
||||
-words, it does not work to call @code{ungetc} twice without doing input |
||||
-in between. Other systems might let you push back multiple characters; |
||||
-then reading from the stream retrieves the characters in the reverse |
||||
-order that they were pushed. |
||||
+@Theglibc{} supports pushing back multiple characters; subsequently |
||||
+reading from the stream retrieves the characters in the reverse order |
||||
+that they were pushed. |
||||
|
||||
Pushing back characters doesn't alter the file; only the internal |
||||
buffering for the stream is affected. If a file positioning function |
||||
diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c |
||||
index 5c808f073419f00b..388b202493ddd586 100644 |
||||
--- a/stdio-common/tst-ungetc.c |
||||
+++ b/stdio-common/tst-ungetc.c |
||||
@@ -48,6 +48,8 @@ do_test (void) |
||||
TEST_VERIFY_EXIT (getc (fp) == 'b'); |
||||
TEST_VERIFY_EXIT (getc (fp) == 'l'); |
||||
TEST_VERIFY_EXIT (ungetc ('m', fp) == 'm'); |
||||
+ TEST_VERIFY_EXIT (ungetc ('n', fp) == 'n'); |
||||
+ TEST_VERIFY_EXIT (getc (fp) == 'n'); |
||||
TEST_VERIFY_EXIT (getc (fp) == 'm'); |
||||
TEST_VERIFY_EXIT ((c = getc (fp)) == 'a'); |
||||
TEST_VERIFY_EXIT (getc (fp) == EOF); |
@ -0,0 +1,136 @@
@@ -0,0 +1,136 @@
|
||||
commit a5cd39541396b91d90cc611858ee7b3355fcfe47 |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Tue Aug 13 21:08:49 2024 -0400 |
||||
|
||||
ungetc: Fix backup buffer leak on program exit [BZ #27821] |
||||
|
||||
If a file descriptor is left unclosed and is cleaned up by _IO_cleanup |
||||
on exit, its backup buffer remains unfreed, registering as a leak in |
||||
valgrind. This is not strictly an issue since (1) the program should |
||||
ideally be closing the stream once it's not in use and (2) the program |
||||
is about to exit anyway, so keeping the backup buffer around a wee bit |
||||
longer isn't a real problem. Free it anyway to keep valgrind happy |
||||
when the streams in question are the standard ones, i.e. stdout, stdin |
||||
or stderr. |
||||
|
||||
Also, the _IO_have_backup macro checks for _IO_save_base, |
||||
which is a roundabout way to check for a backup buffer instead of |
||||
directly looking for _IO_backup_base. The roundabout check breaks when |
||||
the main get area has not been used and user pushes a char into the |
||||
backup buffer with ungetc. Fix this to use the _IO_backup_base |
||||
directly. |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
||||
(cherry picked from commit 3e1d8d1d1dca24ae90df2ea826a8916896fc7e77) |
||||
(cherry picked from commit b9f72bd5de931eac39219018c2fa319a449bb2cf) |
||||
|
||||
diff --git a/libio/genops.c b/libio/genops.c |
||||
index a5dd6a06d9e259d8..b5fc53fd1ef6e911 100644 |
||||
--- a/libio/genops.c |
||||
+++ b/libio/genops.c |
||||
@@ -796,6 +796,12 @@ _IO_unbuffer_all (void) |
||||
legacy = 1; |
||||
#endif |
||||
|
||||
+ /* Free up the backup area if it was ever allocated. */ |
||||
+ if (_IO_have_backup (fp)) |
||||
+ _IO_free_backup_area (fp); |
||||
+ if (fp->_mode > 0 && _IO_have_wbackup (fp)) |
||||
+ _IO_free_wbackup_area (fp); |
||||
+ |
||||
if (! (fp->_flags & _IO_UNBUFFERED) |
||||
/* Iff stream is un-orientated, it wasn't used. */ |
||||
&& (legacy || fp->_mode != 0)) |
||||
diff --git a/libio/libioP.h b/libio/libioP.h |
||||
index dc9a2ce9c8d7744c..bab5f3770f0760c4 100644 |
||||
--- a/libio/libioP.h |
||||
+++ b/libio/libioP.h |
||||
@@ -529,8 +529,8 @@ extern void _IO_old_init (FILE *fp, int flags) __THROW; |
||||
((__fp)->_wide_data->_IO_write_base \ |
||||
= (__fp)->_wide_data->_IO_write_ptr = __p, \ |
||||
(__fp)->_wide_data->_IO_write_end = (__ep)) |
||||
-#define _IO_have_backup(fp) ((fp)->_IO_save_base != NULL) |
||||
-#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_save_base != NULL) |
||||
+#define _IO_have_backup(fp) ((fp)->_IO_backup_base != NULL) |
||||
+#define _IO_have_wbackup(fp) ((fp)->_wide_data->_IO_backup_base != NULL) |
||||
#define _IO_in_backup(fp) ((fp)->_flags & _IO_IN_BACKUP) |
||||
#define _IO_have_markers(fp) ((fp)->_markers != NULL) |
||||
#define _IO_blen(fp) ((fp)->_IO_buf_end - (fp)->_IO_buf_base) |
||||
diff --git a/stdio-common/Makefile b/stdio-common/Makefile |
||||
index 08bedd01be61a55d..f10bf28878e0aebc 100644 |
||||
--- a/stdio-common/Makefile |
||||
+++ b/stdio-common/Makefile |
||||
@@ -201,6 +201,7 @@ tests := \ |
||||
tst-swscanf \ |
||||
tst-tmpnam \ |
||||
tst-ungetc \ |
||||
+ tst-ungetc-leak \ |
||||
tst-unlockedio \ |
||||
tst-vfprintf-mbs-prec \ |
||||
tst-vfprintf-user-type \ |
||||
@@ -229,6 +230,7 @@ tests-special += \ |
||||
$(objpfx)tst-printfsz-islongdouble.out \ |
||||
$(objpfx)tst-setvbuf1-cmp.out \ |
||||
$(objpfx)tst-unbputc.out \ |
||||
+ $(objpfx)tst-ungetc-leak-mem.out \ |
||||
$(objpfx)tst-vfprintf-width-prec-mem.out \ |
||||
# tests-special |
||||
|
||||
@@ -243,6 +245,8 @@ generated += \ |
||||
tst-printf-fp-leak-mem.out \ |
||||
tst-printf-fp-leak.mtrace \ |
||||
tst-scanf-bz27650.mtrace \ |
||||
+ tst-ungetc-leak-mem.out \ |
||||
+ tst-ungetc-leak.mtrace \ |
||||
tst-vfprintf-width-prec-mem.out \ |
||||
tst-vfprintf-width-prec.mtrace \ |
||||
# generated |
||||
@@ -288,6 +292,9 @@ tst-printf-fp-leak-ENV = \ |
||||
tst-scanf-bz27650-ENV = \ |
||||
MALLOC_TRACE=$(objpfx)tst-scanf-bz27650.mtrace \ |
||||
LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so |
||||
+tst-ungetc-leak-ENV = \ |
||||
+ MALLOC_TRACE=$(objpfx)tst-ungetc-leak.mtrace \ |
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so |
||||
|
||||
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc |
||||
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \ |
||||
diff --git a/stdio-common/tst-ungetc-leak.c b/stdio-common/tst-ungetc-leak.c |
||||
new file mode 100644 |
||||
index 0000000000000000..6c5152b43f80b217 |
||||
--- /dev/null |
||||
+++ b/stdio-common/tst-ungetc-leak.c |
||||
@@ -0,0 +1,32 @@ |
||||
+/* Test for memory leak with ungetc when stream is unused. |
||||
+ Copyright The GNU Toolchain Authors. |
||||
+ This file is part of the GNU C Library. |
||||
+ |
||||
+ The GNU C Library is free software; you can redistribute it and/or |
||||
+ modify it under the terms of the GNU Lesser General Public |
||||
+ License as published by the Free Software Foundation; either |
||||
+ version 2.1 of the License, or (at your option) any later version. |
||||
+ |
||||
+ The GNU C Library is distributed in the hope that it will be useful, |
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
+ Lesser General Public License for more details. |
||||
+ |
||||
+ You should have received a copy of the GNU Lesser General Public |
||||
+ License along with the GNU C Library; if not, see |
||||
+ <https://www.gnu.org/licenses/>. */ |
||||
+ |
||||
+#include <stdio.h> |
||||
+#include <mcheck.h> |
||||
+#include <support/check.h> |
||||
+#include <support/support.h> |
||||
+ |
||||
+static int |
||||
+do_test (void) |
||||
+{ |
||||
+ mtrace (); |
||||
+ TEST_COMPARE (ungetc('y', stdin), 'y'); |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+#include <support/test-driver.c> |
@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
|
||||
commit 9d26e50364def249e483b1601beb6ecf9141ecc7 |
||||
Author: Maciej W. Rozycki <macro@redhat.com> |
||||
Date: Fri Jul 26 13:21:34 2024 +0100 |
||||
|
||||
posix: Use <support/check.h> facilities in tst-truncate and tst-truncate64 |
||||
|
||||
Remove local FAIL macro in favor to FAIL_RET from <support/check.h>, |
||||
which provides equivalent reporting, with the name of the file of the |
||||
failure site additionally included, for the tst-truncate-common core |
||||
shared between the tst-truncate and tst-truncate64 tests. |
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com> |
||||
(cherry picked from commit fe47595504a55e7bb992f8928533df154b510383) |
||||
|
||||
diff --git a/posix/tst-truncate-common.c b/posix/tst-truncate-common.c |
||||
index 00c999d372693bfa..1f6c4bd256a638f9 100644 |
||||
--- a/posix/tst-truncate-common.c |
||||
+++ b/posix/tst-truncate-common.c |
||||
@@ -21,6 +21,8 @@ |
||||
#include <sys/stat.h> |
||||
#include <unistd.h> |
||||
|
||||
+#include <support/check.h> |
||||
+ |
||||
static void do_prepare (void); |
||||
#define PREPARE(argc, argv) do_prepare () |
||||
static int do_test (void); |
||||
@@ -42,9 +44,6 @@ do_prepare (void) |
||||
} |
||||
} |
||||
|
||||
-#define FAIL(str) \ |
||||
- do { printf ("error: %s (line %d)\n", str, __LINE__); return 1; } while (0) |
||||
- |
||||
static int |
||||
do_test_with_offset (off_t offset) |
||||
{ |
||||
@@ -54,35 +53,35 @@ do_test_with_offset (off_t offset) |
||||
memset (buf, 0xcf, sizeof (buf)); |
||||
|
||||
if (pwrite (temp_fd, buf, sizeof (buf), offset) != sizeof (buf)) |
||||
- FAIL ("write failed"); |
||||
+ FAIL_RET ("write failed"); |
||||
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + sizeof (buf))) |
||||
- FAIL ("initial size wrong"); |
||||
+ FAIL_RET ("initial size wrong"); |
||||
|
||||
if (ftruncate (temp_fd, offset + 800) < 0) |
||||
- FAIL ("size reduction with ftruncate failed"); |
||||
+ FAIL_RET ("size reduction with ftruncate failed"); |
||||
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800)) |
||||
- FAIL ("size after reduction with ftruncate is incorrect"); |
||||
+ FAIL_RET ("size after reduction with ftruncate is incorrect"); |
||||
|
||||
/* The following test covers more than POSIX. POSIX does not require |
||||
that ftruncate() can increase the file size. But we are testing |
||||
Unix systems. */ |
||||
if (ftruncate (temp_fd, offset + 1200) < 0) |
||||
- FAIL ("size increate with ftruncate failed"); |
||||
+ FAIL_RET ("size increate with ftruncate failed"); |
||||
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200)) |
||||
- FAIL ("size after increase is incorrect"); |
||||
+ FAIL_RET ("size after increase is incorrect"); |
||||
|
||||
if (truncate (temp_filename, offset + 800) < 0) |
||||
- FAIL ("size reduction with truncate failed"); |
||||
+ FAIL_RET ("size reduction with truncate failed"); |
||||
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800)) |
||||
- FAIL ("size after reduction with truncate incorrect"); |
||||
+ FAIL_RET ("size after reduction with truncate incorrect"); |
||||
|
||||
/* The following test covers more than POSIX. POSIX does not require |
||||
that truncate() can increase the file size. But we are testing |
||||
Unix systems. */ |
||||
if (truncate (temp_filename, (offset + 1200)) < 0) |
||||
- FAIL ("size increase with truncate failed"); |
||||
+ FAIL_RET ("size increase with truncate failed"); |
||||
if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200)) |
||||
- FAIL ("size increase with truncate is incorrect"); |
||||
+ FAIL_RET ("size increase with truncate is incorrect"); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,129 @@
@@ -0,0 +1,129 @@
|
||||
commit c21ca2a696c03ff3f3931768a3ada234eebf6337 |
||||
Author: Maciej W. Rozycki <macro@redhat.com> |
||||
Date: Fri Jul 26 13:21:34 2024 +0100 |
||||
|
||||
nptl: Use <support/check.h> facilities in tst-setuid3 |
||||
|
||||
Remove local FAIL macro in favor to FAIL_EXIT1 from <support/check.h>, |
||||
which provides equivalent reporting, with the name of the file and the |
||||
line number within of the failure site additionally included. Remove |
||||
FAIL_ERR altogether and include ": %m" explicitly with the format string |
||||
supplied to FAIL_EXIT1 as there seems little value to have a separate |
||||
macro just for this. |
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com> |
||||
(cherry picked from commit 8c98195af6e6f1ce21743fc26c723e0f7e45bcf2) |
||||
|
||||
diff --git a/sysdeps/pthread/tst-setuid3.c b/sysdeps/pthread/tst-setuid3.c |
||||
index 254555960e1ffe74..88a2a3ef20e273f7 100644 |
||||
--- a/sysdeps/pthread/tst-setuid3.c |
||||
+++ b/sysdeps/pthread/tst-setuid3.c |
||||
@@ -15,24 +15,19 @@ |
||||
License along with the GNU C Library; if not, see |
||||
<https://www.gnu.org/licenses/>. */ |
||||
|
||||
-#include <stdio.h> |
||||
#include <errno.h> |
||||
#include <pthread.h> |
||||
#include <stdbool.h> |
||||
#include <unistd.h> |
||||
|
||||
+#include <support/check.h> |
||||
+ |
||||
/* The test must run under a non-privileged user ID. */ |
||||
static const uid_t test_uid = 1; |
||||
|
||||
static pthread_barrier_t barrier1; |
||||
static pthread_barrier_t barrier2; |
||||
|
||||
-#define FAIL(fmt, ...) \ |
||||
- do { printf ("FAIL: " fmt "\n", __VA_ARGS__); _exit (1); } while (0) |
||||
- |
||||
-#define FAIL_ERR(fmt, ...) \ |
||||
- do { printf ("FAIL: " fmt ": %m\n", __VA_ARGS__); _exit (1); } while (0) |
||||
- |
||||
/* True if x is not a successful return code from pthread_barrier_wait. */ |
||||
static inline bool |
||||
is_invalid_barrier_ret (int x) |
||||
@@ -45,10 +40,10 @@ thread_func (void *ctx __attribute__ ((unused))) |
||||
{ |
||||
int ret = pthread_barrier_wait (&barrier1); |
||||
if (is_invalid_barrier_ret (ret)) |
||||
- FAIL ("pthread_barrier_wait (barrier1) (on thread): %d", ret); |
||||
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier1) (on thread): %d", ret); |
||||
ret = pthread_barrier_wait (&barrier2); |
||||
if (is_invalid_barrier_ret (ret)) |
||||
- FAIL ("pthread_barrier_wait (barrier2) (on thread): %d", ret); |
||||
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier2) (on thread): %d", ret); |
||||
return NULL; |
||||
} |
||||
|
||||
@@ -59,13 +54,13 @@ setuid_failure (int phase) |
||||
switch (ret) |
||||
{ |
||||
case 0: |
||||
- FAIL ("setuid succeeded unexpectedly in phase %d", phase); |
||||
+ FAIL_EXIT1 ("setuid succeeded unexpectedly in phase %d", phase); |
||||
case -1: |
||||
if (errno != EPERM) |
||||
- FAIL_ERR ("setuid phase %d", phase); |
||||
+ FAIL_EXIT1 ("setuid phase %d: %m", phase); |
||||
break; |
||||
default: |
||||
- FAIL ("invalid setuid return value in phase %d: %d", phase, ret); |
||||
+ FAIL_EXIT1 ("invalid setuid return value in phase %d: %d", phase, ret); |
||||
} |
||||
} |
||||
|
||||
@@ -74,42 +69,42 @@ do_test (void) |
||||
{ |
||||
if (getuid () == 0) |
||||
if (setuid (test_uid) != 0) |
||||
- FAIL_ERR ("setuid (%u)", (unsigned) test_uid); |
||||
+ FAIL_EXIT1 ("setuid (%u): %m", (unsigned) test_uid); |
||||
if (setuid (getuid ())) |
||||
- FAIL_ERR ("setuid (%s)", "getuid ()"); |
||||
+ FAIL_EXIT1 ("setuid (%s): %m", "getuid ()"); |
||||
setuid_failure (1); |
||||
|
||||
int ret = pthread_barrier_init (&barrier1, NULL, 2); |
||||
if (ret != 0) |
||||
- FAIL ("pthread_barrier_init (barrier1): %d", ret); |
||||
+ FAIL_EXIT1 ("pthread_barrier_init (barrier1): %d", ret); |
||||
ret = pthread_barrier_init (&barrier2, NULL, 2); |
||||
if (ret != 0) |
||||
- FAIL ("pthread_barrier_init (barrier2): %d", ret); |
||||
+ FAIL_EXIT1 ("pthread_barrier_init (barrier2): %d", ret); |
||||
|
||||
pthread_t thread; |
||||
ret = pthread_create (&thread, NULL, thread_func, NULL); |
||||
if (ret != 0) |
||||
- FAIL ("pthread_create: %d", ret); |
||||
+ FAIL_EXIT1 ("pthread_create: %d", ret); |
||||
|
||||
/* Ensure that the thread is running properly. */ |
||||
ret = pthread_barrier_wait (&barrier1); |
||||
if (is_invalid_barrier_ret (ret)) |
||||
- FAIL ("pthread_barrier_wait (barrier1): %d", ret); |
||||
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier1): %d", ret); |
||||
|
||||
setuid_failure (2); |
||||
|
||||
/* Check success case. */ |
||||
if (setuid (getuid ()) != 0) |
||||
- FAIL_ERR ("setuid (%s)", "getuid ()"); |
||||
+ FAIL_EXIT1 ("setuid (%s): %m", "getuid ()"); |
||||
|
||||
/* Shutdown. */ |
||||
ret = pthread_barrier_wait (&barrier2); |
||||
if (is_invalid_barrier_ret (ret)) |
||||
- FAIL ("pthread_barrier_wait (barrier2): %d", ret); |
||||
+ FAIL_EXIT1 ("pthread_barrier_wait (barrier2): %d", ret); |
||||
|
||||
ret = pthread_join (thread, NULL); |
||||
if (ret != 0) |
||||
- FAIL ("pthread_join: %d", ret); |
||||
+ FAIL_EXIT1 ("pthread_join: %d", ret); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
commit ae4d44b1d501421ad9a3af95279b8f4d1546f1ce |
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Date: Tue Sep 3 14:58:33 2024 -0400 |
||||
|
||||
libio: Attempt wide backup free only for non-legacy code |
||||
|
||||
_wide_data and _mode are not available in legacy code, so do not attempt |
||||
to free the wide backup buffer in legacy code. |
||||
|
||||
Resolves: BZ #32137 and BZ #27821 |
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com> |
||||
|
||||
diff --git a/libio/genops.c b/libio/genops.c |
||||
index b5fc53fd1ef6e911..99ef9d03505f3238 100644 |
||||
--- a/libio/genops.c |
||||
+++ b/libio/genops.c |
||||
@@ -799,7 +799,7 @@ _IO_unbuffer_all (void) |
||||
/* Free up the backup area if it was ever allocated. */ |
||||
if (_IO_have_backup (fp)) |
||||
_IO_free_backup_area (fp); |
||||
- if (fp->_mode > 0 && _IO_have_wbackup (fp)) |
||||
+ if (!legacy && fp->_mode > 0 && _IO_have_wbackup (fp)) |
||||
_IO_free_wbackup_area (fp); |
||||
|
||||
if (! (fp->_flags & _IO_UNBUFFERED) |
Loading…
Reference in new issue