SHA256
8
0
forked from pool/glibc

7 Commits

Author SHA256 Message Date
11bdce59fa +- nss-missing-checks.patch: nss: Missing checks in __nss_configure_lookup,
+  __nss_database_get (bsc#1258319, BZ #28940)
2026-02-17 16:55:56 +01:00
0e0a97f21b - s390-z17.patch: S390: Add new s390 platform z17 (jsc#PED-14685) 2026-01-26 13:01:17 +01:00
045836fcce +- memalign-overflow-check.patch: memalign: reinstate alignment overflow
+  check (CVE-2026-0861, bsc#1256766, BZ #33796)
+- nss-dns-getnetbyaddr.patch: resolv: Fix NSS DNS backend for getnetbyaddr
+  (CVE-2026-0915, bsc#1256822, BZ #33802)
+- nptl-optimize-trylock.patch: nptl: Optimize trylock for high cache
+  contention workloads (bsc#1256436, BZ #33704)
+- wordexp-wrde-reuse.patch: posix: Reset wordexp_t fields with WRDE_REUSE
+  (CVE-2025-15281, bsc#1257005, BZ #33814)
2026-01-26 13:01:17 +01:00
a78eec5d8a Don't use %tmpfiles_create 2026-01-26 13:01:17 +01:00
29991678d3 - Manage files in /var with systemd-tmpfiles (bsc#1253139) 2026-01-07 14:23:42 +01:00
a6b3163cca foo 2025-10-07 13:47:15 +02:00
99d9e86c19 Sync changes to SLFO-1.2 branch 2025-08-20 09:18:05 +02:00
28 changed files with 3433 additions and 7432 deletions

View File

@@ -3,8 +3,6 @@
<package>utils</package>
<package>testsuite</package>
<package>cross-aarch64</package>
<package>cross-hppa</package>
<package>cross-loongarch64</package>
<package>cross-ppc64le</package>
<package>cross-riscv64</package>
<package>cross-s390x</package>

View File

@@ -0,0 +1,63 @@
From 7d4b6bcae91f29d7b4daf15bab06b66cf1d2217c Mon Sep 17 00:00:00 2001
From: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Tue, 21 Jan 2025 16:11:06 -0500
Subject: [PATCH] Fix underallocation of abort_msg_s struct (CVE-2025-0395)
Include the space needed to store the length of the message itself, in
addition to the message string. This resolves BZ #32582.
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 68ee0f704cb81e9ad0a78c644a83e1e9cd2ee578)
---
assert/assert.c | 4 +++-
sysdeps/posix/libc_fatal.c | 4 +++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/assert/assert.c b/assert/assert.c
index c29629f5f6..b6e37d694c 100644
--- a/assert/assert.c
+++ b/assert/assert.c
@@ -18,6 +18,7 @@
#include <assert.h>
#include <atomic.h>
#include <ldsodefs.h>
+#include <libc-pointer-arith.h>
#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
@@ -65,7 +66,8 @@ __assert_fail_base (const char *fmt, const char *assertion, const char *file,
(void) __fxprintf (NULL, "%s", str);
(void) fflush (stderr);
- total = (total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
+ total = ALIGN_UP (total + sizeof (struct abort_msg_s) + 1,
+ GLRO(dl_pagesize));
struct abort_msg_s *buf = __mmap (NULL, total, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
if (__glibc_likely (buf != MAP_FAILED))
diff --git a/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c
index f9e3425e04..089c47b04b 100644
--- a/sysdeps/posix/libc_fatal.c
+++ b/sysdeps/posix/libc_fatal.c
@@ -20,6 +20,7 @@
#include <errno.h>
#include <fcntl.h>
#include <ldsodefs.h>
+#include <libc-pointer-arith.h>
#include <paths.h>
#include <stdarg.h>
#include <stdbool.h>
@@ -105,7 +106,8 @@ __libc_message_impl (const char *fmt, ...)
{
WRITEV_FOR_FATAL (fd, iov, iovcnt, total);
- total = (total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
+ total = ALIGN_UP (total + sizeof (struct abort_msg_s) + 1,
+ GLRO(dl_pagesize));
struct abort_msg_s *buf = __mmap (NULL, total,
PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
--
2.51.0

View File

@@ -1,48 +0,0 @@
From a900dbaf70f0a957f56b52caa69173592ad7596e Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 20 Feb 2025 07:08:26 +0800
Subject: [PATCH] x86 (__HAVE_FLOAT128): Defined to 0 for Intel SYCL compiler
[BZ #32723]
Intel compiler always defines __INTEL_LLVM_COMPILER. When SYCL is
enabled by -fsycl, it also defines SYCL_LANGUAGE_VERSION. Since Intel
SYCL compiler doesn't support _Float128:
https://github.com/intel/llvm/issues/16903
define __HAVE_FLOAT128 to 0 for Intel SYCL compiler.
This fixes BZ #32723.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Sam James <sam@gentoo.org>
(cherry picked from commit 5a4573be6f96ff49111bb6cae767676b5aafa7a8)
---
sysdeps/x86/bits/floatn.h | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/sysdeps/x86/bits/floatn.h b/sysdeps/x86/bits/floatn.h
index d197cb10dd..adc7ed2e9e 100644
--- a/sysdeps/x86/bits/floatn.h
+++ b/sysdeps/x86/bits/floatn.h
@@ -25,11 +25,15 @@
floating-point type with the IEEE 754 binary128 format, and this
glibc includes corresponding *f128 interfaces for it. The required
libgcc support was added some time after the basic compiler
- support, for x86_64 and x86. */
+ support, for x86_64 and x86. Intel SYCL compiler doesn't support
+ _Float128: https://github.com/intel/llvm/issues/16903
+ */
#if (defined __x86_64__ \
? __GNUC_PREREQ (4, 3) \
: (defined __GNU__ ? __GNUC_PREREQ (4, 5) : __GNUC_PREREQ (4, 4))) \
- || __glibc_clang_prereq (3, 4)
+ || (__glibc_clang_prereq (3, 4) \
+ && (!defined __INTEL_LLVM_COMPILER \
+ || !defined SYCL_LANGUAGE_VERSION))
# define __HAVE_FLOAT128 1
#else
# define __HAVE_FLOAT128 0
--
2.48.1

View File

@@ -0,0 +1,28 @@
From 5f62cf88c4530c11904482775b7582bd7f6d80d2 Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@suse.de>
Date: Wed, 25 Sep 2024 11:49:30 +0200
Subject: [PATCH] Fix missing randomness in __gen_tempname (bug 32214)
Make sure to update the random value also if getrandom fails.
Fixes: 686d542025 ("posix: Sync tempname with gnulib")
---
sysdeps/posix/tempname.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c
index c00fe0c181..fc30958a0c 100644
--- a/sysdeps/posix/tempname.c
+++ b/sysdeps/posix/tempname.c
@@ -117,6 +117,8 @@ random_bits (random_value *r, random_value s)
succeed. */
#if !_LIBC
*r = mix_random_values (v, clock ());
+#else
+ *r = v;
#endif
return false;
}
--
2.46.2

BIN
glibc-2.40.tar.xz LFS Normal file

Binary file not shown.

16
glibc-2.40.tar.xz.sig Normal file
View File

@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEcnNUKzmWLfeymZMUFnkrTqJTQPgFAmaeSXIACgkQFnkrTqJT
QPhcfw/+LG5lo6bi7F8Kggp7rsxw1QpRsT76HUNdsoVZRbKvERYihexEQST8rNM/
BvzWv+eAxE8h1XcBdYk3qKtyvsggVogaxnsfRq1+5yonrI0FGDdQZEjDhYVBEPma
T1m8qmZywPingm37gT5RevQJP3vg2OBW9l5/nwGk9K33e+09RXCAyvZVrn7binTV
27VESY5/6X7uC2Ga1WnZG2omu3W5+vAsGWoFnCNjJHfqyW6agaGLbGNSBJnSABv+
mTy4v8S6zpRovWZOA2hi7FUVbtDyvyJrGZLnTNBA/DxqKiKc2ZQUljXy7Uv+piDt
H0bwNsrC0mcRxdqsA8FNUv/gIpHcuBaLjUz37bA6d0iwkvqf8YCJ47O6KbMuuDeu
DudKO+QIVTgs0ahUnbomW27Un46cvkM2JM7dU9Akt5Cja9hImOOn1cbotkaMfmsL
c3Hq+O3LYwI76p3HUwsjg3xjgoLZy24+46PaXRncrYImgTif6yGq4uVjWXnaFsLs
WtE16EU9fvU1zCBRbdcT6cI6TiNQvQdc8aBGxKs4oFTMROWiczfwKmcIrC6OROIJ
kW5V0nI5t3Sk8XSubUxj4dZhk6E1e58RhKm/5pcdOVzwbd3H9sb5q/BhlWB7M49M
i5n7p77a1YCjuhl/m43Q036uDCER7/JSbnekU6zsTYUDX/ZfWiA=
=hPC5
-----END PGP SIGNATURE-----

Binary file not shown.

View File

@@ -1,19 +0,0 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQKTBAABCgB9FiEE/Rnm0xsZLuTcY+rT3CsWIV7VQSoFAmea1xNfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEZE
MTlFNkQzMUIxOTJFRTREQzYzRUFEM0RDMkIxNjIxNUVENTQxMkEACgkQ3CsWIV7V
QSq+Qg//VwaVsRXRHVHHAbbFyqjeYPQfkgIwzOfbrkVEe75L+PnVBF52cRJ8S2YK
FopiiK+xBmS6rUyuzhOVtLSpGepPtOHJI5NzWz2radZmoRhW8ozoFL7iGmJxIYoX
wz6zadwJeg5AFMY3VFNTAtkxRIn7zk25x6LYMj7cIF1dxoh6NbiGGq/5z5Ru+9l0
zX1x1wPfDNqgjW0pZyZ4xt1O853EZjmY1kvsLrrHk+ruq3TGcEUjUlmw3F9LKwny
H9GYwNIfcbnuK7ZDh2cIqxBVd/T8e1Eam+tyVlSaijIHptsF59roBvP3kFAdkDp9
byHnmR8c/5M5KFFdOgURl17ST9yNyOEgMgzrknqk9Onfd24DBz2c/rv93IjrBNpy
Tllw0yGgVElyKeXVSGDm6DOHJT50LB/ra2Pb82zf33rs5prw1yLL7VZ3Y58ysUJq
fi7IGWEFK8uhxT/15jIyp19x2RpQvHJqVIpNQmx/SLbGCuh4lS+1poIng3M5ktMX
R4KviCHrPGWCLQIveqffHiBr6kbKOmZL9NSYFI+o1aINL0pToqT9jw7gA4brYnzn
9Uu9xN4YkSqCXWBXdJCj2rDJDVqOWarUaC7/datpFkdC/hCeN63CQ+cTj166CpdZ
Cyqcai2WeyNJvcoLY3G5J/6BDBzVP78Ze42Ki/IsSo3YDK3NFGg=
=KfhY
-----END PGP SIGNATURE-----

View File

@@ -8,7 +8,7 @@ Index: glibc-2.27/csu/version.c
static const char banner[] =
-"GNU C Library "PKGVERSION RELEASE" release version "VERSION".\n\
+"GNU C Library "PKGVERSION RELEASE" release version "VERSION" (git "GITID").\n\
Copyright (C) 2025 Free Software Foundation, Inc.\n\
Copyright (C) 2024 Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions.\n\
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\
PARTICULAR PURPOSE.\n\

View File

@@ -1,3 +1,43 @@
-------------------------------------------------------------------
Tue Feb 17 15:00:29 UTC 2026 - Andreas Schwab <schwab@suse.de>
- nss-missing-checks.patch: nss: Missing checks in __nss_configure_lookup,
__nss_database_get (bsc#1258319, BZ #28940)
-------------------------------------------------------------------
Mon Jan 26 11:56:25 UTC 2026 - Andreas Schwab <schwab@suse.de>
- s390-z17.patch: S390: Add new s390 platform z17 (jsc#PED-14685)
-------------------------------------------------------------------
Tue Jan 20 10:13:43 UTC 2026 - Andreas Schwab <schwab@suse.de>
- memalign-overflow-check.patch: memalign: reinstate alignment overflow
check (CVE-2026-0861, bsc#1256766, BZ #33796)
- nss-dns-getnetbyaddr.patch: resolv: Fix NSS DNS backend for getnetbyaddr
(CVE-2026-0915, bsc#1256822, BZ #33802)
- nptl-optimize-trylock.patch: nptl: Optimize trylock for high cache
contention workloads (bsc#1256436, BZ #33704)
- wordexp-wrde-reuse.patch: posix: Reset wordexp_t fields with WRDE_REUSE
(CVE-2025-15281, bsc#1257005, BZ #33814)
-------------------------------------------------------------------
Wed Jan 7 13:22:30 UTC 2026 - Andreas Schwab <schwab@suse.de>
- Manage files in /var with systemd-tmpfiles (bsc#1253139)
-------------------------------------------------------------------
Tue Oct 7 10:33:16 UTC 2025 - Andreas Schwab <schwab@suse.de>
- abort-msg-s-underallocation.patch: Fix underallocation of abort_msg_s
struct (CVE-2025-0395, bsc#1236282, BZ #32582)
-------------------------------------------------------------------
Thu Jul 24 10:14:52 UTC 2025 - Andreas Schwab <schwab@suse.de>
- regcomp-double-free.patch: posix: Fix double-free after allocation
failure in regcomp (CVE-2025-8058, bsc#1246965, BZ #33185)
-------------------------------------------------------------------
Tue Jun 17 09:11:26 UTC 2025 - Andreas Schwab <schwab@suse.de>
@@ -8,16 +48,27 @@ Tue Jun 17 09:11:26 UTC 2025 - Andreas Schwab <schwab@suse.de>
implementation (BZ #33059)
-------------------------------------------------------------------
Mon Jun 2 10:54:37 UTC 2025 - Andreas Schwab <schwab@suse.de>
Thu Jun 5 09:18:29 UTC 2025 - Andreas Schwab <schwab@suse.de>
- Add support for userspace livepatching for ppc64le (jsc#PED-11850)
-------------------------------------------------------------------
Mon Jun 2 12:09:30 UTC 2025 - Andreas Schwab <schwab@suse.de>
- Filter GLIBC_PRIVATE symbols again
- Drop ngpt provides
- Refine libc_nonshared.a workaround
- Compile functions in libc_nonshared.a as PIC
-------------------------------------------------------------------
Fri Apr 18 19:50:23 UTC 2025 - Giuliano Belinassi <giuliano.belinassi@suse.com>
Thu Apr 3 14:43:21 UTC 2025 - Andreas Schwab <schwab@suse.de>
- Enable Userspace Livepatching on ppc64le (jsc#PED-7395)
- pthread-wakeup.patch: pthreads NPTL: lost wakeup fix 2 (bsc#1234128, BZ
#25847)
-------------------------------------------------------------------
Mon Mar 24 15:24:22 UTC 2025 - Andreas Schwab <schwab@suse.de>
- Mark functions in libc_nonshared.a as hidden (bsc#1239883)
-------------------------------------------------------------------
Wed Mar 12 10:28:15 UTC 2025 - Andreas Schwab <schwab@suse.de>
@@ -25,26 +76,11 @@ Wed Mar 12 10:28:15 UTC 2025 - Andreas Schwab <schwab@suse.de>
- Do not build libnsl1 (bsc#1239459)
-------------------------------------------------------------------
Wed Feb 26 15:29:17 UTC 2025 - Andreas Schwab <schwab@suse.de>
Wed Feb 26 15:32:06 UTC 2025 - Andreas Schwab <schwab@suse.de>
- Bump minimal kernel version to 4.3 to enable use of direct socketcalls
on x86-32 and s390x (bsc#1234713)
-------------------------------------------------------------------
Thu Feb 20 09:53:20 UTC 2025 - Andreas Schwab <schwab@suse.de>
- Build cross-hppa and cross-loongarch64 only with gcc >= 14
- round-log10p1f.patch: math: Fix log10p1f internal table value (BZ
#32626)
- round-sinhf.patch: math: Fix sinhf for some inputs (BZ #32627)
- nptl-stack-size-up.patch: nptl: Correct stack size attribute when stack
grows up (BZ #32574)
- round-tanf.patch: math: Fix tanf for some inputs (BZ 32630)
- tst-aarch64-pkey.patch: Fix tst-aarch64-pkey to handle ENOSPC as not
supported
- float128-sycl.patch: x86 (__HAVE_FLOAT128): Defined to 0 for Intel SYCL
compiler (BZ #32723)
-------------------------------------------------------------------
Mon Feb 17 10:37:02 UTC 2025 - Andreas Schwab <schwab@suse.de>
@@ -55,66 +91,6 @@ Mon Feb 10 12:19:00 UTC 2025 - Andreas Schwab <schwab@suse.de>
- Use rpm.execute when available (bsc#1236869)
-------------------------------------------------------------------
Wed Jan 29 09:19:29 UTC 2025 - Andreas Schwab <schwab@suse.de>
- Update to glibc 2.41
* In /etc/resolv.conf and the RES_OPTIONS environment variable, option
flags can now be prefixed with “-” to clear previously set flags
* The DNS stub resolver now supports the strict-error option
* On Linux, the sched_setattr and sched_getattr functions have been
added
* The iconv program now supports converting files in place
* Character encoding, character type info, and transliteration tables
have been updated to Unicode 16.0.0
* The following ISO C23 function families (introduced in TS
18661-4:2015) are now supported in <math.h>:
- Trigonometric functions: acospi, asinpi, atan2pi, atanpi, cospi,
sinpi, tanpi.
* The GNU C Library now supports a feature test macro _ISOC2Y_SOURCE to
enable features from the draft ISO C2Y standard
* Optimized and correctly rounded exp10m1f, exp2m1f, expm1f, log10f,
log2p1f, log1pf, log10p1f, cbrtf, erff, erfcf, lgammaf, tgammaf,
tanf, acosf, acoshf, asinf, asinhf, atanf, atan2f, atanhf, coshf,
sinhf, and tanhf functions have been added from the CORE-MATH
project <https://core-math.gitlabpages.inria.fr/>
* A new tunable, glibc.rtld.execstack, can be used to control whether an
executable stack is allowed from the main program, either implicitly
due to a mising GNU_STACK ELF header or explicit explicitly because
of the executable bit in GNU_STACK
* Support for the extensible rseq ABI introduced in the Linux kernel
version 6.3 has been added
* The GNU C Library now supports the Guarded Control Stack extension
that allows to use shadow stacks on AArch64 systems that support this
extension
* Significant effort has been put into improving the code generation
and speed of mathematical functions in the vector mathematics library
on AArch64, with regard to the Scalable Vector Extension (SVE) and
Advanced SIMD (Neon) intrinsics
* Support for memory protection keys on AArch64 systems with enabled
Stage 1 permission overlays feature as introduced in Armv8.9 / 9.4
has been added
* On PowerPC64, support for the return-oriented programming protection
instructions added in ISA 3.1 (Power10) has been added, as well as
function optimizations for Power10
* A new architecture type has been introduced internally to better
support Hygon x86-64 processors
* abort is now async-signal-safe and its implementation makes longjmp
from the SIGABRT handler always abort if set up with setjmp
* dlopen and dlmopen no longer make the stack executable if a shared
library requires it, either implicitly because of a missing GNU_STACK
ELF header (and default ABI permission having the executable bit set)
or explicitly because of the executable bit in GNU_STACK, and the
stack is not already executable
* On recent Linux kernels with vDSO getrandom support, getrandom does
not act as a "shall occur" cancellation point, in which case it might
not issue a syscall or trigger a deferred cancellation event
* GLIBC-SA-2025-0001: assert: Buffer overflow when printing assertion
failure message (CVE-2025-0395)
- Add cross-hppa and cross-loongarch64 packages
- gen-tempname-randomness.patch: Removed
- ulp-prologue-into-asm-functions.patch: Rebase
-------------------------------------------------------------------
Mon Jan 20 13:33:58 UTC 2025 - Andreas Schwab <schwab@suse.de>
@@ -191,6 +167,7 @@ Mon Jul 29 07:50:31 UTC 2024 - Andreas Schwab <schwab@suse.de>
s390-clone-error-clobber-r7.patch, sigisemptyset.patch,
stdbit-builtins.patch, utmp-time-bits.patch: Removed
- glibc-2.3.90-langpackdir.diff: Rediff
- bsc#1228041
-------------------------------------------------------------------
Mon Jun 3 08:24:38 UTC 2024 - Dominique Leuenberger <dimstar@opensuse.org>
@@ -340,7 +317,6 @@ Thu Feb 1 09:25:37 UTC 2024 - Andreas Schwab <schwab@suse.de>
sem-open-o-creat.patch, setxid-propagate-glibc-tunables.patch,
syslog-buffer-overflow.patch, tls-modid-reuse.patch,
tunables-string-parsing.patch: Removed
- CVE-2025-4802
-------------------------------------------------------------------
Wed Jan 31 09:25:16 UTC 2024 - Andreas Schwab <schwab@suse.de>

File diff suppressed because it is too large Load Diff

View File

@@ -34,12 +34,6 @@
%if "%flavor" == "cross-aarch64"
%define cross_cpu aarch64
%endif
%if "%flavor" == "cross-hppa"
%define cross_cpu hppa
%endif
%if "%flavor" == "cross-loongarch64"
%define cross_cpu loongarch64
%endif
%if "%flavor" == "cross-riscv64"
%define cross_cpu riscv64
%endif
@@ -57,13 +51,13 @@
%define sysroot %{_prefix}/%{binutils_os}/sys-root
%endif
%if %{suse_version} >= 1550
%if 0%{?suse_version} >= 1550
%bcond_without usrmerged
%else
%bcond_with usrmerged
%endif
%if %{suse_version} >= 1600
%if 0%{?suse_version} >= 1600
%bcond_with nscd
%else
%bcond_without nscd
@@ -102,7 +96,7 @@ ExclusiveArch: do_not_build
%undefine _build_create_debug
%define _enable_debug_packages 0
ExcludeArch: %{cross_arch}
%if %{suse_version} < 1600
%if 0%{?suse_version} < 1600
ExclusiveArch: do_not_build
%endif
%endif
@@ -186,10 +180,10 @@ Name: glibc%{name_suffix}
Summary: Standard Shared Libraries (from the GNU C Library)
License: GPL-2.0-or-later AND LGPL-2.1-or-later AND LGPL-2.1-or-later WITH GCC-exception-2.0
Group: System/Libraries
Version: 2.41
Version: 2.40
Release: 0
%if %{without snapshot}
%define git_id 74f59e9271
%define git_id ef321e23c2
%define libversion %version
%else
%define git_id %(echo %version | sed 's/.*\.g//')
@@ -201,7 +195,7 @@ Source: https://ftp.gnu.org/pub/gnu/glibc/glibc-%{version}.tar.xz
%if %{without snapshot}
Source1: https://ftp.gnu.org/pub/gnu/glibc/glibc-%{version}.tar.xz.sig
%endif
Source2: https://savannah.gnu.org/project/release-gpgkeys.php?group=libc&download=1&file=./glibc.keyring
Source2: http://savannah.gnu.org/project/memberlist-gpgkeys.php?group=libc&download=1#/glibc.keyring
Source4: manpages.tar.bz2
Source5: nsswitch.conf
Source7: bindresvport.blacklist
@@ -279,11 +273,6 @@ BuildArch: i686
# Sync only this build counter with the main build
#!BcntSyncTag: glibc
%endif
%if 0%{?gcc_version} < 14
%if "%flavor" == "cross-loongarch64" || "%flavor" == "cross-hppa"
ExclusiveArch: do_not_build
%endif
%endif
###
# Patches are ordered in the following groups:
@@ -336,23 +325,31 @@ Patch306: glibc-fix-double-loopback.diff
%if %{without snapshot}
###
# Patches from upstream
# PATCH-FIX-UPSTREAM math: Fix log10p1f internal table value (BZ #32626)
Patch1000: round-log10p1f.patch
# PATCH-FIX-UPSTREAM math: Fix sinhf for some inputs (BZ #32627)
Patch1001: round-sinhf.patch
# PATCH-FIX-UPSTREAM nptl: Correct stack size attribute when stack grows up (BZ #32574)
Patch1002: nptl-stack-size-up.patch
# PATCH-FIX-UPSTREAM math: Fix tanf for some inputs (BZ 32630)
Patch1003: round-tanf.patch
# PATCH-FIX-UPSTREAM Fix tst-aarch64-pkey to handle ENOSPC as not supported
Patch1004: tst-aarch64-pkey.patch
# PATCH-FIX-UPSTREAM x86 (__HAVE_FLOAT128): Defined to 0 for Intel SYCL compiler (BZ #32723)
Patch1005: float128-sycl.patch
###
# PATCH-FIX-UPSTREAM Fix missing randomness in __gen_tempname (BZ #32214)
Patch1000: gen-tempname-randomness.patch
# PATCH-FIX-UPSTREAM pthreads NPTL: lost wakeup fix 2 (BZ #25847)
Patch1001: pthread-wakeup.patch
# PATCH-FIX-UPSTREAM Revert optimized POWER10 strcmp, strncmp implementations (CVE-2025-5745, CVE-2025-5702, BZ #33060, BZ #33056)
Patch1006: ppc64le-revert-power10-strcmp.patch
# PATCH-FIX-UPSTREAM Revert optimized POWER10 memcmp (BZ #33059)
Patch1007: ppc64le-revert-power10-memcmp.patch
###
# PATCH-FIX-UPSTREAM posix: Fix double-free after allocation failure in regcomp (BZ #33185)
Patch1008: regcomp-double-free.patch
# PATCH-FIX-UPSTREAM Fix underallocation of abort_msg_s struct (CVE-2025-0395, BZ #32582)
Patch1009: abort-msg-s-underallocation.patch
# PATCH-FIX-UPSTREAM memalign: reinstate alignment overflow check (CVE-2026-0861, BZ #33796)
Patch1010: memalign-overflow-check.patch
# PATCH-FIX-UPSTREAM resolv: Fix NSS DNS backend for getnetbyaddr (CVE-2026-0915, BZ #33802)
Patch1011: nss-dns-getnetbyaddr.patch
# PATCH-FIX-UPSTREAM nptl: Optimize trylock for high cache contention workloads (BZ #33704)
Patch1012: nptl-optimize-trylock.patch
# PATCH-FIX-UPSTREAM posix: Reset wordexp_t fields with WRDE_REUSE (CVE-2025-15281, BZ #33814)
Patch1013: wordexp-wrde-reuse.patch
# PATCH-FIX-UPSTREAM S390: Add new s390 platform z17
Patch1014: s390-z17.patch
# PATCH-FIX-UPSTREAM nss: Missing checks in __nss_configure_lookup, __nss_database_get (BZ #28940)
Patch1015: nss-missing-checks.patch
%endif
###
@@ -570,7 +567,7 @@ Group: System/Libraries
Network Support Library for legacy architectures. This library does not
have support for IPv6.
%if %{suse_version} >= 1500
%if 0%{suse_version} >= 1500
%define make_output_sync -Oline
%endif
@@ -628,11 +625,6 @@ for opt in $tmp; do
%endif
%if %{build_cross}
-m*) ;; # remove all machine specific options for crosses
%endif
%if "%{cross_arch}" == "hppa"
# -fstack-clash-protection is not supported on targets where the
# stack grows from lower to higher addresses
-fstack-clash-protection) ;;
%endif
*) BuildFlags+=" $opt" ;;
esac
@@ -722,7 +714,7 @@ profile="--disable-profile"
%if %{build_cross}
--with-headers=%{sysroot}/usr/include \
%else
%ifarch armv7hl ppc ppc64 ppc64le i686 x86_64 sparc sparc64 s390 s390x riscv64
%ifarch armv7hl ppc ppc64 ppc64le i686 x86_64 sparc sparc64 s390 s390x
--enable-multi-arch \
%endif
%ifarch aarch64
@@ -738,7 +730,7 @@ profile="--disable-profile"
--with-cpu=power7 \
%endif
%ifarch x86_64
%if %{suse_version} > 1500
%if %suse_version > 1500
--enable-cet \
%endif
%endif
@@ -1021,7 +1013,7 @@ rm -rf %{buildroot}%{_datadir}/locale/*/
# Miscelanna:
install -m 644 %{SOURCE7} %{buildroot}/etc
%if %{suse_version} > 1500
%if %suse_version > 1500
install -D -m 644 %{SOURCE5} %{buildroot}%{_prefix}/etc/nsswitch.conf
%else
install -m 644 %{SOURCE5} %{buildroot}/etc/nsswitch.conf
@@ -1064,6 +1056,9 @@ include /etc/ld.so.conf.d/*.conf
EOF
# Add ldconfig cache directory for directory ownership
mkdir -p %{buildroot}/var/cache/ldconfig
mkdir -p %{buildroot}%{_tmpfilesdir}
echo 'd /var/cache/ldconfig 0700 root root' > %{buildroot}%{_tmpfilesdir}/glibc.conf
# Empty the ld.so.cache:
rm -f %{buildroot}/etc/ld.so.cache
touch %{buildroot}/etc/ld.so.cache
@@ -1079,12 +1074,12 @@ rm -f %{buildroot}%{slibdir}/libnsl.so.1
%if %{with nscd}
%ifnarch i686
mkdir -p %{buildroot}/usr/lib/tmpfiles.d/
install -m 644 %{SOURCE20} %{buildroot}/usr/lib/tmpfiles.d/
mkdir -p %{buildroot}%{_tmpfilesdir}
install -m 644 %{SOURCE20} %{buildroot}%{_tmpfilesdir}/
mkdir -p %{buildroot}/usr/lib/systemd/system
install -m 644 %{SOURCE21} %{buildroot}/usr/lib/systemd/system
mkdir -p %{buildroot}/usr/lib/sysusers.d/
install -m 644 %{SOURCE22} %{buildroot}/usr/lib/sysusers.d/nscd.conf
mkdir -p %{buildroot}%{_sysusersdir}/
install -m 644 %{SOURCE22} %{buildroot}%{_sysusersdir}/nscd.conf
%endif
%endif
@@ -1123,6 +1118,8 @@ rm -f %{buildroot}%{_sbindir}/nscd
mkdir %{buildroot}%{_prefix}/share/misc
mv %{buildroot}/var/lib/misc/Makefile %{buildroot}%{_prefix}/share/misc/Makefile.makedb
ln -s %{_prefix}/share/misc/Makefile.makedb %{buildroot}/var/lib/misc/Makefile
mkdir -p %{buildroot}%{_tmpfilesdir}/
echo 'L /var/lib/misc/Makefile - - - - /usr/share/misc/Makefile.makedb' > %{buildroot}%{_tmpfilesdir}/glibc-extra.conf
%endif
%endif
@@ -1288,7 +1285,6 @@ end
%post -n nscd
%service_add_post nscd.service
%tmpfiles_create /usr/lib/tmpfiles.d/nscd.conf
# Previously we had nscd.socket, remove it
test -x /usr/bin/systemctl && /usr/bin/systemctl stop nscd.socket 2>/dev/null || :
test -x /usr/bin/systemctl && /usr/bin/systemctl disable nscd.socket 2>/dev/null || :
@@ -1308,7 +1304,7 @@ exit 0
%config /etc/ld.so.conf
%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/ld.so.cache
%config(noreplace) /etc/rpc
%if %{suse_version} > 1500
%if %suse_version > 1500
%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/nsswitch.conf
%{_prefix}/etc/nsswitch.conf
%else
@@ -1360,7 +1356,7 @@ exit 0
%ifarch %libutil_archs
%{slibdir}/libutil.so.1
%endif
%dir %attr(0700,root,root) /var/cache/ldconfig
%dir %attr(0700,root,root) %ghost /var/cache/ldconfig
%{rootsbindir}/ldconfig
%{_bindir}/gencat
%{_bindir}/getconf
@@ -1391,6 +1387,7 @@ exit 0
%{_libdir}/gconv/UTF8_UTF16_Z9.so
%endif
%attr(0644,root,root) %verify(not md5 size mtime) %ghost %{_libdir}/gconv/gconv-modules.cache
%{_tmpfilesdir}/glibc.conf
%files gconv-modules-extra
%dir %{_libdir}/gconv
@@ -1504,14 +1501,14 @@ exit 0
%{_sbindir}/nscd
%{_sbindir}/rcnscd
/usr/lib/systemd/system/nscd.service
%dir /usr/lib/tmpfiles.d
/usr/lib/tmpfiles.d/nscd.conf
%dir /usr/lib/sysusers.d
/usr/lib/sysusers.d/nscd.conf
%dir %{_tmpfilesdir}
%{_tmpfilesdir}/nscd.conf
%dir %{_sysusersdir}
%{_sysusersdir}/nscd.conf
%dir %attr(0755,root,root) %ghost /run/nscd
%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /run/nscd/nscd.pid
%attr(0666,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /run/nscd/socket
%dir %attr(0755,root,root) /var/lib/nscd
%dir %attr(0755,root,root) %ghost /var/lib/nscd
%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/lib/nscd/passwd
%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/lib/nscd/group
%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/lib/nscd/hosts
@@ -1546,7 +1543,8 @@ exit 0
%defattr(-,root,root)
%{_bindir}/makedb
%{_prefix}/share/misc/Makefile.makedb
/var/lib/misc/Makefile
%ghost /var/lib/misc/Makefile
%{_tmpfilesdir}/glibc-extra.conf
%files lang -f libc.lang
%endif

View File

@@ -0,0 +1,88 @@
From bfc4dd9e526eacf3017dd8864ba0848e9d045dd4 Mon Sep 17 00:00:00 2001
From: Siddhesh Poyarekar <siddhesh@gotplt.org>
Date: Thu, 15 Jan 2026 06:06:40 -0500
Subject: [PATCH] memalign: reinstate alignment overflow check (CVE-2026-0861)
The change to cap valid sizes to PTRDIFF_MAX inadvertently dropped the
overflow check for alignment in memalign functions, _mid_memalign and
_int_memalign. Reinstate the overflow check in _int_memalign, aligned
with the PTRDIFF_MAX change since that is directly responsible for the
CVE. The missing _mid_memalign check is not relevant (and does not have
a security impact) and may need a different approach to fully resolve,
so it has been omitted.
CVE-Id: CVE-2026-0861
Vulnerable-Commit: 9bf8e29ca136094f73f69f725f15c51facc97206
Reported-by: Igor Morgenstern, Aisle Research
Fixes: BZ #33796
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
(cherry picked from commit c9188d333717d3ceb7e3020011651f424f749f93)
---
malloc/malloc.c | 7 +++++--
malloc/tst-malloc-too-large.c | 10 ++--------
2 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/malloc/malloc.c b/malloc/malloc.c
index bcb6e5b83c..e39354595e 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -5049,7 +5049,7 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
INTERNAL_SIZE_T size;
nb = checked_request2size (bytes);
- if (nb == 0)
+ if (nb == 0 || alignment > PTRDIFF_MAX)
{
__set_errno (ENOMEM);
return NULL;
@@ -5065,7 +5065,10 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
we don't find anything in those bins, the common malloc code will
scan starting at 2x. */
- /* Call malloc with worst case padding to hit alignment. */
+ /* Call malloc with worst case padding to hit alignment. ALIGNMENT is a
+ power of 2, so it tops out at (PTRDIFF_MAX >> 1) + 1, leaving plenty of
+ space to add MINSIZE and whatever checked_request2size adds to BYTES to
+ get NB. Consequently, total below also does not overflow. */
m = (char *) (_int_malloc (av, nb + alignment + MINSIZE));
if (m == 0)
diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c
index 2b91377e54..15b25cf01d 100644
--- a/malloc/tst-malloc-too-large.c
+++ b/malloc/tst-malloc-too-large.c
@@ -152,7 +152,6 @@ test_large_allocations (size_t size)
}
-static long pagesize;
/* This function tests the following aligned memory allocation functions
using several valid alignments and precedes each allocation test with a
@@ -171,8 +170,8 @@ test_large_aligned_allocations (size_t size)
/* All aligned memory allocation functions expect an alignment that is a
power of 2. Given this, we test each of them with every valid
- alignment from 1 thru PAGESIZE. */
- for (align = 1; align <= pagesize; align *= 2)
+ alignment for the type of ALIGN, i.e. until it wraps to 0. */
+ for (align = 1; align > 0; align <<= 1)
{
test_setup ();
#if __GNUC_PREREQ (7, 0)
@@ -265,11 +264,6 @@ do_test (void)
DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
#endif
- /* Aligned memory allocation functions need to be tested up to alignment
- size equivalent to page size, which should be a power of 2. */
- pagesize = sysconf (_SC_PAGESIZE);
- TEST_VERIFY_EXIT (powerof2 (pagesize));
-
/* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e.
in the range (SIZE_MAX - 2^14, SIZE_MAX], fail.
--
2.52.0

View File

@@ -0,0 +1,50 @@
From d861635092a5ad3499baf18b2ff955b778734a0e Mon Sep 17 00:00:00 2001
From: Sunil K Pandey <sunil.k.pandey@intel.com>
Date: Tue, 9 Dec 2025 08:57:44 -0800
Subject: [PATCH] nptl: Optimize trylock for high cache contention workloads
(BZ #33704)
Check lock availability before acquisition to reduce cache line
bouncing. Significantly improves trylock throughput on multi-core
systems under heavy contention.
Tested on x86_64.
Fixes BZ #33704.
Co-authored-by: Alex M Wells <alex.m.wells@intel.com>
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
(cherry picked from commit 63716823dbad9482e09972907ae98e9cb00f9b86)
---
nptl/pthread_mutex_trylock.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
index 720c103f3f..6cf47403dd 100644
--- a/nptl/pthread_mutex_trylock.c
+++ b/nptl/pthread_mutex_trylock.c
@@ -48,7 +48,8 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex)
return 0;
}
- if (lll_trylock (mutex->__data.__lock) == 0)
+ if (atomic_load_relaxed (&(mutex->__data.__lock)) == 0
+ && lll_trylock (mutex->__data.__lock) == 0)
{
/* Record the ownership. */
mutex->__data.__owner = id;
@@ -71,7 +72,10 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex)
/*FALL THROUGH*/
case PTHREAD_MUTEX_ADAPTIVE_NP:
case PTHREAD_MUTEX_ERRORCHECK_NP:
- if (lll_trylock (mutex->__data.__lock) != 0)
+ /* Mutex type is already loaded, lock check overhead should
+ be minimal. */
+ if (atomic_load_relaxed (&(mutex->__data.__lock)) != 0
+ || lll_trylock (mutex->__data.__lock) != 0)
break;
/* Record the ownership. */
--
2.52.0

View File

@@ -1,40 +0,0 @@
From cb7f20653724029be89224ed3a35d627cc5b4163 Mon Sep 17 00:00:00 2001
From: John David Anglin <danglin@gcc.gnu.org>
Date: Wed, 29 Jan 2025 16:51:16 -0500
Subject: [PATCH] nptl: Correct stack size attribute when stack grows up [BZ
#32574]
Set stack size attribute to the size of the mmap'd region only
when the size of the remaining stack space is less than the size
of the mmap'd region.
This was reversed. As a result, the initial stack size was only
135168 bytes. On architectures where the stack grows down, the
initial stack size is approximately 8384512 bytes with the default
rlimit settings. The small main stack size on hppa broke
applications like ruby that check for stack overflows.
Signed-off-by: John David Anglin <dave.anglin@bell.net>
---
nptl/pthread_getattr_np.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/nptl/pthread_getattr_np.c b/nptl/pthread_getattr_np.c
index e98e2df152..43dd16d59c 100644
--- a/nptl/pthread_getattr_np.c
+++ b/nptl/pthread_getattr_np.c
@@ -145,9 +145,9 @@ __pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
> (size_t) iattr->stackaddr - last_to)
iattr->stacksize = (size_t) iattr->stackaddr - last_to;
#else
- /* The limit might be too high. */
+ /* The limit might be too low. */
if ((size_t) iattr->stacksize
- > to - (size_t) iattr->stackaddr)
+ < to - (size_t) iattr->stackaddr)
iattr->stacksize = to - (size_t) iattr->stackaddr;
#endif
/* We succeed and no need to look further. */
--
2.48.1

View File

@@ -0,0 +1,77 @@
From 329c775788b2c9ff3da774ccf59fba7b6b8ff08e Mon Sep 17 00:00:00 2001
From: Carlos O'Donell <carlos@redhat.com>
Date: Thu, 15 Jan 2026 15:09:38 -0500
Subject: [PATCH] resolv: Fix NSS DNS backend for getnetbyaddr (CVE-2026-0915)
The default network value of zero for net was never tested for and
results in a DNS query constructed from uninitialized stack bytes.
The solution is to provide a default query for the case where net
is zero.
Adding a test case for this was straight forward given the existence of
tst-resolv-network and if the test is added without the fix you observe
this failure:
FAIL: resolv/tst-resolv-network
original exit status 1
error: tst-resolv-network.c:174: invalid QNAME: \146\218\129\128
error: 1 test failures
With a random QNAME resulting from the use of uninitialized stack bytes.
After the fix the test passes.
Additionally verified using wireshark before and after to ensure
on-the-wire bytes for the DNS query were as expected.
No regressions on x86_64.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit e56ff82d5034ec66c6a78f517af6faa427f65b0b)
---
resolv/nss_dns/dns-network.c | 4 ++++
resolv/tst-resolv-network.c | 6 ++++++
2 files changed, 10 insertions(+)
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
index b32fd0fcab..71d67aa6f8 100644
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -207,6 +207,10 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
net_bytes[1], net_bytes[0]);
break;
+ default:
+ /* Default network (net is originally zero). */
+ strcpy (qbuf, "0.0.0.0.in-addr.arpa");
+ break;
}
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
diff --git a/resolv/tst-resolv-network.c b/resolv/tst-resolv-network.c
index f40e6f926c..8d4f8badf3 100644
--- a/resolv/tst-resolv-network.c
+++ b/resolv/tst-resolv-network.c
@@ -46,6 +46,9 @@ handle_code (const struct resolv_response_context *ctx,
{
switch (code)
{
+ case 0:
+ send_ptr (b, qname, qclass, qtype, "0.in-addr.arpa");
+ break;
case 1:
send_ptr (b, qname, qclass, qtype, "1.in-addr.arpa");
break;
@@ -265,6 +268,9 @@ do_test (void)
"error: TRY_AGAIN\n");
/* Lookup by address, success cases. */
+ check_reverse (0,
+ "name: 0.in-addr.arpa\n"
+ "net: 0x00000000\n");
check_reverse (1,
"name: 1.in-addr.arpa\n"
"net: 0x00000001\n");
--
2.52.0

44
nss-missing-checks.patch Normal file
View File

@@ -0,0 +1,44 @@
From 4b1bd2ab9318f680a355913987a0ba514cbcd0c9 Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
Date: Fri, 13 Feb 2026 09:02:07 +0100
Subject: [PATCH] nss: Missing checks in __nss_configure_lookup,
__nss_database_get (bug 28940)
This avoids a null pointer dereference in the
nss_database_check_reload_and_get function, and assertion failures.
Reviewed-by: Sam James <sam@gentoo.org>
---
nss/nss_database.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/nss/nss_database.c b/nss/nss_database.c
index efe77aeaff..cd7c9f00ec 100644
--- a/nss/nss_database.c
+++ b/nss/nss_database.c
@@ -251,9 +251,12 @@ __nss_configure_lookup (const char *dbname, const char *service_line)
/* Force any load/cache/read whatever to happen, so we can override
it. */
- __nss_database_get (db, &result);
+ if (!__nss_database_get (db, &result))
+ return -1;
local = nss_database_state_get ();
+ if (local == NULL)
+ return -1;
result = __nss_action_parse (service_line);
if (result == NULL)
@@ -478,6 +481,8 @@ bool
__nss_database_get (enum nss_database db, nss_action_list *actions)
{
struct nss_database_state *local = nss_database_state_get ();
+ if (local == NULL)
+ return false;
return nss_database_check_reload_and_get (local, actions, db);
}
libc_hidden_def (__nss_database_get)
--
2.53.0

View File

@@ -1,10 +1,10 @@
Index: glibc-2.41/sysdeps/powerpc/powerpc64/le/power10/memchr.S
Index: glibc-2.40/sysdeps/powerpc/powerpc64/le/power10/memchr.S
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/le/power10/memchr.S
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/le/power10/memchr.S
+++ /dev/null
@@ -1,315 +0,0 @@
-/* Optimized memchr implementation for POWER10 LE.
- Copyright (C) 2021-2025 Free Software Foundation, Inc.
- 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
@@ -318,10 +318,10 @@ Index: glibc-2.41/sysdeps/powerpc/powerpc64/le/power10/memchr.S
-
-weak_alias (__memchr, memchr)
-libc_hidden_builtin_def (memchr)
Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/Makefile
Index: glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/Makefile
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/multiarch/Makefile
+++ glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/Makefile
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/multiarch/Makefile
+++ glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/Makefile
@@ -31,7 +31,7 @@ sysdep_routines += memcpy-power8-cached
strncase-power8
@@ -330,11 +330,11 @@ Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/Makefile
+sysdep_routines += memcmp-power10 memcpy-power10 \
memmove-power10 memset-power10 rawmemchr-power9 \
rawmemchr-power10 strcmp-power9 \
strncmp-power9 strcpy-power9 strcat-power10 \
Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
strncmp-power9 strcpy-power9 stpcpy-power9 \
Index: glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
+++ glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
+++ glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
@@ -226,12 +226,6 @@ __libc_ifunc_impl_list (const char *name
/* Support sysdeps/powerpc/powerpc64/multiarch/memchr.c. */
@@ -348,13 +348,13 @@ Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
IFUNC_IMPL_ADD (array, i, memchr,
hwcap2 & PPC_FEATURE2_ARCH_2_07
&& hwcap & PPC_FEATURE_HAS_ALTIVEC,
Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/memchr-power10.S
Index: glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/memchr-power10.S
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/multiarch/memchr-power10.S
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/multiarch/memchr-power10.S
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Optimized memchr implementation for POWER10/PPC64.
- Copyright (C) 2016-2025 Free Software Foundation, Inc.
- Copyright (C) 2016-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
@@ -381,10 +381,10 @@ Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/memchr-power10.S
-
-#include <sysdeps/powerpc/powerpc64/le/power10/memchr.S>
-#endif
Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/memchr.c
Index: glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/memchr.c
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/multiarch/memchr.c
+++ glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/memchr.c
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/multiarch/memchr.c
+++ glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/memchr.c
@@ -25,23 +25,15 @@ extern __typeof (__memchr) __memchr_ppc
extern __typeof (__memchr) __memchr_power7 attribute_hidden;
extern __typeof (__memchr) __memchr_power8 attribute_hidden;

View File

@@ -1,10 +1,10 @@
Index: glibc-2.41/sysdeps/powerpc/powerpc64/le/power10/strcmp.S
Index: glibc-2.40/sysdeps/powerpc/powerpc64/le/power10/strcmp.S
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/le/power10/strcmp.S
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/le/power10/strcmp.S
+++ /dev/null
@@ -1,233 +0,0 @@
-/* Optimized strcmp implementation for PowerPC64/POWER10.
- Copyright (C) 2021-2025 Free Software Foundation, Inc.
- 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
@@ -236,13 +236,13 @@ Index: glibc-2.41/sysdeps/powerpc/powerpc64/le/power10/strcmp.S
-
-END (STRCMP)
-libc_hidden_builtin_def (strcmp)
Index: glibc-2.41/sysdeps/powerpc/powerpc64/le/power10/strncmp.S
Index: glibc-2.40/sysdeps/powerpc/powerpc64/le/power10/strncmp.S
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/le/power10/strncmp.S
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/le/power10/strncmp.S
+++ /dev/null
@@ -1,271 +0,0 @@
-/* Optimized strncmp implementation for PowerPC64/POWER10.
- Copyright (C) 2024-2025 Free Software Foundation, Inc.
- 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
@@ -512,25 +512,25 @@ Index: glibc-2.41/sysdeps/powerpc/powerpc64/le/power10/strncmp.S
-
-END(STRNCMP)
-libc_hidden_builtin_def(strncmp)
Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/Makefile
Index: glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/Makefile
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/multiarch/Makefile
+++ glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/Makefile
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/multiarch/Makefile
+++ glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/Makefile
@@ -33,8 +33,8 @@ sysdep_routines += memcpy-power8-cached
ifneq (,$(filter %le,$(config-machine)))
sysdep_routines += memchr-power10 memcmp-power10 memcpy-power10 \
memmove-power10 memset-power10 rawmemchr-power9 \
- rawmemchr-power10 strcmp-power9 strcmp-power10 \
- strncmp-power9 strncmp-power10 strcpy-power9 strcat-power10 \
- strncmp-power9 strncmp-power10 strcpy-power9 stpcpy-power9 \
+ rawmemchr-power10 strcmp-power9 \
+ strncmp-power9 strcpy-power9 strcat-power10 \
stpcpy-power9 strlen-power9 strncpy-power9 stpncpy-power9 \
strlen-power10
+ strncmp-power9 strcpy-power9 stpcpy-power9 \
strlen-power9 strncpy-power9 stpncpy-power9 strlen-power10
endif
Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops
Index: glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
+++ glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
+++ glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
@@ -164,9 +164,6 @@ __libc_ifunc_impl_list (const char *name
/* Support sysdeps/powerpc/powerpc64/multiarch/strncmp.c. */
IFUNC_IMPL (i, name, strncmp,
@@ -552,13 +552,13 @@ Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
hwcap2 & PPC_FEATURE2_ARCH_3_00
&& hwcap & PPC_FEATURE_HAS_ALTIVEC,
__strcmp_power9)
Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/strcmp-power10.S
Index: glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/strcmp-power10.S
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/multiarch/strcmp-power10.S
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/multiarch/strcmp-power10.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Optimized strcmp implementation for POWER10/PPC64.
- Copyright (C) 2021-2025 Free Software Foundation, Inc.
- 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
@@ -583,10 +583,10 @@ Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/strcmp-power10.S
-
-#include <sysdeps/powerpc/powerpc64/le/power10/strcmp.S>
-#endif /* __LITTLE_ENDIAN__ && IS_IN (libc) */
Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
Index: glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
+++ glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
+++ glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
@@ -29,16 +29,12 @@ extern __typeof (strcmp) __strcmp_power7
extern __typeof (strcmp) __strcmp_power8 attribute_hidden;
# ifdef __LITTLE_ENDIAN__
@@ -604,12 +604,12 @@ Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
(hwcap2 & PPC_FEATURE2_ARCH_3_00
&& hwcap & PPC_FEATURE_HAS_ALTIVEC)
? __strcmp_power9 :
Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/strncmp-power10.S
Index: glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/strncmp-power10.S
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/multiarch/strncmp-power10.S
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/multiarch/strncmp-power10.S
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (C) 2024-2025 Free Software Foundation, Inc.
-/* 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
@@ -634,10 +634,10 @@ Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/strncmp-power10.S
-
-#include <sysdeps/powerpc/powerpc64/le/power10/strncmp.S>
-#endif
Index: glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
Index: glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
===================================================================
--- glibc-2.41.orig/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
+++ glibc-2.41/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
--- glibc-2.40.orig/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
+++ glibc-2.40/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
@@ -29,7 +29,6 @@ extern __typeof (strncmp) __strncmp_ppc
extern __typeof (strncmp) __strncmp_power8 attribute_hidden;
# ifdef __LITTLE_ENDIAN__

650
pthread-wakeup.patch Normal file
View File

@@ -0,0 +1,650 @@
diff --git c/nptl/pthread_cond_broadcast.c w/nptl/pthread_cond_broadcast.c
index 7409958394..f5793e715f 100644
--- c/nptl/pthread_cond_broadcast.c
+++ w/nptl/pthread_cond_broadcast.c
@@ -57,10 +57,10 @@ ___pthread_cond_broadcast (pthread_cond_t *cond)
{
/* Add as many signals as the remaining size of the group. */
atomic_fetch_add_relaxed (cond->__data.__g_signals + g1,
- cond->__data.__g_size[g1] << 1);
+ cond->__data.__g_size[g1]);
cond->__data.__g_size[g1] = 0;
- /* We need to wake G1 waiters before we quiesce G1 below. */
+ /* We need to wake G1 waiters before we switch G1 below. */
/* TODO Only set it if there are indeed futex waiters. We could
also try to move this out of the critical section in cases when
G2 is empty (and we don't need to quiesce). */
@@ -69,11 +69,11 @@ ___pthread_cond_broadcast (pthread_cond_t *cond)
/* G1 is complete. Step (2) is next unless there are no waiters in G2, in
which case we can stop. */
- if (__condvar_quiesce_and_switch_g1 (cond, wseq, &g1, private))
+ if (__condvar_switch_g1 (cond, wseq, &g1, private))
{
/* Step (3): Send signals to all waiters in the old G2 / new G1. */
atomic_fetch_add_relaxed (cond->__data.__g_signals + g1,
- cond->__data.__g_size[g1] << 1);
+ cond->__data.__g_size[g1]);
cond->__data.__g_size[g1] = 0;
/* TODO Only set it if there are indeed futex waiters. */
do_futex_wake = true;
diff --git c/nptl/pthread_cond_common.c w/nptl/pthread_cond_common.c
index 7440bb18e6..99640968f1 100644
--- c/nptl/pthread_cond_common.c
+++ w/nptl/pthread_cond_common.c
@@ -189,19 +189,17 @@ __condvar_get_private (int flags)
return FUTEX_SHARED;
}
-/* This closes G1 (whose index is in G1INDEX), waits for all futex waiters to
- leave G1, converts G1 into a fresh G2, and then switches group roles so that
- the former G2 becomes the new G1 ending at the current __wseq value when we
- eventually make the switch (WSEQ is just an observation of __wseq by the
- signaler).
+/* This closes G1 (whose index is in G1INDEX), converts G1 into a fresh G2,
+ and then switches group roles so that the former G2 becomes the new G1
+ ending at the current __wseq value when we eventually make the switch
+ (WSEQ is just an observation of __wseq by the signaler).
If G2 is empty, it will not switch groups because then it would create an
empty G1 which would require switching groups again on the next signal.
Returns false iff groups were not switched because G2 was empty. */
static bool __attribute__ ((unused))
-__condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
+__condvar_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
unsigned int *g1index, int private)
{
- const unsigned int maxspin = 0;
unsigned int g1 = *g1index;
/* If there is no waiter in G2, we don't do anything. The expression may
@@ -210,96 +208,23 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
behavior.
Note that this works correctly for a zero-initialized condvar too. */
unsigned int old_orig_size = __condvar_get_orig_size (cond);
- uint64_t old_g1_start = __condvar_load_g1_start_relaxed (cond) >> 1;
- if (((unsigned) (wseq - old_g1_start - old_orig_size)
- + cond->__data.__g_size[g1 ^ 1]) == 0)
+ uint64_t old_g1_start = __condvar_load_g1_start_relaxed (cond);
+ uint64_t new_g1_start = old_g1_start + old_orig_size;
+ if (((unsigned) (wseq - new_g1_start) + cond->__data.__g_size[g1 ^ 1]) == 0)
return false;
- /* Now try to close and quiesce G1. We have to consider the following kinds
- of waiters:
+ /* We have to consider the following kinds of waiters:
* Waiters from less recent groups than G1 are not affected because
nothing will change for them apart from __g1_start getting larger.
* New waiters arriving concurrently with the group switching will all go
into G2 until we atomically make the switch. Waiters existing in G2
are not affected.
- * Waiters in G1 will be closed out immediately by setting a flag in
- __g_signals, which will prevent waiters from blocking using a futex on
- __g_signals and also notifies them that the group is closed. As a
- result, they will eventually remove their group reference, allowing us
- to close switch group roles. */
+ * Waiters in G1 have already received a signal and been woken. */
- /* First, set the closed flag on __g_signals. This tells waiters that are
- about to wait that they shouldn't do that anymore. This basically
- serves as an advance notification of the upcoming change to __g1_start;
- waiters interpret it as if __g1_start was larger than their waiter
- sequence position. This allows us to change __g1_start after waiting
- for all existing waiters with group references to leave, which in turn
- makes recovery after stealing a signal simpler because it then can be
- skipped if __g1_start indicates that the group is closed (otherwise,
- we would have to recover always because waiters don't know how big their
- groups are). Relaxed MO is fine. */
- atomic_fetch_or_relaxed (cond->__data.__g_signals + g1, 1);
-
- /* Wait until there are no group references anymore. The fetch-or operation
- injects us into the modification order of __g_refs; release MO ensures
- that waiters incrementing __g_refs after our fetch-or see the previous
- changes to __g_signals and to __g1_start that had to happen before we can
- switch this G1 and alias with an older group (we have two groups, so
- aliasing requires switching group roles twice). Note that nobody else
- can have set the wake-request flag, so we do not have to act upon it.
-
- Also note that it is harmless if older waiters or waiters from this G1
- get a group reference after we have quiesced the group because it will
- remain closed for them either because of the closed flag in __g_signals
- or the later update to __g1_start. New waiters will never arrive here
- but instead continue to go into the still current G2. */
- unsigned r = atomic_fetch_or_release (cond->__data.__g_refs + g1, 0);
- while ((r >> 1) > 0)
- {
- for (unsigned int spin = maxspin; ((r >> 1) > 0) && (spin > 0); spin--)
- {
- /* TODO Back off. */
- r = atomic_load_relaxed (cond->__data.__g_refs + g1);
- }
- if ((r >> 1) > 0)
- {
- /* There is still a waiter after spinning. Set the wake-request
- flag and block. Relaxed MO is fine because this is just about
- this futex word.
-
- Update r to include the set wake-request flag so that the upcoming
- futex_wait only blocks if the flag is still set (otherwise, we'd
- violate the basic client-side futex protocol). */
- r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1) | 1;
-
- if ((r >> 1) > 0)
- futex_wait_simple (cond->__data.__g_refs + g1, r, private);
- /* Reload here so we eventually see the most recent value even if we
- do not spin. */
- r = atomic_load_relaxed (cond->__data.__g_refs + g1);
- }
- }
- /* Acquire MO so that we synchronize with the release operation that waiters
- use to decrement __g_refs and thus happen after the waiters we waited
- for. */
- atomic_thread_fence_acquire ();
-
- /* Update __g1_start, which finishes closing this group. The value we add
- will never be negative because old_orig_size can only be zero when we
- switch groups the first time after a condvar was initialized, in which
- case G1 will be at index 1 and we will add a value of 1. See above for
- why this takes place after waiting for quiescence of the group.
- Relaxed MO is fine because the change comes with no additional
- constraints that others would have to observe. */
- __condvar_add_g1_start_relaxed (cond,
- (old_orig_size << 1) + (g1 == 1 ? 1 : - 1));
-
- /* Now reopen the group, thus enabling waiters to again block using the
- futex controlled by __g_signals. Release MO so that observers that see
- no signals (and thus can block) also see the write __g1_start and thus
- that this is now a new group (see __pthread_cond_wait_common for the
- matching acquire MO loads). */
- atomic_store_release (cond->__data.__g_signals + g1, 0);
+ /* Update __g1_start, which closes this group. Relaxed MO is fine because
+ the change comes with no additional constraints that others would have
+ to observe. */
+ __condvar_add_g1_start_relaxed (cond, old_orig_size);
/* At this point, the old G1 is now a valid new G2 (but not in use yet).
No old waiter can neither grab a signal nor acquire a reference without
@@ -311,9 +236,13 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq,
g1 ^= 1;
*g1index ^= 1;
+ /* Now advance the new G1 g_signals to the new g1_start, giving it
+ an effective signal count of 0 to start. */
+ atomic_store_release (cond->__data.__g_signals + g1, (unsigned)new_g1_start);
+
/* These values are just observed by signalers, and thus protected by the
lock. */
- unsigned int orig_size = wseq - (old_g1_start + old_orig_size);
+ unsigned int orig_size = wseq - new_g1_start;
__condvar_set_orig_size (cond, orig_size);
/* Use and addition to not loose track of cancellations in what was
previously G2. */
diff --git c/nptl/pthread_cond_signal.c w/nptl/pthread_cond_signal.c
index 9ac4bd9f75..bdc1e82466 100644
--- c/nptl/pthread_cond_signal.c
+++ w/nptl/pthread_cond_signal.c
@@ -69,19 +69,18 @@ ___pthread_cond_signal (pthread_cond_t *cond)
bool do_futex_wake = false;
/* If G1 is still receiving signals, we put the signal there. If not, we
- check if G2 has waiters, and if so, quiesce and switch G1 to the former
- G2; if this results in a new G1 with waiters (G2 might have cancellations
- already, see __condvar_quiesce_and_switch_g1), we put the signal in the
- new G1. */
+ check if G2 has waiters, and if so, switch G1 to the former G2; if this
+ results in a new G1 with waiters (G2 might have cancellations already,
+ see __condvar_switch_g1), we put the signal in the new G1. */
if ((cond->__data.__g_size[g1] != 0)
- || __condvar_quiesce_and_switch_g1 (cond, wseq, &g1, private))
+ || __condvar_switch_g1 (cond, wseq, &g1, private))
{
/* Add a signal. Relaxed MO is fine because signaling does not need to
- establish a happens-before relation (see above). We do not mask the
- release-MO store when initializing a group in
- __condvar_quiesce_and_switch_g1 because we use an atomic
- read-modify-write and thus extend that store's release sequence. */
- atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 2);
+ establish a happens-before relation (see above). We do not mask the
+ release-MO store when initializing a group in __condvar_switch_g1
+ because we use an atomic read-modify-write and thus extend that
+ store's release sequence. */
+ atomic_fetch_add_relaxed (cond->__data.__g_signals + g1, 1);
cond->__data.__g_size[g1]--;
/* TODO Only set it if there are indeed futex waiters. */
do_futex_wake = true;
diff --git c/nptl/pthread_cond_wait.c w/nptl/pthread_cond_wait.c
index 806c432d13..d919b3622a 100644
--- c/nptl/pthread_cond_wait.c
+++ w/nptl/pthread_cond_wait.c
@@ -84,7 +84,7 @@ __condvar_cancel_waiting (pthread_cond_t *cond, uint64_t seq, unsigned int g,
not hold a reference on the group. */
__condvar_acquire_lock (cond, private);
- uint64_t g1_start = __condvar_load_g1_start_relaxed (cond) >> 1;
+ uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
if (g1_start > seq)
{
/* Our group is closed, so someone provided enough signals for it.
@@ -143,23 +143,6 @@ __condvar_cancel_waiting (pthread_cond_t *cond, uint64_t seq, unsigned int g,
}
}
-/* Wake up any signalers that might be waiting. */
-static void
-__condvar_dec_grefs (pthread_cond_t *cond, unsigned int g, int private)
-{
- /* Release MO to synchronize-with the acquire load in
- __condvar_quiesce_and_switch_g1. */
- if (atomic_fetch_add_release (cond->__data.__g_refs + g, -2) == 3)
- {
- /* Clear the wake-up request flag before waking up. We do not need more
- than relaxed MO and it doesn't matter if we apply this for an aliased
- group because we wake all futex waiters right after clearing the
- flag. */
- atomic_fetch_and_relaxed (cond->__data.__g_refs + g, ~(unsigned int) 1);
- futex_wake (cond->__data.__g_refs + g, INT_MAX, private);
- }
-}
-
/* Clean-up for cancellation of waiters waiting for normal signals. We cancel
our registration as a waiter, confirm we have woken up, and re-acquire the
mutex. */
@@ -171,8 +154,6 @@ __condvar_cleanup_waiting (void *arg)
pthread_cond_t *cond = cbuffer->cond;
unsigned g = cbuffer->wseq & 1;
- __condvar_dec_grefs (cond, g, cbuffer->private);
-
__condvar_cancel_waiting (cond, cbuffer->wseq >> 1, g, cbuffer->private);
/* FIXME With the current cancellation implementation, it is possible that
a thread is cancelled after it has returned from a syscall. This could
@@ -238,9 +219,7 @@ __condvar_cleanup_waiting (void *arg)
signaled), and a reference count.
The group reference count is used to maintain the number of waiters that
- are using the group's futex. Before a group can change its role, the
- reference count must show that no waiters are using the futex anymore; this
- prevents ABA issues on the futex word.
+ are using the group's futex.
To represent which intervals in the waiter sequence the groups cover (and
thus also which group slot contains G1 or G2), we use a 64b counter to
@@ -251,7 +230,7 @@ __condvar_cleanup_waiting (void *arg)
figure out whether they are in a group that has already been completely
signaled (i.e., if the current G1 starts at a later position that the
waiter's position). Waiters cannot determine whether they are currently
- in G2 or G1 -- but they do not have too because all they are interested in
+ in G2 or G1 -- but they do not have to because all they are interested in
is whether there are available signals, and they always start in G2 (whose
group slot they know because of the bit in the waiter sequence. Signalers
will simply fill the right group until it is completely signaled and can
@@ -280,7 +259,6 @@ __condvar_cleanup_waiting (void *arg)
* Waiters fetch-add while having acquire the mutex associated with the
condvar. Signalers load it and fetch-xor it concurrently.
__g1_start: Starting position of G1 (inclusive)
- * LSB is index of current G2.
* Modified by signalers while having acquired the condvar-internal lock
and observed concurrently by waiters.
__g1_orig_size: Initial size of G1
@@ -300,11 +278,10 @@ __condvar_cleanup_waiting (void *arg)
last reference.
* Reference count used by waiters concurrently with signalers that have
acquired the condvar-internal lock.
- __g_signals: The number of signals that can still be consumed.
+ __g_signals: The number of signals that can still be consumed, relative to
+ the current g1_start. (i.e. g1_start with the signal count added)
* Used as a futex word by waiters. Used concurrently by waiters and
signalers.
- * LSB is true iff this group has been completely signaled (i.e., it is
- closed).
__g_size: Waiters remaining in this group (i.e., which have not been
signaled yet.
* Accessed by signalers and waiters that cancel waiting (both do so only
@@ -328,27 +305,6 @@ __condvar_cleanup_waiting (void *arg)
sufficient because if a waiter can see a sufficiently large value, it could
have also consume a signal in the waiters group.
- Waiters try to grab a signal from __g_signals without holding a reference
- count, which can lead to stealing a signal from a more recent group after
- their own group was already closed. They cannot always detect whether they
- in fact did because they do not know when they stole, but they can
- conservatively add a signal back to the group they stole from; if they
- did so unnecessarily, all that happens is a spurious wake-up. To make this
- even less likely, __g1_start contains the index of the current g2 too,
- which allows waiters to check if there aliasing on the group slots; if
- there wasn't, they didn't steal from the current G1, which means that the
- G1 they stole from must have been already closed and they do not need to
- fix anything.
-
- It is essential that the last field in pthread_cond_t is __g_signals[1]:
- The previous condvar used a pointer-sized field in pthread_cond_t, so a
- PTHREAD_COND_INITIALIZER from that condvar implementation might only
- initialize 4 bytes to zero instead of the 8 bytes we need (i.e., 44 bytes
- in total instead of the 48 we need). __g_signals[1] is not accessed before
- the first group switch (G2 starts at index 0), which will set its value to
- zero after a harmless fetch-or whose return value is ignored. This
- effectively completes initialization.
-
Limitations:
* This condvar isn't designed to allow for more than
@@ -379,7 +335,6 @@ static __always_inline int
__pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
clockid_t clockid, const struct __timespec64 *abstime)
{
- const int maxspin = 0;
int err;
int result = 0;
@@ -396,8 +351,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
because we do not need to establish any happens-before relation with
signalers (see __pthread_cond_signal); modification order alone
establishes a total order of waiters/signals. We do need acquire MO
- to synchronize with group reinitialization in
- __condvar_quiesce_and_switch_g1. */
+ to synchronize with group reinitialization in __condvar_switch_g1. */
uint64_t wseq = __condvar_fetch_add_wseq_acquire (cond, 2);
/* Find our group's index. We always go into what was G2 when we acquired
our position. */
@@ -424,178 +378,64 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
return err;
}
- /* Now wait until a signal is available in our group or it is closed.
- Acquire MO so that if we observe a value of zero written after group
- switching in __condvar_quiesce_and_switch_g1, we synchronize with that
- store and will see the prior update of __g1_start done while switching
- groups too. */
- unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
- do
+ while (1)
{
- while (1)
- {
- /* Spin-wait first.
- Note that spinning first without checking whether a timeout
- passed might lead to what looks like a spurious wake-up even
- though we should return ETIMEDOUT (e.g., if the caller provides
- an absolute timeout that is clearly in the past). However,
- (1) spurious wake-ups are allowed, (2) it seems unlikely that a
- user will (ab)use pthread_cond_wait as a check for whether a
- point in time is in the past, and (3) spinning first without
- having to compare against the current time seems to be the right
- choice from a performance perspective for most use cases. */
- unsigned int spin = maxspin;
- while (signals == 0 && spin > 0)
- {
- /* Check that we are not spinning on a group that's already
- closed. */
- if (seq < (__condvar_load_g1_start_relaxed (cond) >> 1))
- goto done;
-
- /* TODO Back off. */
-
- /* Reload signals. See above for MO. */
- signals = atomic_load_acquire (cond->__data.__g_signals + g);
- spin--;
- }
-
- /* If our group will be closed as indicated by the flag on signals,
- don't bother grabbing a signal. */
- if (signals & 1)
- goto done;
-
- /* If there is an available signal, don't block. */
- if (signals != 0)
- break;
-
- /* No signals available after spinning, so prepare to block.
- We first acquire a group reference and use acquire MO for that so
- that we synchronize with the dummy read-modify-write in
- __condvar_quiesce_and_switch_g1 if we read from that. In turn,
- in this case this will make us see the closed flag on __g_signals
- that designates a concurrent attempt to reuse the group's slot.
- We use acquire MO for the __g_signals check to make the
- __g1_start check work (see spinning above).
- Note that the group reference acquisition will not mask the
- release MO when decrementing the reference count because we use
- an atomic read-modify-write operation and thus extend the release
- sequence. */
- atomic_fetch_add_acquire (cond->__data.__g_refs + g, 2);
- if (((atomic_load_acquire (cond->__data.__g_signals + g) & 1) != 0)
- || (seq < (__condvar_load_g1_start_relaxed (cond) >> 1)))
- {
- /* Our group is closed. Wake up any signalers that might be
- waiting. */
- __condvar_dec_grefs (cond, g, private);
- goto done;
- }
-
- // Now block.
- struct _pthread_cleanup_buffer buffer;
- struct _condvar_cleanup_buffer cbuffer;
- cbuffer.wseq = wseq;
- cbuffer.cond = cond;
- cbuffer.mutex = mutex;
- cbuffer.private = private;
- __pthread_cleanup_push (&buffer, __condvar_cleanup_waiting, &cbuffer);
-
- err = __futex_abstimed_wait_cancelable64 (
- cond->__data.__g_signals + g, 0, clockid, abstime, private);
-
- __pthread_cleanup_pop (&buffer, 0);
-
- if (__glibc_unlikely (err == ETIMEDOUT || err == EOVERFLOW))
- {
- __condvar_dec_grefs (cond, g, private);
- /* If we timed out, we effectively cancel waiting. Note that
- we have decremented __g_refs before cancellation, so that a
- deadlock between waiting for quiescence of our group in
- __condvar_quiesce_and_switch_g1 and us trying to acquire
- the lock during cancellation is not possible. */
- __condvar_cancel_waiting (cond, seq, g, private);
- result = err;
- goto done;
- }
- else
- __condvar_dec_grefs (cond, g, private);
-
- /* Reload signals. See above for MO. */
- signals = atomic_load_acquire (cond->__data.__g_signals + g);
+ /* Now wait until a signal is available in our group or it is closed.
+ Acquire MO so that if we observe (signals == lowseq) after group
+ switching in __condvar_switch_g1, we synchronize with that store and
+ will see the prior update of __g1_start done while switching groups
+ too. */
+ unsigned int signals = atomic_load_acquire (cond->__data.__g_signals + g);
+ uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
+
+ if (seq < g1_start)
+ {
+ /* If the group is closed already,
+ then this waiter originally had enough extra signals to
+ consume, up until the time its group was closed. */
+ break;
+ }
+
+ /* If there is an available signal, don't block.
+ If __g1_start has advanced at all, then we must be in G1
+ by now, perhaps in the process of switching back to an older
+ G2, but in either case we're allowed to consume the available
+ signal and should not block anymore. */
+ if ((int)(signals - (unsigned int)g1_start) > 0)
+ {
+ /* Try to grab a signal. See above for MO. (if we do another loop
+ iteration we need to see the correct value of g1_start) */
+ if (atomic_compare_exchange_weak_acquire (
+ cond->__data.__g_signals + g,
+ &signals, signals - 1))
+ break;
+ else
+ continue;
}
+ // Now block.
+ struct _pthread_cleanup_buffer buffer;
+ struct _condvar_cleanup_buffer cbuffer;
+ cbuffer.wseq = wseq;
+ cbuffer.cond = cond;
+ cbuffer.mutex = mutex;
+ cbuffer.private = private;
+ __pthread_cleanup_push (&buffer, __condvar_cleanup_waiting, &cbuffer);
+
+ err = __futex_abstimed_wait_cancelable64 (
+ cond->__data.__g_signals + g, signals, clockid, abstime, private);
+
+ __pthread_cleanup_pop (&buffer, 0);
+
+ if (__glibc_unlikely (err == ETIMEDOUT || err == EOVERFLOW))
+ {
+ /* If we timed out, we effectively cancel waiting. */
+ __condvar_cancel_waiting (cond, seq, g, private);
+ result = err;
+ break;
+ }
}
- /* Try to grab a signal. Use acquire MO so that we see an up-to-date value
- of __g1_start below (see spinning above for a similar case). In
- particular, if we steal from a more recent group, we will also see a
- more recent __g1_start below. */
- while (!atomic_compare_exchange_weak_acquire (cond->__data.__g_signals + g,
- &signals, signals - 2));
-
- /* We consumed a signal but we could have consumed from a more recent group
- that aliased with ours due to being in the same group slot. If this
- might be the case our group must be closed as visible through
- __g1_start. */
- uint64_t g1_start = __condvar_load_g1_start_relaxed (cond);
- if (seq < (g1_start >> 1))
- {
- /* We potentially stole a signal from a more recent group but we do not
- know which group we really consumed from.
- We do not care about groups older than current G1 because they are
- closed; we could have stolen from these, but then we just add a
- spurious wake-up for the current groups.
- We will never steal a signal from current G2 that was really intended
- for G2 because G2 never receives signals (until it becomes G1). We
- could have stolen a signal from G2 that was conservatively added by a
- previous waiter that also thought it stole a signal -- but given that
- that signal was added unnecessarily, it's not a problem if we steal
- it.
- Thus, the remaining case is that we could have stolen from the current
- G1, where "current" means the __g1_start value we observed. However,
- if the current G1 does not have the same slot index as we do, we did
- not steal from it and do not need to undo that. This is the reason
- for putting a bit with G2's index into__g1_start as well. */
- if (((g1_start & 1) ^ 1) == g)
- {
- /* We have to conservatively undo our potential mistake of stealing
- a signal. We can stop trying to do that when the current G1
- changes because other spinning waiters will notice this too and
- __condvar_quiesce_and_switch_g1 has checked that there are no
- futex waiters anymore before switching G1.
- Relaxed MO is fine for the __g1_start load because we need to
- merely be able to observe this fact and not have to observe
- something else as well.
- ??? Would it help to spin for a little while to see whether the
- current G1 gets closed? This might be worthwhile if the group is
- small or close to being closed. */
- unsigned int s = atomic_load_relaxed (cond->__data.__g_signals + g);
- while (__condvar_load_g1_start_relaxed (cond) == g1_start)
- {
- /* Try to add a signal. We don't need to acquire the lock
- because at worst we can cause a spurious wake-up. If the
- group is in the process of being closed (LSB is true), this
- has an effect similar to us adding a signal. */
- if (((s & 1) != 0)
- || atomic_compare_exchange_weak_relaxed
- (cond->__data.__g_signals + g, &s, s + 2))
- {
- /* If we added a signal, we also need to add a wake-up on
- the futex. We also need to do that if we skipped adding
- a signal because the group is being closed because
- while __condvar_quiesce_and_switch_g1 could have closed
- the group, it might still be waiting for futex waiters to
- leave (and one of those waiters might be the one we stole
- the signal from, which cause it to block using the
- futex). */
- futex_wake (cond->__data.__g_signals + g, 1, private);
- break;
- }
- /* TODO Back off. */
- }
- }
- }
-
- done:
/* Confirm that we have been woken. We do that before acquiring the mutex
to allow for execution of pthread_cond_destroy while having acquired the
diff --git c/nptl/tst-cond22.c w/nptl/tst-cond22.c
index 1336e9c79d..bdcb45c536 100644
--- c/nptl/tst-cond22.c
+++ w/nptl/tst-cond22.c
@@ -106,13 +106,13 @@ do_test (void)
status = 1;
}
- printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u/%u, %u/%u/%u, %u, %u }\n",
+ printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u, %u/%u, %u, %u }\n",
c.__data.__wseq.__value32.__high,
c.__data.__wseq.__value32.__low,
c.__data.__g1_start.__value32.__high,
c.__data.__g1_start.__value32.__low,
- c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
- c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
+ c.__data.__g_signals[0], c.__data.__g_size[0],
+ c.__data.__g_signals[1], c.__data.__g_size[1],
c.__data.__g1_orig_size, c.__data.__wrefs);
if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
@@ -152,13 +152,13 @@ do_test (void)
status = 1;
}
- printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u/%u, %u/%u/%u, %u, %u }\n",
+ printf ("cond = { 0x%x:%x, 0x%x:%x, %u/%u, %u/%u, %u, %u }\n",
c.__data.__wseq.__value32.__high,
c.__data.__wseq.__value32.__low,
c.__data.__g1_start.__value32.__high,
c.__data.__g1_start.__value32.__low,
- c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
- c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
+ c.__data.__g_signals[0], c.__data.__g_size[0],
+ c.__data.__g_signals[1], c.__data.__g_size[1],
c.__data.__g1_orig_size, c.__data.__wrefs);
return status;
diff --git c/sysdeps/nptl/bits/thread-shared-types.h w/sysdeps/nptl/bits/thread-shared-types.h
index 2de6ff9caf..3fe5d4afc0 100644
--- c/sysdeps/nptl/bits/thread-shared-types.h
+++ w/sysdeps/nptl/bits/thread-shared-types.h
@@ -95,11 +95,12 @@ struct __pthread_cond_s
{
__atomic_wide_counter __wseq;
__atomic_wide_counter __g1_start;
- unsigned int __g_refs[2] __LOCK_ALIGNMENT;
- unsigned int __g_size[2];
+ unsigned int __g_size[2] __LOCK_ALIGNMENT;
unsigned int __g1_orig_size;
unsigned int __wrefs;
unsigned int __g_signals[2];
+ unsigned int __unused_initialized_1;
+ unsigned int __unused_initialized_2;
};
typedef unsigned int __tss_t;
diff --git c/sysdeps/nptl/pthread.h w/sysdeps/nptl/pthread.h
index 7f65483542..476cd0ed54 100644
--- c/sysdeps/nptl/pthread.h
+++ w/sysdeps/nptl/pthread.h
@@ -152,7 +152,7 @@ enum
/* Conditional variable handling. */
-#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } }
+#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, 0, 0, {0, 0}, 0, 0 } }
/* Cleanup buffers */

240
regcomp-double-free.patch Normal file
View File

@@ -0,0 +1,240 @@
From 2eb180377b96771b8368b0915669c8c7b267e739 Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
Date: Mon, 21 Jul 2025 21:43:49 +0200
Subject: [PATCH] posix: Fix double-free after allocation failure in regcomp
(bug 33185)
If a memory allocation failure occurs during bracket expression
parsing in regcomp, a double-free error may result.
Reported-by: Anastasia Belova <abelova@astralinux.ru>
Co-authored-by: Paul Eggert <eggert@cs.ucla.edu>
Reviewed-by: Andreas K. Huettel <dilfridge@gentoo.org>
(cherry picked from commit 7ea06e994093fa0bcca0d0ee2c1db271d8d7885d)
---
NEWS | 1 +
posix/Makefile | 1 +
posix/regcomp.c | 4 +-
posix/tst-regcomp-bracket-free.c | 176 +++++++++++++++++++++++++++++++
4 files changed, 181 insertions(+), 1 deletion(-)
create mode 100644 posix/tst-regcomp-bracket-free.c
diff --git a/posix/Makefile b/posix/Makefile
index 2c598cd20a..830278a423 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -303,6 +303,7 @@ tests := \
tst-posix_spawn-setsid \
tst-preadwrite \
tst-preadwrite64 \
+ tst-regcomp-bracket-free \
tst-regcomp-truncated \
tst-regex \
tst-regex2 \
diff --git a/posix/regcomp.c b/posix/regcomp.c
index 5380d3c7b9..6595bb3c0d 100644
--- a/posix/regcomp.c
+++ b/posix/regcomp.c
@@ -3384,6 +3384,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
{
#ifdef RE_ENABLE_I18N
free_charset (mbcset);
+ mbcset = NULL;
#endif
/* Build a tree for simple bracket. */
br_token.type = SIMPLE_BRACKET;
@@ -3399,7 +3400,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
parse_bracket_exp_free_return:
re_free (sbcset);
#ifdef RE_ENABLE_I18N
- free_charset (mbcset);
+ if (__glibc_likely (mbcset != NULL))
+ free_charset (mbcset);
#endif /* RE_ENABLE_I18N */
return NULL;
}
diff --git a/posix/tst-regcomp-bracket-free.c b/posix/tst-regcomp-bracket-free.c
new file mode 100644
index 0000000000..3c091d8c44
--- /dev/null
+++ b/posix/tst-regcomp-bracket-free.c
@@ -0,0 +1,176 @@
+/* Test regcomp bracket parsing with injected allocation failures (bug 33185).
+ Copyright (C) 2025 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 invokes regcomp multiple times, failing one memory
+ allocation in each call. The function call should fail with
+ REG_ESPACE (or succeed if it can recover from the allocation
+ failure). Previously, there was double-free bug. */
+
+#include <errno.h>
+#include <regex.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/support.h>
+
+/* Data structure allocated via MAP_SHARED, so that writes from the
+ subprocess are visible. */
+struct shared_data
+{
+ /* Number of tracked allocations performed so far. */
+ volatile unsigned int allocation_count;
+
+ /* If this number is reached, one allocation fails. */
+ volatile unsigned int failing_allocation;
+
+ /* The subprocess stores the expected name here. */
+ char name[100];
+};
+
+/* Allocation count in shared mapping. */
+static struct shared_data *shared;
+
+/* Returns true if a failure should be injected for this allocation. */
+static bool
+fail_this_allocation (void)
+{
+ if (shared != NULL)
+ {
+ unsigned int count = shared->allocation_count;
+ shared->allocation_count = count + 1;
+ return count == shared->failing_allocation;
+ }
+ else
+ return false;
+}
+
+/* Failure-injecting wrappers for allocation functions used by glibc. */
+
+void *
+malloc (size_t size)
+{
+ if (fail_this_allocation ())
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ extern __typeof (malloc) __libc_malloc;
+ return __libc_malloc (size);
+}
+
+void *
+calloc (size_t a, size_t b)
+{
+ if (fail_this_allocation ())
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ extern __typeof (calloc) __libc_calloc;
+ return __libc_calloc (a, b);
+}
+
+void *
+realloc (void *ptr, size_t size)
+{
+ if (fail_this_allocation ())
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ extern __typeof (realloc) __libc_realloc;
+ return __libc_realloc (ptr, size);
+}
+
+/* No-op subprocess to verify that support_isolate_in_subprocess does
+ not perform any heap allocations. */
+static void
+no_op (void *ignored)
+{
+}
+
+/* Perform a regcomp call in a subprocess. Used to count its
+ allocations. */
+static void
+initialize (void *regexp1)
+{
+ const char *regexp = regexp1;
+
+ shared->allocation_count = 0;
+
+ regex_t reg;
+ TEST_COMPARE (regcomp (&reg, regexp, 0), 0);
+}
+
+/* Perform regcomp in a subprocess with fault injection. */
+static void
+test_in_subprocess (void *regexp1)
+{
+ const char *regexp = regexp1;
+ unsigned int inject_at = shared->failing_allocation;
+
+ regex_t reg;
+ int ret = regcomp (&reg, regexp, 0);
+
+ if (ret != 0)
+ {
+ TEST_COMPARE (ret, REG_ESPACE);
+ printf ("info: allocation %u failure results in return value %d,"
+ " error %s (%d)\n",
+ inject_at, ret, strerrorname_np (errno), errno);
+ }
+}
+
+static int
+do_test (void)
+{
+ char regexp[] = "[:alpha:]";
+
+ shared = support_shared_allocate (sizeof (*shared));
+
+ /* Disable fault injection. */
+ shared->failing_allocation = ~0U;
+
+ support_isolate_in_subprocess (no_op, NULL);
+ TEST_COMPARE (shared->allocation_count, 0);
+
+ support_isolate_in_subprocess (initialize, regexp);
+
+ /* The number of allocations in the successful case, plus some
+ slack. Once the number of expected allocations is exceeded,
+ injecting further failures does not make a difference. */
+ unsigned int maximum_allocation_count = shared->allocation_count;
+ printf ("info: successful call performs %u allocations\n",
+ maximum_allocation_count);
+ maximum_allocation_count += 10;
+
+ for (unsigned int inject_at = 0; inject_at <= maximum_allocation_count;
+ ++inject_at)
+ {
+ shared->allocation_count = 0;
+ shared->failing_allocation = inject_at;
+ support_isolate_in_subprocess (test_in_subprocess, regexp);
+ }
+
+ support_shared_free (shared);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
--
2.50.1

View File

@@ -1,80 +0,0 @@
From bdccbfbc52d3f6957768a0b9d5bd7bc4c90f2744 Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Fri, 31 Jan 2025 10:27:39 -0300
Subject: [PATCH] math: Fix log10p1f internal table value (BZ 32626)
It was copied wrong from CORE-MATH.
(cherry picked from commit c79277a16785c8ae96d821414f4d31d654a0177c)
---
NEWS | 3 ++-
math/auto-libm-test-in | 2 ++
math/auto-libm-test-out-log10p1 | 25 +++++++++++++++++++++++++
sysdeps/ieee754/flt-32/s_log10p1f.c | 2 +-
4 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in
index 01ba689aa8..c0627dc7eb 100644
--- a/math/auto-libm-test-in
+++ b/math/auto-libm-test-in
@@ -7291,6 +7291,8 @@ log10p1 -0x1p-125
log10p1 -0x1p-1021
log10p1 -0x1p-16381
+log10p1 0x1.27f7dap-17
+
log10p1 0x7.2a4368p-4
log10p1 0x6.d3a118p-4
log10p1 0x5.03f228p+0
diff --git a/math/auto-libm-test-out-log10p1 b/math/auto-libm-test-out-log10p1
index 87bdb0bcde..f5ce965720 100644
--- a/math/auto-libm-test-out-log10p1
+++ b/math/auto-libm-test-out-log10p1
@@ -1789,6 +1789,31 @@ log10p1 -0x1p-16381
= log10p1 tonearest binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4dp-16384 : inexact-ok underflow errno-erange-ok
= log10p1 towardzero binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4ccp-16384 : inexact-ok underflow errno-erange-ok
= log10p1 upward binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4ccp-16384 : inexact-ok underflow errno-erange-ok
+log10p1 0x1.27f7dap-17
+= log10p1 downward binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok
+= log10p1 tonearest binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok
+= log10p1 towardzero binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok
+= log10p1 upward binary32 0x9.3fbedp-20 : 0x4.044b58p-20 : inexact-ok
+= log10p1 downward binary64 0x9.3fbedp-20 : 0x4.044b5157872ep-20 : inexact-ok
+= log10p1 tonearest binary64 0x9.3fbedp-20 : 0x4.044b5157872e4p-20 : inexact-ok
+= log10p1 towardzero binary64 0x9.3fbedp-20 : 0x4.044b5157872ep-20 : inexact-ok
+= log10p1 upward binary64 0x9.3fbedp-20 : 0x4.044b5157872e4p-20 : inexact-ok
+= log10p1 downward intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
+= log10p1 tonearest intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
+= log10p1 towardzero intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
+= log10p1 upward intel96 0x9.3fbedp-20 : 0x4.044b5157872e287p-20 : inexact-ok
+= log10p1 downward m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
+= log10p1 tonearest m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
+= log10p1 towardzero m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
+= log10p1 upward m68k96 0x9.3fbedp-20 : 0x4.044b5157872e287p-20 : inexact-ok
+= log10p1 downward binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d808p-20 : inexact-ok
+= log10p1 tonearest binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d80cp-20 : inexact-ok
+= log10p1 towardzero binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d808p-20 : inexact-ok
+= log10p1 upward binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d80cp-20 : inexact-ok
+= log10p1 downward ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok
+= log10p1 tonearest ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok
+= log10p1 towardzero ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok
+= log10p1 upward ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287dap-20 : inexact-ok
log10p1 0x7.2a4368p-4
= log10p1 downward binary32 0x7.2a4368p-4 : 0x2.9248dcp-4 : inexact-ok
= log10p1 tonearest binary32 0x7.2a4368p-4 : 0x2.9248ep-4 : inexact-ok
diff --git a/sysdeps/ieee754/flt-32/s_log10p1f.c b/sysdeps/ieee754/flt-32/s_log10p1f.c
index 64deb1eeda..4e11d55d49 100644
--- a/sysdeps/ieee754/flt-32/s_log10p1f.c
+++ b/sysdeps/ieee754/flt-32/s_log10p1f.c
@@ -70,7 +70,7 @@ __log10p1f (float x)
};
static const double tl[] =
{
- 0x1.562ec497ef351p-43, 0x1.b9476892ea99cp-8, 0x1.b5e909c959eecp-7,
+ -0x1.562ec497ef351p-43, 0x1.b9476892ea99cp-8, 0x1.b5e909c959eecp-7,
0x1.45f4f59ec84fp-6, 0x1.af5f92cbcf2aap-6, 0x1.0ba01a6069052p-5,
0x1.3ed119b99dd41p-5, 0x1.714834298a088p-5, 0x1.a30a9d98309c1p-5,
0x1.d41d51266b9d9p-5, 0x1.02428c0f62dfcp-4, 0x1.1a23444eea521p-4,
--
2.48.1

View File

@@ -1,76 +0,0 @@
From d85a7719536f4892f2b53d4594e18f6d096c2882 Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Fri, 31 Jan 2025 10:34:32 -0300
Subject: [PATCH] math: Fix sinhf for some inputs (BZ 32627)
The logic was copied wrong from CORE-MATH.
---
math/auto-libm-test-in | 1 +
math/auto-libm-test-out-sinh | 25 +++++++++++++++++++++++++
sysdeps/ieee754/flt-32/e_sinhf.c | 2 +-
3 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in
index c0627dc7eb..5f465b31f1 100644
--- a/math/auto-libm-test-in
+++ b/math/auto-libm-test-in
@@ -8300,6 +8300,7 @@ sinh -0x1.3dda8ap+0
sinh -0x5.ee9218p-4
sinh -0x1.bcfc98p+0
sinh -0x6.9bbb6df7c5d08p-4
+sinh 0x1.250bfep-11
# the next value generates larger error bounds on x86_64 (ldbl-96)
sinh 0x2.c5d376167f4052f4p+12
sinh max
diff --git a/math/auto-libm-test-out-sinh b/math/auto-libm-test-out-sinh
index 0b77a77eeb..3924e19d86 100644
--- a/math/auto-libm-test-out-sinh
+++ b/math/auto-libm-test-out-sinh
@@ -2115,6 +2115,31 @@ sinh -0x6.9bbb6df7c5d08p-4
= sinh tonearest ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok
= sinh towardzero ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok
= sinh upward ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok
+sinh 0x1.250bfep-11
+= sinh downward binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok
+= sinh tonearest binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok
+= sinh towardzero binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok
+= sinh upward binary32 0x2.4a17fcp-12 : 0x2.4a18p-12 : inexact-ok
+= sinh downward binary64 0x2.4a17fcp-12 : 0x2.4a17fdffffffep-12 : inexact-ok
+= sinh tonearest binary64 0x2.4a17fcp-12 : 0x2.4a17fep-12 : inexact-ok
+= sinh towardzero binary64 0x2.4a17fcp-12 : 0x2.4a17fdffffffep-12 : inexact-ok
+= sinh upward binary64 0x2.4a17fcp-12 : 0x2.4a17fep-12 : inexact-ok
+= sinh downward intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
+= sinh tonearest intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
+= sinh towardzero intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
+= sinh upward intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
+= sinh downward m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
+= sinh tonearest m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
+= sinh towardzero m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
+= sinh upward m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
+= sinh downward binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec88p-12 : inexact-ok
+= sinh tonearest binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec8ap-12 : inexact-ok
+= sinh towardzero binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec88p-12 : inexact-ok
+= sinh upward binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec8ap-12 : inexact-ok
+= sinh downward ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ecp-12 : inexact-ok
+= sinh tonearest ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786edp-12 : inexact-ok
+= sinh towardzero ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ecp-12 : inexact-ok
+= sinh upward ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786edp-12 : inexact-ok
sinh 0x2.c5d376167f4052f4p+12
= sinh downward binary32 0x2.c5d378p+12 : 0xf.fffffp+124 : inexact-ok overflow errno-erange-ok
= sinh tonearest binary32 0x2.c5d378p+12 : plus_infty : inexact-ok overflow errno-erange
diff --git a/sysdeps/ieee754/flt-32/e_sinhf.c b/sysdeps/ieee754/flt-32/e_sinhf.c
index c007c7d174..dee96fc7cb 100644
--- a/sysdeps/ieee754/flt-32/e_sinhf.c
+++ b/sysdeps/ieee754/flt-32/e_sinhf.c
@@ -83,7 +83,7 @@ __ieee754_sinhf (float x)
{ /* |x| <= 0x1.250bfep-11 */
if (__glibc_unlikely (ux < 0x66000000u)) /* |x| < 0x1p-24 */
return fmaf (x, fabsf (x), x);
- if (__glibc_unlikely (st.uarg == asuint (ux)))
+ if (__glibc_unlikely (st.uarg == ux))
{
float sgn = copysignf (1.0f, x);
return sgn * st.rh + sgn * st.rl;
--
2.48.1

View File

@@ -1,79 +0,0 @@
From cf88351b685da86667e17d344414a70696ac82f1 Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Sun, 2 Feb 2025 16:57:49 -0300
Subject: [PATCH] math: Fix tanf for some inputs (BZ 32630)
The logic was copied wrong from CORE-MATH.
(cherry picked from commit 09e7f4d594b4308fbea18e3044148d67b59757c9)
---
NEWS | 2 ++
math/auto-libm-test-in | 1 +
math/auto-libm-test-out-tan | 25 +++++++++++++++++++++++++
sysdeps/ieee754/flt-32/s_tanf.c | 2 +-
4 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in
index 5f465b31f1..4f194da19d 100644
--- a/math/auto-libm-test-in
+++ b/math/auto-libm-test-in
@@ -8664,6 +8664,7 @@ tan 0x1.1ad374p+0
tan -0x1.0d55b8p+0
tan 1.57079697
tan -1.57079697
+tan 0x1.ada6aap+27
tan 0x1p-5
tan 0x1p-10
tan 0x1p-15
diff --git a/math/auto-libm-test-out-tan b/math/auto-libm-test-out-tan
index 7d00d03e1d..1d5999ab90 100644
--- a/math/auto-libm-test-out-tan
+++ b/math/auto-libm-test-out-tan
@@ -2532,6 +2532,31 @@ tan -1.57079697
= tan tonearest ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5c8p+20 : inexact-ok
= tan towardzero ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5cp+20 : inexact-ok
= tan upward ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5c8p+20 : inexact-ok
+tan 0x1.ada6aap+27
+= tan downward binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
+= tan tonearest binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
+= tan towardzero binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
+= tan upward binary32 0xd.6d355p+24 : 0x3.d0060cp-4 : inexact-ok
+= tan downward binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
+= tan tonearest binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
+= tan towardzero binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
+= tan upward binary64 0xd.6d355p+24 : 0x3.d006080000002p-4 : inexact-ok
+= tan downward intel96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
+= tan tonearest intel96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
+= tan towardzero intel96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
+= tan upward intel96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
+= tan downward m68k96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
+= tan tonearest m68k96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
+= tan towardzero m68k96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
+= tan upward m68k96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
+= tan downward binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok
+= tan tonearest binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok
+= tan towardzero binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok
+= tan upward binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15cp-4 : inexact-ok
+= tan downward ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok
+= tan tonearest ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok
+= tan towardzero ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok
+= tan upward ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c2p-4 : inexact-ok
tan 0x1p-5
= tan downward binary32 0x8p-8 : 0x8.00aabp-8 : inexact-ok
= tan tonearest binary32 0x8p-8 : 0x8.00aacp-8 : inexact-ok
diff --git a/sysdeps/ieee754/flt-32/s_tanf.c b/sysdeps/ieee754/flt-32/s_tanf.c
index dfe56fc2a0..5ee1d6f35e 100644
--- a/sysdeps/ieee754/flt-32/s_tanf.c
+++ b/sysdeps/ieee754/flt-32/s_tanf.c
@@ -166,7 +166,7 @@ __tanf (float x)
uint32_t sgn = t >> 31;
for (int j = 0; j < array_length (st); j++)
{
- if (__glibc_unlikely (asfloat (st[j].arg) == ax))
+ if (__glibc_unlikely (asuint (st[j].arg) == ax))
{
if (sgn)
return -st[j].rh - st[j].rl;
--
2.48.1

658
s390-z17.patch Normal file
View File

@@ -0,0 +1,658 @@
From d56e24327cd59c97eccf3b666344f3297d9593a4 Mon Sep 17 00:00:00 2001
From: Stefan Liebler <stli@linux.ibm.com>
Date: Tue, 29 Apr 2025 13:28:58 +0200
Subject: [PATCH] S390: Add new s390 platform z17.
The glibc-hwcaps subdirectories are extended by "z17". Libraries are loaded if
the z17 facility bits are active:
- Miscellaneous-instruction-extensions facility 4
- Vector-enhancements-facility 3
- Vector-Packed-Decimal-Enhancement Facility 3
- CPU: Concurrent-Functions Facility
tst-glibc-hwcaps.c is extended in order to test z17 via new marker6.
In case of running on a z17 with a kernel not recognizing z17 yet,
AT_PLATFORM will be z900 but vector-bit in AT_HWCAP is set. This situation
is now recognized and this testcase does not fail.
A fatal glibc error is dumped if glibc was build with architecture
level set for z17, but run on an older machine (See dl-hwcap-check.h).
Note, you might get an SIGILL before this check if you don't use:
configure --with-rtld-early-cflags=-march=<older-machine>
ld.so --list-diagnostics now also dumps information about s390.cpu_features.
Independent from z17, the s390x kernel won't introduce new HWCAP-Bits if there
is no special handling needed in kernel itself. For z17, we don't have new
HWCAP flags, but have to check the facility bits retrieved by
stfle-instruction.
Instead of storing all the stfle-bits (currently four 64bit values) in the
cpu_features struct, we now only store those bits, which are needed within
glibc itself. Note that we have this list twice, one with original values and
the other one which can be filtered with GLIBC_TUNABLES=glibc.cpu.hwcaps.
Those new fields are stored in so far reserved space in cpu_features struct.
Thus processes started in between the update of glibc package and we e.g. have
a new ld.so and an old libc.so, won't crash. The glibc internal ifunc-resolvers
would not select the best optimized variant.
The users of stfle-bits are also updated:
- parsing of GLIBC_TUNABLES=glibc.cpu.hwcaps
- glibc internal ifunc-resolvers
- __libc_ifunc_impl_list
- sysconf
---
elf/Makefile | 9 +++
elf/tst-glibc-hwcaps-cache.script | 7 ++
sysdeps/s390/cpu-features.c | 77 +++++++++++++++----
sysdeps/s390/cpu-features.h | 55 +++++++++----
.../ifunc-resolve.h => dl-diagnostics-cpu.c} | 34 ++++----
sysdeps/s390/multiarch/ifunc-impl-list.c | 4 +-
sysdeps/s390/multiarch/ifunc-resolve.h | 2 +-
sysdeps/s390/s390-64/Makefile | 27 ++++++-
sysdeps/s390/s390-64/dl-hwcap-check.h | 21 ++++-
sysdeps/s390/s390-64/dl-hwcaps-subdirs.c | 12 ++-
sysdeps/s390/s390-64/tst-glibc-hwcaps.c | 52 +++++++++----
sysdeps/unix/sysv/linux/s390/sysconf.c | 2 +-
12 files changed, 230 insertions(+), 72 deletions(-)
copy sysdeps/s390/{multiarch/ifunc-resolve.h => dl-diagnostics-cpu.c} (51%)
diff --git a/elf/Makefile b/elf/Makefile
index 0303e08557..172fe149ca 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -732,6 +732,12 @@ modules-names += \
libmarkermod5-3 \
libmarkermod5-4 \
libmarkermod5-5 \
+ libmarkermod6-1 \
+ libmarkermod6-2 \
+ libmarkermod6-3 \
+ libmarkermod6-4 \
+ libmarkermod6-5 \
+ libmarkermod6-6 \
libtracemod1-1 \
libtracemod2-1 \
libtracemod3-1 \
@@ -2710,6 +2716,7 @@ LDFLAGS-libmarkermod2-1.so += -Wl,-soname,libmarkermod2.so
LDFLAGS-libmarkermod3-1.so += -Wl,-soname,libmarkermod3.so
LDFLAGS-libmarkermod4-1.so += -Wl,-soname,libmarkermod4.so
LDFLAGS-libmarkermod5-1.so += -Wl,-soname,libmarkermod5.so
+LDFLAGS-libmarkermod6-1.so += -Wl,-soname,libmarkermod6.so
$(objpfx)libmarkermod%.os : markermodMARKER-VALUE.c
$(compile-command.c) \
-DMARKER=marker$(firstword $(subst -, ,$*)) \
@@ -2724,6 +2731,8 @@ $(objpfx)libmarkermod4.so: $(objpfx)libmarkermod4-1.so
cp $< $@
$(objpfx)libmarkermod5.so: $(objpfx)libmarkermod5-1.so
cp $< $@
+$(objpfx)libmarkermod6.so: $(objpfx)libmarkermod6-1.so
+ cp $< $@
# tst-glibc-hwcaps-prepend checks that --glibc-hwcaps-prepend is
# preferred over auto-detected subdirectories.
diff --git a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script
index d58fc8c5de..af89e9c6f8 100644
--- a/elf/tst-glibc-hwcaps-cache.script
+++ b/elf/tst-glibc-hwcaps-cache.script
@@ -5,6 +5,7 @@ cp $B/elf/libmarkermod2-1.so $L/libmarkermod2.so
cp $B/elf/libmarkermod3-1.so $L/libmarkermod3.so
cp $B/elf/libmarkermod4-1.so $L/libmarkermod4.so
cp $B/elf/libmarkermod5-1.so $L/libmarkermod5.so
+cp $B/elf/libmarkermod6-1.so $L/libmarkermod6.so
mkdirp 0770 $L/glibc-hwcaps/power9
cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/power9/libmarkermod2.so
@@ -26,6 +27,12 @@ cp $B/elf/libmarkermod5-2.so $L/glibc-hwcaps/z13/libmarkermod5.so
cp $B/elf/libmarkermod5-3.so $L/glibc-hwcaps/z14/libmarkermod5.so
cp $B/elf/libmarkermod5-4.so $L/glibc-hwcaps/z15/libmarkermod5.so
cp $B/elf/libmarkermod5-5.so $L/glibc-hwcaps/z16/libmarkermod5.so
+mkdirp 0770 $L/glibc-hwcaps/z17
+cp $B/elf/libmarkermod6-2.so $L/glibc-hwcaps/z13/libmarkermod6.so
+cp $B/elf/libmarkermod6-3.so $L/glibc-hwcaps/z14/libmarkermod6.so
+cp $B/elf/libmarkermod6-4.so $L/glibc-hwcaps/z15/libmarkermod6.so
+cp $B/elf/libmarkermod6-5.so $L/glibc-hwcaps/z16/libmarkermod6.so
+cp $B/elf/libmarkermod6-6.so $L/glibc-hwcaps/z17/libmarkermod6.so
mkdirp 0770 $L/glibc-hwcaps/x86-64-v2
cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod2.so
diff --git a/sysdeps/s390/cpu-features.c b/sysdeps/s390/cpu-features.c
index bc4ad601f1..f44270bd76 100644
--- a/sysdeps/s390/cpu-features.c
+++ b/sysdeps/s390/cpu-features.c
@@ -26,7 +26,7 @@
#define S390_COPY_CPU_FEATURES(SRC_PTR, DEST_PTR) \
(DEST_PTR)->hwcap = (SRC_PTR)->hwcap; \
- (DEST_PTR)->stfle_bits[0] = (SRC_PTR)->stfle_bits[0];
+ (DEST_PTR)->stfle_filtered = (SRC_PTR)->stfle_filtered;
static void
TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
@@ -76,7 +76,7 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
disable = true;
hwcap_mask = HWCAP_S390_VXRS | HWCAP_S390_VXRS_EXT
| HWCAP_S390_VXRS_EXT2;
- stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
+ stfle_bits0_mask = S390_STFLE_BIT61_ARCH13_MIE3;
}
else if (tunable_str_comma_strcmp_cte (&t, "z13")
|| tunable_str_comma_strcmp_cte (&t, "arch11"))
@@ -84,7 +84,7 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
reset_features = true;
disable = true;
hwcap_mask = HWCAP_S390_VXRS_EXT | HWCAP_S390_VXRS_EXT2;
- stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
+ stfle_bits0_mask = S390_STFLE_BIT61_ARCH13_MIE3;
}
else if (tunable_str_comma_strcmp_cte (&t, "z14")
|| tunable_str_comma_strcmp_cte (&t, "arch12"))
@@ -92,12 +92,14 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
reset_features = true;
disable = true;
hwcap_mask = HWCAP_S390_VXRS_EXT2;
- stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
+ stfle_bits0_mask = S390_STFLE_BIT61_ARCH13_MIE3;
}
else if (tunable_str_comma_strcmp_cte (&t, "z15")
|| tunable_str_comma_strcmp_cte (&t, "z16")
+ || tunable_str_comma_strcmp_cte (&t, "z17")
|| tunable_str_comma_strcmp_cte (&t, "arch13")
- || tunable_str_comma_strcmp_cte (&t, "arch14"))
+ || tunable_str_comma_strcmp_cte (&t, "arch14")
+ || tunable_str_comma_strcmp_cte (&t, "arch15"))
{
/* For z15 or newer we don't have to disable something, but we have
to reset to the original values. */
@@ -124,7 +126,7 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
hwcap_mask |= HWCAP_S390_VXRS | HWCAP_S390_VXRS_EXT;
}
else if (tunable_str_comma_strcmp_cte (&t, "STFLE_MIE3"))
- stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
+ stfle_bits0_mask = S390_STFLE_BIT61_ARCH13_MIE3;
/* Perform the actions determined above. */
if (reset_features)
@@ -143,22 +145,26 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
if (stfle_bits0_mask != 0ULL)
{
if (disable)
- cpu_features_curr.stfle_bits[0] &= ~stfle_bits0_mask;
+ cpu_features_curr.stfle_filtered &= ~stfle_bits0_mask;
else
- cpu_features_curr.stfle_bits[0] |= stfle_bits0_mask;
+ cpu_features_curr.stfle_filtered |= stfle_bits0_mask;
}
}
/* Copy back the features after checking that no unsupported features were
enabled by user. */
cpu_features->hwcap = cpu_features_curr.hwcap & cpu_features_orig.hwcap;
- cpu_features->stfle_bits[0] = cpu_features_curr.stfle_bits[0]
- & cpu_features_orig.stfle_bits[0];
+ cpu_features->stfle_filtered = cpu_features_curr.stfle_filtered
+ & cpu_features_orig.stfle_filtered;
}
static inline void
-init_cpu_features (struct cpu_features *cpu_features)
+init_cpu_features_no_tunables (struct cpu_features *cpu_features)
{
+ /* Only initialize once. */
+ if (cpu_features->hwcap != 0)
+ return;
+
/* Fill cpu_features as passed by kernel and machine. */
cpu_features->hwcap = GLRO(dl_hwcap);
@@ -167,20 +173,57 @@ init_cpu_features (struct cpu_features *cpu_features)
&& (cpu_features->hwcap & HWCAP_S390_ZARCH)
&& (cpu_features->hwcap & HWCAP_S390_HIGH_GPRS)))
{
- register unsigned long reg0 __asm__("0") = 0;
+ unsigned long long stfle_bits[4] = { 0 };
+ register unsigned long reg0 __asm__("0") = 3;
__asm__ __volatile__(".machine push" "\n\t"
".machine \"z9-109\"" "\n\t"
".machinemode \"zarch_nohighgprs\"\n\t"
"stfle %0" "\n\t"
".machine pop" "\n"
- : "=QS" (cpu_features->stfle_bits[0]),
+ : "=QS" (stfle_bits[0]),
"+d" (reg0)
: : "cc");
+
+ unsigned long long internal_stfle_bits = 0;
+
+ /* Facility bit 34: z10: General instructions extension. */
+ if ((stfle_bits[0] & (1ULL << (63 - 34))) != 0)
+ internal_stfle_bits |= S390_STFLE_BIT34_Z10;
+
+ /* Facility bit 45: z196: Distinct operands, popcount, ... */
+ if ((stfle_bits[0] & (1ULL << (63 - 45))) != 0)
+ internal_stfle_bits |= S390_STFLE_BIT45_Z196;
+
+ /* Facility bit 61: arch13/z15: Miscellaneous-Instruction-Extensions
+ Facility 3, e.g. mvcrl. */
+ if ((stfle_bits[0] & (1ULL << (63 - 61))) != 0)
+ internal_stfle_bits |= S390_STFLE_BIT61_ARCH13_MIE3;
+
+ /* Facility bit 84: arch15/z17: Miscellaneous-instruction-extensions 4 */
+ if ((stfle_bits[1] & (1ULL << (127 - 84))) != 0)
+ internal_stfle_bits |= S390_STFLE_BIT84_ARCH15_MIE4;
+
+ /* Facility bit 198: arch15/z17: Vector-enhancements-facility 3 */
+ if ((stfle_bits[3] & (1ULL << (255 - 198))) != 0)
+ internal_stfle_bits |= S390_STFLE_BIT198_ARCH15_VXRS_EXT3;
+
+ /* Facility bit 199: arch15/z17: Vector-Packed-Decimal-Enhancement 3 */
+ if ((stfle_bits[3] & (1ULL << (255 - 199))) != 0)
+ internal_stfle_bits |= S390_STFLE_BIT199_ARCH15_VXRS_PDE3;
+
+ /* Facility bit 201: arch15/z17: CPU: Concurrent-Functions Facility */
+ if ((stfle_bits[3] & (1ULL << (255 - 201))) != 0)
+ internal_stfle_bits |= S390_STFLE_BIT201_ARCH15_CON;
+
+ cpu_features->stfle_orig = internal_stfle_bits;
+ cpu_features->stfle_filtered = internal_stfle_bits;
}
- else
- {
- cpu_features->stfle_bits[0] = 0ULL;
- }
+}
+
+static inline void
+init_cpu_features (struct cpu_features *cpu_features)
+{
+ init_cpu_features_no_tunables (cpu_features);
TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
}
diff --git a/sysdeps/s390/cpu-features.h b/sysdeps/s390/cpu-features.h
index 6efea28e35..fa92fbeb44 100644
--- a/sysdeps/s390/cpu-features.h
+++ b/sysdeps/s390/cpu-features.h
@@ -18,29 +18,58 @@
#ifndef __CPU_FEATURES_S390X_H
# define __CPU_FEATURES_S390X_H
-#define S390_STFLE_BITS_Z10 34 /* General instructions extension */
-#define S390_STFLE_BITS_Z196 45 /* Distinct operands, pop ... */
-#define S390_STFLE_BITS_ARCH13_MIE3 61 /* Miscellaneous-Instruction-Extensions
- Facility 3, e.g. mvcrl. */
+/* The following stfle bit definitions are intended to be used for the
+ glibc internal stfle_orig and stfle_filtered fields in cpu_features
+ struct. They can't be used on the double words retrieved by the
+ stfle-instruction. */
-#define S390_STFLE_MASK_ARCH13_MIE3 (1ULL << (63 - S390_STFLE_BITS_ARCH13_MIE3))
+/* Facility bit 34: z10: General instructions extension. */
+#define S390_STFLE_BIT34_Z10 (1ULL << 0)
+/* Facility bit 45: z196: Distinct operands, popcount, ... */
+#define S390_STFLE_BIT45_Z196 (1ULL << 1)
-#define S390_IS_ARCH13_MIE3(STFLE_BITS_ARRAY) \
- (((STFLE_BITS_ARRAY)[0] & S390_STFLE_MASK_ARCH13_MIE3) != 0)
+/* Facility bit 61: arch13/z15: Miscellaneous-Instruction-Extensions
+ Facility 3, e.g. mvcrl. */
+#define S390_STFLE_BIT61_ARCH13_MIE3 (1ULL << 2)
-#define S390_IS_Z196(STFLE_BITS_ARRAY) \
- (((STFLE_BITS_ARRAY)[0] & (1ULL << (63 - S390_STFLE_BITS_Z196))) != 0)
+/* Facility bit 84: arch15/z17: Miscellaneous-instruction-extensions
+ facility 4 */
+#define S390_STFLE_BIT84_ARCH15_MIE4 (1ULL << 3)
-#define S390_IS_Z10(STFLE_BITS_ARRAY) \
- (((STFLE_BITS_ARRAY)[0] & (1ULL << (63 - S390_STFLE_BITS_Z10))) != 0)
+/* Facility bit 198: arch15/z17: Vector-enhancements-facility 3 */
+#define S390_STFLE_BIT198_ARCH15_VXRS_EXT3 (1ULL << 4)
+
+/* Facility bit 199: arch15/z17: Vector-Packed-Decimal-Enhancement
+ Facility 3 */
+#define S390_STFLE_BIT199_ARCH15_VXRS_PDE3 (1ULL << 5)
+
+/* Facility bit 201: arch15/z17: CPU: Concurrent-Functions Facility */
+#define S390_STFLE_BIT201_ARCH15_CON (1ULL << 6)
+
+#define S390_IS_ARCH15(STFLE_BITS) \
+ ((((STFLE_BITS) & S390_STFLE_BIT84_ARCH15_MIE4) != 0) \
+ && (((STFLE_BITS) & S390_STFLE_BIT198_ARCH15_VXRS_EXT3) != 0) \
+ && (((STFLE_BITS) & S390_STFLE_BIT199_ARCH15_VXRS_PDE3) != 0) \
+ && (((STFLE_BITS) & S390_STFLE_BIT201_ARCH15_CON) != 0))
+
+#define S390_IS_ARCH13_MIE3(STFLE_BITS) \
+ (((STFLE_BITS) & S390_STFLE_BIT61_ARCH13_MIE3) != 0)
+
+#define S390_IS_Z196(STFLE_BITS) \
+ (((STFLE_BITS) & S390_STFLE_BIT45_Z196) != 0)
+
+#define S390_IS_Z10(STFLE_BITS) \
+ (((STFLE_BITS) & S390_STFLE_BIT34_Z10) != 0)
struct cpu_features
{
unsigned long int hwcap;
unsigned long int __reserved_hwcap2;
- unsigned long long stfle_bits[3];
- unsigned long long __reserved[11];
+ unsigned long long __reserved;
+ unsigned long long stfle_orig;
+ unsigned long long stfle_filtered;
+ unsigned long long __reserved2[11];
};
#endif /* __CPU_FEATURES_S390X_H */
diff --git a/sysdeps/s390/multiarch/ifunc-resolve.h b/sysdeps/s390/dl-diagnostics-cpu.c
similarity index 51%
copy from sysdeps/s390/multiarch/ifunc-resolve.h
copy to sysdeps/s390/dl-diagnostics-cpu.c
index 2a0c4a56a4..426af2df7a 100644
--- a/sysdeps/s390/multiarch/ifunc-resolve.h
+++ b/sysdeps/s390/dl-diagnostics-cpu.c
@@ -1,6 +1,5 @@
-/* IFUNC resolver function for CPU specific functions.
- 32/64 bit S/390 version.
- Copyright (C) 2015-2024 Free Software Foundation, Inc.
+/* Print CPU diagnostics data in ld.so. s390 version.
+ Copyright (C) 2025 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
@@ -17,19 +16,22 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <unistd.h>
-#include <dl-procinfo.h>
+#include <dl-diagnostics.h>
+#include <ldsodefs.h>
#include <cpu-features.h>
-#define s390_libc_ifunc_expr_stfle_init() \
- const unsigned long long *stfle_bits = features->stfle_bits;
+static void
+print_cpu_features_value (const char *label, uint64_t value)
+{
+ _dl_printf ("s390.cpu_features.");
+ _dl_diagnostics_print_labeled_value (label, value);
+}
-#define s390_libc_ifunc_expr_init() \
- const struct cpu_features *features = &GLRO(dl_s390_cpu_features); \
- /* The hwcap from kernel is passed as argument, but we \
- explicitly use the hwcaps from cpu-features struct. */ \
- hwcap = features->hwcap;
-
-#define s390_libc_ifunc_expr(TYPE_FUNC, FUNC, EXPR) \
- __ifunc (TYPE_FUNC, FUNC, EXPR, unsigned long int hwcap, \
- s390_libc_ifunc_expr_init);
+void
+_dl_diagnostics_cpu (void)
+{
+ const struct cpu_features *cpu_features = &GLRO(dl_s390_cpu_features);
+ print_cpu_features_value ("hwcap", cpu_features->hwcap);
+ print_cpu_features_value ("stfle_orig", cpu_features->stfle_orig);
+ print_cpu_features_value ("stfle_filtered", cpu_features->stfle_filtered);
+}
diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
index b05b86f6bd..48252785cd 100644
--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
+++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
@@ -81,8 +81,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
/* Get hardware information. */
const struct cpu_features *features = &GLRO(dl_s390_cpu_features);
unsigned long int dl_hwcap __attribute__ ((unused)) = features->hwcap;
- const unsigned long long * __attribute__((unused)) stfle_bits
- = features->stfle_bits;
+ const unsigned long long __attribute__((unused)) stfle_bits
+ = features->stfle_filtered;
#if HAVE_MEMSET_IFUNC
IFUNC_IMPL (i, name, memset,
diff --git a/sysdeps/s390/multiarch/ifunc-resolve.h b/sysdeps/s390/multiarch/ifunc-resolve.h
index 2a0c4a56a4..d63b624d0f 100644
--- a/sysdeps/s390/multiarch/ifunc-resolve.h
+++ b/sysdeps/s390/multiarch/ifunc-resolve.h
@@ -22,7 +22,7 @@
#include <cpu-features.h>
#define s390_libc_ifunc_expr_stfle_init() \
- const unsigned long long *stfle_bits = features->stfle_bits;
+ const unsigned long long stfle_bits = features->stfle_filtered;
#define s390_libc_ifunc_expr_init() \
const struct cpu_features *features = &GLRO(dl_s390_cpu_features); \
diff --git a/sysdeps/s390/s390-64/Makefile b/sysdeps/s390/s390-64/Makefile
index 66ed844e68..991025cd2a 100644
--- a/sysdeps/s390/s390-64/Makefile
+++ b/sysdeps/s390/s390-64/Makefile
@@ -11,7 +11,8 @@ $(objpfx)tst-glibc-hwcaps: \
$(objpfx)libmarkermod2-1.so \
$(objpfx)libmarkermod3-1.so \
$(objpfx)libmarkermod4-1.so \
- $(objpfx)libmarkermod5-1.so
+ $(objpfx)libmarkermod5-1.so \
+ $(objpfx)libmarkermod6-1.so
$(objpfx)tst-glibc-hwcaps.out: \
$(objpfx)libmarkermod2.so \
$(objpfx)glibc-hwcaps/z13/libmarkermod2.so \
@@ -26,7 +27,14 @@ $(objpfx)tst-glibc-hwcaps.out: \
$(objpfx)glibc-hwcaps/z13/libmarkermod5.so \
$(objpfx)glibc-hwcaps/z14/libmarkermod5.so \
$(objpfx)glibc-hwcaps/z15/libmarkermod5.so \
- $(objpfx)glibc-hwcaps/z16/libmarkermod5.so
+ $(objpfx)glibc-hwcaps/z16/libmarkermod5.so \
+ $(objpfx)libmarkermod6.so \
+ $(objpfx)glibc-hwcaps/z13/libmarkermod6.so \
+ $(objpfx)glibc-hwcaps/z14/libmarkermod6.so \
+ $(objpfx)glibc-hwcaps/z15/libmarkermod6.so \
+ $(objpfx)glibc-hwcaps/z16/libmarkermod6.so \
+ $(objpfx)glibc-hwcaps/z17/libmarkermod6.so
+
$(objpfx)glibc-hwcaps/z13/libmarkermod2.so: $(objpfx)libmarkermod2-2.so
$(make-target-directory)
@@ -58,6 +66,21 @@ $(objpfx)glibc-hwcaps/z15/libmarkermod5.so: $(objpfx)libmarkermod5-4.so
$(objpfx)glibc-hwcaps/z16/libmarkermod5.so: $(objpfx)libmarkermod5-5.so
$(make-target-directory)
cp $< $@
+$(objpfx)glibc-hwcaps/z13/libmarkermod6.so: $(objpfx)libmarkermod6-2.so
+ $(make-target-directory)
+ cp $< $@
+$(objpfx)glibc-hwcaps/z14/libmarkermod6.so: $(objpfx)libmarkermod6-3.so
+ $(make-target-directory)
+ cp $< $@
+$(objpfx)glibc-hwcaps/z15/libmarkermod6.so: $(objpfx)libmarkermod6-4.so
+ $(make-target-directory)
+ cp $< $@
+$(objpfx)glibc-hwcaps/z16/libmarkermod6.so: $(objpfx)libmarkermod6-5.so
+ $(make-target-directory)
+ cp $< $@
+$(objpfx)glibc-hwcaps/z17/libmarkermod6.so: $(objpfx)libmarkermod6-6.so
+ $(make-target-directory)
+ cp $< $@
ifeq (no,$(build-hardcoded-path-in-tests))
diff --git a/sysdeps/s390/s390-64/dl-hwcap-check.h b/sysdeps/s390/s390-64/dl-hwcap-check.h
index 6ad3242cc9..433a1ebbe8 100644
--- a/sysdeps/s390/s390-64/dl-hwcap-check.h
+++ b/sysdeps/s390/s390-64/dl-hwcap-check.h
@@ -25,8 +25,23 @@
static inline void
dl_hwcap_check (void)
{
-#if defined __ARCH__
-# if GCCMACRO__ARCH__ >= 14
+ /* Note: The s390x kernel won't introduce new HWCAP-Bits if there is
+ no special handling needed in kernel itself. Thus we have have
+ to check the facility-list retrieved with the stfle instruction.
+ We already have a common storage of this list in cpu-features.c.
+ This dl-hwcap-check.h file is included in
+ sysdeps/unix/sysv/linux/dl-sysdep.c, where also dl-machine.h and
+ cpu-features.c is included. Therefore we don't have a special
+ include here. */
+
+#if defined GCCMACRO__ARCH__
+# if GCCMACRO__ARCH__ >= 15
+ init_cpu_features_no_tunables (&GLRO(dl_s390_cpu_features));
+ if (!(S390_IS_ARCH15 (GLRO(dl_s390_cpu_features).stfle_orig)))
+ _dl_fatal_printf ("\
+Fatal glibc error: CPU lacks VXRS_EXT3/VXRS_PDE3/MIE4/Concurrent-functions \
+support (z17 or later required)\n");
+# elif GCCMACRO__ARCH__ >= 14
if (!(GLRO(dl_hwcap) & HWCAP_S390_VXRS_PDE2))
_dl_fatal_printf ("\
Fatal glibc error: CPU lacks VXRS_PDE2 support (z16 or later required)\n");
@@ -39,7 +54,7 @@ Fatal glibc error: CPU lacks VXRS_EXT2 support (z15 or later required)\n");
_dl_fatal_printf ("\
Fatal glibc error: CPU lacks VXE support (z14 or later required)\n");
# endif
-#endif /* __ARCH__ */
+#endif /* GCCMACRO__ARCH__ */
}
#endif /* _DL_HWCAP_CHECK_H */
diff --git a/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c
index 0a8cce1d3c..11c4bbe4f2 100644
--- a/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c
+++ b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c
@@ -18,9 +18,10 @@
#include <dl-hwcaps.h>
#include <ldsodefs.h>
+#include <cpu-features.h>
-const char _dl_hwcaps_subdirs[] = "z16:z15:z14:z13";
-enum { subdirs_count = 4 }; /* Number of components in _dl_hwcaps_subdirs. */
+const char _dl_hwcaps_subdirs[] = "z17:z16:z15:z14:z13";
+enum { subdirs_count = 5 }; /* Number of components in _dl_hwcaps_subdirs. */
uint32_t
_dl_hwcaps_subdirs_active (void)
@@ -57,5 +58,12 @@ _dl_hwcaps_subdirs_active (void)
return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
++active;
+ /* z17.
+ Note: The kernel has not introduced new HWCAP bits as the new facilities do
+ not require kernel interaction. Thus we check the features via stfle. */
+ if (!(S390_IS_ARCH15 (GLRO(dl_s390_cpu_features).stfle_orig)))
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
+ ++active;
+
return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
}
diff --git a/sysdeps/s390/s390-64/tst-glibc-hwcaps.c b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c
index a7dec68d32..391816dfde 100644
--- a/sysdeps/s390/s390-64/tst-glibc-hwcaps.c
+++ b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c
@@ -26,35 +26,53 @@ extern int marker2 (void);
extern int marker3 (void);
extern int marker4 (void);
extern int marker5 (void);
+extern int marker6 (void);
/* Return the arch level, 10 for the baseline libmarkermod*.so's. */
static int
compute_level (void)
{
const char *platform = (const char *) getauxval (AT_PLATFORM);
+ const unsigned long int hwcap = getauxval (AT_HWCAP);
+ const int latest_level = 15;
/* The arch* versions refer to the edition of the Principles of
Operation, and they are off by two when compared with the recent
product names. (The code below should not be considered an
accurate mapping to Principles of Operation editions for earlier
AT_PLATFORM strings). */
- if (strcmp (platform, "z900") == 0)
- return 10;
- if (strcmp (platform, "z990") == 0)
- return 10;
- if (strcmp (platform, "z9-109") == 0)
- return 10;
- if (strcmp (platform, "z10") == 0)
- return 10;
- if (strcmp (platform, "z196") == 0)
- return 10;
- if (strcmp (platform, "zEC12") == 0)
- return 10;
+ if ((strcmp (platform, "z900") == 0)
+ || (strcmp (platform, "z990") == 0)
+ || (strcmp (platform, "z9-109") == 0)
+ || (strcmp (platform, "z10") == 0)
+ || (strcmp (platform, "z196") == 0)
+ || (strcmp (platform, "zEC12") == 0))
+ {
+ if ((hwcap & HWCAP_S390_VX) == 0)
+ {
+ /* As vector-support was introduced with the newer z13
+ architecture, we are really on one of the tested older
+ architectures. */
+ return 10;
+ }
+ else
+ {
+ /* According to AT_PLATFORM we are on an older architecture
+ without vector-support, but according to HWCAPs vector
+ registers are supported. This means we are running on a
+ new architecture which is not yet known by the kernel.
+ Thus the default AT_PLATFORM string is used, which is the
+ oldest supported one. For this test, assume we are on
+ the latest known architecture. See
+ <kernel>/arch/s390/kernel/processor.c:setup_elf_platform().
+ */
+ return latest_level;
+ }
+ }
/* If we are running on z13 or newer and the kernel was booted with novx,
then AT_PLATFORM is z13 or newer, but _dl_hwcaps_subdirs_active will
return zero and the _dl_hwcaps_subdirs are not searched. */
- const unsigned long int hwcap = getauxval (AT_HWCAP);
if ((hwcap & HWCAP_S390_VX) == 0)
return 10;
@@ -66,9 +84,12 @@ compute_level (void)
return 13;
if (strcmp (platform, "z16") == 0)
return 14;
+ if (strcmp (platform, "z17") == 0)
+ return latest_level;
+
printf ("warning: unrecognized AT_PLATFORM value: %s\n", platform);
- /* Assume that the new platform supports z16. */
- return 14;
+ /* Assume that the new platform supports the latest known architecture. */
+ return latest_level;
}
static int
@@ -80,6 +101,7 @@ do_test (void)
TEST_COMPARE (marker3 (), MIN (level - 9, 3));
TEST_COMPARE (marker4 (), MIN (level - 9, 4));
TEST_COMPARE (marker5 (), MIN (level - 9, 5));
+ TEST_COMPARE (marker6 (), MIN (level - 9, 6));
return 0;
}
diff --git a/sysdeps/unix/sysv/linux/s390/sysconf.c b/sysdeps/unix/sysv/linux/s390/sysconf.c
index ca25822811..8b50a7f860 100644
--- a/sysdeps/unix/sysv/linux/s390/sysconf.c
+++ b/sysdeps/unix/sysv/linux/s390/sysconf.c
@@ -65,7 +65,7 @@ get_cache_info (int level, int attr, int type)
return 0L;
}
- if (!S390_IS_Z10 (features->stfle_bits))
+ if (!S390_IS_Z10 (features->stfle_orig))
{
/* We are at least on a z9 machine.
Return 256byte for LINESIZE for L1 d/i-cache,
--
2.52.0

View File

@@ -1,37 +0,0 @@
From 1e0e33e1b19a7634b364ac7b97c3c9612d5b776f Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Sat, 15 Feb 2025 11:08:33 +0100
Subject: [PATCH] Fix tst-aarch64-pkey to handle ENOSPC as not supported
The syscall pkey_alloc can return ENOSPC to indicate either that all
keys are in use or that the system runs in a mode in which memory
protection keys are disabled. In such case the test should not fail and
just return unsupported.
This matches the behaviour of the generic tst-pkey.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 60f2d6be657aa8c663ee14bd266d343ae0f35afb)
---
sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c b/sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c
index 3ff33ef72a..c884efc3b4 100644
--- a/sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c
+++ b/sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c
@@ -55,6 +55,10 @@ do_test (void)
if (errno == ENOSYS || errno == EINVAL)
FAIL_UNSUPPORTED
("kernel or CPU does not support memory protection keys");
+ if (errno == ENOSPC)
+ FAIL_UNSUPPORTED
+ ("no keys available or kernel does not support memory"
+ " protection keys");
FAIL_EXIT1 ("pkey_alloc: %m");
}
--
2.48.1

View File

@@ -1,6 +1,6 @@
From 43c311457caf71c02ea2857bcf4e1e0499dc221a Mon Sep 17 00:00:00 2001
From 14848b3c532520e71ba2614eb23f173f83c541d2 Mon Sep 17 00:00:00 2001
From: Giuliano Belinassi <gbelinassi@suse.de>
Date: Fri, 18 Apr 2025 14:22:49 -0300
Date: Thu, 2 Jan 2025 22:40:22 +0100
Subject: [PATCH] Add Userspace Livepatch prologue into ASM functions
Userspace Live Patching (ULP) refers to the process of applying
@@ -13,23 +13,23 @@ this have to be included manually. This patch does this.
Signed-off-by: Giuliano Belinassi <gbelinassi@suse.de>
---
config.h.in | 3 ++
config.make.in | 2 +
configure | 54 +++++++++++++++++++++++
configure.ac | 29 +++++++++++++
sysdeps/powerpc/powerpc64/le/Makefile | 8 ++++
config.make.in | 1 +
configure | 22 ++++++++++
configure.ac | 13 ++++++
sysdeps/powerpc/powerpc64/le/Makefile | 5 +++
sysdeps/powerpc/powerpc64/sysdep.h | 55 ++++++++++++++++++++++--
sysdeps/x86_64/Makefile | 5 +++
sysdeps/x86_64/multiarch/strcmp-avx2.S | 5 +--
sysdeps/x86_64/multiarch/strcmp-evex.S | 5 +--
sysdeps/x86_64/multiarch/strcmp-sse4_2.S | 5 +--
sysdeps/x86_64/sysdep.h | 54 +++++++++++++++++++++--
11 files changed, 205 insertions(+), 20 deletions(-)
11 files changed, 153 insertions(+), 20 deletions(-)
diff --git a/config.h.in b/config.h.in
index cdbd555366..2cd9838361 100644
index f495f11244..6c46990c8d 100644
--- a/config.h.in
+++ b/config.h.in
@@ -221,6 +221,9 @@
@@ -214,6 +214,9 @@
/* Define to 1 if libpthread actually resides in libc. */
#define PTHREAD_IN_LIBC 0
@@ -40,32 +40,30 @@ index cdbd555366..2cd9838361 100644
#define TIMEOUTFACTOR 1
diff --git a/config.make.in b/config.make.in
index 59897eaec2..63f9b6ee58 100644
index 36096881b7..04cf873fad 100644
--- a/config.make.in
+++ b/config.make.in
@@ -82,6 +82,8 @@ mach-interface-list = @mach_interface_list@
@@ -81,6 +81,7 @@ mach-interface-list = @mach_interface_list@
memory-tagging = @memory_tagging@
# Configuration options.
+enable-userspace-livepatch = @enable_userspace_livepatch@
+supports-msplit-patch-nops = @supports_msplit_patch_nops@
build-shared = @shared@
build-profile = @profile@
build-static-nss = @static_nss@
diff --git a/configure b/configure
index 674d1d7e4a..51dbce3b34 100755
index 1d543548cd..f6275d327e 100755
--- a/configure
+++ b/configure
@@ -615,6 +615,8 @@ LIBOBJS
@@ -615,6 +615,7 @@ LIBOBJS
pthread_in_libc
RELEASE
VERSION
+supports_msplit_patch_nops
+enable_userspace_livepatch
mach_interface_list
DEFINES
static_nss
@@ -821,6 +823,7 @@ enable_cet
@@ -809,6 +810,7 @@ enable_cet
enable_scv
enable_fortify_source
with_cpu
@@ -73,7 +71,7 @@ index 674d1d7e4a..51dbce3b34 100755
'
ac_precious_vars='build_alias
host_alias
@@ -1505,6 +1508,8 @@ Optional Features:
@@ -1491,6 +1493,8 @@ Optional Features:
Use -D_FORTIFY_SOURCE=[1|2|3] to control code
hardening, defaults to highest possible value
supported by the build compiler.
@@ -82,7 +80,7 @@ index 674d1d7e4a..51dbce3b34 100755
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -9152,6 +9157,55 @@ libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
@@ -8096,6 +8100,24 @@ libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
@@ -96,36 +94,6 @@ index 674d1d7e4a..51dbce3b34 100755
+fi
+
+
+# Check if compiler provides -msplit-patch-nops. It may be required on
+# some architectures for livepatching support.
+if test "x$enable_userspace_livepatch" = xyes; then
+ old_CFLAGS="$CFLAGS"
+ CFLAGS="-msplit-patch-nops $CFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern void g(void);
+ __attribute__((patchable_function_entry(14, 13)))
+ void f(void) { g(); }
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ supports_msplit_patch_nops=yes
+else case e in #(
+ e) supports_msplit_patch_nops=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+ CFLAGS="$old_CFLAGS"
+fi
+
+# Libpulp uses -fpatchable-function-entry to add padding NOPS to the
+# prologue of all functions.
+if test "x$enable_userspace_livepatch" = xyes; then
@@ -133,16 +101,15 @@ index 674d1d7e4a..51dbce3b34 100755
+
+fi
+
+
+
VERSION=`sed -n -e 's/^#define VERSION "\([^"]*\)"/\1/p' < $srcdir/version.h`
RELEASE=`sed -n -e 's/^#define RELEASE "\([^"]*\)"/\1/p' < $srcdir/version.h`
diff --git a/configure.ac b/configure.ac
index 57cd24c87d..97c65dc6c5 100644
index 9cbc0bf68f..4ba19209b7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2079,6 +2079,35 @@ AC_SUBST(DEFINES)
@@ -1780,6 +1780,19 @@ AC_SUBST(DEFINES)
dnl See sysdeps/mach/configure.ac for this variable.
AC_SUBST(mach_interface_list)
@@ -152,53 +119,34 @@ index 57cd24c87d..97c65dc6c5 100644
+ [enable_userspace_livepatch=$enableval],
+ [enable_userspace_livepatch=no])
+
+# Check if compiler provides -msplit-patch-nops. It may be required on
+# some architectures for livepatching support.
+if test "x$enable_userspace_livepatch" = xyes; then
+ old_CFLAGS="$CFLAGS"
+ CFLAGS="-msplit-patch-nops $CFLAGS"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+ [[extern void g(void);
+ __attribute__((patchable_function_entry(14, 13)))
+ void f(void) { g(); }]])],
+ [supports_msplit_patch_nops=yes],
+ [supports_msplit_patch_nops=no])
+
+ CFLAGS="$old_CFLAGS"
+fi
+
+# Libpulp uses -fpatchable-function-entry to add padding NOPS to the
+# prologue of all functions.
+if test "x$enable_userspace_livepatch" = xyes; then
+ AC_DEFINE(ENABLE_USERSPACE_LIVEPATCH)
+fi
+AC_SUBST(enable_userspace_livepatch)
+AC_SUBST(supports_msplit_patch_nops)
+
VERSION=`sed -n -e 's/^#define VERSION "\([^"]*\)"/\1/p' < $srcdir/version.h`
RELEASE=`sed -n -e 's/^#define RELEASE "\([^"]*\)"/\1/p' < $srcdir/version.h`
AC_SUBST(VERSION)
diff --git a/sysdeps/powerpc/powerpc64/le/Makefile b/sysdeps/powerpc/powerpc64/le/Makefile
index b77775cf95..8340a8e02f 100644
index b77775cf95..2f81e562db 100644
--- a/sysdeps/powerpc/powerpc64/le/Makefile
+++ b/sysdeps/powerpc/powerpc64/le/Makefile
@@ -1,3 +1,11 @@
@@ -1,3 +1,8 @@
+# Add flags for Userspace Livepatching support.
+ifeq (yes,$(enable-userspace-livepatch))
++cflags += -fpatchable-function-entry=14,13
+ifeq (yes,$(supports-msplit-patch-nops))
++cflags += -msplit-patch-nops
+endif
++cflags += -fpatchable-function-entry=14,13 -msplit-patch-nops
+endif
+
# When building float128 we need to ensure -mfloat128 is
# passed to all such object files.
type-float128-CFLAGS := -mfloat128
diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
index f05dae71f6..55c6b9b45b 100644
index c363939e1a..33ed236407 100644
--- a/sysdeps/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
@@ -163,6 +163,46 @@
@@ -162,6 +162,46 @@
BODY_LABEL(\name):
.endm
@@ -245,7 +193,7 @@ index f05dae71f6..55c6b9b45b 100644
/* Use ENTRY_TOCLESS for functions that make no use of r2 and
guarantee r2 is unchanged on exit. Any function that has @toc or
@got relocs uses r2. Functions that call other functions via the
@@ -175,19 +215,26 @@ BODY_LABEL(\name):
@@ -174,19 +214,26 @@ BODY_LABEL(\name):
before the start of the function's code. */
#ifndef PROF
#define ENTRY_TOCLESS(name, ...) \
@@ -277,7 +225,7 @@ index f05dae71f6..55c6b9b45b 100644
#define ENTRY(name, ...) \
ENTRY_TOCLESS(name, ## __VA_ARGS__)
diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile
index 9d31685e02..d20287a050 100644
index ce949dba27..44e9f38f4e 100644
--- a/sysdeps/x86_64/Makefile
+++ b/sysdeps/x86_64/Makefile
@@ -1,3 +1,8 @@
@@ -290,7 +238,7 @@ index 9d31685e02..d20287a050 100644
long-double-fcts = yes
diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S
index 4b46a8de17..8266f558d9 100644
index 5bc1d90078..3ea96c0aa3 100644
--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S
+++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S
@@ -201,10 +201,7 @@ END (STRCASECMP)
@@ -306,10 +254,10 @@ index 4b46a8de17..8266f558d9 100644
# if defined USE_AS_STRCASECMP_L
/* We have to fall back on the C implementation for locales with
diff --git a/sysdeps/x86_64/multiarch/strcmp-evex.S b/sysdeps/x86_64/multiarch/strcmp-evex.S
index 6316bb940e..91192f2d2e 100644
index 06730ab2a1..d96b1c4824 100644
--- a/sysdeps/x86_64/multiarch/strcmp-evex.S
+++ b/sysdeps/x86_64/multiarch/strcmp-evex.S
@@ -226,10 +226,7 @@ END (STRCASECMP)
@@ -224,10 +224,7 @@ END (STRCASECMP)
# endif
.p2align 4
@@ -322,7 +270,7 @@ index 6316bb940e..91192f2d2e 100644
# if defined USE_AS_STRCASECMP_L
/* We have to fall back on the C implementation for locales with
diff --git a/sysdeps/x86_64/multiarch/strcmp-sse4_2.S b/sysdeps/x86_64/multiarch/strcmp-sse4_2.S
index 1b746c4b2f..01c8eb44e3 100644
index 4e98da0246..2a2280c65f 100644
--- a/sysdeps/x86_64/multiarch/strcmp-sse4_2.S
+++ b/sysdeps/x86_64/multiarch/strcmp-sse4_2.S
@@ -103,10 +103,7 @@ END (STRCASECMP)
@@ -338,7 +286,7 @@ index 1b746c4b2f..01c8eb44e3 100644
/*
* This implementation uses SSE to compare up to 16 bytes at a time.
diff --git a/sysdeps/x86_64/sysdep.h b/sysdeps/x86_64/sysdep.h
index cb475bec98..2bb84c4c31 100644
index db6e36b2dd..86a5d1b2be 100644
--- a/sysdeps/x86_64/sysdep.h
+++ b/sysdeps/x86_64/sysdep.h
@@ -49,6 +49,46 @@ enum cf_protection_level

176
wordexp-wrde-reuse.patch Normal file
View File

@@ -0,0 +1,176 @@
From 9fe8576664d43b87ca19401fb6a975e217e47623 Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Thu, 15 Jan 2026 10:32:19 -0300
Subject: [PATCH] posix: Reset wordexp_t fields with WRDE_REUSE (CVE-2025-15281
/ BZ 33814)
The wordexp fails to properly initialize the input wordexp_t when
WRDE_REUSE is used. The wordexp_t struct is properly freed, but
reuses the old wc_wordc value and updates the we_wordv in the
wrong position. A later wordfree will then call free with an
invalid pointer.
Checked on x86_64-linux-gnu and i686-linux-gnu.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 80cc58ea2de214f85b0a1d902a3b668ad2ecb302)
---
NEWS | 2 +
posix/Makefile | 11 +++++
posix/tst-wordexp-reuse.c | 89 +++++++++++++++++++++++++++++++++++++++
posix/wordexp.c | 2 +
4 files changed, 104 insertions(+)
create mode 100644 posix/tst-wordexp-reuse.c
diff --git a/posix/Makefile b/posix/Makefile
index 830278a423..0cd5572297 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -326,6 +326,7 @@ tests := \
tst-wait4 \
tst-waitid \
tst-wordexp-nocmd \
+ tst-wordexp-reuse \
tstgetopt \
# tests
@@ -454,6 +455,8 @@ generated += \
tst-rxspencer-no-utf8.mtrace \
tst-vfork3-mem.out \
tst-vfork3.mtrace \
+ tst-wordexp-reuse-mem.out \
+ tst-wordexp-reuse.mtrace \
# generated
endif
endif
@@ -489,6 +492,7 @@ tests-special += \
$(objpfx)tst-pcre-mem.out \
$(objpfx)tst-rxspencer-no-utf8-mem.out \
$(objpfx)tst-vfork3-mem.out \
+ $(objpfx)tst-wordexp-reuse.out \
# tests-special
endif
endif
@@ -772,3 +776,10 @@ $(objpfx)posix-conf-vars-def.h: $(..)scripts/gen-posix-conf-vars.awk \
$(make-target-directory)
$(AWK) -f $(filter-out Makefile, $^) > $@.tmp
mv -f $@.tmp $@
+
+tst-wordexp-reuse-ENV += MALLOC_TRACE=$(objpfx)tst-wordexp-reuse.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+
+$(objpfx)tst-wordexp-reuse-mem.out: $(objpfx)tst-wordexp-reuse.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-wordexp-reuse.mtrace > $@; \
+ $(evaluate-test)
diff --git a/posix/tst-wordexp-reuse.c b/posix/tst-wordexp-reuse.c
new file mode 100644
index 0000000000..3926b9f557
--- /dev/null
+++ b/posix/tst-wordexp-reuse.c
@@ -0,0 +1,89 @@
+/* Test for wordexp with WRDE_REUSE flag.
+ Copyright (C) 2026 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 <wordexp.h>
+#include <mcheck.h>
+
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ mtrace ();
+
+ {
+ wordexp_t p = { 0 };
+ TEST_COMPARE (wordexp ("one", &p, 0), 0);
+ TEST_COMPARE (p.we_wordc, 1);
+ TEST_COMPARE_STRING (p.we_wordv[0], "one");
+ TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE), 0);
+ TEST_COMPARE (p.we_wordc, 1);
+ TEST_COMPARE_STRING (p.we_wordv[0], "two");
+ wordfree (&p);
+ }
+
+ {
+ wordexp_t p = { .we_offs = 2 };
+ TEST_COMPARE (wordexp ("one", &p, 0), 0);
+ TEST_COMPARE (p.we_wordc, 1);
+ TEST_COMPARE_STRING (p.we_wordv[0], "one");
+ TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE | WRDE_DOOFFS), 0);
+ TEST_COMPARE (p.we_wordc, 1);
+ TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two");
+ wordfree (&p);
+ }
+
+ {
+ wordexp_t p = { 0 };
+ TEST_COMPARE (wordexp ("one", &p, 0), 0);
+ TEST_COMPARE (p.we_wordc, 1);
+ TEST_COMPARE_STRING (p.we_wordv[0], "one");
+ TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE | WRDE_APPEND), 0);
+ TEST_COMPARE (p.we_wordc, 1);
+ TEST_COMPARE_STRING (p.we_wordv[0], "two");
+ wordfree (&p);
+ }
+
+ {
+ wordexp_t p = { .we_offs = 2 };
+ TEST_COMPARE (wordexp ("one", &p, WRDE_DOOFFS), 0);
+ TEST_COMPARE (p.we_wordc, 1);
+ TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "one");
+ TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE
+ | WRDE_DOOFFS), 0);
+ TEST_COMPARE (p.we_wordc, 1);
+ TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two");
+ wordfree (&p);
+ }
+
+ {
+ wordexp_t p = { .we_offs = 2 };
+ TEST_COMPARE (wordexp ("one", &p, WRDE_DOOFFS), 0);
+ TEST_COMPARE (p.we_wordc, 1);
+ TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "one");
+ TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE
+ | WRDE_DOOFFS | WRDE_APPEND), 0);
+ TEST_COMPARE (p.we_wordc, 1);
+ TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two");
+ wordfree (&p);
+ }
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/posix/wordexp.c b/posix/wordexp.c
index a7362ef31b..4cd2364519 100644
--- a/posix/wordexp.c
+++ b/posix/wordexp.c
@@ -2216,7 +2216,9 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
{
/* Minimal implementation of WRDE_REUSE for now */
wordfree (pwordexp);
+ old_word.we_wordc = 0;
old_word.we_wordv = NULL;
+ pwordexp->we_wordc = 0;
}
if ((flags & WRDE_APPEND) == 0)
--
2.52.0