forked from rpms/glibc
Sync with upstream branch release/2.34/master
Upstream commit: 0ea8174d62263c2679c95c0d215d2627e560f7aa - gmon: fix memory corruption issues [BZ# 30101] - gmon: improve mcount overflow handling [BZ# 27576] - gmon: Fix allocated buffer overflow (bug 29444) - posix: Fix system blocks SIGCHLD erroneously [BZ #30163] - x86_64: Fix asm constraints in feraiseexcept (bug 30305) - gshadow: Matching sgetsgent, sgetsgent_r ERANGE handling (bug 30151) - x86: Check minimum/maximum of non_temporal_threshold [BZ #29953] Resolves: #2188641 Resolves: #2172947 Resolves: #2177235 Resolves: #2177705 Resolves: #2180173
This commit is contained in:
parent
2511b1027f
commit
17e18d1a08
66
glibc-upstream-2.34-391.patch
Normal file
66
glibc-upstream-2.34-391.patch
Normal file
@ -0,0 +1,66 @@
|
||||
commit 89c017de2f52d17862bda9a6f8382e913457bfbe
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Tue Jan 3 13:06:48 2023 -0800
|
||||
|
||||
x86: Check minimum/maximum of non_temporal_threshold [BZ #29953]
|
||||
|
||||
The minimum non_temporal_threshold is 0x4040. non_temporal_threshold may
|
||||
be set to less than the minimum value when the shared cache size isn't
|
||||
available (e.g., in an emulator) or by the tunable. Add checks for
|
||||
minimum and maximum of non_temporal_threshold.
|
||||
|
||||
This fixes BZ #29953.
|
||||
|
||||
(cherry picked from commit 48b74865c63840b288bd85b4d8743533b73b339b)
|
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
index a7d2cc5fef03884b..f2d2de458db7358c 100644
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h
|
||||
@@ -747,6 +747,18 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
share of the cache, it has a substantial risk of negatively
|
||||
impacting the performance of other threads running on the chip. */
|
||||
unsigned long int non_temporal_threshold = shared * 3 / 4;
|
||||
+ /* SIZE_MAX >> 4 because memmove-vec-unaligned-erms right-shifts the value of
|
||||
+ 'x86_non_temporal_threshold' by `LOG_4X_MEMCPY_THRESH` (4) and it is best
|
||||
+ if that operation cannot overflow. Minimum of 0x4040 (16448) because the
|
||||
+ L(large_memset_4x) loops need 64-byte to cache align and enough space for
|
||||
+ at least 1 iteration of 4x PAGE_SIZE unrolled loop. Both values are
|
||||
+ reflected in the manual. */
|
||||
+ unsigned long int maximum_non_temporal_threshold = SIZE_MAX >> 4;
|
||||
+ unsigned long int minimum_non_temporal_threshold = 0x4040;
|
||||
+ if (non_temporal_threshold < minimum_non_temporal_threshold)
|
||||
+ non_temporal_threshold = minimum_non_temporal_threshold;
|
||||
+ else if (non_temporal_threshold > maximum_non_temporal_threshold)
|
||||
+ non_temporal_threshold = maximum_non_temporal_threshold;
|
||||
|
||||
#if HAVE_TUNABLES
|
||||
/* NB: The REP MOVSB threshold must be greater than VEC_SIZE * 8. */
|
||||
@@ -801,8 +813,8 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
shared = tunable_size;
|
||||
|
||||
tunable_size = TUNABLE_GET (x86_non_temporal_threshold, long int, NULL);
|
||||
- /* NB: Ignore the default value 0. */
|
||||
- if (tunable_size != 0)
|
||||
+ if (tunable_size > minimum_non_temporal_threshold
|
||||
+ && tunable_size <= maximum_non_temporal_threshold)
|
||||
non_temporal_threshold = tunable_size;
|
||||
|
||||
tunable_size = TUNABLE_GET (x86_rep_movsb_threshold, long int, NULL);
|
||||
@@ -817,14 +829,9 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
|
||||
TUNABLE_SET_WITH_BOUNDS (x86_data_cache_size, data, 0, SIZE_MAX);
|
||||
TUNABLE_SET_WITH_BOUNDS (x86_shared_cache_size, shared, 0, SIZE_MAX);
|
||||
- /* SIZE_MAX >> 4 because memmove-vec-unaligned-erms right-shifts the value of
|
||||
- 'x86_non_temporal_threshold' by `LOG_4X_MEMCPY_THRESH` (4) and it is best
|
||||
- if that operation cannot overflow. Minimum of 0x4040 (16448) because the
|
||||
- L(large_memset_4x) loops need 64-byte to cache align and enough space for
|
||||
- at least 1 iteration of 4x PAGE_SIZE unrolled loop. Both values are
|
||||
- reflected in the manual. */
|
||||
TUNABLE_SET_WITH_BOUNDS (x86_non_temporal_threshold, non_temporal_threshold,
|
||||
- 0x4040, SIZE_MAX >> 4);
|
||||
+ minimum_non_temporal_threshold,
|
||||
+ maximum_non_temporal_threshold);
|
||||
TUNABLE_SET_WITH_BOUNDS (x86_rep_movsb_threshold, rep_movsb_threshold,
|
||||
minimum_rep_movsb_threshold, SIZE_MAX);
|
||||
TUNABLE_SET_WITH_BOUNDS (x86_rep_stosb_threshold, rep_stosb_threshold, 1,
|
122
glibc-upstream-2.34-392.patch
Normal file
122
glibc-upstream-2.34-392.patch
Normal file
@ -0,0 +1,122 @@
|
||||
commit 6a0d56b009e34caea9cbc0bbec3272345ea8f55a
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Feb 21 09:20:28 2023 +0100
|
||||
|
||||
gshadow: Matching sgetsgent, sgetsgent_r ERANGE handling (bug 30151)
|
||||
|
||||
Before this change, sgetsgent_r did not set errno to ERANGE, but
|
||||
sgetsgent only check errno, not the return value from sgetsgent_r.
|
||||
Consequently, sgetsgent did not detect any error, and reported
|
||||
success to the caller, without initializing the struct sgrp object
|
||||
whose address was returned.
|
||||
|
||||
This commit changes sgetsgent_r to set errno as well. This avoids
|
||||
similar issues in applications which only change errno.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 969e9733c7d17edf1e239a73fa172f357561f440)
|
||||
|
||||
diff --git a/gshadow/Makefile b/gshadow/Makefile
|
||||
index 2fdd0c7641d3655f..094a6c7b5aaad16b 100644
|
||||
--- a/gshadow/Makefile
|
||||
+++ b/gshadow/Makefile
|
||||
@@ -26,7 +26,7 @@ headers = gshadow.h
|
||||
routines = getsgent getsgnam sgetsgent fgetsgent putsgent \
|
||||
getsgent_r getsgnam_r sgetsgent_r fgetsgent_r
|
||||
|
||||
-tests = tst-gshadow tst-putsgent tst-fgetsgent_r
|
||||
+tests = tst-gshadow tst-putsgent tst-fgetsgent_r tst-sgetsgent
|
||||
|
||||
CFLAGS-getsgent_r.c += -fexceptions
|
||||
CFLAGS-getsgent.c += -fexceptions
|
||||
diff --git a/gshadow/sgetsgent_r.c b/gshadow/sgetsgent_r.c
|
||||
index 565463b07e8facbe..ae500d64c386d964 100644
|
||||
--- a/gshadow/sgetsgent_r.c
|
||||
+++ b/gshadow/sgetsgent_r.c
|
||||
@@ -61,7 +61,10 @@ __sgetsgent_r (const char *string, struct sgrp *resbuf, char *buffer,
|
||||
buffer[buflen - 1] = '\0';
|
||||
sp = strncpy (buffer, string, buflen);
|
||||
if (buffer[buflen - 1] != '\0')
|
||||
- return ERANGE;
|
||||
+ {
|
||||
+ __set_errno (ERANGE);
|
||||
+ return ERANGE;
|
||||
+ }
|
||||
}
|
||||
else
|
||||
sp = (char *) string;
|
||||
diff --git a/gshadow/tst-sgetsgent.c b/gshadow/tst-sgetsgent.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..0370c10fd0630b42
|
||||
--- /dev/null
|
||||
+++ b/gshadow/tst-sgetsgent.c
|
||||
@@ -0,0 +1,69 @@
|
||||
+/* Test large input for sgetsgent (bug 30151).
|
||||
+ Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <gshadow.h>
|
||||
+#include <stddef.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xmemstream.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Create a shadow group with 1000 members. */
|
||||
+ struct xmemstream mem;
|
||||
+ xopen_memstream (&mem);
|
||||
+ const char *passwd = "k+zD0nucwfxAo3sw1NXUj6K5vt5M16+X0TVGdE1uFvq5R8V7efJ";
|
||||
+ fprintf (mem.out, "group-name:%s::m0", passwd);
|
||||
+ for (int i = 1; i < 1000; ++i)
|
||||
+ fprintf (mem.out, ",m%d", i);
|
||||
+ xfclose_memstream (&mem);
|
||||
+
|
||||
+ /* Call sgetsgent. */
|
||||
+ char *input = mem.buffer;
|
||||
+ struct sgrp *e = sgetsgent (input);
|
||||
+ TEST_VERIFY_EXIT (e != NULL);
|
||||
+ TEST_COMPARE_STRING (e->sg_namp, "group-name");
|
||||
+ TEST_COMPARE_STRING (e->sg_passwd, passwd);
|
||||
+ /* No administrators. */
|
||||
+ TEST_COMPARE_STRING (e->sg_adm[0], NULL);
|
||||
+ /* Check the members list. */
|
||||
+ for (int i = 0; i < 1000; ++i)
|
||||
+ {
|
||||
+ char *member = xasprintf ("m%d", i);
|
||||
+ TEST_COMPARE_STRING (e->sg_mem[i], member);
|
||||
+ free (member);
|
||||
+ }
|
||||
+ TEST_COMPARE_STRING (e->sg_mem[1000], NULL);
|
||||
+
|
||||
+ /* Check that putsgent brings back the input string. */
|
||||
+ xopen_memstream (&mem);
|
||||
+ TEST_COMPARE (putsgent (e, mem.out), 0);
|
||||
+ xfclose_memstream (&mem);
|
||||
+ /* Compare without the trailing '\n' that putsgent added. */
|
||||
+ TEST_COMPARE (mem.buffer[mem.length - 1], '\n');
|
||||
+ mem.buffer[mem.length - 1] = '\0';
|
||||
+ TEST_COMPARE_STRING (mem.buffer, input);
|
||||
+
|
||||
+ free (mem.buffer);
|
||||
+ free (input);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
36
glibc-upstream-2.34-393.patch
Normal file
36
glibc-upstream-2.34-393.patch
Normal file
@ -0,0 +1,36 @@
|
||||
commit 71eb9cc1ffd79e96549dfb16f8e86aaf88a3bac8
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Apr 3 17:23:11 2023 +0200
|
||||
|
||||
x86_64: Fix asm constraints in feraiseexcept (bug 30305)
|
||||
|
||||
The divss instruction clobbers its first argument, and the constraints
|
||||
need to reflect that. Fortunately, with GCC 12, generated code does
|
||||
not actually change, so there is no externally visible bug.
|
||||
|
||||
Suggested-by: Jakub Jelinek <jakub@redhat.com>
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit 5d1ccdda7b0c625751661d50977f3dfbc73f8eae)
|
||||
|
||||
diff --git a/sysdeps/x86_64/fpu/fraiseexcpt.c b/sysdeps/x86_64/fpu/fraiseexcpt.c
|
||||
index 44a1d93b34796e1a..a301b657c49b31b1 100644
|
||||
--- a/sysdeps/x86_64/fpu/fraiseexcpt.c
|
||||
+++ b/sysdeps/x86_64/fpu/fraiseexcpt.c
|
||||
@@ -33,7 +33,7 @@ __feraiseexcept (int excepts)
|
||||
/* One example of an invalid operation is 0.0 / 0.0. */
|
||||
float f = 0.0;
|
||||
|
||||
- __asm__ __volatile__ ("divss %0, %0 " : : "x" (f));
|
||||
+ __asm__ __volatile__ ("divss %0, %0 " : "+x" (f));
|
||||
(void) &f;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ __feraiseexcept (int excepts)
|
||||
float f = 1.0;
|
||||
float g = 0.0;
|
||||
|
||||
- __asm__ __volatile__ ("divss %1, %0" : : "x" (f), "x" (g));
|
||||
+ __asm__ __volatile__ ("divss %1, %0" : "+x" (f) : "x" (g));
|
||||
(void) &f;
|
||||
}
|
||||
|
278
glibc-upstream-2.34-394.patch
Normal file
278
glibc-upstream-2.34-394.patch
Normal file
@ -0,0 +1,278 @@
|
||||
commit 567f7413fb1179acd936766b542ea72f7ef60d8b
|
||||
Author: Adam Yi <ayi@janestreet.com>
|
||||
Date: Tue Mar 7 07:30:02 2023 -0500
|
||||
|
||||
posix: Fix system blocks SIGCHLD erroneously [BZ #30163]
|
||||
|
||||
Fix bug that SIGCHLD is erroneously blocked forever in the following
|
||||
scenario:
|
||||
|
||||
1. Thread A calls system but hasn't returned yet
|
||||
2. Thread B calls another system but returns
|
||||
|
||||
SIGCHLD would be blocked forever in thread B after its system() returns,
|
||||
even after the system() in thread A returns.
|
||||
|
||||
Although POSIX does not require, glibc system implementation aims to be
|
||||
thread and cancellation safe. This bug was introduced in
|
||||
5fb7fc96350575c9adb1316833e48ca11553be49 when we moved reverting signal
|
||||
mask to happen when the last concurrently running system returns,
|
||||
despite that signal mask is per thread. This commit reverts this logic
|
||||
and adds a test.
|
||||
|
||||
Signed-off-by: Adam Yi <ayi@janestreet.com>
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
(cherry picked from commit 436a604b7dc741fc76b5a6704c6cd8bb178518e7)
|
||||
|
||||
diff --git a/stdlib/tst-system.c b/stdlib/tst-system.c
|
||||
index 178808e048a9b3bc..d1413d7c6a4cb82c 100644
|
||||
--- a/stdlib/tst-system.c
|
||||
+++ b/stdlib/tst-system.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <support/check.h>
|
||||
#include <support/temp_file.h>
|
||||
#include <support/support.h>
|
||||
+#include <support/xthread.h>
|
||||
#include <support/xunistd.h>
|
||||
|
||||
static char *tmpdir;
|
||||
@@ -72,6 +73,20 @@ call_system (void *closure)
|
||||
}
|
||||
}
|
||||
|
||||
+static void *
|
||||
+sleep_and_check_sigchld (void *closure)
|
||||
+{
|
||||
+ double *seconds = (double *) closure;
|
||||
+ char cmd[namemax];
|
||||
+ sprintf (cmd, "sleep %lf" , *seconds);
|
||||
+ TEST_COMPARE (system (cmd), 0);
|
||||
+
|
||||
+ sigset_t blocked = {0};
|
||||
+ TEST_COMPARE (sigprocmask (SIG_BLOCK, NULL, &blocked), 0);
|
||||
+ TEST_COMPARE (sigismember (&blocked, SIGCHLD), 0);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
@@ -155,6 +170,17 @@ do_test (void)
|
||||
xchmod (_PATH_BSHELL, st.st_mode);
|
||||
}
|
||||
|
||||
+ {
|
||||
+ pthread_t long_sleep_thread = xpthread_create (NULL,
|
||||
+ sleep_and_check_sigchld,
|
||||
+ &(double) { 0.2 });
|
||||
+ pthread_t short_sleep_thread = xpthread_create (NULL,
|
||||
+ sleep_and_check_sigchld,
|
||||
+ &(double) { 0.1 });
|
||||
+ xpthread_join (short_sleep_thread);
|
||||
+ xpthread_join (long_sleep_thread);
|
||||
+ }
|
||||
+
|
||||
TEST_COMPARE (system (""), 0);
|
||||
|
||||
return 0;
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index 0aa9d41c5a890087..e7f66920f1abbb48 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -32,6 +32,8 @@ libsupport-routines = \
|
||||
check_hostent \
|
||||
check_netent \
|
||||
delayed_exit \
|
||||
+ dtotimespec \
|
||||
+ dtotimespec-time64 \
|
||||
ignore_stderr \
|
||||
next_to_fault \
|
||||
oom_error \
|
||||
diff --git a/support/dtotimespec-time64.c b/support/dtotimespec-time64.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..b3d5e351e3a631ac
|
||||
--- /dev/null
|
||||
+++ b/support/dtotimespec-time64.c
|
||||
@@ -0,0 +1,27 @@
|
||||
+/* Convert double to timespec. 64-bit time support.
|
||||
+ Copyright (C) 2011-2023 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library and is also part of gnulib.
|
||||
+ Patches to this file should be submitted to both projects.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <time.h>
|
||||
+
|
||||
+#if __TIMESIZE != 64
|
||||
+# define timespec __timespec64
|
||||
+# define time_t __time64_t
|
||||
+# define dtotimespec dtotimespec_time64
|
||||
+# include "dtotimespec.c"
|
||||
+#endif
|
||||
diff --git a/support/dtotimespec.c b/support/dtotimespec.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..cde5b4d74cba1932
|
||||
--- /dev/null
|
||||
+++ b/support/dtotimespec.c
|
||||
@@ -0,0 +1,50 @@
|
||||
+/* Convert double to timespec.
|
||||
+ Copyright (C) 2011-2023 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library and is also part of gnulib.
|
||||
+ Patches to this file should be submitted to both projects.
|
||||
+
|
||||
+ 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/>. */
|
||||
+
|
||||
+/* Convert the double value SEC to a struct timespec. Round toward
|
||||
+ positive infinity. On overflow, return an extremal value. */
|
||||
+
|
||||
+#include <support/timespec.h>
|
||||
+#include <intprops.h>
|
||||
+
|
||||
+struct timespec
|
||||
+dtotimespec (double sec)
|
||||
+{
|
||||
+ if (sec <= TYPE_MINIMUM (time_t))
|
||||
+ return make_timespec (TYPE_MINIMUM (time_t), 0);
|
||||
+ else if (sec >= 1.0 + TYPE_MAXIMUM (time_t))
|
||||
+ return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1);
|
||||
+ else
|
||||
+ {
|
||||
+ time_t s = sec;
|
||||
+ double frac = TIMESPEC_HZ * (sec - s);
|
||||
+ long ns = frac;
|
||||
+ ns += ns < frac;
|
||||
+ s += ns / TIMESPEC_HZ;
|
||||
+ ns %= TIMESPEC_HZ;
|
||||
+
|
||||
+ if (ns < 0)
|
||||
+ {
|
||||
+ s--;
|
||||
+ ns += TIMESPEC_HZ;
|
||||
+ }
|
||||
+
|
||||
+ return make_timespec (s, ns);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/support/shell-container.c b/support/shell-container.c
|
||||
index b2a4324dc7444be5..6fe925dc49075848 100644
|
||||
--- a/support/shell-container.c
|
||||
+++ b/support/shell-container.c
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <error.h>
|
||||
|
||||
#include <support/support.h>
|
||||
+#include <support/timespec.h>
|
||||
|
||||
/* Design considerations
|
||||
|
||||
@@ -171,6 +172,32 @@ kill_func (char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* Emulate the "/bin/sleep" command. No suffix support. Options are
|
||||
+ ignored. */
|
||||
+static int
|
||||
+sleep_func (char **argv)
|
||||
+{
|
||||
+ if (argv[0] == NULL)
|
||||
+ {
|
||||
+ fprintf (stderr, "sleep: missing operand\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ char *endptr = NULL;
|
||||
+ double sec = strtod (argv[0], &endptr);
|
||||
+ if (endptr == argv[0] || errno == ERANGE || sec < 0)
|
||||
+ {
|
||||
+ fprintf (stderr, "sleep: invalid time interval '%s'\n", argv[0]);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ struct timespec ts = dtotimespec (sec);
|
||||
+ if (nanosleep (&ts, NULL) < 0)
|
||||
+ {
|
||||
+ fprintf (stderr, "sleep: failed to nanosleep: %s\n", strerror (errno));
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* This is a list of all the built-in commands we understand. */
|
||||
static struct {
|
||||
const char *name;
|
||||
@@ -181,6 +208,7 @@ static struct {
|
||||
{ "cp", copy_func },
|
||||
{ "exit", exit_func },
|
||||
{ "kill", kill_func },
|
||||
+ { "sleep", sleep_func },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
diff --git a/support/timespec.h b/support/timespec.h
|
||||
index 0478aef51fdcc5ae..843a90d60675f37d 100644
|
||||
--- a/support/timespec.h
|
||||
+++ b/support/timespec.h
|
||||
@@ -57,6 +57,8 @@ int support_timespec_check_in_range (struct timespec expected,
|
||||
struct timespec observed,
|
||||
double lower_bound, double upper_bound);
|
||||
|
||||
+struct timespec dtotimespec (double sec) __attribute__((const));
|
||||
+
|
||||
#else
|
||||
struct timespec __REDIRECT (timespec_add, (struct timespec, struct timespec),
|
||||
timespec_add_time64);
|
||||
@@ -82,6 +84,8 @@ int __REDIRECT (support_timespec_check_in_range, (struct timespec expected,
|
||||
double lower_bound,
|
||||
double upper_bound),
|
||||
support_timespec_check_in_range_time64);
|
||||
+
|
||||
+struct timespec __REDIRECT (dtotimespec, (double sec), dtotimespec_time64);
|
||||
#endif
|
||||
|
||||
/* Check that the timespec on the left represents a time before the
|
||||
diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c
|
||||
index 48668fb392e67d1a..b9676abb1c6f35eb 100644
|
||||
--- a/sysdeps/posix/system.c
|
||||
+++ b/sysdeps/posix/system.c
|
||||
@@ -179,16 +179,16 @@ do_system (const char *line)
|
||||
as if the shell had terminated using _exit(127). */
|
||||
status = W_EXITCODE (127, 0);
|
||||
|
||||
+ /* sigaction can not fail with SIGINT/SIGQUIT used with old
|
||||
+ disposition. Same applies for sigprocmask. */
|
||||
DO_LOCK ();
|
||||
if (SUB_REF () == 0)
|
||||
{
|
||||
- /* sigaction can not fail with SIGINT/SIGQUIT used with old
|
||||
- disposition. Same applies for sigprocmask. */
|
||||
__sigaction (SIGINT, &intr, NULL);
|
||||
__sigaction (SIGQUIT, &quit, NULL);
|
||||
- __sigprocmask (SIG_SETMASK, &omask, NULL);
|
||||
}
|
||||
DO_UNLOCK ();
|
||||
+ __sigprocmask (SIG_SETMASK, &omask, NULL);
|
||||
|
||||
if (ret != 0)
|
||||
__set_errno (ret);
|
71
glibc-upstream-2.34-395.patch
Normal file
71
glibc-upstream-2.34-395.patch
Normal file
@ -0,0 +1,71 @@
|
||||
commit 8e1a8e04b153739a77289e6fc07cbfc252d87e02
|
||||
Author: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
|
||||
Date: Sat Feb 4 14:41:38 2023 +0300
|
||||
|
||||
gmon: Fix allocated buffer overflow (bug 29444)
|
||||
|
||||
The `__monstartup()` allocates a buffer used to store all the data
|
||||
accumulated by the monitor.
|
||||
|
||||
The size of this buffer depends on the size of the internal structures
|
||||
used and the address range for which the monitor is activated, as well
|
||||
as on the maximum density of call instructions and/or callable functions
|
||||
that could be potentially on a segment of executable code.
|
||||
|
||||
In particular a hash table of arcs is placed at the end of this buffer.
|
||||
The size of this hash table is calculated in bytes as
|
||||
p->fromssize = p->textsize / HASHFRACTION;
|
||||
|
||||
but actually should be
|
||||
p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms));
|
||||
|
||||
This results in writing beyond the end of the allocated buffer when an
|
||||
added arc corresponds to a call near from the end of the monitored
|
||||
address range, since `_mcount()` check the incoming caller address for
|
||||
monitored range but not the intermediate result hash-like index that
|
||||
uses to write into the table.
|
||||
|
||||
It should be noted that when the results are output to `gmon.out`, the
|
||||
table is read to the last element calculated from the allocated size in
|
||||
bytes, so the arcs stored outside the buffer boundary did not fall into
|
||||
`gprof` for analysis. Thus this "feature" help me to found this bug
|
||||
during working with https://sourceware.org/bugzilla/show_bug.cgi?id=29438
|
||||
|
||||
Just in case, I will explicitly note that the problem breaks the
|
||||
`make test t=gmon/tst-gmon-dso` added for Bug 29438.
|
||||
There, the arc of the `f3()` call disappears from the output, since in
|
||||
the DSO case, the call to `f3` is located close to the end of the
|
||||
monitored range.
|
||||
|
||||
Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
|
||||
|
||||
Another minor error seems a related typo in the calculation of
|
||||
`kcountsize`, but since kcounts are smaller than froms, this is
|
||||
actually to align the p->froms data.
|
||||
|
||||
Co-authored-by: DJ Delorie <dj@redhat.com>
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit 801af9fafd4689337ebf27260aa115335a0cb2bc)
|
||||
|
||||
diff --git a/gmon/gmon.c b/gmon/gmon.c
|
||||
index dee64803ada583d7..bf76358d5b1aa2da 100644
|
||||
--- a/gmon/gmon.c
|
||||
+++ b/gmon/gmon.c
|
||||
@@ -132,6 +132,8 @@ __monstartup (u_long lowpc, u_long highpc)
|
||||
p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
|
||||
p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
|
||||
p->textsize = p->highpc - p->lowpc;
|
||||
+ /* This looks like a typo, but it's here to align the p->froms
|
||||
+ section. */
|
||||
p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms));
|
||||
p->hashfraction = HASHFRACTION;
|
||||
p->log_hashfraction = -1;
|
||||
@@ -142,7 +144,7 @@ __monstartup (u_long lowpc, u_long highpc)
|
||||
instead of integer division. Precompute shift amount. */
|
||||
p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1;
|
||||
}
|
||||
- p->fromssize = p->textsize / HASHFRACTION;
|
||||
+ p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms));
|
||||
p->tolimit = p->textsize * ARCDENSITY / 100;
|
||||
if (p->tolimit < MINARCS)
|
||||
p->tolimit = MINARCS;
|
464
glibc-upstream-2.34-396.patch
Normal file
464
glibc-upstream-2.34-396.patch
Normal file
@ -0,0 +1,464 @@
|
||||
commit 4dd89b2a8fc91bc74ea85a442ae4c672b6dda113
|
||||
Author: Simon Kissane <skissane@gmail.com>
|
||||
Date: Sat Feb 11 20:12:13 2023 +1100
|
||||
|
||||
gmon: improve mcount overflow handling [BZ# 27576]
|
||||
|
||||
When mcount overflows, no gmon.out file is generated, but no message is printed
|
||||
to the user, leaving the user with no idea why, and thinking maybe there is
|
||||
some bug - which is how BZ 27576 ended up being logged. Print a message to
|
||||
stderr in this case so the user knows what is going on.
|
||||
|
||||
As a comment in sys/gmon.h acknowledges, the hardcoded MAXARCS value is too
|
||||
small for some large applications, including the test case in that BZ. Rather
|
||||
than increase it, add tunables to enable MINARCS and MAXARCS to be overridden
|
||||
at runtime (glibc.gmon.minarcs and glibc.gmon.maxarcs). So if a user gets the
|
||||
mcount overflow error, they can try increasing maxarcs (they might need to
|
||||
increase minarcs too if the heuristic is wrong in their case.)
|
||||
|
||||
Note setting minarcs/maxarcs too large can cause monstartup to fail with an
|
||||
out of memory error. If you set them large enough, it can cause an integer
|
||||
overflow in calculating the buffer size. I haven't done anything to defend
|
||||
against that - it would not generally be a security vulnerability, since these
|
||||
tunables will be ignored in suid/sgid programs (due to the SXID_ERASE default),
|
||||
and if you can set GLIBC_TUNABLES in the environment of a process, you can take
|
||||
it over anyway (LD_PRELOAD, LD_LIBRARY_PATH, etc). I thought about modifying
|
||||
the code of monstartup to defend against integer overflows, but doing so is
|
||||
complicated, and I realise the existing code is susceptible to them even prior
|
||||
to this change (e.g. try passing a pathologically large highpc argument to
|
||||
monstartup), so I decided just to leave that possibility in-place.
|
||||
|
||||
Add a test case which demonstrates mcount overflow and the tunables.
|
||||
|
||||
Document the new tunables in the manual.
|
||||
|
||||
Signed-off-by: Simon Kissane <skissane@gmail.com>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit 31be941e4367c001b2009308839db5c67bf9dcbc)
|
||||
|
||||
# Conflicts:
|
||||
# elf/dl-tunables.list
|
||||
|
||||
diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
|
||||
index ffcd7f18d4fafb91..feb8fcbf5bd5ca7d 100644
|
||||
--- a/elf/dl-tunables.list
|
||||
+++ b/elf/dl-tunables.list
|
||||
@@ -165,4 +165,17 @@ glibc {
|
||||
default: 2
|
||||
}
|
||||
}
|
||||
+
|
||||
+ gmon {
|
||||
+ minarcs {
|
||||
+ type: INT_32
|
||||
+ minval: 50
|
||||
+ default: 50
|
||||
+ }
|
||||
+ maxarcs {
|
||||
+ type: INT_32
|
||||
+ minval: 50
|
||||
+ default: 1048576
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/gmon/Makefile b/gmon/Makefile
|
||||
index 7b7b854327702030..706f50f7dd4cae84 100644
|
||||
--- a/gmon/Makefile
|
||||
+++ b/gmon/Makefile
|
||||
@@ -25,7 +25,7 @@ include ../Makeconfig
|
||||
headers := sys/gmon.h sys/gmon_out.h sys/profil.h
|
||||
routines := gmon mcount profil sprofil prof-freq
|
||||
|
||||
-tests = tst-sprofil tst-gmon
|
||||
+tests = tst-sprofil tst-gmon tst-mcount-overflow
|
||||
ifeq ($(build-profile),yes)
|
||||
tests += tst-profile-static
|
||||
tests-static += tst-profile-static
|
||||
@@ -56,6 +56,18 @@ ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)tst-gmon-gprof.out
|
||||
endif
|
||||
|
||||
+CFLAGS-tst-mcount-overflow.c := -fno-omit-frame-pointer -pg
|
||||
+tst-mcount-overflow-no-pie = yes
|
||||
+CRT-tst-mcount-overflow := $(csu-objpfx)g$(start-installed-name)
|
||||
+# Intentionally use invalid config where maxarcs<minarcs to check warning is printed
|
||||
+tst-mcount-overflow-ENV := GMON_OUT_PREFIX=$(objpfx)tst-mcount-overflow.data \
|
||||
+ GLIBC_TUNABLES=glibc.gmon.minarcs=51:glibc.gmon.maxarcs=50
|
||||
+# Send stderr into output file because we make sure expected messages are printed
|
||||
+tst-mcount-overflow-ARGS := 2>&1 1>/dev/null | cat
|
||||
+ifeq ($(run-built-tests),yes)
|
||||
+tests-special += $(objpfx)tst-mcount-overflow-check.out
|
||||
+endif
|
||||
+
|
||||
CFLAGS-tst-gmon-static.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg
|
||||
CRT-tst-gmon-static := $(csu-objpfx)gcrt1.o
|
||||
tst-gmon-static-no-pie = yes
|
||||
@@ -103,6 +115,14 @@ $(objpfx)tst-gmon.out: clean-tst-gmon-data
|
||||
clean-tst-gmon-data:
|
||||
rm -f $(objpfx)tst-gmon.data.*
|
||||
|
||||
+$(objpfx)tst-mcount-overflow.o: clean-tst-mcount-overflow-data
|
||||
+clean-tst-mcount-overflow-data:
|
||||
+ rm -f $(objpfx)tst-mcount-overflow.data.*
|
||||
+
|
||||
+$(objpfx)tst-mcount-overflow-check.out: tst-mcount-overflow-check.sh $(objpfx)tst-mcount-overflow.out
|
||||
+ $(SHELL) $< $(objpfx)tst-mcount-overflow > $@; \
|
||||
+ $(evaluate-test)
|
||||
+
|
||||
$(objpfx)tst-gmon-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon.out
|
||||
$(SHELL) $< $(GPROF) $(objpfx)tst-gmon $(objpfx)tst-gmon.data.* > $@; \
|
||||
$(evaluate-test)
|
||||
diff --git a/gmon/gmon.c b/gmon/gmon.c
|
||||
index bf76358d5b1aa2da..689bf80141e559ca 100644
|
||||
--- a/gmon/gmon.c
|
||||
+++ b/gmon/gmon.c
|
||||
@@ -46,6 +46,11 @@
|
||||
#include <libc-internal.h>
|
||||
#include <not-cancel.h>
|
||||
|
||||
+#if HAVE_TUNABLES
|
||||
+# define TUNABLE_NAMESPACE gmon
|
||||
+# include <elf/dl-tunables.h>
|
||||
+#endif
|
||||
+
|
||||
#ifdef PIC
|
||||
# include <link.h>
|
||||
|
||||
@@ -124,6 +129,22 @@ __monstartup (u_long lowpc, u_long highpc)
|
||||
int o;
|
||||
char *cp;
|
||||
struct gmonparam *p = &_gmonparam;
|
||||
+ long int minarcs, maxarcs;
|
||||
+
|
||||
+#if HAVE_TUNABLES
|
||||
+ /* Read minarcs/maxarcs tunables. */
|
||||
+ minarcs = TUNABLE_GET (minarcs, int32_t, NULL);
|
||||
+ maxarcs = TUNABLE_GET (maxarcs, int32_t, NULL);
|
||||
+ if (maxarcs < minarcs)
|
||||
+ {
|
||||
+ ERR("monstartup: maxarcs < minarcs, setting maxarcs = minarcs\n");
|
||||
+ maxarcs = minarcs;
|
||||
+ }
|
||||
+#else
|
||||
+ /* No tunables, we use hardcoded defaults */
|
||||
+ minarcs = MINARCS;
|
||||
+ maxarcs = MAXARCS;
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* round lowpc and highpc to multiples of the density we're using
|
||||
@@ -146,10 +167,10 @@ __monstartup (u_long lowpc, u_long highpc)
|
||||
}
|
||||
p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms));
|
||||
p->tolimit = p->textsize * ARCDENSITY / 100;
|
||||
- if (p->tolimit < MINARCS)
|
||||
- p->tolimit = MINARCS;
|
||||
- else if (p->tolimit > MAXARCS)
|
||||
- p->tolimit = MAXARCS;
|
||||
+ if (p->tolimit < minarcs)
|
||||
+ p->tolimit = minarcs;
|
||||
+ else if (p->tolimit > maxarcs)
|
||||
+ p->tolimit = maxarcs;
|
||||
p->tossize = p->tolimit * sizeof(struct tostruct);
|
||||
|
||||
cp = calloc (p->kcountsize + p->fromssize + p->tossize, 1);
|
||||
diff --git a/gmon/mcount.c b/gmon/mcount.c
|
||||
index 9d4a1a50fa6ab21a..f7180fdb83399a14 100644
|
||||
--- a/gmon/mcount.c
|
||||
+++ b/gmon/mcount.c
|
||||
@@ -41,6 +41,10 @@ static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
|
||||
|
||||
#include <atomic.h>
|
||||
|
||||
+#include <not-cancel.h>
|
||||
+#include <unistd.h>
|
||||
+#define ERR(s) __write_nocancel (STDERR_FILENO, s, sizeof (s) - 1)
|
||||
+
|
||||
/*
|
||||
* mcount is called on entry to each function compiled with the profiling
|
||||
* switch set. _mcount(), which is declared in a machine-dependent way
|
||||
@@ -170,6 +174,7 @@ done:
|
||||
return;
|
||||
overflow:
|
||||
p->state = GMON_PROF_ERROR;
|
||||
+ ERR("mcount: call graph buffer size limit exceeded, gmon.out will not be generated\n");
|
||||
return;
|
||||
}
|
||||
|
||||
diff --git a/gmon/sys/gmon.h b/gmon/sys/gmon.h
|
||||
index b4cc3b043a2aec77..af0582a3717085b5 100644
|
||||
--- a/gmon/sys/gmon.h
|
||||
+++ b/gmon/sys/gmon.h
|
||||
@@ -111,6 +111,8 @@ extern struct __bb *__bb_head;
|
||||
* Always allocate at least this many tostructs. This
|
||||
* hides the inadequacy of the ARCDENSITY heuristic, at least
|
||||
* for small programs.
|
||||
+ *
|
||||
+ * Value can be overridden at runtime by glibc.gmon.minarcs tunable.
|
||||
*/
|
||||
#define MINARCS 50
|
||||
|
||||
@@ -124,8 +126,8 @@ extern struct __bb *__bb_head;
|
||||
* Used to be max representable value of ARCINDEX minus 2, but now
|
||||
* that ARCINDEX is a long, that's too large; we don't really want
|
||||
* to allow a 48 gigabyte table.
|
||||
- * The old value of 1<<16 wasn't high enough in practice for large C++
|
||||
- * programs; will 1<<20 be adequate for long? FIXME
|
||||
+ *
|
||||
+ * Value can be overridden at runtime by glibc.gmon.maxarcs tunable.
|
||||
*/
|
||||
#define MAXARCS (1 << 20)
|
||||
|
||||
diff --git a/gmon/tst-mcount-overflow-check.sh b/gmon/tst-mcount-overflow-check.sh
|
||||
new file mode 100644
|
||||
index 0000000000000000..27eb5538fd573a6e
|
||||
--- /dev/null
|
||||
+++ b/gmon/tst-mcount-overflow-check.sh
|
||||
@@ -0,0 +1,45 @@
|
||||
+#!/bin/sh
|
||||
+# Test expected messages generated when mcount overflows
|
||||
+# Copyright (C) 2017-2023 Free Software Foundation, Inc.
|
||||
+# Copyright The GNU Toolchain Authors.
|
||||
+# This file is part of the GNU C Library.
|
||||
+
|
||||
+# The GNU C Library is free software; you can redistribute it and/or
|
||||
+# modify it under the terms of the GNU Lesser General Public
|
||||
+# License as published by the Free Software Foundation; either
|
||||
+# version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+# The GNU C Library is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+# Lesser General Public License for more details.
|
||||
+
|
||||
+# You should have received a copy of the GNU Lesser General Public
|
||||
+# License along with the GNU C Library; if not, see
|
||||
+# <https://www.gnu.org/licenses/>.
|
||||
+
|
||||
+LC_ALL=C
|
||||
+export LC_ALL
|
||||
+set -e
|
||||
+exec 2>&1
|
||||
+
|
||||
+program="$1"
|
||||
+
|
||||
+check_msg() {
|
||||
+ if ! grep -q "$1" "$program.out"; then
|
||||
+ echo "FAIL: expected message not in output: $1"
|
||||
+ exit 1
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+check_msg 'monstartup: maxarcs < minarcs, setting maxarcs = minarcs'
|
||||
+check_msg 'mcount: call graph buffer size limit exceeded, gmon.out will not be generated'
|
||||
+
|
||||
+for data_file in $1.data.*; do
|
||||
+ if [ -f "$data_file" ]; then
|
||||
+ echo "FAIL: expected no data files, but found $data_file"
|
||||
+ exit 1
|
||||
+ fi
|
||||
+done
|
||||
+
|
||||
+echo PASS
|
||||
diff --git a/gmon/tst-mcount-overflow.c b/gmon/tst-mcount-overflow.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..06cc93ef872eb7c1
|
||||
--- /dev/null
|
||||
+++ b/gmon/tst-mcount-overflow.c
|
||||
@@ -0,0 +1,72 @@
|
||||
+/* Test program to trigger mcount overflow in profiling collection.
|
||||
+ Copyright (C) 2017-2023 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* Program with sufficiently complex, yet pointless, call graph
|
||||
+ that it will trigger an mcount overflow, when you set the
|
||||
+ minarcs/maxarcs tunables to very low values. */
|
||||
+
|
||||
+#define PREVENT_TAIL_CALL asm volatile ("")
|
||||
+
|
||||
+/* Calls REP(n) macro 16 times, for n=0..15.
|
||||
+ * You need to define REP(n) before using this.
|
||||
+ */
|
||||
+#define REPS \
|
||||
+ REP(0) REP(1) REP(2) REP(3) REP(4) REP(5) REP(6) REP(7) \
|
||||
+ REP(8) REP(9) REP(10) REP(11) REP(12) REP(13) REP(14) REP(15)
|
||||
+
|
||||
+/* Defines 16 leaf functions named f1_0 to f1_15 */
|
||||
+#define REP(n) \
|
||||
+ __attribute__ ((noinline, noclone, weak)) void f1_##n (void) {};
|
||||
+REPS
|
||||
+#undef REP
|
||||
+
|
||||
+/* Calls all 16 leaf functions f1_* in succession */
|
||||
+__attribute__ ((noinline, noclone, weak)) void
|
||||
+f2 (void)
|
||||
+{
|
||||
+# define REP(n) f1_##n();
|
||||
+ REPS
|
||||
+# undef REP
|
||||
+ PREVENT_TAIL_CALL;
|
||||
+}
|
||||
+
|
||||
+/* Defines 16 functions named f2_0 to f2_15, which all just call f2 */
|
||||
+#define REP(n) \
|
||||
+ __attribute__ ((noinline, noclone, weak)) void \
|
||||
+ f2_##n (void) { f2(); PREVENT_TAIL_CALL; };
|
||||
+REPS
|
||||
+#undef REP
|
||||
+
|
||||
+__attribute__ ((noinline, noclone, weak)) void
|
||||
+f3 (int count)
|
||||
+{
|
||||
+ for (int i = 0; i < count; ++i)
|
||||
+ {
|
||||
+ /* Calls f1_0(), f2_0(), f1_1(), f2_1(), f3_0(), etc */
|
||||
+# define REP(n) f1_##n(); f2_##n();
|
||||
+ REPS
|
||||
+# undef REP
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ f3 (1000);
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/manual/tunables.texi b/manual/tunables.texi
|
||||
index 561e0df230646de1..a387bf3055f3488e 100644
|
||||
--- a/manual/tunables.texi
|
||||
+++ b/manual/tunables.texi
|
||||
@@ -77,6 +77,9 @@ glibc.malloc.check: 0 (min: 0, max: 3)
|
||||
capabilities seen by @theglibc{}
|
||||
* Memory Related Tunables:: Tunables that control the use of memory by
|
||||
@theglibc{}.
|
||||
+* gmon Tunables:: Tunables that control the gmon profiler, used in
|
||||
+ conjunction with gprof
|
||||
+
|
||||
@end menu
|
||||
|
||||
@node Tunable names
|
||||
@@ -596,3 +599,59 @@ support in the kernel if this tunable has any non-zero value.
|
||||
|
||||
The default value is @samp{0}, which disables all memory tagging.
|
||||
@end deftp
|
||||
+
|
||||
+@node gmon Tunables
|
||||
+@section gmon Tunables
|
||||
+@cindex gmon tunables
|
||||
+
|
||||
+@deftp {Tunable namespace} glibc.gmon
|
||||
+This tunable namespace affects the behaviour of the gmon profiler.
|
||||
+gmon is a component of @theglibc{} which is normally used in
|
||||
+conjunction with gprof.
|
||||
+
|
||||
+When GCC compiles a program with the @code{-pg} option, it instruments
|
||||
+the program with calls to the @code{mcount} function, to record the
|
||||
+program's call graph. At program startup, a memory buffer is allocated
|
||||
+to store this call graph; the size of the buffer is calculated using a
|
||||
+heuristic based on code size. If during execution, the buffer is found
|
||||
+to be too small, profiling will be aborted and no @file{gmon.out} file
|
||||
+will be produced. In that case, you will see the following message
|
||||
+printed to standard error:
|
||||
+
|
||||
+@example
|
||||
+mcount: call graph buffer size limit exceeded, gmon.out will not be generated
|
||||
+@end example
|
||||
+
|
||||
+Most of the symbols discussed in this section are defined in the header
|
||||
+@code{sys/gmon.h}. However, some symbols (for example @code{mcount})
|
||||
+are not defined in any header file, since they are only intended to be
|
||||
+called from code generated by the compiler.
|
||||
+@end deftp
|
||||
+
|
||||
+@deftp Tunable glibc.mem.minarcs
|
||||
+The heuristic for sizing the call graph buffer is known to be
|
||||
+insufficient for small programs; hence, the calculated value is clamped
|
||||
+to be at least a minimum size. The default minimum (in units of
|
||||
+call graph entries, @code{struct tostruct}), is given by the macro
|
||||
+@code{MINARCS}. If you have some program with an unusually complex
|
||||
+call graph, for which the heuristic fails to allocate enough space,
|
||||
+you can use this tunable to increase the minimum to a larger value.
|
||||
+@end deftp
|
||||
+
|
||||
+@deftp Tunable glibc.mem.maxarcs
|
||||
+To prevent excessive memory consumption when profiling very large
|
||||
+programs, the call graph buffer is allowed to have a maximum of
|
||||
+@code{MAXARCS} entries. For some very large programs, the default
|
||||
+value of @code{MAXARCS} defined in @file{sys/gmon.h} is too small; in
|
||||
+that case, you can use this tunable to increase it.
|
||||
+
|
||||
+Note the value of the @code{maxarcs} tunable must be greater or equal
|
||||
+to that of the @code{minarcs} tunable; if this constraint is violated,
|
||||
+a warning will printed to standard error at program startup, and
|
||||
+the @code{minarcs} value will be used as the maximum as well.
|
||||
+
|
||||
+Setting either tunable too high may result in a call graph buffer
|
||||
+whose size exceeds the available memory; in that case, an out of memory
|
||||
+error will be printed at program startup, the profiler will be
|
||||
+disabled, and no @file{gmon.out} file will be generated.
|
||||
+@end deftp
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list b/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list
|
||||
index d9d62499be4d67cb..b8495f695c39e2d3 100644
|
||||
--- a/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list
|
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list
|
||||
@@ -26,3 +26,5 @@
|
||||
@order glibc.rtld.optional_static_tls
|
||||
@order glibc.malloc.tcache_max
|
||||
@order glibc.malloc.check
|
||||
+@order glibc.gmon.minarcs
|
||||
+@order glibc.gmon.maxarcs
|
||||
diff --git a/sysdeps/unix/sysv/linux/i386/dl-tunables.list b/sysdeps/unix/sysv/linux/i386/dl-tunables.list
|
||||
index e83962ec3af11691..0ee51cdcdd4a7ee7 100644
|
||||
--- a/sysdeps/unix/sysv/linux/i386/dl-tunables.list
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/dl-tunables.list
|
||||
@@ -33,3 +33,5 @@
|
||||
@order glibc.rtld.optional_static_tls
|
||||
@order glibc.malloc.tcache_max
|
||||
@order glibc.malloc.check
|
||||
+@order glibc.gmon.minarcs
|
||||
+@order glibc.gmon.maxarcs
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list
|
||||
index 8f01840ef57874e7..17b4114e12736fa4 100644
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list
|
||||
@@ -26,3 +26,5 @@
|
||||
@order glibc.rtld.optional_static_tls
|
||||
@order glibc.malloc.tcache_max
|
||||
@order glibc.malloc.check
|
||||
+@order glibc.gmon.minarcs
|
||||
+@order glibc.gmon.maxarcs
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list b/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list
|
||||
index 3dd7e891c5e37b1a..1c8cd0ec14324703 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list
|
||||
@@ -26,3 +26,5 @@
|
||||
@order glibc.malloc.tcache_max
|
||||
@order glibc.malloc.check
|
||||
@order glibc.cpu.hwcaps
|
||||
+@order glibc.gmon.minarcs
|
||||
+@order glibc.gmon.maxarcs
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
|
||||
index e83962ec3af11691..0ee51cdcdd4a7ee7 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
|
||||
@@ -33,3 +33,5 @@
|
||||
@order glibc.rtld.optional_static_tls
|
||||
@order glibc.malloc.tcache_max
|
||||
@order glibc.malloc.check
|
||||
+@order glibc.gmon.minarcs
|
||||
+@order glibc.gmon.maxarcs
|
188
glibc-upstream-2.34-397.patch
Normal file
188
glibc-upstream-2.34-397.patch
Normal file
@ -0,0 +1,188 @@
|
||||
commit f1b15d2005f5125529171db3be39026a1157c2a8
|
||||
Author: Simon Kissane <skissane@gmail.com>
|
||||
Date: Sat Feb 11 08:58:02 2023 +1100
|
||||
|
||||
gmon: fix memory corruption issues [BZ# 30101]
|
||||
|
||||
V2 of this patch fixes an issue in V1, where the state was changed to ON not
|
||||
OFF at end of _mcleanup. I hadn't noticed that (counterintuitively) ON=0 and
|
||||
OFF=3, hence zeroing the buffer turned it back on. So set the state to OFF
|
||||
after the memset.
|
||||
|
||||
1. Prevent double free, and reads from unallocated memory, when
|
||||
_mcleanup is (incorrectly) called two or more times in a row,
|
||||
without an intervening call to __monstartup; with this patch, the
|
||||
second and subsequent calls effectively become no-ops instead.
|
||||
While setting tos=NULL is minimal fix, safest action is to zero the
|
||||
whole gmonparam buffer.
|
||||
|
||||
2. Prevent memory leak when __monstartup is (incorrectly) called two
|
||||
or more times in a row, without an intervening call to _mcleanup;
|
||||
with this patch, the second and subsequent calls effectively become
|
||||
no-ops instead.
|
||||
|
||||
3. After _mcleanup, treat __moncontrol(1) as __moncontrol(0) instead.
|
||||
With zeroing of gmonparam buffer in _mcleanup, this stops the
|
||||
state incorrectly being changed to GMON_PROF_ON despite profiling
|
||||
actually being off. If we'd just done the minimal fix to _mcleanup
|
||||
of setting tos=NULL, there is risk of far worse memory corruption:
|
||||
kcount would point to deallocated memory, and the __profil syscall
|
||||
would make the kernel write profiling data into that memory,
|
||||
which could have since been reallocated to something unrelated.
|
||||
|
||||
4. Ensure __moncontrol(0) still turns off profiling even in error
|
||||
state. Otherwise, if mcount overflows and sets state to
|
||||
GMON_PROF_ERROR, when _mcleanup calls __moncontrol(0), the __profil
|
||||
syscall to disable profiling will not be invoked. _mcleanup will
|
||||
free the buffer, but the kernel will still be writing profiling
|
||||
data into it, potentially corrupted arbitrary memory.
|
||||
|
||||
Also adds a test case for (1). Issues (2)-(4) are not feasible to test.
|
||||
|
||||
Signed-off-by: Simon Kissane <skissane@gmail.com>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit bde121872001d8f3224eeafa5b7effb871c3fbca)
|
||||
|
||||
diff --git a/gmon/Makefile b/gmon/Makefile
|
||||
index 706f50f7dd4cae84..7fd9db8f749a0843 100644
|
||||
--- a/gmon/Makefile
|
||||
+++ b/gmon/Makefile
|
||||
@@ -1,4 +1,5 @@
|
||||
-# Copyright (C) 1995-2021 Free Software Foundation, Inc.
|
||||
+# Copyright (C) 1995-2023 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,7 +26,7 @@ include ../Makeconfig
|
||||
headers := sys/gmon.h sys/gmon_out.h sys/profil.h
|
||||
routines := gmon mcount profil sprofil prof-freq
|
||||
|
||||
-tests = tst-sprofil tst-gmon tst-mcount-overflow
|
||||
+tests = tst-sprofil tst-gmon tst-mcount-overflow tst-mcleanup
|
||||
ifeq ($(build-profile),yes)
|
||||
tests += tst-profile-static
|
||||
tests-static += tst-profile-static
|
||||
@@ -68,6 +69,14 @@ ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)tst-mcount-overflow-check.out
|
||||
endif
|
||||
|
||||
+CFLAGS-tst-mcleanup.c := -fno-omit-frame-pointer -pg
|
||||
+tst-mcleanup-no-pie = yes
|
||||
+CRT-tst-mcleanup := $(csu-objpfx)g$(start-installed-name)
|
||||
+tst-mcleanup-ENV := GMON_OUT_PREFIX=$(objpfx)tst-mcleanup.data
|
||||
+ifeq ($(run-built-tests),yes)
|
||||
+tests-special += $(objpfx)tst-mcleanup.out
|
||||
+endif
|
||||
+
|
||||
CFLAGS-tst-gmon-static.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg
|
||||
CRT-tst-gmon-static := $(csu-objpfx)gcrt1.o
|
||||
tst-gmon-static-no-pie = yes
|
||||
@@ -123,6 +132,10 @@ $(objpfx)tst-mcount-overflow-check.out: tst-mcount-overflow-check.sh $(objpfx)ts
|
||||
$(SHELL) $< $(objpfx)tst-mcount-overflow > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
+$(objpfx)tst-mcleanup.out: clean-tst-mcleanup-data
|
||||
+clean-tst-mcleanup-data:
|
||||
+ rm -f $(objpfx)tst-mcleanup.data.*
|
||||
+
|
||||
$(objpfx)tst-gmon-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon.out
|
||||
$(SHELL) $< $(GPROF) $(objpfx)tst-gmon $(objpfx)tst-gmon.data.* > $@; \
|
||||
$(evaluate-test)
|
||||
diff --git a/gmon/gmon.c b/gmon/gmon.c
|
||||
index 689bf80141e559ca..5e99a7351dc71666 100644
|
||||
--- a/gmon/gmon.c
|
||||
+++ b/gmon/gmon.c
|
||||
@@ -102,11 +102,8 @@ __moncontrol (int mode)
|
||||
{
|
||||
struct gmonparam *p = &_gmonparam;
|
||||
|
||||
- /* Don't change the state if we ran into an error. */
|
||||
- if (p->state == GMON_PROF_ERROR)
|
||||
- return;
|
||||
-
|
||||
- if (mode)
|
||||
+ /* Treat start request as stop if error or gmon not initialized. */
|
||||
+ if (mode && p->state != GMON_PROF_ERROR && p->tos != NULL)
|
||||
{
|
||||
/* start */
|
||||
__profil((void *) p->kcount, p->kcountsize, p->lowpc, s_scale);
|
||||
@@ -116,7 +113,9 @@ __moncontrol (int mode)
|
||||
{
|
||||
/* stop */
|
||||
__profil(NULL, 0, 0, 0);
|
||||
- p->state = GMON_PROF_OFF;
|
||||
+ /* Don't change the state if we ran into an error. */
|
||||
+ if (p->state != GMON_PROF_ERROR)
|
||||
+ p->state = GMON_PROF_OFF;
|
||||
}
|
||||
}
|
||||
libc_hidden_def (__moncontrol)
|
||||
@@ -146,6 +145,14 @@ __monstartup (u_long lowpc, u_long highpc)
|
||||
maxarcs = MAXARCS;
|
||||
#endif
|
||||
|
||||
+ /*
|
||||
+ * If we are incorrectly called twice in a row (without an
|
||||
+ * intervening call to _mcleanup), ignore the second call to
|
||||
+ * prevent leaking memory.
|
||||
+ */
|
||||
+ if (p->tos != NULL)
|
||||
+ return;
|
||||
+
|
||||
/*
|
||||
* round lowpc and highpc to multiples of the density we're using
|
||||
* so the rest of the scaling (here and in gprof) stays in ints.
|
||||
@@ -463,9 +470,14 @@ _mcleanup (void)
|
||||
{
|
||||
__moncontrol (0);
|
||||
|
||||
- if (_gmonparam.state != GMON_PROF_ERROR)
|
||||
+ if (_gmonparam.state != GMON_PROF_ERROR && _gmonparam.tos != NULL)
|
||||
write_gmon ();
|
||||
|
||||
/* free the memory. */
|
||||
free (_gmonparam.tos);
|
||||
+
|
||||
+ /* reset buffer to initial state for safety */
|
||||
+ memset(&_gmonparam, 0, sizeof _gmonparam);
|
||||
+ /* somewhat confusingly, ON=0, OFF=3 */
|
||||
+ _gmonparam.state = GMON_PROF_OFF;
|
||||
}
|
||||
diff --git a/gmon/tst-mcleanup.c b/gmon/tst-mcleanup.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..b259653ec833aca4
|
||||
--- /dev/null
|
||||
+++ b/gmon/tst-mcleanup.c
|
||||
@@ -0,0 +1,31 @@
|
||||
+/* Test program for repeated invocation of _mcleanup
|
||||
+ Copyright The GNU Toolchain Authors.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* Intentionally calls _mcleanup() twice: once manually, it will be
|
||||
+ called again as an atexit handler. This is incorrect use of the API,
|
||||
+ but the point of the test is to make sure we don't crash when the
|
||||
+ API is misused in this way. */
|
||||
+
|
||||
+#include <sys/gmon.h>
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ _mcleanup();
|
||||
+ return 0;
|
||||
+}
|
23
glibc.spec
23
glibc.spec
@ -155,7 +155,7 @@ end \
|
||||
Summary: The GNU libc libraries
|
||||
Name: glibc
|
||||
Version: %{glibcversion}
|
||||
Release: 66%{?dist}
|
||||
Release: 67%{?dist}
|
||||
|
||||
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
||||
# libraries.
|
||||
@ -707,6 +707,16 @@ Patch474: glibc-rh2169978-1.patch
|
||||
Patch475: glibc-rh2169978-2.patch
|
||||
Patch476: glibc-rh2149615-3.patch
|
||||
Patch477: glibc-rh2166710.patch
|
||||
# glibc-upstream-2.34-390.patch backported above as glibc-rh2172953.patch.
|
||||
Patch478: glibc-upstream-2.34-391.patch
|
||||
Patch479: glibc-upstream-2.34-392.patch
|
||||
Patch480: glibc-upstream-2.34-393.patch
|
||||
Patch481: glibc-upstream-2.34-394.patch
|
||||
Patch482: glibc-upstream-2.34-395.patch
|
||||
Patch483: glibc-upstream-2.34-396.patch
|
||||
Patch484: glibc-upstream-2.34-397.patch
|
||||
# glibc-upstream-2.34-398.patch not backported because we can avoid the
|
||||
# ABI tunable issue downstream, using @order directives.
|
||||
|
||||
##############################################################################
|
||||
# Continued list of core "glibc" package information:
|
||||
@ -2866,6 +2876,17 @@ fi
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Fri Apr 28 2023 Florian Weimer <fweimer@redhat.com> - 2.34-67
|
||||
- Sync with upstream branch release/2.34/master,
|
||||
commit 0ea8174d62263c2679c95c0d215d2627e560f7aa:
|
||||
- gmon: fix memory corruption issues [BZ# 30101]
|
||||
- gmon: improve mcount overflow handling [BZ# 27576]
|
||||
- gmon: Fix allocated buffer overflow (bug 29444)
|
||||
- posix: Fix system blocks SIGCHLD erroneously [BZ #30163]
|
||||
- x86_64: Fix asm constraints in feraiseexcept (bug 30305)
|
||||
- gshadow: Matching sgetsgent, sgetsgent_r ERANGE handling (bug 30151)
|
||||
- x86: Check minimum/maximum of non_temporal_threshold [BZ #29953]
|
||||
|
||||
* Thu Apr 20 2023 Patsy Griffin <patsy@redhat.com> - 2.34-66
|
||||
- x86: Cache computation for AMD architecture. (#2166710)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user