diff mbox series

V10 [PATCH] sysconf: Add _SC_MINSIGSTKSZ/_SC_SIGSTKSZ [BZ #20305]

Message ID CAMe9rOoNwX2fNf-cx4ygzBG4iR_Y4FN_q2j9DhtqyPTAM8CMkw@mail.gmail.com
State Committed
Delegated to: Carlos O'Donell
Headers show
Series V10 [PATCH] sysconf: Add _SC_MINSIGSTKSZ/_SC_SIGSTKSZ [BZ #20305] | expand

Commit Message

H.J. Lu Jan. 22, 2021, 7:41 p.m. UTC
On Wed, Jan 20, 2021 at 7:05 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Wed, Jan 20, 2021 at 6:16 AM Carlos O'Donell <carlos@redhat.com> wrote:
> >
> > On 11/20/20 6:13 PM, H.J. Lu via Libc-alpha wrote:
> > > On Fri, Nov 20, 2020 at 6:12 AM Florian Weimer <fw@deneb.enyo.de> wrote:
> > >>
> > >> * H. J. Lu:
> > >>
> > >>> Can we reach a consensus for _GNU_SOURCE vs _SC_SIGSTKSZ_SOURCE?
> > >>>
> > >>> How about we make _GNU_SOURCE to enable _SC_SIGSTKSZ_SOURCE and
> > >>> check _SC_SIGSTKSZ_SOURCE != 0?  If _GNU_SOURCE triggers compilation
> > >>> error and source codes can't be changed, we can add
> > >>> -D_SC_SIGSTKSZ_SOURCE=0 to disable _SC_SIGSTKSZ_SOURCE.
> > >>
> > >> I think the source code compatibility is much more obscure than the
> > >> other things we broke quite recently, even without deprecation.  Why
> > >> do we add the complexity in this case?  I feel it is disproportional.
> > >
> > > Here is the patch with _GNU_SOURCE.  Any comments?
> >
> > (1) New version of patch.
> >
> > This patch no longer compiles due to __cpuid_count errors.
> >
> > Could you please update this and post a v9?
>
> Fixed.
>
> > This is ABI addition for the constants so I want to make sure I review
> > something that works and is final from your end.
> >
> > (2) Kernel definition of constant for AT_MINSIGSTKSZ?
> >
> > We don't have a released kernel for x86 with this constant defined?
> >
> > The kernel patch was only just updated 5 days ago:
> > https://sourceware.org/pipermail/libc-alpha/2021-January/121671.html
> >
> > Doesn't this mean this patch is inappropriate for glibc 2.33?
>
> The new glibc works with the older kernels.  In many cases, we
> use emulation for the older kernels.  This patch only uses the
> existing kernel interface.   The kernel patch you referred doesn't
> add any new interface.  It simply uses the existing AT_MINSIGSTKSZ
> for x86.  My patch includes an emulation for the older kernels.   I
> think my patch is appropriate for glibc 2.33.
>
> Here is the updated patc.
>
> Thanks.

Another rebase.

Comments

Carlos O'Donell Jan. 25, 2021, 1:31 p.m. UTC | #1
On 1/22/21 2:41 PM, H.J. Lu wrote:
> Another rebase.

Just a note here that v10 does not apply with patchwork automation.

This makes things more difficult for my review and automated testing.

If possible could you please just resent via git send-email on a new thread?

e.g.

git format-patch -v 10 ...
git send-email ...
H.J. Lu Jan. 25, 2021, 1:57 p.m. UTC | #2
On Mon, Jan 25, 2021 at 5:32 AM Carlos O'Donell <carlos@redhat.com> wrote:
>
> On 1/22/21 2:41 PM, H.J. Lu wrote:
> > Another rebase.
>
> Just a note here that v10 does not apply with patchwork automation.
>
> This makes things more difficult for my review and automated testing.
>
> If possible could you please just resent via git send-email on a new thread?
>
> e.g.
>
> git format-patch -v 10 ...
> git send-email ...
>

Done.
Carlos O'Donell Jan. 25, 2021, 1:58 p.m. UTC | #3
On 1/22/21 2:41 PM, H.J. Lu wrote:
> On Wed, Jan 20, 2021 at 7:05 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> On Wed, Jan 20, 2021 at 6:16 AM Carlos O'Donell <carlos@redhat.com> wrote:
>>>
>>> On 11/20/20 6:13 PM, H.J. Lu via Libc-alpha wrote:
>>>> On Fri, Nov 20, 2020 at 6:12 AM Florian Weimer <fw@deneb.enyo.de> wrote:
>>>>>
>>>>> * H. J. Lu:
>>>>>
>>>>>> Can we reach a consensus for _GNU_SOURCE vs _SC_SIGSTKSZ_SOURCE?
>>>>>>
>>>>>> How about we make _GNU_SOURCE to enable _SC_SIGSTKSZ_SOURCE and
>>>>>> check _SC_SIGSTKSZ_SOURCE != 0?  If _GNU_SOURCE triggers compilation
>>>>>> error and source codes can't be changed, we can add
>>>>>> -D_SC_SIGSTKSZ_SOURCE=0 to disable _SC_SIGSTKSZ_SOURCE.
>>>>>
>>>>> I think the source code compatibility is much more obscure than the
>>>>> other things we broke quite recently, even without deprecation.  Why
>>>>> do we add the complexity in this case?  I feel it is disproportional.
>>>>
>>>> Here is the patch with _GNU_SOURCE.  Any comments?
>>>
>>> (1) New version of patch.
>>>
>>> This patch no longer compiles due to __cpuid_count errors.
>>>
>>> Could you please update this and post a v9?
>>
>> Fixed.
>>
>>> This is ABI addition for the constants so I want to make sure I review
>>> something that works and is final from your end.
>>>
>>> (2) Kernel definition of constant for AT_MINSIGSTKSZ?
>>>
>>> We don't have a released kernel for x86 with this constant defined?
>>>
>>> The kernel patch was only just updated 5 days ago:
>>> https://sourceware.org/pipermail/libc-alpha/2021-January/121671.html
>>>
>>> Doesn't this mean this patch is inappropriate for glibc 2.33?
>>
>> The new glibc works with the older kernels.  In many cases, we
>> use emulation for the older kernels.  This patch only uses the
>> existing kernel interface.   The kernel patch you referred doesn't
>> add any new interface.  It simply uses the existing AT_MINSIGSTKSZ
>> for x86.  My patch includes an emulation for the older kernels.   I
>> think my patch is appropriate for glibc 2.33.
>>
>> Here is the updated patc.
>>
>> Thanks.
> 
> Another rebase.

This change looks good to me.

We add two new constants _SC_MINSIGSTKSZ and _SC_SIGSTKSZ.

We document them as constants to sysconf().

We document _SC_SIGSTKSZ_SOURCE as the way to request this change.

We document this is part of _GNU_SOURCE.

This may break application builds and may need to be worked around if
the application expected static allocation and need to switch to dynamic
allocation of a constant at runtime. This kind of change may not always
be easy to architect, but should be possible with an early constructor.

Tested on i686 and x86_64 and all pass.

Tested-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
 
> From 9f040b4540feec52577b660cb151c79cdc2741a3 Mon Sep 17 00:00:00 2001
> From: "H.J. Lu" <hjl.tools@gmail.com>
> Date: Fri, 25 Sep 2020 13:10:08 -0700
> Subject: [PATCH] sysconf: Add _SC_MINSIGSTKSZ/_SC_SIGSTKSZ [BZ #20305]
> 
> Add _SC_MINSIGSTKSZ for the minimum signal stack size derived from
> AT_MINSIGSTKSZ, which is the minimum number of bytes of free stack
> space required in order to gurantee successful, non-nested handling

s/gurantee/guarantee/g

> of a single signal whose handler is an empty function, and _SC_SIGSTKSZ
> which is the suggested minimum number of bytes of stack space required
> for a signal stack.
> 
> If AT_MINSIGSTKSZ isn't available, sysconf (_SC_MINSIGSTKSZ) returns
> MINSIGSTKSZ.  On Linux/x86 with XSAVE, the signal frame used by kernel
> is composed of the following areas and laid out as:
> 
>  ------------------------------
>  | alignment padding          |
>  ------------------------------
>  | xsave buffer               |
>  ------------------------------
>  | fsave header (32-bit only) |
>  ------------------------------
>  | siginfo + ucontext         |
>  ------------------------------
> 
> Compute AT_MINSIGSTKSZ value as size of xsave buffer + size of fsave
> header (32-bit only) + size of siginfo and ucontext + alignment padding.
> 
> If _SC_SIGSTKSZ_SOURCE or _GNU_SOURCE are defined, MINSIGSTKSZ and SIGSTKSZ
> are redefined as
> 
> /* Default stack size for a signal handler: sysconf (SC_SIGSTKSZ).  */
>  # undef SIGSTKSZ
>  # define SIGSTKSZ sysconf (_SC_SIGSTKSZ)
> 
> /* Minimum stack size for a signal handler: SIGSTKSZ.  */
>  # undef MINSIGSTKSZ
>  # define MINSIGSTKSZ SIGSTKSZ

OK.

> 
> Compilation will fail if the source assumes constant MINSIGSTKSZ or
> SIGSTKSZ.

OK.

> 
> The reason for not simply increasing the kernel's MINSIGSTKSZ #define
> (apart from the fact that it is rarely used, due to glibc's shadowing
> definitions) was that userspace binaries will have baked in the old
> value of the constant and may be making assumptions about it.

OK. Yes, we need to stop baking this into applications. There may be
some teething pain if constant-sized objects need to switch to be
dynamically sized? This worries me a little bit, but the rare usage
of this constant means the impact will be low.

 
> For example, the type (char [MINSIGSTKSZ]) changes if this #define
> changes.  This could be a problem if an newly built library tries to
> memcpy() or dump such an object defined by and old binary.
> Bounds-checking and the stack sizes passed to things like sigaltstack()
> and makecontext() could similarly go wrong.

OK. Correct. This is always the case and why it's ABI.

> ---
>  NEWS                                          |  5 ++
>  bits/confname.h                               |  8 +-
>  bits/sigstksz.h                               | 21 +++++
>  elf/dl-support.c                              |  5 ++
>  elf/dl-sysdep.c                               |  9 ++
>  include/bits/sigstack.h                       |  5 ++
>  include/bits/sigstksz.h                       |  7 ++
>  include/features.h                            | 11 +++
>  manual/conf.texi                              | 21 +++++
>  manual/creature.texi                          |  6 ++
>  posix/sysconf.c                               |  3 +
>  signal/Makefile                               |  5 +-
>  signal/signal.h                               |  1 +
>  signal/tst-minsigstksz-5.c                    | 84 +++++++++++++++++++
>  sysdeps/generic/ldsodefs.h                    |  3 +
>  sysdeps/unix/sysv/linux/bits/sigstksz.h       | 33 ++++++++
>  .../unix/sysv/linux/ia64/sysconf-sigstksz.h   | 27 ++++++
>  sysdeps/unix/sysv/linux/sysconf-sigstksz.h    | 38 +++++++++
>  sysdeps/unix/sysv/linux/sysconf.c             |  9 ++
>  .../unix/sysv/linux/x86/dl-minsigstacksize.h  | 83 ++++++++++++++++++
>  .../sysv/linux/x86/include/bits/sigstack.h    |  5 ++
>  sysdeps/x86/cpu-features.c                    |  3 +
>  sysdeps/x86/dl-minsigstacksize.h              | 27 ++++++
>  23 files changed, 416 insertions(+), 3 deletions(-)
>  create mode 100644 bits/sigstksz.h
>  create mode 100644 include/bits/sigstack.h
>  create mode 100644 include/bits/sigstksz.h
>  create mode 100644 signal/tst-minsigstksz-5.c
>  create mode 100644 sysdeps/unix/sysv/linux/bits/sigstksz.h
>  create mode 100644 sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h
>  create mode 100644 sysdeps/unix/sysv/linux/sysconf-sigstksz.h
>  create mode 100644 sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h
>  create mode 100644 sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h
>  create mode 100644 sysdeps/x86/dl-minsigstacksize.h
> 
> diff --git a/NEWS b/NEWS
> index d121f7df87..0758bb37e3 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -9,6 +9,11 @@ Version 2.33
>  
>  Major new features:
>  
> +* Add _SC_MINSIGSTKSZ and _SC_SIGSTKSZ.  When _SC_SIGSTKSZ_SOURCE or
> +  _GNU_SOURCE are defined, MINSIGSTKSZ and SIGSTKSZ are no longer
> +  constant on Linux.  MINSIGSTKSZ is redefined to sysconf(_SC_MINSIGSTKSZ)
> +  and SIGSTKSZ is redefined to sysconf (_SC_SIGSTKSZ).

OK.

> +
>  * The dynamic linker accepts the --list-tunables argument which prints
>    all the supported tunables.  This option is disable if glibc is
>    configured with tunables disabled (--enable-tunables=no).
> diff --git a/bits/confname.h b/bits/confname.h
> index 8068bda273..ec6cd07957 100644
> --- a/bits/confname.h
> +++ b/bits/confname.h
> @@ -525,8 +525,14 @@ enum
>  
>      _SC_THREAD_ROBUST_PRIO_INHERIT,
>  #define _SC_THREAD_ROBUST_PRIO_INHERIT	_SC_THREAD_ROBUST_PRIO_INHERIT
> -    _SC_THREAD_ROBUST_PRIO_PROTECT
> +    _SC_THREAD_ROBUST_PRIO_PROTECT,
>  #define _SC_THREAD_ROBUST_PRIO_PROTECT	_SC_THREAD_ROBUST_PRIO_PROTECT
> +
> +    _SC_MINSIGSTKSZ,
> +#define	_SC_MINSIGSTKSZ			_SC_MINSIGSTKSZ

OK.

> +
> +    _SC_SIGSTKSZ
> +#define	_SC_SIGSTKSZ			_SC_SIGSTKSZ

OK.

>    };
>  
>  /* Values for the NAME argument to `confstr'.  */
> diff --git a/bits/sigstksz.h b/bits/sigstksz.h
> new file mode 100644
> index 0000000000..5535d873b5
> --- /dev/null
> +++ b/bits/sigstksz.h
> @@ -0,0 +1,21 @@
> +/* Definition of MINSIGSTKSZ.  Generic version.
> +   Copyright (C) 2020 Free Software Foundation, Inc.

s/2020/2021/g

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SIGNAL_H
> +# error "Never include <bits/sigstksz.h> directly; use <signal.h> instead."
> +#endif
> diff --git a/elf/dl-support.c b/elf/dl-support.c
> index 7abb65d8e3..7fc2ee78e2 100644
> --- a/elf/dl-support.c
> +++ b/elf/dl-support.c
> @@ -142,6 +142,8 @@ void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
>  
>  size_t _dl_pagesize = EXEC_PAGESIZE;
>  
> +size_t _dl_minsigstacksize = CONSTANT_MINSIGSTKSZ;

OK. Constant default value.

> +
>  int _dl_inhibit_cache;
>  
>  unsigned int _dl_osversion;
> @@ -307,6 +309,9 @@ _dl_aux_init (ElfW(auxv_t) *av)
>        case AT_RANDOM:
>  	_dl_random = (void *) av->a_un.a_val;
>  	break;
> +      case AT_MINSIGSTKSZ:
> +	_dl_minsigstacksize = av->a_un.a_val;

OK. Fetch from the kernel.

> +	break;
>        DL_PLATFORM_AUXV
>        }
>    if (seen == 0xf)
> diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
> index 0658c17da6..bd5066fe3b 100644
> --- a/elf/dl-sysdep.c
> +++ b/elf/dl-sysdep.c
> @@ -115,6 +115,11 @@ _dl_sysdep_start (void **start_argptr,
>    user_entry = (ElfW(Addr)) ENTRY_POINT;
>    GLRO(dl_platform) = NULL; /* Default to nothing known about the platform.  */
>  
> +  /* NB: Default to a constant CONSTANT_MINSIGSTKSZ.  */
> +  _Static_assert (__builtin_constant_p (CONSTANT_MINSIGSTKSZ),
> +		  "CONSTANT_MINSIGSTKSZ is constant");
> +  GLRO(dl_minsigstacksize) = CONSTANT_MINSIGSTKSZ;

OK.

> +
>    for (av = GLRO(dl_auxv); av->a_type != AT_NULL; set_seen (av++))
>      switch (av->a_type)
>        {
> @@ -179,6 +184,9 @@ _dl_sysdep_start (void **start_argptr,
>        case AT_RANDOM:
>  	_dl_random = (void *) av->a_un.a_val;
>  	break;
> +      case AT_MINSIGSTKSZ:
> +	GLRO(dl_minsigstacksize) = av->a_un.a_val;
> +	break;

OK.

>        DL_PLATFORM_AUXV
>        }
>  
> @@ -306,6 +314,7 @@ _dl_show_auxv (void)
>  	  [AT_SYSINFO_EHDR - 2] =	{ "SYSINFO_EHDR:      0x", hex },
>  	  [AT_RANDOM - 2] =		{ "RANDOM:            0x", hex },
>  	  [AT_HWCAP2 - 2] =		{ "HWCAP2:            0x", hex },
> +	  [AT_MINSIGSTKSZ - 2] =	{ "MINSIGSTKSZ        ", dec },

OK.

>  	  [AT_L1I_CACHESIZE - 2] =	{ "L1I_CACHESIZE:     ", dec },
>  	  [AT_L1I_CACHEGEOMETRY - 2] =	{ "L1I_CACHEGEOMETRY: 0x", hex },
>  	  [AT_L1D_CACHESIZE - 2] =	{ "L1D_CACHESIZE:     ", dec },
> diff --git a/include/bits/sigstack.h b/include/bits/sigstack.h
> new file mode 100644
> index 0000000000..eea939f59d
> --- /dev/null
> +++ b/include/bits/sigstack.h
> @@ -0,0 +1,5 @@
> +#include_next <bits/sigstack.h>
> +
> +#if !defined _ISOMAC && !defined CONSTANT_MINSIGSTKSZ
> +# define CONSTANT_MINSIGSTKSZ MINSIGSTKSZ

OK. Define constant to old MINSIGSTKSZ. Reasonable enough.

> +#endif
> diff --git a/include/bits/sigstksz.h b/include/bits/sigstksz.h
> new file mode 100644
> index 0000000000..2ca891e918
> --- /dev/null
> +++ b/include/bits/sigstksz.h
> @@ -0,0 +1,7 @@
> +/* NB: Don't define MINSIGSTKSZ nor SIGSTKSZ to sysconf (SC_SIGSTKSZ) for
> +   glibc build.  IS_IN can only be used when _ISOMAC isn't defined.  */
> +#ifdef _ISOMAC
> +# include_next <bits/sigstksz.h>
> +#elif IS_IN (libsupport)
> +# include_next <bits/sigstksz.h>
> +#endif

OK.

> diff --git a/include/features.h b/include/features.h
> index a71ac85af4..cc05a31ae1 100644
> --- a/include/features.h
> +++ b/include/features.h
> @@ -48,6 +48,8 @@
>     _LARGEFILE64_SOURCE	Additional functionality from LFS for large files.
>     _FILE_OFFSET_BITS=N	Select default filesystem interface.
>     _ATFILE_SOURCE	Additional *at interfaces.
> +   _SC_SIGSTKSZ_SOURCE	Select correct (but non compile-time constant)
> +			MINSIGSTKSZ and SIGSTKSZ.

OK. We could argue all day what to call this, and this name is sufficient
to indicate and document what it means.

>     _GNU_SOURCE		All of the above, plus GNU extensions.
>     _DEFAULT_SOURCE	The default set of features (taking precedence over
>  			__STRICT_ANSI__).
> @@ -94,6 +96,8 @@
>     __USE_FILE_OFFSET64	Define 64bit interface as default.
>     __USE_MISC		Define things from 4.3BSD or System V Unix.
>     __USE_ATFILE		Define *at interfaces and AT_* constants for them.
> +   __USE_SC_SIGSTKSZ	Define correct (but non compile-time constant)
> +			MINSIGSTKSZ and SIGSTKSZ.

OK.

>     __USE_GNU		Define GNU extensions.
>     __USE_FORTIFY_LEVEL	Additional security measures used, according to level.
>  
> @@ -137,6 +141,7 @@
>  #undef	__USE_FILE_OFFSET64
>  #undef	__USE_MISC
>  #undef	__USE_ATFILE
> +#undef	__USE_SC_SIGSTKSZ

OK.

>  #undef	__USE_GNU
>  #undef	__USE_FORTIFY_LEVEL
>  #undef	__KERNEL_STRICT_NAMES
> @@ -213,6 +218,8 @@
>  # define _DEFAULT_SOURCE	1
>  # undef  _ATFILE_SOURCE
>  # define _ATFILE_SOURCE	1
> +# undef  _SC_SIGSTKSZ_SOURCE
> +# define _SC_SIGSTKSZ_SOURCE 1

OK.

>  #endif
>  
>  /* If nothing (other than _GNU_SOURCE and _DEFAULT_SOURCE) is defined,
> @@ -388,6 +395,10 @@
>  # define __USE_ATFILE	1
>  #endif
>  
> +#ifdef	_SC_SIGSTKSZ_SOURCE
> +# define __USE_SC_SIGSTKSZ	1

OK. Set __USE_* from top-level feature.

> +#endif
> +
>  #ifdef	_GNU_SOURCE
>  # define __USE_GNU	1
>  #endif
> diff --git a/manual/conf.texi b/manual/conf.texi
> index f959b00bb6..ba9847aaa4 100644
> --- a/manual/conf.texi
> +++ b/manual/conf.texi
> @@ -913,6 +913,27 @@ Inquire about the parameter corresponding to @code{NL_SETMAX}.
>  @item _SC_NL_TEXTMAX
>  @standards{X/Open, unistd.h}
>  Inquire about the parameter corresponding to @code{NL_TEXTMAX}.
> +
> +@item _SC_MINSIGSTKSZ
> +@standards{GNU, unistd.h}
> +Inquire about the minimum number of bytes of free stack space required
> +in order to guarantee successful, non-nested handling of a single signal
> +whose handler is an empty function.

OK.

> +
> +@item _SC_SIGSTKSZ
> +@standards{GNU, unistd.h}
> +Inquire about the suggested minimum number of bytes of stack space
> +required for a signal stack.
> +
> +This is not guaranteed to be enough for any specific purpose other than
> +the invocation of a single, non-nested, empty handler, but nonetheless
> +should be enough for basic scenarios involving simple signal handlers
> +and very low levels of signal nesting (say, 2 or 3 levels at the very
> +most).

OK.

> +
> +This value is provided for developer convenience and to ease migration
> +from the legacy @code{SIGSTKSZ} constant.  Programs requiring stronger
> +guarantees should avoid using it if at all possible.

OK.

>  @end vtable
>  
>  @node Examples of Sysconf
> diff --git a/manual/creature.texi b/manual/creature.texi
> index 31208ccb2b..5090735e4f 100644
> --- a/manual/creature.texi
> +++ b/manual/creature.texi
> @@ -258,6 +258,12 @@ checks are applied. If defined to @math{3}, @theglibc{} may also use
>  checks that may have an additional performance overhead.
>  @end defvr
>  
> +@defvr Macro _SC_SIGSTKSZ_SOURCE
> +@standards{GNU, (none)}
> +If this macro is defined, correct (but non compile-time constant)
> +MINSIGSTKSZ and SIGSTKSZ are defined.

OK.

> +@end defvr
> +
>  @defvr Macro _REENTRANT
>  @defvrx Macro _THREAD_SAFE
>  @standards{Obsolete, (none)}
> diff --git a/posix/sysconf.c b/posix/sysconf.c
> index bb9e132e5c..67d17ca0f8 100644
> --- a/posix/sysconf.c
> +++ b/posix/sysconf.c
> @@ -266,6 +266,9 @@ __sysconf (int name)
>      case _SC_XOPEN_REALTIME:
>      case _SC_XOPEN_REALTIME_THREADS:
>  
> +    case _SC_MINSIGSTKSZ:
> +    case _SC_SIGSTKSZ:

OK.

> +
>        break;
>      }
>  
> diff --git a/signal/Makefile b/signal/Makefile
> index e89c308889..3d8cab1f50 100644
> --- a/signal/Makefile
> +++ b/signal/Makefile
> @@ -31,7 +31,8 @@ headers := signal.h sys/signal.h \
>  	   bits/types/sigevent_t.h bits/types/siginfo_t.h \
>  	   bits/types/sigset_t.h bits/types/sigval_t.h \
>  	   bits/types/stack_t.h bits/types/struct_sigstack.h \
> -	   bits/types/__sigval_t.h bits/signal_ext.h
> +	   bits/types/__sigval_t.h bits/signal_ext.h \
> +	   bits/sigstksz.h

OK.

>  
>  routines	:= signal raise killpg \
>  		   sigaction sigprocmask kill \
> @@ -48,7 +49,7 @@ routines	:= signal raise killpg \
>  tests		:= tst-signal tst-sigset tst-sigsimple tst-raise tst-sigset2 \
>  		   tst-sigwait-eintr tst-sigaction \
>  		   tst-minsigstksz-1 tst-minsigstksz-2 tst-minsigstksz-3 \
> -		   tst-minsigstksz-3a tst-minsigstksz-4 \
> +		   tst-minsigstksz-3a tst-minsigstksz-4 tst-minsigstksz-5 \

OK.

>  		   tst-sigisemptyset
>  
>  include ../Rules
> diff --git a/signal/signal.h b/signal/signal.h
> index 6463c98e11..b17203c99c 100644
> --- a/signal/signal.h
> +++ b/signal/signal.h
> @@ -312,6 +312,7 @@ extern int siginterrupt (int __sig, int __interrupt) __THROW
>    __attribute_deprecated_msg__ ("Use sigaction with SA_RESTART instead");
>  
>  # include <bits/sigstack.h>
> +# include <bits/sigstksz.h>

OK.

>  # include <bits/ss_flags.h>
>  
>  /* Alternate signal handler stack interface.
> diff --git a/signal/tst-minsigstksz-5.c b/signal/tst-minsigstksz-5.c
> new file mode 100644
> index 0000000000..d657d2f4e6
> --- /dev/null
> +++ b/signal/tst-minsigstksz-5.c
> @@ -0,0 +1,84 @@
> +/* Test of signal delivery on an alternate stack with MINSIGSTKSZ size.
> +   Copyright (C) 2020 Free Software Foundation, Inc.

s/2020/2021/g

> +   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 <signal.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +
> +static volatile sig_atomic_t handler_run;
> +
> +static void
> +handler (int signo)
> +{
> +  /* Clear a bit of on-stack memory.  */
> +  volatile char buffer[256];
> +  for (size_t i = 0; i < sizeof (buffer); ++i)
> +    buffer[i] = 0;
> +  handler_run = 1;
> +}
> +
> +int
> +do_test (void)
> +{
> +  size_t stack_buffer_size = 64 * 1024 * 1024;
> +  void *stack_buffer = xmalloc (stack_buffer_size);
> +  void *stack_end = stack_buffer + stack_buffer_size;
> +  memset (stack_buffer, 0xCC, stack_buffer_size);
> +
> +  void *stack_bottom = stack_buffer + (stack_buffer_size + MINSIGSTKSZ) / 2;
> +  void *stack_top = stack_bottom + MINSIGSTKSZ;
> +  stack_t stack =
> +    {
> +      .ss_sp = stack_bottom,
> +      .ss_size = MINSIGSTKSZ,

OK. All these references are sysconf-based now.

> +    };
> +  if (sigaltstack (&stack, NULL) < 0)
> +    FAIL_RET ("sigaltstack: %m\n");
> +
> +  struct sigaction act =
> +    {
> +      .sa_handler = handler,
> +      .sa_flags = SA_ONSTACK,
> +    };
> +  if (sigaction (SIGUSR1, &act, NULL) < 0)
> +    FAIL_RET ("sigaction: %m\n");
> +
> +  if (kill (getpid (), SIGUSR1) < 0)
> +    FAIL_RET ("kill: %m\n");
> +
> +  if (handler_run != 1)
> +    FAIL_RET ("handler did not run\n");
> +
> +  for (void *p = stack_buffer; p < stack_bottom; ++p)
> +    if (*(unsigned char *) p != 0xCC)
> +      FAIL_RET ("changed byte %ld bytes below configured stack\n",
> +		(long) (stack_bottom - p));
> +  for (void *p = stack_top; p < stack_end; ++p)
> +    if (*(unsigned char *) p != 0xCC)
> +      FAIL_RET ("changed byte %ld bytes above configured stack\n",
> +		(long) (p - stack_top));
> +
> +  free (stack_buffer);
> +
> +  return 0;
> +}

OK.

> +
> +#include <support/test-driver.c>
> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index aab7245e93..9720a4e446 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -536,6 +536,9 @@ struct rtld_global_ro
>    /* Cached value of `getpagesize ()'.  */
>    EXTERN size_t _dl_pagesize;
>  
> +  /* Cached value of `sysconf (_SC_MINSIGSTKSZ)'.  */
> +  EXTERN size_t _dl_minsigstacksize;

OK.

> +
>    /* Do we read from ld.so.cache?  */
>    EXTERN int _dl_inhibit_cache;
>  
> diff --git a/sysdeps/unix/sysv/linux/bits/sigstksz.h b/sysdeps/unix/sysv/linux/bits/sigstksz.h
> new file mode 100644
> index 0000000000..926508f2b4
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/sigstksz.h
> @@ -0,0 +1,33 @@
> +/* Definition of MINSIGSTKSZ and SIGSTKSZ.  Linux version.
> +   Copyright (C) 2020 Free Software Foundation, Inc.

s/2020/2021/g

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SIGNAL_H
> +# error "Never include <bits/sigstksz.h> directly; use <signal.h> instead."
> +#endif
> +
> +#if defined __USE_SC_SIGSTKSZ && __USE_SC_SIGSTKSZ
> +# include <unistd.h>
> +
> +/* Default stack size for a signal handler: sysconf (SC_SIGSTKSZ).  */
> +# undef SIGSTKSZ
> +# define SIGSTKSZ sysconf (_SC_SIGSTKSZ)
> +
> +/* Minimum stack size for a signal handler: SIGSTKSZ.  */
> +# undef MINSIGSTKSZ
> +# define MINSIGSTKSZ SIGSTKSZ

OK.

> +#endif
> diff --git a/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h b/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h
> new file mode 100644
> index 0000000000..7e5ceba151
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h
> @@ -0,0 +1,27 @@
> +/* sysconf_sigstksz ().  Linux/ia64 version.
> +   Copyright (C) 2020 Free Software Foundation, Inc.

s/2020/2021/g

> +   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/>.  */
> +
> +/* Return sysconf (_SC_SIGSTKSZ).  */
> +
> +static long int
> +sysconf_sigstksz (void)
> +{
> +  _Static_assert (__builtin_constant_p (SIGSTKSZ),
> +		  "SIGSTKSZ is constant");
> +  return SIGSTKSZ;

OK.

> +}
> diff --git a/sysdeps/unix/sysv/linux/sysconf-sigstksz.h b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h
> new file mode 100644
> index 0000000000..64d450b22c
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h
> @@ -0,0 +1,38 @@
> +/* sysconf_sigstksz ().  Linux version.
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +/* Return sysconf (_SC_SIGSTKSZ).  */
> +
> +static long int
> +sysconf_sigstksz (void)
> +{
> +  long int minsigstacksize = GLRO(dl_minsigstacksize);
> +  assert (minsigstacksize != 0);
> +  _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
> +		  "MINSIGSTKSZ is constant");
> +  if (minsigstacksize < MINSIGSTKSZ)
> +    minsigstacksize = MINSIGSTKSZ;
> +  /* MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4.  */

OK. Return the max of the constant or sysconf value times 4 to allow some
nested signals.

> +  long int sigstacksize = minsigstacksize * 4;
> +  /* Return MAX (SIGSTKSZ, sigstacksize).  */
> +  _Static_assert (__builtin_constant_p (SIGSTKSZ),
> +		  "SIGSTKSZ is constant");
> +  if (sigstacksize < SIGSTKSZ)
> +    sigstacksize = SIGSTKSZ;
> +  return sigstacksize;

OK.

> +}
> diff --git a/sysdeps/unix/sysv/linux/sysconf.c b/sysdeps/unix/sysv/linux/sysconf.c
> index bfad5b6858..366fcef01e 100644
> --- a/sysdeps/unix/sysv/linux/sysconf.c
> +++ b/sysdeps/unix/sysv/linux/sysconf.c
> @@ -16,6 +16,7 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> +#include <assert.h>
>  #include <errno.h>
>  #include <fcntl.h>
>  #include <stdlib.h>
> @@ -26,6 +27,7 @@
>  #include <sys/param.h>
>  #include <not-cancel.h>
>  #include <ldsodefs.h>
> +#include <sysconf-sigstksz.h>
>  
>  /* Legacy value of ARG_MAX.  The macro is now not defined since the
>     actual value varies based on the stack size.  */
> @@ -75,6 +77,13 @@ __sysconf (int name)
>        }
>        break;
>  
> +    case _SC_MINSIGSTKSZ:
> +      assert (GLRO(dl_minsigstacksize) != 0);
> +      return GLRO(dl_minsigstacksize);

OK.

> +
> +    case _SC_SIGSTKSZ:
> +      return sysconf_sigstksz ();

OK.

> +
>      default:
>        break;
>      }
> diff --git a/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h b/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h
> new file mode 100644
> index 0000000000..6088bbc99e
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h
> @@ -0,0 +1,83 @@
> +/* Emulate AT_MINSIGSTKSZ.  Linux/x86 version.
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +
> +   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/>.  */
> +
> +/* Emulate AT_MINSIGSTKSZ with XSAVE. */
> +
> +static inline void
> +dl_check_minsigstacksize (const struct cpu_features *cpu_features)
> +{
> +  /* Return if AT_MINSIGSTKSZ is provide by kernel.  */
> +  if (GLRO(dl_minsigstacksize) != 0)
> +    return;

OK. Cached.

> +
> +  if (cpu_features->basic.max_cpuid >= 0xd
> +      && CPU_FEATURES_CPU_P (cpu_features, OSXSAVE))
> +    {
> +      /* Emulate AT_MINSIGSTKSZ.  In Linux kernel, the signal frame data
> +	 with XSAVE is composed of the following areas and laid out as:
> +	 ------------------------------
> +	 | alignment padding          |
> +	 ------------------------------
> +	 | xsave buffer               |
> +	 ------------------------------
> +	 | fsave header (32-bit only) |
> +	 ------------------------------
> +	 | siginfo + ucontext         |
> +	 ------------------------------
> +	 */
> +
> +      unsigned int sigframe_size;
> +
> +#ifdef __x86_64__
> +      /* NB: sizeof(struct rt_sigframe) + 8-byte return address in Linux
> +	 kernel.  */
> +      sigframe_size = 440 + 8;
> +#else
> +      /* NB: sizeof(struct sigframe_ia32) + sizeof(struct fregs_state)) +
> +	 4-byte return address + 3 * 4-byte arguments in Linux kernel.  */
> +      sigframe_size = 736 + 112 + 4 + 3 * 4;
> +#endif
> +
> +      /* Add 15 bytes to align the stack to 16 bytes.  */
> +      sigframe_size += 15;
> +
> +      /* Make the space before xsave buffer multiple of 16 bytes.  */
> +      sigframe_size = ALIGN_UP (sigframe_size, 16);
> +
> +      /* Add (64 - 16)-byte padding to align xsave buffer at 64 bytes.  */
> +      sigframe_size += 64 - 16;
> +
> +      unsigned int eax, ebx, ecx, edx;
> +      __cpuid_count (0xd, 0, eax, ebx, ecx, edx);
> +
> +      /* Add the size of xsave buffer.  */
> +      sigframe_size += ebx;
> +
> +      /* Add the size of FP_XSTATE_MAGIC2.  */
> +#define FP_XSTATE_MAGIC2 0x46505845U
> +      sigframe_size += sizeof (FP_XSTATE_MAGIC2);
> +
> +      GLRO(dl_minsigstacksize) = sigframe_size;

OK.

> +    }
> +  else
> +    {
> +      /* NB: Default to a constant MINSIGSTKSZ.  */
> +      _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
> +		      "MINSIGSTKSZ is constant");
> +      GLRO(dl_minsigstacksize) = MINSIGSTKSZ;

OK.

> +    }
> +}
> diff --git a/sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h b/sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h
> new file mode 100644
> index 0000000000..208754c497
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h
> @@ -0,0 +1,5 @@
> +#include_next <bits/sigstack.h>
> +
> +#ifndef _ISOMAC
> +# define CONSTANT_MINSIGSTKSZ 0
> +#endif

OK.

> diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
> index 6496512a0d..dfeca31967 100644
> --- a/sysdeps/x86/cpu-features.c
> +++ b/sysdeps/x86/cpu-features.c
> @@ -21,6 +21,7 @@
>  #include <get-isa-level.h>
>  #include <cacheinfo.h>
>  #include <dl-cacheinfo.h>
> +#include <dl-minsigstacksize.h>
>  
>  #if HAVE_TUNABLES
>  extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *)
> @@ -362,6 +363,8 @@ get_common_indices (struct cpu_features *cpu_features,
>  		   cpu_features->features[CPUID_INDEX_19].cpuid.ebx,
>  		   cpu_features->features[CPUID_INDEX_19].cpuid.ecx,
>  		   cpu_features->features[CPUID_INDEX_19].cpuid.edx);
> +
> +  dl_check_minsigstacksize (cpu_features);

OK.

>  }
>  
>  _Static_assert (((index_arch_Fast_Unaligned_Load
> diff --git a/sysdeps/x86/dl-minsigstacksize.h b/sysdeps/x86/dl-minsigstacksize.h
> new file mode 100644
> index 0000000000..959871c970
> --- /dev/null
> +++ b/sysdeps/x86/dl-minsigstacksize.h
> @@ -0,0 +1,27 @@
> +/* Emulate AT_MINSIGSTKSZ.  Generic x86 version.
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +
> +   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/>.  */
> +
> +/* Emulate AT_MINSIGSTKSZ with XSAVE. */
> +
> +static inline void
> +dl_check_minsigstacksize (const struct cpu_features *cpu_features)
> +{
> +  /* NB: Default to a constant MINSIGSTKSZ.  */
> +  _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
> +		  "MINSIGSTKSZ is constant");
> +  GLRO(dl_minsigstacksize) = MINSIGSTKSZ;

OK.

> +}
> -- 
> 2.29.2
>
Carlos O'Donell Jan. 25, 2021, 1:59 p.m. UTC | #4
On 1/25/21 8:57 AM, H.J. Lu wrote:
> On Mon, Jan 25, 2021 at 5:32 AM Carlos O'Donell <carlos@redhat.com> wrote:
>>
>> On 1/22/21 2:41 PM, H.J. Lu wrote:
>>> Another rebase.
>>
>> Just a note here that v10 does not apply with patchwork automation.
>>
>> This makes things more difficult for my review and automated testing.
>>
>> If possible could you please just resent via git send-email on a new thread?
>>
>> e.g.
>>
>> git format-patch -v 10 ...
>> git send-email ...
>>
> 
> Done.
> 

Review of v10 is complete.

If in the future you keep using format-patch and send-email it should go
very smoothly. Particularly when we start adding try-bot to automatically
test patches against specification configurations.
Florian Weimer Jan. 25, 2021, 2:16 p.m. UTC | #5
* Carlos O'Donell via Libc-alpha:

> We document _SC_SIGSTKSZ_SOURCE as the way to request this change.

I have previously objected to _SC_SIGSTKSZ_SOURCE.  I still it's wrong.
We haven't done anything like that in a long time.  All other recent
features have been enabled by _GNU_SOURCE, even world-breaking ones,
like the math TS macros and functions.

Thanks,
Florian
Carlos O'Donell Jan. 25, 2021, 2:34 p.m. UTC | #6
On 1/25/21 8:58 AM, Carlos O'Donell wrote:
> On 1/22/21 2:41 PM, H.J. Lu wrote:
>> On Wed, Jan 20, 2021 at 7:05 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>>
>>> On Wed, Jan 20, 2021 at 6:16 AM Carlos O'Donell <carlos@redhat.com> wrote:
>>>>
>>>> On 11/20/20 6:13 PM, H.J. Lu via Libc-alpha wrote:
>>>>> On Fri, Nov 20, 2020 at 6:12 AM Florian Weimer <fw@deneb.enyo.de> wrote:
>>>>>>
>>>>>> * H. J. Lu:
>>>>>>
>>>>>>> Can we reach a consensus for _GNU_SOURCE vs _SC_SIGSTKSZ_SOURCE?
>>>>>>>
>>>>>>> How about we make _GNU_SOURCE to enable _SC_SIGSTKSZ_SOURCE and
>>>>>>> check _SC_SIGSTKSZ_SOURCE != 0?  If _GNU_SOURCE triggers compilation
>>>>>>> error and source codes can't be changed, we can add
>>>>>>> -D_SC_SIGSTKSZ_SOURCE=0 to disable _SC_SIGSTKSZ_SOURCE.
>>>>>>
>>>>>> I think the source code compatibility is much more obscure than the
>>>>>> other things we broke quite recently, even without deprecation.  Why
>>>>>> do we add the complexity in this case?  I feel it is disproportional.
>>>>>
>>>>> Here is the patch with _GNU_SOURCE.  Any comments?
>>>>
>>>> (1) New version of patch.
>>>>
>>>> This patch no longer compiles due to __cpuid_count errors.
>>>>
>>>> Could you please update this and post a v9?
>>>
>>> Fixed.
>>>
>>>> This is ABI addition for the constants so I want to make sure I review
>>>> something that works and is final from your end.
>>>>
>>>> (2) Kernel definition of constant for AT_MINSIGSTKSZ?
>>>>
>>>> We don't have a released kernel for x86 with this constant defined?
>>>>
>>>> The kernel patch was only just updated 5 days ago:
>>>> https://sourceware.org/pipermail/libc-alpha/2021-January/121671.html
>>>>
>>>> Doesn't this mean this patch is inappropriate for glibc 2.33?
>>>
>>> The new glibc works with the older kernels.  In many cases, we
>>> use emulation for the older kernels.  This patch only uses the
>>> existing kernel interface.   The kernel patch you referred doesn't
>>> add any new interface.  It simply uses the existing AT_MINSIGSTKSZ
>>> for x86.  My patch includes an emulation for the older kernels.   I
>>> think my patch is appropriate for glibc 2.33.
>>>
>>> Here is the updated patc.
>>>
>>> Thanks.
>>
>> Another rebase.
> 
> This change looks good to me.
> 
> We add two new constants _SC_MINSIGSTKSZ and _SC_SIGSTKSZ.
> 
> We document them as constants to sysconf().
> 
> We document _SC_SIGSTKSZ_SOURCE as the way to request this change.
> 
> We document this is part of _GNU_SOURCE.
> 
> This may break application builds and may need to be worked around if
> the application expected static allocation and need to switch to dynamic
> allocation of a constant at runtime. This kind of change may not always
> be easy to architect, but should be possible with an early constructor.
> 
> Tested on i686 and x86_64 and all pass.
> 
> Tested-by: Carlos O'Donell <carlos@redhat.com>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>

This was discussed on the weekly patch review meeting.

HJ and I agreed we would delay this until 2.34 opens.

Likewise the deprecation.

I will add a NEWS item that we are going to do this deprecation.
Carlos O'Donell Feb. 2, 2021, 1:08 p.m. UTC | #7
On 1/25/21 9:16 AM, Florian Weimer wrote:
> * Carlos O'Donell via Libc-alpha:
> 
>> We document _SC_SIGSTKSZ_SOURCE as the way to request this change.
> 
> I have previously objected to _SC_SIGSTKSZ_SOURCE.  I still it's wrong.
> We haven't done anything like that in a long time.  All other recent
> features have been enabled by _GNU_SOURCE, even world-breaking ones,
> like the math TS macros and functions.

I didn't see your objection during my review of the patch. Thank you
for stating it again.

I purposely moved this patch out of glibc 2.33 so we could have more
time to use this before the release.

Do you have a pointer to your original objection with notes about why
you object?
diff mbox series

Patch

From 9f040b4540feec52577b660cb151c79cdc2741a3 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Fri, 25 Sep 2020 13:10:08 -0700
Subject: [PATCH] sysconf: Add _SC_MINSIGSTKSZ/_SC_SIGSTKSZ [BZ #20305]

Add _SC_MINSIGSTKSZ for the minimum signal stack size derived from
AT_MINSIGSTKSZ, which is the minimum number of bytes of free stack
space required in order to gurantee successful, non-nested handling
of a single signal whose handler is an empty function, and _SC_SIGSTKSZ
which is the suggested minimum number of bytes of stack space required
for a signal stack.

If AT_MINSIGSTKSZ isn't available, sysconf (_SC_MINSIGSTKSZ) returns
MINSIGSTKSZ.  On Linux/x86 with XSAVE, the signal frame used by kernel
is composed of the following areas and laid out as:

 ------------------------------
 | alignment padding          |
 ------------------------------
 | xsave buffer               |
 ------------------------------
 | fsave header (32-bit only) |
 ------------------------------
 | siginfo + ucontext         |
 ------------------------------

Compute AT_MINSIGSTKSZ value as size of xsave buffer + size of fsave
header (32-bit only) + size of siginfo and ucontext + alignment padding.

If _SC_SIGSTKSZ_SOURCE or _GNU_SOURCE are defined, MINSIGSTKSZ and SIGSTKSZ
are redefined as

/* Default stack size for a signal handler: sysconf (SC_SIGSTKSZ).  */
 # undef SIGSTKSZ
 # define SIGSTKSZ sysconf (_SC_SIGSTKSZ)

/* Minimum stack size for a signal handler: SIGSTKSZ.  */
 # undef MINSIGSTKSZ
 # define MINSIGSTKSZ SIGSTKSZ

Compilation will fail if the source assumes constant MINSIGSTKSZ or
SIGSTKSZ.

The reason for not simply increasing the kernel's MINSIGSTKSZ #define
(apart from the fact that it is rarely used, due to glibc's shadowing
definitions) was that userspace binaries will have baked in the old
value of the constant and may be making assumptions about it.

For example, the type (char [MINSIGSTKSZ]) changes if this #define
changes.  This could be a problem if an newly built library tries to
memcpy() or dump such an object defined by and old binary.
Bounds-checking and the stack sizes passed to things like sigaltstack()
and makecontext() could similarly go wrong.
---
 NEWS                                          |  5 ++
 bits/confname.h                               |  8 +-
 bits/sigstksz.h                               | 21 +++++
 elf/dl-support.c                              |  5 ++
 elf/dl-sysdep.c                               |  9 ++
 include/bits/sigstack.h                       |  5 ++
 include/bits/sigstksz.h                       |  7 ++
 include/features.h                            | 11 +++
 manual/conf.texi                              | 21 +++++
 manual/creature.texi                          |  6 ++
 posix/sysconf.c                               |  3 +
 signal/Makefile                               |  5 +-
 signal/signal.h                               |  1 +
 signal/tst-minsigstksz-5.c                    | 84 +++++++++++++++++++
 sysdeps/generic/ldsodefs.h                    |  3 +
 sysdeps/unix/sysv/linux/bits/sigstksz.h       | 33 ++++++++
 .../unix/sysv/linux/ia64/sysconf-sigstksz.h   | 27 ++++++
 sysdeps/unix/sysv/linux/sysconf-sigstksz.h    | 38 +++++++++
 sysdeps/unix/sysv/linux/sysconf.c             |  9 ++
 .../unix/sysv/linux/x86/dl-minsigstacksize.h  | 83 ++++++++++++++++++
 .../sysv/linux/x86/include/bits/sigstack.h    |  5 ++
 sysdeps/x86/cpu-features.c                    |  3 +
 sysdeps/x86/dl-minsigstacksize.h              | 27 ++++++
 23 files changed, 416 insertions(+), 3 deletions(-)
 create mode 100644 bits/sigstksz.h
 create mode 100644 include/bits/sigstack.h
 create mode 100644 include/bits/sigstksz.h
 create mode 100644 signal/tst-minsigstksz-5.c
 create mode 100644 sysdeps/unix/sysv/linux/bits/sigstksz.h
 create mode 100644 sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h
 create mode 100644 sysdeps/unix/sysv/linux/sysconf-sigstksz.h
 create mode 100644 sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h
 create mode 100644 sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h
 create mode 100644 sysdeps/x86/dl-minsigstacksize.h

diff --git a/NEWS b/NEWS
index d121f7df87..0758bb37e3 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,11 @@  Version 2.33
 
 Major new features:
 
+* Add _SC_MINSIGSTKSZ and _SC_SIGSTKSZ.  When _SC_SIGSTKSZ_SOURCE or
+  _GNU_SOURCE are defined, MINSIGSTKSZ and SIGSTKSZ are no longer
+  constant on Linux.  MINSIGSTKSZ is redefined to sysconf(_SC_MINSIGSTKSZ)
+  and SIGSTKSZ is redefined to sysconf (_SC_SIGSTKSZ).
+
 * The dynamic linker accepts the --list-tunables argument which prints
   all the supported tunables.  This option is disable if glibc is
   configured with tunables disabled (--enable-tunables=no).
diff --git a/bits/confname.h b/bits/confname.h
index 8068bda273..ec6cd07957 100644
--- a/bits/confname.h
+++ b/bits/confname.h
@@ -525,8 +525,14 @@  enum
 
     _SC_THREAD_ROBUST_PRIO_INHERIT,
 #define _SC_THREAD_ROBUST_PRIO_INHERIT	_SC_THREAD_ROBUST_PRIO_INHERIT
-    _SC_THREAD_ROBUST_PRIO_PROTECT
+    _SC_THREAD_ROBUST_PRIO_PROTECT,
 #define _SC_THREAD_ROBUST_PRIO_PROTECT	_SC_THREAD_ROBUST_PRIO_PROTECT
+
+    _SC_MINSIGSTKSZ,
+#define	_SC_MINSIGSTKSZ			_SC_MINSIGSTKSZ
+
+    _SC_SIGSTKSZ
+#define	_SC_SIGSTKSZ			_SC_SIGSTKSZ
   };
 
 /* Values for the NAME argument to `confstr'.  */
diff --git a/bits/sigstksz.h b/bits/sigstksz.h
new file mode 100644
index 0000000000..5535d873b5
--- /dev/null
+++ b/bits/sigstksz.h
@@ -0,0 +1,21 @@ 
+/* Definition of MINSIGSTKSZ.  Generic version.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _SIGNAL_H
+# error "Never include <bits/sigstksz.h> directly; use <signal.h> instead."
+#endif
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 7abb65d8e3..7fc2ee78e2 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -142,6 +142,8 @@  void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
 
 size_t _dl_pagesize = EXEC_PAGESIZE;
 
+size_t _dl_minsigstacksize = CONSTANT_MINSIGSTKSZ;
+
 int _dl_inhibit_cache;
 
 unsigned int _dl_osversion;
@@ -307,6 +309,9 @@  _dl_aux_init (ElfW(auxv_t) *av)
       case AT_RANDOM:
 	_dl_random = (void *) av->a_un.a_val;
 	break;
+      case AT_MINSIGSTKSZ:
+	_dl_minsigstacksize = av->a_un.a_val;
+	break;
       DL_PLATFORM_AUXV
       }
   if (seen == 0xf)
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
index 0658c17da6..bd5066fe3b 100644
--- a/elf/dl-sysdep.c
+++ b/elf/dl-sysdep.c
@@ -115,6 +115,11 @@  _dl_sysdep_start (void **start_argptr,
   user_entry = (ElfW(Addr)) ENTRY_POINT;
   GLRO(dl_platform) = NULL; /* Default to nothing known about the platform.  */
 
+  /* NB: Default to a constant CONSTANT_MINSIGSTKSZ.  */
+  _Static_assert (__builtin_constant_p (CONSTANT_MINSIGSTKSZ),
+		  "CONSTANT_MINSIGSTKSZ is constant");
+  GLRO(dl_minsigstacksize) = CONSTANT_MINSIGSTKSZ;
+
   for (av = GLRO(dl_auxv); av->a_type != AT_NULL; set_seen (av++))
     switch (av->a_type)
       {
@@ -179,6 +184,9 @@  _dl_sysdep_start (void **start_argptr,
       case AT_RANDOM:
 	_dl_random = (void *) av->a_un.a_val;
 	break;
+      case AT_MINSIGSTKSZ:
+	GLRO(dl_minsigstacksize) = av->a_un.a_val;
+	break;
       DL_PLATFORM_AUXV
       }
 
@@ -306,6 +314,7 @@  _dl_show_auxv (void)
 	  [AT_SYSINFO_EHDR - 2] =	{ "SYSINFO_EHDR:      0x", hex },
 	  [AT_RANDOM - 2] =		{ "RANDOM:            0x", hex },
 	  [AT_HWCAP2 - 2] =		{ "HWCAP2:            0x", hex },
+	  [AT_MINSIGSTKSZ - 2] =	{ "MINSIGSTKSZ        ", dec },
 	  [AT_L1I_CACHESIZE - 2] =	{ "L1I_CACHESIZE:     ", dec },
 	  [AT_L1I_CACHEGEOMETRY - 2] =	{ "L1I_CACHEGEOMETRY: 0x", hex },
 	  [AT_L1D_CACHESIZE - 2] =	{ "L1D_CACHESIZE:     ", dec },
diff --git a/include/bits/sigstack.h b/include/bits/sigstack.h
new file mode 100644
index 0000000000..eea939f59d
--- /dev/null
+++ b/include/bits/sigstack.h
@@ -0,0 +1,5 @@ 
+#include_next <bits/sigstack.h>
+
+#if !defined _ISOMAC && !defined CONSTANT_MINSIGSTKSZ
+# define CONSTANT_MINSIGSTKSZ MINSIGSTKSZ
+#endif
diff --git a/include/bits/sigstksz.h b/include/bits/sigstksz.h
new file mode 100644
index 0000000000..2ca891e918
--- /dev/null
+++ b/include/bits/sigstksz.h
@@ -0,0 +1,7 @@ 
+/* NB: Don't define MINSIGSTKSZ nor SIGSTKSZ to sysconf (SC_SIGSTKSZ) for
+   glibc build.  IS_IN can only be used when _ISOMAC isn't defined.  */
+#ifdef _ISOMAC
+# include_next <bits/sigstksz.h>
+#elif IS_IN (libsupport)
+# include_next <bits/sigstksz.h>
+#endif
diff --git a/include/features.h b/include/features.h
index a71ac85af4..cc05a31ae1 100644
--- a/include/features.h
+++ b/include/features.h
@@ -48,6 +48,8 @@ 
    _LARGEFILE64_SOURCE	Additional functionality from LFS for large files.
    _FILE_OFFSET_BITS=N	Select default filesystem interface.
    _ATFILE_SOURCE	Additional *at interfaces.
+   _SC_SIGSTKSZ_SOURCE	Select correct (but non compile-time constant)
+			MINSIGSTKSZ and SIGSTKSZ.
    _GNU_SOURCE		All of the above, plus GNU extensions.
    _DEFAULT_SOURCE	The default set of features (taking precedence over
 			__STRICT_ANSI__).
@@ -94,6 +96,8 @@ 
    __USE_FILE_OFFSET64	Define 64bit interface as default.
    __USE_MISC		Define things from 4.3BSD or System V Unix.
    __USE_ATFILE		Define *at interfaces and AT_* constants for them.
+   __USE_SC_SIGSTKSZ	Define correct (but non compile-time constant)
+			MINSIGSTKSZ and SIGSTKSZ.
    __USE_GNU		Define GNU extensions.
    __USE_FORTIFY_LEVEL	Additional security measures used, according to level.
 
@@ -137,6 +141,7 @@ 
 #undef	__USE_FILE_OFFSET64
 #undef	__USE_MISC
 #undef	__USE_ATFILE
+#undef	__USE_SC_SIGSTKSZ
 #undef	__USE_GNU
 #undef	__USE_FORTIFY_LEVEL
 #undef	__KERNEL_STRICT_NAMES
@@ -213,6 +218,8 @@ 
 # define _DEFAULT_SOURCE	1
 # undef  _ATFILE_SOURCE
 # define _ATFILE_SOURCE	1
+# undef  _SC_SIGSTKSZ_SOURCE
+# define _SC_SIGSTKSZ_SOURCE 1
 #endif
 
 /* If nothing (other than _GNU_SOURCE and _DEFAULT_SOURCE) is defined,
@@ -388,6 +395,10 @@ 
 # define __USE_ATFILE	1
 #endif
 
+#ifdef	_SC_SIGSTKSZ_SOURCE
+# define __USE_SC_SIGSTKSZ	1
+#endif
+
 #ifdef	_GNU_SOURCE
 # define __USE_GNU	1
 #endif
diff --git a/manual/conf.texi b/manual/conf.texi
index f959b00bb6..ba9847aaa4 100644
--- a/manual/conf.texi
+++ b/manual/conf.texi
@@ -913,6 +913,27 @@  Inquire about the parameter corresponding to @code{NL_SETMAX}.
 @item _SC_NL_TEXTMAX
 @standards{X/Open, unistd.h}
 Inquire about the parameter corresponding to @code{NL_TEXTMAX}.
+
+@item _SC_MINSIGSTKSZ
+@standards{GNU, unistd.h}
+Inquire about the minimum number of bytes of free stack space required
+in order to guarantee successful, non-nested handling of a single signal
+whose handler is an empty function.
+
+@item _SC_SIGSTKSZ
+@standards{GNU, unistd.h}
+Inquire about the suggested minimum number of bytes of stack space
+required for a signal stack.
+
+This is not guaranteed to be enough for any specific purpose other than
+the invocation of a single, non-nested, empty handler, but nonetheless
+should be enough for basic scenarios involving simple signal handlers
+and very low levels of signal nesting (say, 2 or 3 levels at the very
+most).
+
+This value is provided for developer convenience and to ease migration
+from the legacy @code{SIGSTKSZ} constant.  Programs requiring stronger
+guarantees should avoid using it if at all possible.
 @end vtable
 
 @node Examples of Sysconf
diff --git a/manual/creature.texi b/manual/creature.texi
index 31208ccb2b..5090735e4f 100644
--- a/manual/creature.texi
+++ b/manual/creature.texi
@@ -258,6 +258,12 @@  checks are applied. If defined to @math{3}, @theglibc{} may also use
 checks that may have an additional performance overhead.
 @end defvr
 
+@defvr Macro _SC_SIGSTKSZ_SOURCE
+@standards{GNU, (none)}
+If this macro is defined, correct (but non compile-time constant)
+MINSIGSTKSZ and SIGSTKSZ are defined.
+@end defvr
+
 @defvr Macro _REENTRANT
 @defvrx Macro _THREAD_SAFE
 @standards{Obsolete, (none)}
diff --git a/posix/sysconf.c b/posix/sysconf.c
index bb9e132e5c..67d17ca0f8 100644
--- a/posix/sysconf.c
+++ b/posix/sysconf.c
@@ -266,6 +266,9 @@  __sysconf (int name)
     case _SC_XOPEN_REALTIME:
     case _SC_XOPEN_REALTIME_THREADS:
 
+    case _SC_MINSIGSTKSZ:
+    case _SC_SIGSTKSZ:
+
       break;
     }
 
diff --git a/signal/Makefile b/signal/Makefile
index e89c308889..3d8cab1f50 100644
--- a/signal/Makefile
+++ b/signal/Makefile
@@ -31,7 +31,8 @@  headers := signal.h sys/signal.h \
 	   bits/types/sigevent_t.h bits/types/siginfo_t.h \
 	   bits/types/sigset_t.h bits/types/sigval_t.h \
 	   bits/types/stack_t.h bits/types/struct_sigstack.h \
-	   bits/types/__sigval_t.h bits/signal_ext.h
+	   bits/types/__sigval_t.h bits/signal_ext.h \
+	   bits/sigstksz.h
 
 routines	:= signal raise killpg \
 		   sigaction sigprocmask kill \
@@ -48,7 +49,7 @@  routines	:= signal raise killpg \
 tests		:= tst-signal tst-sigset tst-sigsimple tst-raise tst-sigset2 \
 		   tst-sigwait-eintr tst-sigaction \
 		   tst-minsigstksz-1 tst-minsigstksz-2 tst-minsigstksz-3 \
-		   tst-minsigstksz-3a tst-minsigstksz-4 \
+		   tst-minsigstksz-3a tst-minsigstksz-4 tst-minsigstksz-5 \
 		   tst-sigisemptyset
 
 include ../Rules
diff --git a/signal/signal.h b/signal/signal.h
index 6463c98e11..b17203c99c 100644
--- a/signal/signal.h
+++ b/signal/signal.h
@@ -312,6 +312,7 @@  extern int siginterrupt (int __sig, int __interrupt) __THROW
   __attribute_deprecated_msg__ ("Use sigaction with SA_RESTART instead");
 
 # include <bits/sigstack.h>
+# include <bits/sigstksz.h>
 # include <bits/ss_flags.h>
 
 /* Alternate signal handler stack interface.
diff --git a/signal/tst-minsigstksz-5.c b/signal/tst-minsigstksz-5.c
new file mode 100644
index 0000000000..d657d2f4e6
--- /dev/null
+++ b/signal/tst-minsigstksz-5.c
@@ -0,0 +1,84 @@ 
+/* Test of signal delivery on an alternate stack with MINSIGSTKSZ size.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <support/check.h>
+#include <support/support.h>
+
+static volatile sig_atomic_t handler_run;
+
+static void
+handler (int signo)
+{
+  /* Clear a bit of on-stack memory.  */
+  volatile char buffer[256];
+  for (size_t i = 0; i < sizeof (buffer); ++i)
+    buffer[i] = 0;
+  handler_run = 1;
+}
+
+int
+do_test (void)
+{
+  size_t stack_buffer_size = 64 * 1024 * 1024;
+  void *stack_buffer = xmalloc (stack_buffer_size);
+  void *stack_end = stack_buffer + stack_buffer_size;
+  memset (stack_buffer, 0xCC, stack_buffer_size);
+
+  void *stack_bottom = stack_buffer + (stack_buffer_size + MINSIGSTKSZ) / 2;
+  void *stack_top = stack_bottom + MINSIGSTKSZ;
+  stack_t stack =
+    {
+      .ss_sp = stack_bottom,
+      .ss_size = MINSIGSTKSZ,
+    };
+  if (sigaltstack (&stack, NULL) < 0)
+    FAIL_RET ("sigaltstack: %m\n");
+
+  struct sigaction act =
+    {
+      .sa_handler = handler,
+      .sa_flags = SA_ONSTACK,
+    };
+  if (sigaction (SIGUSR1, &act, NULL) < 0)
+    FAIL_RET ("sigaction: %m\n");
+
+  if (kill (getpid (), SIGUSR1) < 0)
+    FAIL_RET ("kill: %m\n");
+
+  if (handler_run != 1)
+    FAIL_RET ("handler did not run\n");
+
+  for (void *p = stack_buffer; p < stack_bottom; ++p)
+    if (*(unsigned char *) p != 0xCC)
+      FAIL_RET ("changed byte %ld bytes below configured stack\n",
+		(long) (stack_bottom - p));
+  for (void *p = stack_top; p < stack_end; ++p)
+    if (*(unsigned char *) p != 0xCC)
+      FAIL_RET ("changed byte %ld bytes above configured stack\n",
+		(long) (p - stack_top));
+
+  free (stack_buffer);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index aab7245e93..9720a4e446 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -536,6 +536,9 @@  struct rtld_global_ro
   /* Cached value of `getpagesize ()'.  */
   EXTERN size_t _dl_pagesize;
 
+  /* Cached value of `sysconf (_SC_MINSIGSTKSZ)'.  */
+  EXTERN size_t _dl_minsigstacksize;
+
   /* Do we read from ld.so.cache?  */
   EXTERN int _dl_inhibit_cache;
 
diff --git a/sysdeps/unix/sysv/linux/bits/sigstksz.h b/sysdeps/unix/sysv/linux/bits/sigstksz.h
new file mode 100644
index 0000000000..926508f2b4
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/sigstksz.h
@@ -0,0 +1,33 @@ 
+/* Definition of MINSIGSTKSZ and SIGSTKSZ.  Linux version.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _SIGNAL_H
+# error "Never include <bits/sigstksz.h> directly; use <signal.h> instead."
+#endif
+
+#if defined __USE_SC_SIGSTKSZ && __USE_SC_SIGSTKSZ
+# include <unistd.h>
+
+/* Default stack size for a signal handler: sysconf (SC_SIGSTKSZ).  */
+# undef SIGSTKSZ
+# define SIGSTKSZ sysconf (_SC_SIGSTKSZ)
+
+/* Minimum stack size for a signal handler: SIGSTKSZ.  */
+# undef MINSIGSTKSZ
+# define MINSIGSTKSZ SIGSTKSZ
+#endif
diff --git a/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h b/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h
new file mode 100644
index 0000000000..7e5ceba151
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h
@@ -0,0 +1,27 @@ 
+/* sysconf_sigstksz ().  Linux/ia64 version.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* Return sysconf (_SC_SIGSTKSZ).  */
+
+static long int
+sysconf_sigstksz (void)
+{
+  _Static_assert (__builtin_constant_p (SIGSTKSZ),
+		  "SIGSTKSZ is constant");
+  return SIGSTKSZ;
+}
diff --git a/sysdeps/unix/sysv/linux/sysconf-sigstksz.h b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h
new file mode 100644
index 0000000000..64d450b22c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h
@@ -0,0 +1,38 @@ 
+/* sysconf_sigstksz ().  Linux version.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* Return sysconf (_SC_SIGSTKSZ).  */
+
+static long int
+sysconf_sigstksz (void)
+{
+  long int minsigstacksize = GLRO(dl_minsigstacksize);
+  assert (minsigstacksize != 0);
+  _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
+		  "MINSIGSTKSZ is constant");
+  if (minsigstacksize < MINSIGSTKSZ)
+    minsigstacksize = MINSIGSTKSZ;
+  /* MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4.  */
+  long int sigstacksize = minsigstacksize * 4;
+  /* Return MAX (SIGSTKSZ, sigstacksize).  */
+  _Static_assert (__builtin_constant_p (SIGSTKSZ),
+		  "SIGSTKSZ is constant");
+  if (sigstacksize < SIGSTKSZ)
+    sigstacksize = SIGSTKSZ;
+  return sigstacksize;
+}
diff --git a/sysdeps/unix/sysv/linux/sysconf.c b/sysdeps/unix/sysv/linux/sysconf.c
index bfad5b6858..366fcef01e 100644
--- a/sysdeps/unix/sysv/linux/sysconf.c
+++ b/sysdeps/unix/sysv/linux/sysconf.c
@@ -16,6 +16,7 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
@@ -26,6 +27,7 @@ 
 #include <sys/param.h>
 #include <not-cancel.h>
 #include <ldsodefs.h>
+#include <sysconf-sigstksz.h>
 
 /* Legacy value of ARG_MAX.  The macro is now not defined since the
    actual value varies based on the stack size.  */
@@ -75,6 +77,13 @@  __sysconf (int name)
       }
       break;
 
+    case _SC_MINSIGSTKSZ:
+      assert (GLRO(dl_minsigstacksize) != 0);
+      return GLRO(dl_minsigstacksize);
+
+    case _SC_SIGSTKSZ:
+      return sysconf_sigstksz ();
+
     default:
       break;
     }
diff --git a/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h b/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h
new file mode 100644
index 0000000000..6088bbc99e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h
@@ -0,0 +1,83 @@ 
+/* Emulate AT_MINSIGSTKSZ.  Linux/x86 version.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   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/>.  */
+
+/* Emulate AT_MINSIGSTKSZ with XSAVE. */
+
+static inline void
+dl_check_minsigstacksize (const struct cpu_features *cpu_features)
+{
+  /* Return if AT_MINSIGSTKSZ is provide by kernel.  */
+  if (GLRO(dl_minsigstacksize) != 0)
+    return;
+
+  if (cpu_features->basic.max_cpuid >= 0xd
+      && CPU_FEATURES_CPU_P (cpu_features, OSXSAVE))
+    {
+      /* Emulate AT_MINSIGSTKSZ.  In Linux kernel, the signal frame data
+	 with XSAVE is composed of the following areas and laid out as:
+	 ------------------------------
+	 | alignment padding          |
+	 ------------------------------
+	 | xsave buffer               |
+	 ------------------------------
+	 | fsave header (32-bit only) |
+	 ------------------------------
+	 | siginfo + ucontext         |
+	 ------------------------------
+	 */
+
+      unsigned int sigframe_size;
+
+#ifdef __x86_64__
+      /* NB: sizeof(struct rt_sigframe) + 8-byte return address in Linux
+	 kernel.  */
+      sigframe_size = 440 + 8;
+#else
+      /* NB: sizeof(struct sigframe_ia32) + sizeof(struct fregs_state)) +
+	 4-byte return address + 3 * 4-byte arguments in Linux kernel.  */
+      sigframe_size = 736 + 112 + 4 + 3 * 4;
+#endif
+
+      /* Add 15 bytes to align the stack to 16 bytes.  */
+      sigframe_size += 15;
+
+      /* Make the space before xsave buffer multiple of 16 bytes.  */
+      sigframe_size = ALIGN_UP (sigframe_size, 16);
+
+      /* Add (64 - 16)-byte padding to align xsave buffer at 64 bytes.  */
+      sigframe_size += 64 - 16;
+
+      unsigned int eax, ebx, ecx, edx;
+      __cpuid_count (0xd, 0, eax, ebx, ecx, edx);
+
+      /* Add the size of xsave buffer.  */
+      sigframe_size += ebx;
+
+      /* Add the size of FP_XSTATE_MAGIC2.  */
+#define FP_XSTATE_MAGIC2 0x46505845U
+      sigframe_size += sizeof (FP_XSTATE_MAGIC2);
+
+      GLRO(dl_minsigstacksize) = sigframe_size;
+    }
+  else
+    {
+      /* NB: Default to a constant MINSIGSTKSZ.  */
+      _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
+		      "MINSIGSTKSZ is constant");
+      GLRO(dl_minsigstacksize) = MINSIGSTKSZ;
+    }
+}
diff --git a/sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h b/sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h
new file mode 100644
index 0000000000..208754c497
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h
@@ -0,0 +1,5 @@ 
+#include_next <bits/sigstack.h>
+
+#ifndef _ISOMAC
+# define CONSTANT_MINSIGSTKSZ 0
+#endif
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
index 6496512a0d..dfeca31967 100644
--- a/sysdeps/x86/cpu-features.c
+++ b/sysdeps/x86/cpu-features.c
@@ -21,6 +21,7 @@ 
 #include <get-isa-level.h>
 #include <cacheinfo.h>
 #include <dl-cacheinfo.h>
+#include <dl-minsigstacksize.h>
 
 #if HAVE_TUNABLES
 extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *)
@@ -362,6 +363,8 @@  get_common_indices (struct cpu_features *cpu_features,
 		   cpu_features->features[CPUID_INDEX_19].cpuid.ebx,
 		   cpu_features->features[CPUID_INDEX_19].cpuid.ecx,
 		   cpu_features->features[CPUID_INDEX_19].cpuid.edx);
+
+  dl_check_minsigstacksize (cpu_features);
 }
 
 _Static_assert (((index_arch_Fast_Unaligned_Load
diff --git a/sysdeps/x86/dl-minsigstacksize.h b/sysdeps/x86/dl-minsigstacksize.h
new file mode 100644
index 0000000000..959871c970
--- /dev/null
+++ b/sysdeps/x86/dl-minsigstacksize.h
@@ -0,0 +1,27 @@ 
+/* Emulate AT_MINSIGSTKSZ.  Generic x86 version.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   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/>.  */
+
+/* Emulate AT_MINSIGSTKSZ with XSAVE. */
+
+static inline void
+dl_check_minsigstacksize (const struct cpu_features *cpu_features)
+{
+  /* NB: Default to a constant MINSIGSTKSZ.  */
+  _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
+		  "MINSIGSTKSZ is constant");
+  GLRO(dl_minsigstacksize) = MINSIGSTKSZ;
+}
-- 
2.29.2