forked from rpms/glibc
import glibc-2.28-189.el8
This commit is contained in:
parent
49f27b7834
commit
9ba4cc0ee9
@ -159,6 +159,7 @@ en_SG/ISO-8859-1 \
|
||||
en_US.UTF-8/UTF-8 \
|
||||
en_US/ISO-8859-1 \
|
||||
en_US.ISO-8859-15/ISO-8859-15 \
|
||||
en_US@ampm.UTF-8/UTF-8 \
|
||||
en_ZA.UTF-8/UTF-8 \
|
||||
en_ZA/ISO-8859-1 \
|
||||
en_ZM/UTF-8 \
|
||||
|
38
SOURCES/glibc-rh1929928-1.patch
Normal file
38
SOURCES/glibc-rh1929928-1.patch
Normal file
@ -0,0 +1,38 @@
|
||||
This patch is a downstream-only variant of this upstream commit:
|
||||
|
||||
commit 45b1e17e9150dbd9ac2d578579063fbfa8e1b327
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Thu Dec 17 10:03:05 2020 +0000
|
||||
|
||||
aarch64: use PTR_ARG and SIZE_ARG instead of DELOUSE
|
||||
|
||||
DELOUSE was added to asm code to make them compatible with non-LP64
|
||||
ABIs, but it is an unfortunate name and the code was not compatible
|
||||
with ABIs where pointer and size_t are different. Glibc currently
|
||||
only supports the LP64 ABI so these macros are not really needed or
|
||||
tested, but for now the name is changed to be more meaningful instead
|
||||
of removing them completely.
|
||||
|
||||
Some DELOUSE macros were dropped: clone, strlen and strnlen used it
|
||||
unnecessarily.
|
||||
|
||||
The out of tree ILP32 patches are currently not maintained and will
|
||||
likely need a rework to rebase them on top of the time64 changes.
|
||||
|
||||
Keeping the DELOUSE macro avoids the need to update all string
|
||||
functions. Lack of BTI markers and architecture variants cause many
|
||||
conflicts in a full upstream backport.
|
||||
|
||||
diff --git a/sysdeps/aarch64/sysdep.h b/sysdeps/aarch64/sysdep.h
|
||||
index 5b30709436d3acea..1bcf15d4f18586ba 100644
|
||||
--- a/sysdeps/aarch64/sysdep.h
|
||||
+++ b/sysdeps/aarch64/sysdep.h
|
||||
@@ -32,6 +32,8 @@
|
||||
# define PTR_LOG_SIZE 2
|
||||
# define DELOUSE(n) mov w##n, w##n
|
||||
#endif
|
||||
+#define PTR_ARG(n) DELOUSE(n)
|
||||
+#define SIZE_ARG(n) DELOUSE(n)
|
||||
|
||||
#define PTR_SIZE (1<<PTR_LOG_SIZE)
|
||||
|
88
SOURCES/glibc-rh1929928-2.patch
Normal file
88
SOURCES/glibc-rh1929928-2.patch
Normal file
@ -0,0 +1,88 @@
|
||||
commit 77d175e14e5f4cf24e9579c03eef5d006a286316
|
||||
Author: Naohiro Tamura <naohirot@jp.fujitsu.com>
|
||||
Date: Wed May 12 09:26:40 2021 +0000
|
||||
|
||||
config: Added HAVE_AARCH64_SVE_ASM for aarch64
|
||||
|
||||
This patch checks if assembler supports '-march=armv8.2-a+sve' to
|
||||
generate SVE code or not, and then define HAVE_AARCH64_SVE_ASM macro.
|
||||
|
||||
Conflicts:
|
||||
config.h.in
|
||||
(missing PAC+BTI support downstream, missing other ports)
|
||||
|
||||
diff --git a/config.h.in b/config.h.in
|
||||
index 8520b0fa8d4668fb..94d5ea367e10f849 100644
|
||||
--- a/config.h.in
|
||||
+++ b/config.h.in
|
||||
@@ -112,6 +112,11 @@
|
||||
/* AArch64 big endian ABI */
|
||||
#undef HAVE_AARCH64_BE
|
||||
|
||||
+/* Assembler support ARMv8.2-A SVE.
|
||||
+ This macro becomes obsolete when glibc increased the minimum
|
||||
+ required version of GNU 'binutils' to 2.28 or later. */
|
||||
+#define HAVE_AARCH64_SVE_ASM 0
|
||||
+
|
||||
/* RISC-V integer ABI for ld.so. */
|
||||
#undef RISCV_ABI_XLEN
|
||||
|
||||
diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure
|
||||
index f78a79338aba1e34..9fb713155d4ee6d8 100644
|
||||
--- a/sysdeps/aarch64/configure
|
||||
+++ b/sysdeps/aarch64/configure
|
||||
@@ -212,3 +212,31 @@ fi
|
||||
$as_echo "$libc_cv_aarch64_variant_pcs" >&6; }
|
||||
config_vars="$config_vars
|
||||
aarch64-variant-pcs = $libc_cv_aarch64_variant_pcs"
|
||||
+
|
||||
+# Check if asm support armv8.2-a+sve
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SVE support in assembler" >&5
|
||||
+$as_echo_n "checking for SVE support in assembler... " >&6; }
|
||||
+if ${libc_cv_asm_sve+:} false; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ cat > conftest.s <<\EOF
|
||||
+ ptrue p0.b
|
||||
+EOF
|
||||
+if { ac_try='${CC-cc} -c -march=armv8.2-a+sve conftest.s 1>&5'
|
||||
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
+ (eval $ac_try) 2>&5
|
||||
+ ac_status=$?
|
||||
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
+ test $ac_status = 0; }; }; then
|
||||
+ libc_cv_aarch64_sve_asm=yes
|
||||
+else
|
||||
+ libc_cv_aarch64_sve_asm=no
|
||||
+fi
|
||||
+rm -f conftest*
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_sve" >&5
|
||||
+$as_echo "$libc_cv_asm_sve" >&6; }
|
||||
+if test $libc_cv_aarch64_sve_asm = yes; then
|
||||
+ $as_echo "#define HAVE_AARCH64_SVE_ASM 1" >>confdefs.h
|
||||
+
|
||||
+fi
|
||||
diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac
|
||||
index 7f13bfb93b60bfd7..0236cfcdf3c8d10d 100644
|
||||
--- a/sysdeps/aarch64/configure.ac
|
||||
+++ b/sysdeps/aarch64/configure.ac
|
||||
@@ -42,3 +42,18 @@ EOF
|
||||
fi
|
||||
rm -rf conftest.*])
|
||||
LIBC_CONFIG_VAR([aarch64-variant-pcs], [$libc_cv_aarch64_variant_pcs])
|
||||
+
|
||||
+# Check if asm support armv8.2-a+sve
|
||||
+AC_CACHE_CHECK(for SVE support in assembler, libc_cv_asm_sve, [dnl
|
||||
+cat > conftest.s <<\EOF
|
||||
+ ptrue p0.b
|
||||
+EOF
|
||||
+if AC_TRY_COMMAND(${CC-cc} -c -march=armv8.2-a+sve conftest.s 1>&AS_MESSAGE_LOG_FD); then
|
||||
+ libc_cv_aarch64_sve_asm=yes
|
||||
+else
|
||||
+ libc_cv_aarch64_sve_asm=no
|
||||
+fi
|
||||
+rm -f conftest*])
|
||||
+if test $libc_cv_aarch64_sve_asm = yes; then
|
||||
+ AC_DEFINE(HAVE_AARCH64_SVE_ASM)
|
||||
+fi
|
140
SOURCES/glibc-rh1929928-3.patch
Normal file
140
SOURCES/glibc-rh1929928-3.patch
Normal file
@ -0,0 +1,140 @@
|
||||
commit 38560563587ad8eafa700c56800ff844f18fbad1
|
||||
Author: Naohiro Tamura <naohirot@fujitsu.com>
|
||||
Date: Thu May 20 07:34:37 2021 +0000
|
||||
|
||||
aarch64: Added Vector Length Set test helper script
|
||||
|
||||
This patch is a test helper script to change Vector Length for child
|
||||
process. This script can be used as test-wrapper for 'make check'.
|
||||
|
||||
Usage examples:
|
||||
|
||||
~/build$ make check subdirs=string \
|
||||
test-wrapper='~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 16'
|
||||
|
||||
~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 16 \
|
||||
make test t=string/test-memcpy
|
||||
|
||||
~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 32 \
|
||||
./debugglibc.sh string/test-memmove
|
||||
|
||||
~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 64 \
|
||||
./testrun.sh string/test-memset
|
||||
|
||||
diff --git a/INSTALL b/INSTALL
|
||||
index 065565093bd76d5b..b3a4370f592c5047 100644
|
||||
--- a/INSTALL
|
||||
+++ b/INSTALL
|
||||
@@ -387,6 +387,10 @@ the same syntax as 'test-wrapper-env', the only difference in its
|
||||
semantics being starting with an empty set of environment variables
|
||||
rather than the ambient set.
|
||||
|
||||
+ For AArch64 with SVE, when testing the GNU C Library, 'test-wrapper'
|
||||
+may be set to "SRCDIR/sysdeps/unix/sysv/linux/aarch64/vltest.py
|
||||
+VECTOR-LENGTH" to change Vector Length.
|
||||
+
|
||||
Installing the C Library
|
||||
========================
|
||||
|
||||
diff --git a/manual/install.texi b/manual/install.texi
|
||||
index 7e9f2be150e6f98a..c262fd56d0cef67b 100644
|
||||
--- a/manual/install.texi
|
||||
+++ b/manual/install.texi
|
||||
@@ -425,6 +425,9 @@ use has the same syntax as @samp{test-wrapper-env}, the only
|
||||
difference in its semantics being starting with an empty set of
|
||||
environment variables rather than the ambient set.
|
||||
|
||||
+For AArch64 with SVE, when testing @theglibc{}, @samp{test-wrapper}
|
||||
+may be set to "@var{srcdir}/sysdeps/unix/sysv/linux/aarch64/vltest.py
|
||||
+@var{vector-length}" to change Vector Length.
|
||||
|
||||
@node Running make install
|
||||
@appendixsec Installing the C Library
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/vltest.py b/sysdeps/unix/sysv/linux/aarch64/vltest.py
|
||||
new file mode 100755
|
||||
index 0000000000000000..bed62ad151e06868
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/vltest.py
|
||||
@@ -0,0 +1,82 @@
|
||||
+#!/usr/bin/python3
|
||||
+# Set Scalable Vector Length test helper
|
||||
+# Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+# This file is part of the GNU C Library.
|
||||
+#
|
||||
+# The GNU C Library is free software; you can redistribute it and/or
|
||||
+# modify it under the terms of the GNU Lesser General Public
|
||||
+# License as published by the Free Software Foundation; either
|
||||
+# version 2.1 of the License, or (at your option) any later version.
|
||||
+#
|
||||
+# The GNU C Library is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+# Lesser General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU Lesser General Public
|
||||
+# License along with the GNU C Library; if not, see
|
||||
+# <https://www.gnu.org/licenses/>.
|
||||
+"""Set Scalable Vector Length test helper.
|
||||
+
|
||||
+Set Scalable Vector Length for child process.
|
||||
+
|
||||
+examples:
|
||||
+
|
||||
+~/build$ make check subdirs=string \
|
||||
+test-wrapper='~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 16'
|
||||
+
|
||||
+~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 16 \
|
||||
+make test t=string/test-memcpy
|
||||
+
|
||||
+~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 32 \
|
||||
+./debugglibc.sh string/test-memmove
|
||||
+
|
||||
+~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 64 \
|
||||
+./testrun.sh string/test-memset
|
||||
+"""
|
||||
+import argparse
|
||||
+from ctypes import cdll, CDLL
|
||||
+import os
|
||||
+import sys
|
||||
+
|
||||
+EXIT_SUCCESS = 0
|
||||
+EXIT_FAILURE = 1
|
||||
+EXIT_UNSUPPORTED = 77
|
||||
+
|
||||
+AT_HWCAP = 16
|
||||
+HWCAP_SVE = (1 << 22)
|
||||
+
|
||||
+PR_SVE_GET_VL = 51
|
||||
+PR_SVE_SET_VL = 50
|
||||
+PR_SVE_SET_VL_ONEXEC = (1 << 18)
|
||||
+PR_SVE_VL_INHERIT = (1 << 17)
|
||||
+PR_SVE_VL_LEN_MASK = 0xffff
|
||||
+
|
||||
+def main(args):
|
||||
+ libc = CDLL("libc.so.6")
|
||||
+ if not libc.getauxval(AT_HWCAP) & HWCAP_SVE:
|
||||
+ print("CPU doesn't support SVE")
|
||||
+ sys.exit(EXIT_UNSUPPORTED)
|
||||
+
|
||||
+ libc.prctl(PR_SVE_SET_VL,
|
||||
+ args.vl[0] | PR_SVE_SET_VL_ONEXEC | PR_SVE_VL_INHERIT)
|
||||
+ os.execvp(args.args[0], args.args)
|
||||
+ print("exec system call failure")
|
||||
+ sys.exit(EXIT_FAILURE)
|
||||
+
|
||||
+if __name__ == '__main__':
|
||||
+ parser = argparse.ArgumentParser(description=
|
||||
+ "Set Scalable Vector Length test helper",
|
||||
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
+
|
||||
+ # positional argument
|
||||
+ parser.add_argument("vl", nargs=1, type=int,
|
||||
+ choices=range(16, 257, 16),
|
||||
+ help=('vector length '\
|
||||
+ 'which is multiples of 16 from 16 to 256'))
|
||||
+ # remainDer arguments
|
||||
+ parser.add_argument('args', nargs=argparse.REMAINDER,
|
||||
+ help=('args '\
|
||||
+ 'which is passed to child process'))
|
||||
+ args = parser.parse_args()
|
||||
+ main(args)
|
623
SOURCES/glibc-rh1929928-4.patch
Normal file
623
SOURCES/glibc-rh1929928-4.patch
Normal file
@ -0,0 +1,623 @@
|
||||
commit fa527f345cbbe852ec085932fbea979956c195b5
|
||||
Author: Naohiro Tamura <naohirot@jp.fujitsu.com>
|
||||
Date: Thu May 27 07:42:35 2021 +0000
|
||||
|
||||
aarch64: Added optimized memcpy and memmove for A64FX
|
||||
|
||||
This patch optimizes the performance of memcpy/memmove for A64FX [1]
|
||||
which implements ARMv8-A SVE and has L1 64KB cache per core and L2 8MB
|
||||
cache per NUMA node.
|
||||
|
||||
The performance optimization makes use of Scalable Vector Register
|
||||
with several techniques such as loop unrolling, memory access
|
||||
alignment, cache zero fill, and software pipelining.
|
||||
|
||||
SVE assembler code for memcpy/memmove is implemented as Vector Length
|
||||
Agnostic code so theoretically it can be run on any SOC which supports
|
||||
ARMv8-A SVE standard.
|
||||
|
||||
We confirmed that all testcases have been passed by running 'make
|
||||
check' and 'make xcheck' not only on A64FX but also on ThunderX2.
|
||||
|
||||
And also we confirmed that the SVE 512 bit vector register performance
|
||||
is roughly 4 times better than Advanced SIMD 128 bit register and 8
|
||||
times better than scalar 64 bit register by running 'make bench'.
|
||||
|
||||
[1] https://github.com/fujitsu/A64FX
|
||||
|
||||
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
|
||||
Reviewed-by: Szabolcs Nagy <Szabolcs.Nagy@arm.com>
|
||||
|
||||
Conflicts:
|
||||
manual/tunables.texi
|
||||
sysdeps/aarch64/multiarch/Makefile
|
||||
sysdeps/aarch64/multiarch/ifunc-impl-list.c
|
||||
sysdeps/aarch64/multiarch/init-arch.h
|
||||
sysdeps/aarch64/multiarch/memcpy.c
|
||||
sysdeps/aarch64/multiarch/memmove.c
|
||||
sysdeps/unix/sysv/linux/aarch64/cpu-features.c
|
||||
sysdeps/unix/sysv/linux/aarch64/cpu-features.h
|
||||
(all conflicts due to missing optimizations for other CPUs)
|
||||
|
||||
diff --git a/manual/tunables.texi b/manual/tunables.texi
|
||||
index bd737b5d57080462..07887981748bc44b 100644
|
||||
--- a/manual/tunables.texi
|
||||
+++ b/manual/tunables.texi
|
||||
@@ -386,7 +386,7 @@ This tunable is specific to powerpc, powerpc64 and powerpc64le.
|
||||
The @code{glibc.cpu.name=xxx} tunable allows the user to tell @theglibc{} to
|
||||
assume that the CPU is @code{xxx} where xxx may have one of these values:
|
||||
@code{generic}, @code{falkor}, @code{thunderxt88}, @code{thunderx2t99},
|
||||
-@code{thunderx2t99p1}.
|
||||
+@code{thunderx2t99p1}, @code{a64fx}.
|
||||
|
||||
This tunable is specific to aarch64.
|
||||
@end deftp
|
||||
diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile
|
||||
index 57ffdf72382c0a44..5a19ba0308e80983 100644
|
||||
--- a/sysdeps/aarch64/multiarch/Makefile
|
||||
+++ b/sysdeps/aarch64/multiarch/Makefile
|
||||
@@ -1,4 +1,5 @@
|
||||
ifeq ($(subdir),string)
|
||||
sysdep_routines += memcpy_generic memcpy_thunderx memcpy_thunderx2 \
|
||||
- memcpy_falkor memmove_falkor memset_generic memset_falkor
|
||||
+ memcpy_falkor memcpy_a64fx \
|
||||
+ memmove_falkor memset_generic memset_falkor
|
||||
endif
|
||||
diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
|
||||
index e55be80103b948a2..f53db12acce37877 100644
|
||||
--- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* Maximum number of IFUNC implementations. */
|
||||
-#define MAX_IFUNC 4
|
||||
+#define MAX_IFUNC 7
|
||||
|
||||
size_t
|
||||
__libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
@@ -42,10 +42,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx)
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx2)
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_falkor)
|
||||
+#if HAVE_AARCH64_SVE_ASM
|
||||
+ IFUNC_IMPL_ADD (array, i, memcpy, sve, __memcpy_a64fx)
|
||||
+#endif
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_generic))
|
||||
IFUNC_IMPL (i, name, memmove,
|
||||
IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx)
|
||||
IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_falkor)
|
||||
+#if HAVE_AARCH64_SVE_ASM
|
||||
+ IFUNC_IMPL_ADD (array, i, memmove, sve, __memmove_a64fx)
|
||||
+#endif
|
||||
IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_generic))
|
||||
IFUNC_IMPL (i, name, memset,
|
||||
/* Enable this on non-falkor processors too so that other cores
|
||||
diff --git a/sysdeps/aarch64/multiarch/init-arch.h b/sysdeps/aarch64/multiarch/init-arch.h
|
||||
index d1e5703cb25fdcff..65dc8f82ff23c754 100644
|
||||
--- a/sysdeps/aarch64/multiarch/init-arch.h
|
||||
+++ b/sysdeps/aarch64/multiarch/init-arch.h
|
||||
@@ -22,4 +22,6 @@
|
||||
uint64_t __attribute__((unused)) midr = \
|
||||
GLRO(dl_aarch64_cpu_features).midr_el1; \
|
||||
unsigned __attribute__((unused)) zva_size = \
|
||||
- GLRO(dl_aarch64_cpu_features).zva_size;
|
||||
+ GLRO(dl_aarch64_cpu_features).zva_size; \
|
||||
+ bool __attribute__((unused)) sve = \
|
||||
+ GLRO(dl_aarch64_cpu_features).sve;
|
||||
diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c
|
||||
index 4a04a63b0fe0c84b..e0313c42e82a7b86 100644
|
||||
--- a/sysdeps/aarch64/multiarch/memcpy.c
|
||||
+++ b/sysdeps/aarch64/multiarch/memcpy.c
|
||||
@@ -32,6 +32,9 @@ extern __typeof (__redirect_memcpy) __memcpy_generic attribute_hidden;
|
||||
extern __typeof (__redirect_memcpy) __memcpy_thunderx attribute_hidden;
|
||||
extern __typeof (__redirect_memcpy) __memcpy_thunderx2 attribute_hidden;
|
||||
extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden;
|
||||
+# if HAVE_AARCH64_SVE_ASM
|
||||
+extern __typeof (__redirect_memcpy) __memcpy_a64fx attribute_hidden;
|
||||
+# endif
|
||||
|
||||
libc_ifunc (__libc_memcpy,
|
||||
(IS_THUNDERX (midr)
|
||||
@@ -40,8 +43,13 @@ libc_ifunc (__libc_memcpy,
|
||||
? __memcpy_falkor
|
||||
: (IS_THUNDERX2 (midr) || IS_THUNDERX2PA (midr)
|
||||
? __memcpy_thunderx2
|
||||
+# if HAVE_AARCH64_SVE_ASM
|
||||
+ : (IS_A64FX (midr)
|
||||
+ ? __memcpy_a64fx
|
||||
+ : __memcpy_generic)))));
|
||||
+# else
|
||||
: __memcpy_generic))));
|
||||
-
|
||||
+# endif
|
||||
# undef memcpy
|
||||
strong_alias (__libc_memcpy, memcpy);
|
||||
#endif
|
||||
diff --git a/sysdeps/aarch64/multiarch/memcpy_a64fx.S b/sysdeps/aarch64/multiarch/memcpy_a64fx.S
|
||||
new file mode 100644
|
||||
index 0000000000000000..65528405bb123737
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/aarch64/multiarch/memcpy_a64fx.S
|
||||
@@ -0,0 +1,406 @@
|
||||
+/* Optimized memcpy for Fujitsu A64FX processor.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library. If not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <sysdep.h>
|
||||
+
|
||||
+/* Assumptions:
|
||||
+ *
|
||||
+ * ARMv8.2-a, AArch64, unaligned accesses, sve
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#define L2_SIZE (8*1024*1024)/2 // L2 8MB/2
|
||||
+#define CACHE_LINE_SIZE 256
|
||||
+#define ZF_DIST (CACHE_LINE_SIZE * 21) // Zerofill distance
|
||||
+#define dest x0
|
||||
+#define src x1
|
||||
+#define n x2 // size
|
||||
+#define tmp1 x3
|
||||
+#define tmp2 x4
|
||||
+#define tmp3 x5
|
||||
+#define rest x6
|
||||
+#define dest_ptr x7
|
||||
+#define src_ptr x8
|
||||
+#define vector_length x9
|
||||
+#define cl_remainder x10 // CACHE_LINE_SIZE remainder
|
||||
+
|
||||
+#if HAVE_AARCH64_SVE_ASM
|
||||
+# if IS_IN (libc)
|
||||
+# define MEMCPY __memcpy_a64fx
|
||||
+# define MEMMOVE __memmove_a64fx
|
||||
+
|
||||
+ .arch armv8.2-a+sve
|
||||
+
|
||||
+ .macro dc_zva times
|
||||
+ dc zva, tmp1
|
||||
+ add tmp1, tmp1, CACHE_LINE_SIZE
|
||||
+ .if \times-1
|
||||
+ dc_zva "(\times-1)"
|
||||
+ .endif
|
||||
+ .endm
|
||||
+
|
||||
+ .macro ld1b_unroll8
|
||||
+ ld1b z0.b, p0/z, [src_ptr, #0, mul vl]
|
||||
+ ld1b z1.b, p0/z, [src_ptr, #1, mul vl]
|
||||
+ ld1b z2.b, p0/z, [src_ptr, #2, mul vl]
|
||||
+ ld1b z3.b, p0/z, [src_ptr, #3, mul vl]
|
||||
+ ld1b z4.b, p0/z, [src_ptr, #4, mul vl]
|
||||
+ ld1b z5.b, p0/z, [src_ptr, #5, mul vl]
|
||||
+ ld1b z6.b, p0/z, [src_ptr, #6, mul vl]
|
||||
+ ld1b z7.b, p0/z, [src_ptr, #7, mul vl]
|
||||
+ .endm
|
||||
+
|
||||
+ .macro stld1b_unroll4a
|
||||
+ st1b z0.b, p0, [dest_ptr, #0, mul vl]
|
||||
+ st1b z1.b, p0, [dest_ptr, #1, mul vl]
|
||||
+ ld1b z0.b, p0/z, [src_ptr, #0, mul vl]
|
||||
+ ld1b z1.b, p0/z, [src_ptr, #1, mul vl]
|
||||
+ st1b z2.b, p0, [dest_ptr, #2, mul vl]
|
||||
+ st1b z3.b, p0, [dest_ptr, #3, mul vl]
|
||||
+ ld1b z2.b, p0/z, [src_ptr, #2, mul vl]
|
||||
+ ld1b z3.b, p0/z, [src_ptr, #3, mul vl]
|
||||
+ .endm
|
||||
+
|
||||
+ .macro stld1b_unroll4b
|
||||
+ st1b z4.b, p0, [dest_ptr, #4, mul vl]
|
||||
+ st1b z5.b, p0, [dest_ptr, #5, mul vl]
|
||||
+ ld1b z4.b, p0/z, [src_ptr, #4, mul vl]
|
||||
+ ld1b z5.b, p0/z, [src_ptr, #5, mul vl]
|
||||
+ st1b z6.b, p0, [dest_ptr, #6, mul vl]
|
||||
+ st1b z7.b, p0, [dest_ptr, #7, mul vl]
|
||||
+ ld1b z6.b, p0/z, [src_ptr, #6, mul vl]
|
||||
+ ld1b z7.b, p0/z, [src_ptr, #7, mul vl]
|
||||
+ .endm
|
||||
+
|
||||
+ .macro stld1b_unroll8
|
||||
+ stld1b_unroll4a
|
||||
+ stld1b_unroll4b
|
||||
+ .endm
|
||||
+
|
||||
+ .macro st1b_unroll8
|
||||
+ st1b z0.b, p0, [dest_ptr, #0, mul vl]
|
||||
+ st1b z1.b, p0, [dest_ptr, #1, mul vl]
|
||||
+ st1b z2.b, p0, [dest_ptr, #2, mul vl]
|
||||
+ st1b z3.b, p0, [dest_ptr, #3, mul vl]
|
||||
+ st1b z4.b, p0, [dest_ptr, #4, mul vl]
|
||||
+ st1b z5.b, p0, [dest_ptr, #5, mul vl]
|
||||
+ st1b z6.b, p0, [dest_ptr, #6, mul vl]
|
||||
+ st1b z7.b, p0, [dest_ptr, #7, mul vl]
|
||||
+ .endm
|
||||
+
|
||||
+ .macro shortcut_for_small_size exit
|
||||
+ // if rest <= vector_length * 2
|
||||
+ whilelo p0.b, xzr, n
|
||||
+ whilelo p1.b, vector_length, n
|
||||
+ b.last 1f
|
||||
+ ld1b z0.b, p0/z, [src, #0, mul vl]
|
||||
+ ld1b z1.b, p1/z, [src, #1, mul vl]
|
||||
+ st1b z0.b, p0, [dest, #0, mul vl]
|
||||
+ st1b z1.b, p1, [dest, #1, mul vl]
|
||||
+ ret
|
||||
+1: // if rest > vector_length * 8
|
||||
+ cmp n, vector_length, lsl 3 // vector_length * 8
|
||||
+ b.hi \exit
|
||||
+ // if rest <= vector_length * 4
|
||||
+ lsl tmp1, vector_length, 1 // vector_length * 2
|
||||
+ whilelo p2.b, tmp1, n
|
||||
+ incb tmp1
|
||||
+ whilelo p3.b, tmp1, n
|
||||
+ b.last 1f
|
||||
+ ld1b z0.b, p0/z, [src, #0, mul vl]
|
||||
+ ld1b z1.b, p1/z, [src, #1, mul vl]
|
||||
+ ld1b z2.b, p2/z, [src, #2, mul vl]
|
||||
+ ld1b z3.b, p3/z, [src, #3, mul vl]
|
||||
+ st1b z0.b, p0, [dest, #0, mul vl]
|
||||
+ st1b z1.b, p1, [dest, #1, mul vl]
|
||||
+ st1b z2.b, p2, [dest, #2, mul vl]
|
||||
+ st1b z3.b, p3, [dest, #3, mul vl]
|
||||
+ ret
|
||||
+1: // if rest <= vector_length * 8
|
||||
+ lsl tmp1, vector_length, 2 // vector_length * 4
|
||||
+ whilelo p4.b, tmp1, n
|
||||
+ incb tmp1
|
||||
+ whilelo p5.b, tmp1, n
|
||||
+ b.last 1f
|
||||
+ ld1b z0.b, p0/z, [src, #0, mul vl]
|
||||
+ ld1b z1.b, p1/z, [src, #1, mul vl]
|
||||
+ ld1b z2.b, p2/z, [src, #2, mul vl]
|
||||
+ ld1b z3.b, p3/z, [src, #3, mul vl]
|
||||
+ ld1b z4.b, p4/z, [src, #4, mul vl]
|
||||
+ ld1b z5.b, p5/z, [src, #5, mul vl]
|
||||
+ st1b z0.b, p0, [dest, #0, mul vl]
|
||||
+ st1b z1.b, p1, [dest, #1, mul vl]
|
||||
+ st1b z2.b, p2, [dest, #2, mul vl]
|
||||
+ st1b z3.b, p3, [dest, #3, mul vl]
|
||||
+ st1b z4.b, p4, [dest, #4, mul vl]
|
||||
+ st1b z5.b, p5, [dest, #5, mul vl]
|
||||
+ ret
|
||||
+1: lsl tmp1, vector_length, 2 // vector_length * 4
|
||||
+ incb tmp1 // vector_length * 5
|
||||
+ incb tmp1 // vector_length * 6
|
||||
+ whilelo p6.b, tmp1, n
|
||||
+ incb tmp1
|
||||
+ whilelo p7.b, tmp1, n
|
||||
+ ld1b z0.b, p0/z, [src, #0, mul vl]
|
||||
+ ld1b z1.b, p1/z, [src, #1, mul vl]
|
||||
+ ld1b z2.b, p2/z, [src, #2, mul vl]
|
||||
+ ld1b z3.b, p3/z, [src, #3, mul vl]
|
||||
+ ld1b z4.b, p4/z, [src, #4, mul vl]
|
||||
+ ld1b z5.b, p5/z, [src, #5, mul vl]
|
||||
+ ld1b z6.b, p6/z, [src, #6, mul vl]
|
||||
+ ld1b z7.b, p7/z, [src, #7, mul vl]
|
||||
+ st1b z0.b, p0, [dest, #0, mul vl]
|
||||
+ st1b z1.b, p1, [dest, #1, mul vl]
|
||||
+ st1b z2.b, p2, [dest, #2, mul vl]
|
||||
+ st1b z3.b, p3, [dest, #3, mul vl]
|
||||
+ st1b z4.b, p4, [dest, #4, mul vl]
|
||||
+ st1b z5.b, p5, [dest, #5, mul vl]
|
||||
+ st1b z6.b, p6, [dest, #6, mul vl]
|
||||
+ st1b z7.b, p7, [dest, #7, mul vl]
|
||||
+ ret
|
||||
+ .endm
|
||||
+
|
||||
+ENTRY (MEMCPY)
|
||||
+
|
||||
+ PTR_ARG (0)
|
||||
+ PTR_ARG (1)
|
||||
+ SIZE_ARG (2)
|
||||
+
|
||||
+L(memcpy):
|
||||
+ cntb vector_length
|
||||
+ // shortcut for less than vector_length * 8
|
||||
+ // gives a free ptrue to p0.b for n >= vector_length
|
||||
+ shortcut_for_small_size L(vl_agnostic)
|
||||
+ // end of shortcut
|
||||
+
|
||||
+L(vl_agnostic): // VL Agnostic
|
||||
+ mov rest, n
|
||||
+ mov dest_ptr, dest
|
||||
+ mov src_ptr, src
|
||||
+ // if rest >= L2_SIZE && vector_length == 64 then L(L2)
|
||||
+ mov tmp1, 64
|
||||
+ cmp rest, L2_SIZE
|
||||
+ ccmp vector_length, tmp1, 0, cs
|
||||
+ b.eq L(L2)
|
||||
+
|
||||
+L(unroll8): // unrolling and software pipeline
|
||||
+ lsl tmp1, vector_length, 3 // vector_length * 8
|
||||
+ .p2align 3
|
||||
+ cmp rest, tmp1
|
||||
+ b.cc L(last)
|
||||
+ ld1b_unroll8
|
||||
+ add src_ptr, src_ptr, tmp1
|
||||
+ sub rest, rest, tmp1
|
||||
+ cmp rest, tmp1
|
||||
+ b.cc 2f
|
||||
+ .p2align 3
|
||||
+1: stld1b_unroll8
|
||||
+ add dest_ptr, dest_ptr, tmp1
|
||||
+ add src_ptr, src_ptr, tmp1
|
||||
+ sub rest, rest, tmp1
|
||||
+ cmp rest, tmp1
|
||||
+ b.ge 1b
|
||||
+2: st1b_unroll8
|
||||
+ add dest_ptr, dest_ptr, tmp1
|
||||
+
|
||||
+ .p2align 3
|
||||
+L(last):
|
||||
+ whilelo p0.b, xzr, rest
|
||||
+ whilelo p1.b, vector_length, rest
|
||||
+ b.last 1f
|
||||
+ ld1b z0.b, p0/z, [src_ptr, #0, mul vl]
|
||||
+ ld1b z1.b, p1/z, [src_ptr, #1, mul vl]
|
||||
+ st1b z0.b, p0, [dest_ptr, #0, mul vl]
|
||||
+ st1b z1.b, p1, [dest_ptr, #1, mul vl]
|
||||
+ ret
|
||||
+1: lsl tmp1, vector_length, 1 // vector_length * 2
|
||||
+ whilelo p2.b, tmp1, rest
|
||||
+ incb tmp1
|
||||
+ whilelo p3.b, tmp1, rest
|
||||
+ b.last 1f
|
||||
+ ld1b z0.b, p0/z, [src_ptr, #0, mul vl]
|
||||
+ ld1b z1.b, p1/z, [src_ptr, #1, mul vl]
|
||||
+ ld1b z2.b, p2/z, [src_ptr, #2, mul vl]
|
||||
+ ld1b z3.b, p3/z, [src_ptr, #3, mul vl]
|
||||
+ st1b z0.b, p0, [dest_ptr, #0, mul vl]
|
||||
+ st1b z1.b, p1, [dest_ptr, #1, mul vl]
|
||||
+ st1b z2.b, p2, [dest_ptr, #2, mul vl]
|
||||
+ st1b z3.b, p3, [dest_ptr, #3, mul vl]
|
||||
+ ret
|
||||
+1: lsl tmp1, vector_length, 2 // vector_length * 4
|
||||
+ whilelo p4.b, tmp1, rest
|
||||
+ incb tmp1
|
||||
+ whilelo p5.b, tmp1, rest
|
||||
+ incb tmp1
|
||||
+ whilelo p6.b, tmp1, rest
|
||||
+ incb tmp1
|
||||
+ whilelo p7.b, tmp1, rest
|
||||
+ ld1b z0.b, p0/z, [src_ptr, #0, mul vl]
|
||||
+ ld1b z1.b, p1/z, [src_ptr, #1, mul vl]
|
||||
+ ld1b z2.b, p2/z, [src_ptr, #2, mul vl]
|
||||
+ ld1b z3.b, p3/z, [src_ptr, #3, mul vl]
|
||||
+ ld1b z4.b, p4/z, [src_ptr, #4, mul vl]
|
||||
+ ld1b z5.b, p5/z, [src_ptr, #5, mul vl]
|
||||
+ ld1b z6.b, p6/z, [src_ptr, #6, mul vl]
|
||||
+ ld1b z7.b, p7/z, [src_ptr, #7, mul vl]
|
||||
+ st1b z0.b, p0, [dest_ptr, #0, mul vl]
|
||||
+ st1b z1.b, p1, [dest_ptr, #1, mul vl]
|
||||
+ st1b z2.b, p2, [dest_ptr, #2, mul vl]
|
||||
+ st1b z3.b, p3, [dest_ptr, #3, mul vl]
|
||||
+ st1b z4.b, p4, [dest_ptr, #4, mul vl]
|
||||
+ st1b z5.b, p5, [dest_ptr, #5, mul vl]
|
||||
+ st1b z6.b, p6, [dest_ptr, #6, mul vl]
|
||||
+ st1b z7.b, p7, [dest_ptr, #7, mul vl]
|
||||
+ ret
|
||||
+
|
||||
+L(L2):
|
||||
+ // align dest address at CACHE_LINE_SIZE byte boundary
|
||||
+ mov tmp1, CACHE_LINE_SIZE
|
||||
+ ands tmp2, dest_ptr, CACHE_LINE_SIZE - 1
|
||||
+ // if cl_remainder == 0
|
||||
+ b.eq L(L2_dc_zva)
|
||||
+ sub cl_remainder, tmp1, tmp2
|
||||
+ // process remainder until the first CACHE_LINE_SIZE boundary
|
||||
+ whilelo p1.b, xzr, cl_remainder // keep p0.b all true
|
||||
+ whilelo p2.b, vector_length, cl_remainder
|
||||
+ b.last 1f
|
||||
+ ld1b z1.b, p1/z, [src_ptr, #0, mul vl]
|
||||
+ ld1b z2.b, p2/z, [src_ptr, #1, mul vl]
|
||||
+ st1b z1.b, p1, [dest_ptr, #0, mul vl]
|
||||
+ st1b z2.b, p2, [dest_ptr, #1, mul vl]
|
||||
+ b 2f
|
||||
+1: lsl tmp1, vector_length, 1 // vector_length * 2
|
||||
+ whilelo p3.b, tmp1, cl_remainder
|
||||
+ incb tmp1
|
||||
+ whilelo p4.b, tmp1, cl_remainder
|
||||
+ ld1b z1.b, p1/z, [src_ptr, #0, mul vl]
|
||||
+ ld1b z2.b, p2/z, [src_ptr, #1, mul vl]
|
||||
+ ld1b z3.b, p3/z, [src_ptr, #2, mul vl]
|
||||
+ ld1b z4.b, p4/z, [src_ptr, #3, mul vl]
|
||||
+ st1b z1.b, p1, [dest_ptr, #0, mul vl]
|
||||
+ st1b z2.b, p2, [dest_ptr, #1, mul vl]
|
||||
+ st1b z3.b, p3, [dest_ptr, #2, mul vl]
|
||||
+ st1b z4.b, p4, [dest_ptr, #3, mul vl]
|
||||
+2: add dest_ptr, dest_ptr, cl_remainder
|
||||
+ add src_ptr, src_ptr, cl_remainder
|
||||
+ sub rest, rest, cl_remainder
|
||||
+
|
||||
+L(L2_dc_zva):
|
||||
+ // zero fill
|
||||
+ and tmp1, dest, 0xffffffffffffff
|
||||
+ and tmp2, src, 0xffffffffffffff
|
||||
+ subs tmp1, tmp1, tmp2 // diff
|
||||
+ b.ge 1f
|
||||
+ neg tmp1, tmp1
|
||||
+1: mov tmp3, ZF_DIST + CACHE_LINE_SIZE * 2
|
||||
+ cmp tmp1, tmp3
|
||||
+ b.lo L(unroll8)
|
||||
+ mov tmp1, dest_ptr
|
||||
+ dc_zva (ZF_DIST / CACHE_LINE_SIZE) - 1
|
||||
+ // unroll
|
||||
+ ld1b_unroll8 // this line has to be after "b.lo L(unroll8)"
|
||||
+ add src_ptr, src_ptr, CACHE_LINE_SIZE * 2
|
||||
+ sub rest, rest, CACHE_LINE_SIZE * 2
|
||||
+ mov tmp1, ZF_DIST
|
||||
+ .p2align 3
|
||||
+1: stld1b_unroll4a
|
||||
+ add tmp2, dest_ptr, tmp1 // dest_ptr + ZF_DIST
|
||||
+ dc zva, tmp2
|
||||
+ stld1b_unroll4b
|
||||
+ add tmp2, tmp2, CACHE_LINE_SIZE
|
||||
+ dc zva, tmp2
|
||||
+ add dest_ptr, dest_ptr, CACHE_LINE_SIZE * 2
|
||||
+ add src_ptr, src_ptr, CACHE_LINE_SIZE * 2
|
||||
+ sub rest, rest, CACHE_LINE_SIZE * 2
|
||||
+ cmp rest, tmp3 // ZF_DIST + CACHE_LINE_SIZE * 2
|
||||
+ b.ge 1b
|
||||
+ st1b_unroll8
|
||||
+ add dest_ptr, dest_ptr, CACHE_LINE_SIZE * 2
|
||||
+ b L(unroll8)
|
||||
+
|
||||
+END (MEMCPY)
|
||||
+libc_hidden_builtin_def (MEMCPY)
|
||||
+
|
||||
+
|
||||
+ENTRY (MEMMOVE)
|
||||
+
|
||||
+ PTR_ARG (0)
|
||||
+ PTR_ARG (1)
|
||||
+ SIZE_ARG (2)
|
||||
+
|
||||
+ // remove tag address
|
||||
+ // dest has to be immutable because it is the return value
|
||||
+ // src has to be immutable because it is used in L(bwd_last)
|
||||
+ and tmp2, dest, 0xffffffffffffff // save dest_notag into tmp2
|
||||
+ and tmp3, src, 0xffffffffffffff // save src_notag intp tmp3
|
||||
+ cmp n, 0
|
||||
+ ccmp tmp2, tmp3, 4, ne
|
||||
+ b.ne 1f
|
||||
+ ret
|
||||
+1: cntb vector_length
|
||||
+ // shortcut for less than vector_length * 8
|
||||
+ // gives a free ptrue to p0.b for n >= vector_length
|
||||
+ // tmp2 and tmp3 should not be used in this macro to keep
|
||||
+ // notag addresses
|
||||
+ shortcut_for_small_size L(dispatch)
|
||||
+ // end of shortcut
|
||||
+
|
||||
+L(dispatch):
|
||||
+ // tmp2 = dest_notag, tmp3 = src_notag
|
||||
+ // diff = dest_notag - src_notag
|
||||
+ sub tmp1, tmp2, tmp3
|
||||
+ // if diff <= 0 || diff >= n then memcpy
|
||||
+ cmp tmp1, 0
|
||||
+ ccmp tmp1, n, 2, gt
|
||||
+ b.cs L(vl_agnostic)
|
||||
+
|
||||
+L(bwd_start):
|
||||
+ mov rest, n
|
||||
+ add dest_ptr, dest, n // dest_end
|
||||
+ add src_ptr, src, n // src_end
|
||||
+
|
||||
+L(bwd_unroll8): // unrolling and software pipeline
|
||||
+ lsl tmp1, vector_length, 3 // vector_length * 8
|
||||
+ .p2align 3
|
||||
+ cmp rest, tmp1
|
||||
+ b.cc L(bwd_last)
|
||||
+ sub src_ptr, src_ptr, tmp1
|
||||
+ ld1b_unroll8
|
||||
+ sub rest, rest, tmp1
|
||||
+ cmp rest, tmp1
|
||||
+ b.cc 2f
|
||||
+ .p2align 3
|
||||
+1: sub src_ptr, src_ptr, tmp1
|
||||
+ sub dest_ptr, dest_ptr, tmp1
|
||||
+ stld1b_unroll8
|
||||
+ sub rest, rest, tmp1
|
||||
+ cmp rest, tmp1
|
||||
+ b.ge 1b
|
||||
+2: sub dest_ptr, dest_ptr, tmp1
|
||||
+ st1b_unroll8
|
||||
+
|
||||
+L(bwd_last):
|
||||
+ mov dest_ptr, dest
|
||||
+ mov src_ptr, src
|
||||
+ b L(last)
|
||||
+
|
||||
+END (MEMMOVE)
|
||||
+libc_hidden_builtin_def (MEMMOVE)
|
||||
+# endif /* IS_IN (libc) */
|
||||
+#endif /* HAVE_AARCH64_SVE_ASM */
|
||||
diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c
|
||||
index e69d8162910b938e..d96612b9cf7c3a4e 100644
|
||||
--- a/sysdeps/aarch64/multiarch/memmove.c
|
||||
+++ b/sysdeps/aarch64/multiarch/memmove.c
|
||||
@@ -31,14 +31,22 @@ extern __typeof (__redirect_memmove) __libc_memmove;
|
||||
extern __typeof (__redirect_memmove) __memmove_generic attribute_hidden;
|
||||
extern __typeof (__redirect_memmove) __memmove_thunderx attribute_hidden;
|
||||
extern __typeof (__redirect_memmove) __memmove_falkor attribute_hidden;
|
||||
+# if HAVE_AARCH64_SVE_ASM
|
||||
+extern __typeof (__redirect_memmove) __memmove_a64fx attribute_hidden;
|
||||
+# endif
|
||||
|
||||
libc_ifunc (__libc_memmove,
|
||||
(IS_THUNDERX (midr)
|
||||
? __memmove_thunderx
|
||||
: (IS_FALKOR (midr) || IS_PHECDA (midr)
|
||||
? __memmove_falkor
|
||||
+# if HAVE_AARCH64_SVE_ASM
|
||||
+ : (IS_A64FX (midr)
|
||||
+ ? __memmove_a64fx
|
||||
+ : __memmove_generic))));
|
||||
+# else
|
||||
: __memmove_generic)));
|
||||
-
|
||||
+# endif
|
||||
# undef memmove
|
||||
strong_alias (__libc_memmove, memmove);
|
||||
#endif
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
|
||||
index b4f348509eb1c6b3..71e4355c972f1ffb 100644
|
||||
--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
|
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
|
||||
@@ -36,6 +36,7 @@ static struct cpu_list cpu_list[] = {
|
||||
{"thunderx2t99", 0x431F0AF0},
|
||||
{"thunderx2t99p1", 0x420F5160},
|
||||
{"phecda", 0x680F0000},
|
||||
+ {"a64fx", 0x460F0010},
|
||||
{"generic", 0x0}
|
||||
};
|
||||
|
||||
@@ -80,4 +81,7 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||
|
||||
if ((dczid & DCZID_DZP_MASK) == 0)
|
||||
cpu_features->zva_size = 4 << (dczid & DCZID_BS_MASK);
|
||||
+
|
||||
+ /* Check if SVE is supported. */
|
||||
+ cpu_features->sve = GLRO (dl_hwcap) & HWCAP_SVE;
|
||||
}
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h
|
||||
index eb35adfbe9d429d5..5691aea6de3cb7f4 100644
|
||||
--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h
|
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h
|
||||
@@ -20,6 +20,7 @@
|
||||
#define _CPU_FEATURES_AARCH64_H
|
||||
|
||||
#include <stdint.h>
|
||||
+#include <stdbool.h>
|
||||
|
||||
#define MIDR_PARTNUM_SHIFT 4
|
||||
#define MIDR_PARTNUM_MASK (0xfff << MIDR_PARTNUM_SHIFT)
|
||||
@@ -52,10 +53,14 @@
|
||||
#define IS_PHECDA(midr) (MIDR_IMPLEMENTOR(midr) == 'h' \
|
||||
&& MIDR_PARTNUM(midr) == 0x000)
|
||||
|
||||
+#define IS_A64FX(midr) (MIDR_IMPLEMENTOR(midr) == 'F' \
|
||||
+ && MIDR_PARTNUM(midr) == 0x001)
|
||||
+
|
||||
struct cpu_features
|
||||
{
|
||||
uint64_t midr_el1;
|
||||
unsigned zva_size;
|
||||
+ bool sve;
|
||||
};
|
||||
|
||||
#endif /* _CPU_FEATURES_AARCH64_H */
|
371
SOURCES/glibc-rh1929928-5.patch
Normal file
371
SOURCES/glibc-rh1929928-5.patch
Normal file
@ -0,0 +1,371 @@
|
||||
commit 4f26956d5ba394eb3ade6c1c20b5c16864a00766
|
||||
Author: Naohiro Tamura <naohirot@jp.fujitsu.com>
|
||||
Date: Thu May 27 07:44:12 2021 +0000
|
||||
|
||||
aarch64: Added optimized memset for A64FX
|
||||
|
||||
This patch optimizes the performance of memset for A64FX [1] which
|
||||
implements ARMv8-A SVE and has L1 64KB cache per core and L2 8MB cache
|
||||
per NUMA node.
|
||||
|
||||
The performance optimization makes use of Scalable Vector Register
|
||||
with several techniques such as loop unrolling, memory access
|
||||
alignment, cache zero fill and prefetch.
|
||||
|
||||
SVE assembler code for memset is implemented as Vector Length Agnostic
|
||||
code so theoretically it can be run on any SOC which supports ARMv8-A
|
||||
SVE standard.
|
||||
|
||||
We confirmed that all testcases have been passed by running 'make
|
||||
check' and 'make xcheck' not only on A64FX but also on ThunderX2.
|
||||
|
||||
And also we confirmed that the SVE 512 bit vector register performance
|
||||
is roughly 4 times better than Advanced SIMD 128 bit register and 8
|
||||
times better than scalar 64 bit register by running 'make bench'.
|
||||
|
||||
[1] https://github.com/fujitsu/A64FX
|
||||
|
||||
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
|
||||
Reviewed-by: Szabolcs Nagy <Szabolcs.Nagy@arm.com>
|
||||
|
||||
Conflicts:
|
||||
sysdeps/aarch64/multiarch/Makefile
|
||||
sysdeps/aarch64/multiarch/ifunc-impl-list.c
|
||||
sysdeps/aarch64/multiarch/memset.c
|
||||
(all conflicts due to missing other CPU implementations downstream)
|
||||
|
||||
diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile
|
||||
index 5a19ba0308e80983..5ff883a8ad8e3067 100644
|
||||
--- a/sysdeps/aarch64/multiarch/Makefile
|
||||
+++ b/sysdeps/aarch64/multiarch/Makefile
|
||||
@@ -1,5 +1,6 @@
|
||||
ifeq ($(subdir),string)
|
||||
sysdep_routines += memcpy_generic memcpy_thunderx memcpy_thunderx2 \
|
||||
memcpy_falkor memcpy_a64fx \
|
||||
- memmove_falkor memset_generic memset_falkor
|
||||
+ memmove_falkor memset_generic memset_falkor \
|
||||
+ memset_a64fx
|
||||
endif
|
||||
diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
|
||||
index f53db12acce37877..53e3e162a1025e40 100644
|
||||
--- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
|
||||
@@ -37,7 +37,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
|
||||
INIT_ARCH ();
|
||||
|
||||
- /* Support sysdeps/aarch64/multiarch/memcpy.c and memmove.c. */
|
||||
+ /* Support sysdeps/aarch64/multiarch/memcpy.c, memmove.c and memset.c. */
|
||||
IFUNC_IMPL (i, name, memcpy,
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx)
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx2)
|
||||
@@ -57,6 +57,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Enable this on non-falkor processors too so that other cores
|
||||
can do a comparative analysis with __memset_generic. */
|
||||
IFUNC_IMPL_ADD (array, i, memset, (zva_size == 64), __memset_falkor)
|
||||
+#if HAVE_AARCH64_SVE_ASM
|
||||
+ IFUNC_IMPL_ADD (array, i, memset, sve, __memset_a64fx)
|
||||
+#endif
|
||||
IFUNC_IMPL_ADD (array, i, memset, 1, __memset_generic))
|
||||
|
||||
return i;
|
||||
diff --git a/sysdeps/aarch64/multiarch/memset.c b/sysdeps/aarch64/multiarch/memset.c
|
||||
index d74ed3a549a54b10..2c8cc72bb0b18474 100644
|
||||
--- a/sysdeps/aarch64/multiarch/memset.c
|
||||
+++ b/sysdeps/aarch64/multiarch/memset.c
|
||||
@@ -29,12 +29,21 @@
|
||||
extern __typeof (__redirect_memset) __libc_memset;
|
||||
|
||||
extern __typeof (__redirect_memset) __memset_falkor attribute_hidden;
|
||||
+# if HAVE_AARCH64_SVE_ASM
|
||||
+extern __typeof (__redirect_memset) __memset_a64fx attribute_hidden;
|
||||
+# endif
|
||||
extern __typeof (__redirect_memset) __memset_generic attribute_hidden;
|
||||
|
||||
libc_ifunc (__libc_memset,
|
||||
((IS_FALKOR (midr) || IS_PHECDA (midr)) && zva_size == 64
|
||||
? __memset_falkor
|
||||
+# if HAVE_AARCH64_SVE_ASM
|
||||
+ : (IS_A64FX (midr)
|
||||
+ ? __memset_a64fx
|
||||
+ : __memset_generic)));
|
||||
+# else
|
||||
: __memset_generic));
|
||||
+# endif
|
||||
|
||||
# undef memset
|
||||
strong_alias (__libc_memset, memset);
|
||||
diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
|
||||
new file mode 100644
|
||||
index 0000000000000000..ce54e5418b08c8bc
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
|
||||
@@ -0,0 +1,268 @@
|
||||
+/* Optimized memset for Fujitsu A64FX processor.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library. If not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <sysdep.h>
|
||||
+#include <sysdeps/aarch64/memset-reg.h>
|
||||
+
|
||||
+/* Assumptions:
|
||||
+ *
|
||||
+ * ARMv8.2-a, AArch64, unaligned accesses, sve
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#define L1_SIZE (64*1024) // L1 64KB
|
||||
+#define L2_SIZE (8*1024*1024) // L2 8MB - 1MB
|
||||
+#define CACHE_LINE_SIZE 256
|
||||
+#define PF_DIST_L1 (CACHE_LINE_SIZE * 16) // Prefetch distance L1
|
||||
+#define ZF_DIST (CACHE_LINE_SIZE * 21) // Zerofill distance
|
||||
+#define rest x8
|
||||
+#define vector_length x9
|
||||
+#define vl_remainder x10 // vector_length remainder
|
||||
+#define cl_remainder x11 // CACHE_LINE_SIZE remainder
|
||||
+
|
||||
+#if HAVE_AARCH64_SVE_ASM
|
||||
+# if IS_IN (libc)
|
||||
+# define MEMSET __memset_a64fx
|
||||
+
|
||||
+ .arch armv8.2-a+sve
|
||||
+
|
||||
+ .macro dc_zva times
|
||||
+ dc zva, tmp1
|
||||
+ add tmp1, tmp1, CACHE_LINE_SIZE
|
||||
+ .if \times-1
|
||||
+ dc_zva "(\times-1)"
|
||||
+ .endif
|
||||
+ .endm
|
||||
+
|
||||
+ .macro st1b_unroll first=0, last=7
|
||||
+ st1b z0.b, p0, [dst, #\first, mul vl]
|
||||
+ .if \last-\first
|
||||
+ st1b_unroll "(\first+1)", \last
|
||||
+ .endif
|
||||
+ .endm
|
||||
+
|
||||
+ .macro shortcut_for_small_size exit
|
||||
+ // if rest <= vector_length * 2
|
||||
+ whilelo p0.b, xzr, count
|
||||
+ whilelo p1.b, vector_length, count
|
||||
+ b.last 1f
|
||||
+ st1b z0.b, p0, [dstin, #0, mul vl]
|
||||
+ st1b z0.b, p1, [dstin, #1, mul vl]
|
||||
+ ret
|
||||
+1: // if rest > vector_length * 8
|
||||
+ cmp count, vector_length, lsl 3 // vector_length * 8
|
||||
+ b.hi \exit
|
||||
+ // if rest <= vector_length * 4
|
||||
+ lsl tmp1, vector_length, 1 // vector_length * 2
|
||||
+ whilelo p2.b, tmp1, count
|
||||
+ incb tmp1
|
||||
+ whilelo p3.b, tmp1, count
|
||||
+ b.last 1f
|
||||
+ st1b z0.b, p0, [dstin, #0, mul vl]
|
||||
+ st1b z0.b, p1, [dstin, #1, mul vl]
|
||||
+ st1b z0.b, p2, [dstin, #2, mul vl]
|
||||
+ st1b z0.b, p3, [dstin, #3, mul vl]
|
||||
+ ret
|
||||
+1: // if rest <= vector_length * 8
|
||||
+ lsl tmp1, vector_length, 2 // vector_length * 4
|
||||
+ whilelo p4.b, tmp1, count
|
||||
+ incb tmp1
|
||||
+ whilelo p5.b, tmp1, count
|
||||
+ b.last 1f
|
||||
+ st1b z0.b, p0, [dstin, #0, mul vl]
|
||||
+ st1b z0.b, p1, [dstin, #1, mul vl]
|
||||
+ st1b z0.b, p2, [dstin, #2, mul vl]
|
||||
+ st1b z0.b, p3, [dstin, #3, mul vl]
|
||||
+ st1b z0.b, p4, [dstin, #4, mul vl]
|
||||
+ st1b z0.b, p5, [dstin, #5, mul vl]
|
||||
+ ret
|
||||
+1: lsl tmp1, vector_length, 2 // vector_length * 4
|
||||
+ incb tmp1 // vector_length * 5
|
||||
+ incb tmp1 // vector_length * 6
|
||||
+ whilelo p6.b, tmp1, count
|
||||
+ incb tmp1
|
||||
+ whilelo p7.b, tmp1, count
|
||||
+ st1b z0.b, p0, [dstin, #0, mul vl]
|
||||
+ st1b z0.b, p1, [dstin, #1, mul vl]
|
||||
+ st1b z0.b, p2, [dstin, #2, mul vl]
|
||||
+ st1b z0.b, p3, [dstin, #3, mul vl]
|
||||
+ st1b z0.b, p4, [dstin, #4, mul vl]
|
||||
+ st1b z0.b, p5, [dstin, #5, mul vl]
|
||||
+ st1b z0.b, p6, [dstin, #6, mul vl]
|
||||
+ st1b z0.b, p7, [dstin, #7, mul vl]
|
||||
+ ret
|
||||
+ .endm
|
||||
+
|
||||
+ENTRY (MEMSET)
|
||||
+
|
||||
+ PTR_ARG (0)
|
||||
+ SIZE_ARG (2)
|
||||
+
|
||||
+ cbnz count, 1f
|
||||
+ ret
|
||||
+1: dup z0.b, valw
|
||||
+ cntb vector_length
|
||||
+ // shortcut for less than vector_length * 8
|
||||
+ // gives a free ptrue to p0.b for n >= vector_length
|
||||
+ shortcut_for_small_size L(vl_agnostic)
|
||||
+ // end of shortcut
|
||||
+
|
||||
+L(vl_agnostic): // VL Agnostic
|
||||
+ mov rest, count
|
||||
+ mov dst, dstin
|
||||
+ add dstend, dstin, count
|
||||
+ // if rest >= L2_SIZE && vector_length == 64 then L(L2)
|
||||
+ mov tmp1, 64
|
||||
+ cmp rest, L2_SIZE
|
||||
+ ccmp vector_length, tmp1, 0, cs
|
||||
+ b.eq L(L2)
|
||||
+ // if rest >= L1_SIZE && vector_length == 64 then L(L1_prefetch)
|
||||
+ cmp rest, L1_SIZE
|
||||
+ ccmp vector_length, tmp1, 0, cs
|
||||
+ b.eq L(L1_prefetch)
|
||||
+
|
||||
+L(unroll32):
|
||||
+ lsl tmp1, vector_length, 3 // vector_length * 8
|
||||
+ lsl tmp2, vector_length, 5 // vector_length * 32
|
||||
+ .p2align 3
|
||||
+1: cmp rest, tmp2
|
||||
+ b.cc L(unroll8)
|
||||
+ st1b_unroll
|
||||
+ add dst, dst, tmp1
|
||||
+ st1b_unroll
|
||||
+ add dst, dst, tmp1
|
||||
+ st1b_unroll
|
||||
+ add dst, dst, tmp1
|
||||
+ st1b_unroll
|
||||
+ add dst, dst, tmp1
|
||||
+ sub rest, rest, tmp2
|
||||
+ b 1b
|
||||
+
|
||||
+L(unroll8):
|
||||
+ lsl tmp1, vector_length, 3
|
||||
+ .p2align 3
|
||||
+1: cmp rest, tmp1
|
||||
+ b.cc L(last)
|
||||
+ st1b_unroll
|
||||
+ add dst, dst, tmp1
|
||||
+ sub rest, rest, tmp1
|
||||
+ b 1b
|
||||
+
|
||||
+L(last):
|
||||
+ whilelo p0.b, xzr, rest
|
||||
+ whilelo p1.b, vector_length, rest
|
||||
+ b.last 1f
|
||||
+ st1b z0.b, p0, [dst, #0, mul vl]
|
||||
+ st1b z0.b, p1, [dst, #1, mul vl]
|
||||
+ ret
|
||||
+1: lsl tmp1, vector_length, 1 // vector_length * 2
|
||||
+ whilelo p2.b, tmp1, rest
|
||||
+ incb tmp1
|
||||
+ whilelo p3.b, tmp1, rest
|
||||
+ b.last 1f
|
||||
+ st1b z0.b, p0, [dst, #0, mul vl]
|
||||
+ st1b z0.b, p1, [dst, #1, mul vl]
|
||||
+ st1b z0.b, p2, [dst, #2, mul vl]
|
||||
+ st1b z0.b, p3, [dst, #3, mul vl]
|
||||
+ ret
|
||||
+1: lsl tmp1, vector_length, 2 // vector_length * 4
|
||||
+ whilelo p4.b, tmp1, rest
|
||||
+ incb tmp1
|
||||
+ whilelo p5.b, tmp1, rest
|
||||
+ incb tmp1
|
||||
+ whilelo p6.b, tmp1, rest
|
||||
+ incb tmp1
|
||||
+ whilelo p7.b, tmp1, rest
|
||||
+ st1b z0.b, p0, [dst, #0, mul vl]
|
||||
+ st1b z0.b, p1, [dst, #1, mul vl]
|
||||
+ st1b z0.b, p2, [dst, #2, mul vl]
|
||||
+ st1b z0.b, p3, [dst, #3, mul vl]
|
||||
+ st1b z0.b, p4, [dst, #4, mul vl]
|
||||
+ st1b z0.b, p5, [dst, #5, mul vl]
|
||||
+ st1b z0.b, p6, [dst, #6, mul vl]
|
||||
+ st1b z0.b, p7, [dst, #7, mul vl]
|
||||
+ ret
|
||||
+
|
||||
+L(L1_prefetch): // if rest >= L1_SIZE
|
||||
+ .p2align 3
|
||||
+1: st1b_unroll 0, 3
|
||||
+ prfm pstl1keep, [dst, PF_DIST_L1]
|
||||
+ st1b_unroll 4, 7
|
||||
+ prfm pstl1keep, [dst, PF_DIST_L1 + CACHE_LINE_SIZE]
|
||||
+ add dst, dst, CACHE_LINE_SIZE * 2
|
||||
+ sub rest, rest, CACHE_LINE_SIZE * 2
|
||||
+ cmp rest, L1_SIZE
|
||||
+ b.ge 1b
|
||||
+ cbnz rest, L(unroll32)
|
||||
+ ret
|
||||
+
|
||||
+L(L2):
|
||||
+ // align dst address at vector_length byte boundary
|
||||
+ sub tmp1, vector_length, 1
|
||||
+ ands tmp2, dst, tmp1
|
||||
+ // if vl_remainder == 0
|
||||
+ b.eq 1f
|
||||
+ sub vl_remainder, vector_length, tmp2
|
||||
+ // process remainder until the first vector_length boundary
|
||||
+ whilelt p2.b, xzr, vl_remainder
|
||||
+ st1b z0.b, p2, [dst]
|
||||
+ add dst, dst, vl_remainder
|
||||
+ sub rest, rest, vl_remainder
|
||||
+ // align dstin address at CACHE_LINE_SIZE byte boundary
|
||||
+1: mov tmp1, CACHE_LINE_SIZE
|
||||
+ ands tmp2, dst, CACHE_LINE_SIZE - 1
|
||||
+ // if cl_remainder == 0
|
||||
+ b.eq L(L2_dc_zva)
|
||||
+ sub cl_remainder, tmp1, tmp2
|
||||
+ // process remainder until the first CACHE_LINE_SIZE boundary
|
||||
+ mov tmp1, xzr // index
|
||||
+2: whilelt p2.b, tmp1, cl_remainder
|
||||
+ st1b z0.b, p2, [dst, tmp1]
|
||||
+ incb tmp1
|
||||
+ cmp tmp1, cl_remainder
|
||||
+ b.lo 2b
|
||||
+ add dst, dst, cl_remainder
|
||||
+ sub rest, rest, cl_remainder
|
||||
+
|
||||
+L(L2_dc_zva):
|
||||
+ // zero fill
|
||||
+ mov tmp1, dst
|
||||
+ dc_zva (ZF_DIST / CACHE_LINE_SIZE) - 1
|
||||
+ mov zva_len, ZF_DIST
|
||||
+ add tmp1, zva_len, CACHE_LINE_SIZE * 2
|
||||
+ // unroll
|
||||
+ .p2align 3
|
||||
+1: st1b_unroll 0, 3
|
||||
+ add tmp2, dst, zva_len
|
||||
+ dc zva, tmp2
|
||||
+ st1b_unroll 4, 7
|
||||
+ add tmp2, tmp2, CACHE_LINE_SIZE
|
||||
+ dc zva, tmp2
|
||||
+ add dst, dst, CACHE_LINE_SIZE * 2
|
||||
+ sub rest, rest, CACHE_LINE_SIZE * 2
|
||||
+ cmp rest, tmp1 // ZF_DIST + CACHE_LINE_SIZE * 2
|
||||
+ b.ge 1b
|
||||
+ cbnz rest, L(unroll8)
|
||||
+ ret
|
||||
+
|
||||
+END (MEMSET)
|
||||
+libc_hidden_builtin_def (MEMSET)
|
||||
+
|
||||
+#endif /* IS_IN (libc) */
|
||||
+#endif /* HAVE_AARCH64_SVE_ASM */
|
159
SOURCES/glibc-rh1934162-1.patch
Normal file
159
SOURCES/glibc-rh1934162-1.patch
Normal file
@ -0,0 +1,159 @@
|
||||
From 332421312576bd7095e70589154af99b124dd2d1 Mon Sep 17 00:00:00 2001
|
||||
From: Carlos O'Donell <carlos@redhat.com>
|
||||
Date: Fri, 12 Mar 2021 16:44:47 +0100
|
||||
Subject: elf: Always set l in _dl_init_paths (bug 23462)
|
||||
|
||||
After d1d5471579eb0426671bf94f2d71e61dfb204c30 ("Remove dead
|
||||
DL_DST_REQ_STATIC code.") we always setup the link map l to make the
|
||||
static and shared cases the same. The bug is that in elf/dl-load.c
|
||||
(_dl_init_paths) we conditionally set l only in the #ifdef SHARED
|
||||
case, but unconditionally use it later. The simple solution is to
|
||||
remove the #ifdef SHARED conditional, because it's no longer needed,
|
||||
and unconditionally setup l for both the static and shared cases. A
|
||||
regression test is added to run a static binary with
|
||||
LD_LIBRARY_PATH='$ORIGIN' which crashes before the fix and runs after
|
||||
the fix.
|
||||
|
||||
Co-Authored-By: Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
--- a/elf/Makefile 2021-11-02 16:28:14.720143774 -0400
|
||||
+++ b/elf/Makefile 2021-11-02 18:42:38.763843571 -0400
|
||||
@@ -151,7 +151,8 @@ endif
|
||||
tests-static-normal := tst-leaks1-static tst-array1-static tst-array5-static \
|
||||
tst-dl-iter-static \
|
||||
tst-tlsalign-static tst-tlsalign-extern-static \
|
||||
- tst-linkall-static tst-env-setuid tst-env-setuid-tunables
|
||||
+ tst-linkall-static tst-env-setuid tst-env-setuid-tunables \
|
||||
+ tst-dst-static
|
||||
tests-static-internal := tst-tls1-static tst-tls2-static \
|
||||
tst-ptrguard1-static tst-stackguard1-static \
|
||||
tst-tls1-static-non-pie tst-libc_dlvsym-static
|
||||
@@ -1811,3 +1812,5 @@ $(objpfx)tst-glibc-hwcaps-mask.out: \
|
||||
# Generic dependency for sysdeps implementation of
|
||||
# tst-glibc-hwcaps-cache.
|
||||
$(objpfx)tst-glibc-hwcaps-cache.out: $(objpfx)tst-glibc-hwcaps
|
||||
+
|
||||
+tst-dst-static-ENV = LD_LIBRARY_PATH='$$ORIGIN'
|
||||
diff --git a/elf/dl-load.c b/elf/dl-load.c
|
||||
index 9e2089cfaa..376a2e64d6 100644
|
||||
--- a/elf/dl-load.c
|
||||
+++ b/elf/dl-load.c
|
||||
@@ -758,50 +758,45 @@ _dl_init_paths (const char *llp, const char *source,
|
||||
max_dirnamelen = SYSTEM_DIRS_MAX_LEN;
|
||||
*aelem = NULL;
|
||||
|
||||
-#ifdef SHARED
|
||||
/* This points to the map of the main object. */
|
||||
l = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
- if (l != NULL)
|
||||
+ assert (l->l_type != lt_loaded);
|
||||
+
|
||||
+ if (l->l_info[DT_RUNPATH])
|
||||
+ {
|
||||
+ /* Allocate room for the search path and fill in information
|
||||
+ from RUNPATH. */
|
||||
+ decompose_rpath (&l->l_runpath_dirs,
|
||||
+ (const void *) (D_PTR (l, l_info[DT_STRTAB])
|
||||
+ + l->l_info[DT_RUNPATH]->d_un.d_val),
|
||||
+ l, "RUNPATH");
|
||||
+ /* During rtld init the memory is allocated by the stub malloc,
|
||||
+ prevent any attempt to free it by the normal malloc. */
|
||||
+ l->l_runpath_dirs.malloced = 0;
|
||||
+
|
||||
+ /* The RPATH is ignored. */
|
||||
+ l->l_rpath_dirs.dirs = (void *) -1;
|
||||
+ }
|
||||
+ else
|
||||
{
|
||||
- assert (l->l_type != lt_loaded);
|
||||
+ l->l_runpath_dirs.dirs = (void *) -1;
|
||||
|
||||
- if (l->l_info[DT_RUNPATH])
|
||||
+ if (l->l_info[DT_RPATH])
|
||||
{
|
||||
/* Allocate room for the search path and fill in information
|
||||
- from RUNPATH. */
|
||||
- decompose_rpath (&l->l_runpath_dirs,
|
||||
+ from RPATH. */
|
||||
+ decompose_rpath (&l->l_rpath_dirs,
|
||||
(const void *) (D_PTR (l, l_info[DT_STRTAB])
|
||||
- + l->l_info[DT_RUNPATH]->d_un.d_val),
|
||||
- l, "RUNPATH");
|
||||
- /* During rtld init the memory is allocated by the stub malloc,
|
||||
- prevent any attempt to free it by the normal malloc. */
|
||||
- l->l_runpath_dirs.malloced = 0;
|
||||
-
|
||||
- /* The RPATH is ignored. */
|
||||
- l->l_rpath_dirs.dirs = (void *) -1;
|
||||
+ + l->l_info[DT_RPATH]->d_un.d_val),
|
||||
+ l, "RPATH");
|
||||
+ /* During rtld init the memory is allocated by the stub
|
||||
+ malloc, prevent any attempt to free it by the normal
|
||||
+ malloc. */
|
||||
+ l->l_rpath_dirs.malloced = 0;
|
||||
}
|
||||
else
|
||||
- {
|
||||
- l->l_runpath_dirs.dirs = (void *) -1;
|
||||
-
|
||||
- if (l->l_info[DT_RPATH])
|
||||
- {
|
||||
- /* Allocate room for the search path and fill in information
|
||||
- from RPATH. */
|
||||
- decompose_rpath (&l->l_rpath_dirs,
|
||||
- (const void *) (D_PTR (l, l_info[DT_STRTAB])
|
||||
- + l->l_info[DT_RPATH]->d_un.d_val),
|
||||
- l, "RPATH");
|
||||
- /* During rtld init the memory is allocated by the stub
|
||||
- malloc, prevent any attempt to free it by the normal
|
||||
- malloc. */
|
||||
- l->l_rpath_dirs.malloced = 0;
|
||||
- }
|
||||
- else
|
||||
- l->l_rpath_dirs.dirs = (void *) -1;
|
||||
- }
|
||||
+ l->l_rpath_dirs.dirs = (void *) -1;
|
||||
}
|
||||
-#endif /* SHARED */
|
||||
|
||||
if (llp != NULL && *llp != '\0')
|
||||
{
|
||||
diff --git a/elf/tst-dst-static.c b/elf/tst-dst-static.c
|
||||
new file mode 100644
|
||||
index 0000000000..56eb371c96
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-dst-static.c
|
||||
@@ -0,0 +1,32 @@
|
||||
+/* Test DST expansion for static binaries doesn't carsh. Bug 23462.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* The purpose of this test is to exercise the code in elf/dl-loac.c
|
||||
+ (_dl_init_paths) or thereabout and ensure that static binaries
|
||||
+ don't crash when expanding DSTs.
|
||||
+
|
||||
+ If the dynamic loader code linked into the static binary cannot
|
||||
+ handle expanding the DSTs e.g. null-deref on an incomplete link
|
||||
+ map, then it will crash before reaching main, so the test harness
|
||||
+ is unnecessary. */
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
74
SOURCES/glibc-rh1934162-2.patch
Normal file
74
SOURCES/glibc-rh1934162-2.patch
Normal file
@ -0,0 +1,74 @@
|
||||
From 4e6db99c665d3b82a70a3e218860ef087b1555b4 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon, 15 Mar 2021 10:33:43 +0100
|
||||
Subject: elf: ld.so --help calls _dl_init_paths without a main map [BZ #27577]
|
||||
|
||||
In this case, use the link map of the dynamic loader itself as
|
||||
a replacement. This is more than just a hack: if we ever support
|
||||
DT_RUNPATH/DT_RPATH for the dynamic loader, reporting it for
|
||||
ld.so --help (without further command line arguments) would be the
|
||||
right thing to do.
|
||||
|
||||
Fixes commit 332421312576bd7095e70589154af99b124dd2d1 ("elf: Always
|
||||
set l in _dl_init_paths (bug 23462)").
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 4c9e63dac9..ba4689a7fa 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -231,7 +231,7 @@ tests += $(tests-execstack-$(have-z-execstack))
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)tst-leaks1-mem.out \
|
||||
$(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out \
|
||||
- $(objpfx)tst-ldconfig-X.out
|
||||
+ $(objpfx)tst-ldconfig-X.out $(objpfx)tst-rtld-help.out
|
||||
endif
|
||||
tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
||||
tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
||||
@@ -409,7 +409,8 @@ endif
|
||||
ifeq (yes,$(build-shared))
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \
|
||||
- $(objpfx)tst-rtld-preload.out $(objpfx)argv0test.out
|
||||
+ $(objpfx)tst-rtld-preload.out $(objpfx)argv0test.out \
|
||||
+ $(objpfx)tst-rtld-help.out
|
||||
endif
|
||||
tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
|
||||
$(objpfx)check-wx-segment.out \
|
||||
@@ -1814,3 +1815,16 @@ $(objpfx)list-tunables.out: tst-rtld-list-tunables.sh $(objpfx)ld.so
|
||||
$(objpfx)tst-glibc-hwcaps-cache.out: $(objpfx)tst-glibc-hwcaps
|
||||
|
||||
tst-dst-static-ENV = LD_LIBRARY_PATH='$$ORIGIN'
|
||||
+
|
||||
+$(objpfx)tst-rtld-help.out: $(objpfx)ld.so
|
||||
+ $(test-wrapper) $(rtld-prefix) --help > $@; \
|
||||
+ status=$$?; \
|
||||
+ echo "info: ld.so exit status: $$status" >> $@; \
|
||||
+ if ! grep -q 'Legacy HWCAP subdirectories under library search path directories' $@; then \
|
||||
+ echo "error: missing subdirectory pattern" >> $@; \
|
||||
+ if test $$status -eq 0; then \
|
||||
+ status=1; \
|
||||
+ fi; \
|
||||
+ fi; \
|
||||
+ (exit $$status); \
|
||||
+ $(evaluate-test)
|
||||
diff --git a/elf/dl-load.c b/elf/dl-load.c
|
||||
index 376a2e64d6..2f760503c5 100644
|
||||
--- a/elf/dl-load.c
|
||||
+++ b/elf/dl-load.c
|
||||
@@ -758,8 +758,14 @@ _dl_init_paths (const char *llp, const char *source,
|
||||
max_dirnamelen = SYSTEM_DIRS_MAX_LEN;
|
||||
*aelem = NULL;
|
||||
|
||||
- /* This points to the map of the main object. */
|
||||
+ /* This points to the map of the main object. If there is no main
|
||||
+ object (e.g., under --help, use the dynamic loader itself as a
|
||||
+ stand-in. */
|
||||
l = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
+#ifdef SHARED
|
||||
+ if (l == NULL)
|
||||
+ l = &GL (dl_rtld_map);
|
||||
+#endif
|
||||
assert (l->l_type != lt_loaded);
|
||||
|
||||
if (l->l_info[DT_RUNPATH])
|
90
SOURCES/glibc-rh1937515.patch
Normal file
90
SOURCES/glibc-rh1937515.patch
Normal file
@ -0,0 +1,90 @@
|
||||
Based on the following commit, adjusted for glibc-2.28 in RHEL-8:
|
||||
|
||||
commit 27f74636752d0c4438cf8346cf2a76b6fcf3be16
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Fri Mar 19 06:15:37 2021 -0700
|
||||
|
||||
x86: Properly disable XSAVE related features [BZ #27605]
|
||||
|
||||
1. Support GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVE.
|
||||
2. Disable all features which depend on XSAVE:
|
||||
a. If OSXSAVE is disabled by glibc tunables. Or
|
||||
b. If both XSAVE and XSAVEC aren't usable.
|
||||
|
||||
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||
index 805d00a43309fc23..910425053d9e226f 100644
|
||||
--- a/sysdeps/x86/cpu-features.c
|
||||
+++ b/sysdeps/x86/cpu-features.c
|
||||
@@ -654,6 +654,60 @@ no_cpuid:
|
||||
= TUNABLE_GET (x86_data_cache_size, long int, NULL);
|
||||
cpu_features->shared_cache_size
|
||||
= TUNABLE_GET (x86_shared_cache_size, long int, NULL);
|
||||
+
|
||||
+ bool disable_xsave_features = false;
|
||||
+
|
||||
+ if (!CPU_FEATURE_USABLE_P (cpu_features, OSXSAVE))
|
||||
+ {
|
||||
+ /* These features are usable only if OSXSAVE is usable. */
|
||||
+ CPU_FEATURE_UNSET (cpu_features, XSAVE);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, XSAVEOPT);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, XSAVEC);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, XGETBV_ECX_1);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, XFD);
|
||||
+
|
||||
+ disable_xsave_features = true;
|
||||
+ }
|
||||
+
|
||||
+ if (disable_xsave_features
|
||||
+ || (!CPU_FEATURE_USABLE_P (cpu_features, XSAVE)
|
||||
+ && !CPU_FEATURE_USABLE_P (cpu_features, XSAVEC)))
|
||||
+ {
|
||||
+ /* Clear xsave_state_size if both XSAVE and XSAVEC aren't usable. */
|
||||
+ cpu_features->xsave_state_size = 0;
|
||||
+
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX2);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX_VNNI);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, FMA);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, VAES);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, VPCLMULQDQ);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, XOP);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, F16C);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512F);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512CD);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512ER);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512PF);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512VL);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512DQ);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512BW);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512_4FMAPS);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512_4VNNIW);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512_BITALG);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512_IFMA);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512_VBMI);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512_VBMI2);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512_VNNI);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512_VPOPCNTDQ);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512_VP2INTERSECT);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512_BF16);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AVX512_FP16);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AMX_BF16);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AMX_TILE);
|
||||
+ CPU_FEATURE_UNSET (cpu_features, AMX_INT8);
|
||||
+
|
||||
+ CPU_FEATURE_UNSET (cpu_features, FMA4);
|
||||
+ }
|
||||
#endif
|
||||
|
||||
/* Reuse dl_platform, dl_hwcap and dl_hwcap_mask for x86. */
|
||||
diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c
|
||||
index 0728023007a0f423..3173b2b959ca88f9 100644
|
||||
--- a/sysdeps/x86/cpu-tunables.c
|
||||
+++ b/sysdeps/x86/cpu-tunables.c
|
||||
@@ -168,6 +168,7 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
|
||||
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, MOVBE, 5);
|
||||
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SHSTK, 5);
|
||||
CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSSE3, 5);
|
||||
+ CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, XSAVE, 5);
|
||||
}
|
||||
break;
|
||||
case 6:
|
102
SOURCES/glibc-rh1971664-1.patch
Normal file
102
SOURCES/glibc-rh1971664-1.patch
Normal file
@ -0,0 +1,102 @@
|
||||
commit 0c78b0bb78d87a7de18726a033d88904f158f0fe
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Jun 7 14:22:17 2021 +0530
|
||||
|
||||
iconvconfig: Make file handling more general purpose
|
||||
|
||||
Split out configuration file handling code from handle_dir into its
|
||||
own function so that it can be reused for multiple configuration
|
||||
files.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
|
||||
index b6fef1553cbbdd3d..2b3c587bc77cfdcd 100644
|
||||
--- a/iconv/iconvconfig.c
|
||||
+++ b/iconv/iconvconfig.c
|
||||
@@ -644,37 +644,17 @@ add_module (char *rp, const char *directory)
|
||||
cost, need_ext);
|
||||
}
|
||||
|
||||
-
|
||||
-/* Read the config file and add the data for this directory to that. */
|
||||
-static int
|
||||
-handle_dir (const char *dir)
|
||||
+/* Read a gconv-modules configuration file. */
|
||||
+static bool
|
||||
+handle_file (const char *dir, const char *infile)
|
||||
{
|
||||
- char *cp;
|
||||
FILE *fp;
|
||||
char *line = NULL;
|
||||
size_t linelen = 0;
|
||||
- size_t dirlen = strlen (dir);
|
||||
-
|
||||
- if (dir[dirlen - 1] != '/')
|
||||
- {
|
||||
- char *newp = (char *) xmalloc (dirlen + 2);
|
||||
- dir = memcpy (newp, dir, dirlen);
|
||||
- newp[dirlen++] = '/';
|
||||
- newp[dirlen] = '\0';
|
||||
- }
|
||||
-
|
||||
- char infile[prefix_len + dirlen + sizeof "gconv-modules"];
|
||||
- cp = infile;
|
||||
- if (dir[0] == '/')
|
||||
- cp = mempcpy (cp, prefix, prefix_len);
|
||||
- strcpy (mempcpy (cp, dir, dirlen), "gconv-modules");
|
||||
|
||||
fp = fopen (infile, "r");
|
||||
if (fp == NULL)
|
||||
- {
|
||||
- error (0, errno, "cannot open `%s'", infile);
|
||||
- return 1;
|
||||
- }
|
||||
+ return false;
|
||||
|
||||
/* No threads present. */
|
||||
__fsetlocking (fp, FSETLOCKING_BYCALLER);
|
||||
@@ -723,7 +703,42 @@ handle_dir (const char *dir)
|
||||
|
||||
fclose (fp);
|
||||
|
||||
- return 0;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+/* Read config files and add the data for this directory to cache. */
|
||||
+static int
|
||||
+handle_dir (const char *dir)
|
||||
+{
|
||||
+ char *cp;
|
||||
+ size_t dirlen = strlen (dir);
|
||||
+ bool found = false;
|
||||
+
|
||||
+ if (dir[dirlen - 1] != '/')
|
||||
+ {
|
||||
+ char *newp = (char *) xmalloc (dirlen + 2);
|
||||
+ dir = memcpy (newp, dir, dirlen);
|
||||
+ newp[dirlen++] = '/';
|
||||
+ newp[dirlen] = '\0';
|
||||
+ }
|
||||
+
|
||||
+ char infile[prefix_len + dirlen + sizeof "gconv-modules"];
|
||||
+ cp = infile;
|
||||
+ if (dir[0] == '/')
|
||||
+ cp = mempcpy (cp, prefix, prefix_len);
|
||||
+ strcpy (mempcpy (cp, dir, dirlen), "gconv-modules");
|
||||
+
|
||||
+ found |= handle_file (dir, infile);
|
||||
+
|
||||
+ if (!found)
|
||||
+ {
|
||||
+ error (0, errno, "failed to open gconv configuration file in `%s'",
|
||||
+ dir);
|
||||
+ error (0, 0,
|
||||
+ "ensure that the directory contains a valid gconv-modules file.");
|
||||
+ }
|
||||
+
|
||||
+ return found ? 0 : 1;
|
||||
}
|
||||
|
||||
|
188
SOURCES/glibc-rh1971664-10.patch
Normal file
188
SOURCES/glibc-rh1971664-10.patch
Normal file
@ -0,0 +1,188 @@
|
||||
commit eeac390eecf7de24a110dc84e77e1190f42c5305
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Thu Jun 10 14:31:57 2021 +0530
|
||||
|
||||
iconvconfig: Use common gconv module parsing function
|
||||
|
||||
Drop local copy of gconv file parsing and use the one in
|
||||
gconv_parseconfdir.h instead. Now there is a single implementation of
|
||||
configuration file parsing.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
|
||||
index 2f9d5f45ad3a8159..01ecf6f67d55dbbf 100644
|
||||
--- a/iconv/iconvconfig.c
|
||||
+++ b/iconv/iconvconfig.c
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#include <argp.h>
|
||||
#include <assert.h>
|
||||
-#include <dirent.h>
|
||||
#include <error.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -34,10 +33,10 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/cdefs.h>
|
||||
-#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "iconvconfig.h"
|
||||
+#include <gconv_parseconfdir.h>
|
||||
|
||||
/* Get libc version number. */
|
||||
#include "../version.h"
|
||||
@@ -568,7 +567,9 @@ new_module (const char *fromname, size_t fromlen, const char *toname,
|
||||
|
||||
/* Add new module. */
|
||||
static void
|
||||
-add_module (char *rp, const char *directory)
|
||||
+add_module (char *rp, const char *directory,
|
||||
+ size_t dirlen __attribute__ ((__unused__)),
|
||||
+ int modcount __attribute__ ((__unused__)))
|
||||
{
|
||||
/* We expect now
|
||||
1. `from' name
|
||||
@@ -646,131 +647,28 @@ add_module (char *rp, const char *directory)
|
||||
cost, need_ext);
|
||||
}
|
||||
|
||||
-/* Read a gconv-modules configuration file. */
|
||||
-static bool
|
||||
-handle_file (const char *dir, const char *infile)
|
||||
-{
|
||||
- FILE *fp;
|
||||
- char *line = NULL;
|
||||
- size_t linelen = 0;
|
||||
-
|
||||
- fp = fopen (infile, "r");
|
||||
- if (fp == NULL)
|
||||
- return false;
|
||||
-
|
||||
- /* No threads present. */
|
||||
- __fsetlocking (fp, FSETLOCKING_BYCALLER);
|
||||
-
|
||||
- while (!feof_unlocked (fp))
|
||||
- {
|
||||
- char *rp, *endp, *word;
|
||||
- ssize_t n = __getdelim (&line, &linelen, '\n', fp);
|
||||
-
|
||||
- if (n < 0)
|
||||
- /* An error occurred. */
|
||||
- break;
|
||||
-
|
||||
- rp = line;
|
||||
- /* Terminate the line (excluding comments or newline) with a NUL
|
||||
- byte to simplify the following code. */
|
||||
- endp = strchr (rp, '#');
|
||||
- if (endp != NULL)
|
||||
- *endp = '\0';
|
||||
- else
|
||||
- if (rp[n - 1] == '\n')
|
||||
- rp[n - 1] = '\0';
|
||||
-
|
||||
- while (isspace (*rp))
|
||||
- ++rp;
|
||||
-
|
||||
- /* If this is an empty line go on with the next one. */
|
||||
- if (rp == endp)
|
||||
- continue;
|
||||
-
|
||||
- word = rp;
|
||||
- while (*rp != '\0' && !isspace (*rp))
|
||||
- ++rp;
|
||||
-
|
||||
- if (rp - word == sizeof ("alias") - 1
|
||||
- && memcmp (word, "alias", sizeof ("alias") - 1) == 0)
|
||||
- add_alias (rp);
|
||||
- else if (rp - word == sizeof ("module") - 1
|
||||
- && memcmp (word, "module", sizeof ("module") - 1) == 0)
|
||||
- add_module (rp, dir);
|
||||
- /* else */
|
||||
- /* Otherwise ignore the line. */
|
||||
- }
|
||||
-
|
||||
- free (line);
|
||||
-
|
||||
- fclose (fp);
|
||||
-
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
/* Read config files and add the data for this directory to cache. */
|
||||
static int
|
||||
handle_dir (const char *dir)
|
||||
{
|
||||
- char *cp;
|
||||
size_t dirlen = strlen (dir);
|
||||
bool found = false;
|
||||
|
||||
+ /* Add the prefix before sending it off to the parser. */
|
||||
+ char *fulldir = xmalloc (prefix_len + dirlen + 2);
|
||||
+ char *cp = mempcpy (mempcpy (fulldir, prefix, prefix_len), dir, dirlen);
|
||||
+
|
||||
if (dir[dirlen - 1] != '/')
|
||||
{
|
||||
- char *newp = (char *) xmalloc (dirlen + 2);
|
||||
- dir = memcpy (newp, dir, dirlen);
|
||||
- newp[dirlen++] = '/';
|
||||
- newp[dirlen] = '\0';
|
||||
+ *cp++ = '/';
|
||||
+ *cp = '\0';
|
||||
+ dirlen++;
|
||||
}
|
||||
|
||||
- /* First, look for a gconv-modules file. */
|
||||
- char *buf = malloc (prefix_len + dirlen + sizeof "gconv-modules.d");
|
||||
- if (buf == NULL)
|
||||
- goto out;
|
||||
-
|
||||
- cp = buf;
|
||||
- if (dir[0] == '/')
|
||||
- cp = mempcpy (cp, prefix, prefix_len);
|
||||
- cp = mempcpy (cp, dir, dirlen);
|
||||
- cp = stpcpy (cp, "gconv-modules");
|
||||
-
|
||||
- found |= handle_file (dir, buf);
|
||||
-
|
||||
- /* Next, see if there is a gconv-modules.d directory containing configuration
|
||||
- files and if it is non-empty. */
|
||||
- cp[0] = '.';
|
||||
- cp[1] = 'd';
|
||||
- cp[2] = '\0';
|
||||
-
|
||||
- DIR *confdir = opendir (buf);
|
||||
- if (confdir != NULL)
|
||||
- {
|
||||
- struct dirent *ent;
|
||||
- while ((ent = readdir (confdir)) != NULL)
|
||||
- {
|
||||
- if (ent->d_type != DT_REG)
|
||||
- continue;
|
||||
-
|
||||
- size_t len = strlen (ent->d_name);
|
||||
- const char *suffix = ".conf";
|
||||
-
|
||||
- if (len > strlen (suffix)
|
||||
- && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
|
||||
- {
|
||||
- char *conf;
|
||||
- if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
|
||||
- continue;
|
||||
- found |= handle_file (dir, conf);
|
||||
- free (conf);
|
||||
- }
|
||||
- }
|
||||
- closedir (confdir);
|
||||
- }
|
||||
+ found = gconv_parseconfdir (fulldir, dirlen + prefix_len);
|
||||
|
||||
- free (buf);
|
||||
+ free (fulldir);
|
||||
|
||||
-out:
|
||||
if (!found)
|
||||
{
|
||||
error (0, errno, "failed to open gconv configuration files in `%s'",
|
53
SOURCES/glibc-rh1971664-11.patch
Normal file
53
SOURCES/glibc-rh1971664-11.patch
Normal file
@ -0,0 +1,53 @@
|
||||
Changes specific to RHEL-8:
|
||||
|
||||
- lstat64 is a macro, so undefine it first
|
||||
|
||||
commit f3629a4be82a393ff56646c388da2fda0101f557
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Thu Jun 10 14:56:37 2021 +0530
|
||||
|
||||
Handle DT_UNKNOWN in gconv-modules.d
|
||||
|
||||
On filesystems that do not support dt_type, a regular file shows up as
|
||||
DT_UNKNOWN. Fall back to using lstat64 to read file properties in
|
||||
such cases.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
|
||||
index 3d4d58d4be10a250..ba9b3fd36d9e30f9 100644
|
||||
--- a/iconv/gconv_parseconfdir.h
|
||||
+++ b/iconv/gconv_parseconfdir.h
|
||||
@@ -32,6 +32,8 @@
|
||||
# define readdir __readdir
|
||||
# define closedir __closedir
|
||||
# define mempcpy __mempcpy
|
||||
+# undef lstat64
|
||||
+# define lstat64 __lstat64
|
||||
#endif
|
||||
|
||||
/* Name of the file containing the module information in the directories
|
||||
@@ -138,7 +140,7 @@ gconv_parseconfdir (const char *dir, size_t dir_len)
|
||||
struct dirent *ent;
|
||||
while ((ent = readdir (confdir)) != NULL)
|
||||
{
|
||||
- if (ent->d_type != DT_REG)
|
||||
+ if (ent->d_type != DT_REG && ent->d_type != DT_UNKNOWN)
|
||||
continue;
|
||||
|
||||
size_t len = strlen (ent->d_name);
|
||||
@@ -148,8 +150,14 @@ gconv_parseconfdir (const char *dir, size_t dir_len)
|
||||
&& strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
|
||||
{
|
||||
char *conf;
|
||||
+ struct stat64 st;
|
||||
if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
|
||||
continue;
|
||||
+ if (ent->d_type == DT_UNKNOWN
|
||||
+ && (lstat64 (conf, &st) == -1
|
||||
+ || !S_ISREG (st.st_mode)))
|
||||
+ continue;
|
||||
+
|
||||
found |= read_conf_file (conf, dir, dir_len);
|
||||
free (conf);
|
||||
}
|
98
SOURCES/glibc-rh1971664-12.patch
Normal file
98
SOURCES/glibc-rh1971664-12.patch
Normal file
@ -0,0 +1,98 @@
|
||||
commit 9429049c178b3af3d6afeb3717ff1f2214dc9572
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Jun 28 09:15:55 2021 +0530
|
||||
|
||||
iconvconfig: Fix multiple issues
|
||||
|
||||
It was noticed on big-endian systems that msgfmt would fail with the
|
||||
following error:
|
||||
|
||||
msgfmt: gconv_builtin.c:70: __gconv_get_builtin_trans: Assertion `cnt < sizeof (map) / sizeof (map[0])' failed.
|
||||
Aborted (core dumped)
|
||||
|
||||
This is only seen on installed systems because it was due to a
|
||||
corrupted gconv-modules.cache. iconvconfig had the following issues
|
||||
(it was specifically freeing fulldir that caused this issue, but other
|
||||
cleanups are also needed) that this patch fixes.
|
||||
|
||||
- Add prefix only if dir starts with '/'
|
||||
- Use asprintf instead of mempcpy so that the directory string is NULL
|
||||
terminated
|
||||
- Make a copy of the directory reference in new_module so that fulldir
|
||||
can be freed within the same scope in handle_dir.
|
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
diff --git a/iconv/Makefile b/iconv/Makefile
|
||||
index d09b8ac842731780..6df9862e748ae588 100644
|
||||
--- a/iconv/Makefile
|
||||
+++ b/iconv/Makefile
|
||||
@@ -33,7 +33,7 @@ vpath %.c ../locale/programs ../intl
|
||||
iconv_prog-modules = iconv_charmap charmap charmap-dir linereader \
|
||||
dummy-repertoire simple-hash xstrdup xmalloc \
|
||||
record-status
|
||||
-iconvconfig-modules = strtab xmalloc hash-string
|
||||
+iconvconfig-modules = strtab xmalloc xasprintf xstrdup hash-string
|
||||
extra-objs = $(iconv_prog-modules:=.o) $(iconvconfig-modules:=.o)
|
||||
CFLAGS-iconv_prog.c += -I../locale/programs
|
||||
CFLAGS-iconv_charmap.c += -I../locale/programs
|
||||
diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
|
||||
index 01ecf6f67d55dbbf..777da870d2f8e99a 100644
|
||||
--- a/iconv/iconvconfig.c
|
||||
+++ b/iconv/iconvconfig.c
|
||||
@@ -250,6 +250,7 @@ static const char gconv_module_ext[] = MODULE_EXT;
|
||||
|
||||
|
||||
#include <programs/xmalloc.h>
|
||||
+#include <programs/xasprintf.h>
|
||||
|
||||
|
||||
/* C string table handling. */
|
||||
@@ -519,11 +520,12 @@ module_compare (const void *p1, const void *p2)
|
||||
/* Create new module record. */
|
||||
static void
|
||||
new_module (const char *fromname, size_t fromlen, const char *toname,
|
||||
- size_t tolen, const char *directory,
|
||||
+ size_t tolen, const char *dir_in,
|
||||
const char *filename, size_t filelen, int cost, size_t need_ext)
|
||||
{
|
||||
struct module *new_module;
|
||||
- size_t dirlen = strlen (directory) + 1;
|
||||
+ size_t dirlen = strlen (dir_in) + 1;
|
||||
+ const char *directory = xstrdup (dir_in);
|
||||
char *tmp;
|
||||
void **inserted;
|
||||
|
||||
@@ -654,20 +656,10 @@ handle_dir (const char *dir)
|
||||
size_t dirlen = strlen (dir);
|
||||
bool found = false;
|
||||
|
||||
- /* Add the prefix before sending it off to the parser. */
|
||||
- char *fulldir = xmalloc (prefix_len + dirlen + 2);
|
||||
- char *cp = mempcpy (mempcpy (fulldir, prefix, prefix_len), dir, dirlen);
|
||||
+ char *fulldir = xasprintf ("%s%s%s", dir[0] == '/' ? prefix : "",
|
||||
+ dir, dir[dirlen - 1] != '/' ? "/" : "");
|
||||
|
||||
- if (dir[dirlen - 1] != '/')
|
||||
- {
|
||||
- *cp++ = '/';
|
||||
- *cp = '\0';
|
||||
- dirlen++;
|
||||
- }
|
||||
-
|
||||
- found = gconv_parseconfdir (fulldir, dirlen + prefix_len);
|
||||
-
|
||||
- free (fulldir);
|
||||
+ found = gconv_parseconfdir (fulldir, strlen (fulldir));
|
||||
|
||||
if (!found)
|
||||
{
|
||||
@@ -679,6 +671,8 @@ handle_dir (const char *dir)
|
||||
"configuration files with names ending in .conf.");
|
||||
}
|
||||
|
||||
+ free (fulldir);
|
||||
+
|
||||
return found ? 0 : 1;
|
||||
}
|
||||
|
34
SOURCES/glibc-rh1971664-13.patch
Normal file
34
SOURCES/glibc-rh1971664-13.patch
Normal file
@ -0,0 +1,34 @@
|
||||
commit 7f784fabcb186ffaa082ed0aeed52a56b7d96cee
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Fri Jul 2 16:53:25 2021 +0530
|
||||
|
||||
iconvconfig: Use the public feof_unlocked
|
||||
|
||||
Build of iconvconfig failed with CFLAGS=-Os since __feof_unlocked is
|
||||
not a public symbol. Replace with feof_unlocked (defined to
|
||||
__feof_unlocked when IS_IN (libc)) to fix this.
|
||||
|
||||
Reported-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
|
||||
diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
|
||||
index ba9b3fd36d9e30f9..234b85a586f1d79a 100644
|
||||
--- a/iconv/gconv_parseconfdir.h
|
||||
+++ b/iconv/gconv_parseconfdir.h
|
||||
@@ -34,6 +34,7 @@
|
||||
# define mempcpy __mempcpy
|
||||
# undef lstat64
|
||||
# define lstat64 __lstat64
|
||||
+# define feof_unlocked __feof_unlocked
|
||||
#endif
|
||||
|
||||
/* Name of the file containing the module information in the directories
|
||||
@@ -65,7 +66,7 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len)
|
||||
|
||||
/* Process the known entries of the file. Comments start with `#' and
|
||||
end with the end of the line. Empty lines are ignored. */
|
||||
- while (!__feof_unlocked (fp))
|
||||
+ while (!feof_unlocked (fp))
|
||||
{
|
||||
char *rp, *endp, *word;
|
||||
ssize_t n = __getdelim (&line, &line_len, '\n', fp);
|
32
SOURCES/glibc-rh1971664-14.patch
Normal file
32
SOURCES/glibc-rh1971664-14.patch
Normal file
@ -0,0 +1,32 @@
|
||||
commit 5f9b78fe35d08739b6da1e5b356786d41116c108
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Aug 3 21:10:20 2021 +0530
|
||||
|
||||
gconv_parseconfdir: Fix memory leak
|
||||
|
||||
The allocated `conf` would leak if we have to skip over the file due
|
||||
to the underlying filesystem not supporting dt_type.
|
||||
|
||||
Reviewed-by: Arjun Shankar <arjun@redhat.com>
|
||||
|
||||
diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
|
||||
index 915b60845ca11c03..e4c3c16d1f96ce0c 100644
|
||||
--- a/iconv/gconv_parseconfdir.h
|
||||
+++ b/iconv/gconv_parseconfdir.h
|
||||
@@ -153,12 +153,11 @@ gconv_parseconfdir (const char *dir, size_t dir_len)
|
||||
struct stat64 st;
|
||||
if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
|
||||
continue;
|
||||
- if (ent->d_type == DT_UNKNOWN
|
||||
- && (lstat64 (conf, &st) == -1
|
||||
- || !S_ISREG (st.st_mode)))
|
||||
- continue;
|
||||
|
||||
- found |= read_conf_file (conf, dir, dir_len);
|
||||
+ if (ent->d_type != DT_UNKNOWN
|
||||
+ || (lstat64 (conf, &st) != -1 && S_ISREG (st.st_mode)))
|
||||
+ found |= read_conf_file (conf, dir, dir_len);
|
||||
+
|
||||
free (conf);
|
||||
}
|
||||
}
|
116
SOURCES/glibc-rh1971664-15.patch
Normal file
116
SOURCES/glibc-rh1971664-15.patch
Normal file
@ -0,0 +1,116 @@
|
||||
commit 43cea6d5652b6b9e61ac6ecc69419c909b504f47
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Sep 13 20:48:35 2021 +0530
|
||||
|
||||
iconvconfig: Fix behaviour with --prefix [BZ #28199]
|
||||
|
||||
The consolidation of configuration parsing broke behaviour with
|
||||
--prefix, where the prefix bled into the modules cache. Accept a
|
||||
prefix which, when non-NULL, is prepended to the path when looking for
|
||||
configuration files but only the original directory is added to the
|
||||
modules cache.
|
||||
|
||||
This has no effect on the codegen of gconv_conf since it passes NULL.
|
||||
|
||||
Reported-by: Patrick McCarty <patrick.mccarty@intel.com>
|
||||
Reported-by: Michael Hudson-Doyle <michael.hudson@canonical.com>
|
||||
Reviewed-by: Andreas Schwab <schwab@linux-m68k.org>
|
||||
|
||||
diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
|
||||
index ce64faa928dc1c52..3f5a692f1510157c 100644
|
||||
--- a/iconv/gconv_conf.c
|
||||
+++ b/iconv/gconv_conf.c
|
||||
@@ -476,7 +476,7 @@ __gconv_read_conf (void)
|
||||
__gconv_get_path ();
|
||||
|
||||
for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt)
|
||||
- gconv_parseconfdir (__gconv_path_elem[cnt].name,
|
||||
+ gconv_parseconfdir (NULL, __gconv_path_elem[cnt].name,
|
||||
__gconv_path_elem[cnt].len);
|
||||
#endif
|
||||
|
||||
diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
|
||||
index e4c3c16d1f96ce0c..433aa18bab5083b0 100644
|
||||
--- a/iconv/gconv_parseconfdir.h
|
||||
+++ b/iconv/gconv_parseconfdir.h
|
||||
@@ -39,7 +39,6 @@
|
||||
/* Name of the file containing the module information in the directories
|
||||
along the path. */
|
||||
static const char gconv_conf_filename[] = "gconv-modules";
|
||||
-static const char gconv_conf_dirname[] = "gconv-modules.d";
|
||||
|
||||
static void add_alias (char *);
|
||||
static void add_module (char *, const char *, size_t, int);
|
||||
@@ -110,19 +109,28 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len)
|
||||
return true;
|
||||
}
|
||||
|
||||
+/* Prefix DIR (with length DIR_LEN) with PREFIX if the latter is non-NULL and
|
||||
+ parse configuration in it. */
|
||||
+
|
||||
static __always_inline bool
|
||||
-gconv_parseconfdir (const char *dir, size_t dir_len)
|
||||
+gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len)
|
||||
{
|
||||
- /* No slash needs to be inserted between dir and gconv_conf_filename;
|
||||
- dir already ends in a slash. */
|
||||
- char *buf = malloc (dir_len + sizeof (gconv_conf_dirname));
|
||||
+ /* No slash needs to be inserted between dir and gconv_conf_filename; dir
|
||||
+ already ends in a slash. The additional 2 is to accommodate the ".d"
|
||||
+ when looking for configuration files in gconv-modules.d. */
|
||||
+ size_t buflen = dir_len + sizeof (gconv_conf_filename) + 2;
|
||||
+ char *buf = malloc (buflen + (prefix != NULL ? strlen (prefix) : 0));
|
||||
+ char *cp = buf;
|
||||
bool found = false;
|
||||
|
||||
if (buf == NULL)
|
||||
return false;
|
||||
|
||||
- char *cp = mempcpy (mempcpy (buf, dir, dir_len), gconv_conf_filename,
|
||||
- sizeof (gconv_conf_filename));
|
||||
+ if (prefix != NULL)
|
||||
+ cp = stpcpy (cp, prefix);
|
||||
+
|
||||
+ cp = mempcpy (mempcpy (cp, dir, dir_len), gconv_conf_filename,
|
||||
+ sizeof (gconv_conf_filename));
|
||||
|
||||
/* Read the gconv-modules configuration file first. */
|
||||
found = read_conf_file (buf, dir, dir_len);
|
||||
diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
|
||||
index 777da870d2f8e99a..b1fd4100b5cbc9d2 100644
|
||||
--- a/iconv/iconvconfig.c
|
||||
+++ b/iconv/iconvconfig.c
|
||||
@@ -653,13 +653,21 @@ add_module (char *rp, const char *directory,
|
||||
static int
|
||||
handle_dir (const char *dir)
|
||||
{
|
||||
+ char *newp = NULL;
|
||||
size_t dirlen = strlen (dir);
|
||||
bool found = false;
|
||||
|
||||
- char *fulldir = xasprintf ("%s%s%s", dir[0] == '/' ? prefix : "",
|
||||
- dir, dir[dirlen - 1] != '/' ? "/" : "");
|
||||
+ /* End directory path with a '/' if it doesn't already. */
|
||||
+ if (dir[dirlen - 1] != '/')
|
||||
+ {
|
||||
+ newp = xmalloc (dirlen + 2);
|
||||
+ memcpy (newp, dir, dirlen);
|
||||
+ newp[dirlen++] = '/';
|
||||
+ newp[dirlen] = '\0';
|
||||
+ dir = newp;
|
||||
+ }
|
||||
|
||||
- found = gconv_parseconfdir (fulldir, strlen (fulldir));
|
||||
+ found = gconv_parseconfdir (dir[0] == '/' ? prefix : NULL, dir, dirlen);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
@@ -671,7 +679,7 @@ handle_dir (const char *dir)
|
||||
"configuration files with names ending in .conf.");
|
||||
}
|
||||
|
||||
- free (fulldir);
|
||||
+ free (newp);
|
||||
|
||||
return found ? 0 : 1;
|
||||
}
|
109
SOURCES/glibc-rh1971664-2.patch
Normal file
109
SOURCES/glibc-rh1971664-2.patch
Normal file
@ -0,0 +1,109 @@
|
||||
commit 3979c3e1bae20459d9b6d424bdb49927d9cd6fec
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Jun 7 14:22:18 2021 +0530
|
||||
|
||||
iconvconfig: Read configuration from gconv-modules.d subdirectory
|
||||
|
||||
In addition to GCONV_PATH/gconv-modules, also read module
|
||||
configuration from *.conf files in GCONV_PATH/gconv-modules.d. This
|
||||
allows a single gconv directory to have multiple sets of gconv modules
|
||||
but at the same time, a single modules cache.
|
||||
|
||||
With this feature, one could separate the glibc supported gconv
|
||||
modules into a minimal essential set (ISO-8859-*, UTF, etc.) from the
|
||||
remaining modules. In future, these could be further segregated into
|
||||
langpack-associated sets with their own
|
||||
gconv-modules.d/someconfig.conf.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
|
||||
index 2b3c587bc77cfdcd..fafc686ae25fb5c1 100644
|
||||
--- a/iconv/iconvconfig.c
|
||||
+++ b/iconv/iconvconfig.c
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <argp.h>
|
||||
#include <assert.h>
|
||||
+#include <dirent.h>
|
||||
#include <error.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -33,6 +34,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/cdefs.h>
|
||||
+#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "iconvconfig.h"
|
||||
@@ -710,6 +712,7 @@ handle_file (const char *dir, const char *infile)
|
||||
static int
|
||||
handle_dir (const char *dir)
|
||||
{
|
||||
+#define BUF_LEN prefix_len + dirlen + sizeof "gconv-modules.d"
|
||||
char *cp;
|
||||
size_t dirlen = strlen (dir);
|
||||
bool found = false;
|
||||
@@ -722,20 +725,55 @@ handle_dir (const char *dir)
|
||||
newp[dirlen] = '\0';
|
||||
}
|
||||
|
||||
- char infile[prefix_len + dirlen + sizeof "gconv-modules"];
|
||||
- cp = infile;
|
||||
+ /* First, look for a gconv-modules file. */
|
||||
+ char buf[BUF_LEN];
|
||||
+ cp = buf;
|
||||
if (dir[0] == '/')
|
||||
cp = mempcpy (cp, prefix, prefix_len);
|
||||
- strcpy (mempcpy (cp, dir, dirlen), "gconv-modules");
|
||||
+ cp = mempcpy (cp, dir, dirlen);
|
||||
+ cp = stpcpy (cp, "gconv-modules");
|
||||
|
||||
- found |= handle_file (dir, infile);
|
||||
+ found |= handle_file (dir, buf);
|
||||
+
|
||||
+ /* Next, see if there is a gconv-modules.d directory containing configuration
|
||||
+ files and if it is non-empty. */
|
||||
+ cp[0] = '.';
|
||||
+ cp[1] = 'd';
|
||||
+ cp[2] = '\0';
|
||||
+
|
||||
+ DIR *confdir = opendir (buf);
|
||||
+ if (confdir != NULL)
|
||||
+ {
|
||||
+ struct dirent *ent;
|
||||
+ while ((ent = readdir (confdir)) != NULL)
|
||||
+ {
|
||||
+ if (ent->d_type != DT_REG)
|
||||
+ continue;
|
||||
+
|
||||
+ size_t len = strlen (ent->d_name);
|
||||
+ const char *suffix = ".conf";
|
||||
+
|
||||
+ if (len > strlen (suffix)
|
||||
+ && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
|
||||
+ {
|
||||
+ /* LEN <= PATH_MAX so this alloca is not unbounded. */
|
||||
+ char *conf = alloca (BUF_LEN + len + 1);
|
||||
+ cp = stpcpy (conf, buf);
|
||||
+ sprintf (cp, "/%s", ent->d_name);
|
||||
+ found |= handle_file (dir, conf);
|
||||
+ }
|
||||
+ }
|
||||
+ closedir (confdir);
|
||||
+ }
|
||||
|
||||
if (!found)
|
||||
{
|
||||
- error (0, errno, "failed to open gconv configuration file in `%s'",
|
||||
+ error (0, errno, "failed to open gconv configuration files in `%s'",
|
||||
dir);
|
||||
error (0, 0,
|
||||
- "ensure that the directory contains a valid gconv-modules file.");
|
||||
+ "ensure that the directory contains either a valid "
|
||||
+ "gconv-modules file or a gconv-modules.d directory with "
|
||||
+ "configuration files with names ending in .conf.");
|
||||
}
|
||||
|
||||
return found ? 0 : 1;
|
99
SOURCES/glibc-rh1971664-3.patch
Normal file
99
SOURCES/glibc-rh1971664-3.patch
Normal file
@ -0,0 +1,99 @@
|
||||
commit b17d29b390154df9dfad9d21f1e6605422521fd2
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Jun 7 14:22:19 2021 +0530
|
||||
|
||||
gconv_conf: Read configuration files in gconv-modules.d
|
||||
|
||||
Read configuration files with names ending in .conf in
|
||||
GCONV_PATH/gconv-modules.d to mirror configuration flexibility in
|
||||
iconvconfig into the iconv program and function.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
|
||||
index f173cde71b2a61d7..8eb981fca7cee36a 100644
|
||||
--- a/iconv/gconv_conf.c
|
||||
+++ b/iconv/gconv_conf.c
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
+#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
@@ -30,6 +31,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
+#include <sys/types.h>
|
||||
|
||||
#include <libc-lock.h>
|
||||
#include <gconv_int.h>
|
||||
@@ -50,6 +52,7 @@ static const struct path_elem empty_path_elem = { NULL, 0 };
|
||||
/* Name of the file containing the module information in the directories
|
||||
along the path. */
|
||||
static const char gconv_conf_filename[] = "gconv-modules";
|
||||
+static const char gconv_conf_dirname[] = "gconv-modules.d";
|
||||
|
||||
/* Filename extension for the modules. */
|
||||
#ifndef MODULE_EXT
|
||||
@@ -554,18 +557,52 @@ __gconv_read_conf (void)
|
||||
|
||||
for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt)
|
||||
{
|
||||
+#define BUF_LEN elem_len + sizeof (gconv_conf_dirname)
|
||||
+
|
||||
const char *elem = __gconv_path_elem[cnt].name;
|
||||
size_t elem_len = __gconv_path_elem[cnt].len;
|
||||
- char *filename;
|
||||
+ char *buf;
|
||||
|
||||
/* No slash needs to be inserted between elem and gconv_conf_filename;
|
||||
elem already ends in a slash. */
|
||||
- filename = alloca (elem_len + sizeof (gconv_conf_filename));
|
||||
- __mempcpy (__mempcpy (filename, elem, elem_len),
|
||||
- gconv_conf_filename, sizeof (gconv_conf_filename));
|
||||
+ buf = alloca (BUF_LEN);
|
||||
+ char *cp = __mempcpy (__mempcpy (buf, elem, elem_len),
|
||||
+ gconv_conf_filename, sizeof (gconv_conf_filename));
|
||||
+
|
||||
+ /* Read the gconv-modules configuration file first. */
|
||||
+ read_conf_file (buf, elem, elem_len, &modules, &nmodules);
|
||||
+
|
||||
+ /* Next, see if there is a gconv-modules.d directory containing
|
||||
+ configuration files and if it is non-empty. */
|
||||
+ cp--;
|
||||
+ cp[0] = '.';
|
||||
+ cp[1] = 'd';
|
||||
+ cp[2] = '\0';
|
||||
+
|
||||
+ DIR *confdir = __opendir (buf);
|
||||
+ if (confdir != NULL)
|
||||
+ {
|
||||
+ struct dirent *ent;
|
||||
+ while ((ent = __readdir (confdir)) != NULL)
|
||||
+ {
|
||||
+ if (ent->d_type != DT_REG)
|
||||
+ continue;
|
||||
+
|
||||
+ size_t len = strlen (ent->d_name);
|
||||
+ const char *suffix = ".conf";
|
||||
|
||||
- /* Read the next configuration file. */
|
||||
- read_conf_file (filename, elem, elem_len, &modules, &nmodules);
|
||||
+ if (len > strlen (suffix)
|
||||
+ && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
|
||||
+ {
|
||||
+ /* LEN <= PATH_MAX so this alloca is not unbounded. */
|
||||
+ char *conf = alloca (BUF_LEN + len + 1);
|
||||
+ cp = stpcpy (conf, buf);
|
||||
+ sprintf (cp, "/%s", ent->d_name);
|
||||
+ read_conf_file (conf, elem, elem_len, &modules, &nmodules);
|
||||
+ }
|
||||
+ }
|
||||
+ __closedir (confdir);
|
||||
+ }
|
||||
}
|
||||
#endif
|
||||
|
179
SOURCES/glibc-rh1971664-4.patch
Normal file
179
SOURCES/glibc-rh1971664-4.patch
Normal file
@ -0,0 +1,179 @@
|
||||
commit fc5bfade69ca12d034967dc6b929dbe3dd715172
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Jun 7 14:22:20 2021 +0530
|
||||
|
||||
iconvdata: Move gconv-modules configuration to gconv-modules.conf
|
||||
|
||||
Move all gconv-modules configuration files to gconv-modules.conf.
|
||||
That is, the S390 extensions now become gconv-modules-s390.conf. Move
|
||||
both configuration files into gconv-modules.d.
|
||||
|
||||
Now GCONV_PATH/gconv-modules is read only for backward compatibility
|
||||
for third-party gconv modules directories.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
# Conflicts:
|
||||
# iconvdata/Makefile
|
||||
|
||||
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
|
||||
index 32656ad31d9b434b..fc403e8abe3cc11f 100644
|
||||
--- a/iconvdata/Makefile
|
||||
+++ b/iconvdata/Makefile
|
||||
@@ -136,10 +136,13 @@ charmaps = ../localedata/charmaps
|
||||
extra-modules-left := $(modules)
|
||||
include extra-module.mk
|
||||
|
||||
+gconv-modules = gconv-modules.conf
|
||||
+modpfx = $(objpfx)gconv-modules.d/
|
||||
|
||||
extra-objs += $(modules.so)
|
||||
install-others = $(addprefix $(inst_gconvdir)/, $(modules.so)) \
|
||||
- $(inst_gconvdir)/gconv-modules
|
||||
+ $(addprefix $(inst_gconvdir)/gconv-modules.d/, \
|
||||
+ $(gconv-modules))
|
||||
|
||||
# We can build the conversion tables for numerous charsets automatically.
|
||||
|
||||
@@ -181,7 +184,7 @@ generated += $(generated-modules:=.h) $(generated-modules:=.stmp) \
|
||||
iconv-test.out iconv-rules tst-loading.mtrace \
|
||||
mtrace-tst-loading.out tst-tables.out iconv-test.xxx
|
||||
ifdef objpfx
|
||||
-generated += gconv-modules
|
||||
+generated += $(addprefix gconv-modules.d/,$(gconv-modules))
|
||||
endif
|
||||
|
||||
# Rules to generate the headers.
|
||||
@@ -249,7 +252,8 @@ headers: $(addprefix $(objpfx), $(generated-modules:=.h))
|
||||
$(addprefix $(inst_gconvdir)/, $(modules.so)): \
|
||||
$(inst_gconvdir)/%: $(objpfx)% $(+force)
|
||||
$(do-install-program)
|
||||
-$(inst_gconvdir)/gconv-modules: $(objpfx)gconv-modules $(+force)
|
||||
+$(addprefix $(inst_gconvdir)/gconv-modules.d/, $(gconv-modules)): \
|
||||
+ $(inst_gconvdir)/gconv-modules.d/%: $(modpfx)% $(+force)
|
||||
$(do-install)
|
||||
ifeq (no,$(cross-compiling))
|
||||
# Update the $(prefix)/lib/gconv/gconv-modules.cache file. This is necessary
|
||||
@@ -297,29 +301,30 @@ $(objpfx)mtrace-tst-loading.out: $(objpfx)tst-loading.out
|
||||
$(common-objpfx)malloc/mtrace $(objpfx)tst-loading.mtrace > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
-$(objpfx)bug-iconv1.out: $(objpfx)gconv-modules \
|
||||
+$(objpfx)bug-iconv1.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)bug-iconv2.out: $(objpfx)gconv-modules \
|
||||
+$(objpfx)bug-iconv2.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
$(objpfx)bug-iconv3: $(libdl)
|
||||
-$(objpfx)bug-iconv3.out: $(objpfx)gconv-modules \
|
||||
+$(objpfx)bug-iconv3.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)bug-iconv5.out: $(objpfx)gconv-modules \
|
||||
+$(objpfx)bug-iconv5.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)tst-loading.out: $(objpfx)gconv-modules \
|
||||
+$(objpfx)tst-loading.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)tst-iconv4.out: $(objpfx)gconv-modules \
|
||||
+$(objpfx)tst-iconv4.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)tst-iconv7.out: $(objpfx)gconv-modules \
|
||||
+$(objpfx)tst-iconv7.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)bug-iconv10.out: $(objpfx)gconv-modules \
|
||||
+$(objpfx)bug-iconv10.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)bug-iconv12.out: $(objpfx)gconv-modules \
|
||||
+$(objpfx)bug-iconv12.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \
|
||||
+$(objpfx)bug-iconv14.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
|
||||
-$(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
|
||||
+$(objpfx)iconv-test.out: run-iconv-test.sh \
|
||||
+ $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so)) \
|
||||
$(common-objdir)/iconv/iconv_prog TESTS
|
||||
iconv_modules="$(modules)" \
|
||||
@@ -327,7 +332,8 @@ $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
|
||||
'$(run-program-env)' > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
-$(objpfx)tst-tables.out: tst-tables.sh $(objpfx)gconv-modules \
|
||||
+$(objpfx)tst-tables.out: tst-tables.sh \
|
||||
+ $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so)) \
|
||||
$(objpfx)tst-table-from $(objpfx)tst-table-to
|
||||
$(SHELL) $< $(common-objpfx) $(common-objpfx)iconvdata/ \
|
||||
@@ -340,5 +346,8 @@ do-tests-clean common-mostlyclean: tst-tables-clean
|
||||
tst-tables-clean:
|
||||
-rm -f $(objpfx)tst-*.table $(objpfx)tst-EUC-TW.irreversible
|
||||
|
||||
-$(objpfx)gconv-modules: gconv-modules
|
||||
- cat $(sysdeps-gconv-modules) $^ > $@
|
||||
+$(modpfx):
|
||||
+ mkdir -p $@
|
||||
+
|
||||
+$(modpfx)%: % $(modpfx)
|
||||
+ cp $< $@
|
||||
diff --git a/iconvdata/gconv-modules b/iconvdata/gconv-modules.conf
|
||||
similarity index 100%
|
||||
rename from iconvdata/gconv-modules
|
||||
rename to iconvdata/gconv-modules.conf
|
||||
diff --git a/localedata/Makefile b/localedata/Makefile
|
||||
index 14fcc37fed21e740..a5ca7a31f43d50c3 100644
|
||||
--- a/localedata/Makefile
|
||||
+++ b/localedata/Makefile
|
||||
@@ -179,7 +179,7 @@ install-others := $(addprefix $(inst_i18ndir)/, \
|
||||
$(locales))
|
||||
endif
|
||||
|
||||
-tests: $(objdir)/iconvdata/gconv-modules
|
||||
+tests: $(objdir)/iconvdata/gconv-modules.d/gconv-modules.conf
|
||||
|
||||
tests-static += tst-langinfo-newlocale-static tst-langinfo-setlocale-static
|
||||
|
||||
@@ -442,5 +442,5 @@ $(objpfx)mtrace-tst-leaks.out: $(objpfx)tst-leaks.out
|
||||
bug-setlocale1-ENV-only = LOCPATH=$(objpfx) LC_CTYPE=de_DE.UTF-8
|
||||
bug-setlocale1-static-ENV-only = $(bug-setlocale1-ENV-only)
|
||||
|
||||
-$(objdir)/iconvdata/gconv-modules:
|
||||
+$(objdir)/iconvdata/gconv-modules.d/gconv-modules.conf:
|
||||
$(MAKE) -C ../iconvdata subdir=iconvdata $@
|
||||
diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
|
||||
index 8bc82e523f9049db..5c8e1170b4d799ba 100644
|
||||
--- a/sysdeps/s390/Makefile
|
||||
+++ b/sysdeps/s390/Makefile
|
||||
@@ -21,13 +21,25 @@ lib := iconvdata
|
||||
include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
|
||||
|
||||
extra-objs += $(addsuffix .so, $(s390x-iconv-modules))
|
||||
-install-others += $(patsubst %, $(inst_gconvdir)/%.so, $(s390x-iconv-modules))
|
||||
+install-others += $(patsubst %, $(inst_gconvdir)/%.so, \
|
||||
+ $(s390x-iconv-modules)) \
|
||||
+ $(inst_gconvdir)/gconv-modules.d/gconv-modules-s390.conf
|
||||
|
||||
$(patsubst %, $(inst_gconvdir)/%.so, $(s390x-iconv-modules)) : \
|
||||
$(inst_gconvdir)/%.so: $(objpfx)%.so $(+force)
|
||||
$(do-install-program)
|
||||
|
||||
-sysdeps-gconv-modules = ../sysdeps/s390/gconv-modules
|
||||
+ifdef objpfx
|
||||
+generated += gconv-modules.d/gconv-modules-s390.conf
|
||||
+endif
|
||||
+
|
||||
+$(inst_gconvdir)/gconv-modules.d/gconv-modules-s390.conf: \
|
||||
+ $(modpfx)gconv-modules-s390.conf $(+force)
|
||||
+ $(do-install)
|
||||
+
|
||||
+$(modpfx)gconv-modules-s390.conf: ../sysdeps/s390/gconv-modules-s390.conf \
|
||||
+ $(modpfx)
|
||||
+ cp $< $@
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),string)
|
||||
diff --git a/sysdeps/s390/gconv-modules b/sysdeps/s390/gconv-modules-s390.conf
|
||||
similarity index 100%
|
||||
rename from sysdeps/s390/gconv-modules
|
||||
rename to sysdeps/s390/gconv-modules-s390.conf
|
3825
SOURCES/glibc-rh1971664-5.patch
Normal file
3825
SOURCES/glibc-rh1971664-5.patch
Normal file
File diff suppressed because it is too large
Load Diff
137
SOURCES/glibc-rh1971664-6.patch
Normal file
137
SOURCES/glibc-rh1971664-6.patch
Normal file
@ -0,0 +1,137 @@
|
||||
commit 06a1b794073c4d6adbfb2e4b11339985a14d7a00
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Jun 14 11:09:56 2021 +0530
|
||||
|
||||
Reinstate gconv-modules as the default configuration file
|
||||
|
||||
Reinstate gconv-modules as the main file so that the configuration
|
||||
files in gconv-modules.d/ become add-on configuration. With this, the
|
||||
effective user visible change is that GCONV_PATH can now have
|
||||
supplementary configuration in GCONV_PATH/gconv-modules.d/ in addition
|
||||
to the main GCONV_PATH/gconv-modules file.
|
||||
|
||||
# Conflicts:
|
||||
# iconvdata/Makefile
|
||||
|
||||
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
|
||||
index d682a98b5c4a8003..95e5fb8f722a513b 100644
|
||||
--- a/iconvdata/Makefile
|
||||
+++ b/iconvdata/Makefile
|
||||
@@ -136,13 +136,12 @@ charmaps = ../localedata/charmaps
|
||||
extra-modules-left := $(modules)
|
||||
include extra-module.mk
|
||||
|
||||
-gconv-modules = gconv-modules.conf gconv-modules-extra.conf
|
||||
+gconv-modules = gconv-modules gconv-modules.d/gconv-modules-extra.conf
|
||||
modpfx = $(objpfx)gconv-modules.d/
|
||||
|
||||
extra-objs += $(modules.so)
|
||||
install-others = $(addprefix $(inst_gconvdir)/, $(modules.so)) \
|
||||
- $(addprefix $(inst_gconvdir)/gconv-modules.d/, \
|
||||
- $(gconv-modules))
|
||||
+ $(addprefix $(inst_gconvdir)/, $(gconv-modules))
|
||||
|
||||
# We can build the conversion tables for numerous charsets automatically.
|
||||
|
||||
@@ -184,7 +183,7 @@ generated += $(generated-modules:=.h) $(generated-modules:=.stmp) \
|
||||
iconv-test.out iconv-rules tst-loading.mtrace \
|
||||
mtrace-tst-loading.out tst-tables.out iconv-test.xxx
|
||||
ifdef objpfx
|
||||
-generated += $(addprefix gconv-modules.d/,$(gconv-modules))
|
||||
+generated += $(gconv-modules)
|
||||
endif
|
||||
|
||||
# Rules to generate the headers.
|
||||
@@ -252,8 +251,8 @@ headers: $(addprefix $(objpfx), $(generated-modules:=.h))
|
||||
$(addprefix $(inst_gconvdir)/, $(modules.so)): \
|
||||
$(inst_gconvdir)/%: $(objpfx)% $(+force)
|
||||
$(do-install-program)
|
||||
-$(addprefix $(inst_gconvdir)/gconv-modules.d/, $(gconv-modules)): \
|
||||
- $(inst_gconvdir)/gconv-modules.d/%: $(modpfx)% $(+force)
|
||||
+$(addprefix $(inst_gconvdir)/, $(gconv-modules)): \
|
||||
+ $(inst_gconvdir)/%: $(objpfx)% $(+force)
|
||||
$(do-install)
|
||||
ifeq (no,$(cross-compiling))
|
||||
# Update the $(prefix)/lib/gconv/gconv-modules.cache file. This is necessary
|
||||
@@ -301,30 +300,30 @@ $(objpfx)mtrace-tst-loading.out: $(objpfx)tst-loading.out
|
||||
$(common-objpfx)malloc/mtrace $(objpfx)tst-loading.mtrace > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
-$(objpfx)bug-iconv1.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+$(objpfx)bug-iconv1.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)bug-iconv2.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+$(objpfx)bug-iconv2.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
$(objpfx)bug-iconv3: $(libdl)
|
||||
-$(objpfx)bug-iconv3.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+$(objpfx)bug-iconv3.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)bug-iconv5.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+$(objpfx)bug-iconv5.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)tst-loading.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+$(objpfx)tst-loading.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)tst-iconv4.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+$(objpfx)tst-iconv4.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)tst-iconv7.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+$(objpfx)tst-iconv7.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)bug-iconv10.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+$(objpfx)bug-iconv10.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)bug-iconv12.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+$(objpfx)bug-iconv12.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
-$(objpfx)bug-iconv14.out: $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+$(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
|
||||
$(objpfx)iconv-test.out: run-iconv-test.sh \
|
||||
- $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+ $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so)) \
|
||||
$(common-objdir)/iconv/iconv_prog TESTS
|
||||
iconv_modules="$(modules)" \
|
||||
@@ -333,7 +332,7 @@ $(objpfx)iconv-test.out: run-iconv-test.sh \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-tables.out: tst-tables.sh \
|
||||
- $(addprefix $(modpfx), $(gconv-modules)) \
|
||||
+ $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so)) \
|
||||
$(objpfx)tst-table-from $(objpfx)tst-table-to
|
||||
$(SHELL) $< $(common-objpfx) $(common-objpfx)iconvdata/ \
|
||||
@@ -351,3 +350,6 @@ $(modpfx):
|
||||
|
||||
$(modpfx)%: % $(modpfx)
|
||||
cp $< $@
|
||||
+
|
||||
+$(objpfx)gconv-modules: gconv-modules
|
||||
+ cp $^ $@
|
||||
diff --git a/iconvdata/gconv-modules.conf b/iconvdata/gconv-modules
|
||||
similarity index 100%
|
||||
rename from iconvdata/gconv-modules.conf
|
||||
rename to iconvdata/gconv-modules
|
||||
diff --git a/localedata/Makefile b/localedata/Makefile
|
||||
index a5ca7a31f43d50c3..14fcc37fed21e740 100644
|
||||
--- a/localedata/Makefile
|
||||
+++ b/localedata/Makefile
|
||||
@@ -179,7 +179,7 @@ install-others := $(addprefix $(inst_i18ndir)/, \
|
||||
$(locales))
|
||||
endif
|
||||
|
||||
-tests: $(objdir)/iconvdata/gconv-modules.d/gconv-modules.conf
|
||||
+tests: $(objdir)/iconvdata/gconv-modules
|
||||
|
||||
tests-static += tst-langinfo-newlocale-static tst-langinfo-setlocale-static
|
||||
|
||||
@@ -442,5 +442,5 @@ $(objpfx)mtrace-tst-leaks.out: $(objpfx)tst-leaks.out
|
||||
bug-setlocale1-ENV-only = LOCPATH=$(objpfx) LC_CTYPE=de_DE.UTF-8
|
||||
bug-setlocale1-static-ENV-only = $(bug-setlocale1-ENV-only)
|
||||
|
||||
-$(objdir)/iconvdata/gconv-modules.d/gconv-modules.conf:
|
||||
+$(objdir)/iconvdata/gconv-modules:
|
||||
$(MAKE) -C ../iconvdata subdir=iconvdata $@
|
107
SOURCES/glibc-rh1971664-7.patch
Normal file
107
SOURCES/glibc-rh1971664-7.patch
Normal file
@ -0,0 +1,107 @@
|
||||
commit e3217c7fd9e67aa2d53700bb1da9a966e73b9684
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Thu Jun 10 00:41:35 2021 +0530
|
||||
|
||||
iconv: Remove alloca use in gconv-modules configuration parsing
|
||||
|
||||
The alloca sizes ought to be constrained to PATH_MAX, but replace them
|
||||
with dynamic allocation to be safe. A static PATH_MAX array would
|
||||
have worked too but Hurd does not have PATH_MAX and the code path is
|
||||
not hot enough to micro-optimise this allocation. Revisit if any of
|
||||
those realities change.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
|
||||
index 8eb981fca7cee36a..3099bf192adce711 100644
|
||||
--- a/iconv/gconv_conf.c
|
||||
+++ b/iconv/gconv_conf.c
|
||||
@@ -557,15 +557,15 @@ __gconv_read_conf (void)
|
||||
|
||||
for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt)
|
||||
{
|
||||
-#define BUF_LEN elem_len + sizeof (gconv_conf_dirname)
|
||||
-
|
||||
const char *elem = __gconv_path_elem[cnt].name;
|
||||
size_t elem_len = __gconv_path_elem[cnt].len;
|
||||
- char *buf;
|
||||
|
||||
/* No slash needs to be inserted between elem and gconv_conf_filename;
|
||||
elem already ends in a slash. */
|
||||
- buf = alloca (BUF_LEN);
|
||||
+ char *buf = malloc (elem_len + sizeof (gconv_conf_dirname));
|
||||
+ if (buf == NULL)
|
||||
+ continue;
|
||||
+
|
||||
char *cp = __mempcpy (__mempcpy (buf, elem, elem_len),
|
||||
gconv_conf_filename, sizeof (gconv_conf_filename));
|
||||
|
||||
@@ -594,15 +594,16 @@ __gconv_read_conf (void)
|
||||
if (len > strlen (suffix)
|
||||
&& strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
|
||||
{
|
||||
- /* LEN <= PATH_MAX so this alloca is not unbounded. */
|
||||
- char *conf = alloca (BUF_LEN + len + 1);
|
||||
- cp = stpcpy (conf, buf);
|
||||
- sprintf (cp, "/%s", ent->d_name);
|
||||
+ char *conf;
|
||||
+ if (__asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
|
||||
+ continue;
|
||||
read_conf_file (conf, elem, elem_len, &modules, &nmodules);
|
||||
+ free (conf);
|
||||
}
|
||||
}
|
||||
__closedir (confdir);
|
||||
}
|
||||
+ free (buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
|
||||
index fafc686ae25fb5c1..2f9d5f45ad3a8159 100644
|
||||
--- a/iconv/iconvconfig.c
|
||||
+++ b/iconv/iconvconfig.c
|
||||
@@ -712,7 +712,6 @@ handle_file (const char *dir, const char *infile)
|
||||
static int
|
||||
handle_dir (const char *dir)
|
||||
{
|
||||
-#define BUF_LEN prefix_len + dirlen + sizeof "gconv-modules.d"
|
||||
char *cp;
|
||||
size_t dirlen = strlen (dir);
|
||||
bool found = false;
|
||||
@@ -726,7 +725,10 @@ handle_dir (const char *dir)
|
||||
}
|
||||
|
||||
/* First, look for a gconv-modules file. */
|
||||
- char buf[BUF_LEN];
|
||||
+ char *buf = malloc (prefix_len + dirlen + sizeof "gconv-modules.d");
|
||||
+ if (buf == NULL)
|
||||
+ goto out;
|
||||
+
|
||||
cp = buf;
|
||||
if (dir[0] == '/')
|
||||
cp = mempcpy (cp, prefix, prefix_len);
|
||||
@@ -756,16 +758,19 @@ handle_dir (const char *dir)
|
||||
if (len > strlen (suffix)
|
||||
&& strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
|
||||
{
|
||||
- /* LEN <= PATH_MAX so this alloca is not unbounded. */
|
||||
- char *conf = alloca (BUF_LEN + len + 1);
|
||||
- cp = stpcpy (conf, buf);
|
||||
- sprintf (cp, "/%s", ent->d_name);
|
||||
+ char *conf;
|
||||
+ if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
|
||||
+ continue;
|
||||
found |= handle_file (dir, conf);
|
||||
+ free (conf);
|
||||
}
|
||||
}
|
||||
closedir (confdir);
|
||||
}
|
||||
|
||||
+ free (buf);
|
||||
+
|
||||
+out:
|
||||
if (!found)
|
||||
{
|
||||
error (0, errno, "failed to open gconv configuration files in `%s'",
|
113
SOURCES/glibc-rh1971664-8.patch
Normal file
113
SOURCES/glibc-rh1971664-8.patch
Normal file
@ -0,0 +1,113 @@
|
||||
commit 23e15ea1ae80ec2120afdf643691359644cf2873
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Thu Jun 10 09:51:50 2021 +0530
|
||||
|
||||
gconv_conf: Remove unused variables
|
||||
|
||||
The modules and nmodules parameters passed to add_modules, add_alias,
|
||||
etc. are not used and are hence unnecessary. Remove them so that
|
||||
their signatures match the functions in iconvconfig.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
Reviewed-by: Andreas Schwab <schwab@linux-m68k.org>
|
||||
|
||||
diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
|
||||
index 3099bf192adce711..dc12ce24844474cc 100644
|
||||
--- a/iconv/gconv_conf.c
|
||||
+++ b/iconv/gconv_conf.c
|
||||
@@ -125,7 +125,7 @@ detect_conflict (const char *alias)
|
||||
|
||||
/* The actual code to add aliases. */
|
||||
static void
|
||||
-add_alias2 (const char *from, const char *to, const char *wp, void *modules)
|
||||
+add_alias2 (const char *from, const char *to, const char *wp)
|
||||
{
|
||||
/* Test whether this alias conflicts with any available module. */
|
||||
if (detect_conflict (from))
|
||||
@@ -154,7 +154,7 @@ add_alias2 (const char *from, const char *to, const char *wp, void *modules)
|
||||
|
||||
/* Add new alias. */
|
||||
static void
|
||||
-add_alias (char *rp, void *modules)
|
||||
+add_alias (char *rp)
|
||||
{
|
||||
/* We now expect two more string. The strings are normalized
|
||||
(converted to UPPER case) and strored in the alias database. */
|
||||
@@ -179,7 +179,7 @@ add_alias (char *rp, void *modules)
|
||||
return;
|
||||
*wp++ = '\0';
|
||||
|
||||
- add_alias2 (from, to, wp, modules);
|
||||
+ add_alias2 (from, to, wp);
|
||||
}
|
||||
|
||||
|
||||
@@ -243,8 +243,7 @@ insert_module (struct gconv_module *newp, int tobefreed)
|
||||
|
||||
/* Add new module. */
|
||||
static void
|
||||
-add_module (char *rp, const char *directory, size_t dir_len, void **modules,
|
||||
- size_t *nmodules, int modcounter)
|
||||
+add_module (char *rp, const char *directory, size_t dir_len, int modcounter)
|
||||
{
|
||||
/* We expect now
|
||||
1. `from' name
|
||||
@@ -357,8 +356,7 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
|
||||
|
||||
/* Read the next configuration file. */
|
||||
static void
|
||||
-read_conf_file (const char *filename, const char *directory, size_t dir_len,
|
||||
- void **modules, size_t *nmodules)
|
||||
+read_conf_file (const char *filename, const char *directory, size_t dir_len)
|
||||
{
|
||||
/* Note the file is opened with cancellation in the I/O functions
|
||||
disabled. */
|
||||
@@ -408,10 +406,10 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
|
||||
|
||||
if (rp - word == sizeof ("alias") - 1
|
||||
&& memcmp (word, "alias", sizeof ("alias") - 1) == 0)
|
||||
- add_alias (rp, *modules);
|
||||
+ add_alias (rp);
|
||||
else if (rp - word == sizeof ("module") - 1
|
||||
&& memcmp (word, "module", sizeof ("module") - 1) == 0)
|
||||
- add_module (rp, directory, dir_len, modules, nmodules, modcounter++);
|
||||
+ add_module (rp, directory, dir_len, modcounter++);
|
||||
/* else */
|
||||
/* Otherwise ignore the line. */
|
||||
}
|
||||
@@ -537,8 +535,6 @@ void
|
||||
attribute_hidden
|
||||
__gconv_read_conf (void)
|
||||
{
|
||||
- void *modules = NULL;
|
||||
- size_t nmodules = 0;
|
||||
int save_errno = errno;
|
||||
size_t cnt;
|
||||
|
||||
@@ -570,7 +566,7 @@ __gconv_read_conf (void)
|
||||
gconv_conf_filename, sizeof (gconv_conf_filename));
|
||||
|
||||
/* Read the gconv-modules configuration file first. */
|
||||
- read_conf_file (buf, elem, elem_len, &modules, &nmodules);
|
||||
+ read_conf_file (buf, elem, elem_len);
|
||||
|
||||
/* Next, see if there is a gconv-modules.d directory containing
|
||||
configuration files and if it is non-empty. */
|
||||
@@ -597,7 +593,7 @@ __gconv_read_conf (void)
|
||||
char *conf;
|
||||
if (__asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
|
||||
continue;
|
||||
- read_conf_file (conf, elem, elem_len, &modules, &nmodules);
|
||||
+ read_conf_file (conf, elem, elem_len);
|
||||
free (conf);
|
||||
}
|
||||
}
|
||||
@@ -631,7 +627,7 @@ __gconv_read_conf (void)
|
||||
const char *to = __rawmemchr (from, '\0') + 1;
|
||||
cp = __rawmemchr (to, '\0') + 1;
|
||||
|
||||
- add_alias2 (from, to, cp, modules);
|
||||
+ add_alias2 (from, to, cp);
|
||||
}
|
||||
while (*cp != '\0');
|
||||
|
360
SOURCES/glibc-rh1971664-9.patch
Normal file
360
SOURCES/glibc-rh1971664-9.patch
Normal file
@ -0,0 +1,360 @@
|
||||
commit d8e8097f3be5b3c49fc741fa19e1da0b0431384c
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Thu Jun 10 14:07:27 2021 +0530
|
||||
|
||||
gconv_conf: Split out configuration file processing
|
||||
|
||||
Split configuration file processing into a separate header file and
|
||||
include it. Macroize all calls that need to go through internal
|
||||
interfaces so that iconvconfig can also use them.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
# Conflicts:
|
||||
# iconv/gconv_conf.c
|
||||
|
||||
diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
|
||||
index dc12ce24844474cc..ce64faa928dc1c52 100644
|
||||
--- a/iconv/gconv_conf.c
|
||||
+++ b/iconv/gconv_conf.c
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
-#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
@@ -31,11 +30,10 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
-#include <sys/types.h>
|
||||
|
||||
#include <libc-lock.h>
|
||||
#include <gconv_int.h>
|
||||
-
|
||||
+#include <gconv_parseconfdir.h>
|
||||
|
||||
/* This is the default path where we look for module lists. */
|
||||
static const char default_gconv_path[] = GCONV_PATH;
|
||||
@@ -49,11 +47,6 @@ size_t __gconv_max_path_elem_len;
|
||||
/* We use the following struct if we couldn't allocate memory. */
|
||||
static const struct path_elem empty_path_elem = { NULL, 0 };
|
||||
|
||||
-/* Name of the file containing the module information in the directories
|
||||
- along the path. */
|
||||
-static const char gconv_conf_filename[] = "gconv-modules";
|
||||
-static const char gconv_conf_dirname[] = "gconv-modules.d";
|
||||
-
|
||||
/* Filename extension for the modules. */
|
||||
#ifndef MODULE_EXT
|
||||
# define MODULE_EXT ".so"
|
||||
@@ -92,9 +85,6 @@ static const char builtin_aliases[] =
|
||||
#undef BUILTIN_ALIAS
|
||||
};
|
||||
|
||||
-#include <libio/libioP.h>
|
||||
-#define __getdelim(line, len, c, fp) _IO_getdelim (line, len, c, fp)
|
||||
-
|
||||
|
||||
/* Value of the GCONV_PATH environment variable. */
|
||||
const char *__gconv_path_envvar;
|
||||
@@ -354,72 +344,6 @@ add_module (char *rp, const char *directory, size_t dir_len, int modcounter)
|
||||
}
|
||||
|
||||
|
||||
-/* Read the next configuration file. */
|
||||
-static void
|
||||
-read_conf_file (const char *filename, const char *directory, size_t dir_len)
|
||||
-{
|
||||
- /* Note the file is opened with cancellation in the I/O functions
|
||||
- disabled. */
|
||||
- FILE *fp = fopen (filename, "rce");
|
||||
- char *line = NULL;
|
||||
- size_t line_len = 0;
|
||||
- static int modcounter;
|
||||
-
|
||||
- /* Don't complain if a file is not present or readable, simply silently
|
||||
- ignore it. */
|
||||
- if (fp == NULL)
|
||||
- return;
|
||||
-
|
||||
- /* No threads reading from this stream. */
|
||||
- __fsetlocking (fp, FSETLOCKING_BYCALLER);
|
||||
-
|
||||
- /* Process the known entries of the file. Comments start with `#' and
|
||||
- end with the end of the line. Empty lines are ignored. */
|
||||
- while (!__feof_unlocked (fp))
|
||||
- {
|
||||
- char *rp, *endp, *word;
|
||||
- ssize_t n = __getdelim (&line, &line_len, '\n', fp);
|
||||
- if (n < 0)
|
||||
- /* An error occurred. */
|
||||
- break;
|
||||
-
|
||||
- rp = line;
|
||||
- /* Terminate the line (excluding comments or newline) by an NUL byte
|
||||
- to simplify the following code. */
|
||||
- endp = strchr (rp, '#');
|
||||
- if (endp != NULL)
|
||||
- *endp = '\0';
|
||||
- else
|
||||
- if (rp[n - 1] == '\n')
|
||||
- rp[n - 1] = '\0';
|
||||
-
|
||||
- while (__isspace_l (*rp, _nl_C_locobj_ptr))
|
||||
- ++rp;
|
||||
-
|
||||
- /* If this is an empty line go on with the next one. */
|
||||
- if (rp == endp)
|
||||
- continue;
|
||||
-
|
||||
- word = rp;
|
||||
- while (*rp != '\0' && !__isspace_l (*rp, _nl_C_locobj_ptr))
|
||||
- ++rp;
|
||||
-
|
||||
- if (rp - word == sizeof ("alias") - 1
|
||||
- && memcmp (word, "alias", sizeof ("alias") - 1) == 0)
|
||||
- add_alias (rp);
|
||||
- else if (rp - word == sizeof ("module") - 1
|
||||
- && memcmp (word, "module", sizeof ("module") - 1) == 0)
|
||||
- add_module (rp, directory, dir_len, modcounter++);
|
||||
- /* else */
|
||||
- /* Otherwise ignore the line. */
|
||||
- }
|
||||
-
|
||||
- free (line);
|
||||
-
|
||||
- fclose (fp);
|
||||
-}
|
||||
-
|
||||
-
|
||||
/* Determine the directories we are looking for data in. */
|
||||
void
|
||||
__gconv_get_path (void)
|
||||
@@ -552,55 +476,8 @@ __gconv_read_conf (void)
|
||||
__gconv_get_path ();
|
||||
|
||||
for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt)
|
||||
- {
|
||||
- const char *elem = __gconv_path_elem[cnt].name;
|
||||
- size_t elem_len = __gconv_path_elem[cnt].len;
|
||||
-
|
||||
- /* No slash needs to be inserted between elem and gconv_conf_filename;
|
||||
- elem already ends in a slash. */
|
||||
- char *buf = malloc (elem_len + sizeof (gconv_conf_dirname));
|
||||
- if (buf == NULL)
|
||||
- continue;
|
||||
-
|
||||
- char *cp = __mempcpy (__mempcpy (buf, elem, elem_len),
|
||||
- gconv_conf_filename, sizeof (gconv_conf_filename));
|
||||
-
|
||||
- /* Read the gconv-modules configuration file first. */
|
||||
- read_conf_file (buf, elem, elem_len);
|
||||
-
|
||||
- /* Next, see if there is a gconv-modules.d directory containing
|
||||
- configuration files and if it is non-empty. */
|
||||
- cp--;
|
||||
- cp[0] = '.';
|
||||
- cp[1] = 'd';
|
||||
- cp[2] = '\0';
|
||||
-
|
||||
- DIR *confdir = __opendir (buf);
|
||||
- if (confdir != NULL)
|
||||
- {
|
||||
- struct dirent *ent;
|
||||
- while ((ent = __readdir (confdir)) != NULL)
|
||||
- {
|
||||
- if (ent->d_type != DT_REG)
|
||||
- continue;
|
||||
-
|
||||
- size_t len = strlen (ent->d_name);
|
||||
- const char *suffix = ".conf";
|
||||
-
|
||||
- if (len > strlen (suffix)
|
||||
- && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
|
||||
- {
|
||||
- char *conf;
|
||||
- if (__asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
|
||||
- continue;
|
||||
- read_conf_file (conf, elem, elem_len);
|
||||
- free (conf);
|
||||
- }
|
||||
- }
|
||||
- __closedir (confdir);
|
||||
- }
|
||||
- free (buf);
|
||||
- }
|
||||
+ gconv_parseconfdir (__gconv_path_elem[cnt].name,
|
||||
+ __gconv_path_elem[cnt].len);
|
||||
#endif
|
||||
|
||||
/* Add the internal modules. */
|
||||
diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..3d4d58d4be10a250
|
||||
--- /dev/null
|
||||
+++ b/iconv/gconv_parseconfdir.h
|
||||
@@ -0,0 +1,161 @@
|
||||
+/* Handle configuration data.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <dirent.h>
|
||||
+#include <libc-symbols.h>
|
||||
+#include <locale.h>
|
||||
+#include <sys/types.h>
|
||||
+
|
||||
+#if IS_IN (libc)
|
||||
+# include <libio/libioP.h>
|
||||
+# define __getdelim(line, len, c, fp) _IO_getdelim (line, len, c, fp)
|
||||
+
|
||||
+# undef isspace
|
||||
+# define isspace(__c) __isspace_l ((__c), _nl_C_locobj_ptr)
|
||||
+# define asprintf __asprintf
|
||||
+# define opendir __opendir
|
||||
+# define readdir __readdir
|
||||
+# define closedir __closedir
|
||||
+# define mempcpy __mempcpy
|
||||
+#endif
|
||||
+
|
||||
+/* Name of the file containing the module information in the directories
|
||||
+ along the path. */
|
||||
+static const char gconv_conf_filename[] = "gconv-modules";
|
||||
+static const char gconv_conf_dirname[] = "gconv-modules.d";
|
||||
+
|
||||
+static void add_alias (char *);
|
||||
+static void add_module (char *, const char *, size_t, int);
|
||||
+
|
||||
+/* Read the next configuration file. */
|
||||
+static bool
|
||||
+read_conf_file (const char *filename, const char *directory, size_t dir_len)
|
||||
+{
|
||||
+ /* Note the file is opened with cancellation in the I/O functions
|
||||
+ disabled. */
|
||||
+ FILE *fp = fopen (filename, "rce");
|
||||
+ char *line = NULL;
|
||||
+ size_t line_len = 0;
|
||||
+ static int modcounter;
|
||||
+
|
||||
+ /* Don't complain if a file is not present or readable, simply silently
|
||||
+ ignore it. */
|
||||
+ if (fp == NULL)
|
||||
+ return false;
|
||||
+
|
||||
+ /* No threads reading from this stream. */
|
||||
+ __fsetlocking (fp, FSETLOCKING_BYCALLER);
|
||||
+
|
||||
+ /* Process the known entries of the file. Comments start with `#' and
|
||||
+ end with the end of the line. Empty lines are ignored. */
|
||||
+ while (!__feof_unlocked (fp))
|
||||
+ {
|
||||
+ char *rp, *endp, *word;
|
||||
+ ssize_t n = __getdelim (&line, &line_len, '\n', fp);
|
||||
+ if (n < 0)
|
||||
+ /* An error occurred. */
|
||||
+ break;
|
||||
+
|
||||
+ rp = line;
|
||||
+ /* Terminate the line (excluding comments or newline) by an NUL byte
|
||||
+ to simplify the following code. */
|
||||
+ endp = strchr (rp, '#');
|
||||
+ if (endp != NULL)
|
||||
+ *endp = '\0';
|
||||
+ else
|
||||
+ if (rp[n - 1] == '\n')
|
||||
+ rp[n - 1] = '\0';
|
||||
+
|
||||
+ while (isspace (*rp))
|
||||
+ ++rp;
|
||||
+
|
||||
+ /* If this is an empty line go on with the next one. */
|
||||
+ if (rp == endp)
|
||||
+ continue;
|
||||
+
|
||||
+ word = rp;
|
||||
+ while (*rp != '\0' && !isspace (*rp))
|
||||
+ ++rp;
|
||||
+
|
||||
+ if (rp - word == sizeof ("alias") - 1
|
||||
+ && memcmp (word, "alias", sizeof ("alias") - 1) == 0)
|
||||
+ add_alias (rp);
|
||||
+ else if (rp - word == sizeof ("module") - 1
|
||||
+ && memcmp (word, "module", sizeof ("module") - 1) == 0)
|
||||
+ add_module (rp, directory, dir_len, modcounter++);
|
||||
+ /* else */
|
||||
+ /* Otherwise ignore the line. */
|
||||
+ }
|
||||
+
|
||||
+ free (line);
|
||||
+
|
||||
+ fclose (fp);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static __always_inline bool
|
||||
+gconv_parseconfdir (const char *dir, size_t dir_len)
|
||||
+{
|
||||
+ /* No slash needs to be inserted between dir and gconv_conf_filename;
|
||||
+ dir already ends in a slash. */
|
||||
+ char *buf = malloc (dir_len + sizeof (gconv_conf_dirname));
|
||||
+ bool found = false;
|
||||
+
|
||||
+ if (buf == NULL)
|
||||
+ return false;
|
||||
+
|
||||
+ char *cp = mempcpy (mempcpy (buf, dir, dir_len), gconv_conf_filename,
|
||||
+ sizeof (gconv_conf_filename));
|
||||
+
|
||||
+ /* Read the gconv-modules configuration file first. */
|
||||
+ found = read_conf_file (buf, dir, dir_len);
|
||||
+
|
||||
+ /* Next, see if there is a gconv-modules.d directory containing
|
||||
+ configuration files and if it is non-empty. */
|
||||
+ cp--;
|
||||
+ cp[0] = '.';
|
||||
+ cp[1] = 'd';
|
||||
+ cp[2] = '\0';
|
||||
+
|
||||
+ DIR *confdir = opendir (buf);
|
||||
+ if (confdir != NULL)
|
||||
+ {
|
||||
+ struct dirent *ent;
|
||||
+ while ((ent = readdir (confdir)) != NULL)
|
||||
+ {
|
||||
+ if (ent->d_type != DT_REG)
|
||||
+ continue;
|
||||
+
|
||||
+ size_t len = strlen (ent->d_name);
|
||||
+ const char *suffix = ".conf";
|
||||
+
|
||||
+ if (len > strlen (suffix)
|
||||
+ && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
|
||||
+ {
|
||||
+ char *conf;
|
||||
+ if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
|
||||
+ continue;
|
||||
+ found |= read_conf_file (conf, dir, dir_len);
|
||||
+ free (conf);
|
||||
+ }
|
||||
+ }
|
||||
+ closedir (confdir);
|
||||
+ }
|
||||
+ free (buf);
|
||||
+ return found;
|
||||
+}
|
33
SOURCES/glibc-rh1977614.patch
Normal file
33
SOURCES/glibc-rh1977614.patch
Normal file
@ -0,0 +1,33 @@
|
||||
commit dfec225ee1972488bb48a8b67a2c4a13010c334a
|
||||
Author: JeffyChen <jeffy.chen@rock-chips.com>
|
||||
Date: Fri Jul 2 17:39:24 2021 +0200
|
||||
|
||||
malloc: Initiate tcache shutdown even without allocations [BZ #28028]
|
||||
|
||||
After commit 1e26d35193efbb29239c710a4c46a64708643320 ("malloc: Fix
|
||||
tcache leak after thread destruction [BZ #22111]"),
|
||||
tcache_shutting_down is still not early enough. When we detach a
|
||||
thread with no tcache allocated, tcache_shutting_down would still be
|
||||
false.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index 00a37f218c0ab3b2..61f7bdc76064c340 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -2960,12 +2960,13 @@ tcache_thread_shutdown (void)
|
||||
int i;
|
||||
tcache_perthread_struct *tcache_tmp = tcache;
|
||||
|
||||
+ tcache_shutting_down = true;
|
||||
+
|
||||
if (!tcache)
|
||||
return;
|
||||
|
||||
/* Disable the tcache and prevent it from being reinitialized. */
|
||||
tcache = NULL;
|
||||
- tcache_shutting_down = true;
|
||||
|
||||
/* Free all of the entries and the tcache itself back to the arena
|
||||
heap for coalescing. */
|
306
SOURCES/glibc-rh1983203-1.patch
Normal file
306
SOURCES/glibc-rh1983203-1.patch
Normal file
@ -0,0 +1,306 @@
|
||||
commit a55e2da2702e235fa0ae66a116d304d1bffc060a
|
||||
Author: Lucas A. M. Magalhaes <lamm@linux.ibm.com>
|
||||
Date: Thu May 6 17:01:52 2021 -0300
|
||||
|
||||
powerpc: Optimized memcmp for power10
|
||||
|
||||
This patch was based on the __memcmp_power8 and the recent
|
||||
__strlen_power10.
|
||||
|
||||
Improvements from __memcmp_power8:
|
||||
|
||||
1. Don't need alignment code.
|
||||
|
||||
On POWER10 lxvp and lxvl do not generate alignment interrupts, so
|
||||
they are safe for use on caching-inhibited memory. Notice that the
|
||||
comparison on the main loop will wait for both VSR to be ready.
|
||||
Therefore aligning one of the input address does not improve
|
||||
performance. In order to align both registers a vperm is necessary
|
||||
which add too much overhead.
|
||||
|
||||
2. Uses new POWER10 instructions
|
||||
|
||||
This code uses lxvp to decrease contention on load by loading 32 bytes
|
||||
per instruction.
|
||||
The vextractbm is used to have a smaller tail code for calculating the
|
||||
return value.
|
||||
|
||||
3. Performance improvement
|
||||
|
||||
This version has around 35% better performance on average. I saw no
|
||||
performance regressions for any length or alignment.
|
||||
|
||||
Thanks Matheus for helping me out with some details.
|
||||
|
||||
Co-authored-by: Matheus Castanho <msc@linux.ibm.com>
|
||||
Reviewed-by: Raphael M Zinsly <rzinsly@linux.ibm.com>
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/le/power10/memcmp.S b/sysdeps/powerpc/powerpc64/le/power10/memcmp.S
|
||||
new file mode 100644
|
||||
index 0000000000000000..52f244e7e77cbdf9
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/powerpc/powerpc64/le/power10/memcmp.S
|
||||
@@ -0,0 +1,179 @@
|
||||
+/* Optimized memcmp implementation for POWER10.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <sysdep.h>
|
||||
+
|
||||
+/* TODO: Replace macros by the actual instructions when minimum binutils becomes
|
||||
+ >= 2.35. This is used to keep compatibility with older versions. */
|
||||
+#define VEXTRACTBM(rt,vrb) \
|
||||
+ .long(((4)<<(32-6)) \
|
||||
+ | ((rt)<<(32-11)) \
|
||||
+ | ((8)<<(32-16)) \
|
||||
+ | ((vrb)<<(32-21)) \
|
||||
+ | 1602)
|
||||
+
|
||||
+#define LXVP(xtp,dq,ra) \
|
||||
+ .long(((6)<<(32-6)) \
|
||||
+ | ((((xtp)-32)>>1)<<(32-10)) \
|
||||
+ | ((1)<<(32-11)) \
|
||||
+ | ((ra)<<(32-16)) \
|
||||
+ | dq)
|
||||
+
|
||||
+/* Compare 32 bytes. */
|
||||
+#define COMPARE_32(vr1,vr2,offset,tail_1,tail_2)\
|
||||
+ LXVP(32+vr1,offset,r3); \
|
||||
+ LXVP(32+vr2,offset,r4); \
|
||||
+ vcmpneb. v5,vr1+1,vr2+1; \
|
||||
+ bne cr6,L(tail_2); \
|
||||
+ vcmpneb. v4,vr1,vr2; \
|
||||
+ bne cr6,L(tail_1); \
|
||||
+
|
||||
+#define TAIL(v_res,s1,s2) \
|
||||
+ vctzlsbb r7,v_res; \
|
||||
+ vextubrx r8,r7,s1; \
|
||||
+ vextubrx r9,r7,s2; \
|
||||
+ subf r3,r9,r8; \
|
||||
+ blr; \
|
||||
+
|
||||
+/* int [r3] memcmp (const char *s1 [r3], const char *s2 [r4],
|
||||
+ size_t size [r5]) */
|
||||
+
|
||||
+#ifndef MEMCMP
|
||||
+# define MEMCMP memcmp
|
||||
+#endif
|
||||
+ .machine power9
|
||||
+ENTRY_TOCLESS (MEMCMP, 4)
|
||||
+ CALL_MCOUNT 3
|
||||
+
|
||||
+ cmpldi cr6,r5,64
|
||||
+ bgt cr6,L(loop_head)
|
||||
+
|
||||
+/* Compare 64 bytes. This section is used for lengths <= 64 and for the last
|
||||
+ bytes for larger lengths. */
|
||||
+L(last_compare):
|
||||
+ li r8,16
|
||||
+
|
||||
+ sldi r9,r5,56
|
||||
+ sldi r8,r8,56
|
||||
+ addi r6,r3,16
|
||||
+ addi r7,r4,16
|
||||
+
|
||||
+ /* Align up to 16 bytes. */
|
||||
+ lxvl 32+v0,r3,r9
|
||||
+ lxvl 32+v2,r4,r9
|
||||
+
|
||||
+ /* The sub. and vcmpneb. results are concatenated by the crnand in order
|
||||
+ to do a single branch. It's doing a NOT(CR0.GT AND CR6.EQ) then
|
||||
+ loading to CR0.LT. That means r9 is not bigger than 0 and v4 is not
|
||||
+ all equal to 0. */
|
||||
+ sub. r9,r9,r8
|
||||
+ vcmpneb. v4,v0,v2
|
||||
+ crnand 4*cr0+lt,4*cr0+gt,4*cr6+eq
|
||||
+ bt 4*cr0+lt,L(tail1)
|
||||
+
|
||||
+ addi r3,r3,32
|
||||
+ addi r4,r4,32
|
||||
+
|
||||
+ lxvl 32+v1,r6,r9
|
||||
+ lxvl 32+v3,r7,r9
|
||||
+ sub. r9,r9,r8
|
||||
+ vcmpneb. v5,v1,v3
|
||||
+ crnand 4*cr0+lt,4*cr0+gt,4*cr6+eq
|
||||
+ bt 4*cr0+lt,L(tail2)
|
||||
+
|
||||
+ addi r6,r3,16
|
||||
+ addi r7,r4,16
|
||||
+
|
||||
+ lxvl 32+v6,r3,r9
|
||||
+ lxvl 32+v8,r4,r9
|
||||
+ sub. r9,r9,r8
|
||||
+ vcmpneb. v4,v6,v8
|
||||
+ crnand 4*cr0+lt,4*cr0+gt,4*cr6+eq
|
||||
+ bt 4*cr0+lt,L(tail3)
|
||||
+
|
||||
+ lxvl 32+v7,r6,r9
|
||||
+ lxvl 32+v9,r7,r9
|
||||
+ vcmpneb. v5,v7,v9
|
||||
+ bne cr6,L(tail4)
|
||||
+
|
||||
+L(finish):
|
||||
+ /* The contents are equal. */
|
||||
+ li r3,0
|
||||
+ blr
|
||||
+
|
||||
+L(loop_head):
|
||||
+ /* Calculate how many loops to run. */
|
||||
+ srdi. r8,r5,7
|
||||
+ beq L(loop_tail)
|
||||
+ mtctr r8
|
||||
+
|
||||
+/* Main loop. Compares 128 bytes each loop. */
|
||||
+ .p2align 5
|
||||
+L(loop_128):
|
||||
+ COMPARE_32(v0,v2,0,tail1,tail2)
|
||||
+ COMPARE_32(v6,v8,32,tail3,tail4)
|
||||
+ COMPARE_32(v10,v12,64,tail5,tail6)
|
||||
+ COMPARE_32(v14,v16,96,tail7,tail8)
|
||||
+
|
||||
+ addi r3,r3,128
|
||||
+ addi r4,r4,128
|
||||
+ bdnz L(loop_128)
|
||||
+
|
||||
+ /* Account loop comparisons. */
|
||||
+ clrldi. r5,r5,57
|
||||
+ beq L(finish)
|
||||
+
|
||||
+/* Compares 64 bytes if length is still bigger than 64 bytes. */
|
||||
+ .p2align 5
|
||||
+L(loop_tail):
|
||||
+ cmpldi r5,64
|
||||
+ ble L(last_compare)
|
||||
+ COMPARE_32(v0,v2,0,tail1,tail2)
|
||||
+ COMPARE_32(v6,v8,32,tail3,tail4)
|
||||
+ addi r3,r3,64
|
||||
+ addi r4,r4,64
|
||||
+ subi r5,r5,64
|
||||
+ b L(last_compare)
|
||||
+
|
||||
+L(tail1):
|
||||
+ TAIL(v4,v0,v2)
|
||||
+
|
||||
+L(tail2):
|
||||
+ TAIL(v5,v1,v3)
|
||||
+
|
||||
+L(tail3):
|
||||
+ TAIL(v4,v6,v8)
|
||||
+
|
||||
+L(tail4):
|
||||
+ TAIL(v5,v7,v9)
|
||||
+
|
||||
+L(tail5):
|
||||
+ TAIL(v4,v10,v12)
|
||||
+
|
||||
+L(tail6):
|
||||
+ TAIL(v5,v11,v13)
|
||||
+
|
||||
+L(tail7):
|
||||
+ TAIL(v4,v14,v16)
|
||||
+
|
||||
+L(tail8):
|
||||
+ TAIL(v5,v15,v17)
|
||||
+
|
||||
+END (MEMCMP)
|
||||
+libc_hidden_builtin_def (memcmp)
|
||||
+weak_alias (memcmp, bcmp)
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile
|
||||
index ac2446aca62cc4ab..ee98417f4a383356 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile
|
||||
@@ -32,7 +32,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \
|
||||
strncase-power8
|
||||
|
||||
ifneq (,$(filter %le,$(config-machine)))
|
||||
-sysdep_routines += memcpy-power10 memmove-power10 memset-power10 \
|
||||
+sysdep_routines += memcmp-power10 memcpy-power10 memmove-power10 memset-power10 \
|
||||
rawmemchr-power9 rawmemchr-power10 \
|
||||
strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \
|
||||
strlen-power9 strncpy-power9 stpncpy-power9 strlen-power10
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
index 127af84b32a8196f..5213abdf87c79c88 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
@@ -184,6 +184,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/memcmp.c. */
|
||||
IFUNC_IMPL (i, name, memcmp,
|
||||
+#ifdef __LITTLE_ENDIAN__
|
||||
+ IFUNC_IMPL_ADD (array, i, memcmp,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_3_1
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ __memcmp_power10)
|
||||
+#endif
|
||||
IFUNC_IMPL_ADD (array, i, memcmp, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__memcmp_power8)
|
||||
IFUNC_IMPL_ADD (array, i, memcmp, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memcmp-power10.S b/sysdeps/powerpc/powerpc64/multiarch/memcmp-power10.S
|
||||
new file mode 100644
|
||||
index 0000000000000000..73a0debd4a811d8e
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memcmp-power10.S
|
||||
@@ -0,0 +1,26 @@
|
||||
+/* Optimized memcmp implementation for POWER10.
|
||||
+ Copyright (C) 2017-2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#define MEMCMP __memcmp_power10
|
||||
+
|
||||
+#undef libc_hidden_builtin_def
|
||||
+#define libc_hidden_builtin_def(name)
|
||||
+#undef weak_alias
|
||||
+#define weak_alias(name,alias)
|
||||
+
|
||||
+#include <sysdeps/powerpc/powerpc64/le/power10/memcmp.S>
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memcmp.c b/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
|
||||
index 2c7a083a6560f920..0b8c0c1d8aa3f90a 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
|
||||
@@ -27,11 +27,17 @@ extern __typeof (memcmp) __memcmp_ppc attribute_hidden;
|
||||
extern __typeof (memcmp) __memcmp_power4 attribute_hidden;
|
||||
extern __typeof (memcmp) __memcmp_power7 attribute_hidden;
|
||||
extern __typeof (memcmp) __memcmp_power8 attribute_hidden;
|
||||
+extern __typeof (memcmp) __memcmp_power10 attribute_hidden;
|
||||
# undef memcmp
|
||||
|
||||
/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
|
||||
ifunc symbol properly. */
|
||||
libc_ifunc_redirected (__redirect_memcmp, memcmp,
|
||||
+#ifdef __LITTLE_ENDIAN__
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_3_1
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ ? __memcmp_power10 :
|
||||
+#endif
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __memcmp_power8 :
|
||||
(hwcap & PPC_FEATURE_HAS_VSX)
|
278
SOURCES/glibc-rh1983203-2.patch
Normal file
278
SOURCES/glibc-rh1983203-2.patch
Normal file
@ -0,0 +1,278 @@
|
||||
commit 813c6ec808556553be9d39e900a3fc97ceb32330
|
||||
Author: Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
|
||||
Date: Wed Jun 30 12:36:07 2021 -0300
|
||||
|
||||
powerpc: optimize strcpy/stpcpy for POWER9/10
|
||||
|
||||
This patch modifies the current POWER9 implementation of strcpy and
|
||||
stpcpy to optimize it for POWER9/10.
|
||||
|
||||
Since no new POWER10 instructions are used, the original POWER9 strcpy is
|
||||
modified instead of creating a new implementation for POWER10. This
|
||||
implementation is based on both the original POWER9 implementation of
|
||||
strcpy and the preamble of the new POWER10 implementation of strlen.
|
||||
|
||||
The changes also affect stpcpy, which uses the same implementation with
|
||||
some additional code before returning.
|
||||
|
||||
On POWER9, averaging improvements across the benchmark
|
||||
inputs (length/source alignment/destination alignment), for an
|
||||
experiment that ran the benchmark five times, bench-strcpy showed an
|
||||
improvement of 5.23%, and bench-stpcpy showed an improvement of 6.59%.
|
||||
|
||||
On POWER10, bench-strcpy showed 13.16%, and bench-stpcpy showed 13.59%.
|
||||
|
||||
The changes are:
|
||||
|
||||
1. Removed the null string optimization.
|
||||
|
||||
Although this results in a few extra cycles for the null string, in
|
||||
combination with the second change, this resulted in improvements for
|
||||
for other cases.
|
||||
|
||||
2. Adapted the preamble from strlen for POWER10.
|
||||
|
||||
This is the part of the function that handles up to the first 16 bytes
|
||||
of the string.
|
||||
|
||||
3. Increased number of unrolled iterations in the main loop to 6.
|
||||
|
||||
Reviewed-by: Matheus Castanho <msc@linux.ibm.com>
|
||||
Tested-by: Matheus Castanho <msc@linux.ibm.com>
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/le/power9/strcpy.S b/sysdeps/powerpc/powerpc64/le/power9/strcpy.S
|
||||
index ce8f50329177fd06..9845a1d4cf0e1e5d 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/le/power9/strcpy.S
|
||||
+++ b/sysdeps/powerpc/powerpc64/le/power9/strcpy.S
|
||||
@@ -45,91 +45,78 @@
|
||||
The implementation can load bytes past a null terminator, but only
|
||||
up to the next 16B boundary, so it never crosses a page. */
|
||||
|
||||
+/* Load quadword at addr+offset to vreg, check for null bytes,
|
||||
+ and branch to label if any are found. */
|
||||
+#define CHECK16(vreg,offset,addr,label) \
|
||||
+ lxv vreg+32,offset(addr); \
|
||||
+ vcmpequb. v6,vreg,v18; \
|
||||
+ bne cr6,L(label);
|
||||
+
|
||||
.machine power9
|
||||
ENTRY_TOCLESS (FUNC_NAME, 4)
|
||||
CALL_MCOUNT 2
|
||||
|
||||
- /* NULL string optimisation */
|
||||
- lbz r0,0(r4)
|
||||
- stb r0,0(r3)
|
||||
- cmpwi r0,0
|
||||
- beqlr
|
||||
-
|
||||
- addi r4,r4,1
|
||||
- addi r11,r3,1
|
||||
-
|
||||
vspltisb v18,0 /* Zeroes in v18 */
|
||||
+ vspltisb v19,-1 /* 0xFF bytes in v19 */
|
||||
|
||||
- neg r5,r4
|
||||
- rldicl r9,r5,0,60 /* How many bytes to get source 16B aligned? */
|
||||
+ /* Next 16B-aligned address. Prepare address for L(loop). */
|
||||
+ addi r5,r4,16
|
||||
+ clrrdi r5,r5,4
|
||||
+ subf r8,r4,r5
|
||||
+ add r11,r3,r8
|
||||
|
||||
- /* Get source 16B aligned */
|
||||
+ /* Align data and fill bytes not loaded with non matching char. */
|
||||
lvx v0,0,r4
|
||||
lvsr v1,0,r4
|
||||
- vperm v0,v18,v0,v1
|
||||
-
|
||||
- vcmpequb v6,v0,v18 /* 0xff if byte is NULL, 0x00 otherwise */
|
||||
- vctzlsbb r7,v6 /* Number of trailing zeroes */
|
||||
- addi r8,r7,1 /* Add null terminator */
|
||||
+ vperm v0,v19,v0,v1
|
||||
|
||||
- /* r8 = bytes including null
|
||||
- r9 = bytes to get source 16B aligned
|
||||
- if r8 > r9
|
||||
- no null, copy r9 bytes
|
||||
- else
|
||||
- there is a null, copy r8 bytes and return. */
|
||||
- cmpd r8,r9
|
||||
- bgt L(no_null)
|
||||
+ vcmpequb. v6,v0,v18 /* 0xff if byte is NULL, 0x00 otherwise */
|
||||
+ beq cr6,L(no_null)
|
||||
|
||||
- sldi r10,r8,56 /* stxvl wants size in top 8 bits */
|
||||
- stxvl 32+v0,r11,r10 /* Partial store */
|
||||
+ /* There's a null byte. */
|
||||
+ vctzlsbb r8,v6 /* Number of trailing zeroes */
|
||||
+ addi r9,r8,1 /* Add null byte. */
|
||||
+ sldi r10,r9,56 /* stxvl wants size in top 8 bits. */
|
||||
+ stxvl 32+v0,r3,r10 /* Partial store */
|
||||
|
||||
#ifdef USE_AS_STPCPY
|
||||
/* stpcpy returns the dest address plus the size not counting the
|
||||
final '\0'. */
|
||||
- add r3,r11,r7
|
||||
+ add r3,r3,r8
|
||||
#endif
|
||||
blr
|
||||
|
||||
L(no_null):
|
||||
- sldi r10,r9,56 /* stxvl wants size in top 8 bits */
|
||||
- stxvl 32+v0,r11,r10 /* Partial store */
|
||||
-
|
||||
- add r4,r4,r9
|
||||
- add r11,r11,r9
|
||||
+ sldi r10,r8,56 /* stxvl wants size in top 8 bits */
|
||||
+ stxvl 32+v0,r3,r10 /* Partial store */
|
||||
|
||||
+ .p2align 4
|
||||
L(loop):
|
||||
- lxv 32+v0,0(r4)
|
||||
- vcmpequb. v6,v0,v18 /* Any zero bytes? */
|
||||
- bne cr6,L(tail1)
|
||||
-
|
||||
- lxv 32+v1,16(r4)
|
||||
- vcmpequb. v6,v1,v18 /* Any zero bytes? */
|
||||
- bne cr6,L(tail2)
|
||||
-
|
||||
- lxv 32+v2,32(r4)
|
||||
- vcmpequb. v6,v2,v18 /* Any zero bytes? */
|
||||
- bne cr6,L(tail3)
|
||||
-
|
||||
- lxv 32+v3,48(r4)
|
||||
- vcmpequb. v6,v3,v18 /* Any zero bytes? */
|
||||
- bne cr6,L(tail4)
|
||||
+ CHECK16(v0,0,r5,tail1)
|
||||
+ CHECK16(v1,16,r5,tail2)
|
||||
+ CHECK16(v2,32,r5,tail3)
|
||||
+ CHECK16(v3,48,r5,tail4)
|
||||
+ CHECK16(v4,64,r5,tail5)
|
||||
+ CHECK16(v5,80,r5,tail6)
|
||||
|
||||
stxv 32+v0,0(r11)
|
||||
stxv 32+v1,16(r11)
|
||||
stxv 32+v2,32(r11)
|
||||
stxv 32+v3,48(r11)
|
||||
+ stxv 32+v4,64(r11)
|
||||
+ stxv 32+v5,80(r11)
|
||||
|
||||
- addi r4,r4,64
|
||||
- addi r11,r11,64
|
||||
+ addi r5,r5,96
|
||||
+ addi r11,r11,96
|
||||
|
||||
b L(loop)
|
||||
|
||||
+ .p2align 4
|
||||
L(tail1):
|
||||
- vctzlsbb r8,v6
|
||||
- addi r9,r8,1
|
||||
+ vctzlsbb r8,v6 /* Number of trailing zeroes */
|
||||
+ addi r9,r8,1 /* Add null terminator */
|
||||
sldi r9,r9,56 /* stxvl wants size in top 8 bits */
|
||||
- stxvl 32+v0,r11,r9
|
||||
+ stxvl 32+v0,r11,r9 /* Partial store */
|
||||
#ifdef USE_AS_STPCPY
|
||||
/* stpcpy returns the dest address plus the size not counting the
|
||||
final '\0'. */
|
||||
@@ -137,50 +124,81 @@ L(tail1):
|
||||
#endif
|
||||
blr
|
||||
|
||||
+ .p2align 4
|
||||
L(tail2):
|
||||
stxv 32+v0,0(r11)
|
||||
- vctzlsbb r8,v6 /* Number of trailing zeroes */
|
||||
- addi r9,r8,1 /* Add null terminator */
|
||||
- sldi r10,r9,56 /* stxvl wants size in top 8 bits */
|
||||
+ vctzlsbb r8,v6
|
||||
+ addi r9,r8,1
|
||||
+ sldi r9,r9,56
|
||||
addi r11,r11,16
|
||||
- stxvl 32+v1,r11,r10 /* Partial store */
|
||||
+ stxvl 32+v1,r11,r9
|
||||
#ifdef USE_AS_STPCPY
|
||||
- /* stpcpy returns the dest address plus the size not counting the
|
||||
- final '\0'. */
|
||||
add r3,r11,r8
|
||||
#endif
|
||||
blr
|
||||
|
||||
+ .p2align 4
|
||||
L(tail3):
|
||||
stxv 32+v0,0(r11)
|
||||
stxv 32+v1,16(r11)
|
||||
- vctzlsbb r8,v6 /* Number of trailing zeroes */
|
||||
- addi r9,r8,1 /* Add null terminator */
|
||||
- sldi r10,r9,56 /* stxvl wants size in top 8 bits */
|
||||
+ vctzlsbb r8,v6
|
||||
+ addi r9,r8,1
|
||||
+ sldi r9,r9,56
|
||||
addi r11,r11,32
|
||||
- stxvl 32+v2,r11,r10 /* Partial store */
|
||||
+ stxvl 32+v2,r11,r9
|
||||
#ifdef USE_AS_STPCPY
|
||||
- /* stpcpy returns the dest address plus the size not counting the
|
||||
- final '\0'. */
|
||||
add r3,r11,r8
|
||||
#endif
|
||||
blr
|
||||
|
||||
+ .p2align 4
|
||||
L(tail4):
|
||||
stxv 32+v0,0(r11)
|
||||
stxv 32+v1,16(r11)
|
||||
stxv 32+v2,32(r11)
|
||||
- vctzlsbb r8,v6 /* Number of trailing zeroes */
|
||||
- addi r9,r8,1 /* Add null terminator */
|
||||
- sldi r10,r9,56 /* stxvl wants size in top 8 bits */
|
||||
+ vctzlsbb r8,v6
|
||||
+ addi r9,r8,1
|
||||
+ sldi r9,r9,56
|
||||
addi r11,r11,48
|
||||
- stxvl 32+v3,r11,r10 /* Partial store */
|
||||
+ stxvl 32+v3,r11,r9
|
||||
#ifdef USE_AS_STPCPY
|
||||
- /* stpcpy returns the dest address plus the size not counting the
|
||||
- final '\0'. */
|
||||
add r3,r11,r8
|
||||
#endif
|
||||
blr
|
||||
+
|
||||
+ .p2align 4
|
||||
+L(tail5):
|
||||
+ stxv 32+v0,0(r11)
|
||||
+ stxv 32+v1,16(r11)
|
||||
+ stxv 32+v2,32(r11)
|
||||
+ stxv 32+v3,48(r11)
|
||||
+ vctzlsbb r8,v6
|
||||
+ addi r9,r8,1
|
||||
+ sldi r9,r9,56
|
||||
+ addi r11,r11,64
|
||||
+ stxvl 32+v4,r11,r9
|
||||
+#ifdef USE_AS_STPCPY
|
||||
+ add r3,r11,r8
|
||||
+#endif
|
||||
+ blr
|
||||
+
|
||||
+ .p2align 4
|
||||
+L(tail6):
|
||||
+ stxv 32+v0,0(r11)
|
||||
+ stxv 32+v1,16(r11)
|
||||
+ stxv 32+v2,32(r11)
|
||||
+ stxv 32+v3,48(r11)
|
||||
+ stxv 32+v4,64(r11)
|
||||
+ vctzlsbb r8,v6
|
||||
+ addi r9,r8,1
|
||||
+ sldi r9,r9,56
|
||||
+ addi r11,r11,80
|
||||
+ stxvl 32+v5,r11,r9
|
||||
+#ifdef USE_AS_STPCPY
|
||||
+ add r3,r11,r8
|
||||
+#endif
|
||||
+ blr
|
||||
+
|
||||
END (FUNC_NAME)
|
||||
#ifndef USE_AS_STPCPY
|
||||
libc_hidden_builtin_def (strcpy)
|
50
SOURCES/glibc-rh1984802-1.patch
Normal file
50
SOURCES/glibc-rh1984802-1.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 756c306502498f999fdd494477b9cea1b45e4faf Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Fri, 21 Aug 2020 11:23:17 +0200
|
||||
Subject: [PATCH] S390: Sync HWCAP names with kernel by adding aliases [BZ
|
||||
#25971]
|
||||
|
||||
Unfortunately some HWCAP names like HWCAP_S390_VX differs between
|
||||
kernel (see <kernel>/arch/s390/include/asm/elf.h) and glibc.
|
||||
|
||||
Therefore, those HWCAP names from kernel are now introduced as alias
|
||||
---
|
||||
sysdeps/s390/dl-procinfo.h | 3 +++
|
||||
sysdeps/unix/sysv/linux/s390/bits/hwcap.h | 3 +++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h
|
||||
index 0db4bc39c7..08eee109f7 100644
|
||||
--- a/sysdeps/s390/dl-procinfo.h
|
||||
+++ b/sysdeps/s390/dl-procinfo.h
|
||||
@@ -51,8 +51,11 @@ enum
|
||||
HWCAP_S390_HIGH_GPRS = 1 << 9,
|
||||
HWCAP_S390_TE = 1 << 10,
|
||||
HWCAP_S390_VX = 1 << 11,
|
||||
+ HWCAP_S390_VXRS = HWCAP_S390_VX,
|
||||
HWCAP_S390_VXD = 1 << 12,
|
||||
+ HWCAP_S390_VXRS_BCD = HWCAP_S390_VXD,
|
||||
HWCAP_S390_VXE = 1 << 13,
|
||||
+ HWCAP_S390_VXRS_EXT = HWCAP_S390_VXE,
|
||||
HWCAP_S390_GS = 1 << 14,
|
||||
HWCAP_S390_VXRS_EXT2 = 1 << 15,
|
||||
HWCAP_S390_VXRS_PDE = 1 << 16,
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
|
||||
index 6adbec018b..f2998ff131 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
|
||||
@@ -36,8 +36,11 @@
|
||||
#define HWCAP_S390_HIGH_GPRS 512
|
||||
#define HWCAP_S390_TE 1024
|
||||
#define HWCAP_S390_VX 2048
|
||||
+#define HWCAP_S390_VXRS HWCAP_S390_VX
|
||||
#define HWCAP_S390_VXD 4096
|
||||
+#define HWCAP_S390_VXRS_BCD HWCAP_S390_VXD
|
||||
#define HWCAP_S390_VXE 8192
|
||||
+#define HWCAP_S390_VXRS_EXT HWCAP_S390_VXE
|
||||
#define HWCAP_S390_GS 16384
|
||||
#define HWCAP_S390_VXRS_EXT2 32768
|
||||
#define HWCAP_S390_VXRS_PDE 65536
|
||||
--
|
||||
2.31.1
|
||||
|
67
SOURCES/glibc-rh1984802-2.patch
Normal file
67
SOURCES/glibc-rh1984802-2.patch
Normal file
@ -0,0 +1,67 @@
|
||||
From 25251c0707fe34f30a27381a5fabc35435a96621 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue, 16 Feb 2021 16:18:56 +0100
|
||||
Subject: [PATCH] S390: Add new hwcap values.
|
||||
|
||||
The new hwcap values indicate support for arch14 architecture.
|
||||
---
|
||||
sysdeps/s390/dl-procinfo.c | 5 +++--
|
||||
sysdeps/s390/dl-procinfo.h | 4 +++-
|
||||
sysdeps/unix/sysv/linux/s390/bits/hwcap.h | 2 ++
|
||||
3 files changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c
|
||||
index 0c334a2551..c174e27b35 100644
|
||||
--- a/sysdeps/s390/dl-procinfo.c
|
||||
+++ b/sysdeps/s390/dl-procinfo.c
|
||||
@@ -46,12 +46,13 @@
|
||||
#if !defined PROCINFO_DECL && defined SHARED
|
||||
._dl_s390_cap_flags
|
||||
#else
|
||||
-PROCINFO_CLASS const char _dl_s390_cap_flags[19][9]
|
||||
+PROCINFO_CLASS const char _dl_s390_cap_flags[21][9]
|
||||
#endif
|
||||
#ifndef PROCINFO_DECL
|
||||
= {
|
||||
"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh",
|
||||
- "highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt"
|
||||
+ "highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt",
|
||||
+ "vxp2", "nnpa"
|
||||
}
|
||||
#endif
|
||||
#if !defined SHARED || defined PROCINFO_DECL
|
||||
diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h
|
||||
index 9e1a8c7ba9..2d9c305808 100644
|
||||
--- a/sysdeps/s390/dl-procinfo.h
|
||||
+++ b/sysdeps/s390/dl-procinfo.h
|
||||
@@ -21,7 +21,7 @@
|
||||
#define _DL_PROCINFO_H 1
|
||||
#include <ldsodefs.h>
|
||||
|
||||
-#define _DL_HWCAP_COUNT 19
|
||||
+#define _DL_HWCAP_COUNT 21
|
||||
|
||||
#define _DL_PLATFORMS_COUNT 10
|
||||
|
||||
@@ -61,6 +61,8 @@ enum
|
||||
HWCAP_S390_VXRS_PDE = 1 << 16,
|
||||
HWCAP_S390_SORT = 1 << 17,
|
||||
HWCAP_S390_DFLT = 1 << 18,
|
||||
+ HWCAP_S390_VXRS_PDE2 = 1 << 19,
|
||||
+ HWCAP_S390_NNPA = 1 << 20,
|
||||
};
|
||||
|
||||
#define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
|
||||
index 696616e779..e9bd3684db 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
|
||||
@@ -46,3 +46,5 @@
|
||||
#define HWCAP_S390_VXRS_PDE 65536
|
||||
#define HWCAP_S390_SORT 131072
|
||||
#define HWCAP_S390_DFLT 262144
|
||||
+#define HWCAP_S390_VXRS_PDE2 524288
|
||||
+#define HWCAP_S390_NNPA 1048576
|
||||
--
|
||||
2.31.1
|
||||
|
88
SOURCES/glibc-rh1984802-3.patch
Normal file
88
SOURCES/glibc-rh1984802-3.patch
Normal file
@ -0,0 +1,88 @@
|
||||
From f2e06656d04a9fcb0603802a4f8ce7aa3a1f055e Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue, 5 Oct 2021 16:14:10 +0200
|
||||
Subject: [PATCH] S390: Add PCI_MIO and SIE HWCAPs
|
||||
|
||||
Both new HWCAPs were introduced in these kernel commits:
|
||||
- 7e8403ecaf884f307b627f3c371475913dd29292
|
||||
"s390: add HWCAP_S390_PCI_MIO to ELF hwcaps"
|
||||
- 7e82523f2583e9813e4109df3656707162541297
|
||||
"s390/hwcaps: make sie capability regular hwcap"
|
||||
|
||||
Also note that the kernel commit 511ad531afd4090625def4d9aba1f5227bd44b8e
|
||||
"s390/hwcaps: shorten HWCAP defines" has shortened the prefix of the macros
|
||||
from "HWCAP_S390_" to "HWCAP_". For compatibility reasons, we do not
|
||||
change the prefix in public glibc header file.
|
||||
---
|
||||
sysdeps/s390/dl-procinfo.c | 4 ++--
|
||||
sysdeps/s390/dl-procinfo.h | 4 +++-
|
||||
sysdeps/unix/sysv/linux/s390/bits/hwcap.h | 7 +++++++
|
||||
3 files changed, 12 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c
|
||||
index 7314c31b15..97be34fe9d 100644
|
||||
--- a/sysdeps/s390/dl-procinfo.c
|
||||
+++ b/sysdeps/s390/dl-procinfo.c
|
||||
@@ -45,13 +45,13 @@
|
||||
#if !defined PROCINFO_DECL && defined SHARED
|
||||
._dl_s390_cap_flags
|
||||
#else
|
||||
-PROCINFO_CLASS const char _dl_s390_cap_flags[21][9]
|
||||
+PROCINFO_CLASS const char _dl_s390_cap_flags[23][9]
|
||||
#endif
|
||||
#ifndef PROCINFO_DECL
|
||||
= {
|
||||
"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh",
|
||||
"highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt",
|
||||
- "vxp2", "nnpa"
|
||||
+ "vxp2", "nnpa", "pcimio", "sie"
|
||||
}
|
||||
#endif
|
||||
#if !defined SHARED || defined PROCINFO_DECL
|
||||
diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h
|
||||
index 2502dd2604..d9a3b264ff 100644
|
||||
--- a/sysdeps/s390/dl-procinfo.h
|
||||
+++ b/sysdeps/s390/dl-procinfo.h
|
||||
@@ -20,7 +20,7 @@
|
||||
#define _DL_PROCINFO_H 1
|
||||
#include <ldsodefs.h>
|
||||
|
||||
-#define _DL_HWCAP_COUNT 21
|
||||
+#define _DL_HWCAP_COUNT 23
|
||||
|
||||
#define _DL_PLATFORMS_COUNT 10
|
||||
|
||||
@@ -62,6 +62,8 @@ enum
|
||||
HWCAP_S390_DFLT = 1 << 18,
|
||||
HWCAP_S390_VXRS_PDE2 = 1 << 19,
|
||||
HWCAP_S390_NNPA = 1 << 20,
|
||||
+ HWCAP_S390_PCI_MIO = 1 << 21,
|
||||
+ HWCAP_S390_SIE = 1 << 22,
|
||||
};
|
||||
|
||||
#define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
|
||||
index e9bd3684db..00e73a3e3b 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
|
||||
@@ -22,6 +22,11 @@
|
||||
|
||||
/*
|
||||
* The following must match the kernels asm/elf.h.
|
||||
+ * Note: The kernel commit 511ad531afd4090625def4d9aba1f5227bd44b8e
|
||||
+ * "s390/hwcaps: shorten HWCAP defines" has shortened the prefix of the macros
|
||||
+ * from "HWCAP_S390_" to "HWCAP_". For compatibility reasons, we do not
|
||||
+ * change the prefix in public glibc header file.
|
||||
+ *
|
||||
* Note that these are *not* the same as the STORE FACILITY LIST bits.
|
||||
*/
|
||||
#define HWCAP_S390_ESAN3 1
|
||||
@@ -48,3 +53,5 @@
|
||||
#define HWCAP_S390_DFLT 262144
|
||||
#define HWCAP_S390_VXRS_PDE2 524288
|
||||
#define HWCAP_S390_NNPA 1048576
|
||||
+#define HWCAP_S390_PCI_MIO 2097152
|
||||
+#define HWCAP_S390_SIE 4194304
|
||||
--
|
||||
2.31.1
|
||||
|
30
SOURCES/glibc-rh1991001-1.patch
Normal file
30
SOURCES/glibc-rh1991001-1.patch
Normal file
@ -0,0 +1,30 @@
|
||||
commit ad78d702757a189b1fa552d607e8aaa22252a45f
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue May 12 19:06:18 2020 +0200
|
||||
|
||||
elf: Remove redundant add_to_global_resize_failure call from dl_open_args
|
||||
|
||||
The second call does not do anything because the data structures have
|
||||
already been resized by the call that comes before the demarcation
|
||||
point. Fixes commit a509eb117fac1d764b15eba64993f4bdb63d7f3c
|
||||
("Avoid late dlopen failure due to scope, TLS slotinfo updates
|
||||
[BZ #25112]").
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index 3d49a84596e99bf6..b052bb0bc2cd17aa 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -769,11 +769,6 @@ dl_open_worker (void *a)
|
||||
DL_STATIC_INIT (new);
|
||||
#endif
|
||||
|
||||
- /* Perform the necessary allocations for adding new global objects
|
||||
- to the global scope below, via add_to_global_update. */
|
||||
- if (mode & RTLD_GLOBAL)
|
||||
- add_to_global_resize (new);
|
||||
-
|
||||
/* Run the initializer functions of new objects. Temporarily
|
||||
disable the exception handler, so that lazy binding failures are
|
||||
fatal. */
|
23
SOURCES/glibc-rh1991001-10.patch
Normal file
23
SOURCES/glibc-rh1991001-10.patch
Normal file
@ -0,0 +1,23 @@
|
||||
commit 52290d8c04569615fb011ee286d52dc5147afbd7
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Thu Apr 15 09:57:10 2021 +0100
|
||||
|
||||
elf: Fix missing include in test case [BZ #27136]
|
||||
|
||||
Broken test was introduced in
|
||||
|
||||
commit 8f85075a2e9c26ff7486d4bbaf358999807d215c
|
||||
elf: Add a DTV setup test [BZ #27136]
|
||||
|
||||
diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
|
||||
index ac5f8c8d39b66dd6..9977ec803208b9c8 100644
|
||||
--- a/elf/tst-tls20.c
|
||||
+++ b/elf/tst-tls20.c
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
#include <support/xdlfcn.h>
|
||||
#include <support/xthread.h>
|
||||
|
160
SOURCES/glibc-rh1991001-11.patch
Normal file
160
SOURCES/glibc-rh1991001-11.patch
Normal file
@ -0,0 +1,160 @@
|
||||
commit 2208066603a136f95cfb815ca9281262e6465784
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Thu Feb 11 13:24:47 2021 +0000
|
||||
|
||||
elf: Remove lazy tlsdesc relocation related code
|
||||
|
||||
Remove generic tlsdesc code related to lazy tlsdesc processing since
|
||||
lazy tlsdesc relocation is no longer supported. This includes removing
|
||||
GL(dl_load_lock) from _dl_make_tlsdesc_dynamic which is only called at
|
||||
load time when that lock is already held.
|
||||
|
||||
Added a documentation comment too.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/elf/tlsdeschtab.h b/elf/tlsdeschtab.h
|
||||
index fea9eefe72edcd6b..c20857e5b4264f00 100644
|
||||
--- a/elf/tlsdeschtab.h
|
||||
+++ b/elf/tlsdeschtab.h
|
||||
@@ -78,6 +78,10 @@ map_generation (struct link_map *map)
|
||||
return GL(dl_tls_generation) + 1;
|
||||
}
|
||||
|
||||
+/* Returns the data pointer for a given map and tls offset that is used
|
||||
+ to fill in one of the GOT entries referenced by a TLSDESC relocation
|
||||
+ when using dynamic TLS. This requires allocation, returns NULL on
|
||||
+ allocation failure. */
|
||||
void *
|
||||
_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
|
||||
{
|
||||
@@ -85,18 +89,12 @@ _dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
|
||||
void **entry;
|
||||
struct tlsdesc_dynamic_arg *td, test;
|
||||
|
||||
- /* FIXME: We could use a per-map lock here, but is it worth it? */
|
||||
- __rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
-
|
||||
ht = map->l_mach.tlsdesc_table;
|
||||
if (! ht)
|
||||
{
|
||||
ht = htab_create ();
|
||||
if (! ht)
|
||||
- {
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
- return 0;
|
||||
- }
|
||||
+ return 0;
|
||||
map->l_mach.tlsdesc_table = ht;
|
||||
}
|
||||
|
||||
@@ -104,15 +102,11 @@ _dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
|
||||
test.tlsinfo.ti_offset = ti_offset;
|
||||
entry = htab_find_slot (ht, &test, 1, hash_tlsdesc, eq_tlsdesc);
|
||||
if (! entry)
|
||||
- {
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
- return 0;
|
||||
- }
|
||||
+ return 0;
|
||||
|
||||
if (*entry)
|
||||
{
|
||||
td = *entry;
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
return td;
|
||||
}
|
||||
|
||||
@@ -122,44 +116,9 @@ _dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
|
||||
thread. */
|
||||
td->gen_count = map_generation (map);
|
||||
td->tlsinfo = test.tlsinfo;
|
||||
-
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
return td;
|
||||
}
|
||||
|
||||
# endif /* SHARED */
|
||||
|
||||
-/* The idea of the following two functions is to stop multiple threads
|
||||
- from attempting to resolve the same TLS descriptor without busy
|
||||
- waiting. Ideally, we should be able to release the lock right
|
||||
- after changing td->entry, and then using say a condition variable
|
||||
- or a futex wake to wake up any waiting threads, but let's try to
|
||||
- avoid introducing such dependencies. */
|
||||
-
|
||||
-static int
|
||||
-__attribute__ ((unused))
|
||||
-_dl_tlsdesc_resolve_early_return_p (struct tlsdesc volatile *td, void *caller)
|
||||
-{
|
||||
- if (caller != atomic_load_relaxed (&td->entry))
|
||||
- return 1;
|
||||
-
|
||||
- __rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
- if (caller != atomic_load_relaxed (&td->entry))
|
||||
- {
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- atomic_store_relaxed (&td->entry, _dl_tlsdesc_resolve_hold);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-__attribute__ ((unused))
|
||||
-_dl_tlsdesc_wake_up_held_fixups (void)
|
||||
-{
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
-}
|
||||
-
|
||||
#endif
|
||||
diff --git a/sysdeps/aarch64/tlsdesc.c b/sysdeps/aarch64/tlsdesc.c
|
||||
index 357465f23d76e2bd..1ead73ab8250e29c 100644
|
||||
--- a/sysdeps/aarch64/tlsdesc.c
|
||||
+++ b/sysdeps/aarch64/tlsdesc.c
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <tls.h>
|
||||
#include <dl-tlsdesc.h>
|
||||
#include <dl-unmap-segments.h>
|
||||
-#define _dl_tlsdesc_resolve_hold 0
|
||||
#include <tlsdeschtab.h>
|
||||
|
||||
/* Unmap the dynamic object, but also release its TLS descriptor table
|
||||
diff --git a/sysdeps/arm/tlsdesc.c b/sysdeps/arm/tlsdesc.c
|
||||
index d142d7a2c91e9adb..b78e3f65785bf587 100644
|
||||
--- a/sysdeps/arm/tlsdesc.c
|
||||
+++ b/sysdeps/arm/tlsdesc.c
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <tls.h>
|
||||
#include <dl-tlsdesc.h>
|
||||
#include <dl-unmap-segments.h>
|
||||
-#define _dl_tlsdesc_resolve_hold 0
|
||||
#include <tlsdeschtab.h>
|
||||
|
||||
/* Unmap the dynamic object, but also release its TLS descriptor table
|
||||
diff --git a/sysdeps/i386/tlsdesc.c b/sysdeps/i386/tlsdesc.c
|
||||
index 1b4227c8381e1b3d..c242ffce726d50e4 100644
|
||||
--- a/sysdeps/i386/tlsdesc.c
|
||||
+++ b/sysdeps/i386/tlsdesc.c
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <tls.h>
|
||||
#include <dl-tlsdesc.h>
|
||||
#include <dl-unmap-segments.h>
|
||||
-#define _dl_tlsdesc_resolve_hold 0
|
||||
#include <tlsdeschtab.h>
|
||||
|
||||
/* Unmap the dynamic object, but also release its TLS descriptor table
|
||||
diff --git a/sysdeps/x86_64/tlsdesc.c b/sysdeps/x86_64/tlsdesc.c
|
||||
index 61a19ae26944c84f..a9325827d0e5e31b 100644
|
||||
--- a/sysdeps/x86_64/tlsdesc.c
|
||||
+++ b/sysdeps/x86_64/tlsdesc.c
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <tls.h>
|
||||
#include <dl-tlsdesc.h>
|
||||
#include <dl-unmap-segments.h>
|
||||
-#define _dl_tlsdesc_resolve_hold 0
|
||||
#include <tlsdeschtab.h>
|
||||
|
||||
/* Unmap the dynamic object, but also release its TLS descriptor table
|
182
SOURCES/glibc-rh1991001-12.patch
Normal file
182
SOURCES/glibc-rh1991001-12.patch
Normal file
@ -0,0 +1,182 @@
|
||||
commit 1387ad6225c2222f027790e3f460e31aa5dd2c54
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Wed Dec 30 19:19:37 2020 +0000
|
||||
|
||||
elf: Fix data races in pthread_create and TLS access [BZ #19329]
|
||||
|
||||
DTV setup at thread creation (_dl_allocate_tls_init) is changed
|
||||
to take the dlopen lock, GL(dl_load_lock). Avoiding data races
|
||||
here without locks would require design changes: the map that is
|
||||
accessed for static TLS initialization here may be concurrently
|
||||
freed by dlclose. That use after free may be solved by only
|
||||
locking around static TLS setup or by ensuring dlclose does not
|
||||
free modules with static TLS, however currently every link map
|
||||
with TLS has to be accessed at least to see if it needs static
|
||||
TLS. And even if that's solved, still a lot of atomics would be
|
||||
needed to synchronize DTV related globals without a lock. So fix
|
||||
both bug 19329 and bug 27111 with a lock that prevents DTV setup
|
||||
running concurrently with dlopen or dlclose.
|
||||
|
||||
_dl_update_slotinfo at TLS access still does not use any locks
|
||||
so CONCURRENCY NOTES are added to explain the synchronization.
|
||||
The early exit from the slotinfo walk when max_modid is reached
|
||||
is not strictly necessary, but does not hurt either.
|
||||
|
||||
An incorrect acquire load was removed from _dl_resize_dtv: it
|
||||
did not synchronize with any release store or fence and
|
||||
synchronization is now handled separately at thread creation
|
||||
and TLS access time.
|
||||
|
||||
There are still a number of racy read accesses to globals that
|
||||
will be changed to relaxed MO atomics in a followup patch. This
|
||||
should not introduce regressions compared to existing behaviour
|
||||
and avoid cluttering the main part of the fix.
|
||||
|
||||
Not all TLS access related data races got fixed here: there are
|
||||
additional races at lazy tlsdesc relocations see bug 27137.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||
index 15ed01d795a8627a..da83cd6ae2ee6504 100644
|
||||
--- a/elf/dl-tls.c
|
||||
+++ b/elf/dl-tls.c
|
||||
@@ -471,14 +471,11 @@ extern dtv_t _dl_static_dtv[];
|
||||
#endif
|
||||
|
||||
static dtv_t *
|
||||
-_dl_resize_dtv (dtv_t *dtv)
|
||||
+_dl_resize_dtv (dtv_t *dtv, size_t max_modid)
|
||||
{
|
||||
/* Resize the dtv. */
|
||||
dtv_t *newp;
|
||||
- /* Load GL(dl_tls_max_dtv_idx) atomically since it may be written to by
|
||||
- other threads concurrently. */
|
||||
- size_t newsize
|
||||
- = atomic_load_acquire (&GL(dl_tls_max_dtv_idx)) + DTV_SURPLUS;
|
||||
+ size_t newsize = max_modid + DTV_SURPLUS;
|
||||
size_t oldsize = dtv[-1].counter;
|
||||
|
||||
if (dtv == GL(dl_initial_dtv))
|
||||
@@ -524,11 +521,14 @@ _dl_allocate_tls_init (void *result)
|
||||
size_t total = 0;
|
||||
size_t maxgen = 0;
|
||||
|
||||
+ /* Protects global dynamic TLS related state. */
|
||||
+ __rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
+
|
||||
/* Check if the current dtv is big enough. */
|
||||
if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
|
||||
{
|
||||
/* Resize the dtv. */
|
||||
- dtv = _dl_resize_dtv (dtv);
|
||||
+ dtv = _dl_resize_dtv (dtv, GL(dl_tls_max_dtv_idx));
|
||||
|
||||
/* Install this new dtv in the thread data structures. */
|
||||
INSTALL_DTV (result, &dtv[-1]);
|
||||
@@ -596,6 +596,7 @@ _dl_allocate_tls_init (void *result)
|
||||
listp = listp->next;
|
||||
assert (listp != NULL);
|
||||
}
|
||||
+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
|
||||
/* The DTV version is up-to-date now. */
|
||||
dtv[0].counter = maxgen;
|
||||
@@ -730,12 +731,29 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
|
||||
if (dtv[0].counter < listp->slotinfo[idx].gen)
|
||||
{
|
||||
- /* The generation counter for the slot is higher than what the
|
||||
- current dtv implements. We have to update the whole dtv but
|
||||
- only those entries with a generation counter <= the one for
|
||||
- the entry we need. */
|
||||
+ /* CONCURRENCY NOTES:
|
||||
+
|
||||
+ Here the dtv needs to be updated to new_gen generation count.
|
||||
+
|
||||
+ This code may be called during TLS access when GL(dl_load_lock)
|
||||
+ is not held. In that case the user code has to synchronize with
|
||||
+ dlopen and dlclose calls of relevant modules. A module m is
|
||||
+ relevant if the generation of m <= new_gen and dlclose of m is
|
||||
+ synchronized: a memory access here happens after the dlopen and
|
||||
+ before the dlclose of relevant modules. The dtv entries for
|
||||
+ relevant modules need to be updated, other entries can be
|
||||
+ arbitrary.
|
||||
+
|
||||
+ This e.g. means that the first part of the slotinfo list can be
|
||||
+ accessed race free, but the tail may be concurrently extended.
|
||||
+ Similarly relevant slotinfo entries can be read race free, but
|
||||
+ other entries are racy. However updating a non-relevant dtv
|
||||
+ entry does not affect correctness. For a relevant module m,
|
||||
+ max_modid >= modid of m. */
|
||||
size_t new_gen = listp->slotinfo[idx].gen;
|
||||
size_t total = 0;
|
||||
+ size_t max_modid = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx));
|
||||
+ assert (max_modid >= req_modid);
|
||||
|
||||
/* We have to look through the entire dtv slotinfo list. */
|
||||
listp = GL(dl_tls_dtv_slotinfo_list);
|
||||
@@ -745,12 +763,14 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
{
|
||||
size_t modid = total + cnt;
|
||||
|
||||
+ /* Later entries are not relevant. */
|
||||
+ if (modid > max_modid)
|
||||
+ break;
|
||||
+
|
||||
size_t gen = listp->slotinfo[cnt].gen;
|
||||
|
||||
if (gen > new_gen)
|
||||
- /* This is a slot for a generation younger than the
|
||||
- one we are handling now. It might be incompletely
|
||||
- set up so ignore it. */
|
||||
+ /* Not relevant. */
|
||||
continue;
|
||||
|
||||
/* If the entry is older than the current dtv layout we
|
||||
@@ -767,7 +787,7 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
continue;
|
||||
|
||||
/* Resize the dtv. */
|
||||
- dtv = _dl_resize_dtv (dtv);
|
||||
+ dtv = _dl_resize_dtv (dtv, max_modid);
|
||||
|
||||
assert (modid <= dtv[-1].counter);
|
||||
|
||||
@@ -789,8 +809,17 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
}
|
||||
|
||||
total += listp->len;
|
||||
+ if (total > max_modid)
|
||||
+ break;
|
||||
+
|
||||
+ /* Synchronize with _dl_add_to_slotinfo. Ideally this would
|
||||
+ be consume MO since we only need to order the accesses to
|
||||
+ the next node after the read of the address and on most
|
||||
+ hardware (other than alpha) a normal load would do that
|
||||
+ because of the address dependency. */
|
||||
+ listp = atomic_load_acquire (&listp->next);
|
||||
}
|
||||
- while ((listp = listp->next) != NULL);
|
||||
+ while (listp != NULL);
|
||||
|
||||
/* This will be the new maximum generation counter. */
|
||||
dtv[0].counter = new_gen;
|
||||
@@ -982,7 +1011,7 @@ _dl_add_to_slotinfo (struct link_map *l, bool do_add)
|
||||
the first slot. */
|
||||
assert (idx == 0);
|
||||
|
||||
- listp = prevp->next = (struct dtv_slotinfo_list *)
|
||||
+ listp = (struct dtv_slotinfo_list *)
|
||||
malloc (sizeof (struct dtv_slotinfo_list)
|
||||
+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
|
||||
if (listp == NULL)
|
||||
@@ -996,6 +1025,8 @@ cannot create TLS data structures"));
|
||||
listp->next = NULL;
|
||||
memset (listp->slotinfo, '\0',
|
||||
TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
|
||||
+ /* Synchronize with _dl_update_slotinfo. */
|
||||
+ atomic_store_release (&prevp->next, listp);
|
||||
}
|
||||
|
||||
/* Add the information into the slotinfo data structure. */
|
193
SOURCES/glibc-rh1991001-13.patch
Normal file
193
SOURCES/glibc-rh1991001-13.patch
Normal file
@ -0,0 +1,193 @@
|
||||
commit f4f8f4d4e0f92488431b268c8cd9555730b9afe9
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Wed Dec 30 19:19:37 2020 +0000
|
||||
|
||||
elf: Use relaxed atomics for racy accesses [BZ #19329]
|
||||
|
||||
This is a follow up patch to the fix for bug 19329. This adds relaxed
|
||||
MO atomics to accesses that were previously data races but are now
|
||||
race conditions, and where relaxed MO is sufficient.
|
||||
|
||||
The race conditions all follow the pattern that the write is behind the
|
||||
dlopen lock, but a read can happen concurrently (e.g. during tls access)
|
||||
without holding the lock. For slotinfo entries the read value only
|
||||
matters if it reads from a synchronized write in dlopen or dlclose,
|
||||
otherwise the related dtv entry is not valid to access so it is fine
|
||||
to leave it in an inconsistent state. The same applies for
|
||||
GL(dl_tls_max_dtv_idx) and GL(dl_tls_generation), but there the
|
||||
algorithm relies on the fact that the read of the last synchronized
|
||||
write is an increasing value.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||
index 1ece0ae1dd062d1e..7d2dc2272cd643f5 100644
|
||||
--- a/elf/dl-close.c
|
||||
+++ b/elf/dl-close.c
|
||||
@@ -79,9 +79,10 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
|
||||
{
|
||||
assert (old_map->l_tls_modid == idx);
|
||||
|
||||
- /* Mark the entry as unused. */
|
||||
- listp->slotinfo[idx - disp].gen = GL(dl_tls_generation) + 1;
|
||||
- listp->slotinfo[idx - disp].map = NULL;
|
||||
+ /* Mark the entry as unused. These can be read concurrently. */
|
||||
+ atomic_store_relaxed (&listp->slotinfo[idx - disp].gen,
|
||||
+ GL(dl_tls_generation) + 1);
|
||||
+ atomic_store_relaxed (&listp->slotinfo[idx - disp].map, NULL);
|
||||
}
|
||||
|
||||
/* If this is not the last currently used entry no need to look
|
||||
@@ -96,8 +97,8 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
|
||||
|
||||
if (listp->slotinfo[idx - disp].map != NULL)
|
||||
{
|
||||
- /* Found a new last used index. */
|
||||
- GL(dl_tls_max_dtv_idx) = idx;
|
||||
+ /* Found a new last used index. This can be read concurrently. */
|
||||
+ atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), idx);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -571,7 +572,9 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
GL(dl_tls_dtv_slotinfo_list), 0,
|
||||
imap->l_init_called))
|
||||
/* All dynamically loaded modules with TLS are unloaded. */
|
||||
- GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem);
|
||||
+ /* Can be read concurrently. */
|
||||
+ atomic_store_relaxed (&GL(dl_tls_max_dtv_idx),
|
||||
+ GL(dl_tls_static_nelem));
|
||||
|
||||
if (imap->l_tls_offset != NO_TLS_OFFSET
|
||||
&& imap->l_tls_offset != FORCED_DYNAMIC_TLS_OFFSET)
|
||||
@@ -769,8 +772,11 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
/* If we removed any object which uses TLS bump the generation counter. */
|
||||
if (any_tls)
|
||||
{
|
||||
- if (__glibc_unlikely (++GL(dl_tls_generation) == 0))
|
||||
+ size_t newgen = GL(dl_tls_generation) + 1;
|
||||
+ if (__glibc_unlikely (newgen == 0))
|
||||
_dl_fatal_printf ("TLS generation counter wrapped! Please report as described in "REPORT_BUGS_TO".\n");
|
||||
+ /* Can be read concurrently. */
|
||||
+ atomic_store_relaxed (&GL(dl_tls_generation), newgen);
|
||||
|
||||
if (tls_free_end == GL(dl_tls_static_used))
|
||||
GL(dl_tls_static_used) = tls_free_start;
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index b052bb0bc2cd17aa..a67fb3aee40860e1 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -395,9 +395,12 @@ update_tls_slotinfo (struct link_map *new)
|
||||
}
|
||||
}
|
||||
|
||||
- if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
|
||||
+ size_t newgen = GL(dl_tls_generation) + 1;
|
||||
+ if (__glibc_unlikely (newgen == 0))
|
||||
_dl_fatal_printf (N_("\
|
||||
TLS generation counter wrapped! Please report this."));
|
||||
+ /* Can be read concurrently. */
|
||||
+ atomic_store_relaxed (&GL(dl_tls_generation), newgen);
|
||||
|
||||
/* We need a second pass for static tls data, because
|
||||
_dl_update_slotinfo must not be run while calls to
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||
index da83cd6ae2ee6504..801eafad3961573c 100644
|
||||
--- a/elf/dl-tls.c
|
||||
+++ b/elf/dl-tls.c
|
||||
@@ -175,7 +175,9 @@ _dl_next_tls_modid (void)
|
||||
/* No gaps, allocate a new entry. */
|
||||
nogaps:
|
||||
|
||||
- result = ++GL(dl_tls_max_dtv_idx);
|
||||
+ result = GL(dl_tls_max_dtv_idx) + 1;
|
||||
+ /* Can be read concurrently. */
|
||||
+ atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), result);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -359,10 +361,12 @@ allocate_dtv (void *result)
|
||||
dtv_t *dtv;
|
||||
size_t dtv_length;
|
||||
|
||||
+ /* Relaxed MO, because the dtv size is later rechecked, not relied on. */
|
||||
+ size_t max_modid = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx));
|
||||
/* We allocate a few more elements in the dtv than are needed for the
|
||||
initial set of modules. This should avoid in most cases expansions
|
||||
of the dtv. */
|
||||
- dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
|
||||
+ dtv_length = max_modid + DTV_SURPLUS;
|
||||
dtv = calloc (dtv_length + 2, sizeof (dtv_t));
|
||||
if (dtv != NULL)
|
||||
{
|
||||
@@ -767,7 +771,7 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
if (modid > max_modid)
|
||||
break;
|
||||
|
||||
- size_t gen = listp->slotinfo[cnt].gen;
|
||||
+ size_t gen = atomic_load_relaxed (&listp->slotinfo[cnt].gen);
|
||||
|
||||
if (gen > new_gen)
|
||||
/* Not relevant. */
|
||||
@@ -779,7 +783,8 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
continue;
|
||||
|
||||
/* If there is no map this means the entry is empty. */
|
||||
- struct link_map *map = listp->slotinfo[cnt].map;
|
||||
+ struct link_map *map
|
||||
+ = atomic_load_relaxed (&listp->slotinfo[cnt].map);
|
||||
/* Check whether the current dtv array is large enough. */
|
||||
if (dtv[-1].counter < modid)
|
||||
{
|
||||
@@ -923,7 +928,12 @@ __tls_get_addr (GET_ADDR_ARGS)
|
||||
{
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
|
||||
- if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
|
||||
+ /* Update is needed if dtv[0].counter < the generation of the accessed
|
||||
+ module. The global generation counter is used here as it is easier
|
||||
+ to check. Synchronization for the relaxed MO access is guaranteed
|
||||
+ by user code, see CONCURRENCY NOTES in _dl_update_slotinfo. */
|
||||
+ size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
|
||||
+ if (__glibc_unlikely (dtv[0].counter != gen))
|
||||
return update_get_addr (GET_ADDR_PARAM);
|
||||
|
||||
void *p = dtv[GET_ADDR_MODULE].pointer.val;
|
||||
@@ -946,7 +956,10 @@ _dl_tls_get_addr_soft (struct link_map *l)
|
||||
return NULL;
|
||||
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
- if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
|
||||
+ /* This may be called without holding the GL(dl_load_lock). Reading
|
||||
+ arbitrary gen value is fine since this is best effort code. */
|
||||
+ size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
|
||||
+ if (__glibc_unlikely (dtv[0].counter != gen))
|
||||
{
|
||||
/* This thread's DTV is not completely current,
|
||||
but it might already cover this module. */
|
||||
@@ -1032,7 +1045,9 @@ cannot create TLS data structures"));
|
||||
/* Add the information into the slotinfo data structure. */
|
||||
if (do_add)
|
||||
{
|
||||
- listp->slotinfo[idx].map = l;
|
||||
- listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
|
||||
+ /* Can be read concurrently. See _dl_update_slotinfo. */
|
||||
+ atomic_store_relaxed (&listp->slotinfo[idx].map, l);
|
||||
+ atomic_store_relaxed (&listp->slotinfo[idx].gen,
|
||||
+ GL(dl_tls_generation) + 1);
|
||||
}
|
||||
}
|
||||
diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c
|
||||
index 533ee2b3a6e85ad8..bc543dcc264ea361 100644
|
||||
--- a/sysdeps/x86_64/dl-tls.c
|
||||
+++ b/sysdeps/x86_64/dl-tls.c
|
||||
@@ -40,7 +40,8 @@ __tls_get_addr_slow (GET_ADDR_ARGS)
|
||||
{
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
|
||||
- if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
|
||||
+ size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
|
||||
+ if (__glibc_unlikely (dtv[0].counter != gen))
|
||||
return update_get_addr (GET_ADDR_PARAM);
|
||||
|
||||
return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL);
|
133
SOURCES/glibc-rh1991001-14.patch
Normal file
133
SOURCES/glibc-rh1991001-14.patch
Normal file
@ -0,0 +1,133 @@
|
||||
commit 9d0e30329c23b5ad736fda3f174208c25970dbce
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Tue Dec 13 12:28:41 2016 +0000
|
||||
|
||||
elf: Add test case for [BZ #19329]
|
||||
|
||||
Test concurrent dlopen and pthread_create when the loaded modules have
|
||||
TLS. This triggers dl-tls assertion failures more reliably than the
|
||||
nptl/tst-stack4 test.
|
||||
|
||||
The dlopened module has 100 DT_NEEDED dependencies with TLS, they were
|
||||
reused from an existing TLS test. The number of created threads during
|
||||
dlopen depends on filesystem speed and hardware, but at most 3 threads
|
||||
are alive at a time to limit resource usage.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(usual testing differences)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 0995d810b57d0dda..be40e3761cf91c4a 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -210,7 +210,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
tst-tls-ie tst-tls-ie-dlmopen \
|
||||
argv0test \
|
||||
tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
|
||||
- tst-tls20
|
||||
+ tst-tls20 tst-tls21
|
||||
# reldep9
|
||||
tests-internal += loadtest unload unload2 circleload1 \
|
||||
neededtest neededtest2 neededtest3 neededtest4 \
|
||||
@@ -333,7 +333,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||
libmarkermod2-1 libmarkermod2-2 \
|
||||
libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \
|
||||
libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \
|
||||
- tst-tls20mod-bad
|
||||
+ tst-tls20mod-bad tst-tls21mod \
|
||||
|
||||
# Most modules build with _ISOMAC defined, but those filtered out
|
||||
# depend on internal headers.
|
||||
@@ -1836,3 +1836,8 @@ tst-tls20mod-bad.so-no-z-defs = yes
|
||||
$(objpfx)tst-tls20: $(libdl) $(shared-thread-library)
|
||||
$(objpfx)tst-tls20.out: $(objpfx)tst-tls20mod-bad.so \
|
||||
$(tst-tls-many-dynamic-modules:%=$(objpfx)%.so)
|
||||
+
|
||||
+# Reuses tst-tls-many-dynamic-modules
|
||||
+$(objpfx)tst-tls21: $(libdl) $(shared-thread-library)
|
||||
+$(objpfx)tst-tls21.out: $(objpfx)tst-tls21mod.so
|
||||
+$(objpfx)tst-tls21mod.so: $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so)
|
||||
diff --git a/elf/tst-tls21.c b/elf/tst-tls21.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..560bf5813a746417
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tls21.c
|
||||
@@ -0,0 +1,68 @@
|
||||
+/* Test concurrent dlopen and pthread_create: BZ 19329.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <dlfcn.h>
|
||||
+#include <pthread.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdatomic.h>
|
||||
+#include <support/xdlfcn.h>
|
||||
+#include <support/xthread.h>
|
||||
+
|
||||
+#define THREADS 10000
|
||||
+
|
||||
+static atomic_int done;
|
||||
+
|
||||
+static void *
|
||||
+start (void *a)
|
||||
+{
|
||||
+ /* Load a module with many dependencies that each have TLS. */
|
||||
+ xdlopen ("tst-tls21mod.so", RTLD_LAZY);
|
||||
+ atomic_store_explicit (&done, 1, memory_order_release);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+nop (void *a)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ pthread_t t1, t2;
|
||||
+ int i;
|
||||
+
|
||||
+ /* Load a module with lots of dependencies and TLS. */
|
||||
+ t1 = xpthread_create (0, start, 0);
|
||||
+
|
||||
+ /* Concurrently create lots of threads until dlopen is observably done. */
|
||||
+ for (i = 0; i < THREADS; i++)
|
||||
+ {
|
||||
+ if (atomic_load_explicit (&done, memory_order_acquire) != 0)
|
||||
+ break;
|
||||
+ t2 = xpthread_create (0, nop, 0);
|
||||
+ xpthread_join (t2);
|
||||
+ }
|
||||
+
|
||||
+ xpthread_join (t1);
|
||||
+ printf ("threads created during dlopen: %d\n", i);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/elf/tst-tls21mod.c b/elf/tst-tls21mod.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..206ece4fb34622a9
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tls21mod.c
|
||||
@@ -0,0 +1 @@
|
||||
+int __thread x;
|
81
SOURCES/glibc-rh1991001-15.patch
Normal file
81
SOURCES/glibc-rh1991001-15.patch
Normal file
@ -0,0 +1,81 @@
|
||||
commit 572bd547d57a39b6cf0ea072545dc4048921f4c3
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Thu Dec 31 13:59:38 2020 +0000
|
||||
|
||||
elf: Fix DTV gap reuse logic [BZ #27135]
|
||||
|
||||
For some reason only dlopen failure caused dtv gaps to be reused.
|
||||
|
||||
It is possible that the intent was to never reuse modids for a
|
||||
different module, but after dlopen failure all gaps are reused
|
||||
not just the ones caused by the unfinished dlopened.
|
||||
|
||||
So the code has to handle reused modids already which seems to
|
||||
work, however the data races at thread creation and tls access
|
||||
(see bug 19329 and bug 27111) may be more severe if slots are
|
||||
reused so this is scheduled after those fixes. I think fixing
|
||||
the races are not simpler if reuse is disallowed and reuse has
|
||||
other benefits, so set GL(dl_tls_dtv_gaps) whenever entries are
|
||||
removed from the middle of the slotinfo list. The value does
|
||||
not have to be correct: incorrect true value causes the next
|
||||
modid query to do a slotinfo walk, incorrect false will leave
|
||||
gaps and new entries are added at the end.
|
||||
|
||||
Fixes bug 27135.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||
index 7d2dc2272cd643f5..41cb6c58491c364b 100644
|
||||
--- a/elf/dl-close.c
|
||||
+++ b/elf/dl-close.c
|
||||
@@ -88,7 +88,11 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
|
||||
/* If this is not the last currently used entry no need to look
|
||||
further. */
|
||||
if (idx != GL(dl_tls_max_dtv_idx))
|
||||
- return true;
|
||||
+ {
|
||||
+ /* There is an unused dtv entry in the middle. */
|
||||
+ GL(dl_tls_dtv_gaps) = true;
|
||||
+ return true;
|
||||
+ }
|
||||
}
|
||||
|
||||
while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0))
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index a67fb3aee40860e1..54727402750f4c0c 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -896,16 +896,6 @@ no more namespaces available for dlmopen()"));
|
||||
state if relocation failed, for example. */
|
||||
if (args.map)
|
||||
{
|
||||
- /* Maybe some of the modules which were loaded use TLS.
|
||||
- Since it will be removed in the following _dl_close call
|
||||
- we have to mark the dtv array as having gaps to fill the
|
||||
- holes. This is a pessimistic assumption which won't hurt
|
||||
- if not true. There is no need to do this when we are
|
||||
- loading the auditing DSOs since TLS has not yet been set
|
||||
- up. */
|
||||
- if ((mode & __RTLD_AUDIT) == 0)
|
||||
- GL(dl_tls_dtv_gaps) = true;
|
||||
-
|
||||
_dl_close_worker (args.map, true);
|
||||
|
||||
/* All l_nodelete_pending objects should have been deleted
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||
index 801eafad3961573c..bacb4101e2e2c4e5 100644
|
||||
--- a/elf/dl-tls.c
|
||||
+++ b/elf/dl-tls.c
|
||||
@@ -187,10 +187,7 @@ _dl_next_tls_modid (void)
|
||||
size_t
|
||||
_dl_count_modids (void)
|
||||
{
|
||||
- /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
|
||||
- we fail to load a module and unload it leaving a gap. If we don't
|
||||
- have gaps then the number of modids is the current maximum so
|
||||
- return that. */
|
||||
+ /* The count is the max unless dlclose or failed dlopen created gaps. */
|
||||
if (__glibc_likely (!GL(dl_tls_dtv_gaps)))
|
||||
return GL(dl_tls_max_dtv_idx);
|
||||
|
71
SOURCES/glibc-rh1991001-16.patch
Normal file
71
SOURCES/glibc-rh1991001-16.patch
Normal file
@ -0,0 +1,71 @@
|
||||
commit 40ebfd016ad284872f434bdd76dbe9c708db4d6b
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jun 25 08:09:08 2021 +0200
|
||||
|
||||
elf: Disable most of TLS modid gaps processing [BZ #27135]
|
||||
|
||||
Revert "elf: Fix DTV gap reuse logic [BZ #27135]"
|
||||
|
||||
This reverts commit 572bd547d57a39b6cf0ea072545dc4048921f4c3.
|
||||
|
||||
It turns out that the _dl_next_tls_modid in _dl_map_object_from_fd keeps
|
||||
returning the same modid over and over again if there is a gap and
|
||||
more than TLS-using module is loaded in one dlopen call. This corrupts
|
||||
TLS data structures. The bug is still present after a revert, but
|
||||
empirically it is much more difficult to trigger (because it involves a
|
||||
dlopen failure).
|
||||
|
||||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||
index 41cb6c58491c364b..7d2dc2272cd643f5 100644
|
||||
--- a/elf/dl-close.c
|
||||
+++ b/elf/dl-close.c
|
||||
@@ -88,11 +88,7 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
|
||||
/* If this is not the last currently used entry no need to look
|
||||
further. */
|
||||
if (idx != GL(dl_tls_max_dtv_idx))
|
||||
- {
|
||||
- /* There is an unused dtv entry in the middle. */
|
||||
- GL(dl_tls_dtv_gaps) = true;
|
||||
- return true;
|
||||
- }
|
||||
+ return true;
|
||||
}
|
||||
|
||||
while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0))
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index 54727402750f4c0c..a67fb3aee40860e1 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -896,6 +896,16 @@ no more namespaces available for dlmopen()"));
|
||||
state if relocation failed, for example. */
|
||||
if (args.map)
|
||||
{
|
||||
+ /* Maybe some of the modules which were loaded use TLS.
|
||||
+ Since it will be removed in the following _dl_close call
|
||||
+ we have to mark the dtv array as having gaps to fill the
|
||||
+ holes. This is a pessimistic assumption which won't hurt
|
||||
+ if not true. There is no need to do this when we are
|
||||
+ loading the auditing DSOs since TLS has not yet been set
|
||||
+ up. */
|
||||
+ if ((mode & __RTLD_AUDIT) == 0)
|
||||
+ GL(dl_tls_dtv_gaps) = true;
|
||||
+
|
||||
_dl_close_worker (args.map, true);
|
||||
|
||||
/* All l_nodelete_pending objects should have been deleted
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||
index bacb4101e2e2c4e5..801eafad3961573c 100644
|
||||
--- a/elf/dl-tls.c
|
||||
+++ b/elf/dl-tls.c
|
||||
@@ -187,7 +187,10 @@ _dl_next_tls_modid (void)
|
||||
size_t
|
||||
_dl_count_modids (void)
|
||||
{
|
||||
- /* The count is the max unless dlclose or failed dlopen created gaps. */
|
||||
+ /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
|
||||
+ we fail to load a module and unload it leaving a gap. If we don't
|
||||
+ have gaps then the number of modids is the current maximum so
|
||||
+ return that. */
|
||||
if (__glibc_likely (!GL(dl_tls_dtv_gaps)))
|
||||
return GL(dl_tls_max_dtv_idx);
|
||||
|
585
SOURCES/glibc-rh1991001-17.patch
Normal file
585
SOURCES/glibc-rh1991001-17.patch
Normal file
@ -0,0 +1,585 @@
|
||||
commit ba33937be210da5d07f7f01709323743f66011ce
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Fri Jun 25 10:54:12 2021 -0300
|
||||
|
||||
elf: Fix DTV gap reuse logic (BZ #27135)
|
||||
|
||||
This is updated version of the 572bd547d57a (reverted by 40ebfd016ad2)
|
||||
that fixes the _dl_next_tls_modid issues.
|
||||
|
||||
This issue with 572bd547d57a patch is the DTV entry will be only
|
||||
update on dl_open_worker() with the update_tls_slotinfo() call after
|
||||
all dependencies are being processed by _dl_map_object_deps(). However
|
||||
_dl_map_object_deps() itself might call _dl_next_tls_modid(), and since
|
||||
the _dl_tls_dtv_slotinfo_list::map is not yet set the entry will be
|
||||
wrongly reused.
|
||||
|
||||
This patch fixes by renaming the _dl_next_tls_modid() function to
|
||||
_dl_assign_tls_modid() and by passing the link_map so it can set
|
||||
the slotinfo value so a subsequente _dl_next_tls_modid() call will
|
||||
see the entry as allocated.
|
||||
|
||||
The intermediary value is cleared up on remove_slotinfo() for the case
|
||||
a library fails to load with RTLD_NOW.
|
||||
|
||||
This patch fixes BZ #27135.
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(testing differences; libdl removal upstream)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index be40e3761cf91c4a..3e71939d3234c4c3 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -242,6 +242,13 @@ one-hundred = $(foreach x,0 1 2 3 4 5 6 7 8 9, \
|
||||
0$x 1$x 2$x 3$x 4$x 5$x 6$x 7$x 8$x 9$x)
|
||||
tst-tls-many-dynamic-modules := \
|
||||
$(foreach n,$(one-hundred),tst-tls-manydynamic$(n)mod)
|
||||
+tst-tls-many-dynamic-modules-dep-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 \
|
||||
+ 14 15 16 17 18 19
|
||||
+tst-tls-many-dynamic-modules-dep = \
|
||||
+ $(foreach n,$(tst-tls-many-dynamic-modules-dep-suffixes),tst-tls-manydynamic$(n)mod-dep)
|
||||
+tst-tls-many-dynamic-modules-dep-bad-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
||||
+tst-tls-many-dynamic-modules-dep-bad = \
|
||||
+ $(foreach n,$(tst-tls-many-dynamic-modules-dep-bad-suffixes),tst-tls-manydynamic$(n)mod-dep-bad)
|
||||
extra-test-objs += $(tlsmod17a-modules:=.os) $(tlsmod18a-modules:=.os) \
|
||||
tst-tlsalign-vars.o
|
||||
test-extras += tst-tlsmod17a tst-tlsmod18a tst-tlsalign-vars
|
||||
@@ -314,6 +321,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||
tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \
|
||||
tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \
|
||||
tst-latepthreadmod $(tst-tls-many-dynamic-modules) \
|
||||
+ $(tst-tls-many-dynamic-modules-dep) \
|
||||
+ $(tst-tls-many-dynamic-modules-dep-bad) \
|
||||
tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \
|
||||
tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \
|
||||
tst-absolute-zero-lib tst-big-note-lib \
|
||||
@@ -1832,10 +1841,63 @@ $(objpfx)tst-rtld-help.out: $(objpfx)ld.so
|
||||
$(evaluate-test)
|
||||
|
||||
# Reuses tst-tls-many-dynamic-modules
|
||||
+$(patsubst %,$(objpfx)%.os,$(tst-tls-many-dynamic-modules-dep)): \
|
||||
+ $(objpfx)tst-tls-manydynamic%mod-dep.os : tst-tls-manydynamicmod.c
|
||||
+ $(compile-command.c) \
|
||||
+ -DNAME=tls_global_$* -DSETTER=set_value_$* -DGETTER=get_value_$*
|
||||
+$(patsubst %,$(objpfx)%.os,$(tst-tls-many-dynamic-modules-dep-bad)): \
|
||||
+ $(objpfx)tst-tls-manydynamic%mod-dep-bad.os : tst-tls-manydynamicmod.c
|
||||
+ $(compile-command.c) \
|
||||
+ -DNAME=tls_global_$* -DSETTER=set_value_$* -DGETTER=get_value_$*
|
||||
tst-tls20mod-bad.so-no-z-defs = yes
|
||||
+# Single dependency.
|
||||
+$(objpfx)tst-tls-manydynamic0mod-dep.so: $(objpfx)tst-tls-manydynamic1mod-dep.so
|
||||
+# Double dependencies.
|
||||
+$(objpfx)tst-tls-manydynamic2mod-dep.so: $(objpfx)tst-tls-manydynamic3mod-dep.so \
|
||||
+ $(objpfx)tst-tls-manydynamic4mod-dep.so
|
||||
+# Double dependencies with each dependency depent of another module.
|
||||
+$(objpfx)tst-tls-manydynamic5mod-dep.so: $(objpfx)tst-tls-manydynamic6mod-dep.so \
|
||||
+ $(objpfx)tst-tls-manydynamic7mod-dep.so
|
||||
+$(objpfx)tst-tls-manydynamic6mod-dep.so: $(objpfx)tst-tls-manydynamic8mod-dep.so
|
||||
+$(objpfx)tst-tls-manydynamic7mod-dep.so: $(objpfx)tst-tls-manydynamic8mod-dep.so
|
||||
+# Long chain with one double dependency in the middle
|
||||
+$(objpfx)tst-tls-manydynamic9mod-dep.so: $(objpfx)tst-tls-manydynamic10mod-dep.so \
|
||||
+ $(objpfx)tst-tls-manydynamic11mod-dep.so
|
||||
+$(objpfx)tst-tls-manydynamic10mod-dep.so: $(objpfx)tst-tls-manydynamic12mod-dep.so
|
||||
+$(objpfx)tst-tls-manydynamic12mod-dep.so: $(objpfx)tst-tls-manydynamic13mod-dep.so
|
||||
+# Long chain with two double depedencies in the middle
|
||||
+$(objpfx)tst-tls-manydynamic14mod-dep.so: $(objpfx)tst-tls-manydynamic15mod-dep.so
|
||||
+$(objpfx)tst-tls-manydynamic15mod-dep.so: $(objpfx)tst-tls-manydynamic16mod-dep.so \
|
||||
+ $(objpfx)tst-tls-manydynamic17mod-dep.so
|
||||
+$(objpfx)tst-tls-manydynamic16mod-dep.so: $(objpfx)tst-tls-manydynamic18mod-dep.so \
|
||||
+ $(objpfx)tst-tls-manydynamic19mod-dep.so
|
||||
+# Same but with an invalid module.
|
||||
+# Single dependency.
|
||||
+$(objpfx)tst-tls-manydynamic0mod-dep-bad.so: $(objpfx)tst-tls20mod-bad.so
|
||||
+# Double dependencies.
|
||||
+$(objpfx)tst-tls-manydynamic1mod-dep-bad.so: $(objpfx)tst-tls-manydynamic2mod-dep-bad.so \
|
||||
+ $(objpfx)tst-tls20mod-bad.so
|
||||
+# Double dependencies with each dependency depent of another module.
|
||||
+$(objpfx)tst-tls-manydynamic3mod-dep-bad.so: $(objpfx)tst-tls-manydynamic4mod-dep-bad.so \
|
||||
+ $(objpfx)tst-tls-manydynamic5mod-dep-bad.so
|
||||
+$(objpfx)tst-tls-manydynamic4mod-dep-bad.so: $(objpfx)tst-tls20mod-bad.so
|
||||
+$(objpfx)tst-tls-manydynamic5mod-dep-bad.so: $(objpfx)tst-tls20mod-bad.so
|
||||
+# Long chain with one double dependency in the middle
|
||||
+$(objpfx)tst-tls-manydynamic6mod-dep-bad.so: $(objpfx)tst-tls-manydynamic7mod-dep-bad.so \
|
||||
+ $(objpfx)tst-tls-manydynamic8mod-dep-bad.so
|
||||
+$(objpfx)tst-tls-manydynamic7mod-dep-bad.so: $(objpfx)tst-tls-manydynamic9mod-dep-bad.so
|
||||
+$(objpfx)tst-tls-manydynamic9mod-dep-bad.so: $(objpfx)tst-tls20mod-bad.so
|
||||
+# Long chain with two double depedencies in the middle
|
||||
+$(objpfx)tst-tls-manydynamic10mod-dep-bad.so: $(objpfx)tst-tls-manydynamic11mod-dep-bad.so
|
||||
+$(objpfx)tst-tls-manydynamic11mod-dep-bad.so: $(objpfx)tst-tls-manydynamic12mod-dep-bad.so \
|
||||
+ $(objpfx)tst-tls-manydynamic13mod-dep-bad.so
|
||||
+$(objpfx)tst-tls-manydynamic12mod-dep-bad.so: $(objpfx)tst-tls-manydynamic14mod-dep-bad.so \
|
||||
+ $(objpfx)tst-tls20mod-bad.so
|
||||
$(objpfx)tst-tls20: $(libdl) $(shared-thread-library)
|
||||
$(objpfx)tst-tls20.out: $(objpfx)tst-tls20mod-bad.so \
|
||||
- $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so)
|
||||
+ $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so) \
|
||||
+ $(tst-tls-many-dynamic-modules-dep:%=$(objpfx)%.so) \
|
||||
+ $(tst-tls-many-dynamic-modules-dep-bad:%=$(objpfx)%.so) \
|
||||
|
||||
# Reuses tst-tls-many-dynamic-modules
|
||||
$(objpfx)tst-tls21: $(libdl) $(shared-thread-library)
|
||||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||
index 7d2dc2272cd643f5..18227fe992029364 100644
|
||||
--- a/elf/dl-close.c
|
||||
+++ b/elf/dl-close.c
|
||||
@@ -77,8 +77,6 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
|
||||
object that wasn't fully set up. */
|
||||
if (__glibc_likely (old_map != NULL))
|
||||
{
|
||||
- assert (old_map->l_tls_modid == idx);
|
||||
-
|
||||
/* Mark the entry as unused. These can be read concurrently. */
|
||||
atomic_store_relaxed (&listp->slotinfo[idx - disp].gen,
|
||||
GL(dl_tls_generation) + 1);
|
||||
@@ -88,7 +86,11 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
|
||||
/* If this is not the last currently used entry no need to look
|
||||
further. */
|
||||
if (idx != GL(dl_tls_max_dtv_idx))
|
||||
- return true;
|
||||
+ {
|
||||
+ /* There is an unused dtv entry in the middle. */
|
||||
+ GL(dl_tls_dtv_gaps) = true;
|
||||
+ return true;
|
||||
+ }
|
||||
}
|
||||
|
||||
while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0))
|
||||
diff --git a/elf/dl-load.c b/elf/dl-load.c
|
||||
index 80fc38041a936c3c..cdb5d4b5b67f1ca1 100644
|
||||
--- a/elf/dl-load.c
|
||||
+++ b/elf/dl-load.c
|
||||
@@ -1419,7 +1419,7 @@ cannot enable executable stack as shared object requires");
|
||||
not set up TLS data structures, so don't use them now. */
|
||||
|| __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL)))
|
||||
/* Assign the next available module ID. */
|
||||
- l->l_tls_modid = _dl_next_tls_modid ();
|
||||
+ _dl_assign_tls_modid (l);
|
||||
|
||||
#ifdef DL_AFTER_LOAD
|
||||
DL_AFTER_LOAD (l);
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index a67fb3aee40860e1..54727402750f4c0c 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -896,16 +896,6 @@ no more namespaces available for dlmopen()"));
|
||||
state if relocation failed, for example. */
|
||||
if (args.map)
|
||||
{
|
||||
- /* Maybe some of the modules which were loaded use TLS.
|
||||
- Since it will be removed in the following _dl_close call
|
||||
- we have to mark the dtv array as having gaps to fill the
|
||||
- holes. This is a pessimistic assumption which won't hurt
|
||||
- if not true. There is no need to do this when we are
|
||||
- loading the auditing DSOs since TLS has not yet been set
|
||||
- up. */
|
||||
- if ((mode & __RTLD_AUDIT) == 0)
|
||||
- GL(dl_tls_dtv_gaps) = true;
|
||||
-
|
||||
_dl_close_worker (args.map, true);
|
||||
|
||||
/* All l_nodelete_pending objects should have been deleted
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||
index 801eafad3961573c..8c0f9e972d7a0eac 100644
|
||||
--- a/elf/dl-tls.c
|
||||
+++ b/elf/dl-tls.c
|
||||
@@ -122,8 +122,8 @@ oom (void)
|
||||
}
|
||||
|
||||
|
||||
-size_t
|
||||
-_dl_next_tls_modid (void)
|
||||
+void
|
||||
+_dl_assign_tls_modid (struct link_map *l)
|
||||
{
|
||||
size_t result;
|
||||
|
||||
@@ -153,7 +153,11 @@ _dl_next_tls_modid (void)
|
||||
}
|
||||
|
||||
if (result - disp < runp->len)
|
||||
- break;
|
||||
+ {
|
||||
+ /* Mark the entry as used, so any dependency see it. */
|
||||
+ atomic_store_relaxed (&runp->slotinfo[result - disp].map, l);
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
disp += runp->len;
|
||||
}
|
||||
@@ -180,17 +184,14 @@ _dl_next_tls_modid (void)
|
||||
atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), result);
|
||||
}
|
||||
|
||||
- return result;
|
||||
+ l->l_tls_modid = result;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
_dl_count_modids (void)
|
||||
{
|
||||
- /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
|
||||
- we fail to load a module and unload it leaving a gap. If we don't
|
||||
- have gaps then the number of modids is the current maximum so
|
||||
- return that. */
|
||||
+ /* The count is the max unless dlclose or failed dlopen created gaps. */
|
||||
if (__glibc_likely (!GL(dl_tls_dtv_gaps)))
|
||||
return GL(dl_tls_max_dtv_idx);
|
||||
|
||||
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||
index 992f825ba00762a7..118c454a2329573f 100644
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -1693,7 +1693,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||
/* Add the dynamic linker to the TLS list if it also uses TLS. */
|
||||
if (GL(dl_rtld_map).l_tls_blocksize != 0)
|
||||
/* Assign a module ID. Do this before loading any audit modules. */
|
||||
- GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
|
||||
+ _dl_assign_tls_modid (&GL(dl_rtld_map));
|
||||
|
||||
audit_list_add_dynamic_tag (&state.audit_list, main_map, DT_AUDIT);
|
||||
audit_list_add_dynamic_tag (&state.audit_list, main_map, DT_DEPAUDIT);
|
||||
diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
|
||||
index 9977ec803208b9c8..d8d04fe574597f35 100644
|
||||
--- a/elf/tst-tls20.c
|
||||
+++ b/elf/tst-tls20.c
|
||||
@@ -16,12 +16,14 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
+#include <array_length.h>
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
+#include <support/test-driver.h>
|
||||
#include <support/xdlfcn.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
@@ -59,28 +61,75 @@ access (int i)
|
||||
char *buf = xasprintf ("tls_global_%02d", i);
|
||||
dlerror ();
|
||||
int *p = dlsym (mod[i], buf);
|
||||
- printf ("mod[%d]: &tls = %p\n", i, p);
|
||||
+ if (test_verbose)
|
||||
+ printf ("mod[%d]: &tls = %p\n", i, p);
|
||||
if (p == NULL)
|
||||
FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
|
||||
+ TEST_COMPARE (*p, 0);
|
||||
++*p;
|
||||
free (buf);
|
||||
}
|
||||
|
||||
+static void
|
||||
+access_mod (const char *modname, void *mod, int i)
|
||||
+{
|
||||
+ char *modsym = xasprintf ("tls_global_%d", i);
|
||||
+ dlerror ();
|
||||
+ int *p = dlsym (mod, modsym);
|
||||
+ if (test_verbose)
|
||||
+ printf ("%s: &tls = %p\n", modname, p);
|
||||
+ if (p == NULL)
|
||||
+ FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
|
||||
+ TEST_COMPARE (*p, 0);
|
||||
+ ++*p;
|
||||
+ free (modsym);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+access_dep (int i)
|
||||
+{
|
||||
+ char *modname = xasprintf ("tst-tls-manydynamic%dmod-dep.so", i);
|
||||
+ void *moddep = xdlopen (modname, RTLD_LAZY);
|
||||
+ access_mod (modname, moddep, i);
|
||||
+ free (modname);
|
||||
+ xdlclose (moddep);
|
||||
+}
|
||||
+
|
||||
+struct start_args
|
||||
+{
|
||||
+ const char *modname;
|
||||
+ void *mod;
|
||||
+ int modi;
|
||||
+ int ndeps;
|
||||
+ const int *deps;
|
||||
+};
|
||||
+
|
||||
static void *
|
||||
start (void *a)
|
||||
{
|
||||
+ struct start_args *args = a;
|
||||
+
|
||||
for (int i = 0; i < NMOD; i++)
|
||||
if (mod[i] != NULL)
|
||||
access (i);
|
||||
+
|
||||
+ if (args != NULL)
|
||||
+ {
|
||||
+ access_mod (args->modname, args->mod, args->modi);
|
||||
+ for (int n = 0; n < args->ndeps; n++)
|
||||
+ access_dep (args->deps[n]);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int
|
||||
-do_test (void)
|
||||
+/* This test gaps with shared libraries with dynamic TLS that has no
|
||||
+ dependencies. The DTV gap is set with by trying to load an invalid
|
||||
+ module, the entry should be used on the dlopen. */
|
||||
+static void
|
||||
+do_test_no_depedency (void)
|
||||
{
|
||||
- int i;
|
||||
-
|
||||
- for (i = 0; i < NMOD; i++)
|
||||
+ for (int i = 0; i < NMOD; i++)
|
||||
{
|
||||
load_mod (i);
|
||||
/* Bump the generation of mod[0] without using new dtv slot. */
|
||||
@@ -91,8 +140,220 @@ do_test (void)
|
||||
pthread_t t = xpthread_create (0, start, 0);
|
||||
xpthread_join (t);
|
||||
}
|
||||
- for (i = 0; i < NMOD; i++)
|
||||
+ for (int i = 0; i < NMOD; i++)
|
||||
unload_mod (i);
|
||||
+}
|
||||
+
|
||||
+/* The following test check DTV gaps handling with shared libraries that has
|
||||
+ dependencies. It defines 5 different sets:
|
||||
+
|
||||
+ 1. Single dependency:
|
||||
+ mod0 -> mod1
|
||||
+ 2. Double dependency:
|
||||
+ mod2 -> [mod3,mod4]
|
||||
+ 3. Double dependency with each dependency depent of another module:
|
||||
+ mod5 -> [mod6,mod7] -> mod8
|
||||
+ 4. Long chain with one double dependency in the middle:
|
||||
+ mod9 -> [mod10, mod11] -> mod12 -> mod13
|
||||
+ 5. Long chain with two double depedencies in the middle:
|
||||
+ mod14 -> mod15 -> [mod16, mod17]
|
||||
+ mod15 -> [mod18, mod19]
|
||||
+
|
||||
+ This does not cover all the possible gaps and configuration, but it
|
||||
+ should check if different dynamic shared sets are placed correctly in
|
||||
+ different gaps configurations. */
|
||||
+
|
||||
+static int
|
||||
+nmodules (uint32_t v)
|
||||
+{
|
||||
+ unsigned int r = 0;
|
||||
+ while (v >>= 1)
|
||||
+ r++;
|
||||
+ return r + 1;
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+is_mod_set (uint32_t g, uint32_t n)
|
||||
+{
|
||||
+ return (1U << (n - 1)) & g;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+print_gap (uint32_t g)
|
||||
+{
|
||||
+ if (!test_verbose)
|
||||
+ return;
|
||||
+ printf ("gap: ");
|
||||
+ int nmods = nmodules (g);
|
||||
+ for (int n = 1; n <= nmods; n++)
|
||||
+ printf ("%c", ((1 << (n - 1)) & g) == 0 ? 'G' : 'M');
|
||||
+ printf ("\n");
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_test_dependency (void)
|
||||
+{
|
||||
+ /* Maps the module and its dependencies, use thread to access the TLS on
|
||||
+ each loaded module. */
|
||||
+ static const int tlsmanydeps0[] = { 1 };
|
||||
+ static const int tlsmanydeps1[] = { 3, 4 };
|
||||
+ static const int tlsmanydeps2[] = { 6, 7, 8 };
|
||||
+ static const int tlsmanydeps3[] = { 10, 11, 12 };
|
||||
+ static const int tlsmanydeps4[] = { 15, 16, 17, 18, 19 };
|
||||
+ static const struct tlsmanydeps_t
|
||||
+ {
|
||||
+ int modi;
|
||||
+ int ndeps;
|
||||
+ const int *deps;
|
||||
+ } tlsmanydeps[] =
|
||||
+ {
|
||||
+ { 0, array_length (tlsmanydeps0), tlsmanydeps0 },
|
||||
+ { 2, array_length (tlsmanydeps1), tlsmanydeps1 },
|
||||
+ { 5, array_length (tlsmanydeps2), tlsmanydeps2 },
|
||||
+ { 9, array_length (tlsmanydeps3), tlsmanydeps3 },
|
||||
+ { 14, array_length (tlsmanydeps4), tlsmanydeps4 },
|
||||
+ };
|
||||
+
|
||||
+ /* The gap configuration is defined as a bitmap: the bit set represents a
|
||||
+ loaded module prior the tests execution, while a bit unsed is a module
|
||||
+ unloaded. Not all permtation will show gaps, but it is simpler than
|
||||
+ define each one independently. */
|
||||
+ for (uint32_t g = 0; g < 64; g++)
|
||||
+ {
|
||||
+ print_gap (g);
|
||||
+ int nmods = nmodules (g);
|
||||
+
|
||||
+ int mods[nmods];
|
||||
+ /* We use '0' as indication for a gap, to avoid the dlclose on iteration
|
||||
+ cleanup. */
|
||||
+ for (int n = 1; n <= nmods; n++)
|
||||
+ {
|
||||
+ load_mod (n);
|
||||
+ mods[n] = n;
|
||||
+ }
|
||||
+ for (int n = 1; n <= nmods; n++)
|
||||
+ {
|
||||
+ if (!is_mod_set (g, n))
|
||||
+ {
|
||||
+ unload_mod (n);
|
||||
+ mods[n] = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for (int t = 0; t < array_length (tlsmanydeps); t++)
|
||||
+ {
|
||||
+ char *moddepname = xasprintf ("tst-tls-manydynamic%dmod-dep.so",
|
||||
+ tlsmanydeps[t].modi);
|
||||
+ void *moddep = xdlopen (moddepname, RTLD_LAZY);
|
||||
+
|
||||
+ /* Access TLS in all loaded modules. */
|
||||
+ struct start_args args =
|
||||
+ {
|
||||
+ moddepname,
|
||||
+ moddep,
|
||||
+ tlsmanydeps[t].modi,
|
||||
+ tlsmanydeps[t].ndeps,
|
||||
+ tlsmanydeps[t].deps
|
||||
+ };
|
||||
+ pthread_t t = xpthread_create (0, start, &args);
|
||||
+ xpthread_join (t);
|
||||
+
|
||||
+ free (moddepname);
|
||||
+ xdlclose (moddep);
|
||||
+ }
|
||||
+
|
||||
+ for (int n = 1; n <= nmods; n++)
|
||||
+ if (mods[n] != 0)
|
||||
+ unload_mod (n);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* The following test check DTV gaps handling with shared libraries that has
|
||||
+ invalid dependencies. It defines 5 different sets:
|
||||
+
|
||||
+ 1. Single dependency:
|
||||
+ mod0 -> invalid
|
||||
+ 2. Double dependency:
|
||||
+ mod1 -> [mod2,invalid]
|
||||
+ 3. Double dependency with each dependency depent of another module:
|
||||
+ mod3 -> [mod4,mod5] -> invalid
|
||||
+ 4. Long chain with one double dependency in the middle:
|
||||
+ mod6 -> [mod7, mod8] -> mod12 -> invalid
|
||||
+ 5. Long chain with two double depedencies in the middle:
|
||||
+ mod10 -> mod11 -> [mod12, mod13]
|
||||
+ mod12 -> [mod14, invalid]
|
||||
+
|
||||
+ This does not cover all the possible gaps and configuration, but it
|
||||
+ should check if different dynamic shared sets are placed correctly in
|
||||
+ different gaps configurations. */
|
||||
+
|
||||
+static void
|
||||
+do_test_invalid_dependency (bool bind_now)
|
||||
+{
|
||||
+ static const int tlsmanydeps[] = { 0, 1, 3, 6, 10 };
|
||||
+
|
||||
+ /* The gap configuration is defined as a bitmap: the bit set represents a
|
||||
+ loaded module prior the tests execution, while a bit unsed is a module
|
||||
+ unloaded. Not all permtation will show gaps, but it is simpler than
|
||||
+ define each one independently. */
|
||||
+ for (uint32_t g = 0; g < 64; g++)
|
||||
+ {
|
||||
+ print_gap (g);
|
||||
+ int nmods = nmodules (g);
|
||||
+
|
||||
+ int mods[nmods];
|
||||
+ /* We use '0' as indication for a gap, to avoid the dlclose on iteration
|
||||
+ cleanup. */
|
||||
+ for (int n = 1; n <= nmods; n++)
|
||||
+ {
|
||||
+ load_mod (n);
|
||||
+ mods[n] = n;
|
||||
+ }
|
||||
+ for (int n = 1; n <= nmods; n++)
|
||||
+ {
|
||||
+ if (!is_mod_set (g, n))
|
||||
+ {
|
||||
+ unload_mod (n);
|
||||
+ mods[n] = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for (int t = 0; t < array_length (tlsmanydeps); t++)
|
||||
+ {
|
||||
+ char *moddepname = xasprintf ("tst-tls-manydynamic%dmod-dep-bad.so",
|
||||
+ tlsmanydeps[t]);
|
||||
+ void *moddep;
|
||||
+ if (bind_now)
|
||||
+ {
|
||||
+ moddep = dlopen (moddepname, RTLD_NOW);
|
||||
+ TEST_VERIFY (moddep == 0);
|
||||
+ }
|
||||
+ else
|
||||
+ moddep = dlopen (moddepname, RTLD_LAZY);
|
||||
+
|
||||
+ /* Access TLS in all loaded modules. */
|
||||
+ pthread_t t = xpthread_create (0, start, NULL);
|
||||
+ xpthread_join (t);
|
||||
+
|
||||
+ free (moddepname);
|
||||
+ if (!bind_now)
|
||||
+ xdlclose (moddep);
|
||||
+ }
|
||||
+
|
||||
+ for (int n = 1; n <= nmods; n++)
|
||||
+ if (mods[n] != 0)
|
||||
+ unload_mod (n);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ do_test_no_depedency ();
|
||||
+ do_test_dependency ();
|
||||
+ do_test_invalid_dependency (true);
|
||||
+ do_test_invalid_dependency (false);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||
index 6cbbaa808a596f77..0138353ccb41c5f1 100644
|
||||
--- a/sysdeps/generic/ldsodefs.h
|
||||
+++ b/sysdeps/generic/ldsodefs.h
|
||||
@@ -1111,8 +1111,8 @@ extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
|
||||
extern void _dl_sysdep_start_cleanup (void) attribute_hidden;
|
||||
|
||||
|
||||
-/* Determine next available module ID. */
|
||||
-extern size_t _dl_next_tls_modid (void) attribute_hidden;
|
||||
+/* Determine next available module ID and set the L l_tls_modid. */
|
||||
+extern void _dl_assign_tls_modid (struct link_map *l) attribute_hidden;
|
||||
|
||||
/* Count the modules with TLS segments. */
|
||||
extern size_t _dl_count_modids (void) attribute_hidden;
|
42
SOURCES/glibc-rh1991001-18.patch
Normal file
42
SOURCES/glibc-rh1991001-18.patch
Normal file
@ -0,0 +1,42 @@
|
||||
commit 881b68e45c3a518319dcf5a3c4a2b3ec59e1c1e5
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Fri Jul 16 08:32:05 2021 -0300
|
||||
|
||||
elf: Fix a wrong array access on tst-tls20
|
||||
|
||||
Check on x86_64-linux-gnu with --enable-stack-protector=all.
|
||||
|
||||
diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
|
||||
index d8d04fe574597f35..831c3336c914790d 100644
|
||||
--- a/elf/tst-tls20.c
|
||||
+++ b/elf/tst-tls20.c
|
||||
@@ -226,12 +226,12 @@ do_test_dependency (void)
|
||||
int mods[nmods];
|
||||
/* We use '0' as indication for a gap, to avoid the dlclose on iteration
|
||||
cleanup. */
|
||||
- for (int n = 1; n <= nmods; n++)
|
||||
+ for (int n = 1; n < nmods; n++)
|
||||
{
|
||||
load_mod (n);
|
||||
mods[n] = n;
|
||||
}
|
||||
- for (int n = 1; n <= nmods; n++)
|
||||
+ for (int n = 1; n < nmods; n++)
|
||||
{
|
||||
if (!is_mod_set (g, n))
|
||||
{
|
||||
@@ -304,12 +304,12 @@ do_test_invalid_dependency (bool bind_now)
|
||||
int mods[nmods];
|
||||
/* We use '0' as indication for a gap, to avoid the dlclose on iteration
|
||||
cleanup. */
|
||||
- for (int n = 1; n <= nmods; n++)
|
||||
+ for (int n = 1; n < nmods; n++)
|
||||
{
|
||||
load_mod (n);
|
||||
mods[n] = n;
|
||||
}
|
||||
- for (int n = 1; n <= nmods; n++)
|
||||
+ for (int n = 1; n < nmods; n++)
|
||||
{
|
||||
if (!is_mod_set (g, n))
|
||||
{
|
468
SOURCES/glibc-rh1991001-19.patch
Normal file
468
SOURCES/glibc-rh1991001-19.patch
Normal file
@ -0,0 +1,468 @@
|
||||
commit 83b5323261bb72313bffcf37476c1b8f0847c736
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Wed Sep 15 15:16:19 2021 +0100
|
||||
|
||||
elf: Avoid deadlock between pthread_create and ctors [BZ #28357]
|
||||
|
||||
The fix for bug 19329 caused a regression such that pthread_create can
|
||||
deadlock when concurrent ctors from dlopen are waiting for it to finish.
|
||||
Use a new GL(dl_load_tls_lock) in pthread_create that is not taken
|
||||
around ctors in dlopen.
|
||||
|
||||
The new lock is also used in __tls_get_addr instead of GL(dl_load_lock).
|
||||
|
||||
The new lock is held in _dl_open_worker and _dl_close_worker around
|
||||
most of the logic before/after the init/fini routines. When init/fini
|
||||
routines are running then TLS is in a consistent, usable state.
|
||||
In _dl_open_worker the new lock requires catching and reraising dlopen
|
||||
failures that happen in the critical section.
|
||||
|
||||
The new lock is reinitialized in a fork child, to keep the existing
|
||||
behaviour and it is kept recursive in case malloc interposition or TLS
|
||||
access from signal handlers can retake it. It is not obvious if this
|
||||
is necessary or helps, but avoids changing the preexisting behaviour.
|
||||
|
||||
The new lock may be more appropriate for dl_iterate_phdr too than
|
||||
GL(dl_load_write_lock), since TLS state of an incompletely loaded
|
||||
module may be accessed. If the new lock can replace the old one,
|
||||
that can be a separate change.
|
||||
|
||||
Fixes bug 28357.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
Conflicts:
|
||||
posix/fork.c
|
||||
(reworked due to file rename upstream and libpthread integration)
|
||||
sysdeps/pthread/Makefile
|
||||
(htl testing support was missing downstream, reconstituted here;
|
||||
added $(libdl) required downstream)
|
||||
|
||||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||
index 18227fe992029364..7fe91bdd9aaf694e 100644
|
||||
--- a/elf/dl-close.c
|
||||
+++ b/elf/dl-close.c
|
||||
@@ -549,6 +549,9 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
size_t tls_free_end;
|
||||
tls_free_start = tls_free_end = NO_TLS_OFFSET;
|
||||
|
||||
+ /* Protects global and module specitic TLS state. */
|
||||
+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
|
||||
+
|
||||
/* We modify the list of loaded objects. */
|
||||
__rtld_lock_lock_recursive (GL(dl_load_write_lock));
|
||||
|
||||
@@ -784,6 +787,9 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
GL(dl_tls_static_used) = tls_free_start;
|
||||
}
|
||||
|
||||
+ /* TLS is cleaned up for the unloaded modules. */
|
||||
+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
+
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we have deleted all objects. */
|
||||
if (__glibc_unlikely (do_audit))
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index 54727402750f4c0c..736df62ce6e46d34 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -65,6 +65,9 @@ struct dl_open_args
|
||||
libc_map value in the namespace in case of a dlopen failure. */
|
||||
bool libc_already_loaded;
|
||||
|
||||
+ /* Set to true if the end of dl_open_worker_begin was reached. */
|
||||
+ bool worker_continue;
|
||||
+
|
||||
/* Original parameters to the program and the current environment. */
|
||||
int argc;
|
||||
char **argv;
|
||||
@@ -481,7 +484,7 @@ call_dl_init (void *closure)
|
||||
}
|
||||
|
||||
static void
|
||||
-dl_open_worker (void *a)
|
||||
+dl_open_worker_begin (void *a)
|
||||
{
|
||||
struct dl_open_args *args = a;
|
||||
const char *file = args->file;
|
||||
@@ -772,6 +775,36 @@ dl_open_worker (void *a)
|
||||
DL_STATIC_INIT (new);
|
||||
#endif
|
||||
|
||||
+ args->worker_continue = true;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+dl_open_worker (void *a)
|
||||
+{
|
||||
+ struct dl_open_args *args = a;
|
||||
+
|
||||
+ args->worker_continue = false;
|
||||
+
|
||||
+ {
|
||||
+ /* Protects global and module specific TLS state. */
|
||||
+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
|
||||
+
|
||||
+ struct dl_exception ex;
|
||||
+ int err = _dl_catch_exception (&ex, dl_open_worker_begin, args);
|
||||
+
|
||||
+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
+
|
||||
+ if (__glibc_unlikely (ex.errstring != NULL))
|
||||
+ /* Reraise the error. */
|
||||
+ _dl_signal_exception (err, &ex, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (!args->worker_continue)
|
||||
+ return;
|
||||
+
|
||||
+ int mode = args->mode;
|
||||
+ struct link_map *new = args->map;
|
||||
+
|
||||
/* Run the initializer functions of new objects. Temporarily
|
||||
disable the exception handler, so that lazy binding failures are
|
||||
fatal. */
|
||||
diff --git a/elf/dl-support.c b/elf/dl-support.c
|
||||
index 34be8e5babfb6af3..3e5531138eaa18f8 100644
|
||||
--- a/elf/dl-support.c
|
||||
+++ b/elf/dl-support.c
|
||||
@@ -212,6 +212,13 @@ __rtld_lock_define_initialized_recursive (, _dl_load_lock)
|
||||
list of loaded objects while an object is added to or removed from
|
||||
that list. */
|
||||
__rtld_lock_define_initialized_recursive (, _dl_load_write_lock)
|
||||
+ /* This lock protects global and module specific TLS related data.
|
||||
+ E.g. it is held in dlopen and dlclose when GL(dl_tls_generation),
|
||||
+ GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are
|
||||
+ accessed and when TLS related relocations are processed for a
|
||||
+ module. It was introduced to keep pthread_create accessing TLS
|
||||
+ state that is being set up. */
|
||||
+__rtld_lock_define_initialized_recursive (, _dl_load_tls_lock)
|
||||
|
||||
|
||||
#ifdef HAVE_AUX_VECTOR
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||
index 8c0f9e972d7a0eac..7865fc390c3f3f0a 100644
|
||||
--- a/elf/dl-tls.c
|
||||
+++ b/elf/dl-tls.c
|
||||
@@ -527,7 +527,7 @@ _dl_allocate_tls_init (void *result)
|
||||
size_t maxgen = 0;
|
||||
|
||||
/* Protects global dynamic TLS related state. */
|
||||
- __rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
|
||||
|
||||
/* Check if the current dtv is big enough. */
|
||||
if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
|
||||
@@ -601,7 +601,7 @@ _dl_allocate_tls_init (void *result)
|
||||
listp = listp->next;
|
||||
assert (listp != NULL);
|
||||
}
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
|
||||
/* The DTV version is up-to-date now. */
|
||||
dtv[0].counter = maxgen;
|
||||
@@ -740,7 +740,7 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
|
||||
Here the dtv needs to be updated to new_gen generation count.
|
||||
|
||||
- This code may be called during TLS access when GL(dl_load_lock)
|
||||
+ This code may be called during TLS access when GL(dl_load_tls_lock)
|
||||
is not held. In that case the user code has to synchronize with
|
||||
dlopen and dlclose calls of relevant modules. A module m is
|
||||
relevant if the generation of m <= new_gen and dlclose of m is
|
||||
@@ -862,11 +862,11 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
|
||||
if (__glibc_unlikely (the_map->l_tls_offset
|
||||
!= FORCED_DYNAMIC_TLS_OFFSET))
|
||||
{
|
||||
- __rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
|
||||
if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET))
|
||||
{
|
||||
the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
}
|
||||
else if (__glibc_likely (the_map->l_tls_offset
|
||||
!= FORCED_DYNAMIC_TLS_OFFSET))
|
||||
@@ -878,7 +878,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
|
||||
#else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
|
||||
dtv[GET_ADDR_MODULE].pointer.to_free = NULL;
|
||||
dtv[GET_ADDR_MODULE].pointer.val = p;
|
||||
@@ -886,7 +886,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
|
||||
return (char *) p + GET_ADDR_OFFSET;
|
||||
}
|
||||
else
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
}
|
||||
struct dtv_pointer result = allocate_and_init (the_map);
|
||||
dtv[GET_ADDR_MODULE].pointer = result;
|
||||
@@ -957,7 +957,7 @@ _dl_tls_get_addr_soft (struct link_map *l)
|
||||
return NULL;
|
||||
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
- /* This may be called without holding the GL(dl_load_lock). Reading
|
||||
+ /* This may be called without holding the GL(dl_load_tls_lock). Reading
|
||||
arbitrary gen value is fine since this is best effort code. */
|
||||
size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
|
||||
if (__glibc_unlikely (dtv[0].counter != gen))
|
||||
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||
index 118c454a2329573f..9e09896da078274d 100644
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -317,6 +317,7 @@ struct rtld_global _rtld_global =
|
||||
#ifdef _LIBC_REENTRANT
|
||||
._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
||||
._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
||||
+ ._dl_load_tls_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
||||
#endif
|
||||
._dl_nns = 1,
|
||||
._dl_ns =
|
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||
index 0138353ccb41c5f1..7b0a667629ddc06a 100644
|
||||
--- a/sysdeps/generic/ldsodefs.h
|
||||
+++ b/sysdeps/generic/ldsodefs.h
|
||||
@@ -373,6 +373,13 @@ struct rtld_global
|
||||
list of loaded objects while an object is added to or removed
|
||||
from that list. */
|
||||
__rtld_lock_define_recursive (EXTERN, _dl_load_write_lock)
|
||||
+ /* This lock protects global and module specific TLS related data.
|
||||
+ E.g. it is held in dlopen and dlclose when GL(dl_tls_generation),
|
||||
+ GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are
|
||||
+ accessed and when TLS related relocations are processed for a
|
||||
+ module. It was introduced to keep pthread_create accessing TLS
|
||||
+ state that is being set up. */
|
||||
+ __rtld_lock_define_recursive (EXTERN, _dl_load_tls_lock)
|
||||
|
||||
/* Incremented whenever something may have been added to dl_loaded. */
|
||||
EXTERN unsigned long long _dl_load_adds;
|
||||
@@ -1192,7 +1199,7 @@ extern int _dl_scope_free (void *) attribute_hidden;
|
||||
|
||||
/* Add module to slot information data. If DO_ADD is false, only the
|
||||
required memory is allocated. Must be called with GL
|
||||
- (dl_load_lock) acquired. If the function has already been called
|
||||
+ (dl_load_tls_lock) acquired. If the function has already been called
|
||||
for the link map L with !do_add, then this function will not raise
|
||||
an exception, otherwise it is possible that it encounters a memory
|
||||
allocation failure. */
|
||||
diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
|
||||
index 37db30f3d1e846b6..b4d20fa652f4ba3b 100644
|
||||
--- a/sysdeps/nptl/fork.c
|
||||
+++ b/sysdeps/nptl/fork.c
|
||||
@@ -125,6 +125,9 @@ __libc_fork (void)
|
||||
/* Reset the lock the dynamic loader uses to protect its data. */
|
||||
__rtld_lock_initialize (GL(dl_load_lock));
|
||||
|
||||
+ /* Reset the lock protecting dynamic TLS related data. */
|
||||
+ __rtld_lock_initialize (GL(dl_load_tls_lock));
|
||||
+
|
||||
/* Run the handlers registered for the child. */
|
||||
__run_fork_handlers (atfork_run_child, multiple_threads);
|
||||
}
|
||||
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
|
||||
index ea4f8894891b2636..98a92f8d6bb119ba 100644
|
||||
--- a/sysdeps/pthread/Makefile
|
||||
+++ b/sysdeps/pthread/Makefile
|
||||
@@ -25,3 +25,24 @@ $(objpfx)tst-timer: $(objpfx)librt.a $(static-thread-library)
|
||||
endif
|
||||
|
||||
endif
|
||||
+
|
||||
+ifneq (,$(filter $(subdir),htl nptl))
|
||||
+ifeq ($(build-shared),yes)
|
||||
+tests += tst-create1
|
||||
+endif
|
||||
+
|
||||
+tst-create1mod.so-no-z-defs = yes
|
||||
+
|
||||
+ifeq ($(build-shared),yes)
|
||||
+# Build all the modules even when not actually running test programs.
|
||||
+tests: $(test-modules)
|
||||
+endif
|
||||
+
|
||||
+modules-names += tst-create1mod
|
||||
+test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
|
||||
+
|
||||
+LDFLAGS-tst-create1 = -Wl,-export-dynamic
|
||||
+$(objpfx)tst-create1: $(libdl) $(shared-thread-library)
|
||||
+$(objpfx)tst-create1.out: $(objpfx)tst-create1mod.so
|
||||
+
|
||||
+endif
|
||||
diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..932586c30990d1d4
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/pthread/tst-create1.c
|
||||
@@ -0,0 +1,119 @@
|
||||
+/* Verify that pthread_create does not deadlock when ctors take locks.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <support/xdlfcn.h>
|
||||
+#include <support/xthread.h>
|
||||
+
|
||||
+/*
|
||||
+Check if ctor and pthread_create deadlocks in
|
||||
+
|
||||
+thread 1: dlopen -> ctor -> lock(user_lock)
|
||||
+thread 2: lock(user_lock) -> pthread_create
|
||||
+
|
||||
+or in
|
||||
+
|
||||
+thread 1: dlclose -> dtor -> lock(user_lock)
|
||||
+thread 2: lock(user_lock) -> pthread_create
|
||||
+*/
|
||||
+
|
||||
+static pthread_barrier_t bar_ctor;
|
||||
+static pthread_barrier_t bar_dtor;
|
||||
+static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
+
|
||||
+void
|
||||
+ctor (void)
|
||||
+{
|
||||
+ xpthread_barrier_wait (&bar_ctor);
|
||||
+ dprintf (1, "thread 1: in ctor: started.\n");
|
||||
+ xpthread_mutex_lock (&user_lock);
|
||||
+ dprintf (1, "thread 1: in ctor: locked user_lock.\n");
|
||||
+ xpthread_mutex_unlock (&user_lock);
|
||||
+ dprintf (1, "thread 1: in ctor: unlocked user_lock.\n");
|
||||
+ dprintf (1, "thread 1: in ctor: done.\n");
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+dtor (void)
|
||||
+{
|
||||
+ xpthread_barrier_wait (&bar_dtor);
|
||||
+ dprintf (1, "thread 1: in dtor: started.\n");
|
||||
+ xpthread_mutex_lock (&user_lock);
|
||||
+ dprintf (1, "thread 1: in dtor: locked user_lock.\n");
|
||||
+ xpthread_mutex_unlock (&user_lock);
|
||||
+ dprintf (1, "thread 1: in dtor: unlocked user_lock.\n");
|
||||
+ dprintf (1, "thread 1: in dtor: done.\n");
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+thread3 (void *a)
|
||||
+{
|
||||
+ dprintf (1, "thread 3: started.\n");
|
||||
+ dprintf (1, "thread 3: done.\n");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+thread2 (void *a)
|
||||
+{
|
||||
+ pthread_t t3;
|
||||
+ dprintf (1, "thread 2: started.\n");
|
||||
+
|
||||
+ xpthread_mutex_lock (&user_lock);
|
||||
+ dprintf (1, "thread 2: locked user_lock.\n");
|
||||
+ xpthread_barrier_wait (&bar_ctor);
|
||||
+ t3 = xpthread_create (0, thread3, 0);
|
||||
+ xpthread_mutex_unlock (&user_lock);
|
||||
+ dprintf (1, "thread 2: unlocked user_lock.\n");
|
||||
+ xpthread_join (t3);
|
||||
+
|
||||
+ xpthread_mutex_lock (&user_lock);
|
||||
+ dprintf (1, "thread 2: locked user_lock.\n");
|
||||
+ xpthread_barrier_wait (&bar_dtor);
|
||||
+ t3 = xpthread_create (0, thread3, 0);
|
||||
+ xpthread_mutex_unlock (&user_lock);
|
||||
+ dprintf (1, "thread 2: unlocked user_lock.\n");
|
||||
+ xpthread_join (t3);
|
||||
+
|
||||
+ dprintf (1, "thread 2: done.\n");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+thread1 (void)
|
||||
+{
|
||||
+ dprintf (1, "thread 1: started.\n");
|
||||
+ xpthread_barrier_init (&bar_ctor, NULL, 2);
|
||||
+ xpthread_barrier_init (&bar_dtor, NULL, 2);
|
||||
+ pthread_t t2 = xpthread_create (0, thread2, 0);
|
||||
+ void *p = xdlopen ("tst-create1mod.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
+ dprintf (1, "thread 1: dlopen done.\n");
|
||||
+ xdlclose (p);
|
||||
+ dprintf (1, "thread 1: dlclose done.\n");
|
||||
+ xpthread_join (t2);
|
||||
+ dprintf (1, "thread 1: done.\n");
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ thread1 ();
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/sysdeps/pthread/tst-create1mod.c b/sysdeps/pthread/tst-create1mod.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..62c9006961683177
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/pthread/tst-create1mod.c
|
||||
@@ -0,0 +1,41 @@
|
||||
+/* Verify that pthread_create does not deadlock when ctors take locks.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+/* Require TLS setup for the module. */
|
||||
+__thread int tlsvar;
|
||||
+
|
||||
+void ctor (void);
|
||||
+void dtor (void);
|
||||
+
|
||||
+static void __attribute__ ((constructor))
|
||||
+do_init (void)
|
||||
+{
|
||||
+ dprintf (1, "constructor started: %d.\n", tlsvar++);
|
||||
+ ctor ();
|
||||
+ dprintf (1, "constructor done: %d.\n", tlsvar++);
|
||||
+}
|
||||
+
|
||||
+static void __attribute__ ((destructor))
|
||||
+do_end (void)
|
||||
+{
|
||||
+ dprintf (1, "destructor started: %d.\n", tlsvar++);
|
||||
+ dtor ();
|
||||
+ dprintf (1, "destructor done: %d.\n", tlsvar++);
|
||||
+}
|
28
SOURCES/glibc-rh1991001-2.patch
Normal file
28
SOURCES/glibc-rh1991001-2.patch
Normal file
@ -0,0 +1,28 @@
|
||||
commit d2b997c7172e9a00895a9deb379f8782fbd2e36f
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Wed Dec 30 23:40:14 2020 +0000
|
||||
|
||||
elf: Fix a DTV setup issue [BZ #27136]
|
||||
|
||||
The max modid is a valid index in the dtv, it should not be skipped.
|
||||
|
||||
The bug is observable if the last module has modid == 64 and its
|
||||
generation is same or less than the max generation of the previous
|
||||
modules. Then dtv[0].counter implies dtv[64] is initialized but
|
||||
it isn't. Fixes bug 27136.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||
index cccf74b33481b866..0b96b1dceed99d58 100644
|
||||
--- a/elf/dl-tls.c
|
||||
+++ b/elf/dl-tls.c
|
||||
@@ -590,7 +590,7 @@ _dl_allocate_tls_init (void *result)
|
||||
}
|
||||
|
||||
total += cnt;
|
||||
- if (total >= GL(dl_tls_max_dtv_idx))
|
||||
+ if (total > GL(dl_tls_max_dtv_idx))
|
||||
break;
|
||||
|
||||
listp = listp->next;
|
20
SOURCES/glibc-rh1991001-20.patch
Normal file
20
SOURCES/glibc-rh1991001-20.patch
Normal file
@ -0,0 +1,20 @@
|
||||
commit 3c7c5117826816021f9d3f352f49e0dd0236cbad
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Nov 30 14:35:54 2021 +0100
|
||||
|
||||
elf: Include <stdint.h> in tst-tls20.c
|
||||
|
||||
The test uses standard integer types.
|
||||
|
||||
diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
|
||||
index 831c3336c914790d..18067e6b0a6093f9 100644
|
||||
--- a/elf/tst-tls20.c
|
||||
+++ b/elf/tst-tls20.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <array_length.h>
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
+#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/check.h>
|
20
SOURCES/glibc-rh1991001-21.patch
Normal file
20
SOURCES/glibc-rh1991001-21.patch
Normal file
@ -0,0 +1,20 @@
|
||||
commit df4cb2280e32187380520f71bd27ab32252cbc85
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Nov 30 15:39:17 2021 +0100
|
||||
|
||||
elf: Include <stdbool.h> in tst-tls20.c
|
||||
|
||||
The test uses the bool type.
|
||||
|
||||
diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
|
||||
index 18067e6b0a6093f9..200dacb748af21a8 100644
|
||||
--- a/elf/tst-tls20.c
|
||||
+++ b/elf/tst-tls20.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <array_length.h>
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
+#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
62
SOURCES/glibc-rh1991001-22.patch
Normal file
62
SOURCES/glibc-rh1991001-22.patch
Normal file
@ -0,0 +1,62 @@
|
||||
commit 5cc338565479a620244c2f8ff35956629c4dbf81
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Dec 10 05:14:24 2021 +0100
|
||||
|
||||
nptl: Add one more barrier to nptl/tst-create1
|
||||
|
||||
Without the bar_ctor_finish barrier, it was possible that thread2
|
||||
re-locked user_lock before ctor had a chance to lock it. ctor then
|
||||
blocked in its locking operation, xdlopen from the main thread
|
||||
did not return, and thread2 was stuck waiting in bar_dtor:
|
||||
|
||||
thread 1: started.
|
||||
thread 2: started.
|
||||
thread 2: locked user_lock.
|
||||
constructor started: 0.
|
||||
thread 1: in ctor: started.
|
||||
thread 3: started.
|
||||
thread 3: done.
|
||||
thread 2: unlocked user_lock.
|
||||
thread 2: locked user_lock.
|
||||
|
||||
Fixes the test in commit 83b5323261bb72313bffcf37476c1b8f0847c736
|
||||
("elf: Avoid deadlock between pthread_create and ctors [BZ #28357]").
|
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
|
||||
diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c
|
||||
index 932586c30990d1d4..763ded8d7956f943 100644
|
||||
--- a/sysdeps/pthread/tst-create1.c
|
||||
+++ b/sysdeps/pthread/tst-create1.c
|
||||
@@ -33,6 +33,7 @@ thread 2: lock(user_lock) -> pthread_create
|
||||
*/
|
||||
|
||||
static pthread_barrier_t bar_ctor;
|
||||
+static pthread_barrier_t bar_ctor_finish;
|
||||
static pthread_barrier_t bar_dtor;
|
||||
static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
@@ -46,6 +47,7 @@ ctor (void)
|
||||
xpthread_mutex_unlock (&user_lock);
|
||||
dprintf (1, "thread 1: in ctor: unlocked user_lock.\n");
|
||||
dprintf (1, "thread 1: in ctor: done.\n");
|
||||
+ xpthread_barrier_wait (&bar_ctor_finish);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -81,6 +83,7 @@ thread2 (void *a)
|
||||
xpthread_mutex_unlock (&user_lock);
|
||||
dprintf (1, "thread 2: unlocked user_lock.\n");
|
||||
xpthread_join (t3);
|
||||
+ xpthread_barrier_wait (&bar_ctor_finish);
|
||||
|
||||
xpthread_mutex_lock (&user_lock);
|
||||
dprintf (1, "thread 2: locked user_lock.\n");
|
||||
@@ -99,6 +102,7 @@ thread1 (void)
|
||||
{
|
||||
dprintf (1, "thread 1: started.\n");
|
||||
xpthread_barrier_init (&bar_ctor, NULL, 2);
|
||||
+ xpthread_barrier_init (&bar_ctor_finish, NULL, 2);
|
||||
xpthread_barrier_init (&bar_dtor, NULL, 2);
|
||||
pthread_t t2 = xpthread_create (0, thread2, 0);
|
||||
void *p = xdlopen ("tst-create1mod.so", RTLD_NOW | RTLD_GLOBAL);
|
163
SOURCES/glibc-rh1991001-3.patch
Normal file
163
SOURCES/glibc-rh1991001-3.patch
Normal file
@ -0,0 +1,163 @@
|
||||
commit 8f85075a2e9c26ff7486d4bbaf358999807d215c
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Thu Dec 31 12:24:38 2020 +0000
|
||||
|
||||
elf: Add a DTV setup test [BZ #27136]
|
||||
|
||||
The test dlopens a large number of modules with TLS, they are reused
|
||||
from an existing test.
|
||||
|
||||
The test relies on the reuse of slotinfo entries after dlclose, without
|
||||
bug 27135 fixed this needs a failing dlopen. With a slotinfo list that
|
||||
has non-monotone increasing generation counters, bug 27136 can trigger.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(usual test differences)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 82fb019a634caf81..0995d810b57d0dda 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -209,7 +209,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
tst-audit14 tst-audit15 tst-audit16 \
|
||||
tst-tls-ie tst-tls-ie-dlmopen \
|
||||
argv0test \
|
||||
- tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask
|
||||
+ tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
|
||||
+ tst-tls20
|
||||
# reldep9
|
||||
tests-internal += loadtest unload unload2 circleload1 \
|
||||
neededtest neededtest2 neededtest3 neededtest4 \
|
||||
@@ -332,6 +333,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||
libmarkermod2-1 libmarkermod2-2 \
|
||||
libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \
|
||||
libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \
|
||||
+ tst-tls20mod-bad
|
||||
|
||||
# Most modules build with _ISOMAC defined, but those filtered out
|
||||
# depend on internal headers.
|
||||
@@ -1828,3 +1830,9 @@ $(objpfx)tst-rtld-help.out: $(objpfx)ld.so
|
||||
fi; \
|
||||
(exit $$status); \
|
||||
$(evaluate-test)
|
||||
+
|
||||
+# Reuses tst-tls-many-dynamic-modules
|
||||
+tst-tls20mod-bad.so-no-z-defs = yes
|
||||
+$(objpfx)tst-tls20: $(libdl) $(shared-thread-library)
|
||||
+$(objpfx)tst-tls20.out: $(objpfx)tst-tls20mod-bad.so \
|
||||
+ $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so)
|
||||
diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..ac5f8c8d39b66dd6
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tls20.c
|
||||
@@ -0,0 +1,98 @@
|
||||
+/* Test dtv setup if entries don't have monotone increasing generation.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <dlfcn.h>
|
||||
+#include <pthread.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/xdlfcn.h>
|
||||
+#include <support/xthread.h>
|
||||
+
|
||||
+#define NMOD 100
|
||||
+static void *mod[NMOD];
|
||||
+
|
||||
+static void
|
||||
+load_fail (void)
|
||||
+{
|
||||
+ /* Expected to fail because of a missing symbol. */
|
||||
+ void *m = dlopen ("tst-tls20mod-bad.so", RTLD_NOW);
|
||||
+ if (m != NULL)
|
||||
+ FAIL_EXIT1 ("dlopen of tst-tls20mod-bad.so succeeded\n");
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+load_mod (int i)
|
||||
+{
|
||||
+ char *buf = xasprintf ("tst-tls-manydynamic%02dmod.so", i);
|
||||
+ mod[i] = xdlopen (buf, RTLD_LAZY);
|
||||
+ free (buf);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+unload_mod (int i)
|
||||
+{
|
||||
+ if (mod[i] != NULL)
|
||||
+ xdlclose (mod[i]);
|
||||
+ mod[i] = NULL;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+access (int i)
|
||||
+{
|
||||
+ char *buf = xasprintf ("tls_global_%02d", i);
|
||||
+ dlerror ();
|
||||
+ int *p = dlsym (mod[i], buf);
|
||||
+ printf ("mod[%d]: &tls = %p\n", i, p);
|
||||
+ if (p == NULL)
|
||||
+ FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
|
||||
+ ++*p;
|
||||
+ free (buf);
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+start (void *a)
|
||||
+{
|
||||
+ for (int i = 0; i < NMOD; i++)
|
||||
+ if (mod[i] != NULL)
|
||||
+ access (i);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < NMOD; i++)
|
||||
+ {
|
||||
+ load_mod (i);
|
||||
+ /* Bump the generation of mod[0] without using new dtv slot. */
|
||||
+ unload_mod (0);
|
||||
+ load_fail (); /* Ensure GL(dl_tls_dtv_gaps) is true: see bug 27135. */
|
||||
+ load_mod (0);
|
||||
+ /* Access TLS in all loaded modules. */
|
||||
+ pthread_t t = xpthread_create (0, start, 0);
|
||||
+ xpthread_join (t);
|
||||
+ }
|
||||
+ for (i = 0; i < NMOD; i++)
|
||||
+ unload_mod (i);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/elf/tst-tls20mod-bad.c b/elf/tst-tls20mod-bad.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..c1aed8ea7deffd22
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tls20mod-bad.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+void missing_symbol (void);
|
||||
+void f (void) {missing_symbol ();}
|
41
SOURCES/glibc-rh1991001-4.patch
Normal file
41
SOURCES/glibc-rh1991001-4.patch
Normal file
@ -0,0 +1,41 @@
|
||||
commit c489c35054c39d7f2437ca61b369e3ede448f022
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Wed Nov 30 11:44:25 2016 +0000
|
||||
|
||||
elf: Fix comments and logic in _dl_add_to_slotinfo
|
||||
|
||||
Since
|
||||
|
||||
commit a509eb117fac1d764b15eba64993f4bdb63d7f3c
|
||||
Avoid late dlopen failure due to scope, TLS slotinfo updates [BZ #25112]
|
||||
|
||||
the generation counter update is not needed in the failure path.
|
||||
That commit ensures allocation in _dl_add_to_slotinfo happens before
|
||||
the demarcation point in dlopen (it is called twice, first time is for
|
||||
allocation only where dlopen can still be reverted on failure, then
|
||||
second time actual dtv updates are done which then cannot fail).
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||
index 0b96b1dceed99d58..9375650a3ab5247d 100644
|
||||
--- a/elf/dl-tls.c
|
||||
+++ b/elf/dl-tls.c
|
||||
@@ -998,16 +998,7 @@ _dl_add_to_slotinfo (struct link_map *l, bool do_add)
|
||||
+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
|
||||
if (listp == NULL)
|
||||
{
|
||||
- /* We ran out of memory. We will simply fail this
|
||||
- call but don't undo anything we did so far. The
|
||||
- application will crash or be terminated anyway very
|
||||
- soon. */
|
||||
-
|
||||
- /* We have to do this since some entries in the dtv
|
||||
- slotinfo array might already point to this
|
||||
- generation. */
|
||||
- ++GL(dl_tls_generation);
|
||||
-
|
||||
+ /* We ran out of memory while resizing the dtv slotinfo list. */
|
||||
_dl_signal_error (ENOMEM, "dlopen", NULL, N_("\
|
||||
cannot create TLS data structures"));
|
||||
}
|
58
SOURCES/glibc-rh1991001-5.patch
Normal file
58
SOURCES/glibc-rh1991001-5.patch
Normal file
@ -0,0 +1,58 @@
|
||||
commit c0669ae1a629e16b536bf11cdd0865e0dbcf4bee
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Wed Dec 30 21:52:38 2020 +0000
|
||||
|
||||
elf: Refactor _dl_update_slotinfo to avoid use after free
|
||||
|
||||
map is not valid to access here because it can be freed by a concurrent
|
||||
dlclose: during tls access (via __tls_get_addr) _dl_update_slotinfo is
|
||||
called without holding dlopen locks. So don't check the modid of map.
|
||||
|
||||
The map == 0 and map != 0 code paths can be shared (avoiding the dtv
|
||||
resize in case of map == 0 is just an optimization: larger dtv than
|
||||
necessary would be fine too).
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||
index 9375650a3ab5247d..15ed01d795a8627a 100644
|
||||
--- a/elf/dl-tls.c
|
||||
+++ b/elf/dl-tls.c
|
||||
@@ -743,6 +743,8 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
{
|
||||
for (size_t cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
|
||||
{
|
||||
+ size_t modid = total + cnt;
|
||||
+
|
||||
size_t gen = listp->slotinfo[cnt].gen;
|
||||
|
||||
if (gen > new_gen)
|
||||
@@ -758,25 +760,12 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
|
||||
/* If there is no map this means the entry is empty. */
|
||||
struct link_map *map = listp->slotinfo[cnt].map;
|
||||
- if (map == NULL)
|
||||
- {
|
||||
- if (dtv[-1].counter >= total + cnt)
|
||||
- {
|
||||
- /* If this modid was used at some point the memory
|
||||
- might still be allocated. */
|
||||
- free (dtv[total + cnt].pointer.to_free);
|
||||
- dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
|
||||
- dtv[total + cnt].pointer.to_free = NULL;
|
||||
- }
|
||||
-
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
/* Check whether the current dtv array is large enough. */
|
||||
- size_t modid = map->l_tls_modid;
|
||||
- assert (total + cnt == modid);
|
||||
if (dtv[-1].counter < modid)
|
||||
{
|
||||
+ if (map == NULL)
|
||||
+ continue;
|
||||
+
|
||||
/* Resize the dtv. */
|
||||
dtv = _dl_resize_dtv (dtv);
|
||||
|
48
SOURCES/glibc-rh1991001-6.patch
Normal file
48
SOURCES/glibc-rh1991001-6.patch
Normal file
@ -0,0 +1,48 @@
|
||||
commit 8f7e09f4dbdb5c815a18b8285fbc5d5d7bc17d86
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Thu Feb 11 11:29:23 2021 +0000
|
||||
|
||||
x86_64: Avoid lazy relocation of tlsdesc [BZ #27137]
|
||||
|
||||
Lazy tlsdesc relocation is racy because the static tls optimization and
|
||||
tlsdesc management operations are done without holding the dlopen lock.
|
||||
|
||||
This similar to the commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67
|
||||
for aarch64, but it fixes a different race: bug 27137.
|
||||
|
||||
Another issue is that ld auditing ignores DT_BIND_NOW and thus tries to
|
||||
relocate tlsdesc lazily, but that does not work in a BIND_NOW module
|
||||
due to missing DT_TLSDESC_PLT. Unconditionally relocating tlsdesc at
|
||||
load time fixes this bug 27721 too.
|
||||
|
||||
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
|
||||
index e308b662d245cc63..ef5740ba281c7282 100644
|
||||
--- a/sysdeps/x86_64/dl-machine.h
|
||||
+++ b/sysdeps/x86_64/dl-machine.h
|
||||
@@ -563,12 +563,21 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||
}
|
||||
else if (__glibc_likely (r_type == R_X86_64_TLSDESC))
|
||||
{
|
||||
- struct tlsdesc volatile * __attribute__((__unused__)) td =
|
||||
- (struct tlsdesc volatile *)reloc_addr;
|
||||
+ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
|
||||
+ const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
|
||||
+ const ElfW (Sym) *sym = &symtab[symndx];
|
||||
+ const struct r_found_version *version = NULL;
|
||||
|
||||
- td->arg = (void*)reloc;
|
||||
- td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)])
|
||||
- + map->l_addr);
|
||||
+ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||
+ {
|
||||
+ const ElfW (Half) *vernum =
|
||||
+ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
|
||||
+ version = &map->l_versions[vernum[symndx] & 0x7fff];
|
||||
+ }
|
||||
+
|
||||
+ /* Always initialize TLS descriptors completely at load time, in
|
||||
+ case static TLS is allocated for it that requires locking. */
|
||||
+ elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
|
||||
}
|
||||
else if (__glibc_unlikely (r_type == R_X86_64_IRELATIVE))
|
||||
{
|
116
SOURCES/glibc-rh1991001-7.patch
Normal file
116
SOURCES/glibc-rh1991001-7.patch
Normal file
@ -0,0 +1,116 @@
|
||||
commit ddcacd91cc10ff92d6201eda87047d029c14158d
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Thu Feb 11 11:40:11 2021 +0000
|
||||
|
||||
i386: Avoid lazy relocation of tlsdesc [BZ #27137]
|
||||
|
||||
Lazy tlsdesc relocation is racy because the static tls optimization and
|
||||
tlsdesc management operations are done without holding the dlopen lock.
|
||||
|
||||
This similar to the commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67
|
||||
for aarch64, but it fixes a different race: bug 27137.
|
||||
|
||||
On i386 the code is a bit more complicated than on x86_64 because both
|
||||
rel and rela relocs are supported.
|
||||
|
||||
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
|
||||
index e5776ef7bc8ad749..3a30671591284d79 100644
|
||||
--- a/sysdeps/i386/dl-machine.h
|
||||
+++ b/sysdeps/i386/dl-machine.h
|
||||
@@ -679,50 +679,32 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||
}
|
||||
else if (__glibc_likely (r_type == R_386_TLS_DESC))
|
||||
{
|
||||
- struct tlsdesc volatile * __attribute__((__unused__)) td =
|
||||
- (struct tlsdesc volatile *)reloc_addr;
|
||||
-
|
||||
- /* Handle relocations that reference the local *ABS* in a simple
|
||||
- way, so as to preserve a potential addend. */
|
||||
- if (ELF32_R_SYM (reloc->r_info) == 0)
|
||||
- td->entry = _dl_tlsdesc_resolve_abs_plus_addend;
|
||||
- /* Given a known-zero addend, we can store a pointer to the
|
||||
- reloc in the arg position. */
|
||||
- else if (td->arg == 0)
|
||||
- {
|
||||
- td->arg = (void*)reloc;
|
||||
- td->entry = _dl_tlsdesc_resolve_rel;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* We could handle non-*ABS* relocations with non-zero addends
|
||||
- by allocating dynamically an arg to hold a pointer to the
|
||||
- reloc, but that sounds pointless. */
|
||||
- const Elf32_Rel *const r = reloc;
|
||||
- /* The code below was borrowed from elf_dynamic_do_rel(). */
|
||||
- const ElfW(Sym) *const symtab =
|
||||
- (const void *) D_PTR (map, l_info[DT_SYMTAB]);
|
||||
+ const Elf32_Rel *const r = reloc;
|
||||
+ /* The code below was borrowed from elf_dynamic_do_rel(). */
|
||||
+ const ElfW(Sym) *const symtab =
|
||||
+ (const void *) D_PTR (map, l_info[DT_SYMTAB]);
|
||||
|
||||
+ /* Always initialize TLS descriptors completely at load time, in
|
||||
+ case static TLS is allocated for it that requires locking. */
|
||||
# ifdef RTLD_BOOTSTRAP
|
||||
- /* The dynamic linker always uses versioning. */
|
||||
- assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
|
||||
+ /* The dynamic linker always uses versioning. */
|
||||
+ assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
|
||||
# else
|
||||
- if (map->l_info[VERSYMIDX (DT_VERSYM)])
|
||||
+ if (map->l_info[VERSYMIDX (DT_VERSYM)])
|
||||
# endif
|
||||
- {
|
||||
- const ElfW(Half) *const version =
|
||||
- (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
|
||||
- ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
|
||||
- elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
|
||||
- &map->l_versions[ndx],
|
||||
- (void *) (l_addr + r->r_offset), skip_ifunc);
|
||||
- }
|
||||
+ {
|
||||
+ const ElfW(Half) *const version =
|
||||
+ (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
|
||||
+ ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
|
||||
+ elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
|
||||
+ &map->l_versions[ndx],
|
||||
+ (void *) (l_addr + r->r_offset), skip_ifunc);
|
||||
+ }
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
- else
|
||||
- elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
|
||||
- (void *) (l_addr + r->r_offset), skip_ifunc);
|
||||
+ else
|
||||
+ elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
|
||||
+ (void *) (l_addr + r->r_offset), skip_ifunc);
|
||||
# endif
|
||||
- }
|
||||
}
|
||||
else if (__glibc_unlikely (r_type == R_386_IRELATIVE))
|
||||
{
|
||||
@@ -749,11 +731,21 @@ elf_machine_lazy_rela (struct link_map *map,
|
||||
;
|
||||
else if (__glibc_likely (r_type == R_386_TLS_DESC))
|
||||
{
|
||||
- struct tlsdesc volatile * __attribute__((__unused__)) td =
|
||||
- (struct tlsdesc volatile *)reloc_addr;
|
||||
+ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
|
||||
+ const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
|
||||
+ const ElfW (Sym) *sym = &symtab[symndx];
|
||||
+ const struct r_found_version *version = NULL;
|
||||
+
|
||||
+ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||
+ {
|
||||
+ const ElfW (Half) *vernum =
|
||||
+ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
|
||||
+ version = &map->l_versions[vernum[symndx] & 0x7fff];
|
||||
+ }
|
||||
|
||||
- td->arg = (void*)reloc;
|
||||
- td->entry = _dl_tlsdesc_resolve_rela;
|
||||
+ /* Always initialize TLS descriptors completely at load time, in
|
||||
+ case static TLS is allocated for it that requires locking. */
|
||||
+ elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
|
||||
}
|
||||
else if (__glibc_unlikely (r_type == R_386_IRELATIVE))
|
||||
{
|
277
SOURCES/glibc-rh1991001-8.patch
Normal file
277
SOURCES/glibc-rh1991001-8.patch
Normal file
@ -0,0 +1,277 @@
|
||||
commit 55c9f3238080e9aba733bc0902779c46cfa16446
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Thu Feb 11 11:52:24 2021 +0000
|
||||
|
||||
x86_64: Remove lazy tlsdesc relocation related code
|
||||
|
||||
_dl_tlsdesc_resolve_rela and _dl_tlsdesc_resolve_hold are only used for
|
||||
lazy tlsdesc relocation processing which is no longer supported.
|
||||
|
||||
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
|
||||
index ef5740ba281c7282..b94d3b39ec1dca64 100644
|
||||
--- a/sysdeps/x86_64/dl-machine.h
|
||||
+++ b/sysdeps/x86_64/dl-machine.h
|
||||
@@ -127,10 +127,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
}
|
||||
}
|
||||
|
||||
- if (l->l_info[ADDRIDX (DT_TLSDESC_GOT)] && lazy)
|
||||
- *(ElfW(Addr)*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_GOT)]) + l->l_addr)
|
||||
- = (ElfW(Addr)) &_dl_tlsdesc_resolve_rela;
|
||||
-
|
||||
return lazy;
|
||||
}
|
||||
|
||||
diff --git a/sysdeps/x86_64/dl-tlsdesc.S b/sysdeps/x86_64/dl-tlsdesc.S
|
||||
index 80d771cd887dd626..77e78cf0a6d8babc 100644
|
||||
--- a/sysdeps/x86_64/dl-tlsdesc.S
|
||||
+++ b/sysdeps/x86_64/dl-tlsdesc.S
|
||||
@@ -148,107 +148,3 @@ _dl_tlsdesc_dynamic:
|
||||
cfi_endproc
|
||||
.size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
|
||||
#endif /* SHARED */
|
||||
-
|
||||
- /* This function is a wrapper for a lazy resolver for TLS_DESC
|
||||
- RELA relocations. The incoming 0(%rsp) points to the caller's
|
||||
- link map, pushed by the dynamic object's internal lazy TLS
|
||||
- resolver front-end before tail-calling us. We need to pop it
|
||||
- ourselves. %rax points to a TLS descriptor, such that 0(%rax)
|
||||
- holds the address of the internal resolver front-end (unless
|
||||
- some other thread beat us to resolving it) and 8(%rax) holds a
|
||||
- pointer to the relocation.
|
||||
-
|
||||
- When the actual resolver returns, it will have adjusted the
|
||||
- TLS descriptor such that we can tail-call it for it to return
|
||||
- the TP offset of the symbol. */
|
||||
-
|
||||
- .hidden _dl_tlsdesc_resolve_rela
|
||||
- .global _dl_tlsdesc_resolve_rela
|
||||
- .type _dl_tlsdesc_resolve_rela,@function
|
||||
- cfi_startproc
|
||||
- .align 16
|
||||
- /* The PLT entry will have pushed the link_map pointer. */
|
||||
-_dl_tlsdesc_resolve_rela:
|
||||
- _CET_ENDBR
|
||||
- cfi_adjust_cfa_offset (8)
|
||||
- /* Save all call-clobbered registers. Add 8 bytes for push in
|
||||
- the PLT entry to align the stack. */
|
||||
- subq $80, %rsp
|
||||
- cfi_adjust_cfa_offset (80)
|
||||
- movq %rax, (%rsp)
|
||||
- movq %rdi, 8(%rsp)
|
||||
- movq %rax, %rdi /* Pass tlsdesc* in %rdi. */
|
||||
- movq %rsi, 16(%rsp)
|
||||
- movq 80(%rsp), %rsi /* Pass link_map* in %rsi. */
|
||||
- movq %r8, 24(%rsp)
|
||||
- movq %r9, 32(%rsp)
|
||||
- movq %r10, 40(%rsp)
|
||||
- movq %r11, 48(%rsp)
|
||||
- movq %rdx, 56(%rsp)
|
||||
- movq %rcx, 64(%rsp)
|
||||
- call _dl_tlsdesc_resolve_rela_fixup
|
||||
- movq (%rsp), %rax
|
||||
- movq 8(%rsp), %rdi
|
||||
- movq 16(%rsp), %rsi
|
||||
- movq 24(%rsp), %r8
|
||||
- movq 32(%rsp), %r9
|
||||
- movq 40(%rsp), %r10
|
||||
- movq 48(%rsp), %r11
|
||||
- movq 56(%rsp), %rdx
|
||||
- movq 64(%rsp), %rcx
|
||||
- addq $88, %rsp
|
||||
- cfi_adjust_cfa_offset (-88)
|
||||
- jmp *(%rax)
|
||||
- cfi_endproc
|
||||
- .size _dl_tlsdesc_resolve_rela, .-_dl_tlsdesc_resolve_rela
|
||||
-
|
||||
- /* This function is a placeholder for lazy resolving of TLS
|
||||
- relocations. Once some thread starts resolving a TLS
|
||||
- relocation, it sets up the TLS descriptor to use this
|
||||
- resolver, such that other threads that would attempt to
|
||||
- resolve it concurrently may skip the call to the original lazy
|
||||
- resolver and go straight to a condition wait.
|
||||
-
|
||||
- When the actual resolver returns, it will have adjusted the
|
||||
- TLS descriptor such that we can tail-call it for it to return
|
||||
- the TP offset of the symbol. */
|
||||
-
|
||||
- .hidden _dl_tlsdesc_resolve_hold
|
||||
- .global _dl_tlsdesc_resolve_hold
|
||||
- .type _dl_tlsdesc_resolve_hold,@function
|
||||
- cfi_startproc
|
||||
- .align 16
|
||||
-_dl_tlsdesc_resolve_hold:
|
||||
-0:
|
||||
- _CET_ENDBR
|
||||
- /* Save all call-clobbered registers. */
|
||||
- subq $72, %rsp
|
||||
- cfi_adjust_cfa_offset (72)
|
||||
- movq %rax, (%rsp)
|
||||
- movq %rdi, 8(%rsp)
|
||||
- movq %rax, %rdi /* Pass tlsdesc* in %rdi. */
|
||||
- movq %rsi, 16(%rsp)
|
||||
- /* Pass _dl_tlsdesc_resolve_hold's address in %rsi. */
|
||||
- leaq . - _dl_tlsdesc_resolve_hold(%rip), %rsi
|
||||
- movq %r8, 24(%rsp)
|
||||
- movq %r9, 32(%rsp)
|
||||
- movq %r10, 40(%rsp)
|
||||
- movq %r11, 48(%rsp)
|
||||
- movq %rdx, 56(%rsp)
|
||||
- movq %rcx, 64(%rsp)
|
||||
- call _dl_tlsdesc_resolve_hold_fixup
|
||||
-1:
|
||||
- movq (%rsp), %rax
|
||||
- movq 8(%rsp), %rdi
|
||||
- movq 16(%rsp), %rsi
|
||||
- movq 24(%rsp), %r8
|
||||
- movq 32(%rsp), %r9
|
||||
- movq 40(%rsp), %r10
|
||||
- movq 48(%rsp), %r11
|
||||
- movq 56(%rsp), %rdx
|
||||
- movq 64(%rsp), %rcx
|
||||
- addq $72, %rsp
|
||||
- cfi_adjust_cfa_offset (-72)
|
||||
- jmp *(%rax)
|
||||
- cfi_endproc
|
||||
- .size _dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold
|
||||
diff --git a/sysdeps/x86_64/dl-tlsdesc.h b/sysdeps/x86_64/dl-tlsdesc.h
|
||||
index 66e659bb5c7ede74..1cde1ee9664f4908 100644
|
||||
--- a/sysdeps/x86_64/dl-tlsdesc.h
|
||||
+++ b/sysdeps/x86_64/dl-tlsdesc.h
|
||||
@@ -55,9 +55,7 @@ struct tlsdesc_dynamic_arg
|
||||
|
||||
extern ptrdiff_t attribute_hidden
|
||||
_dl_tlsdesc_return(struct tlsdesc *on_rax),
|
||||
- _dl_tlsdesc_undefweak(struct tlsdesc *on_rax),
|
||||
- _dl_tlsdesc_resolve_rela(struct tlsdesc *on_rax),
|
||||
- _dl_tlsdesc_resolve_hold(struct tlsdesc *on_rax);
|
||||
+ _dl_tlsdesc_undefweak(struct tlsdesc *on_rax);
|
||||
|
||||
# ifdef SHARED
|
||||
extern void *_dl_make_tlsdesc_dynamic (struct link_map *map,
|
||||
diff --git a/sysdeps/x86_64/tlsdesc.c b/sysdeps/x86_64/tlsdesc.c
|
||||
index 302d097dbb0c4f1e..61a19ae26944c84f 100644
|
||||
--- a/sysdeps/x86_64/tlsdesc.c
|
||||
+++ b/sysdeps/x86_64/tlsdesc.c
|
||||
@@ -16,120 +16,13 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#include <link.h>
|
||||
#include <ldsodefs.h>
|
||||
-#include <elf/dynamic-link.h>
|
||||
#include <tls.h>
|
||||
#include <dl-tlsdesc.h>
|
||||
#include <dl-unmap-segments.h>
|
||||
+#define _dl_tlsdesc_resolve_hold 0
|
||||
#include <tlsdeschtab.h>
|
||||
|
||||
-/* The following 2 functions take a caller argument, that contains the
|
||||
- address expected to be in the TLS descriptor. If it's changed, we
|
||||
- want to return immediately. */
|
||||
-
|
||||
-/* This function is used to lazily resolve TLS_DESC RELA relocations.
|
||||
- The argument location is used to hold a pointer to the relocation. */
|
||||
-
|
||||
-void
|
||||
-attribute_hidden
|
||||
-_dl_tlsdesc_resolve_rela_fixup (struct tlsdesc volatile *td,
|
||||
- struct link_map *l)
|
||||
-{
|
||||
- const ElfW(Rela) *reloc = td->arg;
|
||||
-
|
||||
- if (_dl_tlsdesc_resolve_early_return_p
|
||||
- (td, (void*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_PLT)]) + l->l_addr)))
|
||||
- return;
|
||||
-
|
||||
- /* The code below was borrowed from _dl_fixup(). */
|
||||
- const ElfW(Sym) *const symtab
|
||||
- = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
|
||||
- const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
|
||||
- const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
|
||||
- lookup_t result;
|
||||
-
|
||||
- /* Look up the target symbol. If the normal lookup rules are not
|
||||
- used don't look in the global scope. */
|
||||
- if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL
|
||||
- && __builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
|
||||
- {
|
||||
- const struct r_found_version *version = NULL;
|
||||
-
|
||||
- if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||
- {
|
||||
- const ElfW(Half) *vernum =
|
||||
- (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
|
||||
- ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
|
||||
- version = &l->l_versions[ndx];
|
||||
- if (version->hash == 0)
|
||||
- version = NULL;
|
||||
- }
|
||||
-
|
||||
- result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
|
||||
- l->l_scope, version, ELF_RTYPE_CLASS_PLT,
|
||||
- DL_LOOKUP_ADD_DEPENDENCY, NULL);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* We already found the symbol. The module (and therefore its load
|
||||
- address) is also known. */
|
||||
- result = l;
|
||||
- }
|
||||
-
|
||||
- if (! sym)
|
||||
- {
|
||||
- td->arg = (void*)reloc->r_addend;
|
||||
- td->entry = _dl_tlsdesc_undefweak;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
-# ifndef SHARED
|
||||
- CHECK_STATIC_TLS (l, result);
|
||||
-# else
|
||||
- if (!TRY_STATIC_TLS (l, result))
|
||||
- {
|
||||
- td->arg = _dl_make_tlsdesc_dynamic (result, sym->st_value
|
||||
- + reloc->r_addend);
|
||||
- td->entry = _dl_tlsdesc_dynamic;
|
||||
- }
|
||||
- else
|
||||
-# endif
|
||||
- {
|
||||
- td->arg = (void*)(sym->st_value - result->l_tls_offset
|
||||
- + reloc->r_addend);
|
||||
- td->entry = _dl_tlsdesc_return;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- _dl_tlsdesc_wake_up_held_fixups ();
|
||||
-}
|
||||
-
|
||||
-/* This function is used to avoid busy waiting for other threads to
|
||||
- complete the lazy relocation. Once another thread wins the race to
|
||||
- relocate a TLS descriptor, it sets the descriptor up such that this
|
||||
- function is called to wait until the resolver releases the
|
||||
- lock. */
|
||||
-
|
||||
-void
|
||||
-attribute_hidden
|
||||
-_dl_tlsdesc_resolve_hold_fixup (struct tlsdesc volatile *td,
|
||||
- void *caller)
|
||||
-{
|
||||
- /* Maybe we're lucky and can return early. */
|
||||
- if (caller != td->entry)
|
||||
- return;
|
||||
-
|
||||
- /* Locking here will stop execution until the running resolver runs
|
||||
- _dl_tlsdesc_wake_up_held_fixups(), releasing the lock.
|
||||
-
|
||||
- FIXME: We'd be better off waiting on a condition variable, such
|
||||
- that we didn't have to hold the lock throughout the relocation
|
||||
- processing. */
|
||||
- __rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
-}
|
||||
-
|
||||
/* Unmap the dynamic object, but also release its TLS descriptor table
|
||||
if there is one. */
|
||||
|
443
SOURCES/glibc-rh1991001-9.patch
Normal file
443
SOURCES/glibc-rh1991001-9.patch
Normal file
@ -0,0 +1,443 @@
|
||||
commit a75a02a696f9f869d77b17b99964823aa8833a8b
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Thu Feb 11 11:58:20 2021 +0000
|
||||
|
||||
i386: Remove lazy tlsdesc relocation related code
|
||||
|
||||
Like in commit e75711ebfa976d5468ec292282566a18b07e4d67 for x86_64,
|
||||
remove unused lazy tlsdesc relocation processing code:
|
||||
|
||||
_dl_tlsdesc_resolve_abs_plus_addend
|
||||
_dl_tlsdesc_resolve_rel
|
||||
_dl_tlsdesc_resolve_rela
|
||||
_dl_tlsdesc_resolve_hold
|
||||
|
||||
diff --git a/sysdeps/i386/dl-tlsdesc.S b/sysdeps/i386/dl-tlsdesc.S
|
||||
index 128f0af3188f46bb..22ecb2c6adc6cc6e 100644
|
||||
--- a/sysdeps/i386/dl-tlsdesc.S
|
||||
+++ b/sysdeps/i386/dl-tlsdesc.S
|
||||
@@ -138,159 +138,3 @@ _dl_tlsdesc_dynamic:
|
||||
cfi_endproc
|
||||
.size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
|
||||
#endif /* SHARED */
|
||||
-
|
||||
- /* This function is a wrapper for a lazy resolver for TLS_DESC
|
||||
- REL relocations that reference the *ABS* segment in their own
|
||||
- link maps. %ebx points to the caller's GOT. %eax points to a
|
||||
- TLS descriptor, such that 0(%eax) holds the address of the
|
||||
- resolver wrapper itself (unless some other thread beat us to
|
||||
- it) and 4(%eax) holds the addend in the relocation.
|
||||
-
|
||||
- When the actual resolver returns, it will have adjusted the
|
||||
- TLS descriptor such that we can tail-call it for it to return
|
||||
- the TP offset of the symbol. */
|
||||
-
|
||||
- .hidden _dl_tlsdesc_resolve_abs_plus_addend
|
||||
- .global _dl_tlsdesc_resolve_abs_plus_addend
|
||||
- .type _dl_tlsdesc_resolve_abs_plus_addend,@function
|
||||
- cfi_startproc
|
||||
- .align 16
|
||||
-_dl_tlsdesc_resolve_abs_plus_addend:
|
||||
-0:
|
||||
- _CET_ENDBR
|
||||
- pushl %eax
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- pushl %ecx
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- pushl %edx
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- movl $1f - 0b, %ecx
|
||||
- movl 4(%ebx), %edx
|
||||
- call _dl_tlsdesc_resolve_abs_plus_addend_fixup
|
||||
-1:
|
||||
- popl %edx
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- popl %ecx
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- popl %eax
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- jmp *(%eax)
|
||||
- cfi_endproc
|
||||
- .size _dl_tlsdesc_resolve_abs_plus_addend, .-_dl_tlsdesc_resolve_abs_plus_addend
|
||||
-
|
||||
- /* This function is a wrapper for a lazy resolver for TLS_DESC
|
||||
- REL relocations that had zero addends. %ebx points to the
|
||||
- caller's GOT. %eax points to a TLS descriptor, such that
|
||||
- 0(%eax) holds the address of the resolver wrapper itself
|
||||
- (unless some other thread beat us to it) and 4(%eax) holds a
|
||||
- pointer to the relocation.
|
||||
-
|
||||
- When the actual resolver returns, it will have adjusted the
|
||||
- TLS descriptor such that we can tail-call it for it to return
|
||||
- the TP offset of the symbol. */
|
||||
-
|
||||
- .hidden _dl_tlsdesc_resolve_rel
|
||||
- .global _dl_tlsdesc_resolve_rel
|
||||
- .type _dl_tlsdesc_resolve_rel,@function
|
||||
- cfi_startproc
|
||||
- .align 16
|
||||
-_dl_tlsdesc_resolve_rel:
|
||||
-0:
|
||||
- _CET_ENDBR
|
||||
- pushl %eax
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- pushl %ecx
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- pushl %edx
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- movl $1f - 0b, %ecx
|
||||
- movl 4(%ebx), %edx
|
||||
- call _dl_tlsdesc_resolve_rel_fixup
|
||||
-1:
|
||||
- popl %edx
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- popl %ecx
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- popl %eax
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- jmp *(%eax)
|
||||
- cfi_endproc
|
||||
- .size _dl_tlsdesc_resolve_rel, .-_dl_tlsdesc_resolve_rel
|
||||
-
|
||||
- /* This function is a wrapper for a lazy resolver for TLS_DESC
|
||||
- RELA relocations. %ebx points to the caller's GOT. %eax
|
||||
- points to a TLS descriptor, such that 0(%eax) holds the
|
||||
- address of the resolver wrapper itself (unless some other
|
||||
- thread beat us to it) and 4(%eax) holds a pointer to the
|
||||
- relocation.
|
||||
-
|
||||
- When the actual resolver returns, it will have adjusted the
|
||||
- TLS descriptor such that we can tail-call it for it to return
|
||||
- the TP offset of the symbol. */
|
||||
-
|
||||
- .hidden _dl_tlsdesc_resolve_rela
|
||||
- .global _dl_tlsdesc_resolve_rela
|
||||
- .type _dl_tlsdesc_resolve_rela,@function
|
||||
- cfi_startproc
|
||||
- .align 16
|
||||
-_dl_tlsdesc_resolve_rela:
|
||||
-0:
|
||||
- _CET_ENDBR
|
||||
- pushl %eax
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- pushl %ecx
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- pushl %edx
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- movl $1f - 0b, %ecx
|
||||
- movl 4(%ebx), %edx
|
||||
- call _dl_tlsdesc_resolve_rela_fixup
|
||||
-1:
|
||||
- popl %edx
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- popl %ecx
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- popl %eax
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- jmp *(%eax)
|
||||
- cfi_endproc
|
||||
- .size _dl_tlsdesc_resolve_rela, .-_dl_tlsdesc_resolve_rela
|
||||
-
|
||||
- /* This function is a placeholder for lazy resolving of TLS
|
||||
- relocations. Once some thread starts resolving a TLS
|
||||
- relocation, it sets up the TLS descriptor to use this
|
||||
- resolver, such that other threads that would attempt to
|
||||
- resolve it concurrently may skip the call to the original lazy
|
||||
- resolver and go straight to a condition wait.
|
||||
-
|
||||
- When the actual resolver returns, it will have adjusted the
|
||||
- TLS descriptor such that we can tail-call it for it to return
|
||||
- the TP offset of the symbol. */
|
||||
-
|
||||
- .hidden _dl_tlsdesc_resolve_hold
|
||||
- .global _dl_tlsdesc_resolve_hold
|
||||
- .type _dl_tlsdesc_resolve_hold,@function
|
||||
- cfi_startproc
|
||||
- .align 16
|
||||
-_dl_tlsdesc_resolve_hold:
|
||||
-0:
|
||||
- _CET_ENDBR
|
||||
- pushl %eax
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- pushl %ecx
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- pushl %edx
|
||||
- cfi_adjust_cfa_offset (4)
|
||||
- movl $1f - 0b, %ecx
|
||||
- movl 4(%ebx), %edx
|
||||
- call _dl_tlsdesc_resolve_hold_fixup
|
||||
-1:
|
||||
- popl %edx
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- popl %ecx
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- popl %eax
|
||||
- cfi_adjust_cfa_offset (-4)
|
||||
- jmp *(%eax)
|
||||
- cfi_endproc
|
||||
- .size _dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold
|
||||
diff --git a/sysdeps/i386/dl-tlsdesc.h b/sysdeps/i386/dl-tlsdesc.h
|
||||
index c8a1e056150dc418..1a1a22c303baf85b 100644
|
||||
--- a/sysdeps/i386/dl-tlsdesc.h
|
||||
+++ b/sysdeps/i386/dl-tlsdesc.h
|
||||
@@ -43,11 +43,7 @@ struct tlsdesc_dynamic_arg
|
||||
|
||||
extern ptrdiff_t attribute_hidden __attribute__ ((regparm (1)))
|
||||
_dl_tlsdesc_return (struct tlsdesc *),
|
||||
- _dl_tlsdesc_undefweak (struct tlsdesc *),
|
||||
- _dl_tlsdesc_resolve_abs_plus_addend (struct tlsdesc *),
|
||||
- _dl_tlsdesc_resolve_rel (struct tlsdesc *),
|
||||
- _dl_tlsdesc_resolve_rela (struct tlsdesc *),
|
||||
- _dl_tlsdesc_resolve_hold (struct tlsdesc *);
|
||||
+ _dl_tlsdesc_undefweak (struct tlsdesc *);
|
||||
|
||||
# ifdef SHARED
|
||||
extern void *_dl_make_tlsdesc_dynamic (struct link_map *map,
|
||||
diff --git a/sysdeps/i386/tlsdesc.c b/sysdeps/i386/tlsdesc.c
|
||||
index 82fa8a1d35fd1912..1b4227c8381e1b3d 100644
|
||||
--- a/sysdeps/i386/tlsdesc.c
|
||||
+++ b/sysdeps/i386/tlsdesc.c
|
||||
@@ -16,242 +16,13 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-#include <link.h>
|
||||
#include <ldsodefs.h>
|
||||
-#include <elf/dynamic-link.h>
|
||||
#include <tls.h>
|
||||
#include <dl-tlsdesc.h>
|
||||
#include <dl-unmap-segments.h>
|
||||
+#define _dl_tlsdesc_resolve_hold 0
|
||||
#include <tlsdeschtab.h>
|
||||
|
||||
-/* The following 4 functions take an entry_check_offset argument.
|
||||
- It's computed by the caller as an offset between its entry point
|
||||
- and the call site, such that by adding the built-in return address
|
||||
- that is implicitly passed to the function with this offset, we can
|
||||
- easily obtain the caller's entry point to compare with the entry
|
||||
- point given in the TLS descriptor. If it's changed, we want to
|
||||
- return immediately. */
|
||||
-
|
||||
-/* This function is used to lazily resolve TLS_DESC REL relocations
|
||||
- that reference the *ABS* segment in their own link maps. The
|
||||
- argument is the addend originally stored there. */
|
||||
-
|
||||
-void
|
||||
-__attribute__ ((regparm (3))) attribute_hidden
|
||||
-_dl_tlsdesc_resolve_abs_plus_addend_fixup (struct tlsdesc volatile *td,
|
||||
- struct link_map *l,
|
||||
- ptrdiff_t entry_check_offset)
|
||||
-{
|
||||
- ptrdiff_t addend = (ptrdiff_t) td->arg;
|
||||
-
|
||||
- if (_dl_tlsdesc_resolve_early_return_p (td, __builtin_return_address (0)
|
||||
- - entry_check_offset))
|
||||
- return;
|
||||
-
|
||||
-#ifndef SHARED
|
||||
- CHECK_STATIC_TLS (l, l);
|
||||
-#else
|
||||
- if (!TRY_STATIC_TLS (l, l))
|
||||
- {
|
||||
- td->arg = _dl_make_tlsdesc_dynamic (l, addend);
|
||||
- td->entry = _dl_tlsdesc_dynamic;
|
||||
- }
|
||||
- else
|
||||
-#endif
|
||||
- {
|
||||
- td->arg = (void*) (addend - l->l_tls_offset);
|
||||
- td->entry = _dl_tlsdesc_return;
|
||||
- }
|
||||
-
|
||||
- _dl_tlsdesc_wake_up_held_fixups ();
|
||||
-}
|
||||
-
|
||||
-/* This function is used to lazily resolve TLS_DESC REL relocations
|
||||
- that originally had zero addends. The argument location, that
|
||||
- originally held the addend, is used to hold a pointer to the
|
||||
- relocation, but it has to be restored before we call the function
|
||||
- that applies relocations. */
|
||||
-
|
||||
-void
|
||||
-__attribute__ ((regparm (3))) attribute_hidden
|
||||
-_dl_tlsdesc_resolve_rel_fixup (struct tlsdesc volatile *td,
|
||||
- struct link_map *l,
|
||||
- ptrdiff_t entry_check_offset)
|
||||
-{
|
||||
- const ElfW(Rel) *reloc = td->arg;
|
||||
-
|
||||
- if (_dl_tlsdesc_resolve_early_return_p (td, __builtin_return_address (0)
|
||||
- - entry_check_offset))
|
||||
- return;
|
||||
-
|
||||
- /* The code below was borrowed from _dl_fixup(),
|
||||
- except for checking for STB_LOCAL. */
|
||||
- const ElfW(Sym) *const symtab
|
||||
- = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
|
||||
- const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
|
||||
- const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
|
||||
- lookup_t result;
|
||||
-
|
||||
- /* Look up the target symbol. If the normal lookup rules are not
|
||||
- used don't look in the global scope. */
|
||||
- if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL
|
||||
- && __builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
|
||||
- {
|
||||
- const struct r_found_version *version = NULL;
|
||||
-
|
||||
- if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||
- {
|
||||
- const ElfW(Half) *vernum =
|
||||
- (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
|
||||
- ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
|
||||
- version = &l->l_versions[ndx];
|
||||
- if (version->hash == 0)
|
||||
- version = NULL;
|
||||
- }
|
||||
-
|
||||
- result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
|
||||
- l->l_scope, version, ELF_RTYPE_CLASS_PLT,
|
||||
- DL_LOOKUP_ADD_DEPENDENCY, NULL);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* We already found the symbol. The module (and therefore its load
|
||||
- address) is also known. */
|
||||
- result = l;
|
||||
- }
|
||||
-
|
||||
- if (!sym)
|
||||
- {
|
||||
- td->arg = 0;
|
||||
- td->entry = _dl_tlsdesc_undefweak;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
-# ifndef SHARED
|
||||
- CHECK_STATIC_TLS (l, result);
|
||||
-# else
|
||||
- if (!TRY_STATIC_TLS (l, result))
|
||||
- {
|
||||
- td->arg = _dl_make_tlsdesc_dynamic (result, sym->st_value);
|
||||
- td->entry = _dl_tlsdesc_dynamic;
|
||||
- }
|
||||
- else
|
||||
-# endif
|
||||
- {
|
||||
- td->arg = (void*)(sym->st_value - result->l_tls_offset);
|
||||
- td->entry = _dl_tlsdesc_return;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- _dl_tlsdesc_wake_up_held_fixups ();
|
||||
-}
|
||||
-
|
||||
-/* This function is used to lazily resolve TLS_DESC RELA relocations.
|
||||
- The argument location is used to hold a pointer to the relocation. */
|
||||
-
|
||||
-void
|
||||
-__attribute__ ((regparm (3))) attribute_hidden
|
||||
-_dl_tlsdesc_resolve_rela_fixup (struct tlsdesc volatile *td,
|
||||
- struct link_map *l,
|
||||
- ptrdiff_t entry_check_offset)
|
||||
-{
|
||||
- const ElfW(Rela) *reloc = td->arg;
|
||||
-
|
||||
- if (_dl_tlsdesc_resolve_early_return_p (td, __builtin_return_address (0)
|
||||
- - entry_check_offset))
|
||||
- return;
|
||||
-
|
||||
- /* The code below was borrowed from _dl_fixup(),
|
||||
- except for checking for STB_LOCAL. */
|
||||
- const ElfW(Sym) *const symtab
|
||||
- = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
|
||||
- const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
|
||||
- const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
|
||||
- lookup_t result;
|
||||
-
|
||||
- /* Look up the target symbol. If the normal lookup rules are not
|
||||
- used don't look in the global scope. */
|
||||
- if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL
|
||||
- && __builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
|
||||
- {
|
||||
- const struct r_found_version *version = NULL;
|
||||
-
|
||||
- if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||
- {
|
||||
- const ElfW(Half) *vernum =
|
||||
- (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
|
||||
- ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
|
||||
- version = &l->l_versions[ndx];
|
||||
- if (version->hash == 0)
|
||||
- version = NULL;
|
||||
- }
|
||||
-
|
||||
- result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
|
||||
- l->l_scope, version, ELF_RTYPE_CLASS_PLT,
|
||||
- DL_LOOKUP_ADD_DEPENDENCY, NULL);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* We already found the symbol. The module (and therefore its load
|
||||
- address) is also known. */
|
||||
- result = l;
|
||||
- }
|
||||
-
|
||||
- if (!sym)
|
||||
- {
|
||||
- td->arg = (void*) reloc->r_addend;
|
||||
- td->entry = _dl_tlsdesc_undefweak;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
-# ifndef SHARED
|
||||
- CHECK_STATIC_TLS (l, result);
|
||||
-# else
|
||||
- if (!TRY_STATIC_TLS (l, result))
|
||||
- {
|
||||
- td->arg = _dl_make_tlsdesc_dynamic (result, sym->st_value
|
||||
- + reloc->r_addend);
|
||||
- td->entry = _dl_tlsdesc_dynamic;
|
||||
- }
|
||||
- else
|
||||
-# endif
|
||||
- {
|
||||
- td->arg = (void*) (sym->st_value - result->l_tls_offset
|
||||
- + reloc->r_addend);
|
||||
- td->entry = _dl_tlsdesc_return;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- _dl_tlsdesc_wake_up_held_fixups ();
|
||||
-}
|
||||
-
|
||||
-/* This function is used to avoid busy waiting for other threads to
|
||||
- complete the lazy relocation. Once another thread wins the race to
|
||||
- relocate a TLS descriptor, it sets the descriptor up such that this
|
||||
- function is called to wait until the resolver releases the
|
||||
- lock. */
|
||||
-
|
||||
-void
|
||||
-__attribute__ ((regparm (3))) attribute_hidden
|
||||
-_dl_tlsdesc_resolve_hold_fixup (struct tlsdesc volatile *td,
|
||||
- struct link_map *l __attribute__((__unused__)),
|
||||
- ptrdiff_t entry_check_offset)
|
||||
-{
|
||||
- /* Maybe we're lucky and can return early. */
|
||||
- if (__builtin_return_address (0) - entry_check_offset != td->entry)
|
||||
- return;
|
||||
-
|
||||
- /* Locking here will stop execution until the running resolver runs
|
||||
- _dl_tlsdesc_wake_up_held_fixups(), releasing the lock.
|
||||
-
|
||||
- FIXME: We'd be better off waiting on a condition variable, such
|
||||
- that we didn't have to hold the lock throughout the relocation
|
||||
- processing. */
|
||||
- __rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
-}
|
||||
-
|
||||
-
|
||||
/* Unmap the dynamic object, but also release its TLS descriptor table
|
||||
if there is one. */
|
||||
|
205
SOURCES/glibc-rh2000374.patch
Normal file
205
SOURCES/glibc-rh2000374.patch
Normal file
@ -0,0 +1,205 @@
|
||||
Bug RHEL #2000374
|
||||
Bugs Upstream #24046, #25923
|
||||
|
||||
This patch provides 12-hour time for the English language UTF-8 locale as a
|
||||
new locale en_US@ampm.UTF-8.
|
||||
|
||||
Two upstream commits were applied to en_US to create the new file en_US@ampm:
|
||||
Upstream commit: 7395f3a0efad9fc51bb54fa383ef6524702e0c49
|
||||
Upstream commit: 8cde977077b3568310c743b21a905ca9ab286724
|
||||
|
||||
en_US remains unchanged and the new file en_US@ampm is now supported.
|
||||
|
||||
|
||||
diff -Nrup a/localedata/locales/en_US@ampm b/localedata/locales/en_US@ampm
|
||||
--- a/localedata/locales/en_US@ampm 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ b/localedata/locales/en_US@ampm 2021-11-17 17:19:15.338720307 -0500
|
||||
@@ -0,0 +1,177 @@
|
||||
+comment_char %
|
||||
+escape_char /
|
||||
+
|
||||
+% This file is part of the GNU C Library and contains locale data.
|
||||
+% The Free Software Foundation does not claim any copyright interest
|
||||
+% in the locale data contained in this file. The foregoing does not
|
||||
+% affect the license of the GNU C Library as a whole. It does not
|
||||
+% exempt you from the conditions of the license if your use would
|
||||
+% otherwise be governed by that license.
|
||||
+
|
||||
+% Locale for English locale in the USA
|
||||
+% Contributed by Ulrich Drepper <drepper@redhat.com>, 2000
|
||||
+
|
||||
+LC_IDENTIFICATION
|
||||
+title "English locale for the USA"
|
||||
+source "Free Software Foundation, Inc."
|
||||
+address "http:////www.gnu.org//software//libc//"
|
||||
+contact ""
|
||||
+email "bug-glibc-locales@gnu.org"
|
||||
+tel ""
|
||||
+fax ""
|
||||
+language "American English"
|
||||
+territory "United States"
|
||||
+revision "1.0"
|
||||
+date "2000-06-24"
|
||||
+
|
||||
+category "i18n:2012";LC_IDENTIFICATION
|
||||
+category "i18n:2012";LC_CTYPE
|
||||
+category "i18n:2012";LC_COLLATE
|
||||
+category "i18n:2012";LC_TIME
|
||||
+category "i18n:2012";LC_NUMERIC
|
||||
+category "i18n:2012";LC_MONETARY
|
||||
+category "i18n:2012";LC_MESSAGES
|
||||
+category "i18n:2012";LC_PAPER
|
||||
+category "i18n:2012";LC_NAME
|
||||
+category "i18n:2012";LC_ADDRESS
|
||||
+category "i18n:2012";LC_TELEPHONE
|
||||
+category "i18n:2012";LC_MEASUREMENT
|
||||
+END LC_IDENTIFICATION
|
||||
+
|
||||
+LC_CTYPE
|
||||
+copy "en_GB"
|
||||
+END LC_CTYPE
|
||||
+
|
||||
+LC_COLLATE
|
||||
+
|
||||
+% Copy the template from ISO/IEC 14651
|
||||
+copy "iso14651_t1"
|
||||
+
|
||||
+END LC_COLLATE
|
||||
+
|
||||
+LC_MONETARY
|
||||
+int_curr_symbol "USD "
|
||||
+currency_symbol "$"
|
||||
+mon_decimal_point "."
|
||||
+mon_thousands_sep ","
|
||||
+mon_grouping 3;3
|
||||
+positive_sign ""
|
||||
+negative_sign "-"
|
||||
+int_frac_digits 2
|
||||
+frac_digits 2
|
||||
+p_cs_precedes 1
|
||||
+int_p_sep_by_space 1
|
||||
+p_sep_by_space 0
|
||||
+n_cs_precedes 1
|
||||
+int_n_sep_by_space 1
|
||||
+n_sep_by_space 0
|
||||
+p_sign_posn 1
|
||||
+n_sign_posn 1
|
||||
+%
|
||||
+END LC_MONETARY
|
||||
+
|
||||
+LC_NUMERIC
|
||||
+decimal_point "."
|
||||
+thousands_sep ","
|
||||
+grouping 3;3
|
||||
+END LC_NUMERIC
|
||||
+
|
||||
+LC_TIME
|
||||
+abday "Sun";"Mon";"Tue";"Wed";"Thu";"Fri";"Sat"
|
||||
+day "Sunday";/
|
||||
+ "Monday";/
|
||||
+ "Tuesday";/
|
||||
+ "Wednesday";/
|
||||
+ "Thursday";/
|
||||
+ "Friday";/
|
||||
+ "Saturday"
|
||||
+
|
||||
+week 7;19971130;1
|
||||
+abmon "Jan";"Feb";/
|
||||
+ "Mar";"Apr";/
|
||||
+ "May";"Jun";/
|
||||
+ "Jul";"Aug";/
|
||||
+ "Sep";"Oct";/
|
||||
+ "Nov";"Dec"
|
||||
+mon "January";/
|
||||
+ "February";/
|
||||
+ "March";/
|
||||
+ "April";/
|
||||
+ "May";/
|
||||
+ "June";/
|
||||
+ "July";/
|
||||
+ "August";/
|
||||
+ "September";/
|
||||
+ "October";/
|
||||
+ "November";/
|
||||
+ "December"
|
||||
+% Appropriate date and time representation (%c)
|
||||
+d_t_fmt "%a %d %b %Y %r %Z"
|
||||
+%
|
||||
+% Appropriate date representation (%x)
|
||||
+d_fmt "%m//%d//%Y"
|
||||
+%
|
||||
+% Appropriate time representation (%X)
|
||||
+t_fmt "%r"
|
||||
+%
|
||||
+% Appropriate AM/PM time representation (%r)
|
||||
+t_fmt_ampm "%I:%M:%S %p"
|
||||
+%
|
||||
+% Appropriate date and time representation for date(1). This is
|
||||
+% different from d_t_fmt for historical reasons and has been different
|
||||
+% since 2000 when date_fmt was added as a GNU extension. At the end
|
||||
+% of 2018 it was adjusted to use 12H time (bug 24046) instead of 24H.
|
||||
+date_fmt "%a %b %e %r %Z %Y"
|
||||
+%
|
||||
+% Strings for AM/PM
|
||||
+%
|
||||
+am_pm "AM";"PM"
|
||||
+END LC_TIME
|
||||
+
|
||||
+LC_MESSAGES
|
||||
+yesexpr "^[+1yY]"
|
||||
+noexpr "^[-0nN]"
|
||||
+yesstr "yes"
|
||||
+nostr "no"
|
||||
+END LC_MESSAGES
|
||||
+
|
||||
+LC_PAPER
|
||||
+height 279
|
||||
+width 216
|
||||
+END LC_PAPER
|
||||
+
|
||||
+LC_NAME
|
||||
+name_fmt "%d%t%g%t%m%t%f"
|
||||
+name_miss "Miss."
|
||||
+name_mr "Mr."
|
||||
+name_mrs "Mrs."
|
||||
+name_ms "Ms."
|
||||
+END LC_NAME
|
||||
+
|
||||
+
|
||||
+LC_ADDRESS
|
||||
+postal_fmt "%a%N%f%N%d%N%b%N%h %s %e %r%N%T, %S %z%N%c%N"
|
||||
+country_name "United States"
|
||||
+country_post "USA"
|
||||
+country_ab2 "US"
|
||||
+country_ab3 "USA"
|
||||
+country_num 840
|
||||
+country_car "USA"
|
||||
+country_isbn 0
|
||||
+lang_name "English"
|
||||
+lang_ab "en"
|
||||
+lang_term "eng"
|
||||
+lang_lib "eng"
|
||||
+END LC_ADDRESS
|
||||
+
|
||||
+LC_TELEPHONE
|
||||
+tel_int_fmt "+%c (%a) %l"
|
||||
+tel_dom_fmt "(%a) %l"
|
||||
+int_select "11"
|
||||
+int_prefix "1"
|
||||
+END LC_TELEPHONE
|
||||
+
|
||||
+LC_MEASUREMENT
|
||||
+% US customary units.
|
||||
+measurement 2
|
||||
+END LC_MEASUREMENT
|
||||
diff -Nrup a/localedata/SUPPORTED b/localedata/SUPPORTED
|
||||
--- a/localedata/SUPPORTED 2021-11-17 17:14:33.831631483 -0500
|
||||
+++ b/localedata/SUPPORTED 2021-11-17 17:21:16.418188595 -0500
|
||||
@@ -159,6 +159,7 @@ en_SG/ISO-8859-1 \
|
||||
en_US.UTF-8/UTF-8 \
|
||||
en_US/ISO-8859-1 \
|
||||
en_US.ISO-8859-15/ISO-8859-15 \
|
||||
+en_US@ampm.UTF-8/UTF-8 \
|
||||
en_ZA.UTF-8/UTF-8 \
|
||||
en_ZA/ISO-8859-1 \
|
||||
en_ZM/UTF-8 \
|
92
SOURCES/glibc-rh2007327-1.patch
Normal file
92
SOURCES/glibc-rh2007327-1.patch
Normal file
@ -0,0 +1,92 @@
|
||||
commit 28c30a6232aa9a54783c146590498a061fc0112a
|
||||
Author: Samuel Thibault <samuel.thibault@ens-lyon.org>
|
||||
Date: Sun Feb 9 19:50:21 2020 +0000
|
||||
|
||||
pthread: Move most once tests from nptl to sysdeps/pthread
|
||||
|
||||
So they can be checked with htl too.
|
||||
|
||||
# Conflicts:
|
||||
# sysdeps/pthread/Makefile
|
||||
# (Moved only the tests in this commit which subsequently
|
||||
# needed for the pthread_once fix)
|
||||
|
||||
diff --git a/nptl/Makefile b/nptl/Makefile
|
||||
index b14de3ffb330c10b..dcf3868869767015 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -260,7 +260,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
|
||||
tst-rwlock4 tst-rwlock5 tst-rwlock6 tst-rwlock7 tst-rwlock8 \
|
||||
tst-rwlock9 tst-rwlock10 tst-rwlock11 tst-rwlock12 tst-rwlock13 \
|
||||
tst-rwlock14 tst-rwlock15 tst-rwlock16 tst-rwlock17 tst-rwlock18 \
|
||||
- tst-once1 tst-once2 tst-once3 tst-once4 tst-once5 \
|
||||
+ tst-once5 \
|
||||
tst-key1 tst-key2 tst-key3 tst-key4 \
|
||||
tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
|
||||
tst-sem8 tst-sem9 tst-sem10 tst-sem14 \
|
||||
@@ -384,8 +384,7 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
|
||||
tst-cancelx6 tst-cancelx7 tst-cancelx8 tst-cancelx9 tst-cancelx10 \
|
||||
tst-cancelx11 tst-cancelx12 tst-cancelx13 tst-cancelx14 tst-cancelx15 \
|
||||
tst-cancelx16 tst-cancelx17 tst-cancelx18 tst-cancelx20 tst-cancelx21 \
|
||||
- tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \
|
||||
- tst-oncex3 tst-oncex4
|
||||
+ tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4
|
||||
ifeq ($(build-shared),yes)
|
||||
tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder \
|
||||
tst-audit-threads
|
||||
@@ -525,8 +524,6 @@ CFLAGS-tst-cleanupx2.c += -fexceptions
|
||||
CFLAGS-tst-cleanupx3.c += -fexceptions
|
||||
CFLAGS-tst-cleanupx4.c += -fexceptions
|
||||
CFLAGS-tst-cleanupx4aux.c += -fexceptions
|
||||
-CFLAGS-tst-oncex3.c += -fexceptions
|
||||
-CFLAGS-tst-oncex4.c += -fexceptions
|
||||
CFLAGS-tst-align.c += $(stack-align-test-flags)
|
||||
CFLAGS-tst-align3.c += $(stack-align-test-flags)
|
||||
CFLAGS-tst-initializers1.c += -W -Wall -Werror
|
||||
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
|
||||
index 98a92f8d6bb119ba..14ef04247cb84ad3 100644
|
||||
--- a/sysdeps/pthread/Makefile
|
||||
+++ b/sysdeps/pthread/Makefile
|
||||
@@ -33,11 +33,18 @@ endif
|
||||
|
||||
tst-create1mod.so-no-z-defs = yes
|
||||
|
||||
+tests += tst-once1 tst-once2 tst-once3 tst-once4
|
||||
+
|
||||
+tests += tst-oncex3 tst-oncex4
|
||||
+
|
||||
ifeq ($(build-shared),yes)
|
||||
# Build all the modules even when not actually running test programs.
|
||||
tests: $(test-modules)
|
||||
endif
|
||||
|
||||
+CFLAGS-tst-oncex3.c += -fexceptions
|
||||
+CFLAGS-tst-oncex4.c += -fexceptions
|
||||
+
|
||||
modules-names += tst-create1mod
|
||||
test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
|
||||
|
||||
diff --git a/nptl/tst-once1.c b/sysdeps/pthread/tst-once1.c
|
||||
similarity index 100%
|
||||
rename from nptl/tst-once1.c
|
||||
rename to sysdeps/pthread/tst-once1.c
|
||||
diff --git a/nptl/tst-once2.c b/sysdeps/pthread/tst-once2.c
|
||||
similarity index 100%
|
||||
rename from nptl/tst-once2.c
|
||||
rename to sysdeps/pthread/tst-once2.c
|
||||
diff --git a/nptl/tst-once3.c b/sysdeps/pthread/tst-once3.c
|
||||
similarity index 100%
|
||||
rename from nptl/tst-once3.c
|
||||
rename to sysdeps/pthread/tst-once3.c
|
||||
diff --git a/nptl/tst-once4.c b/sysdeps/pthread/tst-once4.c
|
||||
similarity index 100%
|
||||
rename from nptl/tst-once4.c
|
||||
rename to sysdeps/pthread/tst-once4.c
|
||||
diff --git a/nptl/tst-oncex3.c b/sysdeps/pthread/tst-oncex3.c
|
||||
similarity index 100%
|
||||
rename from nptl/tst-oncex3.c
|
||||
rename to sysdeps/pthread/tst-oncex3.c
|
||||
diff --git a/nptl/tst-oncex4.c b/sysdeps/pthread/tst-oncex4.c
|
||||
similarity index 100%
|
||||
rename from nptl/tst-oncex4.c
|
||||
rename to sysdeps/pthread/tst-oncex4.c
|
200
SOURCES/glibc-rh2007327-2.patch
Normal file
200
SOURCES/glibc-rh2007327-2.patch
Normal file
@ -0,0 +1,200 @@
|
||||
commit f0419e6a10740a672b28e112c409ae24f5e890ab
|
||||
Author: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Thu Mar 4 15:15:33 2021 +0100
|
||||
|
||||
[PATCH] pthread_once hangs when init routine throws an exception [BZ #18435]
|
||||
|
||||
This is another attempt at making pthread_once handle throwing exceptions
|
||||
from the init routine callback. As the new testcases show, just switching
|
||||
to the cleanup attribute based cleanup does fix the tst-once5 test, but
|
||||
breaks the new tst-oncey3 test. That is because when throwing exceptions,
|
||||
only the unwind info registered cleanups (i.e. C++ destructors or cleanup
|
||||
attribute), when cancelling threads and there has been unwind info from the
|
||||
cancellation point up to whatever needs cleanup both unwind info registered
|
||||
cleanups and THREAD_SETMEM (self, cleanup, ...) registered cleanups are
|
||||
invoked, but once we hit some frame with no unwind info, only the
|
||||
THREAD_SETMEM (self, cleanup, ...) registered cleanups are invoked.
|
||||
So, to stay fully backwards compatible (allow init routines without
|
||||
unwind info which encounter cancellation points) and handle exception throwing
|
||||
we actually need to register the pthread_once cleanups in both unwind info
|
||||
and in the THREAD_SETMEM (self, cleanup, ...) way.
|
||||
If an exception is thrown, only the former will happen and we in that case
|
||||
need to also unregister the THREAD_SETMEM (self, cleanup, ...) registered
|
||||
handler, because otherwise after catching the exception the user code could
|
||||
call deeper into the stack some cancellation point, get cancelled and then
|
||||
a stale cleanup handler would clobber stack and probably crash.
|
||||
If a thread calling init routine is cancelled and unwind info ends before
|
||||
the pthread_once frame, it will be cleaned up through self->cleanup as
|
||||
before. And if unwind info is present, unwind_stop first calls the
|
||||
self->cleanup registered handler for the frame, then it will call the
|
||||
unwind info registered handler but that will already see __do_it == 0
|
||||
and do nothing.
|
||||
|
||||
# Conflicts:
|
||||
# nptl/Makefile
|
||||
# (The usual cleanups because they don't match.)
|
||||
# sysdeps/pthread/Makefile
|
||||
# (The usual cleanups because all the other tests aren't moved.)
|
||||
|
||||
diff --git a/nptl/Makefile b/nptl/Makefile
|
||||
index dcf3868869767015..70a3be23ecfcd9c9 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -334,10 +334,6 @@ xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \
|
||||
tst-mutexpp1 tst-mutexpp6 tst-mutexpp10
|
||||
test-srcs = tst-oddstacklimit
|
||||
|
||||
-# Test expected to fail on most targets (except x86_64) due to bug
|
||||
-# 18435 - pthread_once hangs when init routine throws an exception.
|
||||
-test-xfail-tst-once5 = yes
|
||||
-
|
||||
# Files which must not be linked with libpthread.
|
||||
tests-nolibpthread = tst-unload
|
||||
|
||||
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
|
||||
index a2d48b2015cd385c..7ddc166cf32414c4 100644
|
||||
--- a/nptl/pthreadP.h
|
||||
+++ b/nptl/pthreadP.h
|
||||
@@ -571,6 +571,67 @@ extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
|
||||
# undef pthread_cleanup_pop
|
||||
# define pthread_cleanup_pop(execute) \
|
||||
__pthread_cleanup_pop (&_buffer, (execute)); }
|
||||
+
|
||||
+# if defined __EXCEPTIONS && !defined __cplusplus
|
||||
+/* Structure to hold the cleanup handler information. */
|
||||
+struct __pthread_cleanup_combined_frame
|
||||
+{
|
||||
+ void (*__cancel_routine) (void *);
|
||||
+ void *__cancel_arg;
|
||||
+ int __do_it;
|
||||
+ struct _pthread_cleanup_buffer __buffer;
|
||||
+};
|
||||
+
|
||||
+/* Special cleanup macros which register cleanup both using
|
||||
+ __pthread_cleanup_{push,pop} and using cleanup attribute. This is needed
|
||||
+ for pthread_once, so that it supports both throwing exceptions from the
|
||||
+ pthread_once callback (only cleanup attribute works there) and cancellation
|
||||
+ of the thread running the callback if the callback or some routines it
|
||||
+ calls don't have unwind information. */
|
||||
+
|
||||
+static __always_inline void
|
||||
+__pthread_cleanup_combined_routine (struct __pthread_cleanup_combined_frame
|
||||
+ *__frame)
|
||||
+{
|
||||
+ if (__frame->__do_it)
|
||||
+ {
|
||||
+ __frame->__cancel_routine (__frame->__cancel_arg);
|
||||
+ __frame->__do_it = 0;
|
||||
+ __pthread_cleanup_pop (&__frame->__buffer, 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+__pthread_cleanup_combined_routine_voidptr (void *__arg)
|
||||
+{
|
||||
+ struct __pthread_cleanup_combined_frame *__frame
|
||||
+ = (struct __pthread_cleanup_combined_frame *) __arg;
|
||||
+ if (__frame->__do_it)
|
||||
+ {
|
||||
+ __frame->__cancel_routine (__frame->__cancel_arg);
|
||||
+ __frame->__do_it = 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+# define pthread_cleanup_combined_push(routine, arg) \
|
||||
+ do { \
|
||||
+ void (*__cancel_routine) (void *) = (routine); \
|
||||
+ struct __pthread_cleanup_combined_frame __clframe \
|
||||
+ __attribute__ ((__cleanup__ (__pthread_cleanup_combined_routine))) \
|
||||
+ = { .__cancel_routine = __cancel_routine, .__cancel_arg = (arg), \
|
||||
+ .__do_it = 1 }; \
|
||||
+ __pthread_cleanup_push (&__clframe.__buffer, \
|
||||
+ __pthread_cleanup_combined_routine_voidptr, \
|
||||
+ &__clframe);
|
||||
+
|
||||
+# define pthread_cleanup_combined_pop(execute) \
|
||||
+ __pthread_cleanup_pop (&__clframe.__buffer, 0); \
|
||||
+ __clframe.__do_it = 0; \
|
||||
+ if (execute) \
|
||||
+ __cancel_routine (__clframe.__cancel_arg); \
|
||||
+ } while (0)
|
||||
+
|
||||
+# endif
|
||||
#endif
|
||||
|
||||
extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
|
||||
diff --git a/nptl/pthread_once.c b/nptl/pthread_once.c
|
||||
index 1653226286dc3539..45e965e8743d9412 100644
|
||||
--- a/nptl/pthread_once.c
|
||||
+++ b/nptl/pthread_once.c
|
||||
@@ -111,11 +111,11 @@ __pthread_once_slow (pthread_once_t *once_control, void (*init_routine) (void))
|
||||
/* This thread is the first here. Do the initialization.
|
||||
Register a cleanup handler so that in case the thread gets
|
||||
interrupted the initialization can be restarted. */
|
||||
- pthread_cleanup_push (clear_once_control, once_control);
|
||||
+ pthread_cleanup_combined_push (clear_once_control, once_control);
|
||||
|
||||
init_routine ();
|
||||
|
||||
- pthread_cleanup_pop (0);
|
||||
+ pthread_cleanup_combined_pop (0);
|
||||
|
||||
|
||||
/* Mark *once_control as having finished the initialization. We need
|
||||
diff --git a/nptl/tst-once5.cc b/nptl/tst-once5.cc
|
||||
index d232266c3ace89d9..dda18e610c9114bc 100644
|
||||
--- a/nptl/tst-once5.cc
|
||||
+++ b/nptl/tst-once5.cc
|
||||
@@ -59,7 +59,7 @@ do_test (void)
|
||||
" throwing an exception", stderr);
|
||||
}
|
||||
catch (OnceException) {
|
||||
- if (1 < niter)
|
||||
+ if (niter > 1)
|
||||
fputs ("pthread_once unexpectedly threw", stderr);
|
||||
result = 0;
|
||||
}
|
||||
@@ -75,7 +75,5 @@ do_test (void)
|
||||
return result;
|
||||
}
|
||||
|
||||
-// The test currently hangs and is XFAILed. Reduce the timeout.
|
||||
-#define TIMEOUT 1
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
|
||||
index 14ef04247cb84ad3..80a71f3f9f0e72ae 100644
|
||||
--- a/sysdeps/pthread/Makefile
|
||||
+++ b/sysdeps/pthread/Makefile
|
||||
@@ -35,7 +35,7 @@ tst-create1mod.so-no-z-defs = yes
|
||||
|
||||
tests += tst-once1 tst-once2 tst-once3 tst-once4
|
||||
|
||||
-tests += tst-oncex3 tst-oncex4
|
||||
+tests += tst-oncex3 tst-oncex4 tst-oncey3 tst-oncey4
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
# Build all the modules even when not actually running test programs.
|
||||
@@ -44,6 +44,8 @@ endif
|
||||
|
||||
CFLAGS-tst-oncex3.c += -fexceptions
|
||||
CFLAGS-tst-oncex4.c += -fexceptions
|
||||
+CFLAGS-tst-oncey3.c += -fno-exceptions -fno-asynchronous-unwind-tables
|
||||
+CFLAGS-tst-oncey4.c += -fno-exceptions -fno-asynchronous-unwind-tables
|
||||
|
||||
modules-names += tst-create1mod
|
||||
test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
|
||||
diff --git a/sysdeps/pthread/tst-oncey3.c b/sysdeps/pthread/tst-oncey3.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..08225b88dc06b979
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/pthread/tst-oncey3.c
|
||||
@@ -0,0 +1 @@
|
||||
+#include "tst-once3.c"
|
||||
diff --git a/sysdeps/pthread/tst-oncey4.c b/sysdeps/pthread/tst-oncey4.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..9b4d98f3f13c265a
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/pthread/tst-oncey4.c
|
||||
@@ -0,0 +1 @@
|
||||
+#include "tst-once4.c"
|
40
SOURCES/glibc-rh2021452.patch
Normal file
40
SOURCES/glibc-rh2021452.patch
Normal file
@ -0,0 +1,40 @@
|
||||
commit 98966749f2b418825ff2ea496a0ee89fe63d2cc8
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Nov 10 15:21:37 2021 +0100
|
||||
|
||||
s390: Use long branches across object boundaries (jgh instead of jh)
|
||||
|
||||
Depending on the layout chosen by the linker, the 16-bit displacement
|
||||
of the jh instruction is insufficient to reach the target label.
|
||||
|
||||
Analysis of the linker failure was carried out by Nick Clifton.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
Reviewed-by: Stefan Liebler <stli@linux.ibm.com>
|
||||
|
||||
diff --git a/sysdeps/s390/memmem-arch13.S b/sysdeps/s390/memmem-arch13.S
|
||||
index b59d60acf0f6aaa0..4faede0cd2f942e3 100644
|
||||
--- a/sysdeps/s390/memmem-arch13.S
|
||||
+++ b/sysdeps/s390/memmem-arch13.S
|
||||
@@ -41,7 +41,7 @@ ENTRY(MEMMEM_ARCH13)
|
||||
# error The arch13 variant of memmem needs the z13 variant of memmem!
|
||||
# endif
|
||||
clgfi %r5,9
|
||||
- jh MEMMEM_Z13
|
||||
+ jgh MEMMEM_Z13
|
||||
|
||||
aghik %r0,%r5,-1 /* vll needs highest index. */
|
||||
bc 4,0(%r14) /* cc==1: return if needle-len == 0. */
|
||||
diff --git a/sysdeps/s390/strstr-arch13.S b/sysdeps/s390/strstr-arch13.S
|
||||
index faa969849e09c2e1..ffc34c2523ce635a 100644
|
||||
--- a/sysdeps/s390/strstr-arch13.S
|
||||
+++ b/sysdeps/s390/strstr-arch13.S
|
||||
@@ -49,7 +49,7 @@ ENTRY(STRSTR_ARCH13)
|
||||
# error The arch13 variant of strstr needs the z13 variant of strstr!
|
||||
# endif
|
||||
clgfi %r4,9
|
||||
- jh STRSTR_Z13
|
||||
+ jgh STRSTR_Z13
|
||||
|
||||
/* In case of a partial match, the vstrs instruction returns the index
|
||||
of the partial match in a vector-register. Then we have to
|
304
SOURCES/glibc-rh2023420-1.patch
Normal file
304
SOURCES/glibc-rh2023420-1.patch
Normal file
@ -0,0 +1,304 @@
|
||||
commit 86f65dffc2396d408beb628f1cad2b8f63e197bd
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Sun Jul 12 06:04:53 2020 -0700
|
||||
|
||||
ld.so: Add --list-tunables to print tunable values
|
||||
|
||||
Pass --list-tunables to ld.so to print tunables with min and max values.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(different backporting order)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 3e71939d3234c4c3..aa65ec59f143bccf 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -44,6 +44,10 @@ dl-routines += dl-tunables
|
||||
tunables-type = $(addprefix TUNABLES_FRONTEND_,$(have-tunables))
|
||||
CPPFLAGS-dl-tunables.c += -DTUNABLES_FRONTEND=$(tunables-type)
|
||||
|
||||
+ifeq (yesyes,$(build-shared)$(run-built-tests))
|
||||
+tests-special += $(objpfx)list-tunables.out
|
||||
+endif
|
||||
+
|
||||
# Make sure that the compiler does not insert any library calls in tunables
|
||||
# code paths.
|
||||
ifeq (yes,$(have-loop-to-function))
|
||||
@@ -1825,6 +1829,13 @@ $(objpfx)tst-glibc-hwcaps-mask.out: \
|
||||
# tst-glibc-hwcaps-cache.
|
||||
$(objpfx)tst-glibc-hwcaps-cache.out: $(objpfx)tst-glibc-hwcaps
|
||||
|
||||
+$(objpfx)list-tunables.out: tst-rtld-list-tunables.sh $(objpfx)ld.so
|
||||
+ $(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \
|
||||
+ '$(run_program_env)' > $(objpfx)/tst-rtld-list-tunables.out
|
||||
+ cmp tst-rtld-list-tunables.exp \
|
||||
+ $(objpfx)/tst-rtld-list-tunables.out > $@; \
|
||||
+ $(evaluate-test)
|
||||
+
|
||||
tst-dst-static-ENV = LD_LIBRARY_PATH='$$ORIGIN'
|
||||
|
||||
$(objpfx)tst-rtld-help.out: $(objpfx)ld.so
|
||||
diff --git a/elf/dl-main.h b/elf/dl-main.h
|
||||
index 566713a0d10cfdb7..9e7b51d8f010e904 100644
|
||||
--- a/elf/dl-main.h
|
||||
+++ b/elf/dl-main.h
|
||||
@@ -63,7 +63,7 @@ struct audit_list
|
||||
enum rtld_mode
|
||||
{
|
||||
rtld_mode_normal, rtld_mode_list, rtld_mode_verify, rtld_mode_trace,
|
||||
- rtld_mode_help,
|
||||
+ rtld_mode_list_tunables, rtld_mode_help,
|
||||
};
|
||||
|
||||
/* Aggregated state information extracted from environment variables
|
||||
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
|
||||
index bbc3679e3564a766..3c84809d44381241 100644
|
||||
--- a/elf/dl-tunables.c
|
||||
+++ b/elf/dl-tunables.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <sysdep.h>
|
||||
#include <fcntl.h>
|
||||
#include <ldsodefs.h>
|
||||
+#include <array_length.h>
|
||||
|
||||
#define TUNABLES_INTERNAL 1
|
||||
#include "dl-tunables.h"
|
||||
@@ -359,6 +360,48 @@ __tunables_init (char **envp)
|
||||
}
|
||||
}
|
||||
|
||||
+void
|
||||
+__tunables_print (void)
|
||||
+{
|
||||
+ for (int i = 0; i < array_length (tunable_list); i++)
|
||||
+ {
|
||||
+ const tunable_t *cur = &tunable_list[i];
|
||||
+ if (cur->type.type_code == TUNABLE_TYPE_STRING
|
||||
+ && cur->val.strval == NULL)
|
||||
+ _dl_printf ("%s:\n", cur->name);
|
||||
+ else
|
||||
+ {
|
||||
+ _dl_printf ("%s: ", cur->name);
|
||||
+ switch (cur->type.type_code)
|
||||
+ {
|
||||
+ case TUNABLE_TYPE_INT_32:
|
||||
+ _dl_printf ("%d (min: %d, max: %d)\n",
|
||||
+ (int) cur->val.numval,
|
||||
+ (int) cur->type.min,
|
||||
+ (int) cur->type.max);
|
||||
+ break;
|
||||
+ case TUNABLE_TYPE_UINT_64:
|
||||
+ _dl_printf ("0x%lx (min: 0x%lx, max: 0x%lx)\n",
|
||||
+ (long int) cur->val.numval,
|
||||
+ (long int) cur->type.min,
|
||||
+ (long int) cur->type.max);
|
||||
+ break;
|
||||
+ case TUNABLE_TYPE_SIZE_T:
|
||||
+ _dl_printf ("0x%Zx (min: 0x%Zx, max: 0x%Zx)\n",
|
||||
+ (size_t) cur->val.numval,
|
||||
+ (size_t) cur->type.min,
|
||||
+ (size_t) cur->type.max);
|
||||
+ break;
|
||||
+ case TUNABLE_TYPE_STRING:
|
||||
+ _dl_printf ("%s\n", cur->val.strval);
|
||||
+ break;
|
||||
+ default:
|
||||
+ __builtin_unreachable ();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* Set the tunable value. This is called by the module that the tunable exists
|
||||
in. */
|
||||
void
|
||||
diff --git a/elf/dl-tunables.h b/elf/dl-tunables.h
|
||||
index 7f181f3316cd9fc1..f4f2cfaeb9828599 100644
|
||||
--- a/elf/dl-tunables.h
|
||||
+++ b/elf/dl-tunables.h
|
||||
@@ -69,9 +69,11 @@ typedef struct _tunable tunable_t;
|
||||
# include "dl-tunable-list.h"
|
||||
|
||||
extern void __tunables_init (char **);
|
||||
+extern void __tunables_print (void);
|
||||
extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
|
||||
extern void __tunable_set_val (tunable_id_t, void *);
|
||||
rtld_hidden_proto (__tunables_init)
|
||||
+rtld_hidden_proto (__tunables_print)
|
||||
rtld_hidden_proto (__tunable_get_val)
|
||||
|
||||
/* Define TUNABLE_GET and TUNABLE_SET in short form if TOP_NAMESPACE and
|
||||
diff --git a/elf/dl-usage.c b/elf/dl-usage.c
|
||||
index e22a9c39427187d1..908b4894b3014b2d 100644
|
||||
--- a/elf/dl-usage.c
|
||||
+++ b/elf/dl-usage.c
|
||||
@@ -255,7 +255,12 @@ setting environment variables (which would be inherited by subprocesses).\n\
|
||||
in LIST\n\
|
||||
--audit LIST use objects named in LIST as auditors\n\
|
||||
--preload LIST preload objects named in LIST\n\
|
||||
- --argv0 STRING set argv[0] to STRING before running\n\
|
||||
+ --argv0 STRING set argv[0] to STRING before running\n"
|
||||
+#if HAVE_TUNABLES
|
||||
+"\
|
||||
+ --list-tunables list all tunables with minimum and maximum values\n"
|
||||
+#endif
|
||||
+"\
|
||||
--help display this help and exit\n\
|
||||
--version output version information and exit\n\
|
||||
\n\
|
||||
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||
index 9e09896da078274d..54b621ec5ca014fa 100644
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <libc-early-init.h>
|
||||
#include <dl-main.h>
|
||||
#include <gnu/lib-names.h>
|
||||
+#include <dl-tunables.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -1262,6 +1263,16 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
_dl_argc -= 2;
|
||||
_dl_argv += 2;
|
||||
}
|
||||
+#if HAVE_TUNABLES
|
||||
+ else if (! strcmp (_dl_argv[1], "--list-tunables"))
|
||||
+ {
|
||||
+ state.mode = rtld_mode_list_tunables;
|
||||
+
|
||||
+ ++_dl_skip_args;
|
||||
+ --_dl_argc;
|
||||
+ ++_dl_argv;
|
||||
+ }
|
||||
+#endif
|
||||
else if (strcmp (_dl_argv[1], "--help") == 0)
|
||||
{
|
||||
state.mode = rtld_mode_help;
|
||||
@@ -1282,6 +1293,14 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
else
|
||||
break;
|
||||
|
||||
+#if HAVE_TUNABLES
|
||||
+ if (__glibc_unlikely (state.mode == rtld_mode_list_tunables))
|
||||
+ {
|
||||
+ __tunables_print ();
|
||||
+ _exit (0);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
/* If we have no further argument the program was called incorrectly.
|
||||
Grant the user some education. */
|
||||
if (_dl_argc < 2)
|
||||
diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp
|
||||
new file mode 100644
|
||||
index 0000000000000000..4f3f7ee4e30a2b42
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-rtld-list-tunables.exp
|
||||
@@ -0,0 +1,14 @@
|
||||
+glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0x[f]+)
|
||||
+glibc.malloc.arena_test: 0x0 (min: 0x1, max: 0x[f]+)
|
||||
+glibc.malloc.check: 0 (min: 0, max: 3)
|
||||
+glibc.malloc.mmap_max: 0 (min: -2147483648, max: 2147483647)
|
||||
+glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0x[f]+)
|
||||
+glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0x[f]+)
|
||||
+glibc.malloc.perturb: 0 (min: 0, max: 255)
|
||||
+glibc.malloc.tcache_count: 0x0 (min: 0x0, max: 0x[f]+)
|
||||
+glibc.malloc.tcache_max: 0x0 (min: 0x0, max: 0x[f]+)
|
||||
+glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0x[f]+)
|
||||
+glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0x[f]+)
|
||||
+glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0x[f]+)
|
||||
+glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
|
||||
+glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+)
|
||||
diff --git a/elf/tst-rtld-list-tunables.sh b/elf/tst-rtld-list-tunables.sh
|
||||
new file mode 100755
|
||||
index 0000000000000000..e7bbdde94952b872
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-rtld-list-tunables.sh
|
||||
@@ -0,0 +1,34 @@
|
||||
+#!/bin/sh
|
||||
+# Test for --list-tunables option ld.so.
|
||||
+# Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+# This file is part of the GNU C Library.
|
||||
+#
|
||||
+# The GNU C Library is free software; you can redistribute it and/or
|
||||
+# modify it under the terms of the GNU Lesser General Public
|
||||
+# License as published by the Free Software Foundation; either
|
||||
+# version 2.1 of the License, or (at your option) any later version.
|
||||
+#
|
||||
+# The GNU C Library is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+# Lesser General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU Lesser General Public
|
||||
+# License along with the GNU C Library; if not, see
|
||||
+# <https://www.gnu.org/licenses/>.
|
||||
+
|
||||
+set -e
|
||||
+
|
||||
+rtld=$1
|
||||
+test_wrapper_env=$2
|
||||
+run_program_env=$3
|
||||
+
|
||||
+LC_ALL=C
|
||||
+export LC_ALL
|
||||
+
|
||||
+${test_wrapper_env} \
|
||||
+${run_program_env} \
|
||||
+$rtld --list-tunables \
|
||||
+| sort -u \
|
||||
+| egrep "(rtld|malloc)" \
|
||||
+| sed -e "s/0xf\+/0x[f]+/"
|
||||
diff --git a/manual/tunables.texi b/manual/tunables.texi
|
||||
index 07887981748bc44b..43272cf885d1e3e6 100644
|
||||
--- a/manual/tunables.texi
|
||||
+++ b/manual/tunables.texi
|
||||
@@ -28,6 +28,44 @@ Finally, the set of tunables available may vary between distributions as
|
||||
the tunables feature allows distributions to add their own tunables under
|
||||
their own namespace.
|
||||
|
||||
+Passing @option{--list-tunables} to the dynamic loader to print all
|
||||
+tunables with minimum and maximum values:
|
||||
+
|
||||
+@example
|
||||
+$ /lib64/ld-linux-x86-64.so.2 --list-tunables
|
||||
+glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
|
||||
+glibc.elision.skip_lock_after_retries: 3 (min: -2147483648, max: 2147483647)
|
||||
+glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.malloc.perturb: 0 (min: 0, max: 255)
|
||||
+glibc.cpu.x86_shared_cache_size: 0x100000 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.mem.tagging: 0 (min: 0, max: 255)
|
||||
+glibc.elision.tries: 3 (min: -2147483648, max: 2147483647)
|
||||
+glibc.elision.enable: 0 (min: 0, max: 1)
|
||||
+glibc.cpu.x86_rep_movsb_threshold: 0x1000 (min: 0x100, max: 0xffffffffffffffff)
|
||||
+glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.elision.skip_lock_busy: 3 (min: -2147483648, max: 2147483647)
|
||||
+glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.cpu.x86_rep_stosb_threshold: 0x800 (min: 0x1, max: 0xffffffffffffffff)
|
||||
+glibc.cpu.x86_non_temporal_threshold: 0xc0000 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.cpu.x86_shstk:
|
||||
+glibc.cpu.hwcap_mask: 0x6 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.malloc.mmap_max: 0 (min: -2147483648, max: 2147483647)
|
||||
+glibc.elision.skip_trylock_internal_abort: 3 (min: -2147483648, max: 2147483647)
|
||||
+glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.cpu.x86_ibt:
|
||||
+glibc.cpu.hwcaps:
|
||||
+glibc.elision.skip_lock_internal_abort: 3 (min: -2147483648, max: 2147483647)
|
||||
+glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0xffffffffffffffff)
|
||||
+glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.cpu.x86_data_cache_size: 0x8000 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.malloc.tcache_count: 0x0 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.malloc.arena_test: 0x0 (min: 0x1, max: 0xffffffffffffffff)
|
||||
+glibc.pthread.mutex_spin_count: 100 (min: 0, max: 32767)
|
||||
+glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.malloc.tcache_max: 0x0 (min: 0x0, max: 0xffffffffffffffff)
|
||||
+glibc.malloc.check: 0 (min: 0, max: 3)
|
||||
+@end example
|
||||
+
|
||||
@menu
|
||||
* Tunable names:: The structure of a tunable name
|
||||
* Memory Allocation Tunables:: Tunables in the memory allocation subsystem
|
30
SOURCES/glibc-rh2023420-2.patch
Normal file
30
SOURCES/glibc-rh2023420-2.patch
Normal file
@ -0,0 +1,30 @@
|
||||
commit d2d12c7a988a9a04aec23b5e4af549db61b0a005
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Tue Feb 2 09:31:56 2021 -0800
|
||||
|
||||
tst-rtld-list-tunables.sh: Unset glibc tunables
|
||||
|
||||
Unset glibc tunables and their aliases for --list-tunables test.
|
||||
|
||||
diff --git a/elf/tst-rtld-list-tunables.sh b/elf/tst-rtld-list-tunables.sh
|
||||
index e7bbdde94952b872..78f4ed2ebbd3db2c 100755
|
||||
--- a/elf/tst-rtld-list-tunables.sh
|
||||
+++ b/elf/tst-rtld-list-tunables.sh
|
||||
@@ -26,6 +26,17 @@ run_program_env=$3
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
|
||||
+# Unset tunables and their aliases.
|
||||
+GLIBC_TUNABLES=
|
||||
+MALLOC_ARENA_MAX=
|
||||
+MALLOC_ARENA_TEST=
|
||||
+MALLOC_CHECK_=
|
||||
+MALLOC_MMAP_MAX_=
|
||||
+MALLOC_MMAP_THRESHOLD_=
|
||||
+MALLOC_PERTURB_=
|
||||
+MALLOC_TOP_PAD_=
|
||||
+MALLOC_TRIM_THRESHOLD_=
|
||||
+
|
||||
${test_wrapper_env} \
|
||||
${run_program_env} \
|
||||
$rtld --list-tunables \
|
578
SOURCES/glibc-rh2023420-3.patch
Normal file
578
SOURCES/glibc-rh2023420-3.patch
Normal file
@ -0,0 +1,578 @@
|
||||
commit 851f32cf7bf7067f73b991610778915edd57d7b4
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Mar 2 14:38:42 2021 +0100
|
||||
|
||||
ld.so: Implement the --list-diagnostics option
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index aa65ec59f143bccf..d246f1c0d9e019fd 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -64,7 +64,7 @@ elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
|
||||
# interpreter and operating independent of libc.
|
||||
rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \
|
||||
dl-error-minimal dl-conflict dl-hwcaps dl-hwcaps_split dl-hwcaps-subdirs \
|
||||
- dl-usage
|
||||
+ dl-usage dl-diagnostics dl-diagnostics-kernel dl-diagnostics-cpu
|
||||
all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines)
|
||||
|
||||
CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables
|
||||
@@ -672,6 +672,9 @@ CFLAGS-cache.c += $(SYSCONF-FLAGS)
|
||||
CFLAGS-rtld.c += $(SYSCONF-FLAGS)
|
||||
CFLAGS-dl-usage.c += $(SYSCONF-FLAGS) \
|
||||
-D'RTLD="$(rtlddir)/$(rtld-installed-name)"'
|
||||
+CFLAGS-dl-diagnostics.c += $(SYSCONF-FLAGS) \
|
||||
+ -D'PREFIX="$(prefix)"' \
|
||||
+ -D'RTLD="$(rtlddir)/$(rtld-installed-name)"'
|
||||
|
||||
cpp-srcs-left := $(all-rtld-routines:=.os)
|
||||
lib := rtld
|
||||
diff --git a/elf/dl-diagnostics-cpu.c b/elf/dl-diagnostics-cpu.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..f7d149764bcb35a1
|
||||
--- /dev/null
|
||||
+++ b/elf/dl-diagnostics-cpu.c
|
||||
@@ -0,0 +1,24 @@
|
||||
+/* Print CPU diagnostics data in ld.so. Stub version.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <dl-diagnostics.h>
|
||||
+
|
||||
+void
|
||||
+_dl_diagnostics_cpu (void)
|
||||
+{
|
||||
+}
|
||||
diff --git a/elf/dl-diagnostics-kernel.c b/elf/dl-diagnostics-kernel.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..831c358f1463cbf4
|
||||
--- /dev/null
|
||||
+++ b/elf/dl-diagnostics-kernel.c
|
||||
@@ -0,0 +1,24 @@
|
||||
+/* Print kernel diagnostics data in ld.so. Stub version.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <dl-diagnostics.h>
|
||||
+
|
||||
+void
|
||||
+_dl_diagnostics_kernel (void)
|
||||
+{
|
||||
+}
|
||||
diff --git a/elf/dl-diagnostics.c b/elf/dl-diagnostics.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..bef224b36cbf5fc3
|
||||
--- /dev/null
|
||||
+++ b/elf/dl-diagnostics.c
|
||||
@@ -0,0 +1,265 @@
|
||||
+/* Print diagnostics data in ld.so.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <gnu/lib-names.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stddef.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include <dl-diagnostics.h>
|
||||
+#include <dl-hwcaps.h>
|
||||
+#include <dl-main.h>
|
||||
+#include <dl-procinfo.h>
|
||||
+#include <dl-sysdep.h>
|
||||
+#include <ldsodefs.h>
|
||||
+#include "trusted-dirs.h"
|
||||
+#include "version.h"
|
||||
+
|
||||
+/* Write CH to standard output. */
|
||||
+static void
|
||||
+_dl_putc (char ch)
|
||||
+{
|
||||
+ _dl_write (STDOUT_FILENO, &ch, 1);
|
||||
+}
|
||||
+
|
||||
+/* Print CH to standard output, quoting it if necessary. */
|
||||
+static void
|
||||
+print_quoted_char (char ch)
|
||||
+{
|
||||
+ if (ch < ' ' || ch > '~')
|
||||
+ {
|
||||
+ char buf[4];
|
||||
+ buf[0] = '\\';
|
||||
+ buf[1] = '0' + ((ch >> 6) & 7);
|
||||
+ buf[2] = '0' + ((ch >> 6) & 7);
|
||||
+ buf[3] = '0' + (ch & 7);
|
||||
+ _dl_write (STDOUT_FILENO, buf, 4);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (ch == '\\' || ch == '"')
|
||||
+ _dl_putc ('\\');
|
||||
+ _dl_putc (ch);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Print S of LEN bytes to standard output, quoting characters as
|
||||
+ needed. */
|
||||
+static void
|
||||
+print_string_length (const char *s, size_t len)
|
||||
+{
|
||||
+ _dl_putc ('"');
|
||||
+ for (size_t i = 0; i < len; ++i)
|
||||
+ print_quoted_char (s[i]);
|
||||
+ _dl_putc ('"');
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+_dl_diagnostics_print_string (const char *s)
|
||||
+{
|
||||
+ if (s == NULL)
|
||||
+ {
|
||||
+ _dl_printf ("0x0");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ _dl_putc ('"');
|
||||
+ while (*s != '\0')
|
||||
+ {
|
||||
+ print_quoted_char (*s);
|
||||
+ ++s;
|
||||
+ }
|
||||
+ _dl_putc ('"');
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+_dl_diagnostics_print_labeled_string (const char *label, const char *s)
|
||||
+{
|
||||
+ _dl_printf ("%s=", label);
|
||||
+ _dl_diagnostics_print_string (s);
|
||||
+ _dl_putc ('\n');
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+_dl_diagnostics_print_labeled_value (const char *label, uint64_t value)
|
||||
+{
|
||||
+ if (sizeof (value) == sizeof (unsigned long int))
|
||||
+ /* _dl_printf can print 64-bit values directly. */
|
||||
+ _dl_printf ("%s=0x%lx\n", label, (unsigned long int) value);
|
||||
+ else
|
||||
+ {
|
||||
+ uint32_t high = value >> 32;
|
||||
+ uint32_t low = value;
|
||||
+ if (high == 0)
|
||||
+ _dl_printf ("%s=0x%x\n", label, low);
|
||||
+ else
|
||||
+ _dl_printf ("%s=0x%x%08x\n", label, high, low);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Return true if ENV is an unfiltered environment variable. */
|
||||
+static bool
|
||||
+unfiltered_envvar (const char *env, size_t *name_length)
|
||||
+{
|
||||
+ char *env_equal = strchr (env, '=');
|
||||
+ if (env_equal == NULL)
|
||||
+ {
|
||||
+ /* Always dump malformed entries. */
|
||||
+ *name_length = strlen (env);
|
||||
+ return true;
|
||||
+ }
|
||||
+ size_t envname_length = env_equal - env;
|
||||
+ *name_length = envname_length;
|
||||
+
|
||||
+ /* LC_ and LD_ variables. */
|
||||
+ if (env[0] == 'L' && (env[1] == 'C' || env[1] == 'D')
|
||||
+ && env[2] == '_')
|
||||
+ return true;
|
||||
+
|
||||
+ /* MALLOC_ variables. */
|
||||
+ if (strncmp (env, "MALLOC_", strlen ("MALLOC_")) == 0)
|
||||
+ return true;
|
||||
+
|
||||
+ static const char unfiltered[] =
|
||||
+ "DATEMSK\0"
|
||||
+ "GCONV_PATH\0"
|
||||
+ "GETCONF_DIR\0"
|
||||
+ "GETCONF_DIR\0"
|
||||
+ "GLIBC_TUNABLES\0"
|
||||
+ "GMON_OUTPUT_PREFIX\0"
|
||||
+ "HESIOD_CONFIG\0"
|
||||
+ "HES_DOMAIN\0"
|
||||
+ "HOSTALIASES\0"
|
||||
+ "I18NPATH\0"
|
||||
+ "IFS\0"
|
||||
+ "LANG\0"
|
||||
+ "LOCALDOMAIN\0"
|
||||
+ "LOCPATH\0"
|
||||
+ "MSGVERB\0"
|
||||
+ "NIS_DEFAULTS\0"
|
||||
+ "NIS_GROUP\0"
|
||||
+ "NIS_PATH\0"
|
||||
+ "NLSPATH\0"
|
||||
+ "PATH\0"
|
||||
+ "POSIXLY_CORRECT\0"
|
||||
+ "RESOLV_HOST_CONF\0"
|
||||
+ "RES_OPTIONS\0"
|
||||
+ "SEV_LEVEL\0"
|
||||
+ "TMPDIR\0"
|
||||
+ "TZ\0"
|
||||
+ "TZDIR\0"
|
||||
+ /* Two null bytes at the end to mark the end of the list via an
|
||||
+ empty substring. */
|
||||
+ ;
|
||||
+ for (const char *candidate = unfiltered; *candidate != '\0'; )
|
||||
+ {
|
||||
+ size_t candidate_length = strlen (candidate);
|
||||
+ if (candidate_length == envname_length
|
||||
+ && memcmp (candidate, env, candidate_length) == 0)
|
||||
+ return true;
|
||||
+ candidate += candidate_length + 1;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+/* Dump the process environment. */
|
||||
+static void
|
||||
+print_environ (char **environ)
|
||||
+{
|
||||
+ unsigned int index = 0;
|
||||
+ for (char **envp = environ; *envp != NULL; ++envp)
|
||||
+ {
|
||||
+ char *env = *envp;
|
||||
+ size_t name_length;
|
||||
+ bool unfiltered = unfiltered_envvar (env, &name_length);
|
||||
+ _dl_printf ("env%s[0x%x]=",
|
||||
+ unfiltered ? "" : "_filtered", index);
|
||||
+ if (unfiltered)
|
||||
+ _dl_diagnostics_print_string (env);
|
||||
+ else
|
||||
+ print_string_length (env, name_length);
|
||||
+ _dl_putc ('\n');
|
||||
+ ++index;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Print configured paths and the built-in search path. */
|
||||
+static void
|
||||
+print_paths (void)
|
||||
+{
|
||||
+ _dl_diagnostics_print_labeled_string ("path.prefix", PREFIX);
|
||||
+ _dl_diagnostics_print_labeled_string ("path.rtld", RTLD);
|
||||
+ _dl_diagnostics_print_labeled_string ("path.sysconfdir", SYSCONFDIR);
|
||||
+
|
||||
+ unsigned int index = 0;
|
||||
+ static const char *system_dirs = SYSTEM_DIRS "\0";
|
||||
+ for (const char *e = system_dirs; *e != '\0'; )
|
||||
+ {
|
||||
+ size_t len = strlen (e);
|
||||
+ _dl_printf ("path.system_dirs[0x%x]=", index);
|
||||
+ print_string_length (e, len);
|
||||
+ _dl_putc ('\n');
|
||||
+ ++index;
|
||||
+ e += len + 1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Print information about the glibc version. */
|
||||
+static void
|
||||
+print_version (void)
|
||||
+{
|
||||
+ _dl_diagnostics_print_labeled_string ("version.release", RELEASE);
|
||||
+ _dl_diagnostics_print_labeled_string ("version.version", VERSION);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+_dl_print_diagnostics (char **environ)
|
||||
+{
|
||||
+#ifdef HAVE_DL_DISCOVER_OSVERSION
|
||||
+ _dl_diagnostics_print_labeled_value
|
||||
+ ("dl_discover_osversion", _dl_discover_osversion ());
|
||||
+#endif
|
||||
+ _dl_diagnostics_print_labeled_string ("dl_dst_lib", DL_DST_LIB);
|
||||
+ _dl_diagnostics_print_labeled_value ("dl_hwcap", GLRO (dl_hwcap));
|
||||
+ _dl_diagnostics_print_labeled_value ("dl_hwcap_important", HWCAP_IMPORTANT);
|
||||
+ _dl_diagnostics_print_labeled_value ("dl_hwcap2", GLRO (dl_hwcap2));
|
||||
+ _dl_diagnostics_print_labeled_string
|
||||
+ ("dl_hwcaps_subdirs", _dl_hwcaps_subdirs);
|
||||
+ _dl_diagnostics_print_labeled_value
|
||||
+ ("dl_hwcaps_subdirs_active", _dl_hwcaps_subdirs_active ());
|
||||
+ _dl_diagnostics_print_labeled_value ("dl_osversion", GLRO (dl_osversion));
|
||||
+ _dl_diagnostics_print_labeled_value ("dl_pagesize", GLRO (dl_pagesize));
|
||||
+ _dl_diagnostics_print_labeled_string ("dl_platform", GLRO (dl_platform));
|
||||
+ _dl_diagnostics_print_labeled_string
|
||||
+ ("dl_profile_output", GLRO (dl_profile_output));
|
||||
+ _dl_diagnostics_print_labeled_value
|
||||
+ ("dl_string_platform", _dl_string_platform ( GLRO (dl_platform)));
|
||||
+
|
||||
+ _dl_diagnostics_print_labeled_string ("dso.ld", LD_SO);
|
||||
+ _dl_diagnostics_print_labeled_string ("dso.libc", LIBC_SO);
|
||||
+
|
||||
+ print_environ (environ);
|
||||
+ print_paths ();
|
||||
+ print_version ();
|
||||
+
|
||||
+ _dl_diagnostics_kernel ();
|
||||
+ _dl_diagnostics_cpu ();
|
||||
+
|
||||
+ _exit (EXIT_SUCCESS);
|
||||
+}
|
||||
diff --git a/elf/dl-diagnostics.h b/elf/dl-diagnostics.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..27dcb12bca12e5b6
|
||||
--- /dev/null
|
||||
+++ b/elf/dl-diagnostics.h
|
||||
@@ -0,0 +1,46 @@
|
||||
+/* Interfaces for printing diagnostics in ld.so.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef _DL_DIAGNOSTICS_H
|
||||
+#define _DL_DIAGNOSTICS_H
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+/* Write the null-terminated string to standard output, surrounded in
|
||||
+ quotation marks. */
|
||||
+void _dl_diagnostics_print_string (const char *s) attribute_hidden;
|
||||
+
|
||||
+/* Like _dl_diagnostics_print_string, but add a LABEL= prefix, and a
|
||||
+ newline character as a suffix. */
|
||||
+void _dl_diagnostics_print_labeled_string (const char *label, const char *s)
|
||||
+ attribute_hidden;
|
||||
+
|
||||
+/* Print LABEL=VALUE to standard output, followed by a newline
|
||||
+ character. */
|
||||
+void _dl_diagnostics_print_labeled_value (const char *label, uint64_t value)
|
||||
+ attribute_hidden;
|
||||
+
|
||||
+/* Print diagnostics data for the kernel. Called from
|
||||
+ _dl_print_diagnostics. */
|
||||
+void _dl_diagnostics_kernel (void) attribute_hidden;
|
||||
+
|
||||
+/* Print diagnostics data for the CPU(s). Called from
|
||||
+ _dl_print_diagnostics. */
|
||||
+void _dl_diagnostics_cpu (void) attribute_hidden;
|
||||
+
|
||||
+#endif /* _DL_DIAGNOSTICS_H */
|
||||
diff --git a/elf/dl-main.h b/elf/dl-main.h
|
||||
index 9e7b51d8f010e904..9fbbdb0fac09adf3 100644
|
||||
--- a/elf/dl-main.h
|
||||
+++ b/elf/dl-main.h
|
||||
@@ -63,7 +63,7 @@ struct audit_list
|
||||
enum rtld_mode
|
||||
{
|
||||
rtld_mode_normal, rtld_mode_list, rtld_mode_verify, rtld_mode_trace,
|
||||
- rtld_mode_list_tunables, rtld_mode_help,
|
||||
+ rtld_mode_list_tunables, rtld_mode_list_diagnostics, rtld_mode_help,
|
||||
};
|
||||
|
||||
/* Aggregated state information extracted from environment variables
|
||||
@@ -121,4 +121,7 @@ _Noreturn void _dl_version (void) attribute_hidden;
|
||||
_Noreturn void _dl_help (const char *argv0, struct dl_main_state *state)
|
||||
attribute_hidden;
|
||||
|
||||
+/* Print a diagnostics dump. */
|
||||
+_Noreturn void _dl_print_diagnostics (char **environ) attribute_hidden;
|
||||
+
|
||||
#endif /* _DL_MAIN */
|
||||
diff --git a/elf/dl-usage.c b/elf/dl-usage.c
|
||||
index 908b4894b3014b2d..e19e1791d9169da2 100644
|
||||
--- a/elf/dl-usage.c
|
||||
+++ b/elf/dl-usage.c
|
||||
@@ -261,6 +261,7 @@ setting environment variables (which would be inherited by subprocesses).\n\
|
||||
--list-tunables list all tunables with minimum and maximum values\n"
|
||||
#endif
|
||||
"\
|
||||
+ --list-diagnostics list diagnostics information\n\
|
||||
--help display this help and exit\n\
|
||||
--version output version information and exit\n\
|
||||
\n\
|
||||
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||
index 54b621ec5ca014fa..d14c388f548d6d51 100644
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -138,6 +138,7 @@ static void dl_main_state_init (struct dl_main_state *state);
|
||||
/* Process all environments variables the dynamic linker must recognize.
|
||||
Since all of them start with `LD_' we are a bit smarter while finding
|
||||
all the entries. */
|
||||
+extern char **_environ attribute_hidden;
|
||||
static void process_envvars (struct dl_main_state *state);
|
||||
|
||||
#ifdef DL_ARGV_NOT_RELRO
|
||||
@@ -1273,6 +1274,14 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
++_dl_argv;
|
||||
}
|
||||
#endif
|
||||
+ else if (! strcmp (_dl_argv[1], "--list-diagnostics"))
|
||||
+ {
|
||||
+ state.mode = rtld_mode_list_diagnostics;
|
||||
+
|
||||
+ ++_dl_skip_args;
|
||||
+ --_dl_argc;
|
||||
+ ++_dl_argv;
|
||||
+ }
|
||||
else if (strcmp (_dl_argv[1], "--help") == 0)
|
||||
{
|
||||
state.mode = rtld_mode_help;
|
||||
@@ -1301,6 +1310,9 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
}
|
||||
#endif
|
||||
|
||||
+ if (state.mode == rtld_mode_list_diagnostics)
|
||||
+ _dl_print_diagnostics (_environ);
|
||||
+
|
||||
/* If we have no further argument the program was called incorrectly.
|
||||
Grant the user some education. */
|
||||
if (_dl_argc < 2)
|
||||
@@ -2623,12 +2635,6 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n");
|
||||
}
|
||||
}
|
||||
|
||||
-/* Process all environments variables the dynamic linker must recognize.
|
||||
- Since all of them start with `LD_' we are a bit smarter while finding
|
||||
- all the entries. */
|
||||
-extern char **_environ attribute_hidden;
|
||||
-
|
||||
-
|
||||
static void
|
||||
process_envvars (struct dl_main_state *state)
|
||||
{
|
||||
diff --git a/sysdeps/unix/sysv/linux/dl-diagnostics-kernel.c b/sysdeps/unix/sysv/linux/dl-diagnostics-kernel.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..59f6402c547ba590
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/dl-diagnostics-kernel.c
|
||||
@@ -0,0 +1,77 @@
|
||||
+/* Print kernel diagnostics data in ld.so. Linux version.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <dl-diagnostics.h>
|
||||
+#include <ldsodefs.h>
|
||||
+#include <sys/utsname.h>
|
||||
+
|
||||
+/* Dump the auxiliary vector to standard output. */
|
||||
+static void
|
||||
+print_auxv (void)
|
||||
+{
|
||||
+ /* See _dl_show_auxv. The code below follows the general output
|
||||
+ format for diagnostic dumps. */
|
||||
+ unsigned int index = 0;
|
||||
+ for (ElfW(auxv_t) *av = GLRO(dl_auxv); av->a_type != AT_NULL; ++av)
|
||||
+ {
|
||||
+ _dl_printf ("auxv[0x%x].a_type=0x%lx\n"
|
||||
+ "auxv[0x%x].a_val=",
|
||||
+ index, (unsigned long int) av->a_type, index);
|
||||
+ if (av->a_type == AT_EXECFN
|
||||
+ || av->a_type == AT_PLATFORM
|
||||
+ || av->a_type == AT_BASE_PLATFORM)
|
||||
+ /* The address of the strings is not useful at all, so print
|
||||
+ the strings themselvs. */
|
||||
+ _dl_diagnostics_print_string ((const char *) av->a_un.a_val);
|
||||
+ else
|
||||
+ _dl_printf ("0x%lx", (unsigned long int) av->a_un.a_val);
|
||||
+ _dl_printf ("\n");
|
||||
+ ++index;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Print one uname entry. */
|
||||
+static void
|
||||
+print_utsname_entry (const char *field, const char *value)
|
||||
+{
|
||||
+ _dl_printf ("uname.");
|
||||
+ _dl_diagnostics_print_labeled_string (field, value);
|
||||
+}
|
||||
+
|
||||
+/* Print information from uname, including the kernel version. */
|
||||
+static void
|
||||
+print_uname (void)
|
||||
+{
|
||||
+ struct utsname uts;
|
||||
+ if (__uname (&uts) == 0)
|
||||
+ {
|
||||
+ print_utsname_entry ("sysname", uts.sysname);
|
||||
+ print_utsname_entry ("nodename", uts.nodename);
|
||||
+ print_utsname_entry ("release", uts.release);
|
||||
+ print_utsname_entry ("version", uts.version);
|
||||
+ print_utsname_entry ("machine", uts.machine);
|
||||
+ print_utsname_entry ("domainname", uts.domainname);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+_dl_diagnostics_kernel (void)
|
||||
+{
|
||||
+ print_auxv ();
|
||||
+ print_uname ();
|
||||
+}
|
117
SOURCES/glibc-rh2023420-4.patch
Normal file
117
SOURCES/glibc-rh2023420-4.patch
Normal file
@ -0,0 +1,117 @@
|
||||
commit e4933c8a92ea08eecdf3ab45e7f76c95dc3d20ac
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Mar 2 14:58:05 2021 +0100
|
||||
|
||||
x86: Automate generation of PREFERRED_FEATURE_INDEX_1 bitfield
|
||||
|
||||
Use a .def file to define the bitfield layout, so that it is possible
|
||||
to iterate over field members using the preprocessor.
|
||||
|
||||
Conflicts:
|
||||
sysdeps/x86/include/cpu-features.h
|
||||
(re-did the change from scratch)
|
||||
sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
|
||||
(adjusted to the downstream bits)
|
||||
|
||||
diff --git a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
|
||||
new file mode 100644
|
||||
index 0000000000000000..17a5cc428c1dabea
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
|
||||
@@ -0,0 +1,34 @@
|
||||
+/* Bits in the PREFERRED_FEATURE_INDEX_1 bitfield of <cpu-features.h>.
|
||||
+ Copyright (C) 2020-2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+BIT (I586)
|
||||
+BIT (I686)
|
||||
+BIT (Fast_Rep_String)
|
||||
+BIT (Fast_Copy_Backward)
|
||||
+BIT (Fast_Unaligned_Load)
|
||||
+BIT (Fast_Unaligned_Copy)
|
||||
+BIT (Slow_BSF)
|
||||
+BIT (Slow_SSE4_2)
|
||||
+BIT (AVX_Fast_Unaligned_Load)
|
||||
+BIT (Prefer_MAP_32BIT_EXEC)
|
||||
+BIT (Prefer_PMINUB_for_stringop)
|
||||
+BIT (Prefer_No_VZEROUPPER)
|
||||
+BIT (Prefer_ERMS)
|
||||
+BIT (Prefer_FSRM)
|
||||
+BIT (Prefer_No_AVX512)
|
||||
+BIT (MathVec_Prefer_No_AVX512)
|
||||
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
|
||||
index f62be0b9b3746675..f43e22f677b249a9 100644
|
||||
--- a/sysdeps/x86/include/cpu-features.h
|
||||
+++ b/sysdeps/x86/include/cpu-features.h
|
||||
@@ -80,40 +80,23 @@ enum
|
||||
# define HAS_ARCH_FEATURE(name) \
|
||||
CPU_FEATURE_PREFERRED (name)
|
||||
|
||||
-/* PREFERRED_FEATURE_INDEX_1. */
|
||||
-# define bit_arch_I586 (1u << 0)
|
||||
-# define bit_arch_I686 (1u << 1)
|
||||
-# define bit_arch_Fast_Rep_String (1u << 2)
|
||||
-# define bit_arch_Fast_Copy_Backward (1u << 3)
|
||||
-# define bit_arch_Fast_Unaligned_Load (1u << 4)
|
||||
-# define bit_arch_Fast_Unaligned_Copy (1u << 5)
|
||||
-# define bit_arch_Slow_BSF (1u << 6)
|
||||
-# define bit_arch_Slow_SSE4_2 (1u << 7)
|
||||
-# define bit_arch_AVX_Fast_Unaligned_Load (1u << 8)
|
||||
-# define bit_arch_Prefer_MAP_32BIT_EXEC (1u << 9)
|
||||
-# define bit_arch_Prefer_PMINUB_for_stringop (1u << 10)
|
||||
-# define bit_arch_Prefer_No_VZEROUPPER (1u << 11)
|
||||
-# define bit_arch_Prefer_ERMS (1u << 12)
|
||||
-# define bit_arch_Prefer_FSRM (1u << 13)
|
||||
-# define bit_arch_Prefer_No_AVX512 (1u << 14)
|
||||
-# define bit_arch_MathVec_Prefer_No_AVX512 (1u << 15)
|
||||
-
|
||||
-# define index_arch_Fast_Rep_String PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_Fast_Copy_Backward PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_Slow_BSF PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_Prefer_PMINUB_for_stringop PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_Fast_Unaligned_Copy PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_I586 PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_I686 PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_Slow_SSE4_2 PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_AVX_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_Prefer_MAP_32BIT_EXEC PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_Prefer_No_VZEROUPPER PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_Prefer_ERMS PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_MathVec_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
|
||||
-# define index_arch_Prefer_FSRM PREFERRED_FEATURE_INDEX_1
|
||||
+/* PREFERRED_FEATURE_INDEX_1. First define the bitindex values
|
||||
+ sequentially, then define the bit_arch* and index_arch_* lookup
|
||||
+ constants. */
|
||||
+enum
|
||||
+ {
|
||||
+#define BIT(x) _bitindex_arch_##x ,
|
||||
+#include "cpu-features-preferred_feature_index_1.def"
|
||||
+#undef BIT
|
||||
+ };
|
||||
+enum
|
||||
+ {
|
||||
+#define BIT(x) \
|
||||
+ bit_arch_##x = 1u << _bitindex_arch_##x , \
|
||||
+ index_arch_##x = PREFERRED_FEATURE_INDEX_1,
|
||||
+#include "cpu-features-preferred_feature_index_1.def"
|
||||
+#undef BIT
|
||||
+ };
|
||||
|
||||
/* XCR0 Feature flags. */
|
||||
# define bit_XMM_state (1u << 1)
|
131
SOURCES/glibc-rh2023420-5.patch
Normal file
131
SOURCES/glibc-rh2023420-5.patch
Normal file
@ -0,0 +1,131 @@
|
||||
commit 01a5746b6c8a44dc29d33e056b63485075a6a3cc
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Feb 24 13:12:04 2021 +0100
|
||||
|
||||
x86: Add CPU-specific diagnostics to ld.so --list-diagnostics
|
||||
|
||||
Conflicts:
|
||||
sysdeps/x86/dl-diagnostics-cpu.c
|
||||
(reworked due to struct differences, different knobs
|
||||
downstream)
|
||||
|
||||
diff --git a/sysdeps/x86/dl-diagnostics-cpu.c b/sysdeps/x86/dl-diagnostics-cpu.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..0ba286a828b69937
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86/dl-diagnostics-cpu.c
|
||||
@@ -0,0 +1,101 @@
|
||||
+/* Print CPU diagnostics data in ld.so. x86 version.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <dl-diagnostics.h>
|
||||
+#include <ldsodefs.h>
|
||||
+
|
||||
+static void
|
||||
+print_cpu_features_value (const char *label, uint64_t value)
|
||||
+{
|
||||
+ _dl_printf ("x86.cpu_features.");
|
||||
+ _dl_diagnostics_print_labeled_value (label, value);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+print_cpu_feature_internal (unsigned int index, const char *kind,
|
||||
+ unsigned int reg, uint32_t value)
|
||||
+{
|
||||
+ _dl_printf ("x86.cpu_features.features[0x%x].%s[0x%x]=0x%x\n",
|
||||
+ index, kind, reg, value);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+print_cpu_feature_preferred (const char *label, unsigned int flag)
|
||||
+{
|
||||
+ _dl_printf("x86.cpu_features.preferred.%s=0x%x\n", label, flag);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+_dl_diagnostics_cpu (void)
|
||||
+{
|
||||
+ const struct cpu_features *cpu_features = __get_cpu_features ();
|
||||
+
|
||||
+ print_cpu_features_value ("basic.kind", cpu_features->basic.kind);
|
||||
+ print_cpu_features_value ("basic.max_cpuid", cpu_features->basic.max_cpuid);
|
||||
+ print_cpu_features_value ("basic.family", cpu_features->basic.family);
|
||||
+ print_cpu_features_value ("basic.model", cpu_features->basic.model);
|
||||
+ print_cpu_features_value ("basic.stepping", cpu_features->basic.stepping);
|
||||
+
|
||||
+ for (unsigned int index = 0; index < COMMON_CPUID_INDEX_MAX; ++index)
|
||||
+ {
|
||||
+ /* Downstream, these constants are not part of the ABI yet, so
|
||||
+ analysis needs to take the precise glibc version into
|
||||
+ account. */
|
||||
+ print_cpu_feature_internal
|
||||
+ (index, "cpuid", 0, cpu_features->features[index].cpuid.eax);
|
||||
+ print_cpu_feature_internal
|
||||
+ (index, "cpuid", 1, cpu_features->features[index].cpuid.ebx);
|
||||
+ print_cpu_feature_internal
|
||||
+ (index, "cpuid", 2, cpu_features->features[index].cpuid.ecx);
|
||||
+ print_cpu_feature_internal
|
||||
+ (index, "cpuid", 3, cpu_features->features[index].cpuid.edx);
|
||||
+ print_cpu_feature_internal
|
||||
+ (index, "usable", 0, cpu_features->features[index].usable.eax);
|
||||
+ print_cpu_feature_internal
|
||||
+ (index, "usable", 1, cpu_features->features[index].usable.ebx);
|
||||
+ print_cpu_feature_internal
|
||||
+ (index, "usable", 2, cpu_features->features[index].usable.ecx);
|
||||
+ print_cpu_feature_internal
|
||||
+ (index, "usable", 3, cpu_features->features[index].usable.edx);
|
||||
+ }
|
||||
+
|
||||
+ /* The preferred indicators are not part of the ABI and need to be
|
||||
+ translated. */
|
||||
+#define BIT(x) \
|
||||
+ print_cpu_feature_preferred (#x, CPU_FEATURE_PREFERRED_P (cpu_features, x));
|
||||
+#include "cpu-features-preferred_feature_index_1.def"
|
||||
+#undef BIT
|
||||
+
|
||||
+ print_cpu_features_value ("xsave_state_size",
|
||||
+ cpu_features->xsave_state_size);
|
||||
+ print_cpu_features_value ("xsave_state_full_size",
|
||||
+ cpu_features->xsave_state_full_size);
|
||||
+ print_cpu_features_value ("data_cache_size", cpu_features->data_cache_size);
|
||||
+ print_cpu_features_value ("shared_cache_size",
|
||||
+ cpu_features->shared_cache_size);
|
||||
+ print_cpu_features_value ("non_temporal_threshold",
|
||||
+ cpu_features->non_temporal_threshold);
|
||||
+ print_cpu_features_value ("rep_movsb_threshold",
|
||||
+ cpu_features->rep_movsb_threshold);
|
||||
+ print_cpu_features_value ("rep_stosb_threshold",
|
||||
+ cpu_features->rep_stosb_threshold);
|
||||
+ _Static_assert (offsetof (struct cpu_features, rep_stosb_threshold)
|
||||
+ + sizeof (cpu_features->rep_stosb_threshold)
|
||||
+ == sizeof (*cpu_features),
|
||||
+ "last cpu_features field has been printed");
|
||||
+}
|
||||
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
|
||||
index f43e22f677b249a9..536643b209425198 100644
|
||||
--- a/sysdeps/x86/include/cpu-features.h
|
||||
+++ b/sysdeps/x86/include/cpu-features.h
|
||||
@@ -107,6 +107,8 @@ enum
|
||||
# define bit_XTILECFG_state (1u << 17)
|
||||
# define bit_XTILEDATA_state (1u << 18)
|
||||
|
||||
+/* NB: When adding new fields, update sysdeps/x86/dl-diagnostics-cpu.c
|
||||
+ to print them. */
|
||||
struct cpu_features
|
||||
{
|
||||
struct cpu_features_basic basic;
|
255
SOURCES/glibc-rh2023420-6.patch
Normal file
255
SOURCES/glibc-rh2023420-6.patch
Normal file
@ -0,0 +1,255 @@
|
||||
commit c1cb2deeca1a85c6fc5bd41b90816d48a95bc434
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Sun Dec 5 11:28:34 2021 +0100
|
||||
|
||||
elf: execve statically linked programs instead of crashing [BZ #28648]
|
||||
|
||||
Programs without dynamic dependencies and without a program
|
||||
interpreter are now run via execve.
|
||||
|
||||
Previously, the dynamic linker either crashed while attempting to
|
||||
read a non-existing dynamic segment (looking for DT_AUDIT/DT_DEPAUDIT
|
||||
data), or the self-relocated in the static PIE executable crashed
|
||||
because the outer dynamic linker had already applied RELRO protection.
|
||||
|
||||
<dl-execve.h> is needed because execve is not available in the
|
||||
dynamic loader on Hurd.
|
||||
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(some missing backports)
|
||||
elf/rtld.c
|
||||
(missing rework of ld.so self-relocation downstream,
|
||||
always print error as a number due to missing
|
||||
sterrorname_np, also fix errcode/errno glitch)
|
||||
sysdeps/unix/sysv/linux/dl-execve.h
|
||||
(missing INTERNAL_SYSCALL_CALL refactoring to Linux-like
|
||||
calling convention)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index d246f1c0d9e019fd..b3e8ab2792608de7 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -214,7 +214,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
tst-tls-ie tst-tls-ie-dlmopen \
|
||||
argv0test \
|
||||
tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
|
||||
- tst-tls20 tst-tls21
|
||||
+ tst-tls20 tst-tls21 \
|
||||
+ tst-rtld-run-static \
|
||||
# reldep9
|
||||
tests-internal += loadtest unload unload2 circleload1 \
|
||||
neededtest neededtest2 neededtest3 neededtest4 \
|
||||
@@ -1917,3 +1918,5 @@ $(objpfx)tst-tls20.out: $(objpfx)tst-tls20mod-bad.so \
|
||||
$(objpfx)tst-tls21: $(libdl) $(shared-thread-library)
|
||||
$(objpfx)tst-tls21.out: $(objpfx)tst-tls21mod.so
|
||||
$(objpfx)tst-tls21mod.so: $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so)
|
||||
+
|
||||
+$(objpfx)tst-rtld-run-static.out: $(objpfx)/ldconfig
|
||||
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||
index d14c388f548d6d51..461d8c114a875a9b 100644
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <dl-main.h>
|
||||
#include <gnu/lib-names.h>
|
||||
#include <dl-tunables.h>
|
||||
+#include <dl-execve.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -1114,6 +1115,40 @@ load_audit_modules (struct link_map *main_map, struct audit_list *audit_list)
|
||||
}
|
||||
}
|
||||
|
||||
+/* Check if the executable is not actualy dynamically linked, and
|
||||
+ invoke it directly in that case. */
|
||||
+static void
|
||||
+rtld_chain_load (struct link_map *main_map, char *argv0)
|
||||
+{
|
||||
+ /* The dynamic loader run against itself. */
|
||||
+ const char *rtld_soname
|
||||
+ = ((const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
|
||||
+ + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val);
|
||||
+ if (main_map->l_info[DT_SONAME] != NULL
|
||||
+ && strcmp (rtld_soname,
|
||||
+ ((const char *) D_PTR (main_map, l_info[DT_STRTAB])
|
||||
+ + main_map->l_info[DT_SONAME]->d_un.d_val)) == 0)
|
||||
+ _dl_fatal_printf ("%s: loader cannot load itself\n", rtld_soname);
|
||||
+
|
||||
+ /* With DT_NEEDED dependencies, the executable is dynamically
|
||||
+ linked. */
|
||||
+ if (__glibc_unlikely (main_map->l_info[DT_NEEDED] != NULL))
|
||||
+ return;
|
||||
+
|
||||
+ /* If the executable has program interpreter, it is dynamically
|
||||
+ linked. */
|
||||
+ for (size_t i = 0; i < main_map->l_phnum; ++i)
|
||||
+ if (main_map->l_phdr[i].p_type == PT_INTERP)
|
||||
+ return;
|
||||
+
|
||||
+ const char *pathname = _dl_argv[0];
|
||||
+ if (argv0 != NULL)
|
||||
+ _dl_argv[0] = argv0;
|
||||
+ int errcode = __rtld_execve (pathname, _dl_argv, _environ);
|
||||
+ _dl_fatal_printf("%s: cannot execute %s: %d\n",
|
||||
+ rtld_soname, pathname, errcode);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
dl_main (const ElfW(Phdr) *phdr,
|
||||
ElfW(Word) phnum,
|
||||
@@ -1384,14 +1419,8 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
/* Now the map for the main executable is available. */
|
||||
main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
|
||||
- if (__glibc_likely (state.mode == rtld_mode_normal)
|
||||
- && GL(dl_rtld_map).l_info[DT_SONAME] != NULL
|
||||
- && main_map->l_info[DT_SONAME] != NULL
|
||||
- && strcmp ((const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
|
||||
- + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val,
|
||||
- (const char *) D_PTR (main_map, l_info[DT_STRTAB])
|
||||
- + main_map->l_info[DT_SONAME]->d_un.d_val) == 0)
|
||||
- _dl_fatal_printf ("loader cannot load itself\n");
|
||||
+ if (__glibc_likely (state.mode == rtld_mode_normal))
|
||||
+ rtld_chain_load (main_map, argv0);
|
||||
|
||||
phdr = main_map->l_phdr;
|
||||
phnum = main_map->l_phnum;
|
||||
diff --git a/elf/tst-rtld-run-static.c b/elf/tst-rtld-run-static.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..7281093504b675c4
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-rtld-run-static.c
|
||||
@@ -0,0 +1,62 @@
|
||||
+/* Test running statically linked programs using ld.so.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/capture_subprocess.h>
|
||||
+#include <string.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ char *ldconfig_path = xasprintf ("%s/elf/ldconfig", support_objdir_root);
|
||||
+
|
||||
+ {
|
||||
+ char *argv[] = { (char *) "ld.so", ldconfig_path, (char *) "--help", NULL };
|
||||
+ struct support_capture_subprocess cap
|
||||
+ = support_capture_subprogram (support_objdir_elf_ldso, argv);
|
||||
+ support_capture_subprocess_check (&cap, "no --argv0", 0, sc_allow_stdout);
|
||||
+ puts ("info: output without --argv0:");
|
||||
+ puts (cap.out.buffer);
|
||||
+ TEST_VERIFY (strstr (cap.out.buffer, "Usage: ldconfig [OPTION...]\n")
|
||||
+ == cap.out.buffer);
|
||||
+ support_capture_subprocess_free (&cap);
|
||||
+ }
|
||||
+
|
||||
+ {
|
||||
+ char *argv[] =
|
||||
+ {
|
||||
+ (char *) "ld.so", (char *) "--argv0", (char *) "ldconfig-argv0",
|
||||
+ ldconfig_path, (char *) "--help", NULL
|
||||
+ };
|
||||
+ struct support_capture_subprocess cap
|
||||
+ = support_capture_subprogram (support_objdir_elf_ldso, argv);
|
||||
+ support_capture_subprocess_check (&cap, "with --argv0", 0, sc_allow_stdout);
|
||||
+ puts ("info: output with --argv0:");
|
||||
+ puts (cap.out.buffer);
|
||||
+ TEST_VERIFY (strstr (cap.out.buffer, "Usage: ldconfig-argv0 [OPTION...]\n")
|
||||
+ == cap.out.buffer);
|
||||
+ support_capture_subprocess_free (&cap);
|
||||
+ }
|
||||
+
|
||||
+ free (ldconfig_path);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/sysdeps/generic/dl-execve.h b/sysdeps/generic/dl-execve.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..5fd097df69e1770c
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/generic/dl-execve.h
|
||||
@@ -0,0 +1,25 @@
|
||||
+/* execve for the dynamic linker. Generic stub version.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+
|
||||
+static int
|
||||
+__rtld_execve (const char *path, char *const *argv, char *const *envp)
|
||||
+{
|
||||
+ return ENOSYS;
|
||||
+}
|
||||
diff --git a/sysdeps/unix/sysv/linux/dl-execve.h b/sysdeps/unix/sysv/linux/dl-execve.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..9ec6539286bb0589
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/dl-execve.h
|
||||
@@ -0,0 +1,30 @@
|
||||
+/* execve for the dynamic linker. Linux version.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+
|
||||
+static inline int
|
||||
+__rtld_execve (const char *path, char *const *argv, char *const *envp)
|
||||
+{
|
||||
+ INTERNAL_SYSCALL_DECL (err);
|
||||
+ long int r = INTERNAL_SYSCALL_CALL (execve, err, path, argv, envp);
|
||||
+ if (INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||
+ return INTERNAL_SYSCALL_ERRNO (r, err);
|
||||
+ else
|
||||
+ return 0;
|
||||
+}
|
41
SOURCES/glibc-rh2023420-7.patch
Normal file
41
SOURCES/glibc-rh2023420-7.patch
Normal file
@ -0,0 +1,41 @@
|
||||
commit 2e75604f8337fa4332977f72a8f6726309679edf
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Dec 10 16:06:36 2021 +0100
|
||||
|
||||
elf: Install a symbolic link to ld.so as /usr/bin/ld.so
|
||||
|
||||
This makes ld.so features such as --preload, --audit,
|
||||
and --list-diagnostics more accessible to end users because they
|
||||
do not need to know the ABI name of the dynamic loader.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(versioned shared objects downstream)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index b3e8ab2792608de7..c552aff350c2faac 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -99,7 +99,7 @@ endif
|
||||
ifeq (yes,$(build-shared))
|
||||
extra-objs = $(all-rtld-routines:%=%.os) soinit.os sofini.os interp.os
|
||||
generated += librtld.os dl-allobjs.os ld.so ldd
|
||||
-install-others = $(inst_rtlddir)/$(rtld-installed-name)
|
||||
+install-others = $(inst_rtlddir)/$(rtld-installed-name) $(inst_bindir)/ld.so
|
||||
install-bin-script = ldd
|
||||
endif
|
||||
|
||||
@@ -622,6 +622,11 @@ $(inst_rtlddir)/$(rtld-installed-name): \
|
||||
$(make-target-directory)
|
||||
$(make-shlib-link)
|
||||
|
||||
+# Creates the relative /usr/bin/ld.so symbolic link.
|
||||
+$(inst_bindir)/ld.so: $(inst_rtlddir)/$(rtld-installed-name)
|
||||
+ $(make-target-directory)
|
||||
+ $(make-link)
|
||||
+
|
||||
# Special target called by parent to install just the dynamic linker.
|
||||
.PHONY: ldso_install
|
||||
ldso_install: $(inst_rtlddir)/$(rtld-installed-name)
|
64
SOURCES/glibc-rh2032281-1.patch
Normal file
64
SOURCES/glibc-rh2032281-1.patch
Normal file
@ -0,0 +1,64 @@
|
||||
commit a7e9dbb7742954814643a8562dcad09abb0b0e5d
|
||||
Author: Alexandra Hájková <ahajkova@redhat.com>
|
||||
Date: Sat Dec 26 18:45:13 2020 +0100
|
||||
|
||||
Add xchdir to libsupport.
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index dcf3c4baa2a31070..fb95a69ed9158e78 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -82,6 +82,7 @@ libsupport-routines = \
|
||||
xasprintf \
|
||||
xbind \
|
||||
xcalloc \
|
||||
+ xchdir \
|
||||
xchroot \
|
||||
xclose \
|
||||
xconnect \
|
||||
diff --git a/support/xchdir.c b/support/xchdir.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..beb4feff72832065
|
||||
--- /dev/null
|
||||
+++ b/support/xchdir.c
|
||||
@@ -0,0 +1,28 @@
|
||||
+/* chdir with error checking.
|
||||
+ Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+void
|
||||
+xchdir (const char *path)
|
||||
+{
|
||||
+ if (chdir (path) != 0)
|
||||
+ FAIL_EXIT1 ("chdir (\"%s\"): %m", path);
|
||||
+}
|
||||
diff --git a/support/xunistd.h b/support/xunistd.h
|
||||
index f99f362cb4763c5b..74fd2771d12c36fe 100644
|
||||
--- a/support/xunistd.h
|
||||
+++ b/support/xunistd.h
|
||||
@@ -44,6 +44,7 @@ long xsysconf (int name);
|
||||
long long xlseek (int fd, long long offset, int whence);
|
||||
void xftruncate (int fd, long long length);
|
||||
void xsymlink (const char *target, const char *linkpath);
|
||||
+void xchdir (const char *path);
|
||||
|
||||
/* Equivalent of "mkdir -p". */
|
||||
void xmkdirp (const char *, mode_t);
|
74
SOURCES/glibc-rh2032281-2.patch
Normal file
74
SOURCES/glibc-rh2032281-2.patch
Normal file
@ -0,0 +1,74 @@
|
||||
Additionally include stdbool.h to fix issues with bool keyword usage.
|
||||
|
||||
commit 60854f40ea2d420867ed2f0f052ee7fca661dbff
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Thu Oct 15 15:14:22 2020 -0300
|
||||
|
||||
support: Add create_temp_file_in_dir
|
||||
|
||||
It allows created a temporary file in a specified directory.
|
||||
|
||||
diff --git a/support/support.h b/support/support.h
|
||||
index f50f8cc1496d657d..96833bd4e992e6d3 100644
|
||||
--- a/support/support.h
|
||||
+++ b/support/support.h
|
||||
@@ -23,6 +23,7 @@
|
||||
#ifndef SUPPORT_H
|
||||
#define SUPPORT_H
|
||||
|
||||
+#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
/* For mode_t. */
|
||||
diff --git a/support/temp_file.c b/support/temp_file.c
|
||||
index 0bbc7f997264f758..5a2728c94a9c32ae 100644
|
||||
--- a/support/temp_file.c
|
||||
+++ b/support/temp_file.c
|
||||
@@ -60,14 +60,12 @@ add_temp_file (const char *name)
|
||||
}
|
||||
|
||||
int
|
||||
-create_temp_file (const char *base, char **filename)
|
||||
+create_temp_file_in_dir (const char *base, const char *dir, char **filename)
|
||||
{
|
||||
char *fname;
|
||||
int fd;
|
||||
|
||||
- fname = (char *) xmalloc (strlen (test_dir) + 1 + strlen (base)
|
||||
- + sizeof ("XXXXXX"));
|
||||
- strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX");
|
||||
+ fname = xasprintf ("%s/%sXXXXXX", dir, base);
|
||||
|
||||
fd = mkstemp (fname);
|
||||
if (fd == -1)
|
||||
@@ -86,6 +84,12 @@ create_temp_file (const char *base, char **filename)
|
||||
return fd;
|
||||
}
|
||||
|
||||
+int
|
||||
+create_temp_file (const char *base, char **filename)
|
||||
+{
|
||||
+ return create_temp_file_in_dir (base, test_dir, filename);
|
||||
+}
|
||||
+
|
||||
char *
|
||||
support_create_temp_directory (const char *base)
|
||||
{
|
||||
diff --git a/support/temp_file.h b/support/temp_file.h
|
||||
index c7795cc577ca22a9..d64563f41f1f50cd 100644
|
||||
--- a/support/temp_file.h
|
||||
+++ b/support/temp_file.h
|
||||
@@ -32,6 +32,13 @@ void add_temp_file (const char *name);
|
||||
*FILENAME. */
|
||||
int create_temp_file (const char *base, char **filename);
|
||||
|
||||
+/* Create a temporary file in directory DIR. Return the opened file
|
||||
+ descriptor on success, or -1 on failure. Write the file name to
|
||||
+ *FILENAME if FILENAME is not NULL. In this case, the caller is
|
||||
+ expected to free *FILENAME. */
|
||||
+int create_temp_file_in_dir (const char *base, const char *dir,
|
||||
+ char **filename);
|
||||
+
|
||||
/* Create a temporary directory and schedule it for deletion. BASE is
|
||||
used as a prefix for the unique directory name, which the function
|
||||
returns. The caller should free this string. */
|
278
SOURCES/glibc-rh2032281-3.patch
Normal file
278
SOURCES/glibc-rh2032281-3.patch
Normal file
@ -0,0 +1,278 @@
|
||||
commit fb7bff12e81c677a6622f724edd4d4987dd9d971
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Jan 18 13:29:36 2022 +0530
|
||||
|
||||
support: Add helpers to create paths longer than PATH_MAX
|
||||
|
||||
Add new helpers support_create_and_chdir_toolong_temp_directory and
|
||||
support_chdir_toolong_temp_directory to create and descend into
|
||||
directory trees longer than PATH_MAX.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
# Conflicts:
|
||||
# support/temp_file.c
|
||||
|
||||
diff --git a/support/temp_file.c b/support/temp_file.c
|
||||
index 5a2728c94a9c32ae..661c86bad5c0121f 100644
|
||||
--- a/support/temp_file.c
|
||||
+++ b/support/temp_file.c
|
||||
@@ -1,5 +1,6 @@
|
||||
/* Temporary file handling for tests.
|
||||
- Copyright (C) 1998-2018 Free Software Foundation, Inc.
|
||||
+ Copyright (C) 1998-2022 Free Software Foundation, Inc.
|
||||
+ Copyright The GNU Tools Authors.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -20,15 +21,17 @@
|
||||
some 32-bit platforms. */
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
+#include <support/check.h>
|
||||
#include <support/temp_file.h>
|
||||
#include <support/temp_file-internal.h>
|
||||
#include <support/support.h>
|
||||
|
||||
+#include <errno.h>
|
||||
#include <paths.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
-#include <unistd.h>
|
||||
+#include <xunistd.h>
|
||||
|
||||
/* List of temporary files. */
|
||||
static struct temp_name_list
|
||||
@@ -36,14 +39,20 @@ static struct temp_name_list
|
||||
struct temp_name_list *next;
|
||||
char *name;
|
||||
pid_t owner;
|
||||
+ bool toolong;
|
||||
} *temp_name_list;
|
||||
|
||||
/* Location of the temporary files. Set by the test skeleton via
|
||||
support_set_test_dir. The string is not be freed. */
|
||||
static const char *test_dir = _PATH_TMP;
|
||||
|
||||
-void
|
||||
-add_temp_file (const char *name)
|
||||
+/* Name of subdirectories in a too long temporary directory tree. */
|
||||
+static char toolong_subdir[NAME_MAX + 1];
|
||||
+static bool toolong_initialized;
|
||||
+static size_t toolong_path_max;
|
||||
+
|
||||
+static void
|
||||
+add_temp_file_internal (const char *name, bool toolong)
|
||||
{
|
||||
struct temp_name_list *newp
|
||||
= (struct temp_name_list *) xcalloc (sizeof (*newp), 1);
|
||||
@@ -53,12 +62,19 @@ add_temp_file (const char *name)
|
||||
newp->name = newname;
|
||||
newp->next = temp_name_list;
|
||||
newp->owner = getpid ();
|
||||
+ newp->toolong = toolong;
|
||||
temp_name_list = newp;
|
||||
}
|
||||
else
|
||||
free (newp);
|
||||
}
|
||||
|
||||
+void
|
||||
+add_temp_file (const char *name)
|
||||
+{
|
||||
+ add_temp_file_internal (name, false);
|
||||
+}
|
||||
+
|
||||
int
|
||||
create_temp_file_in_dir (const char *base, const char *dir, char **filename)
|
||||
{
|
||||
@@ -90,8 +106,8 @@ create_temp_file (const char *base, char **filename)
|
||||
return create_temp_file_in_dir (base, test_dir, filename);
|
||||
}
|
||||
|
||||
-char *
|
||||
-support_create_temp_directory (const char *base)
|
||||
+static char *
|
||||
+create_temp_directory_internal (const char *base, bool toolong)
|
||||
{
|
||||
char *path = xasprintf ("%s/%sXXXXXX", test_dir, base);
|
||||
if (mkdtemp (path) == NULL)
|
||||
@@ -99,16 +115,132 @@ support_create_temp_directory (const char *base)
|
||||
printf ("error: mkdtemp (\"%s\"): %m", path);
|
||||
exit (1);
|
||||
}
|
||||
- add_temp_file (path);
|
||||
+ add_temp_file_internal (path, toolong);
|
||||
return path;
|
||||
}
|
||||
|
||||
-/* Helper functions called by the test skeleton follow. */
|
||||
+char *
|
||||
+support_create_temp_directory (const char *base)
|
||||
+{
|
||||
+ return create_temp_directory_internal (base, false);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+ensure_toolong_initialized (void)
|
||||
+{
|
||||
+ if (!toolong_initialized)
|
||||
+ FAIL_EXIT1 ("uninitialized toolong directory tree\n");
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+initialize_toolong (const char *base)
|
||||
+{
|
||||
+ long name_max = pathconf (base, _PC_NAME_MAX);
|
||||
+ name_max = (name_max < 0 ? 64
|
||||
+ : (name_max < sizeof (toolong_subdir) ? name_max
|
||||
+ : sizeof (toolong_subdir) - 1));
|
||||
+
|
||||
+ long path_max = pathconf (base, _PC_PATH_MAX);
|
||||
+ path_max = (path_max < 0 ? 1024
|
||||
+ : path_max <= PTRDIFF_MAX ? path_max : PTRDIFF_MAX);
|
||||
+
|
||||
+ /* Sanity check to ensure that the test does not create temporary directories
|
||||
+ in different filesystems because this API doesn't support it. */
|
||||
+ if (toolong_initialized)
|
||||
+ {
|
||||
+ if (name_max != strlen (toolong_subdir))
|
||||
+ FAIL_UNSUPPORTED ("name_max: Temporary directories in different"
|
||||
+ " filesystems not supported yet\n");
|
||||
+ if (path_max != toolong_path_max)
|
||||
+ FAIL_UNSUPPORTED ("path_max: Temporary directories in different"
|
||||
+ " filesystems not supported yet\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ toolong_path_max = path_max;
|
||||
+
|
||||
+ size_t len = name_max;
|
||||
+ memset (toolong_subdir, 'X', len);
|
||||
+ toolong_initialized = true;
|
||||
+}
|
||||
+
|
||||
+char *
|
||||
+support_create_and_chdir_toolong_temp_directory (const char *basename)
|
||||
+{
|
||||
+ char *base = create_temp_directory_internal (basename, true);
|
||||
+ xchdir (base);
|
||||
+
|
||||
+ initialize_toolong (base);
|
||||
+
|
||||
+ size_t sz = strlen (toolong_subdir);
|
||||
+
|
||||
+ /* Create directories and descend into them so that the final path is larger
|
||||
+ than PATH_MAX. */
|
||||
+ for (size_t i = 0; i <= toolong_path_max / sz; i++)
|
||||
+ {
|
||||
+ int ret = mkdir (toolong_subdir, S_IRWXU);
|
||||
+ if (ret != 0 && errno == ENAMETOOLONG)
|
||||
+ FAIL_UNSUPPORTED ("Filesystem does not support creating too long "
|
||||
+ "directory trees\n");
|
||||
+ else if (ret != 0)
|
||||
+ FAIL_EXIT1 ("Failed to create directory tree: %m\n");
|
||||
+ xchdir (toolong_subdir);
|
||||
+ }
|
||||
+ return base;
|
||||
+}
|
||||
|
||||
void
|
||||
-support_set_test_dir (const char *path)
|
||||
+support_chdir_toolong_temp_directory (const char *base)
|
||||
{
|
||||
- test_dir = path;
|
||||
+ ensure_toolong_initialized ();
|
||||
+
|
||||
+ xchdir (base);
|
||||
+
|
||||
+ size_t sz = strlen (toolong_subdir);
|
||||
+ for (size_t i = 0; i <= toolong_path_max / sz; i++)
|
||||
+ xchdir (toolong_subdir);
|
||||
+}
|
||||
+
|
||||
+/* Helper functions called by the test skeleton follow. */
|
||||
+
|
||||
+static void
|
||||
+remove_toolong_subdirs (const char *base)
|
||||
+{
|
||||
+ ensure_toolong_initialized ();
|
||||
+
|
||||
+ if (chdir (base) != 0)
|
||||
+ {
|
||||
+ printf ("warning: toolong cleanup base failed: chdir (\"%s\"): %m\n",
|
||||
+ base);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Descend. */
|
||||
+ int levels = 0;
|
||||
+ size_t sz = strlen (toolong_subdir);
|
||||
+ for (levels = 0; levels <= toolong_path_max / sz; levels++)
|
||||
+ if (chdir (toolong_subdir) != 0)
|
||||
+ {
|
||||
+ printf ("warning: toolong cleanup failed: chdir (\"%s\"): %m\n",
|
||||
+ toolong_subdir);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Ascend and remove. */
|
||||
+ while (--levels >= 0)
|
||||
+ {
|
||||
+ if (chdir ("..") != 0)
|
||||
+ {
|
||||
+ printf ("warning: toolong cleanup failed: chdir (\"..\"): %m\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ if (remove (toolong_subdir) != 0)
|
||||
+ {
|
||||
+ printf ("warning: could not remove subdirectory: %s: %m\n",
|
||||
+ toolong_subdir);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
@@ -123,6 +255,9 @@ support_delete_temp_files (void)
|
||||
around, to prevent PID reuse.) */
|
||||
if (temp_name_list->owner == pid)
|
||||
{
|
||||
+ if (temp_name_list->toolong)
|
||||
+ remove_toolong_subdirs (temp_name_list->name);
|
||||
+
|
||||
if (remove (temp_name_list->name) != 0)
|
||||
printf ("warning: could not remove temporary file: %s: %m\n",
|
||||
temp_name_list->name);
|
||||
@@ -147,3 +282,9 @@ support_print_temp_files (FILE *f)
|
||||
fprintf (f, ")\n");
|
||||
}
|
||||
}
|
||||
+
|
||||
+void
|
||||
+support_set_test_dir (const char *path)
|
||||
+{
|
||||
+ test_dir = path;
|
||||
+}
|
||||
diff --git a/support/temp_file.h b/support/temp_file.h
|
||||
index d64563f41f1f50cd..055e31dcfb843ba6 100644
|
||||
--- a/support/temp_file.h
|
||||
+++ b/support/temp_file.h
|
||||
@@ -44,6 +44,15 @@ int create_temp_file_in_dir (const char *base, const char *dir,
|
||||
returns. The caller should free this string. */
|
||||
char *support_create_temp_directory (const char *base);
|
||||
|
||||
+/* Create a temporary directory tree that is longer than PATH_MAX and schedule
|
||||
+ it for deletion. BASENAME is used as a prefix for the unique directory
|
||||
+ name, which the function returns. The caller should free this string. */
|
||||
+char *support_create_and_chdir_toolong_temp_directory (const char *basename);
|
||||
+
|
||||
+/* Change into the innermost directory of the directory tree BASE, which was
|
||||
+ created using support_create_and_chdir_toolong_temp_directory. */
|
||||
+void support_chdir_toolong_temp_directory (const char *base);
|
||||
+
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SUPPORT_TEMP_FILE_H */
|
331
SOURCES/glibc-rh2032281-4.patch
Normal file
331
SOURCES/glibc-rh2032281-4.patch
Normal file
@ -0,0 +1,331 @@
|
||||
commit 23e0e8f5f1fb5ed150253d986ecccdc90c2dcd5e
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Fri Jan 21 23:32:56 2022 +0530
|
||||
|
||||
getcwd: Set errno to ERANGE for size == 1 (CVE-2021-3999)
|
||||
|
||||
No valid path returned by getcwd would fit into 1 byte, so reject the
|
||||
size early and return NULL with errno set to ERANGE. This change is
|
||||
prompted by CVE-2021-3999, which describes a single byte buffer
|
||||
underflow and overflow when all of the following conditions are met:
|
||||
|
||||
- The buffer size (i.e. the second argument of getcwd) is 1 byte
|
||||
- The current working directory is too long
|
||||
- '/' is also mounted on the current working directory
|
||||
|
||||
Sequence of events:
|
||||
|
||||
- In sysdeps/unix/sysv/linux/getcwd.c, the syscall returns ENAMETOOLONG
|
||||
because the linux kernel checks for name length before it checks
|
||||
buffer size
|
||||
|
||||
- The code falls back to the generic getcwd in sysdeps/posix
|
||||
|
||||
- In the generic func, the buf[0] is set to '\0' on line 250
|
||||
|
||||
- this while loop on line 262 is bypassed:
|
||||
|
||||
while (!(thisdev == rootdev && thisino == rootino))
|
||||
|
||||
since the rootfs (/) is bind mounted onto the directory and the flow
|
||||
goes on to line 449, where it puts a '/' in the byte before the
|
||||
buffer.
|
||||
|
||||
- Finally on line 458, it moves 2 bytes (the underflowed byte and the
|
||||
'\0') to the buf[0] and buf[1], resulting in a 1 byte buffer overflow.
|
||||
|
||||
- buf is returned on line 469 and errno is not set.
|
||||
|
||||
This resolves BZ #28769.
|
||||
|
||||
Reviewed-by: Andreas Schwab <schwab@linux-m68k.org>
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Signed-off-by: Qualys Security Advisory <qsa@qualys.com>
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
# Conflicts:
|
||||
# sysdeps/posix/getcwd.c
|
||||
# sysdeps/unix/sysv/linux/Makefile
|
||||
|
||||
diff --git a/sysdeps/posix/getcwd.c b/sysdeps/posix/getcwd.c
|
||||
index b53433a2dc77fafa..fcd7aaea79c6477b 100644
|
||||
--- a/sysdeps/posix/getcwd.c
|
||||
+++ b/sysdeps/posix/getcwd.c
|
||||
@@ -238,6 +238,13 @@ __getcwd (char *buf, size_t size)
|
||||
bool fd_needs_closing = false;
|
||||
int fd = AT_FDCWD;
|
||||
|
||||
+ /* A size of 1 byte is never useful. */
|
||||
+ if (size == 1)
|
||||
+ {
|
||||
+ __set_errno (ERANGE);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
char *path;
|
||||
#ifndef NO_ALLOCATION
|
||||
size_t allocated = size;
|
||||
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
|
||||
index 688cf9fa9dea23a6..bb055f9d6b841ff5 100644
|
||||
--- a/sysdeps/unix/sysv/linux/Makefile
|
||||
+++ b/sysdeps/unix/sysv/linux/Makefile
|
||||
@@ -180,7 +180,11 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \
|
||||
|
||||
sysdep_headers += bits/fcntl-linux.h
|
||||
|
||||
-tests += tst-fallocate tst-fallocate64
|
||||
+tests += \
|
||||
+ tst-fallocate \
|
||||
+ tst-fallocate64 \
|
||||
+ tst-getcwd-smallbuff \
|
||||
+# tests
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),elf)
|
||||
diff --git a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..d460d6e7662dc5e4
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c
|
||||
@@ -0,0 +1,241 @@
|
||||
+/* Verify that getcwd returns ERANGE for size 1 byte and does not underflow
|
||||
+ buffer when the CWD is too long and is also a mount target of /. See bug
|
||||
+ #28769 or CVE-2021-3999 for more context.
|
||||
+ Copyright The GNU Toolchain Authors.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <intprops.h>
|
||||
+#include <limits.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <sys/mount.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/wait.h>
|
||||
+
|
||||
+#include <sys/socket.h>
|
||||
+#include <sys/un.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/xsched.h>
|
||||
+#include <support/xunistd.h>
|
||||
+
|
||||
+static char *base;
|
||||
+#define BASENAME "tst-getcwd-smallbuff"
|
||||
+#define MOUNT_NAME "mpoint"
|
||||
+static int sockfd[2];
|
||||
+
|
||||
+static void
|
||||
+do_cleanup (void)
|
||||
+{
|
||||
+ support_chdir_toolong_temp_directory (base);
|
||||
+ TEST_VERIFY_EXIT (rmdir (MOUNT_NAME) == 0);
|
||||
+ free (base);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+send_fd (const int sock, const int fd)
|
||||
+{
|
||||
+ struct msghdr msg = {0};
|
||||
+ union
|
||||
+ {
|
||||
+ struct cmsghdr hdr;
|
||||
+ char buf[CMSG_SPACE (sizeof (int))];
|
||||
+ } cmsgbuf = {0};
|
||||
+ struct cmsghdr *cmsg;
|
||||
+ struct iovec vec;
|
||||
+ char ch = 'A';
|
||||
+ ssize_t n;
|
||||
+
|
||||
+ msg.msg_control = &cmsgbuf.buf;
|
||||
+ msg.msg_controllen = sizeof (cmsgbuf.buf);
|
||||
+
|
||||
+ cmsg = CMSG_FIRSTHDR (&msg);
|
||||
+ cmsg->cmsg_len = CMSG_LEN (sizeof (int));
|
||||
+ cmsg->cmsg_level = SOL_SOCKET;
|
||||
+ cmsg->cmsg_type = SCM_RIGHTS;
|
||||
+ memcpy (CMSG_DATA (cmsg), &fd, sizeof (fd));
|
||||
+
|
||||
+ vec.iov_base = &ch;
|
||||
+ vec.iov_len = 1;
|
||||
+ msg.msg_iov = &vec;
|
||||
+ msg.msg_iovlen = 1;
|
||||
+
|
||||
+ while ((n = sendmsg (sock, &msg, 0)) == -1 && errno == EINTR);
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (n == 1);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+recv_fd (const int sock)
|
||||
+{
|
||||
+ struct msghdr msg = {0};
|
||||
+ union
|
||||
+ {
|
||||
+ struct cmsghdr hdr;
|
||||
+ char buf[CMSG_SPACE(sizeof(int))];
|
||||
+ } cmsgbuf = {0};
|
||||
+ struct cmsghdr *cmsg;
|
||||
+ struct iovec vec;
|
||||
+ ssize_t n;
|
||||
+ char ch = '\0';
|
||||
+ int fd = -1;
|
||||
+
|
||||
+ vec.iov_base = &ch;
|
||||
+ vec.iov_len = 1;
|
||||
+ msg.msg_iov = &vec;
|
||||
+ msg.msg_iovlen = 1;
|
||||
+
|
||||
+ msg.msg_control = &cmsgbuf.buf;
|
||||
+ msg.msg_controllen = sizeof (cmsgbuf.buf);
|
||||
+
|
||||
+ while ((n = recvmsg (sock, &msg, 0)) == -1 && errno == EINTR);
|
||||
+ if (n != 1 || ch != 'A')
|
||||
+ return -1;
|
||||
+
|
||||
+ cmsg = CMSG_FIRSTHDR (&msg);
|
||||
+ if (cmsg == NULL)
|
||||
+ return -1;
|
||||
+ if (cmsg->cmsg_type != SCM_RIGHTS)
|
||||
+ return -1;
|
||||
+ memcpy (&fd, CMSG_DATA (cmsg), sizeof (fd));
|
||||
+ if (fd < 0)
|
||||
+ return -1;
|
||||
+ return fd;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+child_func (void * const arg)
|
||||
+{
|
||||
+ xclose (sockfd[0]);
|
||||
+ const int sock = sockfd[1];
|
||||
+ char ch;
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (read (sock, &ch, 1) == 1);
|
||||
+ TEST_VERIFY_EXIT (ch == '1');
|
||||
+
|
||||
+ if (mount ("/", MOUNT_NAME, NULL, MS_BIND | MS_REC, NULL))
|
||||
+ FAIL_EXIT1 ("mount failed: %m\n");
|
||||
+ const int fd = xopen ("mpoint",
|
||||
+ O_RDONLY | O_PATH | O_DIRECTORY | O_NOFOLLOW, 0);
|
||||
+
|
||||
+ send_fd (sock, fd);
|
||||
+ xclose (fd);
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (read (sock, &ch, 1) == 1);
|
||||
+ TEST_VERIFY_EXIT (ch == 'a');
|
||||
+
|
||||
+ xclose (sock);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+update_map (char * const mapping, const char * const map_file)
|
||||
+{
|
||||
+ const size_t map_len = strlen (mapping);
|
||||
+
|
||||
+ const int fd = xopen (map_file, O_WRONLY, 0);
|
||||
+ xwrite (fd, mapping, map_len);
|
||||
+ xclose (fd);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+proc_setgroups_write (const long child_pid, const char * const str)
|
||||
+{
|
||||
+ const size_t str_len = strlen(str);
|
||||
+
|
||||
+ char setgroups_path[sizeof ("/proc//setgroups") + INT_STRLEN_BOUND (long)];
|
||||
+
|
||||
+ snprintf (setgroups_path, sizeof (setgroups_path),
|
||||
+ "/proc/%ld/setgroups", child_pid);
|
||||
+
|
||||
+ const int fd = open (setgroups_path, O_WRONLY);
|
||||
+
|
||||
+ if (fd < 0)
|
||||
+ {
|
||||
+ TEST_VERIFY_EXIT (errno == ENOENT);
|
||||
+ FAIL_UNSUPPORTED ("/proc/%ld/setgroups not found\n", child_pid);
|
||||
+ }
|
||||
+
|
||||
+ xwrite (fd, str, str_len);
|
||||
+ xclose(fd);
|
||||
+}
|
||||
+
|
||||
+static char child_stack[1024 * 1024];
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ base = support_create_and_chdir_toolong_temp_directory (BASENAME);
|
||||
+
|
||||
+ xmkdir (MOUNT_NAME, S_IRWXU);
|
||||
+ atexit (do_cleanup);
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfd) == 0);
|
||||
+ pid_t child_pid = xclone (child_func, NULL, child_stack,
|
||||
+ sizeof (child_stack),
|
||||
+ CLONE_NEWUSER | CLONE_NEWNS | SIGCHLD);
|
||||
+
|
||||
+ xclose (sockfd[1]);
|
||||
+ const int sock = sockfd[0];
|
||||
+
|
||||
+ char map_path[sizeof ("/proc//uid_map") + INT_STRLEN_BOUND (long)];
|
||||
+ char map_buf[sizeof ("0 1") + INT_STRLEN_BOUND (long)];
|
||||
+
|
||||
+ snprintf (map_path, sizeof (map_path), "/proc/%ld/uid_map",
|
||||
+ (long) child_pid);
|
||||
+ snprintf (map_buf, sizeof (map_buf), "0 %ld 1", (long) getuid());
|
||||
+ update_map (map_buf, map_path);
|
||||
+
|
||||
+ proc_setgroups_write ((long) child_pid, "deny");
|
||||
+ snprintf (map_path, sizeof (map_path), "/proc/%ld/gid_map",
|
||||
+ (long) child_pid);
|
||||
+ snprintf (map_buf, sizeof (map_buf), "0 %ld 1", (long) getgid());
|
||||
+ update_map (map_buf, map_path);
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (send (sock, "1", 1, MSG_NOSIGNAL) == 1);
|
||||
+ const int fd = recv_fd (sock);
|
||||
+ TEST_VERIFY_EXIT (fd >= 0);
|
||||
+ TEST_VERIFY_EXIT (fchdir (fd) == 0);
|
||||
+
|
||||
+ static char buf[2 * 10 + 1];
|
||||
+ memset (buf, 'A', sizeof (buf));
|
||||
+
|
||||
+ /* Finally, call getcwd and check if it resulted in a buffer underflow. */
|
||||
+ char * cwd = getcwd (buf + sizeof (buf) / 2, 1);
|
||||
+ TEST_VERIFY (cwd == NULL);
|
||||
+ TEST_VERIFY (errno == ERANGE);
|
||||
+
|
||||
+ for (int i = 0; i < sizeof (buf); i++)
|
||||
+ if (buf[i] != 'A')
|
||||
+ {
|
||||
+ printf ("buf[%d] = %02x\n", i, (unsigned int) buf[i]);
|
||||
+ support_record_failure ();
|
||||
+ }
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (send (sock, "a", 1, MSG_NOSIGNAL) == 1);
|
||||
+ xclose (sock);
|
||||
+ TEST_VERIFY_EXIT (xwaitpid (child_pid, NULL, 0) == child_pid);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define CLEANUP_HANDLER do_cleanup
|
||||
+#include <support/test-driver.c>
|
121
SOURCES/glibc-rh2032281-5.patch
Normal file
121
SOURCES/glibc-rh2032281-5.patch
Normal file
@ -0,0 +1,121 @@
|
||||
commit de8995a2a04163617c1a233b4b81356ef9f9741f
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Mar 10 12:26:30 2021 -0300
|
||||
|
||||
support: Add xclone
|
||||
|
||||
It is a wrapper for Linux clone syscall, to simplify the call to the
|
||||
use only the most common arguments and remove architecture specific
|
||||
handling (such as ia64 different name and signature).
|
||||
|
||||
# Conflicts:
|
||||
# support/Makefile
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index fb95a69ed9158e78..d2b95539403e416c 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -84,6 +84,7 @@ libsupport-routines = \
|
||||
xcalloc \
|
||||
xchdir \
|
||||
xchroot \
|
||||
+ xclone \
|
||||
xclose \
|
||||
xconnect \
|
||||
xcopy_file_range \
|
||||
diff --git a/support/xclone.c b/support/xclone.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..924d2b875402a819
|
||||
--- /dev/null
|
||||
+++ b/support/xclone.c
|
||||
@@ -0,0 +1,50 @@
|
||||
+/* Auxiliary functions to issue the clone syscall.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifdef __linux__
|
||||
+# include <support/check.h>
|
||||
+# include <stackinfo.h> /* For _STACK_GROWS_{UP,DOWN}. */
|
||||
+# include <xsched.h>
|
||||
+
|
||||
+pid_t
|
||||
+xclone (int (*fn) (void *arg), void *arg, void *stack, size_t stack_size,
|
||||
+ int flags)
|
||||
+{
|
||||
+ pid_t r = -1;
|
||||
+
|
||||
+# ifdef __ia64__
|
||||
+ extern int __clone2 (int (*fn) (void *arg), void *stack, size_t stack_size,
|
||||
+ int flags, void *arg, ...);
|
||||
+ r = __clone2 (f, stack, stack_size, flags, arg, /* ptid */ NULL,
|
||||
+ /* tls */ NULL, /* ctid */ ctid);
|
||||
+# else
|
||||
+# if _STACK_GROWS_DOWN
|
||||
+ r = clone (fn, stack + stack_size, flags, arg, /* ptid */ NULL,
|
||||
+ /* tls */ NULL, /* ctid */ NULL);
|
||||
+# elif _STACK_GROWS_UP
|
||||
+ r = clone (fn, stack, flags, arg, /* ptid */ NULL, /* tls */ NULL,
|
||||
+ &ctid);
|
||||
+# endif
|
||||
+# endif
|
||||
+
|
||||
+ if (r < 0)
|
||||
+ FAIL_EXIT1 ("clone: %m");
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
+#endif
|
||||
diff --git a/support/xsched.h b/support/xsched.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..eefd731940187b39
|
||||
--- /dev/null
|
||||
+++ b/support/xsched.h
|
||||
@@ -0,0 +1,34 @@
|
||||
+/* Wrapper for sched.h functions.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef SUPPORT_XSCHED_H
|
||||
+#define SUPPORT_XSCHED_H
|
||||
+
|
||||
+__BEGIN_DECLS
|
||||
+
|
||||
+#include <sched.h>
|
||||
+#include <sys/types.h>
|
||||
+
|
||||
+#ifdef __linux__
|
||||
+pid_t xclone (int (*fn) (void *arg), void *arg, void *stack,
|
||||
+ size_t stack_size, int flags);
|
||||
+#endif
|
||||
+
|
||||
+__END_DECLS
|
||||
+
|
||||
+#endif
|
46
SOURCES/glibc-rh2032281-6.patch
Normal file
46
SOURCES/glibc-rh2032281-6.patch
Normal file
@ -0,0 +1,46 @@
|
||||
commit 5b8e7980c5dabd9aaefeba4f0208baa8cf7653ee
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jan 24 18:14:24 2022 +0100
|
||||
|
||||
Linux: Detect user namespace support in io/tst-getcwd-smallbuff
|
||||
|
||||
Otherwise the test fails with certain container runtimes.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c
|
||||
index d460d6e7662dc5e4..55362f6060a2b3be 100644
|
||||
--- a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c
|
||||
+++ b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <sys/un.h>
|
||||
#include <support/check.h>
|
||||
#include <support/temp_file.h>
|
||||
+#include <support/test-driver.h>
|
||||
#include <support/xsched.h>
|
||||
#include <support/xunistd.h>
|
||||
|
||||
@@ -188,6 +189,23 @@ do_test (void)
|
||||
xmkdir (MOUNT_NAME, S_IRWXU);
|
||||
atexit (do_cleanup);
|
||||
|
||||
+ /* Check whether user namespaces are supported. */
|
||||
+ {
|
||||
+ pid_t pid = xfork ();
|
||||
+ if (pid == 0)
|
||||
+ {
|
||||
+ if (unshare (CLONE_NEWUSER | CLONE_NEWNS) != 0)
|
||||
+ _exit (EXIT_UNSUPPORTED);
|
||||
+ else
|
||||
+ _exit (0);
|
||||
+ }
|
||||
+ int status;
|
||||
+ xwaitpid (pid, &status, 0);
|
||||
+ TEST_VERIFY_EXIT (WIFEXITED (status));
|
||||
+ if (WEXITSTATUS (status) != 0)
|
||||
+ return WEXITSTATUS (status);
|
||||
+ }
|
||||
+
|
||||
TEST_VERIFY_EXIT (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfd) == 0);
|
||||
pid_t child_pid = xclone (child_func, NULL, child_stack,
|
||||
sizeof (child_stack),
|
24
SOURCES/glibc-rh2032281-7.patch
Normal file
24
SOURCES/glibc-rh2032281-7.patch
Normal file
@ -0,0 +1,24 @@
|
||||
commit 3842ba494963b1d76ad5f68b8d1e5c2279160e31
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Tue Jun 1 09:23:40 2021 +0100
|
||||
|
||||
aarch64: align stack in clone [BZ #27939]
|
||||
|
||||
The AArch64 PCS requires 16 byte aligned stack. Previously if the
|
||||
caller passed an unaligned stack to clone then the child crashed.
|
||||
|
||||
Fixes bug 27939.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/clone.S b/sysdeps/unix/sysv/linux/aarch64/clone.S
|
||||
index e0653048259dd9a3..4a1a999447ee5cf1 100644
|
||||
--- a/sysdeps/unix/sysv/linux/aarch64/clone.S
|
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/clone.S
|
||||
@@ -48,6 +48,8 @@ ENTRY(__clone)
|
||||
/* Sanity check args. */
|
||||
mov x0, #-EINVAL
|
||||
cbz x10, .Lsyscall_error
|
||||
+ /* Align sp. */
|
||||
+ and x1, x1, -16
|
||||
cbz x1, .Lsyscall_error
|
||||
|
||||
/* Do the system call. */
|
51
SOURCES/glibc-rh2033648-1.patch
Normal file
51
SOURCES/glibc-rh2033648-1.patch
Normal file
@ -0,0 +1,51 @@
|
||||
commit c36f64aa6dff13b12a1e03a185e75a50fa9f6a4c
|
||||
Author: Hans-Peter Nilsson <hp@axis.com>
|
||||
Date: Fri Dec 17 21:38:00 2021 +0100
|
||||
|
||||
timezone: handle truncated timezones from tzcode-2021d and later (BZ #28707)
|
||||
|
||||
When using a timezone file with a truncated starting time,
|
||||
generated by the zic in IANA tzcode-2021d a.k.a. tzlib-2021d
|
||||
(also in tzlib-2021e; current as of this writing), glibc
|
||||
asserts in __tzfile_read (on e.g. tzset() for this file) and
|
||||
you may find lines matching "tzfile.c:435: __tzfile_read:
|
||||
Assertion `num_types == 1' failed" in your syslog.
|
||||
|
||||
One example of such a file is the tzfile for Asuncion
|
||||
generated by tzlib-2021e as follows, using the tzlib-2021e zic:
|
||||
"zic -d DEST -r @1546300800 -L /dev/null -b slim
|
||||
SOURCE/southamerica". Note that in its type 2 header, it has
|
||||
two entries in its "time-types" array (types), but only one
|
||||
entry in its "transition types" array (type_idxs).
|
||||
|
||||
This is valid and expected already in the published RFC8536, and
|
||||
not even frowned upon: "Local time for timestamps before the
|
||||
first transition is specified by the first time type (time type
|
||||
0)" ... "every nonzero local time type index SHOULD appear at
|
||||
least once in the transition type array". Note the "nonzero ...
|
||||
index". Until the 2021d zic, index 0 has been shared by the
|
||||
first valid transition but with 2021d it's separate, set apart
|
||||
as a placeholder and only "implicitly" indexed. (A draft update
|
||||
of the RFC mandates that the entry at index 0 is a placeholder
|
||||
in this case, hence can no longer be shared.)
|
||||
|
||||
* time/tzfile.c (__tzfile_read): Don't assert when no transitions
|
||||
are found.
|
||||
|
||||
Co-authored-by: Christopher Wong <Christopher.Wong@axis.com>
|
||||
|
||||
diff --git a/time/tzfile.c b/time/tzfile.c
|
||||
index 190a777152..8668392ad3 100644
|
||||
--- a/time/tzfile.c
|
||||
+++ b/time/tzfile.c
|
||||
@@ -431,8 +431,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
if (__tzname[0] == NULL)
|
||||
{
|
||||
/* This should only happen if there are no transition rules.
|
||||
- In this case there should be only one single type. */
|
||||
- assert (num_types == 1);
|
||||
+ In this case there's usually only one single type, unless
|
||||
+ e.g. the data file has a truncated time-range. */
|
||||
__tzname[0] = __tzstring (zone_names);
|
||||
}
|
||||
if (__tzname[1] == NULL)
|
126
SOURCES/glibc-rh2033648-2.patch
Normal file
126
SOURCES/glibc-rh2033648-2.patch
Normal file
@ -0,0 +1,126 @@
|
||||
commit ebe899af0dc3215159a9c896ac6f35b72a18cb6e
|
||||
Author: Hans-Peter Nilsson <hp@axis.com>
|
||||
Date: Fri Dec 17 21:45:54 2021 +0100
|
||||
|
||||
timezone: test-case for BZ #28707
|
||||
|
||||
This test-case is the tzfile for Asuncion generated by
|
||||
tzlib-2021e as follows, using the tzlib-2021e zic: "zic -d
|
||||
DEST -r @1546300800 -L /dev/null -b slim
|
||||
SOURCE/southamerica". Note that in its type 2 header, it
|
||||
has two entries in its "time-types" array (types), but only
|
||||
one entry in its "transition types" array (type_idxs).
|
||||
|
||||
* timezone/Makefile, timezone/tst-pr28707.c,
|
||||
timezone/testdata/gen-XT5.sh: New test.
|
||||
|
||||
Co-authored-by: Christopher Wong <Christopher.Wong@axis.com>
|
||||
|
||||
Reworked due to timezone/Makefile difference.
|
||||
|
||||
diff -Nrup a/timezone/Makefile b/timezone/Makefile
|
||||
--- a/timezone/Makefile 2021-07-06 15:04:00.000000000 -0400
|
||||
+++ b/timezone/Makefile 2022-01-05 15:03:57.433756574 -0500
|
||||
@@ -23,7 +23,7 @@ subdir := timezone
|
||||
include ../Makeconfig
|
||||
|
||||
others := zdump zic
|
||||
-tests := test-tz tst-timezone tst-tzset
|
||||
+tests := test-tz tst-timezone tst-tzset tst-bz28707
|
||||
|
||||
generated-dirs += testdata
|
||||
|
||||
@@ -85,10 +85,12 @@ $(objpfx)tst-timezone.out: $(addprefix $
|
||||
America/Sao_Paulo Asia/Tokyo \
|
||||
Europe/London)
|
||||
$(objpfx)tst-tzset.out: $(addprefix $(testdata)/XT, 1 2 3 4)
|
||||
+$(objpfx)tst-bz28707.out: $(testdata)/XT5
|
||||
|
||||
test-tz-ENV = TZDIR=$(testdata)
|
||||
tst-timezone-ENV = TZDIR=$(testdata)
|
||||
tst-tzset-ENV = TZDIR=$(testdata)
|
||||
+tst-bz28707-ENV = TZDIR=$(testdata)
|
||||
|
||||
# Note this must come second in the deps list for $(built-program-cmd) to work.
|
||||
zic-deps = $(objpfx)zic $(leapseconds) yearistype
|
||||
@@ -122,6 +124,10 @@ $(testdata)/XT%: testdata/XT%
|
||||
$(make-target-directory)
|
||||
cp $< $@
|
||||
|
||||
+$(testdata)/XT%: testdata/gen-XT%.sh
|
||||
+ $(SHELL) $< > $@.tmp
|
||||
+ mv $@.tmp $@
|
||||
+
|
||||
$(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make
|
||||
sed -e 's|/bin/bash|$(BASH)|' \
|
||||
-e 's|TZDIR=[^}]*|TZDIR=$(zonedir)|' \
|
||||
diff -Nrup a/timezone/testdata/gen-XT5.sh b/timezone/testdata/gen-XT5.sh
|
||||
--- a/timezone/testdata/gen-XT5.sh 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ b/timezone/testdata/gen-XT5.sh 2022-01-05 12:50:01.666972313 -0500
|
||||
@@ -0,0 +1,16 @@
|
||||
+#! /bin/sh
|
||||
+
|
||||
+# This test-case is the tzfile for America/Asuncion
|
||||
+# generated by tzlib-2021e as follows, using the tzlib-2021e
|
||||
+# zic: "zic -d DEST -r @1546300800 -L /dev/null -b slim
|
||||
+# SOURCE/southamerica". Note that in its type 2 header, it
|
||||
+# has two entries in its "time-types" array (types), but
|
||||
+# only one entry in its "transition types" array
|
||||
+# (type_idxs).
|
||||
+
|
||||
+printf \
|
||||
+'TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'\
|
||||
+'\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0TZif2\0\0\0\0\0\0\0\0'\
|
||||
+'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\2\0\0\0\b\0'\
|
||||
+'\0\0\0\*\255\200\1\0\0\0\0\0\0\377\377\325\320\1\4-00\0-03\0\n'\
|
||||
+'<-04>4<-03>,M10.1.0/0,M3.4.0/0\n'
|
||||
diff -Nrup a/timezone/tst-bz28707.c b/timezone/tst-bz28707.c
|
||||
--- a/timezone/tst-bz28707.c 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ b/timezone/tst-bz28707.c 2022-01-05 12:50:01.666972313 -0500
|
||||
@@ -0,0 +1,46 @@
|
||||
+/* Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <time.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+/* Test that we can use a truncated timezone-file, where the time-type
|
||||
+ at index 0 is not indexed by the transition-types array (and the
|
||||
+ transition-types array does not contain at least both one DST and one
|
||||
+ normal time members). */
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ if (setenv ("TZ", "XT5", 1))
|
||||
+ {
|
||||
+ puts ("setenv failed.");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ tzset ();
|
||||
+
|
||||
+ return
|
||||
+ /* Sanity-check that we got the right timezone-name for DST. For
|
||||
+ normal time, we're likely to get "-00" (the "unspecified" marker),
|
||||
+ even though the POSIX timezone string says "-04". Let's not test
|
||||
+ that. */
|
||||
+ !(strcmp (tzname[1], "-03") == 0);
|
||||
+}
|
||||
+#include <support/test-driver.c>
|
185
SOURCES/glibc-rh2033655.patch
Normal file
185
SOURCES/glibc-rh2033655.patch
Normal file
@ -0,0 +1,185 @@
|
||||
commit ff012870b2c02a62598c04daa1e54632e020fd7d
|
||||
Author: Nikita Popov <npv1310@gmail.com>
|
||||
Date: Tue Nov 2 13:21:42 2021 +0500
|
||||
|
||||
gconv: Do not emit spurious NUL character in ISO-2022-JP-3 (bug 28524)
|
||||
|
||||
Bugfix 27256 has introduced another issue:
|
||||
In conversion from ISO-2022-JP-3 encoding, it is possible
|
||||
to force iconv to emit extra NUL character on internal state reset.
|
||||
To do this, it is sufficient to feed iconv with escape sequence
|
||||
which switches active character set.
|
||||
The simplified check 'data->__statep->__count != ASCII_set'
|
||||
introduced by the aforementioned bugfix picks that case and
|
||||
behaves as if '\0' character has been queued thus emitting it.
|
||||
|
||||
To eliminate this issue, these steps are taken:
|
||||
* Restore original condition
|
||||
'(data->__statep->__count & ~7) != ASCII_set'.
|
||||
It is necessary since bits 0-2 may contain
|
||||
number of buffered input characters.
|
||||
* Check that queued character is not NUL.
|
||||
Similar step is taken for main conversion loop.
|
||||
|
||||
Bundled test case follows following logic:
|
||||
* Try to convert ISO-2022-JP-3 escape sequence
|
||||
switching active character set
|
||||
* Reset internal state by providing NULL as input buffer
|
||||
* Ensure that nothing has been converted.
|
||||
|
||||
Signed-off-by: Nikita Popov <npv1310@gmail.com>
|
||||
|
||||
Conflicts:
|
||||
iconvdata/Makefile
|
||||
(Copyright header. Usual test backporting differences.)
|
||||
iconvdata/iso-2022-jp-3.c
|
||||
(Copyright header.)
|
||||
|
||||
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
|
||||
index 95e5fb8f722a513b..646e2ccd11478646 100644
|
||||
--- a/iconvdata/Makefile
|
||||
+++ b/iconvdata/Makefile
|
||||
@@ -1,4 +1,5 @@
|
||||
-# Copyright (C) 1997-2018 Free Software Foundation, Inc.
|
||||
+# Copyright (C) 1997-2021 Free Software Foundation, Inc.
|
||||
+# Copyright (C) The GNU Toolchain Authors.
|
||||
# This file is part of the GNU C Library.
|
||||
|
||||
# The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -73,7 +74,8 @@ modules.so := $(addsuffix .so, $(modules))
|
||||
ifeq (yes,$(build-shared))
|
||||
tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
|
||||
tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
|
||||
- bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 bug-iconv14
|
||||
+ bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 bug-iconv14 \
|
||||
+ bug-iconv15
|
||||
ifeq ($(have-thread-library),yes)
|
||||
tests += bug-iconv3
|
||||
endif
|
||||
@@ -321,6 +323,8 @@ $(objpfx)bug-iconv12.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
$(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
+$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
+ $(addprefix $(objpfx),$(modules.so))
|
||||
|
||||
$(objpfx)iconv-test.out: run-iconv-test.sh \
|
||||
$(addprefix $(objpfx), $(gconv-modules)) \
|
||||
diff --git a/iconvdata/bug-iconv15.c b/iconvdata/bug-iconv15.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..cc04bd0313a68786
|
||||
--- /dev/null
|
||||
+++ b/iconvdata/bug-iconv15.c
|
||||
@@ -0,0 +1,60 @@
|
||||
+/* Bug 28524: Conversion from ISO-2022-JP-3 with iconv
|
||||
+ may emit spurious NUL character on state reset.
|
||||
+ Copyright (C) The GNU Toolchain Authors.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stddef.h>
|
||||
+#include <iconv.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ char in[] = "\x1b(I";
|
||||
+ char *inbuf = in;
|
||||
+ size_t inleft = sizeof (in) - 1;
|
||||
+ char out[1];
|
||||
+ char *outbuf = out;
|
||||
+ size_t outleft = sizeof (out);
|
||||
+ iconv_t cd;
|
||||
+
|
||||
+ cd = iconv_open ("UTF8", "ISO-2022-JP-3");
|
||||
+ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
|
||||
+
|
||||
+ /* First call to iconv should alter internal state.
|
||||
+ Now, JISX0201_Kana_set is selected and
|
||||
+ state value != ASCII_set. */
|
||||
+ TEST_VERIFY (iconv (cd, &inbuf, &inleft, &outbuf, &outleft) != (size_t) -1);
|
||||
+
|
||||
+ /* No bytes should have been added to
|
||||
+ the output buffer at this point. */
|
||||
+ TEST_VERIFY (outbuf == out);
|
||||
+ TEST_VERIFY (outleft == sizeof (out));
|
||||
+
|
||||
+ /* Second call shall emit spurious NUL character in unpatched glibc. */
|
||||
+ TEST_VERIFY (iconv (cd, NULL, NULL, &outbuf, &outleft) != (size_t) -1);
|
||||
+
|
||||
+ /* No characters are expected to be produced. */
|
||||
+ TEST_VERIFY (outbuf == out);
|
||||
+ TEST_VERIFY (outleft == sizeof (out));
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (iconv_close (cd) != -1);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c
|
||||
index 047fab8e8dfbde7e..a2b33b171e56392a 100644
|
||||
--- a/iconvdata/iso-2022-jp-3.c
|
||||
+++ b/iconvdata/iso-2022-jp-3.c
|
||||
@@ -1,5 +1,6 @@
|
||||
/* Conversion module for ISO-2022-JP-3.
|
||||
- Copyright (C) 1998-2018 Free Software Foundation, Inc.
|
||||
+ Copyright (C) 1998-2021 Free Software Foundation, Inc.
|
||||
+ Copyright (C) The GNU Toolchain Authors.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998,
|
||||
and Bruno Haible <bruno@clisp.org>, 2002.
|
||||
@@ -81,20 +82,31 @@ enum
|
||||
the output state to the initial state. This has to be done during the
|
||||
flushing. */
|
||||
#define EMIT_SHIFT_TO_INIT \
|
||||
- if (data->__statep->__count != ASCII_set) \
|
||||
+ if ((data->__statep->__count & ~7) != ASCII_set) \
|
||||
{ \
|
||||
if (FROM_DIRECTION) \
|
||||
{ \
|
||||
- if (__glibc_likely (outbuf + 4 <= outend)) \
|
||||
+ uint32_t ch = data->__statep->__count >> 6; \
|
||||
+ \
|
||||
+ if (__glibc_unlikely (ch != 0)) \
|
||||
{ \
|
||||
- /* Write out the last character. */ \
|
||||
- *((uint32_t *) outbuf) = data->__statep->__count >> 6; \
|
||||
- outbuf += sizeof (uint32_t); \
|
||||
- data->__statep->__count = ASCII_set; \
|
||||
+ if (__glibc_likely (outbuf + 4 <= outend)) \
|
||||
+ { \
|
||||
+ /* Write out the last character. */ \
|
||||
+ put32u (outbuf, ch); \
|
||||
+ outbuf += 4; \
|
||||
+ data->__statep->__count &= 7; \
|
||||
+ data->__statep->__count |= ASCII_set; \
|
||||
+ } \
|
||||
+ else \
|
||||
+ /* We don't have enough room in the output buffer. */ \
|
||||
+ status = __GCONV_FULL_OUTPUT; \
|
||||
} \
|
||||
else \
|
||||
- /* We don't have enough room in the output buffer. */ \
|
||||
- status = __GCONV_FULL_OUTPUT; \
|
||||
+ { \
|
||||
+ data->__statep->__count &= 7; \
|
||||
+ data->__statep->__count |= ASCII_set; \
|
||||
+ } \
|
||||
} \
|
||||
else \
|
||||
{ \
|
54
SOURCES/glibc-rh2036955.patch
Normal file
54
SOURCES/glibc-rh2036955.patch
Normal file
@ -0,0 +1,54 @@
|
||||
commit e5fa62b8db546f8792ec9e5c61e6419f4f8e3f4d
|
||||
Author: Wilco Dijkstra <wdijkstr@arm.com>
|
||||
Date: Thu Jan 6 14:36:28 2022 +0000
|
||||
|
||||
AArch64: Check for SVE in ifuncs [BZ #28744]
|
||||
|
||||
Add a check for SVE in the A64FX ifuncs for memcpy, memset and memmove.
|
||||
This fixes BZ #28744.
|
||||
|
||||
Conflicts:
|
||||
sysdeps/aarch64/multiarch/memcpy.c
|
||||
sysdeps/aarch64/multiarch/memmove.c
|
||||
sysdeps/aarch64/multiarch/memset.c
|
||||
(IFUNC resolver differences in the backport.)
|
||||
|
||||
diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c
|
||||
index e0313c42e82a7b86..a6ebeb06d3bda00f 100644
|
||||
--- a/sysdeps/aarch64/multiarch/memcpy.c
|
||||
+++ b/sysdeps/aarch64/multiarch/memcpy.c
|
||||
@@ -44,7 +44,7 @@ libc_ifunc (__libc_memcpy,
|
||||
: (IS_THUNDERX2 (midr) || IS_THUNDERX2PA (midr)
|
||||
? __memcpy_thunderx2
|
||||
# if HAVE_AARCH64_SVE_ASM
|
||||
- : (IS_A64FX (midr)
|
||||
+ : (IS_A64FX (midr) && sve
|
||||
? __memcpy_a64fx
|
||||
: __memcpy_generic)))));
|
||||
# else
|
||||
diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c
|
||||
index d96612b9cf7c3a4e..bea72b3eddde54c0 100644
|
||||
--- a/sysdeps/aarch64/multiarch/memmove.c
|
||||
+++ b/sysdeps/aarch64/multiarch/memmove.c
|
||||
@@ -41,7 +41,7 @@ libc_ifunc (__libc_memmove,
|
||||
: (IS_FALKOR (midr) || IS_PHECDA (midr)
|
||||
? __memmove_falkor
|
||||
# if HAVE_AARCH64_SVE_ASM
|
||||
- : (IS_A64FX (midr)
|
||||
+ : (IS_A64FX (midr) && sve
|
||||
? __memmove_a64fx
|
||||
: __memmove_generic))));
|
||||
# else
|
||||
diff --git a/sysdeps/aarch64/multiarch/memset.c b/sysdeps/aarch64/multiarch/memset.c
|
||||
index 2c8cc72bb0b18474..e7bd412377533f18 100644
|
||||
--- a/sysdeps/aarch64/multiarch/memset.c
|
||||
+++ b/sysdeps/aarch64/multiarch/memset.c
|
||||
@@ -38,7 +38,7 @@ libc_ifunc (__libc_memset,
|
||||
((IS_FALKOR (midr) || IS_PHECDA (midr)) && zva_size == 64
|
||||
? __memset_falkor
|
||||
# if HAVE_AARCH64_SVE_ASM
|
||||
- : (IS_A64FX (midr)
|
||||
+ : (IS_A64FX (midr) && sve
|
||||
? __memset_a64fx
|
||||
: __memset_generic)));
|
||||
# else
|
164
SOURCES/glibc-rh2045063-1.patch
Normal file
164
SOURCES/glibc-rh2045063-1.patch
Normal file
@ -0,0 +1,164 @@
|
||||
commit e368b12f6c16b6888dda99ba641e999b9c9643c8
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jan 17 10:21:34 2022 +0100
|
||||
|
||||
socket: Add the __sockaddr_un_set function
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
# Conflicts:
|
||||
# socket/Makefile
|
||||
|
||||
diff --git a/include/sys/un.h b/include/sys/un.h
|
||||
index bdbee999806930f4..152afd9fc7426d8b 100644
|
||||
--- a/include/sys/un.h
|
||||
+++ b/include/sys/un.h
|
||||
@@ -1 +1,13 @@
|
||||
#include <socket/sys/un.h>
|
||||
+
|
||||
+#ifndef _ISOMAC
|
||||
+
|
||||
+/* Set ADDR->sun_family to AF_UNIX and ADDR->sun_path to PATHNAME.
|
||||
+ Return 0 on success or -1 on failure (due to overlong PATHNAME).
|
||||
+ The caller should always use sizeof (struct sockaddr_un) as the
|
||||
+ socket address length, disregaring the length of PATHNAME.
|
||||
+ Only concrete (non-abstract) pathnames are supported. */
|
||||
+int __sockaddr_un_set (struct sockaddr_un *addr, const char *pathname)
|
||||
+ attribute_hidden;
|
||||
+
|
||||
+#endif /* _ISOMAC */
|
||||
diff --git a/socket/Makefile b/socket/Makefile
|
||||
index b41eb071507a6271..8975a65c2aabbfbc 100644
|
||||
--- a/socket/Makefile
|
||||
+++ b/socket/Makefile
|
||||
@@ -29,10 +29,14 @@ headers := sys/socket.h sys/un.h bits/sockaddr.h bits/socket.h \
|
||||
routines := accept bind connect getpeername getsockname getsockopt \
|
||||
listen recv recvfrom recvmsg send sendmsg sendto \
|
||||
setsockopt shutdown socket socketpair isfdtype opensock \
|
||||
- sockatmark accept4 recvmmsg sendmmsg
|
||||
+ sockatmark accept4 recvmmsg sendmmsg sockaddr_un_set
|
||||
|
||||
tests := tst-accept4
|
||||
|
||||
+tests-internal := \
|
||||
+ tst-sockaddr_un_set \
|
||||
+ # tests-internal
|
||||
+
|
||||
aux := sa_len
|
||||
|
||||
include ../Rules
|
||||
diff --git a/socket/sockaddr_un_set.c b/socket/sockaddr_un_set.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..0bd40dc34e3d7efc
|
||||
--- /dev/null
|
||||
+++ b/socket/sockaddr_un_set.c
|
||||
@@ -0,0 +1,41 @@
|
||||
+/* Set the sun_path member of struct sockaddr_un.
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <string.h>
|
||||
+#include <sys/socket.h>
|
||||
+#include <sys/un.h>
|
||||
+
|
||||
+int
|
||||
+__sockaddr_un_set (struct sockaddr_un *addr, const char *pathname)
|
||||
+{
|
||||
+ size_t name_length = strlen (pathname);
|
||||
+
|
||||
+ /* The kernel supports names of exactly sizeof (addr->sun_path)
|
||||
+ bytes, without a null terminator, but userspace does not; see the
|
||||
+ SUN_LEN macro. */
|
||||
+ if (name_length >= sizeof (addr->sun_path))
|
||||
+ {
|
||||
+ __set_errno (EINVAL); /* Error code used by the kernel. */
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ addr->sun_family = AF_UNIX;
|
||||
+ memcpy (addr->sun_path, pathname, name_length + 1);
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/socket/tst-sockaddr_un_set.c b/socket/tst-sockaddr_un_set.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..29c2a81afda81b5e
|
||||
--- /dev/null
|
||||
+++ b/socket/tst-sockaddr_un_set.c
|
||||
@@ -0,0 +1,62 @@
|
||||
+/* Test the __sockaddr_un_set function.
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* Re-compile the function because the version in libc is not
|
||||
+ exported. */
|
||||
+#include "sockaddr_un_set.c"
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct sockaddr_un sun;
|
||||
+
|
||||
+ memset (&sun, 0xcc, sizeof (sun));
|
||||
+ __sockaddr_un_set (&sun, "");
|
||||
+ TEST_COMPARE (sun.sun_family, AF_UNIX);
|
||||
+ TEST_COMPARE (__sockaddr_un_set (&sun, ""), 0);
|
||||
+
|
||||
+ memset (&sun, 0xcc, sizeof (sun));
|
||||
+ TEST_COMPARE (__sockaddr_un_set (&sun, "/example"), 0);
|
||||
+ TEST_COMPARE_STRING (sun.sun_path, "/example");
|
||||
+
|
||||
+ {
|
||||
+ char pathname[108]; /* Length of sun_path (ABI constant). */
|
||||
+ memset (pathname, 'x', sizeof (pathname));
|
||||
+ pathname[sizeof (pathname) - 1] = '\0';
|
||||
+ memset (&sun, 0xcc, sizeof (sun));
|
||||
+ TEST_COMPARE (__sockaddr_un_set (&sun, pathname), 0);
|
||||
+ TEST_COMPARE (sun.sun_family, AF_UNIX);
|
||||
+ TEST_COMPARE_STRING (sun.sun_path, pathname);
|
||||
+ }
|
||||
+
|
||||
+ {
|
||||
+ char pathname[109];
|
||||
+ memset (pathname, 'x', sizeof (pathname));
|
||||
+ pathname[sizeof (pathname) - 1] = '\0';
|
||||
+ memset (&sun, 0xcc, sizeof (sun));
|
||||
+ errno = 0;
|
||||
+ TEST_COMPARE (__sockaddr_un_set (&sun, pathname), -1);
|
||||
+ TEST_COMPARE (errno, EINVAL);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
32
SOURCES/glibc-rh2045063-2.patch
Normal file
32
SOURCES/glibc-rh2045063-2.patch
Normal file
@ -0,0 +1,32 @@
|
||||
commit 226b46770c82899b555986583294b049c6ec9b40
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jan 17 10:21:34 2022 +0100
|
||||
|
||||
CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix" (bug 22542)
|
||||
|
||||
Processing an overlong pathname in the sunrpc clnt_create function
|
||||
results in a stack-based buffer overflow.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/sunrpc/clnt_gen.c b/sunrpc/clnt_gen.c
|
||||
index 13ced8994e49d4ee..b44357cd88e60599 100644
|
||||
--- a/sunrpc/clnt_gen.c
|
||||
+++ b/sunrpc/clnt_gen.c
|
||||
@@ -57,9 +57,13 @@ clnt_create (const char *hostname, u_long prog, u_long vers,
|
||||
|
||||
if (strcmp (proto, "unix") == 0)
|
||||
{
|
||||
- memset ((char *)&sun, 0, sizeof (sun));
|
||||
- sun.sun_family = AF_UNIX;
|
||||
- strcpy (sun.sun_path, hostname);
|
||||
+ if (__sockaddr_un_set (&sun, hostname) < 0)
|
||||
+ {
|
||||
+ struct rpc_createerr *ce = &get_rpc_createerr ();
|
||||
+ ce->cf_stat = RPC_SYSTEMERROR;
|
||||
+ ce->cf_error.re_errno = errno;
|
||||
+ return NULL;
|
||||
+ }
|
||||
sock = RPC_ANYSOCK;
|
||||
client = clntunix_create (&sun, prog, vers, &sock, 0, 0);
|
||||
if (client == NULL)
|
80
SOURCES/glibc-rh2045063-3.patch
Normal file
80
SOURCES/glibc-rh2045063-3.patch
Normal file
@ -0,0 +1,80 @@
|
||||
commit ef972a4c50014a16132b5c75571cfb6b30bef136
|
||||
Author: Martin Sebor <msebor@redhat.com>
|
||||
Date: Mon Jan 17 10:21:34 2022 +0100
|
||||
|
||||
sunrpc: Test case for clnt_create "unix" buffer overflow (bug 22542)
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
# Conflicts:
|
||||
# sunrpc/Makefile
|
||||
|
||||
diff --git a/sunrpc/Makefile b/sunrpc/Makefile
|
||||
index 85b0b3356aaf81a3..2f8f0597c99e117f 100644
|
||||
--- a/sunrpc/Makefile
|
||||
+++ b/sunrpc/Makefile
|
||||
@@ -95,7 +95,8 @@ others += rpcgen
|
||||
endif
|
||||
|
||||
tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \
|
||||
- tst-udp-nonblocking
|
||||
+ tst-udp-nonblocking tst-bug22542
|
||||
+
|
||||
xtests := tst-getmyaddr
|
||||
|
||||
ifeq ($(have-thread-library),yes)
|
||||
@@ -246,3 +247,4 @@ $(objpfx)tst-udp-timeout: $(common-objpfx)linkobj/libc.so
|
||||
$(objpfx)tst-udp-nonblocking: $(common-objpfx)linkobj/libc.so
|
||||
$(objpfx)tst-udp-garbage: \
|
||||
$(common-objpfx)linkobj/libc.so $(shared-thread-library)
|
||||
+$(objpfx)tst-bug22542: $(common-objpfx)linkobj/libc.so
|
||||
diff --git a/sunrpc/tst-bug22542.c b/sunrpc/tst-bug22542.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..d6cd79787bdef21d
|
||||
--- /dev/null
|
||||
+++ b/sunrpc/tst-bug22542.c
|
||||
@@ -0,0 +1,44 @@
|
||||
+/* Test to verify that overlong hostname is rejected by clnt_create
|
||||
+ and doesn't cause a buffer overflow (bug 22542).
|
||||
+
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <rpc/clnt.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <sys/socket.h>
|
||||
+#include <sys/un.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Create an arbitrary hostname that's longer than fits in sun_path. */
|
||||
+ char name [sizeof ((struct sockaddr_un*)0)->sun_path * 2];
|
||||
+ memset (name, 'x', sizeof name - 1);
|
||||
+ name [sizeof name - 1] = '\0';
|
||||
+
|
||||
+ errno = 0;
|
||||
+ CLIENT *clnt = clnt_create (name, 0, 0, "unix");
|
||||
+
|
||||
+ TEST_VERIFY (clnt == NULL);
|
||||
+ TEST_COMPARE (errno, EINVAL);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
101
SOURCES/glibc-rh2045063-4.patch
Normal file
101
SOURCES/glibc-rh2045063-4.patch
Normal file
@ -0,0 +1,101 @@
|
||||
commit f545ad4928fa1f27a3075265182b38a4f939a5f7
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Jan 17 10:21:34 2022 +0100
|
||||
|
||||
CVE-2022-23218: Buffer overflow in sunrpc svcunix_create (bug 28768)
|
||||
|
||||
The sunrpc function svcunix_create suffers from a stack-based buffer
|
||||
overflow with overlong pathname arguments.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/sunrpc/Makefile b/sunrpc/Makefile
|
||||
index 2f8f0597c99e117f..5f7087aee494cc2e 100644
|
||||
--- a/sunrpc/Makefile
|
||||
+++ b/sunrpc/Makefile
|
||||
@@ -95,7 +95,7 @@ others += rpcgen
|
||||
endif
|
||||
|
||||
tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \
|
||||
- tst-udp-nonblocking tst-bug22542
|
||||
+ tst-udp-nonblocking tst-bug22542 tst-bug28768
|
||||
|
||||
xtests := tst-getmyaddr
|
||||
|
||||
diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c
|
||||
index c2c076aa87f0a2ad..8fac2b35da1d38a5 100644
|
||||
--- a/sunrpc/svc_unix.c
|
||||
+++ b/sunrpc/svc_unix.c
|
||||
@@ -154,7 +154,10 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
|
||||
SVCXPRT *xprt;
|
||||
struct unix_rendezvous *r;
|
||||
struct sockaddr_un addr;
|
||||
- socklen_t len = sizeof (struct sockaddr_in);
|
||||
+ socklen_t len = sizeof (addr);
|
||||
+
|
||||
+ if (__sockaddr_un_set (&addr, path) < 0)
|
||||
+ return NULL;
|
||||
|
||||
if (sock == RPC_ANYSOCK)
|
||||
{
|
||||
@@ -165,12 +168,6 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
|
||||
}
|
||||
madesock = TRUE;
|
||||
}
|
||||
- memset (&addr, '\0', sizeof (addr));
|
||||
- addr.sun_family = AF_UNIX;
|
||||
- len = strlen (path) + 1;
|
||||
- memcpy (addr.sun_path, path, len);
|
||||
- len += sizeof (addr.sun_family);
|
||||
-
|
||||
__bind (sock, (struct sockaddr *) &addr, len);
|
||||
|
||||
if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0
|
||||
diff --git a/sunrpc/tst-bug28768.c b/sunrpc/tst-bug28768.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..35a4b7b0b3d34350
|
||||
--- /dev/null
|
||||
+++ b/sunrpc/tst-bug28768.c
|
||||
@@ -0,0 +1,42 @@
|
||||
+/* Test to verify that long path is rejected by svcunix_create (bug 28768).
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <rpc/svc.h>
|
||||
+#include <shlib-compat.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+/* svcunix_create does not have a default version in linkobj/libc.so. */
|
||||
+compat_symbol_reference (libc, svcunix_create, svcunix_create, GLIBC_2_1);
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ char pathname[109];
|
||||
+ memset (pathname, 'x', sizeof (pathname));
|
||||
+ pathname[sizeof (pathname) - 1] = '\0';
|
||||
+
|
||||
+ errno = 0;
|
||||
+ TEST_VERIFY (svcunix_create (RPC_ANYSOCK, 4096, 4096, pathname) == NULL);
|
||||
+ TEST_COMPARE (errno, EINVAL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
54
SOURCES/glibc-rh2045063-5.patch
Normal file
54
SOURCES/glibc-rh2045063-5.patch
Normal file
@ -0,0 +1,54 @@
|
||||
commit 36f6e408845c8c539128f3fb9cb132bf1845a2c8
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Mar 9 21:07:24 2021 +0100
|
||||
|
||||
<shlib-compat.h>: Support compat_symbol_reference for _ISOMAC
|
||||
|
||||
This is helpful for testing compat symbols in cases where _ISOMAC
|
||||
is activated implicitly due to -DMODULE_NAME=testsuite and cannot
|
||||
be disabled easily.
|
||||
|
||||
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
|
||||
index 41436050d060b89f..44e12b63d40cc572 100644
|
||||
--- a/include/libc-symbols.h
|
||||
+++ b/include/libc-symbols.h
|
||||
@@ -59,6 +59,19 @@
|
||||
# define IN_MODULE (-1)
|
||||
#endif
|
||||
|
||||
+/* Use symbol_version_reference to specify the version a symbol
|
||||
+ reference should link to. Use symbol_version or
|
||||
+ default_symbol_version for the definition of a versioned symbol.
|
||||
+ The difference is that the latter is a no-op in non-shared
|
||||
+ builds. */
|
||||
+#ifdef __ASSEMBLER__
|
||||
+# define symbol_version_reference(real, name, version) \
|
||||
+ .symver real, name##@##version
|
||||
+#else /* !__ASSEMBLER__ */
|
||||
+# define symbol_version_reference(real, name, version) \
|
||||
+ __asm__ (".symver " #real "," #name "@" #version)
|
||||
+#endif
|
||||
+
|
||||
#ifndef _ISOMAC
|
||||
|
||||
/* This is defined for the compilation of all C library code. features.h
|
||||
@@ -388,19 +401,6 @@ for linking")
|
||||
past the last element in SET. */
|
||||
#define symbol_set_end_p(set, ptr) ((ptr) >= (void *const *) &__stop_##set)
|
||||
|
||||
-/* Use symbol_version_reference to specify the version a symbol
|
||||
- reference should link to. Use symbol_version or
|
||||
- default_symbol_version for the definition of a versioned symbol.
|
||||
- The difference is that the latter is a no-op in non-shared
|
||||
- builds. */
|
||||
-#ifdef __ASSEMBLER__
|
||||
-# define symbol_version_reference(real, name, version) \
|
||||
- .symver real, name##@##version
|
||||
-#else /* !__ASSEMBLER__ */
|
||||
-# define symbol_version_reference(real, name, version) \
|
||||
- __asm__ (".symver " #real "," #name "@" #version)
|
||||
-#endif
|
||||
-
|
||||
#ifdef SHARED
|
||||
# define symbol_version(real, name, version) \
|
||||
symbol_version_reference(real, name, version)
|
112
SOURCES/wrap-find-debuginfo.sh
Executable file
112
SOURCES/wrap-find-debuginfo.sh
Executable file
@ -0,0 +1,112 @@
|
||||
#!/bin/bash
|
||||
# Wrapper script for find-debuginfo.sh
|
||||
#
|
||||
# Usage:
|
||||
# wrap-find-debuginfo.sh SYSROOT-PATH SCRIPT-PATH SCRIPT-ARGS...
|
||||
#
|
||||
# The wrapper saves the original version of ld.so found in SYSROOT-PATH,
|
||||
# invokes SCRIPT-PATH with SCRIPT-ARGS, and then restores the
|
||||
# LDSO-PATH file, followed by note merging and DWZ compression.
|
||||
# As a result, ld.so has (mostly) unchanged debuginfo even
|
||||
# after debuginfo extraction.
|
||||
#
|
||||
# For libc.so.6 and other shared objects, a set of strategic symbols
|
||||
# is preserved in .symtab that are frequently used in valgrind
|
||||
# suppressions and elsewhere.
|
||||
|
||||
set -evx
|
||||
|
||||
tar_tmp="$(mktemp)"
|
||||
|
||||
# Prefer a separately installed debugedit over the RPM-integrated one.
|
||||
if command -v debugedit >/dev/null ; then
|
||||
debugedit=debugedit
|
||||
else
|
||||
debugedit=/usr/lib/rpm/debugedit
|
||||
fi
|
||||
|
||||
cleanup () {
|
||||
rm -f "$tar_tmp"
|
||||
}
|
||||
trap cleanup 0
|
||||
|
||||
sysroot_path="$1"
|
||||
shift
|
||||
script_path="$1"
|
||||
shift
|
||||
|
||||
# See run_ldso setting in glibc.spec.
|
||||
ldso_list=`cd "$sysroot_path"; find . -name 'ld-*.so' -type f`
|
||||
libc_list=`cd "$sysroot_path"; find . -name 'libc-*.so' -type f`
|
||||
libdl_list=`cd "$sysroot_path"; find . -name 'libdl-*.so' -type f`
|
||||
libpthread_list=`cd "$sysroot_path"; find . -name 'libpthread-*.so' -type f`
|
||||
librt_list=`cd "$sysroot_path"; find . -name 'librt-*.so' -type f`
|
||||
|
||||
full_list="$ldso_list $libc_list $libdl_list $libpthread_list $librt_list"
|
||||
|
||||
# Preserve the original files.
|
||||
(cd "$sysroot_path"; ls -l $full_list)
|
||||
(cd "$sysroot_path"; tar cvf "$tar_tmp" $full_list)
|
||||
|
||||
# Run the debuginfo extraction.
|
||||
"$script_path" "$@"
|
||||
|
||||
# Restore the original files.
|
||||
(cd "$sysroot_path"; tar xf "$tar_tmp")
|
||||
(cd "$sysroot_path"; ls -l $full_list)
|
||||
|
||||
# Reduce the size of notes. Primarily for annobin.
|
||||
for p in $full_list
|
||||
do
|
||||
objcopy --merge-notes "$sysroot_path/$p"
|
||||
done
|
||||
|
||||
# libc.so.6 and other shared objects: Reduce to valuable symbols.
|
||||
# Eliminate file symbols, annobin symbols, and symbols used by the
|
||||
# glibc build to implement hidden aliases (__EI_*). We would also
|
||||
# like to remove __GI_* symbols, but even listing them explicitly (as
|
||||
# in -K __GI_strlen) still causes strip to remove them, so there is no
|
||||
# filtering of __GI_* here. (Debuginfo is gone after this, so no need
|
||||
# to optimize it.)
|
||||
for p in $libc_list $libdl_list $libpthread_list $librt_list ; do
|
||||
strip -w \
|
||||
-K '*' \
|
||||
-K '!*.c' \
|
||||
-K '!*.os' \
|
||||
-K '!.annobin_*' \
|
||||
-K '!__EI_*' \
|
||||
-K '!__PRETTY_FUNCTION__*' \
|
||||
"$sysroot_path/$p"
|
||||
done
|
||||
|
||||
# ld.so: Rewrite the source file paths to match the extracted
|
||||
# locations. First compute the arguments for invoking debugedit.
|
||||
# See find-debuginfo.sh.
|
||||
debug_dest_name="/usr/src/debug"
|
||||
last_arg=
|
||||
while true ; do
|
||||
arg="$1"
|
||||
shift || break
|
||||
case "$arg" in
|
||||
(--unique-debug-src-base)
|
||||
debug_dest_name="/usr/src/debug/$1"
|
||||
shift
|
||||
;;
|
||||
(-*)
|
||||
;;
|
||||
(*)
|
||||
last_arg="$arg"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
debug_base_name=${last_arg:-$RPM_BUILD_ROOT}
|
||||
for p in $ldso_list
|
||||
do
|
||||
$debugedit -b "$debug_base_name" -d "$debug_dest_name" -n "$sysroot_path/$p"
|
||||
done
|
||||
|
||||
# Apply single-file DWARF optimization.
|
||||
for ldso in $ldso_list
|
||||
do
|
||||
dwz "$sysroot_path/$p"
|
||||
done
|
580
SPECS/glibc.spec
580
SPECS/glibc.spec
@ -1,6 +1,6 @@
|
||||
%define glibcsrcdir glibc-2.28
|
||||
%define glibcversion 2.28
|
||||
%define glibcrelease 164%{?dist}
|
||||
%define glibcrelease 189%{?dist}
|
||||
# Pre-release tarballs are pulled in from git using a command that is
|
||||
# effectively:
|
||||
#
|
||||
@ -85,6 +85,47 @@
|
||||
# here. If the arch is not listed here then a single core debuginfo package
|
||||
# will be created for the architecture.
|
||||
%define debuginfocommonarches %{biarcharches} alpha alphaev6
|
||||
|
||||
##############################################################################
|
||||
# Utility functions for pre/post scripts. Stick them at the beginning of
|
||||
# any lua %pre, %post, %postun, etc. sections to have them expand into
|
||||
# those scripts. It only works in lua sections and not anywhere else.
|
||||
%define glibc_post_funcs() \
|
||||
-- We use lua posix.exec because there may be no shell that we can \
|
||||
-- run during glibc upgrade. We used to implement much of %%post as a \
|
||||
-- C program, but from an overall maintenance perspective the lua in \
|
||||
-- the spec file was simpler and safer given the operations required. \
|
||||
-- All lua code will be ignored by rpm-ostree; see: \
|
||||
-- https://github.com/projectatomic/rpm-ostree/pull/1869 \
|
||||
-- If we add new lua actions to the %%post code we should coordinate \
|
||||
-- with rpm-ostree and ensure that their glibc install is functional. \
|
||||
function post_exec (program, ...) \
|
||||
local pid = posix.fork () \
|
||||
if pid == 0 then \
|
||||
posix.exec (program, ...) \
|
||||
assert (nil) \
|
||||
elseif pid > 0 then \
|
||||
posix.wait (pid) \
|
||||
end \
|
||||
end \
|
||||
\
|
||||
function update_gconv_modules_cache () \
|
||||
local iconv_dir = "%{_libdir}/gconv" \
|
||||
local iconv_cache = iconv_dir .. "/gconv-modules.cache" \
|
||||
local iconv_modules = iconv_dir .. "/gconv-modules" \
|
||||
if (posix.utime (iconv_modules) == 0) then \
|
||||
if (posix.utime (iconv_cache) == 0) then \
|
||||
post_exec ("%{_prefix}/sbin/iconvconfig", \
|
||||
"-o", iconv_cache, \
|
||||
"--nostdlib", \
|
||||
iconv_dir) \
|
||||
else \
|
||||
io.stdout:write ("Error: Missing " .. iconv_cache .. " file.\n") \
|
||||
end \
|
||||
end \
|
||||
end \
|
||||
%{nil}
|
||||
|
||||
##############################################################################
|
||||
# %%package glibc - The GNU C Library (glibc) core package.
|
||||
##############################################################################
|
||||
@ -135,6 +176,23 @@ Source11: SUPPORTED
|
||||
# Include in the source RPM for reference.
|
||||
Source12: ChangeLog.old
|
||||
|
||||
Source13: wrap-find-debuginfo.sh
|
||||
|
||||
######################################################################
|
||||
# Activate the wrapper script for debuginfo generation, by rewriting
|
||||
# the definition of __debug_install_post.
|
||||
%{lua:
|
||||
local wrapper = rpm.expand("%{SOURCE13}")
|
||||
local sysroot = rpm.expand("%{glibc_sysroot}")
|
||||
local original = rpm.expand("%{__find_debuginfo}")
|
||||
rpm.define("__find_debuginfo " .. wrapper .. " " .. sysroot .. " " .. original)
|
||||
}
|
||||
|
||||
# The wrapper script relies on the fact that debugedit does not change
|
||||
# build IDs.
|
||||
%define _no_recompute_build_ids 1
|
||||
%undefine _unique_build_ids
|
||||
|
||||
##############################################################################
|
||||
# Patches:
|
||||
# - See each individual patch file for origin and upstream status.
|
||||
@ -719,6 +777,84 @@ Patch582: glibc-rh1966472-1.patch
|
||||
Patch583: glibc-rh1966472-2.patch
|
||||
Patch584: glibc-rh1966472-3.patch
|
||||
Patch585: glibc-rh1966472-4.patch
|
||||
Patch586: glibc-rh1971664-1.patch
|
||||
Patch587: glibc-rh1971664-2.patch
|
||||
Patch588: glibc-rh1971664-3.patch
|
||||
Patch589: glibc-rh1971664-4.patch
|
||||
Patch590: glibc-rh1971664-5.patch
|
||||
Patch591: glibc-rh1971664-6.patch
|
||||
Patch592: glibc-rh1971664-7.patch
|
||||
Patch593: glibc-rh1971664-8.patch
|
||||
Patch594: glibc-rh1971664-9.patch
|
||||
Patch595: glibc-rh1971664-10.patch
|
||||
Patch596: glibc-rh1971664-11.patch
|
||||
Patch597: glibc-rh1971664-12.patch
|
||||
Patch598: glibc-rh1971664-13.patch
|
||||
Patch599: glibc-rh1971664-14.patch
|
||||
Patch600: glibc-rh1971664-15.patch
|
||||
Patch601: glibc-rh1977614.patch
|
||||
Patch602: glibc-rh1983203-1.patch
|
||||
Patch603: glibc-rh1983203-2.patch
|
||||
Patch604: glibc-rh2021452.patch
|
||||
Patch605: glibc-rh1937515.patch
|
||||
Patch606: glibc-rh1934162-1.patch
|
||||
Patch607: glibc-rh1934162-2.patch
|
||||
Patch608: glibc-rh2000374.patch
|
||||
Patch609: glibc-rh1991001-1.patch
|
||||
Patch610: glibc-rh1991001-2.patch
|
||||
Patch611: glibc-rh1991001-3.patch
|
||||
Patch612: glibc-rh1991001-4.patch
|
||||
Patch613: glibc-rh1991001-5.patch
|
||||
Patch614: glibc-rh1991001-6.patch
|
||||
Patch615: glibc-rh1991001-7.patch
|
||||
Patch616: glibc-rh1991001-8.patch
|
||||
Patch617: glibc-rh1991001-9.patch
|
||||
Patch618: glibc-rh1991001-10.patch
|
||||
Patch619: glibc-rh1991001-11.patch
|
||||
Patch620: glibc-rh1991001-12.patch
|
||||
Patch621: glibc-rh1991001-13.patch
|
||||
Patch622: glibc-rh1991001-14.patch
|
||||
Patch623: glibc-rh1991001-15.patch
|
||||
Patch624: glibc-rh1991001-16.patch
|
||||
Patch625: glibc-rh1991001-17.patch
|
||||
Patch626: glibc-rh1991001-18.patch
|
||||
Patch627: glibc-rh1991001-19.patch
|
||||
Patch628: glibc-rh1991001-20.patch
|
||||
Patch629: glibc-rh1991001-21.patch
|
||||
Patch630: glibc-rh1991001-22.patch
|
||||
Patch631: glibc-rh1929928-1.patch
|
||||
Patch632: glibc-rh1929928-2.patch
|
||||
Patch633: glibc-rh1929928-3.patch
|
||||
Patch634: glibc-rh1929928-4.patch
|
||||
Patch635: glibc-rh1929928-5.patch
|
||||
Patch636: glibc-rh1984802-1.patch
|
||||
Patch637: glibc-rh1984802-2.patch
|
||||
Patch638: glibc-rh1984802-3.patch
|
||||
Patch639: glibc-rh2023420-1.patch
|
||||
Patch640: glibc-rh2023420-2.patch
|
||||
Patch641: glibc-rh2023420-3.patch
|
||||
Patch642: glibc-rh2023420-4.patch
|
||||
Patch643: glibc-rh2023420-5.patch
|
||||
Patch644: glibc-rh2023420-6.patch
|
||||
Patch645: glibc-rh2023420-7.patch
|
||||
Patch646: glibc-rh2033648-1.patch
|
||||
Patch647: glibc-rh2033648-2.patch
|
||||
Patch648: glibc-rh2036955.patch
|
||||
Patch649: glibc-rh2033655.patch
|
||||
Patch650: glibc-rh2007327-1.patch
|
||||
Patch651: glibc-rh2007327-2.patch
|
||||
Patch652: glibc-rh2032281-1.patch
|
||||
Patch653: glibc-rh2032281-2.patch
|
||||
Patch654: glibc-rh2032281-3.patch
|
||||
Patch655: glibc-rh2032281-4.patch
|
||||
Patch656: glibc-rh2032281-5.patch
|
||||
Patch657: glibc-rh2032281-6.patch
|
||||
Patch658: glibc-rh2032281-7.patch
|
||||
Patch659: glibc-rh2045063-1.patch
|
||||
Patch660: glibc-rh2045063-2.patch
|
||||
Patch661: glibc-rh2045063-3.patch
|
||||
Patch662: glibc-rh2045063-4.patch
|
||||
Patch663: glibc-rh2045063-5.patch
|
||||
|
||||
##############################################################################
|
||||
# Continued list of core "glibc" package information:
|
||||
@ -748,11 +884,6 @@ Recommends: (nss_db(x86-32) if nss_db(x86-64))
|
||||
BuildRequires: gd-devel libpng-devel zlib-devel
|
||||
%endif
|
||||
%if %{with docs}
|
||||
# Removing texinfo will cause check-safety.sh test to fail because it seems to
|
||||
# trigger documentation generation based on dependencies. We need to fix this
|
||||
# upstream in some way that doesn't depend on generating docs to validate the
|
||||
# texinfo. I expect it's simply the wrong dependency for that target.
|
||||
BuildRequires: texinfo >= 5.0
|
||||
%endif
|
||||
%if %{without bootstrap}
|
||||
BuildRequires: libselinux-devel >= 1.33.4-3
|
||||
@ -813,7 +944,8 @@ Conflicts: prelink < 0.4.2
|
||||
|
||||
%if 0%{?_enable_debug_packages}
|
||||
BuildRequires: elfutils >= 0.72
|
||||
BuildRequires: rpm >= 4.2-0.56
|
||||
# -20 adds __find_debuginfo macro
|
||||
BuildRequires: rpm >= 4.14.3-20
|
||||
%endif
|
||||
|
||||
%if %{without bootstrap}
|
||||
@ -849,6 +981,10 @@ BuildRequires: libidn2
|
||||
Requires: glibc-langpack = %{version}-%{release}
|
||||
Suggests: glibc-all-langpacks = %{version}-%{release}
|
||||
|
||||
# Suggest extra gconv modules so that they are installed by default but can be
|
||||
# removed if needed to build a minimal OS image.
|
||||
Recommends: glibc-gconv-extra%{_isa} = %{version}-%{release}
|
||||
|
||||
%description
|
||||
The glibc package contains standard libraries which are used by
|
||||
multiple programs on the system. In order to save disk space and
|
||||
@ -896,6 +1032,26 @@ executables.
|
||||
Install glibc-devel if you are going to develop programs which will
|
||||
use the standard C libraries.
|
||||
|
||||
##############################################################################
|
||||
# glibc "doc" sub-package
|
||||
##############################################################################
|
||||
%if %{with docs}
|
||||
%package doc
|
||||
Summary: Documentation for GNU libc
|
||||
BuildArch: noarch
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
# Removing texinfo will cause check-safety.sh test to fail because it seems to
|
||||
# trigger documentation generation based on dependencies. We need to fix this
|
||||
# upstream in some way that doesn't depend on generating docs to validate the
|
||||
# texinfo. I expect it's simply the wrong dependency for that target.
|
||||
BuildRequires: texinfo >= 5.0
|
||||
|
||||
%description doc
|
||||
The glibc-doc package contains The GNU C Library Reference Manual in info
|
||||
format. Additional package documentation is also provided.
|
||||
%endif
|
||||
|
||||
##############################################################################
|
||||
# glibc "static" sub-package
|
||||
##############################################################################
|
||||
@ -1098,6 +1254,15 @@ nothing else. It is designed for assembling a minimal system.
|
||||
%files minimal-langpack
|
||||
%endif
|
||||
|
||||
# Infrequently used iconv converter modules.
|
||||
%package gconv-extra
|
||||
Summary: All iconv converter modules for %{name}.
|
||||
Requires: %{name}%{_isa} = %{version}-%{release}
|
||||
Requires: %{name}-common = %{version}-%{release}
|
||||
|
||||
%description gconv-extra
|
||||
This package contains all iconv converter modules built in %{name}.
|
||||
|
||||
##############################################################################
|
||||
# glibc "nscd" sub-package
|
||||
##############################################################################
|
||||
@ -1180,62 +1345,6 @@ which can be helpful during program debugging.
|
||||
|
||||
If unsure if you need this, don't install this package.
|
||||
|
||||
##############################################################################
|
||||
# glibc core "debuginfo" sub-package
|
||||
##############################################################################
|
||||
%if 0%{?_enable_debug_packages}
|
||||
%define debug_package %{nil}
|
||||
%define __debug_install_post %{nil}
|
||||
%global __debug_package 1
|
||||
# Disable thew new features that glibc packages don't use.
|
||||
%undefine _debugsource_packages
|
||||
%undefine _debuginfo_subpackages
|
||||
%undefine _unique_debug_names
|
||||
%undefine _unique_debug_srcs
|
||||
|
||||
%package debuginfo
|
||||
Summary: Debug information for package %{name}
|
||||
AutoReqProv: no
|
||||
%ifarch %{debuginfocommonarches}
|
||||
Requires: glibc-debuginfo-common = %{version}-%{release}
|
||||
%else
|
||||
%ifarch %{ix86} %{sparc}
|
||||
Obsoletes: glibc-debuginfo-common
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%description debuginfo
|
||||
This package provides debug information for package %{name}.
|
||||
Debug information is useful when developing applications that use this
|
||||
package or when debugging this package.
|
||||
|
||||
This package also contains static standard C libraries with
|
||||
debugging information. You need this only if you want to step into
|
||||
C library routines during debugging programs statically linked against
|
||||
one or more of the standard C libraries.
|
||||
To use this debugging information, you need to link binaries
|
||||
with -static -L%{_prefix}/lib/debug%{_libdir} compiler options.
|
||||
|
||||
##############################################################################
|
||||
# glibc common "debuginfo-common" sub-package
|
||||
##############################################################################
|
||||
%ifarch %{debuginfocommonarches}
|
||||
|
||||
%package debuginfo-common
|
||||
Summary: Debug information for package %{name}
|
||||
AutoReqProv: no
|
||||
|
||||
%description debuginfo-common
|
||||
This package provides debug information for package %{name}.
|
||||
Debug information is useful when developing applications that use this
|
||||
package or when debugging this package.
|
||||
|
||||
%comment Matches: %ifarch %{debuginfocommonarches}
|
||||
%endif
|
||||
|
||||
%comment Matches: %if 0%{?_enable_debug_packages}
|
||||
%endif
|
||||
|
||||
%if %{with benchtests}
|
||||
%package benchtests
|
||||
Summary: Benchmarking binaries and scripts for %{name}
|
||||
@ -1602,6 +1711,9 @@ fi
|
||||
# Compress all of the info files.
|
||||
gzip -9nvf %{glibc_sysroot}%{_infodir}/libc*
|
||||
|
||||
# Copy the debugger interface documentation over to the right location
|
||||
mkdir -p %{glibc_sysroot}%{_docdir}/glibc
|
||||
cp elf/rtld-debugger-interface.txt %{glibc_sysroot}%{_docdir}/glibc
|
||||
%else
|
||||
rm -f %{glibc_sysroot}%{_infodir}/dir
|
||||
rm -f %{glibc_sysroot}%{_infodir}/libc.info*
|
||||
@ -1693,15 +1805,6 @@ chmod 644 %{glibc_sysroot}%{_libdir}/gconv/gconv-modules.cache
|
||||
# archives we might have added.
|
||||
##############################################################################
|
||||
|
||||
# If we are building a debug package then copy all of the static archives
|
||||
# into the debug directory to keep them as unstripped copies.
|
||||
%if 0%{?_enable_debug_packages}
|
||||
mkdir -p %{glibc_sysroot}%{_prefix}/lib/debug%{_libdir}
|
||||
cp -a %{glibc_sysroot}%{_libdir}/*.a \
|
||||
%{glibc_sysroot}%{_prefix}/lib/debug%{_libdir}/
|
||||
rm -f %{glibc_sysroot}%{_prefix}/lib/debug%{_libdir}/*_p.a
|
||||
%endif
|
||||
|
||||
# Remove any zoneinfo files; they are maintained by tzdata.
|
||||
rm -rf %{glibc_sysroot}%{_prefix}/share/zoneinfo
|
||||
|
||||
@ -1715,7 +1818,14 @@ touch -r %{SOURCE0} %{glibc_sysroot}/etc/ld.so.conf
|
||||
touch -r sunrpc/etc.rpc %{glibc_sysroot}/etc/rpc
|
||||
|
||||
pushd build-%{target}
|
||||
$GCC -Os -g -static -o build-locale-archive %{SOURCE1} \
|
||||
$GCC -Os -g \
|
||||
%ifarch %{pie_arches}
|
||||
-fPIE \
|
||||
-static-pie \
|
||||
%else
|
||||
-static \
|
||||
%endif
|
||||
-o build-locale-archive %{SOURCE1} \
|
||||
../build-%{target}/locale/locarchive.o \
|
||||
../build-%{target}/locale/md5.o \
|
||||
../build-%{target}/locale/record-status.o \
|
||||
@ -1725,12 +1835,6 @@ $GCC -Os -g -static -o build-locale-archive %{SOURCE1} \
|
||||
install -m 700 build-locale-archive %{glibc_sysroot}%{_prefix}/sbin/build-locale-archive
|
||||
popd
|
||||
|
||||
# Lastly copy some additional documentation for the packages.
|
||||
rm -rf documentation
|
||||
mkdir documentation
|
||||
cp timezone/README documentation/README.timezone
|
||||
cp posix/gai.conf documentation/
|
||||
|
||||
%ifarch s390x
|
||||
# Compatibility symlink
|
||||
mkdir -p %{glibc_sysroot}/lib
|
||||
@ -1755,6 +1859,7 @@ cp benchtests/scripts/benchout.schema.json %{glibc_sysroot}%{_prefix}/libexec/gl
|
||||
cp benchtests/scripts/compare_bench.py %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/
|
||||
cp benchtests/scripts/import_bench.py %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/
|
||||
cp benchtests/scripts/validate_benchout.py %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/
|
||||
%endif
|
||||
|
||||
%if 0%{?_enable_debug_packages}
|
||||
# The #line directives gperf generates do not give the proper
|
||||
@ -1765,6 +1870,7 @@ popd
|
||||
pushd iconv
|
||||
ln -s ../locale/programs/charmap-kw.gperf .
|
||||
popd
|
||||
%endif
|
||||
|
||||
%if %{with docs}
|
||||
# Remove the `dir' info-heirarchy file which will be maintained
|
||||
@ -1849,6 +1955,8 @@ ar cr %{glibc_sysroot}%{_prefix}/%{_lib}/libpthread_nonshared.a
|
||||
# - Files for the nscd subpackage.
|
||||
# * devel.filelist
|
||||
# - Files for the devel subpackage.
|
||||
# * doc.filelist
|
||||
# - Files for the documentation subpackage.
|
||||
# * headers.filelist
|
||||
# - Files for the headers subpackage.
|
||||
# * static.filelist
|
||||
@ -1862,11 +1970,6 @@ ar cr %{glibc_sysroot}%{_prefix}/%{_lib}/libpthread_nonshared.a
|
||||
# - File list with the .so symbolic links for NSS packages.
|
||||
# * compat-libpthread-nonshared.filelist.
|
||||
# - File list for compat-libpthread-nonshared subpackage.
|
||||
# * debuginfo.filelist
|
||||
# - Files for the glibc debuginfo package.
|
||||
# * debuginfocommon.filelist
|
||||
# - Files for the glibc common debuginfo package.
|
||||
#
|
||||
|
||||
# Create the main file lists. This way we can append to any one of them later
|
||||
# wihtout having to create it. Note these are removed at the start of the
|
||||
@ -1875,8 +1978,10 @@ touch master.filelist
|
||||
touch glibc.filelist
|
||||
touch common.filelist
|
||||
touch utils.filelist
|
||||
touch gconv.filelist
|
||||
touch nscd.filelist
|
||||
touch devel.filelist
|
||||
touch doc.filelist
|
||||
touch headers.filelist
|
||||
touch static.filelist
|
||||
touch libnsl.filelist
|
||||
@ -1884,8 +1989,6 @@ touch nss_db.filelist
|
||||
touch nss_hesiod.filelist
|
||||
touch nss-devel.filelist
|
||||
touch compat-libpthread-nonshared.filelist
|
||||
touch debuginfo.filelist
|
||||
touch debuginfocommon.filelist
|
||||
|
||||
###############################################################################
|
||||
# Master file list, excluding a few things.
|
||||
@ -1897,10 +2000,10 @@ touch debuginfocommon.filelist
|
||||
find %{glibc_sysroot} \( -type f -o -type l \) \
|
||||
\( \
|
||||
-name etc -printf "%%%%config " -o \
|
||||
-name gconv-modules \
|
||||
-printf "%%%%verify(not md5 size mtime) %%%%config(noreplace) " -o \
|
||||
-name gconv-modules.cache \
|
||||
-printf "%%%%verify(not md5 size mtime) " \
|
||||
-printf "%%%%verify(not md5 size mtime) " -o \
|
||||
-name gconv-modules* \
|
||||
-printf "%%%%verify(not md5 size mtime) %%%%config(noreplace) " \
|
||||
, \
|
||||
! -path "*/lib/debug/*" -printf "/%%P\n" \)
|
||||
# List all directories with a %%dir prefix. We omit the info directory and
|
||||
@ -1952,6 +2055,7 @@ chmod 0444 master.filelist
|
||||
# - All bench test binaries.
|
||||
# - The aux-cache, since it's handled specially in the files section.
|
||||
# - The build-locale-archive binary since it's in the common package.
|
||||
# - Extra gconv modules. We add the required modules later.
|
||||
cat master.filelist \
|
||||
| grep -v \
|
||||
-e '%{_infodir}' \
|
||||
@ -1960,6 +2064,8 @@ cat master.filelist \
|
||||
-e '%{_libdir}/lib.*\.a' \
|
||||
-e '%{_libdir}/.*\.o' \
|
||||
-e '%{_libdir}/lib.*\.so' \
|
||||
-e '%{_libdir}/gconv/.*\.so$' \
|
||||
-e '%{_libdir}/gconv/gconv-modules.d/gconv-modules-extra\.conf$' \
|
||||
-e 'nscd' \
|
||||
-e '%{_prefix}/bin' \
|
||||
-e '%{_prefix}/lib/locale' \
|
||||
@ -1985,18 +2091,41 @@ done
|
||||
grep -e "libmemusage.so" -e "libpcprofile.so" master.filelist >> glibc.filelist
|
||||
|
||||
###############################################################################
|
||||
# glibc-devel
|
||||
# glibc-gconv-extra
|
||||
###############################################################################
|
||||
|
||||
%if %{with docs}
|
||||
# Put the info files into the devel file list, but exclude the generated dir.
|
||||
grep '%{_infodir}' master.filelist | grep -v '%{_infodir}/dir' > devel.filelist
|
||||
grep -e "gconv-modules-extra.conf" master.filelist > gconv.filelist
|
||||
|
||||
# Put the essential gconv modules into the main package.
|
||||
GconvBaseModules="ANSI_X3.110 ISO8859-15 ISO8859-1 CP1252"
|
||||
GconvBaseModules="$GconvBaseModules UNICODE UTF-16 UTF-32 UTF-7"
|
||||
%ifarch s390 s390x
|
||||
GconvBaseModules="$GconvBaseModules ISO-8859-1_CP037_Z900 UTF8_UTF16_Z9"
|
||||
GconvBaseModules="$GconvBaseModules UTF16_UTF32_Z9 UTF8_UTF32_Z9"
|
||||
%endif
|
||||
GconvAllModules=$(cat master.filelist |
|
||||
sed -n 's|%{_libdir}/gconv/\(.*\)\.so|\1|p')
|
||||
|
||||
# Put the base modules into glibc and the rest into glibc-gconv-extra
|
||||
for conv in $GconvAllModules; do
|
||||
if echo $GconvBaseModules | grep -q $conv; then
|
||||
grep -E -e "%{_libdir}/gconv/$conv.so$" \
|
||||
master.filelist >> glibc.filelist
|
||||
else
|
||||
grep -E -e "%{_libdir}/gconv/$conv.so$" \
|
||||
master.filelist >> gconv.filelist
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
###############################################################################
|
||||
# glibc-devel
|
||||
###############################################################################
|
||||
|
||||
# Put some static files into the devel package.
|
||||
grep '%{_libdir}/lib.*\.a' master.filelist \
|
||||
| grep '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \
|
||||
>> devel.filelist
|
||||
> devel.filelist
|
||||
|
||||
# Put all of the object files and *.so (not the versioned ones) into the
|
||||
# devel package.
|
||||
@ -2010,6 +2139,16 @@ sed -i -e '\,libmemusage.so,d' \
|
||||
-e '\,/libnss_[a-z]*\.so$,d' \
|
||||
devel.filelist
|
||||
|
||||
###############################################################################
|
||||
# glibc-doc
|
||||
###############################################################################
|
||||
|
||||
%if %{with docs}
|
||||
# Put the info files into the doc file list, but exclude the generated dir.
|
||||
grep '%{_infodir}' master.filelist | grep -v '%{_infodir}/dir' > doc.filelist
|
||||
grep '%{_docdir}' master.filelist >> doc.filelist
|
||||
%endif
|
||||
|
||||
###############################################################################
|
||||
# glibc-headers
|
||||
###############################################################################
|
||||
@ -2052,12 +2191,14 @@ grep '%{_prefix}/sbin' master.filelist \
|
||||
# multilib-independent.
|
||||
# Exceptions:
|
||||
# - The actual share directory, not owned by us.
|
||||
# - The info files which go in devel, and the info directory.
|
||||
# - The info files which go into doc, and the info directory.
|
||||
# - All documentation files, which go into doc.
|
||||
grep '%{_prefix}/share' master.filelist \
|
||||
| grep -v \
|
||||
-e '%{_prefix}/share/info/libc.info.*' \
|
||||
-e '%%dir %{prefix}/share/info' \
|
||||
-e '%%dir %{prefix}/share' \
|
||||
-e '%{_docdir}' \
|
||||
>> common.filelist
|
||||
|
||||
# Add the binary to build locales to the common subpackage.
|
||||
@ -2079,8 +2220,8 @@ cat > utils.filelist <<EOF
|
||||
%if %{without bootstrap}
|
||||
%{_prefix}/bin/memusage
|
||||
%{_prefix}/bin/memusagestat
|
||||
%endif
|
||||
%{_prefix}/bin/mtrace
|
||||
%endif
|
||||
%{_prefix}/bin/pcprofiledump
|
||||
%{_prefix}/bin/xtrace
|
||||
EOF
|
||||
@ -2112,6 +2253,7 @@ grep '/libnss_[a-z]*\.so$' master.filelist > nss-devel.filelist
|
||||
grep '/libnsl-[0-9.]*.so$' master.filelist > libnsl.filelist
|
||||
test $(wc -l < libnsl.filelist) -eq 1
|
||||
|
||||
%if %{with benchtests}
|
||||
###############################################################################
|
||||
# glibc-benchtests
|
||||
###############################################################################
|
||||
@ -2136,101 +2278,6 @@ echo "%{_prefix}/libexec/glibc-benchtests/validate_benchout.py*" >> benchtests.f
|
||||
###############################################################################
|
||||
echo "%{_libdir}/libpthread_nonshared.a" >> compat-libpthread-nonshared.filelist
|
||||
|
||||
###############################################################################
|
||||
# glibc-debuginfocommon, and glibc-debuginfo
|
||||
###############################################################################
|
||||
|
||||
find_debuginfo_args='--strict-build-id -g -i'
|
||||
%ifarch %{debuginfocommonarches}
|
||||
find_debuginfo_args="$find_debuginfo_args \
|
||||
-l common.filelist \
|
||||
-l utils.filelist \
|
||||
-l nscd.filelist \
|
||||
-p '.*/(sbin|libexec)/.*' \
|
||||
-o debuginfocommon.filelist \
|
||||
-l nss_db.filelist -l nss_hesiod.filelist \
|
||||
-l libnsl.filelist -l glibc.filelist \
|
||||
%if %{with benchtests}
|
||||
-l benchtests.filelist
|
||||
%endif
|
||||
"
|
||||
%endif
|
||||
|
||||
/usr/lib/rpm/find-debuginfo.sh $find_debuginfo_args -o debuginfo.filelist
|
||||
|
||||
# List all of the *.a archives in the debug directory.
|
||||
list_debug_archives()
|
||||
{
|
||||
local dir=%{_prefix}/lib/debug%{_libdir}
|
||||
find %{glibc_sysroot}$dir -name "*.a" -printf "$dir/%%P\n"
|
||||
}
|
||||
|
||||
%ifarch %{debuginfocommonarches}
|
||||
|
||||
# Remove the source files from the common package debuginfo.
|
||||
sed -i '\#^%{glibc_sysroot}%{_prefix}/src/debug/#d' debuginfocommon.filelist
|
||||
|
||||
# Create a list of all of the source files we copied to the debug directory.
|
||||
find %{glibc_sysroot}%{_prefix}/src/debug \
|
||||
\( -type d -printf '%%%%dir ' \) , \
|
||||
-printf '%{_prefix}/src/debug/%%P\n' > debuginfocommon.sources
|
||||
|
||||
%ifarch %{biarcharches}
|
||||
|
||||
# Add the source files to the core debuginfo package.
|
||||
cat debuginfocommon.sources >> debuginfo.filelist
|
||||
|
||||
%else
|
||||
|
||||
%ifarch %{ix86}
|
||||
%define basearch i686
|
||||
%endif
|
||||
%ifarch sparc sparcv9
|
||||
%define basearch sparc
|
||||
%endif
|
||||
|
||||
# The auxarches get only these few source files.
|
||||
auxarches_debugsources=\
|
||||
'/(generic|linux|%{basearch}|nptl(_db)?)/|/%{glibcsrcdir}/build|/dl-osinfo\.h'
|
||||
|
||||
# Place the source files into the core debuginfo pakcage.
|
||||
egrep "$auxarches_debugsources" debuginfocommon.sources >> debuginfo.filelist
|
||||
|
||||
# Remove the source files from the common debuginfo package.
|
||||
egrep -v "$auxarches_debugsources" \
|
||||
debuginfocommon.sources >> debuginfocommon.filelist
|
||||
|
||||
%comment Matches: %ifarch %{biarcharches}
|
||||
%endif
|
||||
|
||||
# Add the list of *.a archives in the debug directory to
|
||||
# the common debuginfo package.
|
||||
list_debug_archives >> debuginfocommon.filelist
|
||||
|
||||
%comment Matches: %ifarch %{debuginfocommonarches}
|
||||
%endif
|
||||
|
||||
# Remove some common directories from the common package debuginfo so that we
|
||||
# don't end up owning them.
|
||||
exclude_common_dirs()
|
||||
{
|
||||
exclude_dirs="%{_prefix}/src/debug"
|
||||
exclude_dirs="$exclude_dirs $(echo %{_prefix}/lib/debug{,/%{_lib},/bin,/sbin})"
|
||||
exclude_dirs="$exclude_dirs $(echo %{_prefix}/lib/debug%{_prefix}{,/%{_lib},/libexec,/bin,/sbin})"
|
||||
|
||||
for d in $(echo $exclude_dirs | sed 's/ /\n/g'); do
|
||||
sed -i "\|^%%dir $d/\?$|d" $1
|
||||
done
|
||||
}
|
||||
|
||||
%ifarch %{debuginfocommonarches}
|
||||
exclude_common_dirs debuginfocommon.filelist
|
||||
%endif
|
||||
exclude_common_dirs debuginfo.filelist
|
||||
|
||||
%comment Matches: %if 0%{?_enable_debug_packages}
|
||||
%endif
|
||||
|
||||
##############################################################################
|
||||
# Delete files that we do not intended to ship with the auxarch.
|
||||
# This is the only place where we touch the installed files after generating
|
||||
@ -2320,6 +2367,15 @@ echo ====================PLT RELOCS LIBC.SO==============
|
||||
readelf -Wr %{glibc_sysroot}/%{_lib}/libc-*.so | sed -n -e "$PLTCMD"
|
||||
echo ====================PLT RELOCS END==================
|
||||
|
||||
# Obtain a way to run the dynamic loader. Avoid matching the symbolic
|
||||
# link and then pick the first loader (although there should be only
|
||||
# one).
|
||||
run_ldso="$(find %{glibc_sysroot}/%{_lib}/ld-*.so -type f | LC_ALL=C sort | head -n1) --library-path %{glibc_sysroot}/%{_lib}"
|
||||
|
||||
# Show the auxiliary vector as seen by the new library
|
||||
# (even if we do not perform the valgrind test).
|
||||
LD_SHOW_AUXV=1 $run_ldso /bin/true
|
||||
|
||||
# Finally, check if valgrind runs with the new glibc.
|
||||
# We want to fail building if valgrind is not able to run with this glibc so
|
||||
# that we can then coordinate with valgrind to get it fixed before we update
|
||||
@ -2328,16 +2384,15 @@ pushd build-%{target}
|
||||
|
||||
# Show the auxiliary vector as seen by the new library
|
||||
# (even if we do not perform the valgrind test).
|
||||
LD_SHOW_AUXV=1 elf/ld.so --library-path .:elf:nptl:dlfcn /bin/true
|
||||
LD_SHOW_AUXV=1 $run_ldso /bin/true
|
||||
|
||||
%if %{with valgrind}
|
||||
elf/ld.so --library-path .:elf:nptl:dlfcn \
|
||||
/usr/bin/valgrind --error-exitcode=1 \
|
||||
elf/ld.so --library-path .:elf:nptl:dlfcn /usr/bin/true
|
||||
$run_ldso /usr/bin/valgrind --error-exitcode=1 \
|
||||
$run_ldso /usr/bin/true
|
||||
%endif
|
||||
popd
|
||||
|
||||
%comment Matches: %if %{run_glibc_tests}
|
||||
%comment Matches: %if %{with testsuite}
|
||||
%endif
|
||||
|
||||
|
||||
@ -2350,17 +2405,7 @@ if rpm.vercmp(rel, required) < 0 then
|
||||
end
|
||||
|
||||
%post -p <lua>
|
||||
-- We use lua's posix.exec because there may be no shell that we can
|
||||
-- run during glibc upgrade.
|
||||
function post_exec (program, ...)
|
||||
local pid = posix.fork ()
|
||||
if pid == 0 then
|
||||
assert (posix.exec (program, ...))
|
||||
elseif pid > 0 then
|
||||
posix.wait (pid)
|
||||
end
|
||||
end
|
||||
|
||||
%glibc_post_funcs
|
||||
-- (1) Remove multilib libraries from previous installs.
|
||||
-- In order to support in-place upgrades, we must immediately remove
|
||||
-- obsolete platform directories after installing a new glibc
|
||||
@ -2469,16 +2514,7 @@ post_exec ("%{_prefix}/sbin/ldconfig")
|
||||
-- We assume that the cache is in _libdir/gconv and called
|
||||
-- "gconv-modules.cache".
|
||||
|
||||
local iconv_dir = "%{_libdir}/gconv"
|
||||
local iconv_cache = iconv_dir .. "/gconv-modules.cache"
|
||||
if (posix.utime (iconv_cache) == 0) then
|
||||
post_exec ("%{_prefix}/sbin/iconvconfig",
|
||||
"-o", iconv_cache,
|
||||
"--nostdlib",
|
||||
iconv_dir)
|
||||
else
|
||||
io.stdout:write ("Error: Missing " .. iconv_cache .. " file.\n")
|
||||
end
|
||||
update_gconv_modules_cache()
|
||||
|
||||
%posttrans all-langpacks -e -p <lua>
|
||||
-- If at the end of the transaction we are still installed
|
||||
@ -2519,6 +2555,14 @@ if [ "$1" = 0 ]; then
|
||||
fi
|
||||
%endif
|
||||
|
||||
%post gconv-extra -p <lua>
|
||||
%glibc_post_funcs
|
||||
update_gconv_modules_cache ()
|
||||
|
||||
%postun gconv-extra -p <lua>
|
||||
%glibc_post_funcs
|
||||
update_gconv_modules_cache ()
|
||||
|
||||
%pre -n nscd
|
||||
getent group nscd >/dev/null || /usr/sbin/groupadd -g 28 -r nscd
|
||||
getent passwd nscd >/dev/null ||
|
||||
@ -2551,11 +2595,11 @@ fi
|
||||
%dir /etc/ld.so.conf.d
|
||||
%dir %{_prefix}/libexec/getconf
|
||||
%dir %{_libdir}/gconv
|
||||
%dir %{_libdir}/gconv/gconv-modules.d
|
||||
%dir %attr(0700,root,root) /var/cache/ldconfig
|
||||
%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/cache/ldconfig/aux-cache
|
||||
%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/ld.so.cache
|
||||
%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/gai.conf
|
||||
%doc README NEWS INSTALL elf/rtld-debugger-interface.txt
|
||||
# If rpm doesn't support %license, then use %doc instead.
|
||||
%{!?_licensedir:%global license %%doc}
|
||||
%license COPYING COPYING.LIB LICENSES
|
||||
@ -2565,8 +2609,6 @@ fi
|
||||
%dir %{_prefix}/lib/locale
|
||||
%dir %{_prefix}/lib/locale/C.utf8
|
||||
%{_prefix}/lib/locale/C.utf8/*
|
||||
%doc documentation/README.timezone
|
||||
%doc documentation/gai.conf
|
||||
|
||||
%files all-langpacks
|
||||
%attr(0644,root,root) %verify(not md5 size mtime) %{_prefix}/lib/locale/locale-archive.tmpl
|
||||
@ -2580,12 +2622,18 @@ fi
|
||||
|
||||
%files -f devel.filelist devel
|
||||
|
||||
%if %{with docs}
|
||||
%files -f doc.filelist doc
|
||||
%endif
|
||||
|
||||
%files -f static.filelist static
|
||||
|
||||
%files -f headers.filelist headers
|
||||
|
||||
%files -f utils.filelist utils
|
||||
|
||||
%files -f gconv.filelist gconv-extra
|
||||
|
||||
%files -f nscd.filelist -n nscd
|
||||
%config(noreplace) /etc/nscd.conf
|
||||
%dir %attr(0755,root,root) /var/run/nscd
|
||||
@ -2615,15 +2663,6 @@ fi
|
||||
%files -f libnsl.filelist -n libnsl
|
||||
/%{_lib}/libnsl.so.1
|
||||
|
||||
%if 0%{?_enable_debug_packages}
|
||||
%files debuginfo -f debuginfo.filelist
|
||||
%ifarch %{debuginfocommonarches}
|
||||
%ifnarch %{auxarches}
|
||||
%files debuginfo-common -f debuginfocommon.filelist
|
||||
%endif
|
||||
%endif
|
||||
%endif
|
||||
|
||||
%if %{with benchtests}
|
||||
%files benchtests -f benchtests.filelist
|
||||
%endif
|
||||
@ -2631,6 +2670,89 @@ fi
|
||||
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
|
||||
|
||||
%changelog
|
||||
* Thu Jan 27 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-189
|
||||
- CVE-2021-3999: getcwd: align stack on clone in aarch64 and fix a memory leak
|
||||
(#2032281)
|
||||
|
||||
* Tue Jan 25 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-188
|
||||
- CVE-2022-23218, CVE-2022-23219: Fix buffer overflows in sunrpc clnt_create
|
||||
for "unix" and svcunix_create (#2045063).
|
||||
|
||||
* Mon Jan 24 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-187
|
||||
- CVE-2021-3999: getcwd: Set errno to ERANGE for size == 1 (#2032281)
|
||||
|
||||
* Fri Jan 21 2022 Carlos O'Donell <carlos@redhat.com> - 2.28-186
|
||||
- Fix pthread_once regression with C++ exceptions (#2007327)
|
||||
|
||||
* Thu Jan 20 2022 DJ Delorie <dj@redhat.com> - 2.28-185
|
||||
- Adjust to rpm's find-debuginfo.sh changes, to keep stripping binaries (#1661513)
|
||||
|
||||
* Fri Jan 7 2022 Florian Weimer <fweimer@redhat.com> - 2.28-184
|
||||
- Conversion from ISO-2022-JP-3 may emit spurious NUL character (#2033655)
|
||||
|
||||
* Fri Jan 7 2022 Florian Weimer <fweimer@redhat.com> - 2.28-183
|
||||
- aarch64: A64FX optimizations break "sve=off" guest mode (#2036955)
|
||||
|
||||
* Fri Jan 7 2022 Patsy Griffin <patsy@redhat.com> - 2.28-182
|
||||
- Handle truncated timezones from tzcode-2021d and later. (#2033648)
|
||||
|
||||
* Tue Jan 4 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-181
|
||||
- Weaken dependency of glibc on glibc-gconv-extra (#2015768)
|
||||
|
||||
* Mon Dec 13 2021 Florian Weimer <fweimer@redhat.com> - 2.28-180
|
||||
- Do not install /usr/lib/debug/usr/bin/ld.so.debug (#2023420)
|
||||
|
||||
* Fri Dec 10 2021 Florian Weimer <fweimer@redhat.com> - 2.28-179
|
||||
- Add /usr/bin/ld.so --list-diagnostics (#2023420)
|
||||
|
||||
* Fri Dec 10 2021 Carlos O'Donell <carlos@redhat.com> - 2.28-178
|
||||
- Preliminary support for new IBM zSeries hardware (#1984802)
|
||||
|
||||
* Fri Dec 10 2021 Carlos O'Donell <carlos@redhat.com> - 2.28-177
|
||||
- Fix --with and --without builds for benchtests and bootstrap (#2020989)
|
||||
|
||||
* Wed Dec 1 2021 Florian Weimer <fweimer@redhat.com> - 2.28-176
|
||||
- A64FX memcpy/memmove/memset optimizations (#1929928)
|
||||
|
||||
* Tue Nov 30 2021 Florian Weimer <fweimer@redhat.com> - 2.28-175
|
||||
- Fix dl-tls.c assert failure with pthread_create & dlopen (#1991001)
|
||||
- Fix x86_64 TLS lazy binding with auditors (#1950056)
|
||||
|
||||
* Thu Nov 25 2021 Arjun Shankar <arjun@redhat.com> - 2.28-174
|
||||
- Introduce new glibc-doc.noarch subpackage (#2021671)
|
||||
- Move the reference manual info pages from glibc-devel to glibc-doc
|
||||
- Move debugger interface documentation from glibc to glibc-doc
|
||||
- Remove unnecessary README, INSTALL, NEWS files from glibc
|
||||
- Remove unnecessary README.timezone and gai.conf files from glibc-common
|
||||
|
||||
* Wed Nov 17 2021 Patsy Griffin <patsy@redhat.com> - 2.28-173
|
||||
- Add new English-language 12 hour time locale en_US@ampm.UTF-8 (#2000374)
|
||||
|
||||
* Tue Nov 16 2021 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-172
|
||||
- Build build-locale-archive with -static-pie when supported (#1965377)
|
||||
|
||||
* Wed Nov 10 2021 DJ Delorie <dj@redhat.com> - 2.28-171
|
||||
- elf: Always set link map in _dl_init_paths (#1934162)
|
||||
|
||||
* Wed Nov 10 2021 Arjun Shankar <arjun@redhat.com> - 2.28-170
|
||||
- x86: Properly disable XSAVE related features when its use is disabled via
|
||||
tunables (#1937515)
|
||||
|
||||
* Wed Nov 10 2021 Arjun Shankar <arjun@redhat.com> - 2.28-169
|
||||
- s390: Use long branches across object boundaries (#2021452)
|
||||
|
||||
* Fri Oct 29 2021 Arjun Shankar <arjun@redhat.com> - 2.28-168
|
||||
- Optimize memcmp, strcpy, and stpcpy for IBM POWER10 (#1983203)
|
||||
|
||||
* Wed Oct 13 2021 Arjun Shankar <arjun@redhat.com> - 2.28-167
|
||||
- malloc: Initiate tcache shutdown even without allocations (#1977614)
|
||||
|
||||
* Wed Oct 13 2021 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-166
|
||||
- Fix debuginfo location for gconv-extra and make glibc Require it (#1971664).
|
||||
|
||||
* Wed Oct 6 2021 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-165
|
||||
- Split extra gconv modules into a separate package (#1971664).
|
||||
|
||||
* Mon Aug 9 2021 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-164
|
||||
- librt: fix NULL pointer dereference (#1966472).
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user