Blame SOURCES/0005-sysconf-Add-_SC_MINSIGSTKSZ-_SC_SIGSTKSZ-BZ-20305.patch

3c8a07
From 232e45c1720857fbf1948c4aeba39a3c8cc52335 Mon Sep 17 00:00:00 2001
3c8a07
From: "H.J. Lu" <hjl.tools@gmail.com>
3c8a07
Date: Mon, 1 Feb 2021 11:00:38 -0800
3c8a07
Subject: [PATCH 5/5] sysconf: Add _SC_MINSIGSTKSZ/_SC_SIGSTKSZ [BZ #20305]
3c8a07
3c8a07
Add _SC_MINSIGSTKSZ for the minimum signal stack size derived from
3c8a07
AT_MINSIGSTKSZ, which is the minimum number of bytes of free stack
3c8a07
space required in order to gurantee successful, non-nested handling
3c8a07
of a single signal whose handler is an empty function, and _SC_SIGSTKSZ
3c8a07
which is the suggested minimum number of bytes of stack space required
3c8a07
for a signal stack.
3c8a07
3c8a07
If AT_MINSIGSTKSZ isn't available, sysconf (_SC_MINSIGSTKSZ) returns
3c8a07
MINSIGSTKSZ.  On Linux/x86 with XSAVE, the signal frame used by kernel
3c8a07
is composed of the following areas and laid out as:
3c8a07
3c8a07
 ------------------------------
3c8a07
 | alignment padding          |
3c8a07
 ------------------------------
3c8a07
 | xsave buffer               |
3c8a07
 ------------------------------
3c8a07
 | fsave header (32-bit only) |
3c8a07
 ------------------------------
3c8a07
 | siginfo + ucontext         |
3c8a07
 ------------------------------
3c8a07
3c8a07
Compute AT_MINSIGSTKSZ value as size of xsave buffer + size of fsave
3c8a07
header (32-bit only) + size of siginfo and ucontext + alignment padding.
3c8a07
3c8a07
If _SC_SIGSTKSZ_SOURCE or _GNU_SOURCE are defined, MINSIGSTKSZ and SIGSTKSZ
3c8a07
are redefined as
3c8a07
3c8a07
/* Default stack size for a signal handler: sysconf (SC_SIGSTKSZ).  */
3c8a07
 # undef SIGSTKSZ
3c8a07
 # define SIGSTKSZ sysconf (_SC_SIGSTKSZ)
3c8a07
3c8a07
/* Minimum stack size for a signal handler: SIGSTKSZ.  */
3c8a07
 # undef MINSIGSTKSZ
3c8a07
 # define MINSIGSTKSZ SIGSTKSZ
3c8a07
3c8a07
Compilation will fail if the source assumes constant MINSIGSTKSZ or
3c8a07
SIGSTKSZ.
3c8a07
3c8a07
The reason for not simply increasing the kernel's MINSIGSTKSZ #define
3c8a07
(apart from the fact that it is rarely used, due to glibc's shadowing
3c8a07
definitions) was that userspace binaries will have baked in the old
3c8a07
value of the constant and may be making assumptions about it.
3c8a07
3c8a07
For example, the type (char [MINSIGSTKSZ]) changes if this #define
3c8a07
changes.  This could be a problem if an newly built library tries to
3c8a07
memcpy() or dump such an object defined by and old binary.
3c8a07
Bounds-checking and the stack sizes passed to things like sigaltstack()
3c8a07
and makecontext() could similarly go wrong.
3c8a07
3c8a07
UPDATE:
3c8a07
3c8a07
Backported to glibc 2.28
3c8a07
3c8a07
Signed-off-by: Jair Gonzalez <jair.de.jesus.gonzalez.plascencia@intel.com>
3c8a07
---
3c8a07
 NEWS                                          |  5 ++
3c8a07
 bits/confname.h                               |  8 +-
3c8a07
 bits/sigstksz.h                               | 21 +++++
3c8a07
 elf/dl-support.c                              |  5 ++
3c8a07
 elf/dl-sysdep.c                               |  9 ++
3c8a07
 include/bits/sigstack.h                       |  5 ++
3c8a07
 include/bits/sigstksz.h                       |  7 ++
3c8a07
 include/features.h                            | 11 +++
3c8a07
 manual/conf.texi                              | 21 +++++
3c8a07
 manual/creature.texi                          |  6 ++
3c8a07
 posix/sysconf.c                               |  3 +
3c8a07
 signal/Makefile                               |  5 +-
3c8a07
 signal/signal.h                               |  1 +
3c8a07
 signal/tst-minsigstksz-5.c                    | 84 +++++++++++++++++++
3c8a07
 sysdeps/generic/ldsodefs.h                    |  3 +
3c8a07
 sysdeps/unix/sysv/linux/bits/sigstksz.h       | 33 ++++++++
3c8a07
 .../unix/sysv/linux/ia64/sysconf-sigstksz.h   | 27 ++++++
3c8a07
 sysdeps/unix/sysv/linux/sysconf-sigstksz.h    | 38 +++++++++
3c8a07
 sysdeps/unix/sysv/linux/sysconf.c             |  9 ++
3c8a07
 .../unix/sysv/linux/x86/dl-minsigstacksize.h  | 83 ++++++++++++++++++
3c8a07
 .../sysv/linux/x86/include/bits/sigstack.h    |  5 ++
3c8a07
 sysdeps/x86/dl-minsigstacksize.h              | 27 ++++++
3c8a07
 22 files changed, 413 insertions(+), 3 deletions(-)
3c8a07
 create mode 100644 bits/sigstksz.h
3c8a07
 create mode 100644 include/bits/sigstack.h
3c8a07
 create mode 100644 include/bits/sigstksz.h
3c8a07
 create mode 100644 signal/tst-minsigstksz-5.c
3c8a07
 create mode 100644 sysdeps/unix/sysv/linux/bits/sigstksz.h
3c8a07
 create mode 100644 sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h
3c8a07
 create mode 100644 sysdeps/unix/sysv/linux/sysconf-sigstksz.h
3c8a07
 create mode 100644 sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h
3c8a07
 create mode 100644 sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h
3c8a07
 create mode 100644 sysdeps/x86/dl-minsigstacksize.h
3c8a07
3c8a07
diff --git a/NEWS b/NEWS
3c8a07
index 154ab22d..e0e95cb8 100644
3c8a07
--- a/NEWS
3c8a07
+++ b/NEWS
3c8a07
@@ -9,6 +9,11 @@ Version 2.28
3c8a07
 
3c8a07
 Major new features:
3c8a07
 
3c8a07
+* Add _SC_MINSIGSTKSZ and _SC_SIGSTKSZ.  When _SC_SIGSTKSZ_SOURCE or
3c8a07
+  _GNU_SOURCE are defined, MINSIGSTKSZ and SIGSTKSZ are no longer
3c8a07
+  constant on Linux.  MINSIGSTKSZ is redefined to sysconf(_SC_MINSIGSTKSZ)
3c8a07
+  and SIGSTKSZ is redefined to sysconf (_SC_SIGSTKSZ).
3c8a07
+
3c8a07
 * The localization data for ISO 14651 is updated to match the 2016
3c8a07
   Edition 4 release of the standard, this matches data provided by
3c8a07
   Unicode 9.0.0.  This update introduces significant improvements to the
3c8a07
diff --git a/bits/confname.h b/bits/confname.h
3c8a07
index 59d31721..36279222 100644
3c8a07
--- a/bits/confname.h
3c8a07
+++ b/bits/confname.h
3c8a07
@@ -525,8 +525,14 @@ enum
3c8a07
 
3c8a07
     _SC_THREAD_ROBUST_PRIO_INHERIT,
3c8a07
 #define _SC_THREAD_ROBUST_PRIO_INHERIT	_SC_THREAD_ROBUST_PRIO_INHERIT
3c8a07
-    _SC_THREAD_ROBUST_PRIO_PROTECT
3c8a07
+    _SC_THREAD_ROBUST_PRIO_PROTECT,
3c8a07
 #define _SC_THREAD_ROBUST_PRIO_PROTECT	_SC_THREAD_ROBUST_PRIO_PROTECT
3c8a07
+
3c8a07
+    _SC_MINSIGSTKSZ,
3c8a07
+#define	_SC_MINSIGSTKSZ			_SC_MINSIGSTKSZ
3c8a07
+
3c8a07
+    _SC_SIGSTKSZ
3c8a07
+#define	_SC_SIGSTKSZ			_SC_SIGSTKSZ
3c8a07
   };
3c8a07
 
3c8a07
 /* Values for the NAME argument to `confstr'.  */
3c8a07
diff --git a/bits/sigstksz.h b/bits/sigstksz.h
3c8a07
new file mode 100644
3c8a07
index 00000000..5535d873
3c8a07
--- /dev/null
3c8a07
+++ b/bits/sigstksz.h
3c8a07
@@ -0,0 +1,21 @@
3c8a07
+/* Definition of MINSIGSTKSZ.  Generic version.
3c8a07
+   Copyright (C) 2020 Free Software Foundation, Inc.
3c8a07
+   This file is part of the GNU C Library.
3c8a07
+
3c8a07
+   The GNU C Library is free software; you can redistribute it and/or
3c8a07
+   modify it under the terms of the GNU Lesser General Public
3c8a07
+   License as published by the Free Software Foundation; either
3c8a07
+   version 2.1 of the License, or (at your option) any later version.
3c8a07
+
3c8a07
+   The GNU C Library is distributed in the hope that it will be useful,
3c8a07
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
3c8a07
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3c8a07
+   Lesser General Public License for more details.
3c8a07
+
3c8a07
+   You should have received a copy of the GNU Lesser General Public
3c8a07
+   License along with the GNU C Library; if not, see
3c8a07
+   <https://www.gnu.org/licenses/>.  */
3c8a07
+
3c8a07
+#ifndef _SIGNAL_H
3c8a07
+# error "Never include <bits/sigstksz.h> directly; use <signal.h> instead."
3c8a07
+#endif
3c8a07
diff --git a/elf/dl-support.c b/elf/dl-support.c
3c8a07
index 34be8e5b..056945d7 100644
3c8a07
--- a/elf/dl-support.c
3c8a07
+++ b/elf/dl-support.c
3c8a07
@@ -131,6 +131,8 @@ void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
3c8a07
 
3c8a07
 size_t _dl_pagesize = EXEC_PAGESIZE;
3c8a07
 
3c8a07
+size_t _dl_minsigstacksize = CONSTANT_MINSIGSTKSZ;
3c8a07
+
3c8a07
 int _dl_inhibit_cache;
3c8a07
 
3c8a07
 unsigned int _dl_osversion;
3c8a07
@@ -287,6 +289,9 @@ _dl_aux_init (ElfW(auxv_t) *av)
3c8a07
       case AT_RANDOM:
3c8a07
 	_dl_random = (void *) av->a_un.a_val;
3c8a07
 	break;
3c8a07
+      case AT_MINSIGSTKSZ:
3c8a07
+    _dl_minsigstacksize = av->a_un.a_val;
3c8a07
+    break;
3c8a07
 # ifdef DL_PLATFORM_AUXV
3c8a07
       DL_PLATFORM_AUXV
3c8a07
 # endif
3c8a07
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
3c8a07
index 93983251..4bcd75b4 100644
3c8a07
--- a/elf/dl-sysdep.c
3c8a07
+++ b/elf/dl-sysdep.c
3c8a07
@@ -116,6 +116,11 @@ _dl_sysdep_start (void **start_argptr,
3c8a07
   user_entry = (ElfW(Addr)) ENTRY_POINT;
3c8a07
   GLRO(dl_platform) = NULL; /* Default to nothing known about the platform.  */
3c8a07
 
3c8a07
+  /* NB: Default to a constant CONSTANT_MINSIGSTKSZ.  */
3c8a07
+  _Static_assert (__builtin_constant_p (CONSTANT_MINSIGSTKSZ),
3c8a07
+		  "CONSTANT_MINSIGSTKSZ is constant");
3c8a07
+  GLRO(dl_minsigstacksize) = CONSTANT_MINSIGSTKSZ;
3c8a07
+
3c8a07
   for (av = GLRO(dl_auxv); av->a_type != AT_NULL; set_seen (av++))
3c8a07
     switch (av->a_type)
3c8a07
       {
3c8a07
@@ -180,6 +185,9 @@ _dl_sysdep_start (void **start_argptr,
3c8a07
       case AT_RANDOM:
3c8a07
 	_dl_random = (void *) av->a_un.a_val;
3c8a07
 	break;
3c8a07
+      case AT_MINSIGSTKSZ:
3c8a07
+	GLRO(dl_minsigstacksize) = av->a_un.a_val;
3c8a07
+	break;
3c8a07
 #ifdef DL_PLATFORM_AUXV
3c8a07
       DL_PLATFORM_AUXV
3c8a07
 #endif
3c8a07
@@ -317,6 +325,7 @@ _dl_show_auxv (void)
3c8a07
 	  [AT_L2_CACHEGEOMETRY - 2] =	{ "L2_CACHEGEOMETRY:  0x", hex },
3c8a07
 	  [AT_L3_CACHESIZE - 2] =	{ "L3_CACHESIZE:      ", dec },
3c8a07
 	  [AT_L3_CACHEGEOMETRY - 2] =	{ "L3_CACHEGEOMETRY:  0x", hex },
3c8a07
+	  [AT_MINSIGSTKSZ - 2] =	{ "MINSIGSTKSZ        ", dec },
3c8a07
 	};
3c8a07
       unsigned int idx = (unsigned int) (av->a_type - 2);
3c8a07
 
3c8a07
diff --git a/include/bits/sigstack.h b/include/bits/sigstack.h
3c8a07
new file mode 100644
3c8a07
index 00000000..eea939f5
3c8a07
--- /dev/null
3c8a07
+++ b/include/bits/sigstack.h
3c8a07
@@ -0,0 +1,5 @@
3c8a07
+#include_next <bits/sigstack.h>
3c8a07
+
3c8a07
+#if !defined _ISOMAC && !defined CONSTANT_MINSIGSTKSZ
3c8a07
+# define CONSTANT_MINSIGSTKSZ MINSIGSTKSZ
3c8a07
+#endif
3c8a07
diff --git a/include/bits/sigstksz.h b/include/bits/sigstksz.h
3c8a07
new file mode 100644
3c8a07
index 00000000..2ca891e9
3c8a07
--- /dev/null
3c8a07
+++ b/include/bits/sigstksz.h
3c8a07
@@ -0,0 +1,7 @@
3c8a07
+/* NB: Don't define MINSIGSTKSZ nor SIGSTKSZ to sysconf (SC_SIGSTKSZ) for
3c8a07
+   glibc build.  IS_IN can only be used when _ISOMAC isn't defined.  */
3c8a07
+#ifdef _ISOMAC
3c8a07
+# include_next <bits/sigstksz.h>
3c8a07
+#elif IS_IN (libsupport)
3c8a07
+# include_next <bits/sigstksz.h>
3c8a07
+#endif
3c8a07
diff --git a/include/features.h b/include/features.h
3c8a07
index 5bed0a49..fdc3d11d 100644
3c8a07
--- a/include/features.h
3c8a07
+++ b/include/features.h
3c8a07
@@ -47,6 +47,8 @@
3c8a07
    _LARGEFILE64_SOURCE	Additional functionality from LFS for large files.
3c8a07
    _FILE_OFFSET_BITS=N	Select default filesystem interface.
3c8a07
    _ATFILE_SOURCE	Additional *at interfaces.
3c8a07
+   _SC_SIGSTKSZ_SOURCE	Select correct (but non compile-time constant)
3c8a07
+			MINSIGSTKSZ and SIGSTKSZ.
3c8a07
    _GNU_SOURCE		All of the above, plus GNU extensions.
3c8a07
    _DEFAULT_SOURCE	The default set of features (taking precedence over
3c8a07
 			__STRICT_ANSI__).
3c8a07
@@ -93,6 +95,8 @@
3c8a07
    __USE_FILE_OFFSET64	Define 64bit interface as default.
3c8a07
    __USE_MISC		Define things from 4.3BSD or System V Unix.
3c8a07
    __USE_ATFILE		Define *at interfaces and AT_* constants for them.
3c8a07
+   __USE_SC_SIGSTKSZ	Define correct (but non compile-time constant)
3c8a07
+			MINSIGSTKSZ and SIGSTKSZ.
3c8a07
    __USE_GNU		Define GNU extensions.
3c8a07
    __USE_FORTIFY_LEVEL	Additional security measures used, according to level.
3c8a07
 
3c8a07
@@ -136,6 +140,7 @@
3c8a07
 #undef	__USE_FILE_OFFSET64
3c8a07
 #undef	__USE_MISC
3c8a07
 #undef	__USE_ATFILE
3c8a07
+#undef	__USE_SC_SIGSTKSZ
3c8a07
 #undef	__USE_GNU
3c8a07
 #undef	__USE_FORTIFY_LEVEL
3c8a07
 #undef	__KERNEL_STRICT_NAMES
3c8a07
@@ -208,6 +213,8 @@
3c8a07
 # define _DEFAULT_SOURCE	1
3c8a07
 # undef  _ATFILE_SOURCE
3c8a07
 # define _ATFILE_SOURCE	1
3c8a07
+# undef  _SC_SIGSTKSZ_SOURCE
3c8a07
+# define _SC_SIGSTKSZ_SOURCE 1
3c8a07
 #endif
3c8a07
 
3c8a07
 /* If nothing (other than _GNU_SOURCE and _DEFAULT_SOURCE) is defined,
3c8a07
@@ -372,6 +379,10 @@
3c8a07
 # define __USE_ATFILE	1
3c8a07
 #endif
3c8a07
 
3c8a07
+#ifdef	_SC_SIGSTKSZ_SOURCE
3c8a07
+# define __USE_SC_SIGSTKSZ	1
3c8a07
+#endif
3c8a07
+
3c8a07
 #ifdef	_GNU_SOURCE
3c8a07
 # define __USE_GNU	1
3c8a07
 #endif
3c8a07
diff --git a/manual/conf.texi b/manual/conf.texi
3c8a07
index dbd1d302..7321f401 100644
3c8a07
--- a/manual/conf.texi
3c8a07
+++ b/manual/conf.texi
3c8a07
@@ -911,6 +911,27 @@ Inquire about the parameter corresponding to @code{NL_SETMAX}.
3c8a07
 @item _SC_NL_TEXTMAX
3c8a07
 @standards{X/Open, unistd.h}
3c8a07
 Inquire about the parameter corresponding to @code{NL_TEXTMAX}.
3c8a07
+
3c8a07
+@item _SC_MINSIGSTKSZ
3c8a07
+@standards{GNU, unistd.h}
3c8a07
+Inquire about the minimum number of bytes of free stack space required
3c8a07
+in order to guarantee successful, non-nested handling of a single signal
3c8a07
+whose handler is an empty function.
3c8a07
+
3c8a07
+@item _SC_SIGSTKSZ
3c8a07
+@standards{GNU, unistd.h}
3c8a07
+Inquire about the suggested minimum number of bytes of stack space
3c8a07
+required for a signal stack.
3c8a07
+
3c8a07
+This is not guaranteed to be enough for any specific purpose other than
3c8a07
+the invocation of a single, non-nested, empty handler, but nonetheless
3c8a07
+should be enough for basic scenarios involving simple signal handlers
3c8a07
+and very low levels of signal nesting (say, 2 or 3 levels at the very
3c8a07
+most).
3c8a07
+
3c8a07
+This value is provided for developer convenience and to ease migration
3c8a07
+from the legacy @code{SIGSTKSZ} constant.  Programs requiring stronger
3c8a07
+guarantees should avoid using it if at all possible.
3c8a07
 @end vtable
3c8a07
 
3c8a07
 @node Examples of Sysconf
3c8a07
--- a/manual/creature.texi   2022-04-14 11:40:12.081653162 +0300
3c8a07
+++ b/manual/creature.texi       2022-04-14 11:41:54.376167038 +0300
3c8a07
@@ -251,6 +251,12 @@
3c8a07
 checks that may have an additional performance overhead.
3c8a07
 @end defvr
3c8a07
3c8a07
+@defvr Macro _SC_SIGSTKSZ_SOURCE
3c8a07
+@standards{GNU, (none)}
3c8a07
+If this macro is defined, correct (but non compile-time constant)
3c8a07
+MINSIGSTKSZ and SIGSTKSZ are defined.
3c8a07
+@end defvr
3c8a07
+
3c8a07
 @defvr Macro _REENTRANT
3c8a07
 @defvrx Macro _THREAD_SAFE
3c8a07
 @standards{Obsolete, (none)}
3c8a07
diff --git a/posix/sysconf.c b/posix/sysconf.c
3c8a07
index 09ebd95a..48c925f5 100644
3c8a07
--- a/posix/sysconf.c
3c8a07
+++ b/posix/sysconf.c
3c8a07
@@ -266,6 +266,9 @@ __sysconf (int name)
3c8a07
     case _SC_XOPEN_REALTIME:
3c8a07
     case _SC_XOPEN_REALTIME_THREADS:
3c8a07
 
3c8a07
+    case _SC_MINSIGSTKSZ:
3c8a07
+    case _SC_SIGSTKSZ:
3c8a07
+
3c8a07
       break;
3c8a07
     }
3c8a07
 
3c8a07
diff --git a/signal/Makefile b/signal/Makefile
3c8a07
index 7767bb28..cd85b8b6 100644
3c8a07
--- a/signal/Makefile
3c8a07
+++ b/signal/Makefile
3c8a07
@@ -31,7 +31,8 @@ headers := signal.h sys/signal.h \
3c8a07
 	   bits/types/sigevent_t.h bits/types/siginfo_t.h \
3c8a07
 	   bits/types/sigset_t.h bits/types/sigval_t.h \
3c8a07
 	   bits/types/stack_t.h bits/types/struct_sigstack.h \
3c8a07
-	   bits/types/__sigval_t.h
3c8a07
+	   bits/types/__sigval_t.h \
3c8a07
+	   bits/sigstksz.h
3c8a07
 
3c8a07
 routines	:= signal raise killpg \
3c8a07
 		   sigaction sigprocmask kill \
3c8a07
@@ -48,7 +49,7 @@ routines	:= signal raise killpg \
3c8a07
 tests		:= tst-signal tst-sigset tst-sigsimple tst-raise tst-sigset2 \
3c8a07
 		   tst-sigwait-eintr tst-sigaction \
3c8a07
 		   tst-minsigstksz-1 tst-minsigstksz-2 tst-minsigstksz-3 \
3c8a07
-		   tst-minsigstksz-3a tst-minsigstksz-4 \
3c8a07
+		   tst-minsigstksz-3a tst-minsigstksz-4 tst-minsigstksz-5
3c8a07
 
3c8a07
 include ../Rules
3c8a07
 
3c8a07
diff --git a/signal/signal.h b/signal/signal.h
3c8a07
index 87dc82a9..8ebfc6e6 100644
3c8a07
--- a/signal/signal.h
3c8a07
+++ b/signal/signal.h
3c8a07
@@ -314,6 +314,7 @@ extern int sigreturn (struct sigcontext *__scp) __THROW;
3c8a07
 extern int siginterrupt (int __sig, int __interrupt) __THROW;
3c8a07
 
3c8a07
 # include <bits/sigstack.h>
3c8a07
+# include <bits/sigstksz.h>
3c8a07
 # include <bits/ss_flags.h>
3c8a07
 
3c8a07
 /* Alternate signal handler stack interface.
3c8a07
diff --git a/signal/tst-minsigstksz-5.c b/signal/tst-minsigstksz-5.c
3c8a07
new file mode 100644
3c8a07
index 00000000..d657d2f4
3c8a07
--- /dev/null
3c8a07
+++ b/signal/tst-minsigstksz-5.c
3c8a07
@@ -0,0 +1,84 @@
3c8a07
+/* Test of signal delivery on an alternate stack with MINSIGSTKSZ size.
3c8a07
+   Copyright (C) 2020 Free Software Foundation, Inc.
3c8a07
+   This file is part of the GNU C Library.
3c8a07
+
3c8a07
+   The GNU C Library is free software; you can redistribute it and/or
3c8a07
+   modify it under the terms of the GNU Lesser General Public
3c8a07
+   License as published by the Free Software Foundation; either
3c8a07
+   version 2.1 of the License, or (at your option) any later version.
3c8a07
+
3c8a07
+   The GNU C Library is distributed in the hope that it will be useful,
3c8a07
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
3c8a07
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3c8a07
+   Lesser General Public License for more details.
3c8a07
+
3c8a07
+   You should have received a copy of the GNU Lesser General Public
3c8a07
+   License along with the GNU C Library; if not, see
3c8a07
+   <https://www.gnu.org/licenses/>.  */
3c8a07
+
3c8a07
+#include <signal.h>
3c8a07
+#include <stdlib.h>
3c8a07
+#include <string.h>
3c8a07
+#include <unistd.h>
3c8a07
+#include <support/check.h>
3c8a07
+#include <support/support.h>
3c8a07
+
3c8a07
+static volatile sig_atomic_t handler_run;
3c8a07
+
3c8a07
+static void
3c8a07
+handler (int signo)
3c8a07
+{
3c8a07
+  /* Clear a bit of on-stack memory.  */
3c8a07
+  volatile char buffer[256];
3c8a07
+  for (size_t i = 0; i < sizeof (buffer); ++i)
3c8a07
+    buffer[i] = 0;
3c8a07
+  handler_run = 1;
3c8a07
+}
3c8a07
+
3c8a07
+int
3c8a07
+do_test (void)
3c8a07
+{
3c8a07
+  size_t stack_buffer_size = 64 * 1024 * 1024;
3c8a07
+  void *stack_buffer = xmalloc (stack_buffer_size);
3c8a07
+  void *stack_end = stack_buffer + stack_buffer_size;
3c8a07
+  memset (stack_buffer, 0xCC, stack_buffer_size);
3c8a07
+
3c8a07
+  void *stack_bottom = stack_buffer + (stack_buffer_size + MINSIGSTKSZ) / 2;
3c8a07
+  void *stack_top = stack_bottom + MINSIGSTKSZ;
3c8a07
+  stack_t stack =
3c8a07
+    {
3c8a07
+      .ss_sp = stack_bottom,
3c8a07
+      .ss_size = MINSIGSTKSZ,
3c8a07
+    };
3c8a07
+  if (sigaltstack (&stack, NULL) < 0)
3c8a07
+    FAIL_RET ("sigaltstack: %m\n");
3c8a07
+
3c8a07
+  struct sigaction act =
3c8a07
+    {
3c8a07
+      .sa_handler = handler,
3c8a07
+      .sa_flags = SA_ONSTACK,
3c8a07
+    };
3c8a07
+  if (sigaction (SIGUSR1, &act, NULL) < 0)
3c8a07
+    FAIL_RET ("sigaction: %m\n");
3c8a07
+
3c8a07
+  if (kill (getpid (), SIGUSR1) < 0)
3c8a07
+    FAIL_RET ("kill: %m\n");
3c8a07
+
3c8a07
+  if (handler_run != 1)
3c8a07
+    FAIL_RET ("handler did not run\n");
3c8a07
+
3c8a07
+  for (void *p = stack_buffer; p < stack_bottom; ++p)
3c8a07
+    if (*(unsigned char *) p != 0xCC)
3c8a07
+      FAIL_RET ("changed byte %ld bytes below configured stack\n",
3c8a07
+		(long) (stack_bottom - p));
3c8a07
+  for (void *p = stack_top; p < stack_end; ++p)
3c8a07
+    if (*(unsigned char *) p != 0xCC)
3c8a07
+      FAIL_RET ("changed byte %ld bytes above configured stack\n",
3c8a07
+		(long) (p - stack_top));
3c8a07
+
3c8a07
+  free (stack_buffer);
3c8a07
+
3c8a07
+  return 0;
3c8a07
+}
3c8a07
+
3c8a07
+#include <support/test-driver.c>
3c8a07
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
3c8a07
index 6cbbaa80..a15bf2e5 100644
3c8a07
--- a/sysdeps/generic/ldsodefs.h
3c8a07
+++ b/sysdeps/generic/ldsodefs.h
3c8a07
@@ -527,6 +527,9 @@ struct rtld_global_ro
3c8a07
   /* Cached value of `getpagesize ()'.  */
3c8a07
   EXTERN size_t _dl_pagesize;
3c8a07
 
3c8a07
+  /* Cached value of `sysconf (_SC_MINSIGSTKSZ)'.  */
3c8a07
+  EXTERN size_t _dl_minsigstacksize;
3c8a07
+
3c8a07
   /* Do we read from ld.so.cache?  */
3c8a07
   EXTERN int _dl_inhibit_cache;
3c8a07
 
3c8a07
diff --git a/sysdeps/unix/sysv/linux/bits/sigstksz.h b/sysdeps/unix/sysv/linux/bits/sigstksz.h
3c8a07
new file mode 100644
3c8a07
index 00000000..926508f2
3c8a07
--- /dev/null
3c8a07
+++ b/sysdeps/unix/sysv/linux/bits/sigstksz.h
3c8a07
@@ -0,0 +1,33 @@
3c8a07
+/* Definition of MINSIGSTKSZ and SIGSTKSZ.  Linux version.
3c8a07
+   Copyright (C) 2020 Free Software Foundation, Inc.
3c8a07
+   This file is part of the GNU C Library.
3c8a07
+
3c8a07
+   The GNU C Library is free software; you can redistribute it and/or
3c8a07
+   modify it under the terms of the GNU Lesser General Public
3c8a07
+   License as published by the Free Software Foundation; either
3c8a07
+   version 2.1 of the License, or (at your option) any later version.
3c8a07
+
3c8a07
+   The GNU C Library is distributed in the hope that it will be useful,
3c8a07
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
3c8a07
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3c8a07
+   Lesser General Public License for more details.
3c8a07
+
3c8a07
+   You should have received a copy of the GNU Lesser General Public
3c8a07
+   License along with the GNU C Library; if not, see
3c8a07
+   <https://www.gnu.org/licenses/>.  */
3c8a07
+
3c8a07
+#ifndef _SIGNAL_H
3c8a07
+# error "Never include <bits/sigstksz.h> directly; use <signal.h> instead."
3c8a07
+#endif
3c8a07
+
3c8a07
+#if defined __USE_SC_SIGSTKSZ && __USE_SC_SIGSTKSZ
3c8a07
+# include <unistd.h>
3c8a07
+
3c8a07
+/* Default stack size for a signal handler: sysconf (SC_SIGSTKSZ).  */
3c8a07
+# undef SIGSTKSZ
3c8a07
+# define SIGSTKSZ sysconf (_SC_SIGSTKSZ)
3c8a07
+
3c8a07
+/* Minimum stack size for a signal handler: SIGSTKSZ.  */
3c8a07
+# undef MINSIGSTKSZ
3c8a07
+# define MINSIGSTKSZ SIGSTKSZ
3c8a07
+#endif
3c8a07
diff --git a/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h b/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h
3c8a07
new file mode 100644
3c8a07
index 00000000..7e5ceba1
3c8a07
--- /dev/null
3c8a07
+++ b/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h
3c8a07
@@ -0,0 +1,27 @@
3c8a07
+/* sysconf_sigstksz ().  Linux/ia64 version.
3c8a07
+   Copyright (C) 2020 Free Software Foundation, Inc.
3c8a07
+   This file is part of the GNU C Library.
3c8a07
+
3c8a07
+   The GNU C Library is free software; you can redistribute it and/or
3c8a07
+   modify it under the terms of the GNU Lesser General Public
3c8a07
+   License as published by the Free Software Foundation; either
3c8a07
+   version 2.1 of the License, or (at your option) any later version.
3c8a07
+
3c8a07
+   The GNU C Library is distributed in the hope that it will be useful,
3c8a07
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
3c8a07
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3c8a07
+   Lesser General Public License for more details.
3c8a07
+
3c8a07
+   You should have received a copy of the GNU Lesser General Public
3c8a07
+   License along with the GNU C Library; if not, see
3c8a07
+   <https://www.gnu.org/licenses/>.  */
3c8a07
+
3c8a07
+/* Return sysconf (_SC_SIGSTKSZ).  */
3c8a07
+
3c8a07
+static long int
3c8a07
+sysconf_sigstksz (void)
3c8a07
+{
3c8a07
+  _Static_assert (__builtin_constant_p (SIGSTKSZ),
3c8a07
+		  "SIGSTKSZ is constant");
3c8a07
+  return SIGSTKSZ;
3c8a07
+}
3c8a07
diff --git a/sysdeps/unix/sysv/linux/sysconf-sigstksz.h b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h
3c8a07
new file mode 100644
3c8a07
index 00000000..64d450b2
3c8a07
--- /dev/null
3c8a07
+++ b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h
3c8a07
@@ -0,0 +1,38 @@
3c8a07
+/* sysconf_sigstksz ().  Linux version.
3c8a07
+   Copyright (C) 2020 Free Software Foundation, Inc.
3c8a07
+   This file is part of the GNU C Library.
3c8a07
+
3c8a07
+   The GNU C Library is free software; you can redistribute it and/or
3c8a07
+   modify it under the terms of the GNU Lesser General Public
3c8a07
+   License as published by the Free Software Foundation; either
3c8a07
+   version 2.1 of the License, or (at your option) any later version.
3c8a07
+
3c8a07
+   The GNU C Library is distributed in the hope that it will be useful,
3c8a07
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
3c8a07
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3c8a07
+   Lesser General Public License for more details.
3c8a07
+
3c8a07
+   You should have received a copy of the GNU Lesser General Public
3c8a07
+   License along with the GNU C Library; if not, see
3c8a07
+   <https://www.gnu.org/licenses/>.  */
3c8a07
+
3c8a07
+/* Return sysconf (_SC_SIGSTKSZ).  */
3c8a07
+
3c8a07
+static long int
3c8a07
+sysconf_sigstksz (void)
3c8a07
+{
3c8a07
+  long int minsigstacksize = GLRO(dl_minsigstacksize);
3c8a07
+  assert (minsigstacksize != 0);
3c8a07
+  _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
3c8a07
+		  "MINSIGSTKSZ is constant");
3c8a07
+  if (minsigstacksize < MINSIGSTKSZ)
3c8a07
+    minsigstacksize = MINSIGSTKSZ;
3c8a07
+  /* MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4.  */
3c8a07
+  long int sigstacksize = minsigstacksize * 4;
3c8a07
+  /* Return MAX (SIGSTKSZ, sigstacksize).  */
3c8a07
+  _Static_assert (__builtin_constant_p (SIGSTKSZ),
3c8a07
+		  "SIGSTKSZ is constant");
3c8a07
+  if (sigstacksize < SIGSTKSZ)
3c8a07
+    sigstacksize = SIGSTKSZ;
3c8a07
+  return sigstacksize;
3c8a07
+}
3c8a07
diff --git a/sysdeps/unix/sysv/linux/sysconf.c b/sysdeps/unix/sysv/linux/sysconf.c
3c8a07
index 6fab1601..4aa9b171 100644
3c8a07
--- a/sysdeps/unix/sysv/linux/sysconf.c
3c8a07
+++ b/sysdeps/unix/sysv/linux/sysconf.c
3c8a07
@@ -16,6 +16,7 @@
3c8a07
    License along with the GNU C Library; if not, see
3c8a07
    <http://www.gnu.org/licenses/>.  */
3c8a07
 
3c8a07
+#include <assert.h>
3c8a07
 #include <errno.h>
3c8a07
 #include <fcntl.h>
3c8a07
 #include <stdlib.h>
3c8a07
@@ -26,6 +27,7 @@
3c8a07
 #include <sys/param.h>
3c8a07
 #include <not-cancel.h>
3c8a07
 #include <ldsodefs.h>
3c8a07
+#include <sysconf-sigstksz.h>
3c8a07
 
3c8a07
 /* Legacy value of ARG_MAX.  The macro is now not defined since the
3c8a07
    actual value varies based on the stack size.  */
3c8a07
@@ -75,6 +77,13 @@ __sysconf (int name)
3c8a07
       }
3c8a07
       break;
3c8a07
 
3c8a07
+    case _SC_MINSIGSTKSZ:
3c8a07
+      assert (GLRO(dl_minsigstacksize) != 0);
3c8a07
+      return GLRO(dl_minsigstacksize);
3c8a07
+
3c8a07
+    case _SC_SIGSTKSZ:
3c8a07
+      return sysconf_sigstksz ();
3c8a07
+
3c8a07
     default:
3c8a07
       break;
3c8a07
     }
3c8a07
diff --git a/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h b/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h
3c8a07
new file mode 100644
3c8a07
index 00000000..6088bbc9
3c8a07
--- /dev/null
3c8a07
+++ b/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h
3c8a07
@@ -0,0 +1,83 @@
3c8a07
+/* Emulate AT_MINSIGSTKSZ.  Linux/x86 version.
3c8a07
+   Copyright (C) 2020 Free Software Foundation, Inc.
3c8a07
+
3c8a07
+   The GNU C Library is free software; you can redistribute it and/or
3c8a07
+   modify it under the terms of the GNU Lesser General Public
3c8a07
+   License as published by the Free Software Foundation; either
3c8a07
+   version 2.1 of the License, or (at your option) any later version.
3c8a07
+
3c8a07
+   The GNU C Library is distributed in the hope that it will be useful,
3c8a07
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
3c8a07
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3c8a07
+   Lesser General Public License for more details.
3c8a07
+
3c8a07
+   You should have received a copy of the GNU Lesser General Public
3c8a07
+   License along with the GNU C Library; if not, see
3c8a07
+   <https://www.gnu.org/licenses/>.  */
3c8a07
+
3c8a07
+/* Emulate AT_MINSIGSTKSZ with XSAVE. */
3c8a07
+
3c8a07
+static inline void
3c8a07
+dl_check_minsigstacksize (const struct cpu_features *cpu_features)
3c8a07
+{
3c8a07
+  /* Return if AT_MINSIGSTKSZ is provide by kernel.  */
3c8a07
+  if (GLRO(dl_minsigstacksize) != 0)
3c8a07
+    return;
3c8a07
+
3c8a07
+  if (cpu_features->basic.max_cpuid >= 0xd
3c8a07
+      && CPU_FEATURES_CPU_P (cpu_features, OSXSAVE))
3c8a07
+    {
3c8a07
+      /* Emulate AT_MINSIGSTKSZ.  In Linux kernel, the signal frame data
3c8a07
+	 with XSAVE is composed of the following areas and laid out as:
3c8a07
+	 ------------------------------
3c8a07
+	 | alignment padding          |
3c8a07
+	 ------------------------------
3c8a07
+	 | xsave buffer               |
3c8a07
+	 ------------------------------
3c8a07
+	 | fsave header (32-bit only) |
3c8a07
+	 ------------------------------
3c8a07
+	 | siginfo + ucontext         |
3c8a07
+	 ------------------------------
3c8a07
+	 */
3c8a07
+
3c8a07
+      unsigned int sigframe_size;
3c8a07
+
3c8a07
+#ifdef __x86_64__
3c8a07
+      /* NB: sizeof(struct rt_sigframe) + 8-byte return address in Linux
3c8a07
+	 kernel.  */
3c8a07
+      sigframe_size = 440 + 8;
3c8a07
+#else
3c8a07
+      /* NB: sizeof(struct sigframe_ia32) + sizeof(struct fregs_state)) +
3c8a07
+	 4-byte return address + 3 * 4-byte arguments in Linux kernel.  */
3c8a07
+      sigframe_size = 736 + 112 + 4 + 3 * 4;
3c8a07
+#endif
3c8a07
+
3c8a07
+      /* Add 15 bytes to align the stack to 16 bytes.  */
3c8a07
+      sigframe_size += 15;
3c8a07
+
3c8a07
+      /* Make the space before xsave buffer multiple of 16 bytes.  */
3c8a07
+      sigframe_size = ALIGN_UP (sigframe_size, 16);
3c8a07
+
3c8a07
+      /* Add (64 - 16)-byte padding to align xsave buffer at 64 bytes.  */
3c8a07
+      sigframe_size += 64 - 16;
3c8a07
+
3c8a07
+      unsigned int eax, ebx, ecx, edx;
3c8a07
+      __cpuid_count (0xd, 0, eax, ebx, ecx, edx);
3c8a07
+
3c8a07
+      /* Add the size of xsave buffer.  */
3c8a07
+      sigframe_size += ebx;
3c8a07
+
3c8a07
+      /* Add the size of FP_XSTATE_MAGIC2.  */
3c8a07
+#define FP_XSTATE_MAGIC2 0x46505845U
3c8a07
+      sigframe_size += sizeof (FP_XSTATE_MAGIC2);
3c8a07
+
3c8a07
+      GLRO(dl_minsigstacksize) = sigframe_size;
3c8a07
+    }
3c8a07
+  else
3c8a07
+    {
3c8a07
+      /* NB: Default to a constant MINSIGSTKSZ.  */
3c8a07
+      _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
3c8a07
+		      "MINSIGSTKSZ is constant");
3c8a07
+      GLRO(dl_minsigstacksize) = MINSIGSTKSZ;
3c8a07
+    }
3c8a07
+}
3c8a07
diff --git a/sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h b/sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h
3c8a07
new file mode 100644
3c8a07
index 00000000..208754c4
3c8a07
--- /dev/null
3c8a07
+++ b/sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h
3c8a07
@@ -0,0 +1,5 @@
3c8a07
+#include_next <bits/sigstack.h>
3c8a07
+
3c8a07
+#ifndef _ISOMAC
3c8a07
+# define CONSTANT_MINSIGSTKSZ 0
3c8a07
+#endif
3c8a07
diff --git a/sysdeps/x86/dl-minsigstacksize.h b/sysdeps/x86/dl-minsigstacksize.h
3c8a07
new file mode 100644
3c8a07
index 00000000..959871c9
3c8a07
--- /dev/null
3c8a07
+++ b/sysdeps/x86/dl-minsigstacksize.h
3c8a07
@@ -0,0 +1,27 @@
3c8a07
+/* Emulate AT_MINSIGSTKSZ.  Generic x86 version.
3c8a07
+   Copyright (C) 2020 Free Software Foundation, Inc.
3c8a07
+
3c8a07
+   The GNU C Library is free software; you can redistribute it and/or
3c8a07
+   modify it under the terms of the GNU Lesser General Public
3c8a07
+   License as published by the Free Software Foundation; either
3c8a07
+   version 2.1 of the License, or (at your option) any later version.
3c8a07
+
3c8a07
+   The GNU C Library is distributed in the hope that it will be useful,
3c8a07
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
3c8a07
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3c8a07
+   Lesser General Public License for more details.
3c8a07
+
3c8a07
+   You should have received a copy of the GNU Lesser General Public
3c8a07
+   License along with the GNU C Library; if not, see
3c8a07
+   <https://www.gnu.org/licenses/>.  */
3c8a07
+
3c8a07
+/* Emulate AT_MINSIGSTKSZ with XSAVE. */
3c8a07
+
3c8a07
+static inline void
3c8a07
+dl_check_minsigstacksize (const struct cpu_features *cpu_features)
3c8a07
+{
3c8a07
+  /* NB: Default to a constant MINSIGSTKSZ.  */
3c8a07
+  _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
3c8a07
+		  "MINSIGSTKSZ is constant");
3c8a07
+  GLRO(dl_minsigstacksize) = MINSIGSTKSZ;
3c8a07
+}
3c8a07
-- 
3c8a07
2.27.0
3c8a07