forked from pool/glibc
Accepting request 992472 from home:Andreas_Schwab:Factory
- Update to glibc 2.36 Major new features: * Support for DT_RELR relative relocation format has been added to glibc * On Linux, the pidfd_open, pidfd_getfd, and pidfd_send_signal functions have been added * On Linux, the process_madvise function has been added * On Linux, the process_mrelease function has been added * The “no-aaaa” DNS stub resolver option has been added * On Linux, the fsopen, fsmount, move_mount, fsconfig, fspick, open_tree, and mount_setattr have been added * localedef now accepts locale definition files encoded in UTF-8 * Support for the mbrtoc8 and c8rtomb multibyte/UTF-8 character conversion functions has been added per the ISO C2X N2653 and C++20 P0482R6 proposals * The functions arc4random, arc4random_buf, and arc4random_uniform have been added Deprecated and removed features, and other changes affecting compatibility: * Support for prelink will be removed in the next release * The Linux kernel version check has been removed along with the LD_ASSUME_KERNEL environment variable * On Linux, The LD_LIBRARY_VERSION environment variable has been removed - get-nprocs-sched-uninit-read.patch, get-nprocs-inaccurate.patch, strcmp-rtm-fallback.path, pt-load-invalid-hole.patch, localedef-ld-monetary.patch, nptl-spurious-eintr.patch, strncpy-power9-vsx.patch, nptl-cleanup-async-restore.patch, read-chk-cancel.patch, wcrtomb-fortify.patch, nptl-cleanup-async-restore-2.patch: Removed OBS-URL: https://build.opensuse.org/request/show/992472 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=623
This commit is contained in:
parent
0432c11393
commit
c370aa9ab8
@ -1,199 +0,0 @@
|
||||
From 491f2ef1f0ff849490f374917957018d07ee0586 Mon Sep 17 00:00:00 2001
|
||||
From: "Dmitry V. Levin" <ldv@altlinux.org>
|
||||
Date: Sat, 5 Feb 2022 08:00:00 +0000
|
||||
Subject: [PATCH] linux: fix accuracy of get_nprocs and get_nprocs_conf [BZ
|
||||
#28865]
|
||||
|
||||
get_nprocs() and get_nprocs_conf() use various methods to obtain an
|
||||
accurate number of processors. Re-introduce __get_nprocs_sched() as
|
||||
a source of information, and fix the order in which these methods are
|
||||
used to return the most accurate information. The primary source of
|
||||
information used in both functions remains unchanged.
|
||||
|
||||
This also changes __get_nprocs_sched() error return value from 2 to 0,
|
||||
but all its users are already prepared to handle that.
|
||||
|
||||
Old fallback order:
|
||||
get_nprocs:
|
||||
/sys/devices/system/cpu/online -> /proc/stat -> 2
|
||||
get_nprocs_conf:
|
||||
/sys/devices/system/cpu/ -> /proc/stat -> 2
|
||||
|
||||
New fallback order:
|
||||
get_nprocs:
|
||||
/sys/devices/system/cpu/online -> /proc/stat -> sched_getaffinity -> 2
|
||||
get_nprocs_conf:
|
||||
/sys/devices/system/cpu/ -> /proc/stat -> sched_getaffinity -> 2
|
||||
|
||||
Fixes: 342298278e ("linux: Revert the use of sched_getaffinity on get_nproc")
|
||||
Closes: BZ #28865
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
(cherry picked from commit e1d32b836410767270a3adf1f82b1a47e6e4cd51)
|
||||
---
|
||||
NEWS | 2 +
|
||||
sysdeps/unix/sysv/linux/getsysstats.c | 94 ++++++++++++++++++---------
|
||||
2 files changed, 65 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
|
||||
index c98c8ce3d4..d1ea074f0d 100644
|
||||
--- a/sysdeps/unix/sysv/linux/getsysstats.c
|
||||
+++ b/sysdeps/unix/sysv/linux/getsysstats.c
|
||||
@@ -50,9 +50,8 @@ __get_nprocs_sched (void)
|
||||
is an arbitrary values assuming such systems should be rare and there
|
||||
is no offline cpus. */
|
||||
return max_num_cpus;
|
||||
- /* Some other error. 2 is conservative (not a uniprocessor system, so
|
||||
- atomics are needed). */
|
||||
- return 2;
|
||||
+ /* Some other error. */
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
@@ -108,22 +107,19 @@ next_line (int fd, char *const buffer, char **cp, char **re,
|
||||
}
|
||||
|
||||
static int
|
||||
-get_nproc_stat (char *buffer, size_t buffer_size)
|
||||
+get_nproc_stat (void)
|
||||
{
|
||||
+ enum { buffer_size = 1024 };
|
||||
+ char buffer[buffer_size];
|
||||
char *buffer_end = buffer + buffer_size;
|
||||
char *cp = buffer_end;
|
||||
char *re = buffer_end;
|
||||
-
|
||||
- /* Default to an SMP system in case we cannot obtain an accurate
|
||||
- number. */
|
||||
- int result = 2;
|
||||
+ int result = 0;
|
||||
|
||||
const int flags = O_RDONLY | O_CLOEXEC;
|
||||
int fd = __open_nocancel ("/proc/stat", flags);
|
||||
if (fd != -1)
|
||||
{
|
||||
- result = 0;
|
||||
-
|
||||
char *l;
|
||||
while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
|
||||
/* The current format of /proc/stat has all the cpu* entries
|
||||
@@ -139,8 +135,8 @@ get_nproc_stat (char *buffer, size_t buffer_size)
|
||||
return result;
|
||||
}
|
||||
|
||||
-int
|
||||
-__get_nprocs (void)
|
||||
+static int
|
||||
+get_nprocs_cpu_online (void)
|
||||
{
|
||||
enum { buffer_size = 1024 };
|
||||
char buffer[buffer_size];
|
||||
@@ -179,7 +175,8 @@ __get_nprocs (void)
|
||||
}
|
||||
}
|
||||
|
||||
- result += m - n + 1;
|
||||
+ if (m >= n)
|
||||
+ result += m - n + 1;
|
||||
|
||||
l = endp;
|
||||
if (l < re && *l == ',')
|
||||
@@ -188,28 +185,18 @@ __get_nprocs (void)
|
||||
while (l < re && *l != '\n');
|
||||
|
||||
__close_nocancel_nostatus (fd);
|
||||
-
|
||||
- if (result > 0)
|
||||
- return result;
|
||||
}
|
||||
|
||||
- return get_nproc_stat (buffer, buffer_size);
|
||||
+ return result;
|
||||
}
|
||||
-libc_hidden_def (__get_nprocs)
|
||||
-weak_alias (__get_nprocs, get_nprocs)
|
||||
-
|
||||
|
||||
-/* On some architectures it is possible to distinguish between configured
|
||||
- and active cpus. */
|
||||
-int
|
||||
-__get_nprocs_conf (void)
|
||||
+static int
|
||||
+get_nprocs_cpu (void)
|
||||
{
|
||||
- /* Try to use the sysfs filesystem. It has actual information about
|
||||
- online processors. */
|
||||
+ int count = 0;
|
||||
DIR *dir = __opendir ("/sys/devices/system/cpu");
|
||||
if (dir != NULL)
|
||||
{
|
||||
- int count = 0;
|
||||
struct dirent64 *d;
|
||||
|
||||
while ((d = __readdir64 (dir)) != NULL)
|
||||
@@ -224,12 +211,57 @@ __get_nprocs_conf (void)
|
||||
|
||||
__closedir (dir);
|
||||
|
||||
- return count;
|
||||
}
|
||||
+ return count;
|
||||
+}
|
||||
|
||||
- enum { buffer_size = 1024 };
|
||||
- char buffer[buffer_size];
|
||||
- return get_nproc_stat (buffer, buffer_size);
|
||||
+static int
|
||||
+get_nprocs_fallback (void)
|
||||
+{
|
||||
+ int result;
|
||||
+
|
||||
+ /* Try /proc/stat first. */
|
||||
+ result = get_nproc_stat ();
|
||||
+ if (result != 0)
|
||||
+ return result;
|
||||
+
|
||||
+ /* Try sched_getaffinity. */
|
||||
+ result = __get_nprocs_sched ();
|
||||
+ if (result != 0)
|
||||
+ return result;
|
||||
+
|
||||
+ /* We failed to obtain an accurate number. Be conservative: return
|
||||
+ the smallest number meaning that this is not a uniprocessor system,
|
||||
+ so atomics are needed. */
|
||||
+ return 2;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+__get_nprocs (void)
|
||||
+{
|
||||
+ /* Try /sys/devices/system/cpu/online first. */
|
||||
+ int result = get_nprocs_cpu_online ();
|
||||
+ if (result != 0)
|
||||
+ return result;
|
||||
+
|
||||
+ /* Fall back to /proc/stat and sched_getaffinity. */
|
||||
+ return get_nprocs_fallback ();
|
||||
+}
|
||||
+libc_hidden_def (__get_nprocs)
|
||||
+weak_alias (__get_nprocs, get_nprocs)
|
||||
+
|
||||
+/* On some architectures it is possible to distinguish between configured
|
||||
+ and active cpus. */
|
||||
+int
|
||||
+__get_nprocs_conf (void)
|
||||
+{
|
||||
+ /* Try /sys/devices/system/cpu/ first. */
|
||||
+ int result = get_nprocs_cpu ();
|
||||
+ if (result != 0)
|
||||
+ return result;
|
||||
+
|
||||
+ /* Fall back to /proc/stat and sched_getaffinity. */
|
||||
+ return get_nprocs_fallback ();
|
||||
}
|
||||
libc_hidden_def (__get_nprocs_conf)
|
||||
weak_alias (__get_nprocs_conf, get_nprocs_conf)
|
||||
--
|
||||
2.35.0
|
||||
|
@ -1,33 +0,0 @@
|
||||
From a2f1675634b3513c09c38e55e6766e8c05768b1f Mon Sep 17 00:00:00 2001
|
||||
From: Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>
|
||||
Date: Tue, 1 Feb 2022 22:39:02 +0000
|
||||
Subject: [PATCH] linux: __get_nprocs_sched: do not feed CPU_COUNT_S with
|
||||
garbage [BZ #28850]
|
||||
|
||||
Pass the actual number of bytes returned by the kernel.
|
||||
|
||||
Fixes: 33099d72e41c ("linux: Simplify get_nprocs")
|
||||
Reviewed-by: Dmitry V. Levin <ldv@altlinux.org>
|
||||
|
||||
(cherry picked from commit 97ba273b505763325efd802dc3a9562dbba79579)
|
||||
---
|
||||
NEWS | 1 +
|
||||
sysdeps/unix/sysv/linux/getsysstats.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
|
||||
index 4798cc337e..c98c8ce3d4 100644
|
||||
--- a/sysdeps/unix/sysv/linux/getsysstats.c
|
||||
+++ b/sysdeps/unix/sysv/linux/getsysstats.c
|
||||
@@ -44,7 +44,7 @@ __get_nprocs_sched (void)
|
||||
int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, cpu_bits_size,
|
||||
cpu_bits);
|
||||
if (r > 0)
|
||||
- return CPU_COUNT_S (cpu_bits_size, (cpu_set_t*) cpu_bits);
|
||||
+ return CPU_COUNT_S (r, (cpu_set_t*) cpu_bits);
|
||||
else if (r == -EINVAL)
|
||||
/* The input buffer is still not enough to store the number of cpus. This
|
||||
is an arbitrary values assuming such systems should be rare and there
|
||||
--
|
||||
2.35.0
|
||||
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5123732f6b67ccd319305efd399971d58592122bcc2a6518a1bd2510dd0cf52e
|
||||
size 18165952
|
@ -1,16 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCAAdFiEEcnNUKzmWLfeymZMUFnkrTqJTQPgFAmH7d7IACgkQFnkrTqJT
|
||||
QPgoHBAAlQTCY/HD1Hpro1NaUT8nS0zzB1gw13soniPMdBtJvDTOVZhWkOSto1wg
|
||||
9z5Tr/JmmnYCE6iu8npYRjkFRXTkPu+mazNcVvwTg08bb0LVn0q4IYHCkrJTLfZi
|
||||
44fiG76SZOkh/+OTvqNfilWX62zJc1SeMIUy4O1OaPfBA4eZ4hjplOSjJLXG3Hu7
|
||||
SZAp7yrTjz4qKJ0rWhGqqfGI7OsT34q3bnAWBRtzPFz+OesLgsLthOAik9vyuuTq
|
||||
KnBumMmGforja2YToNDa1dkRi7iggDRrUrfi0fBraGXNUMab/QcwifV6gt+bQ/gH
|
||||
CCalirxD1AQZnRQ/3aVAHE3L2u9fZzGIqbGpkCLhY6M35DKQoZTcW9nR3HfHcnZS
|
||||
jpiPTu+ONiL0DTdqGAssgfYqP3cIQFEaX7XOpN6qldpuK2d8oJ6JbihIbT6yX/fn
|
||||
3DYvFbJYSVCW+DN9FL1eMHHVP3R2YPoQ6FS5Iud0W6/p9NGPNYLoFrceZD08yms+
|
||||
0HrxYiAb8YDgqk7M5eMSXdcaz2+uRCSTjZHZeGKhJK/5/x7LYAoCgvad5oy+K2pR
|
||||
fdGxIUfVzJ3LrZRk6/7EbaQGYW07gV3uA0aRfdGQ3UL3xBHhQHEnnRDVpRHHsdSI
|
||||
1mEj5jT7EEBJwEyppTZXOdTFHeV3ZPeC52rwLO0tQDku9Dn4R8U=
|
||||
=vosd
|
||||
-----END PGP SIGNATURE-----
|
3
glibc-2.36.tar.xz
Normal file
3
glibc-2.36.tar.xz
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1c959fea240906226062cb4b1e7ebce71a9f0e3c0836c09e7e3423d434fcfe75
|
||||
size 18610836
|
16
glibc-2.36.tar.xz.sig
Normal file
16
glibc-2.36.tar.xz.sig
Normal file
@ -0,0 +1,16 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCAAdFiEEcnNUKzmWLfeymZMUFnkrTqJTQPgFAmLoeDoACgkQFnkrTqJT
|
||||
QPg4aBAAi49jj5b+KYLEPqwqvBL9o9lF6EX66sxmvcTL/ygZcAGFy2Px3sKfZQpC
|
||||
0cFuVJNGOXJkbFg+jNzK5pPUWx1NLtYYyhHrIvIBYaAJnJsLNNfIullqOI4doJsY
|
||||
uXczpqAmwvlAwYdlZMLoTYVtxS80Td27gk+cL/Uk8gEbJANu1iL/G3ruKwb42jD9
|
||||
dutEFDaTn6tD4rT0yB92rY3UMH7M2SuNertkhO+10utPNMIwEaaIk28Wa+2Q80xc
|
||||
R+ALx36O4RQ5NWfOCnw3nrusEFd2dAHEI5mwBpjyCDaZ/XA3QuURjHzcT4jWF3Df
|
||||
HIi5ED1fbVQpG6gM9V7cfay6hwacDtjoDfEhx3vN4m9l4LD7ySrgh0zrfo9EzO6a
|
||||
prD1OFA+tgWEA1RoQcuoP5WQ0PloLApX758cQd7XhGPkx2vceffpifpxWiSZXVk0
|
||||
Y7u6muq2S3/qzQHHu61ERmNpEYesGEZlXLxvuJvosEmssmYAMTLj7tFTPyIppMDw
|
||||
aOuNX8Qen5ri4bPrBtibAry02n1NTZ/4IAhHc0WbHUMHqZv2BRmXqj0mP48++Jx/
|
||||
BDnJynprKf6yfShhp/6bDXue7eLev21VJH/0GQdppU9f7L/CMlQBI55RLf3fEnw+
|
||||
pgmojWTrDp7R7TnTEglb2bTdPvbOx4YKNlTUYURcJGexiF5ydVE=
|
||||
=EyZe
|
||||
-----END PGP SIGNATURE-----
|
@ -1,3 +1,34 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Aug 2 07:41:38 UTC 2022 - Andreas Schwab <schwab@suse.de>
|
||||
|
||||
- Update to glibc 2.36
|
||||
Major new features:
|
||||
* Support for DT_RELR relative relocation format has been added to
|
||||
glibc
|
||||
* On Linux, the pidfd_open, pidfd_getfd, and pidfd_send_signal functions
|
||||
have been added
|
||||
* On Linux, the process_madvise function has been added
|
||||
* On Linux, the process_mrelease function has been added
|
||||
* The “no-aaaa” DNS stub resolver option has been added
|
||||
* On Linux, the fsopen, fsmount, move_mount, fsconfig, fspick, open_tree,
|
||||
and mount_setattr have been added
|
||||
* localedef now accepts locale definition files encoded in UTF-8
|
||||
* Support for the mbrtoc8 and c8rtomb multibyte/UTF-8 character conversion
|
||||
functions has been added per the ISO C2X N2653 and C++20 P0482R6 proposals
|
||||
* The functions arc4random, arc4random_buf, and arc4random_uniform have been
|
||||
added
|
||||
Deprecated and removed features, and other changes affecting compatibility:
|
||||
* Support for prelink will be removed in the next release
|
||||
* The Linux kernel version check has been removed along with the
|
||||
LD_ASSUME_KERNEL environment variable
|
||||
* On Linux, The LD_LIBRARY_VERSION environment variable has been removed
|
||||
- get-nprocs-sched-uninit-read.patch, get-nprocs-inaccurate.patch,
|
||||
strcmp-rtm-fallback.path, pt-load-invalid-hole.patch,
|
||||
localedef-ld-monetary.patch, nptl-spurious-eintr.patch,
|
||||
strncpy-power9-vsx.patch, nptl-cleanup-async-restore.patch,
|
||||
read-chk-cancel.patch, wcrtomb-fortify.patch,
|
||||
nptl-cleanup-async-restore-2.patch: Removed
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Jul 14 11:21:34 UTC 2022 - Andreas Schwab <schwab@suse.de>
|
||||
|
||||
|
112
glibc.spec
112
glibc.spec
@ -93,43 +93,6 @@ ExcludeArch: %{cross_arch}
|
||||
%define name_suffix -%{flavor}-src
|
||||
%endif
|
||||
|
||||
Name: glibc%{name_suffix}
|
||||
Summary: Standard Shared Libraries (from the GNU C Library)
|
||||
License: GPL-2.0-or-later AND LGPL-2.1-or-later AND LGPL-2.1-or-later WITH GCC-exception-2.0
|
||||
Group: System/Libraries
|
||||
BuildRequires: audit-devel
|
||||
BuildRequires: bison
|
||||
BuildRequires: fdupes
|
||||
BuildRequires: libcap-devel
|
||||
BuildRequires: libselinux-devel
|
||||
BuildRequires: makeinfo
|
||||
BuildRequires: python3-base
|
||||
BuildRequires: shadow
|
||||
BuildRequires: systemd-rpm-macros
|
||||
BuildRequires: systemtap-headers
|
||||
BuildRequires: xz
|
||||
%if %{build_testsuite}
|
||||
BuildRequires: gcc-c++
|
||||
BuildRequires: gdb
|
||||
BuildRequires: glibc-devel-static
|
||||
BuildRequires: libidn2-0
|
||||
BuildRequires: libstdc++-devel
|
||||
BuildRequires: python3-pexpect
|
||||
%endif
|
||||
%if %{build_utils}
|
||||
BuildRequires: gd-devel
|
||||
BuildRequires: libpng-devel
|
||||
BuildRequires: zlib-devel
|
||||
%endif
|
||||
%if %{build_cross}
|
||||
BuildRequires: cross-%{cross_arch}-gcc%{gcc_version}-bootstrap
|
||||
BuildRequires: cross-%{cross_arch}-linux-glibc-devel
|
||||
%endif
|
||||
%if "%flavor" == "i686"
|
||||
ExclusiveArch: i586 i686
|
||||
BuildArch: i686
|
||||
%endif
|
||||
|
||||
%define __filter_GLIBC_PRIVATE 1
|
||||
%ifarch i686
|
||||
# For i686 let's only build what's different from i586, so
|
||||
@ -170,10 +133,14 @@ BuildArch: i686
|
||||
%define enablekernel 4.15
|
||||
%endif
|
||||
|
||||
Version: 2.35
|
||||
Name: glibc%{name_suffix}
|
||||
Summary: Standard Shared Libraries (from the GNU C Library)
|
||||
License: GPL-2.0-or-later AND LGPL-2.1-or-later AND LGPL-2.1-or-later WITH GCC-exception-2.0
|
||||
Group: System/Libraries
|
||||
Version: 2.36
|
||||
Release: 0
|
||||
%if !%{build_snapshot}
|
||||
%define git_id f94f6d8a35
|
||||
%define git_id c804cd1c00
|
||||
%define libversion %version
|
||||
%else
|
||||
%define git_id %(echo %version | sed 's/.*\.g//')
|
||||
@ -228,7 +195,38 @@ Provides: rtld(GNU_HASH)
|
||||
Requires: glibc = %{version}
|
||||
%endif
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
#
|
||||
BuildRequires: audit-devel
|
||||
BuildRequires: bison
|
||||
BuildRequires: fdupes
|
||||
BuildRequires: libcap-devel
|
||||
BuildRequires: libselinux-devel
|
||||
BuildRequires: makeinfo
|
||||
BuildRequires: python3-base
|
||||
BuildRequires: shadow
|
||||
BuildRequires: systemd-rpm-macros
|
||||
BuildRequires: systemtap-headers
|
||||
BuildRequires: xz
|
||||
%if %{build_testsuite}
|
||||
BuildRequires: gcc-c++
|
||||
BuildRequires: gdb
|
||||
BuildRequires: glibc-devel-static
|
||||
BuildRequires: libidn2-0
|
||||
BuildRequires: libstdc++-devel
|
||||
BuildRequires: python3-pexpect
|
||||
%endif
|
||||
%if %{build_utils}
|
||||
BuildRequires: gd-devel
|
||||
BuildRequires: libpng-devel
|
||||
BuildRequires: zlib-devel
|
||||
%endif
|
||||
%if %{build_cross}
|
||||
BuildRequires: cross-%{cross_arch}-gcc%{gcc_version}-bootstrap
|
||||
BuildRequires: cross-%{cross_arch}-linux-glibc-devel
|
||||
%endif
|
||||
%if "%flavor" == "i686"
|
||||
ExclusiveArch: i586 i686
|
||||
BuildArch: i686
|
||||
%endif
|
||||
|
||||
###
|
||||
# Patches are ordered in the following groups:
|
||||
@ -283,28 +281,6 @@ Patch306: glibc-fix-double-loopback.diff
|
||||
###
|
||||
# Patches from upstream
|
||||
###
|
||||
# PATCH-FIX-UPSTREAM linux: __get_nprocs_sched: do not feed CPU_COUNT_S with garbage (BZ #28850)
|
||||
Patch1000: get-nprocs-sched-uninit-read.patch
|
||||
# PATCH-FIX-UPSTREAM linux: fix accuracy of get_nprocs and get_nprocs_conf (BZ #28865)
|
||||
Patch1001: get-nprocs-inaccurate.patch
|
||||
# PATCH-FIX-UPSTREAM x86: Fallback {str|wcs}cmp RTM in the ncmp overflow case (BZ #28896)
|
||||
Patch1002: strcmp-rtm-fallback.path
|
||||
# PATCH-FIX-UPSTREAM elf: Check invalid hole in PT_LOAD segments (BZ #28838)
|
||||
Patch1003: pt-load-invalid-hole.patch
|
||||
# PATCH-FIX-UPSTREAM localedef: Update LC_MONETARY handling (BZ #28845)
|
||||
Patch1004: localedef-ld-monetary.patch
|
||||
# PATCH-FIX-UPSTREAM nptl: Handle spurious EINTR when thread cancellation is disabled (BZ #29029)
|
||||
Patch1005: nptl-spurious-eintr.patch
|
||||
# PATCH-FIX-UPSTREAM powerpc: Fix VSX register number on __strncpy_power9 (BZ #29197)
|
||||
Patch1006: strncpy-power9-vsx.patch
|
||||
# PATCH-FIX-UPSTREAM nptl: Fix __libc_cleanup_pop_restore asynchronous restore (BZ #29214)
|
||||
Patch1007: nptl-cleanup-async-restore.patch
|
||||
# PATCH-FIX-UPSTREAM debug: make __read_chk a cancellation point (BZ #29274)
|
||||
Patch1008: read-chk-cancel.patch
|
||||
# PATCH-FIX-UPSTREAM wcrtomb: Make behavior POSIX compliant
|
||||
Patch1009: wcrtomb-fortify.patch
|
||||
# PATCH-FIX-UPSTREAM nptl: Fix ___pthread_unregister_cancel_restore asynchronous restore (BZ #29214)
|
||||
Patch1010: nptl-cleanup-async-restore-2.patch
|
||||
|
||||
###
|
||||
# Patches awaiting upstream approval
|
||||
@ -528,18 +504,6 @@ library in a cross compilation setting.
|
||||
%patch304 -p1
|
||||
%patch306 -p1
|
||||
|
||||
%patch1000 -p1
|
||||
%patch1001 -p1
|
||||
%patch1002 -p1
|
||||
%patch1003 -p1
|
||||
%patch1004 -p1
|
||||
%patch1005 -p1
|
||||
%patch1006 -p1
|
||||
%patch1007 -p1
|
||||
%patch1008 -p1
|
||||
%patch1009 -p1
|
||||
%patch1010 -p1
|
||||
|
||||
%patch2000 -p1
|
||||
%patch2001 -p1
|
||||
|
||||
|
@ -1,302 +0,0 @@
|
||||
From 3feecd80013c822a12d4b01c5c25e155dfbc6e2f Mon Sep 17 00:00:00 2001
|
||||
From: Carlos O'Donell <carlos@redhat.com>
|
||||
Date: Thu, 3 Feb 2022 16:51:59 -0500
|
||||
Subject: [PATCH] localedef: Update LC_MONETARY handling (Bug 28845)
|
||||
|
||||
ISO C17, POSIX Issue 7, and ISO 30112 all allow the char*
|
||||
types to be empty strings i.e. "", integer or char values to
|
||||
be -1 or CHAR_MAX respectively, with the exception of
|
||||
decimal_point which must be non-empty in ISO C. Note that
|
||||
the defaults for mon_grouping vary, but are functionaly
|
||||
equivalent e.g. "\177" (no further grouping reuqired) vs.
|
||||
"" (no grouping defined for all groups).
|
||||
|
||||
We include a broad comment talking about harmonizing ISO C,
|
||||
POSIX, ISO 30112, and the default C/POSIX locale for glibc.
|
||||
|
||||
We reorder all setting based on locale/categories.def order.
|
||||
|
||||
We soften all missing definitions from errors to warnings when
|
||||
defaults exist.
|
||||
|
||||
Given that ISO C, POSIX and ISO 30112 allow the empty string
|
||||
we change LC_MONETARY handling of mon_decimal_point to allow
|
||||
the empty string. If mon_decimal_point is not defined at all
|
||||
then we pick the existing legacy glibc default value of
|
||||
<U002E> i.e. ".".
|
||||
|
||||
We also set the default for mon_thousands_sep_wc at the
|
||||
same time as mon_thousands_sep, but this is not a change in
|
||||
behaviour, it is always either a matching value or L'\0',
|
||||
but if in the future we change the default to a non-empty
|
||||
string we would need to update both at the same time.
|
||||
|
||||
Tested on x86_64 and i686 without regressions.
|
||||
Tested with install-locale-archive target.
|
||||
Tested with install-locale-files target.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit 2ab8b74567dc0a9a3c98696e6444881997dd6c49)
|
||||
---
|
||||
locale/programs/ld-monetary.c | 182 +++++++++++++++++++++++++++-------
|
||||
1 file changed, 146 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c
|
||||
index 3b0412b405..18698bbe94 100644
|
||||
--- a/locale/programs/ld-monetary.c
|
||||
+++ b/locale/programs/ld-monetary.c
|
||||
@@ -196,21 +196,105 @@ No definition for %s category found"), "LC_MONETARY");
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Generally speaking there are 3 standards the define the default,
|
||||
+ warning, and error behaviour of LC_MONETARY. They are ISO/IEC TR 30112,
|
||||
+ ISO/IEC 9899:2018 (ISO C17), and POSIX.1-2017. Within 30112 we have the
|
||||
+ definition of a standard i18n FDCC-set, which for LC_MONETARY has the
|
||||
+ following default values:
|
||||
+ int_curr_symbol ""
|
||||
+ currency_symbol ""
|
||||
+ mon_decimal_point "<U002C>" i.e. ","
|
||||
+ mon_thousand_sep ""
|
||||
+ mon_grouping "\177" i.e. CHAR_MAX
|
||||
+ positive_sign ""
|
||||
+ negative_sign "<U002E>" i.e. "."
|
||||
+ int_frac_digits -1
|
||||
+ frac_digits -1
|
||||
+ p_cs_precedes -1
|
||||
+ p_sep_by_space -1
|
||||
+ n_cs_precedes -1
|
||||
+ n_sep_by_space -1
|
||||
+ p_sign_posn -1
|
||||
+ n_sign_posn -1
|
||||
+ Under 30112 a keyword that is not provided implies an empty string ""
|
||||
+ for string values or a -1 for integer values, and indicates the value
|
||||
+ is unspecified with no default implied. No errors are considered.
|
||||
+ The exception is mon_grouping which is a string with a terminating
|
||||
+ CHAR_MAX.
|
||||
+ For POSIX Issue 7 we have:
|
||||
+ https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html
|
||||
+ and again values not provided default to "" or -1, and indicate the value
|
||||
+ is not available to the locale. The exception is mon_grouping which is
|
||||
+ a string with a terminating CHAR_MAX. For the POSIX locale the values of
|
||||
+ LC_MONETARY should be:
|
||||
+ int_curr_symbol ""
|
||||
+ currency_symbol ""
|
||||
+ mon_decimal_point ""
|
||||
+ mon_thousands_sep ""
|
||||
+ mon_grouping "\177" i.e. CHAR_MAX
|
||||
+ positive_sign ""
|
||||
+ negative_sign ""
|
||||
+ int_frac_digits -1
|
||||
+ frac_digits -1
|
||||
+ p_cs_precedes -1
|
||||
+ p_sep_by_space -1
|
||||
+ n_cs_precedes -1
|
||||
+ n_sep_by_space -1
|
||||
+ p_sign_posn -1
|
||||
+ n_sign_posn -1
|
||||
+ int_p_cs_precedes -1
|
||||
+ int_p_sep_by_space -1
|
||||
+ int_n_cs_precedes -1
|
||||
+ int_n_sep_by_space -1
|
||||
+ int_p_sign_posn -1
|
||||
+ int_n_sign_posn -1
|
||||
+ Like with 30112, POSIX also considers no error if the keywords are
|
||||
+ missing, only that if the cateory as a whole is missing the referencing
|
||||
+ of the category results in unspecified behaviour.
|
||||
+ For ISO C17 there is no default value provided, but the localeconv
|
||||
+ specification in 7.11.2.1 admits that members of char * type may point
|
||||
+ to "" to indicate a value is not available or is of length zero.
|
||||
+ The exception is decimal_point (not mon_decimal_point) which must be a
|
||||
+ defined non-empty string. The values of char, which are generally
|
||||
+ mapped to integer values in 30112 and POSIX, must be non-negative
|
||||
+ numbers that map to CHAR_MAX when a value is not available in the
|
||||
+ locale.
|
||||
+ In ISO C17 for the "C" locale all values are empty strings "", or
|
||||
+ CHAR_MAX, with the exception of decimal_point which is "." (defined
|
||||
+ in LC_NUMERIC). ISO C17 makes no exception for mon_grouping like
|
||||
+ 30112 and POSIX, but a value of "" is functionally equivalent to
|
||||
+ "\177" since neither defines a grouping (though the latter terminates
|
||||
+ the grouping).
|
||||
+
|
||||
+ Lastly, we must consider the legacy C/POSIX locale that implemented
|
||||
+ as a builtin in glibc and wether a default value mapping to the
|
||||
+ C/POSIX locale may benefit the user from a compatibility perspective.
|
||||
+
|
||||
+ Thus given 30112, POSIX, ISO C, and the builtin C/POSIX locale we
|
||||
+ need to pick appropriate defaults below. */
|
||||
+
|
||||
+ /* The members of LC_MONETARY are handled in the order of their definition
|
||||
+ in locale/categories.def. Please keep them in that order. */
|
||||
+
|
||||
+ /* The purpose of TEST_ELEM is to define a default value for the fields
|
||||
+ in the category if the field was not defined in the cateory. If the
|
||||
+ category was present but we didn't see a definition for the field then
|
||||
+ we also issue a warning, otherwise the only warning you get is the one
|
||||
+ earlier when a default category is created (completely missing category).
|
||||
+ This missing field warning is glibc-specific since no standard requires
|
||||
+ this warning, but we consider it valuable to print a warning for all
|
||||
+ missing fields in the category. */
|
||||
#define TEST_ELEM(cat, initval) \
|
||||
if (monetary->cat == NULL) \
|
||||
{ \
|
||||
if (! nothing) \
|
||||
- record_error (0, 0, _("%s: field `%s' not defined"), \
|
||||
- "LC_MONETARY", #cat); \
|
||||
+ record_warning (_("%s: field `%s' not defined"), \
|
||||
+ "LC_MONETARY", #cat); \
|
||||
monetary->cat = initval; \
|
||||
}
|
||||
|
||||
+ /* Keyword: int_curr_symbol. */
|
||||
TEST_ELEM (int_curr_symbol, "");
|
||||
- TEST_ELEM (currency_symbol, "");
|
||||
- TEST_ELEM (mon_thousands_sep, "");
|
||||
- TEST_ELEM (positive_sign, "");
|
||||
- TEST_ELEM (negative_sign, "");
|
||||
-
|
||||
/* The international currency symbol must come from ISO 4217. */
|
||||
if (monetary->int_curr_symbol != NULL)
|
||||
{
|
||||
@@ -247,41 +331,63 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
|
||||
}
|
||||
}
|
||||
|
||||
- /* The decimal point must not be empty. This is not said explicitly
|
||||
- in POSIX but ANSI C (ISO/IEC 9899) says in 4.4.2.1 it has to be
|
||||
- != "". */
|
||||
+ /* Keyword: currency_symbol */
|
||||
+ TEST_ELEM (currency_symbol, "");
|
||||
+
|
||||
+ /* Keyword: mon_decimal_point */
|
||||
+ /* ISO C17 7.11.2.1.3 explicitly allows mon_decimal_point to be the
|
||||
+ empty string e.g. "". This indicates the value is not available in the
|
||||
+ current locale or is of zero length. However, if the value was never
|
||||
+ defined then we issue a warning and use a glibc-specific default. ISO
|
||||
+ 30112 in the i18n FDCC-Set uses <U002C> ",", and POSIX Issue 7 in the
|
||||
+ POSIX locale uses "". It is specific to glibc that the default is <U002E>
|
||||
+ "."; we retain this existing behaviour for backwards compatibility. */
|
||||
if (monetary->mon_decimal_point == NULL)
|
||||
{
|
||||
if (! nothing)
|
||||
- record_error (0, 0, _("%s: field `%s' not defined"),
|
||||
- "LC_MONETARY", "mon_decimal_point");
|
||||
+ record_warning (_("%s: field `%s' not defined, using defaults"),
|
||||
+ "LC_MONETARY", "mon_decimal_point");
|
||||
monetary->mon_decimal_point = ".";
|
||||
monetary->mon_decimal_point_wc = L'.';
|
||||
}
|
||||
- else if (monetary->mon_decimal_point[0] == '\0' && ! be_quiet && ! nothing)
|
||||
+
|
||||
+ /* Keyword: mon_thousands_sep */
|
||||
+ if (monetary->mon_thousands_sep == NULL)
|
||||
{
|
||||
- record_error (0, 0, _("\
|
||||
-%s: value for field `%s' must not be an empty string"),
|
||||
- "LC_MONETARY", "mon_decimal_point");
|
||||
+ if (! nothing)
|
||||
+ record_warning (_("%s: field `%s' not defined, using defaults"),
|
||||
+ "LC_MONETARY", "mon_thousands_sep");
|
||||
+ monetary->mon_thousands_sep = "";
|
||||
+ monetary->mon_thousands_sep_wc = L'\0';
|
||||
}
|
||||
|
||||
+ /* Keyword: mon_grouping */
|
||||
if (monetary->mon_grouping_len == 0)
|
||||
{
|
||||
if (! nothing)
|
||||
- record_error (0, 0, _("%s: field `%s' not defined"),
|
||||
- "LC_MONETARY", "mon_grouping");
|
||||
-
|
||||
+ record_warning (_("%s: field `%s' not defined"),
|
||||
+ "LC_MONETARY", "mon_grouping");
|
||||
+ /* Missing entries are given 1 element in their bytearray with
|
||||
+ a value of CHAR_MAX which indicates that "No further grouping
|
||||
+ is to be performed" (functionally equivalent to ISO C's "C"
|
||||
+ locale default of ""). */
|
||||
monetary->mon_grouping = (char *) "\177";
|
||||
monetary->mon_grouping_len = 1;
|
||||
}
|
||||
|
||||
+ /* Keyword: positive_sign */
|
||||
+ TEST_ELEM (positive_sign, "");
|
||||
+
|
||||
+ /* Keyword: negative_sign */
|
||||
+ TEST_ELEM (negative_sign, "");
|
||||
+
|
||||
#undef TEST_ELEM
|
||||
#define TEST_ELEM(cat, min, max, initval) \
|
||||
if (monetary->cat == -2) \
|
||||
{ \
|
||||
if (! nothing) \
|
||||
- record_error (0, 0, _("%s: field `%s' not defined"), \
|
||||
- "LC_MONETARY", #cat); \
|
||||
+ record_warning (_("%s: field `%s' not defined"), \
|
||||
+ "LC_MONETARY", #cat); \
|
||||
monetary->cat = initval; \
|
||||
} \
|
||||
else if ((monetary->cat < min || monetary->cat > max) \
|
||||
@@ -300,16 +406,11 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
|
||||
TEST_ELEM (p_sign_posn, -1, 4, -1);
|
||||
TEST_ELEM (n_sign_posn, -1, 4, -1);
|
||||
|
||||
- /* The non-POSIX.2 extensions are optional. */
|
||||
- if (monetary->duo_int_curr_symbol == NULL)
|
||||
- monetary->duo_int_curr_symbol = monetary->int_curr_symbol;
|
||||
- if (monetary->duo_currency_symbol == NULL)
|
||||
- monetary->duo_currency_symbol = monetary->currency_symbol;
|
||||
-
|
||||
- if (monetary->duo_int_frac_digits == -2)
|
||||
- monetary->duo_int_frac_digits = monetary->int_frac_digits;
|
||||
- if (monetary->duo_frac_digits == -2)
|
||||
- monetary->duo_frac_digits = monetary->frac_digits;
|
||||
+ /* Keyword: crncystr */
|
||||
+ monetary->crncystr = (char *) xmalloc (strlen (monetary->currency_symbol)
|
||||
+ + 2);
|
||||
+ monetary->crncystr[0] = monetary->p_cs_precedes ? '-' : '+';
|
||||
+ strcpy (&monetary->crncystr[1], monetary->currency_symbol);
|
||||
|
||||
#undef TEST_ELEM
|
||||
#define TEST_ELEM(cat, alt, min, max) \
|
||||
@@ -327,6 +428,17 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
|
||||
TEST_ELEM (int_p_sign_posn, p_sign_posn, -1, 4);
|
||||
TEST_ELEM (int_n_sign_posn, n_sign_posn, -1, 4);
|
||||
|
||||
+ /* The non-POSIX.2 extensions are optional. */
|
||||
+ if (monetary->duo_int_curr_symbol == NULL)
|
||||
+ monetary->duo_int_curr_symbol = monetary->int_curr_symbol;
|
||||
+ if (monetary->duo_currency_symbol == NULL)
|
||||
+ monetary->duo_currency_symbol = monetary->currency_symbol;
|
||||
+
|
||||
+ if (monetary->duo_int_frac_digits == -2)
|
||||
+ monetary->duo_int_frac_digits = monetary->int_frac_digits;
|
||||
+ if (monetary->duo_frac_digits == -2)
|
||||
+ monetary->duo_frac_digits = monetary->frac_digits;
|
||||
+
|
||||
TEST_ELEM (duo_p_cs_precedes, p_cs_precedes, -1, 1);
|
||||
TEST_ELEM (duo_p_sep_by_space, p_sep_by_space, -1, 2);
|
||||
TEST_ELEM (duo_n_cs_precedes, n_cs_precedes, -1, 1);
|
||||
@@ -349,17 +461,15 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
|
||||
if (monetary->duo_valid_to == 0)
|
||||
monetary->duo_valid_to = 99991231;
|
||||
|
||||
+ /* Keyword: conversion_rate */
|
||||
if (monetary->conversion_rate[0] == 0)
|
||||
{
|
||||
monetary->conversion_rate[0] = 1;
|
||||
monetary->conversion_rate[1] = 1;
|
||||
}
|
||||
|
||||
- /* Create the crncystr entry. */
|
||||
- monetary->crncystr = (char *) xmalloc (strlen (monetary->currency_symbol)
|
||||
- + 2);
|
||||
- monetary->crncystr[0] = monetary->p_cs_precedes ? '-' : '+';
|
||||
- strcpy (&monetary->crncystr[1], monetary->currency_symbol);
|
||||
+ /* A value for monetary-decimal-point-wc was set when
|
||||
+ monetary_decimal_point was set, likewise for monetary-thousands-sep-wc. */
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
2.35.0
|
||||
|
@ -1,31 +0,0 @@
|
||||
From 51e2d3b53bd08a21e5a9a4ed095abd2c61f622bc Mon Sep 17 00:00:00 2001
|
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Wed, 13 Jul 2022 10:37:32 -0300
|
||||
Subject: [PATCH] nptl: Fix ___pthread_unregister_cancel_restore asynchronous
|
||||
restore
|
||||
|
||||
This was due a wrong revert done on 404656009b459658.
|
||||
|
||||
Checked on x86_64-linux-gnu and i686-linux-gnu.
|
||||
|
||||
(cherry picked from commit f27e5e21787abc9f719879af47687221aa1027b3)
|
||||
---
|
||||
nptl/cleanup_defer.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/nptl/cleanup_defer.c b/nptl/cleanup_defer.c
|
||||
index eb0bc77740..4e864ead32 100644
|
||||
--- a/nptl/cleanup_defer.c
|
||||
+++ b/nptl/cleanup_defer.c
|
||||
@@ -71,7 +71,7 @@ ___pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf)
|
||||
return;
|
||||
|
||||
int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
|
||||
- if (cancelhandling & CANCELTYPE_BITMASK)
|
||||
+ if ((cancelhandling & CANCELTYPE_BITMASK) == 0)
|
||||
{
|
||||
int newval;
|
||||
do
|
||||
--
|
||||
2.37.1
|
||||
|
@ -1,136 +0,0 @@
|
||||
From 97dd8b3f705b23de1f84713082b631189084a33b Mon Sep 17 00:00:00 2001
|
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Tue, 31 May 2022 17:13:35 -0300
|
||||
Subject: [PATCH] nptl: Fix __libc_cleanup_pop_restore asynchronous restore
|
||||
(BZ#29214)
|
||||
|
||||
This was due a wrong revert done on 404656009b459658.
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
|
||||
(cherry picked from commit c7d36dcecc08a29825175f65c4ee873ff3177a23)
|
||||
---
|
||||
NEWS | 1 +
|
||||
nptl/libc-cleanup.c | 3 +-
|
||||
sysdeps/pthread/Makefile | 1 +
|
||||
sysdeps/pthread/tst-cancel30.c | 82 ++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 86 insertions(+), 1 deletion(-)
|
||||
create mode 100644 sysdeps/pthread/tst-cancel30.c
|
||||
|
||||
diff --git a/nptl/libc-cleanup.c b/nptl/libc-cleanup.c
|
||||
index c4a83591bf..2ce59388d4 100644
|
||||
--- a/nptl/libc-cleanup.c
|
||||
+++ b/nptl/libc-cleanup.c
|
||||
@@ -57,7 +57,8 @@ __libc_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer)
|
||||
THREAD_SETMEM (self, cleanup, buffer->__prev);
|
||||
|
||||
int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
|
||||
- if (cancelhandling & CANCELTYPE_BITMASK)
|
||||
+ if (buffer->__canceltype != PTHREAD_CANCEL_DEFERRED
|
||||
+ && (cancelhandling & CANCELTYPE_BITMASK) == 0)
|
||||
{
|
||||
int newval;
|
||||
do
|
||||
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
|
||||
index c725586308..3a505c5f99 100644
|
||||
--- a/sysdeps/pthread/Makefile
|
||||
+++ b/sysdeps/pthread/Makefile
|
||||
@@ -126,6 +126,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
|
||||
tst-pthread-raise-blocked-self \
|
||||
tst-pthread_kill-exited \
|
||||
tst-pthread_kill-exiting \
|
||||
+ tst-cancel30 \
|
||||
# tests
|
||||
|
||||
tests-time64 := \
|
||||
diff --git a/sysdeps/pthread/tst-cancel30.c b/sysdeps/pthread/tst-cancel30.c
|
||||
new file mode 100644
|
||||
index 0000000000..e08392f968
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/pthread/tst-cancel30.c
|
||||
@@ -0,0 +1,82 @@
|
||||
+/* Check if printf like functions does not disable asynchronous cancellation
|
||||
+ mode (BZ#29214).
|
||||
+
|
||||
+ 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 <support/check.h>
|
||||
+#include <support/xstdio.h>
|
||||
+#include <support/xthread.h>
|
||||
+#include <sys/syscall.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+static pthread_barrier_t b;
|
||||
+
|
||||
+static void *
|
||||
+tf (void *arg)
|
||||
+{
|
||||
+ int old;
|
||||
+
|
||||
+ TEST_COMPARE (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL), 0);
|
||||
+
|
||||
+ TEST_COMPARE (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old), 0);
|
||||
+ TEST_COMPARE (old, PTHREAD_CANCEL_ASYNCHRONOUS);
|
||||
+
|
||||
+ /* Check if internal lock cleanup routines restore the cancellation type
|
||||
+ correctly. */
|
||||
+ printf ("...\n");
|
||||
+ TEST_COMPARE (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old), 0);
|
||||
+ TEST_COMPARE (old, PTHREAD_CANCEL_ASYNCHRONOUS);
|
||||
+
|
||||
+ xpthread_barrier_wait (&b);
|
||||
+
|
||||
+ /* Wait indefinitely for cancellation, which only works if asynchronous
|
||||
+ cancellation is enabled. */
|
||||
+#ifdef SYS_pause
|
||||
+ syscall (SYS_pause);
|
||||
+#elif defined SYS_ppoll || defined SYS_ppoll_time64
|
||||
+# ifndef SYS_ppoll_time64
|
||||
+# define SYS_ppoll_time64 SYS_ppoll
|
||||
+# endif
|
||||
+ syscall (SYS_ppoll_time64, NULL, 0, NULL, NULL);
|
||||
+#else
|
||||
+ for (;;);
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ xpthread_barrier_init (&b, NULL, 2);
|
||||
+
|
||||
+ pthread_t th = xpthread_create (NULL, tf, NULL);
|
||||
+
|
||||
+ xpthread_barrier_wait (&b);
|
||||
+
|
||||
+ xpthread_cancel (th);
|
||||
+
|
||||
+ void *status = xpthread_join (th);
|
||||
+ TEST_VERIFY (status == PTHREAD_CANCELED);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* There is no need to wait full TIMEOUT if asynchronous is not working. */
|
||||
+#define TIMEOUT 3
|
||||
+#include <support/test-driver.c>
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,856 +0,0 @@
|
||||
From ba9c42ac0e265bf1e4ec1075fa20e7166fda8bfc Mon Sep 17 00:00:00 2001
|
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Wed, 6 Apr 2022 12:24:42 -0300
|
||||
Subject: [PATCH] nptl: Handle spurious EINTR when thread cancellation is
|
||||
disabled (BZ#29029)
|
||||
|
||||
Some Linux interfaces never restart after being interrupted by a signal
|
||||
handler, regardless of the use of SA_RESTART [1]. It means that for
|
||||
pthread cancellation, if the target thread disables cancellation with
|
||||
pthread_setcancelstate and calls such interfaces (like poll or select),
|
||||
it should not see spurious EINTR failures due the internal SIGCANCEL.
|
||||
|
||||
However recent changes made pthread_cancel to always sent the internal
|
||||
signal, regardless of the target thread cancellation status or type.
|
||||
To fix it, the previous semantic is restored, where the cancel signal
|
||||
is only sent if the target thread has cancelation enabled in
|
||||
asynchronous mode.
|
||||
|
||||
The cancel state and cancel type is moved back to cancelhandling
|
||||
and atomic operation are used to synchronize between threads. The
|
||||
patch essentially revert the following commits:
|
||||
|
||||
8c1c0aae20 nptl: Move cancel type out of cancelhandling
|
||||
2b51742531 nptl: Move cancel state out of cancelhandling
|
||||
26cfbb7162 nptl: Remove CANCELING_BITMASK
|
||||
|
||||
However I changed the atomic operation to follow the internal C11
|
||||
semantic and removed the MACRO usage, it simplifies a bit the
|
||||
resulting code (and removes another usage of the old atomic macros).
|
||||
|
||||
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
|
||||
and powerpc64-linux-gnu.
|
||||
|
||||
[1] https://man7.org/linux/man-pages/man7/signal.7.html
|
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
|
||||
|
||||
(cherry-picked from commit 404656009b459658138ed1bd18f3c6cf3863e6a6)
|
||||
---
|
||||
NEWS | 2 +
|
||||
manual/process.texi | 3 +-
|
||||
nptl/allocatestack.c | 2 -
|
||||
nptl/cancellation.c | 50 ++++++--
|
||||
nptl/cleanup_defer.c | 42 ++++++-
|
||||
nptl/descr.h | 41 +++++--
|
||||
nptl/libc-cleanup.c | 39 ++++++-
|
||||
nptl/pthread_cancel.c | 110 +++++++++++++-----
|
||||
nptl/pthread_join_common.c | 7 +-
|
||||
nptl/pthread_setcancelstate.c | 26 ++++-
|
||||
nptl/pthread_setcanceltype.c | 31 ++++-
|
||||
nptl/pthread_testcancel.c | 9 +-
|
||||
sysdeps/nptl/dl-tls_init_tp.c | 3 -
|
||||
sysdeps/nptl/pthreadP.h | 2 +-
|
||||
sysdeps/pthread/Makefile | 1 +
|
||||
sysdeps/pthread/tst-cancel29.c | 207 +++++++++++++++++++++++++++++++++
|
||||
16 files changed, 484 insertions(+), 91 deletions(-)
|
||||
create mode 100644 sysdeps/pthread/tst-cancel29.c
|
||||
|
||||
diff --git a/manual/process.texi b/manual/process.texi
|
||||
index 28c9531f42..9307379194 100644
|
||||
--- a/manual/process.texi
|
||||
+++ b/manual/process.texi
|
||||
@@ -68,8 +68,7 @@ until the subprogram terminates before you can do anything else.
|
||||
@c CLEANUP_HANDLER @ascuplugin @ascuheap @acsmem
|
||||
@c libc_cleanup_region_start @ascuplugin @ascuheap @acsmem
|
||||
@c pthread_cleanup_push_defer @ascuplugin @ascuheap @acsmem
|
||||
-@c __pthread_testcancel @ascuplugin @ascuheap @acsmem
|
||||
-@c CANCEL_ENABLED_AND_CANCELED ok
|
||||
+@c cancel_enabled_and_canceled @ascuplugin @ascuheap @acsmem
|
||||
@c do_cancel @ascuplugin @ascuheap @acsmem
|
||||
@c cancel_handler ok
|
||||
@c kill syscall ok
|
||||
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
|
||||
index 34a33164ff..01a282f3f6 100644
|
||||
--- a/nptl/allocatestack.c
|
||||
+++ b/nptl/allocatestack.c
|
||||
@@ -119,8 +119,6 @@ get_cached_stack (size_t *sizep, void **memp)
|
||||
|
||||
/* Cancellation handling is back to the default. */
|
||||
result->cancelhandling = 0;
|
||||
- result->cancelstate = PTHREAD_CANCEL_ENABLE;
|
||||
- result->canceltype = PTHREAD_CANCEL_DEFERRED;
|
||||
result->cleanup = NULL;
|
||||
result->setup_failed = 0;
|
||||
|
||||
diff --git a/nptl/cancellation.c b/nptl/cancellation.c
|
||||
index 8d54a6add1..f4b08902b2 100644
|
||||
--- a/nptl/cancellation.c
|
||||
+++ b/nptl/cancellation.c
|
||||
@@ -30,19 +30,26 @@ int
|
||||
__pthread_enable_asynccancel (void)
|
||||
{
|
||||
struct pthread *self = THREAD_SELF;
|
||||
+ int oldval = atomic_load_relaxed (&self->cancelhandling);
|
||||
|
||||
- int oldval = THREAD_GETMEM (self, canceltype);
|
||||
- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_ASYNCHRONOUS);
|
||||
+ while (1)
|
||||
+ {
|
||||
+ int newval = oldval | CANCELTYPE_BITMASK;
|
||||
|
||||
- int ch = THREAD_GETMEM (self, cancelhandling);
|
||||
+ if (newval == oldval)
|
||||
+ break;
|
||||
|
||||
- if (self->cancelstate == PTHREAD_CANCEL_ENABLE
|
||||
- && (ch & CANCELED_BITMASK)
|
||||
- && !(ch & EXITING_BITMASK)
|
||||
- && !(ch & TERMINATED_BITMASK))
|
||||
- {
|
||||
- THREAD_SETMEM (self, result, PTHREAD_CANCELED);
|
||||
- __do_cancel ();
|
||||
+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling,
|
||||
+ &oldval, newval))
|
||||
+ {
|
||||
+ if (cancel_enabled_and_canceled_and_async (newval))
|
||||
+ {
|
||||
+ self->result = PTHREAD_CANCELED;
|
||||
+ __do_cancel ();
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
return oldval;
|
||||
@@ -56,10 +63,29 @@ __pthread_disable_asynccancel (int oldtype)
|
||||
{
|
||||
/* If asynchronous cancellation was enabled before we do not have
|
||||
anything to do. */
|
||||
- if (oldtype == PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
+ if (oldtype & CANCELTYPE_BITMASK)
|
||||
return;
|
||||
|
||||
struct pthread *self = THREAD_SELF;
|
||||
- self->canceltype = PTHREAD_CANCEL_DEFERRED;
|
||||
+ int newval;
|
||||
+ int oldval = atomic_load_relaxed (&self->cancelhandling);
|
||||
+ do
|
||||
+ {
|
||||
+ newval = oldval & ~CANCELTYPE_BITMASK;
|
||||
+ }
|
||||
+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
|
||||
+ &oldval, newval));
|
||||
+
|
||||
+ /* We cannot return when we are being canceled. Upon return the
|
||||
+ thread might be things which would have to be undone. The
|
||||
+ following loop should loop until the cancellation signal is
|
||||
+ delivered. */
|
||||
+ while (__glibc_unlikely ((newval & (CANCELING_BITMASK | CANCELED_BITMASK))
|
||||
+ == CANCELING_BITMASK))
|
||||
+ {
|
||||
+ futex_wait_simple ((unsigned int *) &self->cancelhandling, newval,
|
||||
+ FUTEX_PRIVATE);
|
||||
+ newval = atomic_load_relaxed (&self->cancelhandling);
|
||||
+ }
|
||||
}
|
||||
libc_hidden_def (__pthread_disable_asynccancel)
|
||||
diff --git a/nptl/cleanup_defer.c b/nptl/cleanup_defer.c
|
||||
index f8181a40e8..eb0bc77740 100644
|
||||
--- a/nptl/cleanup_defer.c
|
||||
+++ b/nptl/cleanup_defer.c
|
||||
@@ -30,9 +30,22 @@ ___pthread_register_cancel_defer (__pthread_unwind_buf_t *buf)
|
||||
ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
|
||||
ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup);
|
||||
|
||||
- /* Disable asynchronous cancellation for now. */
|
||||
- ibuf->priv.data.canceltype = THREAD_GETMEM (self, canceltype);
|
||||
- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_DEFERRED);
|
||||
+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
|
||||
+ if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK))
|
||||
+ {
|
||||
+ int newval;
|
||||
+ do
|
||||
+ {
|
||||
+ newval = cancelhandling & ~CANCELTYPE_BITMASK;
|
||||
+ }
|
||||
+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
|
||||
+ &cancelhandling,
|
||||
+ newval));
|
||||
+ }
|
||||
+
|
||||
+ ibuf->priv.data.canceltype = (cancelhandling & CANCELTYPE_BITMASK
|
||||
+ ? PTHREAD_CANCEL_ASYNCHRONOUS
|
||||
+ : PTHREAD_CANCEL_DEFERRED);
|
||||
|
||||
/* Store the new cleanup handler info. */
|
||||
THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf);
|
||||
@@ -54,9 +67,26 @@ ___pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf)
|
||||
|
||||
THREAD_SETMEM (self, cleanup_jmp_buf, ibuf->priv.data.prev);
|
||||
|
||||
- THREAD_SETMEM (self, canceltype, ibuf->priv.data.canceltype);
|
||||
- if (ibuf->priv.data.canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
- __pthread_testcancel ();
|
||||
+ if (ibuf->priv.data.canceltype == PTHREAD_CANCEL_DEFERRED)
|
||||
+ return;
|
||||
+
|
||||
+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
|
||||
+ if (cancelhandling & CANCELTYPE_BITMASK)
|
||||
+ {
|
||||
+ int newval;
|
||||
+ do
|
||||
+ {
|
||||
+ newval = cancelhandling | CANCELTYPE_BITMASK;
|
||||
+ }
|
||||
+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
|
||||
+ &cancelhandling, newval));
|
||||
+
|
||||
+ if (cancel_enabled_and_canceled (cancelhandling))
|
||||
+ {
|
||||
+ self->result = PTHREAD_CANCELED;
|
||||
+ __do_cancel ();
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
versioned_symbol (libc, ___pthread_unregister_cancel_restore,
|
||||
__pthread_unregister_cancel_restore, GLIBC_2_34);
|
||||
diff --git a/nptl/descr.h b/nptl/descr.h
|
||||
index ea8aca08e6..bb46b5958e 100644
|
||||
--- a/nptl/descr.h
|
||||
+++ b/nptl/descr.h
|
||||
@@ -279,18 +279,27 @@ struct pthread
|
||||
|
||||
/* Flags determining processing of cancellation. */
|
||||
int cancelhandling;
|
||||
+ /* Bit set if cancellation is disabled. */
|
||||
+#define CANCELSTATE_BIT 0
|
||||
+#define CANCELSTATE_BITMASK (1 << CANCELSTATE_BIT)
|
||||
+ /* Bit set if asynchronous cancellation mode is selected. */
|
||||
+#define CANCELTYPE_BIT 1
|
||||
+#define CANCELTYPE_BITMASK (1 << CANCELTYPE_BIT)
|
||||
+ /* Bit set if canceling has been initiated. */
|
||||
+#define CANCELING_BIT 2
|
||||
+#define CANCELING_BITMASK (1 << CANCELING_BIT)
|
||||
/* Bit set if canceled. */
|
||||
#define CANCELED_BIT 3
|
||||
-#define CANCELED_BITMASK (0x01 << CANCELED_BIT)
|
||||
+#define CANCELED_BITMASK (1 << CANCELED_BIT)
|
||||
/* Bit set if thread is exiting. */
|
||||
#define EXITING_BIT 4
|
||||
-#define EXITING_BITMASK (0x01 << EXITING_BIT)
|
||||
+#define EXITING_BITMASK (1 << EXITING_BIT)
|
||||
/* Bit set if thread terminated and TCB is freed. */
|
||||
#define TERMINATED_BIT 5
|
||||
-#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT)
|
||||
+#define TERMINATED_BITMASK (1 << TERMINATED_BIT)
|
||||
/* Bit set if thread is supposed to change XID. */
|
||||
#define SETXID_BIT 6
|
||||
-#define SETXID_BITMASK (0x01 << SETXID_BIT)
|
||||
+#define SETXID_BITMASK (1 << SETXID_BIT)
|
||||
|
||||
/* Flags. Including those copied from the thread attribute. */
|
||||
int flags;
|
||||
@@ -390,14 +399,6 @@ struct pthread
|
||||
/* Indicates whether is a C11 thread created by thrd_creat. */
|
||||
bool c11;
|
||||
|
||||
- /* Thread cancel state (PTHREAD_CANCEL_ENABLE or
|
||||
- PTHREAD_CANCEL_DISABLE). */
|
||||
- unsigned char cancelstate;
|
||||
-
|
||||
- /* Thread cancel type (PTHREAD_CANCEL_DEFERRED or
|
||||
- PTHREAD_CANCEL_ASYNCHRONOUS). */
|
||||
- unsigned char canceltype;
|
||||
-
|
||||
/* Used in __pthread_kill_internal to detected a thread that has
|
||||
exited or is about to exit. exit_lock must only be acquired
|
||||
after blocking signals. */
|
||||
@@ -417,6 +418,22 @@ struct pthread
|
||||
(sizeof (struct pthread) - offsetof (struct pthread, end_padding))
|
||||
} __attribute ((aligned (TCB_ALIGNMENT)));
|
||||
|
||||
+static inline bool
|
||||
+cancel_enabled_and_canceled (int value)
|
||||
+{
|
||||
+ return (value & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
|
||||
+ | TERMINATED_BITMASK))
|
||||
+ == CANCELED_BITMASK;
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+cancel_enabled_and_canceled_and_async (int value)
|
||||
+{
|
||||
+ return ((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK
|
||||
+ | EXITING_BITMASK | TERMINATED_BITMASK))
|
||||
+ == (CANCELTYPE_BITMASK | CANCELED_BITMASK);
|
||||
+}
|
||||
+
|
||||
/* This yields the pointer that TLS support code calls the thread pointer. */
|
||||
#if TLS_TCB_AT_TP
|
||||
# define TLS_TPADJ(pd) (pd)
|
||||
diff --git a/nptl/libc-cleanup.c b/nptl/libc-cleanup.c
|
||||
index cb4c226281..c4a83591bf 100644
|
||||
--- a/nptl/libc-cleanup.c
|
||||
+++ b/nptl/libc-cleanup.c
|
||||
@@ -26,9 +26,24 @@ __libc_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer)
|
||||
|
||||
buffer->__prev = THREAD_GETMEM (self, cleanup);
|
||||
|
||||
+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
|
||||
+
|
||||
/* Disable asynchronous cancellation for now. */
|
||||
- buffer->__canceltype = THREAD_GETMEM (self, canceltype);
|
||||
- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_DEFERRED);
|
||||
+ if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK))
|
||||
+ {
|
||||
+ int newval;
|
||||
+ do
|
||||
+ {
|
||||
+ newval = cancelhandling & ~CANCELTYPE_BITMASK;
|
||||
+ }
|
||||
+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
|
||||
+ &cancelhandling,
|
||||
+ newval));
|
||||
+ }
|
||||
+
|
||||
+ buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK
|
||||
+ ? PTHREAD_CANCEL_ASYNCHRONOUS
|
||||
+ : PTHREAD_CANCEL_DEFERRED);
|
||||
|
||||
THREAD_SETMEM (self, cleanup, buffer);
|
||||
}
|
||||
@@ -41,8 +56,22 @@ __libc_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer)
|
||||
|
||||
THREAD_SETMEM (self, cleanup, buffer->__prev);
|
||||
|
||||
- THREAD_SETMEM (self, canceltype, buffer->__canceltype);
|
||||
- if (buffer->__canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
- __pthread_testcancel ();
|
||||
+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
|
||||
+ if (cancelhandling & CANCELTYPE_BITMASK)
|
||||
+ {
|
||||
+ int newval;
|
||||
+ do
|
||||
+ {
|
||||
+ newval = cancelhandling | CANCELTYPE_BITMASK;
|
||||
+ }
|
||||
+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
|
||||
+ &cancelhandling, newval));
|
||||
+
|
||||
+ if (cancel_enabled_and_canceled (cancelhandling))
|
||||
+ {
|
||||
+ self->result = PTHREAD_CANCELED;
|
||||
+ __do_cancel ();
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
libc_hidden_def (__libc_cleanup_pop_restore)
|
||||
diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
|
||||
index 7524c7ce4d..c76882e279 100644
|
||||
--- a/nptl/pthread_cancel.c
|
||||
+++ b/nptl/pthread_cancel.c
|
||||
@@ -42,18 +42,29 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx)
|
||||
|
||||
struct pthread *self = THREAD_SELF;
|
||||
|
||||
- int ch = atomic_load_relaxed (&self->cancelhandling);
|
||||
- /* Cancelation not enabled, not cancelled, or already exitting. */
|
||||
- if (self->cancelstate == PTHREAD_CANCEL_DISABLE
|
||||
- || (ch & CANCELED_BITMASK) == 0
|
||||
- || (ch & EXITING_BITMASK) != 0)
|
||||
- return;
|
||||
-
|
||||
- /* Set the return value. */
|
||||
- THREAD_SETMEM (self, result, PTHREAD_CANCELED);
|
||||
- /* Make sure asynchronous cancellation is still enabled. */
|
||||
- if (self->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
- __do_cancel ();
|
||||
+ int oldval = atomic_load_relaxed (&self->cancelhandling);
|
||||
+ while (1)
|
||||
+ {
|
||||
+ /* We are canceled now. When canceled by another thread this flag
|
||||
+ is already set but if the signal is directly send (internally or
|
||||
+ from another process) is has to be done here. */
|
||||
+ int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
|
||||
+
|
||||
+ if (oldval == newval || (oldval & EXITING_BITMASK) != 0)
|
||||
+ /* Already canceled or exiting. */
|
||||
+ break;
|
||||
+
|
||||
+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling,
|
||||
+ &oldval, newval))
|
||||
+ {
|
||||
+ self->result = PTHREAD_CANCELED;
|
||||
+
|
||||
+ /* Make sure asynchronous cancellation is still enabled. */
|
||||
+ if ((oldval & CANCELTYPE_BITMASK) != 0)
|
||||
+ /* Run the registered destructors and terminate the thread. */
|
||||
+ __do_cancel ();
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
int
|
||||
@@ -92,29 +103,70 @@ __pthread_cancel (pthread_t th)
|
||||
}
|
||||
#endif
|
||||
|
||||
- int oldch = atomic_fetch_or_acquire (&pd->cancelhandling, CANCELED_BITMASK);
|
||||
- if ((oldch & CANCELED_BITMASK) != 0)
|
||||
- return 0;
|
||||
-
|
||||
- if (pd == THREAD_SELF)
|
||||
+ /* Some syscalls are never restarted after being interrupted by a signal
|
||||
+ handler, regardless of the use of SA_RESTART (they always fail with
|
||||
+ EINTR). So pthread_cancel cannot send SIGCANCEL unless the cancellation
|
||||
+ is enabled and set as asynchronous (in this case the cancellation will
|
||||
+ be acted in the cancellation handler instead by the syscall wrapper).
|
||||
+ Otherwise the target thread is set as 'cancelling' (CANCELING_BITMASK)
|
||||
+ by atomically setting 'cancelhandling' and the cancelation will be acted
|
||||
+ upon on next cancellation entrypoing in the target thread.
|
||||
+
|
||||
+ It also requires to atomically check if cancellation is enabled and
|
||||
+ asynchronous, so both cancellation state and type are tracked on
|
||||
+ 'cancelhandling'. */
|
||||
+
|
||||
+ int result = 0;
|
||||
+ int oldval = atomic_load_relaxed (&pd->cancelhandling);
|
||||
+ int newval;
|
||||
+ do
|
||||
{
|
||||
- /* A single-threaded process should be able to kill itself, since there
|
||||
- is nothing in the POSIX specification that says that it cannot. So
|
||||
- we set multiple_threads to true so that cancellation points get
|
||||
- executed. */
|
||||
- THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
|
||||
+ newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
|
||||
+ if (oldval == newval)
|
||||
+ break;
|
||||
+
|
||||
+ /* If the cancellation is handled asynchronously just send a
|
||||
+ signal. We avoid this if possible since it's more
|
||||
+ expensive. */
|
||||
+ if (cancel_enabled_and_canceled_and_async (newval))
|
||||
+ {
|
||||
+ /* Mark the cancellation as "in progress". */
|
||||
+ int newval2 = oldval | CANCELING_BITMASK;
|
||||
+ if (!atomic_compare_exchange_weak_acquire (&pd->cancelhandling,
|
||||
+ &oldval, newval2))
|
||||
+ continue;
|
||||
+
|
||||
+ if (pd == THREAD_SELF)
|
||||
+ /* This is not merely an optimization: An application may
|
||||
+ call pthread_cancel (pthread_self ()) without calling
|
||||
+ pthread_create, so the signal handler may not have been
|
||||
+ set up for a self-cancel. */
|
||||
+ {
|
||||
+ pd->result = PTHREAD_CANCELED;
|
||||
+ if ((newval & CANCELTYPE_BITMASK) != 0)
|
||||
+ __do_cancel ();
|
||||
+ }
|
||||
+ else
|
||||
+ /* The cancellation handler will take care of marking the
|
||||
+ thread as canceled. */
|
||||
+ result = __pthread_kill_internal (th, SIGCANCEL);
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* A single-threaded process should be able to kill itself, since
|
||||
+ there is nothing in the POSIX specification that says that it
|
||||
+ cannot. So we set multiple_threads to true so that cancellation
|
||||
+ points get executed. */
|
||||
+ THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
|
||||
#ifndef TLS_MULTIPLE_THREADS_IN_TCB
|
||||
__libc_multiple_threads = 1;
|
||||
#endif
|
||||
-
|
||||
- THREAD_SETMEM (pd, result, PTHREAD_CANCELED);
|
||||
- if (pd->cancelstate == PTHREAD_CANCEL_ENABLE
|
||||
- && pd->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
- __do_cancel ();
|
||||
- return 0;
|
||||
}
|
||||
+ while (!atomic_compare_exchange_weak_acquire (&pd->cancelhandling, &oldval,
|
||||
+ newval));
|
||||
|
||||
- return __pthread_kill_internal (th, SIGCANCEL);
|
||||
+ return result;
|
||||
}
|
||||
versioned_symbol (libc, __pthread_cancel, pthread_cancel, GLIBC_2_34);
|
||||
|
||||
diff --git a/nptl/pthread_join_common.c b/nptl/pthread_join_common.c
|
||||
index a8e884f341..ca3245b0af 100644
|
||||
--- a/nptl/pthread_join_common.c
|
||||
+++ b/nptl/pthread_join_common.c
|
||||
@@ -57,12 +57,9 @@ __pthread_clockjoin_ex (pthread_t threadid, void **thread_return,
|
||||
if ((pd == self
|
||||
|| (self->joinid == pd
|
||||
&& (pd->cancelhandling
|
||||
- & (CANCELED_BITMASK | EXITING_BITMASK
|
||||
+ & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
|
||||
| TERMINATED_BITMASK)) == 0))
|
||||
- && !(self->cancelstate == PTHREAD_CANCEL_ENABLE
|
||||
- && (pd->cancelhandling & (CANCELED_BITMASK | EXITING_BITMASK
|
||||
- | TERMINATED_BITMASK))
|
||||
- == CANCELED_BITMASK))
|
||||
+ && !cancel_enabled_and_canceled (self->cancelhandling))
|
||||
/* This is a deadlock situation. The threads are waiting for each
|
||||
other to finish. Note that this is a "may" error. To be 100%
|
||||
sure we catch this error we would have to lock the data
|
||||
diff --git a/nptl/pthread_setcancelstate.c b/nptl/pthread_setcancelstate.c
|
||||
index 9905b12e4f..f8edf18fbe 100644
|
||||
--- a/nptl/pthread_setcancelstate.c
|
||||
+++ b/nptl/pthread_setcancelstate.c
|
||||
@@ -30,9 +30,29 @@ __pthread_setcancelstate (int state, int *oldstate)
|
||||
|
||||
self = THREAD_SELF;
|
||||
|
||||
- if (oldstate != NULL)
|
||||
- *oldstate = self->cancelstate;
|
||||
- self->cancelstate = state;
|
||||
+ int oldval = atomic_load_relaxed (&self->cancelhandling);
|
||||
+ while (1)
|
||||
+ {
|
||||
+ int newval = (state == PTHREAD_CANCEL_DISABLE
|
||||
+ ? oldval | CANCELSTATE_BITMASK
|
||||
+ : oldval & ~CANCELSTATE_BITMASK);
|
||||
+
|
||||
+ if (oldstate != NULL)
|
||||
+ *oldstate = ((oldval & CANCELSTATE_BITMASK)
|
||||
+ ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE);
|
||||
+
|
||||
+ if (oldval == newval)
|
||||
+ break;
|
||||
+
|
||||
+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling,
|
||||
+ &oldval, newval))
|
||||
+ {
|
||||
+ if (cancel_enabled_and_canceled_and_async (newval))
|
||||
+ __do_cancel ();
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/nptl/pthread_setcanceltype.c b/nptl/pthread_setcanceltype.c
|
||||
index 94e56466de..1307d355c1 100644
|
||||
--- a/nptl/pthread_setcanceltype.c
|
||||
+++ b/nptl/pthread_setcanceltype.c
|
||||
@@ -28,11 +28,32 @@ __pthread_setcanceltype (int type, int *oldtype)
|
||||
|
||||
volatile struct pthread *self = THREAD_SELF;
|
||||
|
||||
- if (oldtype != NULL)
|
||||
- *oldtype = self->canceltype;
|
||||
- self->canceltype = type;
|
||||
- if (type == PTHREAD_CANCEL_ASYNCHRONOUS)
|
||||
- __pthread_testcancel ();
|
||||
+ int oldval = atomic_load_relaxed (&self->cancelhandling);
|
||||
+ while (1)
|
||||
+ {
|
||||
+ int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS
|
||||
+ ? oldval | CANCELTYPE_BITMASK
|
||||
+ : oldval & ~CANCELTYPE_BITMASK);
|
||||
+
|
||||
+ if (oldtype != NULL)
|
||||
+ *oldtype = ((oldval & CANCELTYPE_BITMASK)
|
||||
+ ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED);
|
||||
+
|
||||
+ if (oldval == newval)
|
||||
+ break;
|
||||
+
|
||||
+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling,
|
||||
+ &oldval, newval))
|
||||
+ {
|
||||
+ if (cancel_enabled_and_canceled_and_async (newval))
|
||||
+ {
|
||||
+ THREAD_SETMEM (self, result, PTHREAD_CANCELED);
|
||||
+ __do_cancel ();
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/nptl/pthread_testcancel.c b/nptl/pthread_testcancel.c
|
||||
index 13123608e8..b81928c000 100644
|
||||
--- a/nptl/pthread_testcancel.c
|
||||
+++ b/nptl/pthread_testcancel.c
|
||||
@@ -23,13 +23,10 @@ void
|
||||
___pthread_testcancel (void)
|
||||
{
|
||||
struct pthread *self = THREAD_SELF;
|
||||
- int cancelhandling = THREAD_GETMEM (self, cancelhandling);
|
||||
- if (self->cancelstate == PTHREAD_CANCEL_ENABLE
|
||||
- && (cancelhandling & CANCELED_BITMASK)
|
||||
- && !(cancelhandling & EXITING_BITMASK)
|
||||
- && !(cancelhandling & TERMINATED_BITMASK))
|
||||
+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
|
||||
+ if (cancel_enabled_and_canceled (cancelhandling))
|
||||
{
|
||||
- THREAD_SETMEM (self, result, PTHREAD_CANCELED);
|
||||
+ self->result = PTHREAD_CANCELED;
|
||||
__do_cancel ();
|
||||
}
|
||||
}
|
||||
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
|
||||
index 1294c91816..53fba774a5 100644
|
||||
--- a/sysdeps/nptl/dl-tls_init_tp.c
|
||||
+++ b/sysdeps/nptl/dl-tls_init_tp.c
|
||||
@@ -128,7 +128,4 @@ __tls_init_tp (void)
|
||||
It will be bigger than it actually is, but for unwind.c/pt-longjmp.c
|
||||
purposes this is good enough. */
|
||||
THREAD_SETMEM (pd, stackblock_size, (size_t) __libc_stack_end);
|
||||
-
|
||||
- THREAD_SETMEM (pd, cancelstate, PTHREAD_CANCEL_ENABLE);
|
||||
- THREAD_SETMEM (pd, canceltype, PTHREAD_CANCEL_DEFERRED);
|
||||
}
|
||||
diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h
|
||||
index 708bd92469..601db4ff2b 100644
|
||||
--- a/sysdeps/nptl/pthreadP.h
|
||||
+++ b/sysdeps/nptl/pthreadP.h
|
||||
@@ -275,7 +275,7 @@ __do_cancel (void)
|
||||
struct pthread *self = THREAD_SELF;
|
||||
|
||||
/* Make sure we get no more cancellations. */
|
||||
- THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
|
||||
+ atomic_bit_set (&self->cancelhandling, EXITING_BIT);
|
||||
|
||||
__pthread_unwind ((__pthread_unwind_buf_t *)
|
||||
THREAD_GETMEM (self, cleanup_jmp_buf));
|
||||
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
|
||||
index c972bd819a..e67db428d9 100644
|
||||
--- a/sysdeps/pthread/Makefile
|
||||
+++ b/sysdeps/pthread/Makefile
|
||||
@@ -69,6 +69,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
|
||||
tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 tst-cancel16 \
|
||||
tst-cancel18 tst-cancel19 tst-cancel20 tst-cancel21 \
|
||||
tst-cancel22 tst-cancel23 tst-cancel26 tst-cancel27 tst-cancel28 \
|
||||
+ tst-cancel29 \
|
||||
tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 \
|
||||
tst-clock1 \
|
||||
tst-cond-except \
|
||||
diff --git a/sysdeps/pthread/tst-cancel29.c b/sysdeps/pthread/tst-cancel29.c
|
||||
new file mode 100644
|
||||
index 0000000000..4f0d99e002
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/pthread/tst-cancel29.c
|
||||
@@ -0,0 +1,207 @@
|
||||
+/* Check if a thread that disables cancellation and which call functions
|
||||
+ that might be interrupted by a signal do not see the internal SIGCANCEL.
|
||||
+
|
||||
+ 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 <array_length.h>
|
||||
+#include <errno.h>
|
||||
+#include <inttypes.h>
|
||||
+#include <poll.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/xthread.h>
|
||||
+#include <sys/socket.h>
|
||||
+#include <signal.h>
|
||||
+#include <stdio.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+/* On Linux some interfaces are never restarted after being interrupted by
|
||||
+ a signal handler, regardless of the use of SA_RESTART. It means that
|
||||
+ if asynchronous cancellation is not enabled, the pthread_cancel can not
|
||||
+ set the internal SIGCANCEL otherwise the interface might see a spurious
|
||||
+ EINTR failure. */
|
||||
+
|
||||
+static pthread_barrier_t b;
|
||||
+
|
||||
+/* Cleanup handling test. */
|
||||
+static int cl_called;
|
||||
+static void
|
||||
+cl (void *arg)
|
||||
+{
|
||||
+ ++cl_called;
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+tf_sigtimedwait (void *arg)
|
||||
+{
|
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
|
||||
+ xpthread_barrier_wait (&b);
|
||||
+
|
||||
+ int r;
|
||||
+ pthread_cleanup_push (cl, NULL);
|
||||
+
|
||||
+ sigset_t mask;
|
||||
+ sigemptyset (&mask);
|
||||
+ r = sigtimedwait (&mask, NULL, &(struct timespec) { 0, 250000000 });
|
||||
+ if (r != -1)
|
||||
+ return (void*) -1;
|
||||
+ if (errno != EAGAIN)
|
||||
+ return (void*) -2;
|
||||
+
|
||||
+ pthread_cleanup_pop (0);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+tf_poll (void *arg)
|
||||
+{
|
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
|
||||
+ xpthread_barrier_wait (&b);
|
||||
+
|
||||
+ int r;
|
||||
+ pthread_cleanup_push (cl, NULL);
|
||||
+
|
||||
+ r = poll (NULL, 0, 250);
|
||||
+ if (r != 0)
|
||||
+ return (void*) -1;
|
||||
+
|
||||
+ pthread_cleanup_pop (0);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+tf_ppoll (void *arg)
|
||||
+{
|
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
|
||||
+
|
||||
+ xpthread_barrier_wait (&b);
|
||||
+
|
||||
+ int r;
|
||||
+ pthread_cleanup_push (cl, NULL);
|
||||
+
|
||||
+ r = ppoll (NULL, 0, &(struct timespec) { 0, 250000000 }, NULL);
|
||||
+ if (r != 0)
|
||||
+ return (void*) -1;
|
||||
+
|
||||
+ pthread_cleanup_pop (0);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+tf_select (void *arg)
|
||||
+{
|
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
|
||||
+ xpthread_barrier_wait (&b);
|
||||
+
|
||||
+ int r;
|
||||
+ pthread_cleanup_push (cl, NULL);
|
||||
+
|
||||
+ r = select (0, NULL, NULL, NULL, &(struct timeval) { 0, 250000 });
|
||||
+ if (r != 0)
|
||||
+ return (void*) -1;
|
||||
+
|
||||
+ pthread_cleanup_pop (0);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+tf_pselect (void *arg)
|
||||
+{
|
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
|
||||
+ xpthread_barrier_wait (&b);
|
||||
+
|
||||
+ int r;
|
||||
+ pthread_cleanup_push (cl, NULL);
|
||||
+
|
||||
+ r = pselect (0, NULL, NULL, NULL, &(struct timespec) { 0, 250000000 }, NULL);
|
||||
+ if (r != 0)
|
||||
+ return (void*) -1;
|
||||
+
|
||||
+ pthread_cleanup_pop (0);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+tf_clock_nanosleep (void *arg)
|
||||
+{
|
||||
+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
|
||||
+ xpthread_barrier_wait (&b);
|
||||
+
|
||||
+ int r;
|
||||
+ pthread_cleanup_push (cl, NULL);
|
||||
+
|
||||
+ r = clock_nanosleep (CLOCK_REALTIME, 0, &(struct timespec) { 0, 250000000 },
|
||||
+ NULL);
|
||||
+ if (r != 0)
|
||||
+ return (void*) -1;
|
||||
+
|
||||
+ pthread_cleanup_pop (0);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+struct cancel_test_t
|
||||
+{
|
||||
+ const char *name;
|
||||
+ void * (*cf) (void *);
|
||||
+} tests[] =
|
||||
+{
|
||||
+ { "sigtimedwait", tf_sigtimedwait, },
|
||||
+ { "poll", tf_poll, },
|
||||
+ { "ppoll", tf_ppoll, },
|
||||
+ { "select", tf_select, },
|
||||
+ { "pselect", tf_pselect , },
|
||||
+ { "clock_nanosleep", tf_clock_nanosleep, },
|
||||
+};
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ for (int i = 0; i < array_length (tests); i++)
|
||||
+ {
|
||||
+ xpthread_barrier_init (&b, NULL, 2);
|
||||
+
|
||||
+ cl_called = 0;
|
||||
+
|
||||
+ pthread_t th = xpthread_create (NULL, tests[i].cf, NULL);
|
||||
+
|
||||
+ xpthread_barrier_wait (&b);
|
||||
+
|
||||
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
|
||||
+ while (nanosleep (&ts, &ts) != 0)
|
||||
+ continue;
|
||||
+
|
||||
+ xpthread_cancel (th);
|
||||
+
|
||||
+ void *status = xpthread_join (th);
|
||||
+ if (status != NULL)
|
||||
+ printf ("test '%s' failed: %" PRIdPTR "\n", tests[i].name,
|
||||
+ (intptr_t) status);
|
||||
+ TEST_VERIFY (status == NULL);
|
||||
+
|
||||
+ xpthread_barrier_destroy (&b);
|
||||
+
|
||||
+ TEST_COMPARE (cl_called, 0);
|
||||
+
|
||||
+ printf ("in-time cancel test of '%s' successful\n", tests[i].name);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
--
|
||||
2.35.2
|
||||
|
@ -1,50 +0,0 @@
|
||||
From 1dd783fafdbc30bd82e078ccab42b9539d3274a5 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Tue, 15 Feb 2022 06:57:11 -0800
|
||||
Subject: [PATCH] elf: Check invalid hole in PT_LOAD segments [BZ #28838]
|
||||
|
||||
Changes in v2:
|
||||
|
||||
1. Update commit log.
|
||||
|
||||
commit 163f625cf9becbb82dfec63a29e566324129c0cd
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Tue Dec 21 12:35:47 2021 -0800
|
||||
|
||||
elf: Remove excessive p_align check on PT_LOAD segments [BZ #28688]
|
||||
|
||||
removed the p_align check against the page size. It caused the loader
|
||||
error or crash on elf/tst-p_align3 when loading elf/tst-p_alignmod3.so,
|
||||
which has the invalid p_align in PT_LOAD segments, added by
|
||||
|
||||
commit d8d94863ef125a392b929732b37e07dc927fbcd1
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Tue Dec 21 13:42:28 2021 -0800
|
||||
|
||||
The loader failure caused by a negative length passed to __mprotect is
|
||||
random, depending on architecture and toolchain. Update _dl_map_segments
|
||||
to detect invalid holes. This fixes BZ #28838.
|
||||
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||
(cherry picked from commit 2c0915cbf570cb9c8a65f1d20a55c5a7238e5b63)
|
||||
---
|
||||
elf/dl-map-segments.h | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
|
||||
index 172692b120..fd24cf5d01 100644
|
||||
--- a/elf/dl-map-segments.h
|
||||
+++ b/elf/dl-map-segments.h
|
||||
@@ -113,6 +113,9 @@ _dl_map_segments (struct link_map *l, int fd,
|
||||
unallocated. Then jump into the normal segment-mapping loop to
|
||||
handle the portion of the segment past the end of the file
|
||||
mapping. */
|
||||
+ if (__glibc_unlikely (loadcmds[nloadcmds - 1].mapstart <
|
||||
+ c->mapend))
|
||||
+ return N_("ELF load command address/offset not page-aligned");
|
||||
if (__glibc_unlikely
|
||||
(__mprotect ((caddr_t) (l->l_addr + c->mapend),
|
||||
loadcmds[nloadcmds - 1].mapstart - c->mapend,
|
||||
--
|
||||
2.35.0
|
||||
|
@ -1,129 +0,0 @@
|
||||
From dc30acf20bd635d71cd4c84100e842fdf0429e48 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Schwab <schwab@suse.de>
|
||||
Date: Wed, 22 Jun 2022 13:16:30 +0200
|
||||
Subject: [PATCH] debug: make __read_chk a cancellation point (bug 29274)
|
||||
|
||||
The __read_chk function, as the implementation behind the fortified read
|
||||
function, must be a cancellation point, thus it cannot use INLINE_SYSCALL.
|
||||
---
|
||||
debug/Makefile | 7 ++++++
|
||||
debug/read_chk.c | 10 --------
|
||||
debug/tst-read-chk-cancel.c | 50 +++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 57 insertions(+), 10 deletions(-)
|
||||
create mode 100644 debug/tst-read-chk-cancel.c
|
||||
|
||||
diff --git a/debug/Makefile b/debug/Makefile
|
||||
index 96029f32ee..456b349c4d 100644
|
||||
--- a/debug/Makefile
|
||||
+++ b/debug/Makefile
|
||||
@@ -110,6 +110,7 @@ CPPFLAGS-tst-longjmp_chk2.c += -D_FORTIFY_SOURCE=1
|
||||
CFLAGS-tst-longjmp_chk3.c += -fexceptions -fasynchronous-unwind-tables
|
||||
CPPFLAGS-tst-longjmp_chk3.c += -D_FORTIFY_SOURCE=1
|
||||
CPPFLAGS-tst-realpath-chk.c += -D_FORTIFY_SOURCE=2
|
||||
+CPPFLAGS-tst-read-chk-cancel.c += -D_FORTIFY_SOURCE=2
|
||||
|
||||
# _FORTIFY_SOURCE tests.
|
||||
# Auto-generate tests for _FORTIFY_SOURCE for different levels, compilers and
|
||||
@@ -204,6 +205,10 @@ ifeq ($(have-ssp),yes)
|
||||
tests += tst-ssp-1
|
||||
endif
|
||||
|
||||
+ifeq ($(have-thread-library), yes)
|
||||
+tests += tst-read-chk-cancel
|
||||
+endif
|
||||
+
|
||||
ifeq (,$(CXX))
|
||||
tests-unsupported = $(tests-cc-chk)
|
||||
endif
|
||||
@@ -242,3 +247,5 @@ $(objpfx)xtrace: xtrace.sh
|
||||
-e 's|@BINDIR@|$(bindir)|' -e 's|@PKGVERSION@|$(PKGVERSION)|' \
|
||||
-e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|' $^ > $@.new \
|
||||
&& rm -f $@ && mv $@.new $@ && chmod +x $@
|
||||
+
|
||||
+$(objpfx)tst-read-chk-cancel: $(shared-thread-library)
|
||||
diff --git a/debug/read_chk.c b/debug/read_chk.c
|
||||
index 0cd58db8cb..274b4f93e9 100644
|
||||
--- a/debug/read_chk.c
|
||||
+++ b/debug/read_chk.c
|
||||
@@ -16,12 +16,6 @@
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <unistd.h>
|
||||
-#include <sys/param.h>
|
||||
-#ifdef HAVE_INLINED_SYSCALLS
|
||||
-# include <errno.h>
|
||||
-# include <sysdep.h>
|
||||
-#endif
|
||||
-
|
||||
|
||||
ssize_t
|
||||
__read_chk (int fd, void *buf, size_t nbytes, size_t buflen)
|
||||
@@ -29,9 +23,5 @@ __read_chk (int fd, void *buf, size_t nbytes, size_t buflen)
|
||||
if (nbytes > buflen)
|
||||
__chk_fail ();
|
||||
|
||||
-#ifdef HAVE_INLINED_SYSCALLS
|
||||
- return INLINE_SYSCALL (read, 3, fd, buf, nbytes);
|
||||
-#else
|
||||
return __read (fd, buf, nbytes);
|
||||
-#endif
|
||||
}
|
||||
diff --git a/debug/tst-read-chk-cancel.c b/debug/tst-read-chk-cancel.c
|
||||
new file mode 100644
|
||||
index 0000000000..7e06afb596
|
||||
--- /dev/null
|
||||
+++ b/debug/tst-read-chk-cancel.c
|
||||
@@ -0,0 +1,50 @@
|
||||
+/* Test that __read_chk is a cancellation point (BZ #29274)
|
||||
+ 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 <stdint.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <support/xthread.h>
|
||||
+
|
||||
+static int pipe_fds[2];
|
||||
+static pthread_barrier_t barrier;
|
||||
+
|
||||
+static void *
|
||||
+read_thread (void *n)
|
||||
+{
|
||||
+ xpthread_barrier_wait (&barrier);
|
||||
+ char c;
|
||||
+ /* This call should be forwarded to __read_chk because the buffer size
|
||||
+ is known, but the read length is non-constant. */
|
||||
+ if (read (pipe_fds[0], &c, (uintptr_t) n) != 1)
|
||||
+ return (void *) -1L;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ xpthread_barrier_init (&barrier, 0, 2);
|
||||
+ xpipe (pipe_fds);
|
||||
+ pthread_t thr = xpthread_create (0, read_thread, (void *) 1L);
|
||||
+ xpthread_barrier_wait (&barrier);
|
||||
+ xpthread_cancel (thr);
|
||||
+ xpthread_join (thr);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,132 +0,0 @@
|
||||
From fd412fff6d2bd322ec24ebd13fab196efc6c5506 Mon Sep 17 00:00:00 2001
|
||||
From: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Tue, 15 Feb 2022 08:18:15 -0600
|
||||
Subject: [PATCH] x86: Fallback {str|wcs}cmp RTM in the ncmp overflow case [BZ
|
||||
#28896]
|
||||
|
||||
In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would
|
||||
call strcmp-avx2 and wcscmp-avx2 respectively. This would have
|
||||
not checks around vzeroupper and would trigger spurious
|
||||
aborts. This commit fixes that.
|
||||
|
||||
test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on
|
||||
AVX2 machines with and without RTM.
|
||||
|
||||
Co-authored-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
(cherry picked from commit c6272098323153db373f2986c67786ea8c85f1cf)
|
||||
---
|
||||
sysdeps/x86/Makefile | 2 +-
|
||||
sysdeps/x86/tst-strncmp-rtm.c | 17 ++++++++++++++++-
|
||||
sysdeps/x86_64/multiarch/strcmp-avx2.S | 2 +-
|
||||
sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S | 1 +
|
||||
sysdeps/x86_64/multiarch/strncmp-avx2.S | 1 +
|
||||
sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S | 2 +-
|
||||
sysdeps/x86_64/multiarch/wcsncmp-avx2.S | 2 +-
|
||||
7 files changed, 22 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
|
||||
index 6cf708335c..d110f7b7f2 100644
|
||||
--- a/sysdeps/x86/Makefile
|
||||
+++ b/sysdeps/x86/Makefile
|
||||
@@ -109,7 +109,7 @@ CFLAGS-tst-memset-rtm.c += -mrtm
|
||||
CFLAGS-tst-strchr-rtm.c += -mrtm
|
||||
CFLAGS-tst-strcpy-rtm.c += -mrtm
|
||||
CFLAGS-tst-strlen-rtm.c += -mrtm
|
||||
-CFLAGS-tst-strncmp-rtm.c += -mrtm
|
||||
+CFLAGS-tst-strncmp-rtm.c += -mrtm -Wno-error
|
||||
CFLAGS-tst-strrchr-rtm.c += -mrtm
|
||||
endif
|
||||
|
||||
diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c
|
||||
index 09ed6fa0d6..9e20abaacc 100644
|
||||
--- a/sysdeps/x86/tst-strncmp-rtm.c
|
||||
+++ b/sysdeps/x86/tst-strncmp-rtm.c
|
||||
@@ -16,6 +16,7 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
+#include <stdint.h>
|
||||
#include <tst-string-rtm.h>
|
||||
|
||||
#define LOOP 3000
|
||||
@@ -45,8 +46,22 @@ function (void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
+__attribute__ ((noinline, noclone))
|
||||
+static int
|
||||
+function_overflow (void)
|
||||
+{
|
||||
+ if (strncmp (string1, string2, SIZE_MAX) == 0)
|
||||
+ return 0;
|
||||
+ else
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
- return do_test_1 ("strncmp", LOOP, prepare, function);
|
||||
+ int status = do_test_1 ("strncmp", LOOP, prepare, function);
|
||||
+ if (status != EXIT_SUCCESS)
|
||||
+ return status;
|
||||
+ status = do_test_1 ("strncmp", LOOP, prepare, function_overflow);
|
||||
+ return status;
|
||||
}
|
||||
diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S
|
||||
index 9c73b5899d..cdcb3c5a26 100644
|
||||
--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S
|
||||
+++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S
|
||||
@@ -95,7 +95,7 @@ ENTRY (STRCMP)
|
||||
length to bound a valid memory region. In these cases just use
|
||||
'wcscmp'. */
|
||||
shrq $56, %rcx
|
||||
- jnz __wcscmp_avx2
|
||||
+ jnz OVERFLOW_STRCMP
|
||||
# endif
|
||||
/* Convert units: from wide to byte char. */
|
||||
shl $2, %RDX_LP
|
||||
diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S
|
||||
index 37d1224bb9..68bad365ba 100644
|
||||
--- a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S
|
||||
+++ b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S
|
||||
@@ -1,3 +1,4 @@
|
||||
#define STRCMP __strncmp_avx2_rtm
|
||||
#define USE_AS_STRNCMP 1
|
||||
+#define OVERFLOW_STRCMP __strcmp_avx2_rtm
|
||||
#include "strcmp-avx2-rtm.S"
|
||||
diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2.S b/sysdeps/x86_64/multiarch/strncmp-avx2.S
|
||||
index 1678bcc235..f138e9f1fd 100644
|
||||
--- a/sysdeps/x86_64/multiarch/strncmp-avx2.S
|
||||
+++ b/sysdeps/x86_64/multiarch/strncmp-avx2.S
|
||||
@@ -1,3 +1,4 @@
|
||||
#define STRCMP __strncmp_avx2
|
||||
#define USE_AS_STRNCMP 1
|
||||
+#define OVERFLOW_STRCMP __strcmp_avx2
|
||||
#include "strcmp-avx2.S"
|
||||
diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S
|
||||
index 4e88c70cc6..f467582cbe 100644
|
||||
--- a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S
|
||||
+++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S
|
||||
@@ -1,5 +1,5 @@
|
||||
#define STRCMP __wcsncmp_avx2_rtm
|
||||
#define USE_AS_STRNCMP 1
|
||||
#define USE_AS_WCSCMP 1
|
||||
-
|
||||
+#define OVERFLOW_STRCMP __wcscmp_avx2_rtm
|
||||
#include "strcmp-avx2-rtm.S"
|
||||
diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S
|
||||
index 4fa1de4d3f..e9ede522b8 100644
|
||||
--- a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S
|
||||
+++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S
|
||||
@@ -1,5 +1,5 @@
|
||||
#define STRCMP __wcsncmp_avx2
|
||||
#define USE_AS_STRNCMP 1
|
||||
#define USE_AS_WCSCMP 1
|
||||
-
|
||||
+#define OVERFLOW_STRCMP __wcscmp_avx2
|
||||
#include "strcmp-avx2.S"
|
||||
--
|
||||
2.35.0
|
||||
|
@ -1,48 +0,0 @@
|
||||
From 0a1572b8bb880a63d50a63b2afe4bb67704ac23e Mon Sep 17 00:00:00 2001
|
||||
From: Matheus Castanho <msc@linux.ibm.com>
|
||||
Date: Tue, 7 Jun 2022 10:27:26 -0300
|
||||
Subject: [PATCH] powerpc: Fix VSX register number on __strncpy_power9 [BZ
|
||||
#29197]
|
||||
|
||||
__strncpy_power9 initializes VR 18 with zeroes to be used throughout the
|
||||
code, including when zero-padding the destination string. However, the
|
||||
v18 reference was mistakenly being used for stxv and stxvl, which take a
|
||||
VSX vector as operand. The code ended up using the uninitialized VSR 18
|
||||
register by mistake.
|
||||
|
||||
Both occurrences have been changed to use the proper VSX number for VR 18
|
||||
(i.e. VSR 50).
|
||||
|
||||
Tested on powerpc, powerpc64 and powerpc64le.
|
||||
|
||||
Signed-off-by: Kewen Lin <linkw@gcc.gnu.org>
|
||||
(cherry picked from commit 0218463dd8265ed937622f88ac68c7d984fe0cfc)
|
||||
---
|
||||
sysdeps/powerpc/powerpc64/le/power9/strncpy.S | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/le/power9/strncpy.S b/sysdeps/powerpc/powerpc64/le/power9/strncpy.S
|
||||
index ae23161316..deb94671cc 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/le/power9/strncpy.S
|
||||
+++ b/sysdeps/powerpc/powerpc64/le/power9/strncpy.S
|
||||
@@ -352,7 +352,7 @@ L(zero_padding_loop):
|
||||
cmpldi cr6,r5,16 /* Check if length was reached. */
|
||||
ble cr6,L(zero_padding_end)
|
||||
|
||||
- stxv v18,0(r11)
|
||||
+ stxv 32+v18,0(r11)
|
||||
addi r11,r11,16
|
||||
addi r5,r5,-16
|
||||
|
||||
@@ -360,7 +360,7 @@ L(zero_padding_loop):
|
||||
|
||||
L(zero_padding_end):
|
||||
sldi r10,r5,56 /* stxvl wants size in top 8 bits */
|
||||
- stxvl v18,r11,r10 /* Partial store */
|
||||
+ stxvl 32+v18,r11,r10 /* Partial store */
|
||||
blr
|
||||
|
||||
.align 4
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,224 +0,0 @@
|
||||
From 9bcd12d223a8990254b65e2dada54faa5d2742f3 Mon Sep 17 00:00:00 2001
|
||||
From: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Fri, 13 May 2022 19:10:15 +0530
|
||||
Subject: [PATCH] wcrtomb: Make behavior POSIX compliant
|
||||
|
||||
The GNU implementation of wcrtomb assumes that there are at least
|
||||
MB_CUR_MAX bytes available in the destination buffer passed to wcrtomb
|
||||
as the first argument. This is not compatible with the POSIX
|
||||
definition, which only requires enough space for the input wide
|
||||
character.
|
||||
|
||||
This does not break much in practice because when users supply buffers
|
||||
smaller than MB_CUR_MAX (e.g. in ncurses), they compute and dynamically
|
||||
allocate the buffer, which results in enough spare space (thanks to
|
||||
usable_size in malloc and padding in alloca) that no actual buffer
|
||||
overflow occurs. However when the code is built with _FORTIFY_SOURCE,
|
||||
it runs into the hard check against MB_CUR_MAX in __wcrtomb_chk and
|
||||
hence fails. It wasn't evident until now since dynamic allocations
|
||||
would result in wcrtomb not being fortified but since _FORTIFY_SOURCE=3,
|
||||
that limitation is gone, resulting in such code failing.
|
||||
|
||||
To fix this problem, introduce an internal buffer that is MB_LEN_MAX
|
||||
long and use that to perform the conversion and then copy the resultant
|
||||
bytes into the destination buffer. Also move the fortification check
|
||||
into the main implementation, which checks the result after conversion
|
||||
and aborts if the resultant byte count is greater than the destination
|
||||
buffer size.
|
||||
|
||||
One complication is that applications that assume the MB_CUR_MAX
|
||||
limitation to be gone may not be able to run safely on older glibcs if
|
||||
they use static destination buffers smaller than MB_CUR_MAX; dynamic
|
||||
allocations will always have enough spare space that no actual overruns
|
||||
will occur. One alternative to fixing this is to bump symbol version to
|
||||
prevent them from running on older glibcs but that seems too strict a
|
||||
constraint. Instead, since these users will only have made this
|
||||
decision on reading the manual, I have put a note in the manual warning
|
||||
them about the pitfalls of having static buffers smaller than
|
||||
MB_CUR_MAX and running them on older glibc.
|
||||
|
||||
Benchmarking:
|
||||
|
||||
The wcrtomb microbenchmark shows significant increases in maximum
|
||||
execution time for all locales, ranging from 10x for ar_SA.UTF-8 to
|
||||
1.5x-2x for nearly everything else. The mean execution time however saw
|
||||
practically no impact, with some results even being quicker, indicating
|
||||
that cache locality has a much bigger role in the overhead.
|
||||
|
||||
Given that the additional copy uses a temporary buffer inside wcrtomb,
|
||||
it's likely that a hot path will end up putting that buffer (which is
|
||||
responsible for the additional overhead) in a similar place on stack,
|
||||
giving the necessary cache locality to negate the overhead. However in
|
||||
situations where wcrtomb ends up getting called at wildly different
|
||||
spots on the call stack (or is on different call stacks, e.g. with
|
||||
threads or different execution contexts) and is still a hotspot, the
|
||||
performance lag will be visible.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
---
|
||||
debug/tst-fortify.c | 7 ++++++-
|
||||
debug/wcrtomb_chk.c | 8 ++------
|
||||
include/wchar.h | 4 ++++
|
||||
manual/charset.texi | 11 ++++++-----
|
||||
wcsmbs/wcrtomb.c | 31 +++++++++++++++++++++++--------
|
||||
5 files changed, 41 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c
|
||||
index 03c9867714..8e94643bf2 100644
|
||||
--- a/debug/tst-fortify.c
|
||||
+++ b/debug/tst-fortify.c
|
||||
@@ -1478,10 +1478,15 @@ do_test (void)
|
||||
character which has a multibyte representation which does not
|
||||
fit. */
|
||||
CHK_FAIL_START
|
||||
- char smallbuf[2];
|
||||
+ char smallbuf[1];
|
||||
if (wcrtomb (smallbuf, L'\x100', &s) != 2)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
+
|
||||
+ /* Same input with a large enough buffer and we're good. */
|
||||
+ char bigenoughbuf[2];
|
||||
+ if (wcrtomb (bigenoughbuf, L'\x100', &s) != 2)
|
||||
+ FAIL ();
|
||||
#endif
|
||||
|
||||
wchar_t wenough[10];
|
||||
diff --git a/debug/wcrtomb_chk.c b/debug/wcrtomb_chk.c
|
||||
index 8b6d026560..28c3ea0d2d 100644
|
||||
--- a/debug/wcrtomb_chk.c
|
||||
+++ b/debug/wcrtomb_chk.c
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (C) 2005-2022 Free Software Foundation, Inc.
|
||||
+ Copyright The GNU Toolchain Authors.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -25,10 +26,5 @@
|
||||
size_t
|
||||
__wcrtomb_chk (char *s, wchar_t wchar, mbstate_t *ps, size_t buflen)
|
||||
{
|
||||
- /* We do not have to implement the full wctomb semantics since we
|
||||
- know that S cannot be NULL when we come here. */
|
||||
- if (buflen < MB_CUR_MAX)
|
||||
- __chk_fail ();
|
||||
-
|
||||
- return __wcrtomb (s, wchar, ps);
|
||||
+ return __wcrtomb_internal (s, wchar, ps, buflen);
|
||||
}
|
||||
diff --git a/include/wchar.h b/include/wchar.h
|
||||
index 4267985625..db83297bca 100644
|
||||
--- a/include/wchar.h
|
||||
+++ b/include/wchar.h
|
||||
@@ -172,6 +172,10 @@ libc_hidden_proto (__mbrtowc)
|
||||
libc_hidden_proto (__mbrlen)
|
||||
extern size_t __wcrtomb (char *__restrict __s, wchar_t __wc,
|
||||
__mbstate_t *__restrict __ps) attribute_hidden;
|
||||
+extern size_t __wcrtomb_internal (char *__restrict __s, wchar_t __wc,
|
||||
+ __mbstate_t *__restrict __ps,
|
||||
+ size_t __s_size)
|
||||
+ attribute_hidden;
|
||||
extern size_t __mbsrtowcs (wchar_t *__restrict __dst,
|
||||
const char **__restrict __src,
|
||||
size_t __len, __mbstate_t *__restrict __ps)
|
||||
diff --git a/manual/charset.texi b/manual/charset.texi
|
||||
index a9b5cb4a37..427db3bc80 100644
|
||||
--- a/manual/charset.texi
|
||||
+++ b/manual/charset.texi
|
||||
@@ -883,11 +883,12 @@ the string @var{s}. This includes all bytes representing shift
|
||||
sequences.
|
||||
|
||||
One word about the interface of the function: there is no parameter
|
||||
-specifying the length of the array @var{s}. Instead the function
|
||||
-assumes that there are at least @code{MB_CUR_MAX} bytes available since
|
||||
-this is the maximum length of any byte sequence representing a single
|
||||
-character. So the caller has to make sure that there is enough space
|
||||
-available, otherwise buffer overruns can occur.
|
||||
+specifying the length of the array @var{s}, so the caller has to make sure
|
||||
+that there is enough space available, otherwise buffer overruns can occur.
|
||||
+This version of @theglibc{} does not assume that @var{s} is at least
|
||||
+@var{MB_CUR_MAX} bytes long, but programs that need to run on @glibcadj{}
|
||||
+versions that have this assumption documented in the manual must comply
|
||||
+with this limit.
|
||||
|
||||
@pindex wchar.h
|
||||
@code{wcrtomb} was introduced in @w{Amendment 1} to @w{ISO C90} and is
|
||||
diff --git a/wcsmbs/wcrtomb.c b/wcsmbs/wcrtomb.c
|
||||
index e17438989f..c0cce3792f 100644
|
||||
--- a/wcsmbs/wcrtomb.c
|
||||
+++ b/wcsmbs/wcrtomb.c
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (C) 1996-2022 Free Software Foundation, Inc.
|
||||
+ Copyright The GNU Toolchain Authors.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -20,6 +21,7 @@
|
||||
#include <errno.h>
|
||||
#include <gconv.h>
|
||||
#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <wcsmbsload.h>
|
||||
|
||||
@@ -34,7 +36,7 @@
|
||||
static mbstate_t state;
|
||||
|
||||
size_t
|
||||
-__wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
|
||||
+__wcrtomb_internal (char *s, wchar_t wc, mbstate_t *ps, size_t s_size)
|
||||
{
|
||||
char buf[MB_LEN_MAX];
|
||||
struct __gconv_step_data data;
|
||||
@@ -52,14 +54,11 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
|
||||
/* A first special case is if S is NULL. This means put PS in the
|
||||
initial state. */
|
||||
if (s == NULL)
|
||||
- {
|
||||
- s = buf;
|
||||
- wc = L'\0';
|
||||
- }
|
||||
+ wc = L'\0';
|
||||
|
||||
/* Tell where we want to have the result. */
|
||||
- data.__outbuf = (unsigned char *) s;
|
||||
- data.__outbufend = (unsigned char *) s + MB_CUR_MAX;
|
||||
+ data.__outbuf = (unsigned char *) buf;
|
||||
+ data.__outbufend = (unsigned char *) buf + sizeof buf;
|
||||
|
||||
/* Get the conversion functions. */
|
||||
fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));
|
||||
@@ -101,7 +100,17 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
|
||||
|
||||
if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT
|
||||
|| status == __GCONV_FULL_OUTPUT)
|
||||
- result = data.__outbuf - (unsigned char *) s;
|
||||
+ {
|
||||
+ result = data.__outbuf - (unsigned char *) buf;
|
||||
+
|
||||
+ if (s != NULL)
|
||||
+ {
|
||||
+ if (result > s_size)
|
||||
+ __chk_fail ();
|
||||
+
|
||||
+ memcpy (s, buf, result);
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
{
|
||||
result = (size_t) -1;
|
||||
@@ -110,5 +119,11 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
|
||||
|
||||
return result;
|
||||
}
|
||||
+
|
||||
+size_t
|
||||
+__wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
|
||||
+{
|
||||
+ return __wcrtomb_internal (s, wc, ps, (size_t) -1);
|
||||
+}
|
||||
weak_alias (__wcrtomb, wcrtomb)
|
||||
libc_hidden_weak (wcrtomb)
|
||||
--
|
||||
2.35.3
|
||||
|
Loading…
Reference in New Issue
Block a user