|
|
Message-ID: <20201012075332.GB3819@arm.com>
Date: Mon, 12 Oct 2020 08:53:32 +0100
From: Szabolcs Nagy <szabolcs.nagy@....com>
To: "H.J. Lu" <hjl.tools@...il.com>
Cc: libc-alpha@...rceware.org, libc-coord@...ts.openwall.com
Subject: Re: [PATCH] sysconf: Add _SC_MINSIGSTKSZ/_SC_SIGSTKSZ [BZ #20305]
The 10/10/2020 05:19, H.J. Lu via Libc-alpha wrote:
> 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 is 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.
this looks reasonable to me.
i added libc-coord on cc as it seems to be
a useful generic api across targets.
/* Return MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4. */
this can be excessive for sigstksz,
but reasonable on glibc given the
overhead of libc internal signals
and lazy binding.
does this decrease the size on any
existing target?
> ---
> NEWS | 5 ++
> bits/confname.h | 8 +-
> bits/sigstksz.h | 21 +++++
> conform/data/unistd.h-data | 2 +
> elf/dl-support.c | 5 ++
> elf/dl-sysdep.c | 9 ++
> include/features.h | 8 ++
> manual/conf.texi | 21 +++++
> posix/sysconf.c | 3 +
> signal/Makefile | 5 +-
> signal/signal.h | 1 +
> signal/tst-minsigstksz-5.c | 84 +++++++++++++++++++
> support/Makefile | 3 +
> sysdeps/generic/ldsodefs.h | 3 +
> sysdeps/unix/sysv/linux/Makefile | 8 ++
> sysdeps/unix/sysv/linux/bits/sigstksz.h | 33 ++++++++
> sysdeps/unix/sysv/linux/sysconf.c | 16 ++++
> .../unix/sysv/linux/x86/dl-minsigstacksize.h | 77 +++++++++++++++++
> sysdeps/x86/cpu-features.c | 16 ++--
> sysdeps/x86/dl-minsigstacksize.h | 23 +++++
> 20 files changed, 343 insertions(+), 8 deletions(-)
> create mode 100644 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/x86/dl-minsigstacksize.h
> create mode 100644 sysdeps/x86/dl-minsigstacksize.h
>
> diff --git a/NEWS b/NEWS
> index e84c39aeb1..a7995f8c6a 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 is
> + 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 --argv0 argument and provides opportunity
> to change argv[0] string.
>
> diff --git a/bits/confname.h b/bits/confname.h
> index 5dc8215093..451d3eb636 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/conform/data/unistd.h-data b/conform/data/unistd.h-data
> index aa070528e8..70ab521a29 100644
> --- a/conform/data/unistd.h-data
> +++ b/conform/data/unistd.h-data
> @@ -242,6 +242,7 @@ constant _SC_MEMLOCK_RANGE
> constant _SC_MEMORY_PROTECTION
> constant _SC_MESSAGE_PASSING
> #ifndef POSIX
> +constant _SC_MINSIGSTKSZ
> constant _SC_MONOTONIC_CLOCK
> #endif
> constant _SC_MQ_OPEN_MAX
> @@ -279,6 +280,7 @@ constant _SC_SIGNALS
> #endif
> constant _SC_SIGQUEUE_MAX
> #ifndef POSIX
> +constant _SC_SIGSTKSZ
> constant _SC_SINGLE_PROCESS
> constant _SC_SPIN_LOCKS
> #endif
> diff --git a/elf/dl-support.c b/elf/dl-support.c
> index afbc94df54..18ac0bdd44 100644
> --- a/elf/dl-support.c
> +++ b/elf/dl-support.c
> @@ -136,6 +136,8 @@ void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
>
> size_t _dl_pagesize = EXEC_PAGESIZE;
>
> +size_t _dl_minsigstacksize = MINSIGSTKSZ;
> +
> int _dl_inhibit_cache;
>
> unsigned int _dl_osversion;
> @@ -294,6 +296,9 @@ _dl_aux_init (ElfW(auxv_t) *av)
> 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
> }
> if (seen == 0xf)
> diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
> index 854570821c..2b1bce8cf5 100644
> --- a/elf/dl-sysdep.c
> +++ b/elf/dl-sysdep.c
> @@ -117,6 +117,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 MINSIGSTKSZ. */
> + _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
> + "MINSIGSTKSZ is constant");
> + GLRO(dl_minsigstacksize) = MINSIGSTKSZ;
> +
> for (av = GLRO(dl_auxv); av->a_type != AT_NULL; set_seen (av++))
> switch (av->a_type)
> {
> @@ -181,6 +186,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
> }
>
> @@ -308,6 +316,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/features.h b/include/features.h
> index f3e62d3362..fa5a94455a 100644
> --- a/include/features.h
> +++ b/include/features.h
> @@ -55,6 +55,8 @@
> _FORTIFY_SOURCE Add security hardening to many library functions.
> Set to 1 or 2; 2 performs stricter checks than 1.
>
> + _SC_SIGSTKSZ_SOURCE Select non-constant MINSIGSTKSZ and SIGSTKSZ.
> +
> _REENTRANT, _THREAD_SAFE
> Obsolete; equivalent to _POSIX_C_SOURCE=199506L.
>
> @@ -96,6 +98,7 @@
> __USE_ATFILE Define *at interfaces and AT_* constants for them.
> __USE_GNU Define GNU extensions.
> __USE_FORTIFY_LEVEL Additional security measures used, according to level.
> + __USE_SC_SIGSTKSZ Define non-constant MINSIGSTKSZ and SIGSTKSZ.
>
> The macros `__GNU_LIBRARY__', `__GLIBC__', and `__GLIBC_MINOR__' are
> defined by this file unconditionally. `__GNU_LIBRARY__' is provided
> @@ -139,6 +142,7 @@
> #undef __USE_ATFILE
> #undef __USE_GNU
> #undef __USE_FORTIFY_LEVEL
> +#undef __USE_SC_SIGSTKSZ
> #undef __KERNEL_STRICT_NAMES
> #undef __GLIBC_USE_ISOC2X
> #undef __GLIBC_USE_DEPRECATED_GETS
> @@ -407,6 +411,10 @@
> # define __USE_FORTIFY_LEVEL 0
> #endif
>
> +#ifdef _SC_SIGSTKSZ_SOURCE
> +# define __USE_SC_SIGSTKSZ 1
> +#endif
> +
> /* The function 'gets' existed in C89, but is impossible to use
> safely. It has been removed from ISO C11 and ISO C++14. Note: for
> compatibility with various implementations of <cstdio>, this test
> 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}.
> +
> +@...m _SC_MINSIGSTKSZ
> +@...ndards{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.
> +
> +@...m _SC_SIGSTKSZ
> +@...ndards{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/posix/sysconf.c b/posix/sysconf.c
> index ba303384c1..ca7833e6c4 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 2ec3ddd74f..641d30582d 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 effe3d698f..0311eb2a66 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..8be380227c
> --- /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 %zd bytes below configured stack\n",
> + stack_bottom - p);
> + for (void *p = stack_top; p < stack_end; ++p)
> + if (*(unsigned char *) p != 0xCC)
> + FAIL_RET ("changed byte %zd bytes above configured stack\n",
> + p - stack_top);
> +
> + free (stack_buffer);
> +
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
> diff --git a/support/Makefile b/support/Makefile
> index 93faafddf9..ae889d8627 100644
> --- a/support/Makefile
> +++ b/support/Makefile
> @@ -203,6 +203,9 @@ CFLAGS-support_paths.c = \
> # -fexcess-precision=standard.
> CFLAGS-timespec.c += -fexcess-precision=standard
>
> +# Get the real <bits/sigstksz.h>.
> +CFLAGS-xsigstack.c += -D_ISOMAC
> +
> ifeq (,$(CXX))
> LINKS_DSO_PROGRAM = links-dso-program-c
> else
> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index 382eeb9be0..5ce847aeac 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -528,6 +528,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/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index d760debf40..a17ca28de8 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -190,6 +190,9 @@ sysdep_routines += ntp_gettime ntp_gettimex
> endif
>
> ifeq ($(subdir),signal)
> +# Compile tst-minsigstksz-5.c with _SC_SIGSTKSZ_SOURCE.
> +CFLAGS-tst-minsigstksz-5.c += -D_SC_SIGSTKSZ_SOURCE
> +
> tests-special += $(objpfx)tst-signal-numbers.out
> # Depending on signal.o* is a hack. What we actually want is a dependency
> # on signal.h and everything it includes. That's impractical to write
> @@ -228,6 +231,11 @@ ifeq ($(subdir),sunrpc)
> sysdep_headers += nfs/nfs.h
> endif
>
> +ifeq ($(subdir),support)
> +# Compile xsigstack.c with _SC_SIGSTKSZ_SOURCE.
> +CFLAGS-xsigstack.c += -D_SC_SIGSTKSZ_SOURCE
> +endif
> +
> ifeq ($(subdir),termios)
> sysdep_headers += termio.h
> endif
> diff --git a/sysdeps/unix/sysv/linux/bits/sigstksz.h b/sysdeps/unix/sysv/linux/bits/sigstksz.h
> new file mode 100644
> index 0000000000..8e91bfad64
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/sigstksz.h
> @@ -0,0 +1,33 @@
> +/* Definition of MINSIGSTKSZ. 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
> +
> +#ifdef __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/sysconf.c b/sysdeps/unix/sysv/linux/sysconf.c
> index 7958a74164..0abc8d80bb 100644
> --- a/sysdeps/unix/sysv/linux/sysconf.c
> +++ b/sysdeps/unix/sysv/linux/sysconf.c
> @@ -75,6 +75,22 @@ __sysconf (int name)
> }
> break;
>
> + case _SC_MINSIGSTKSZ:
> + assert (GLRO(dl_minsigstacksize) != 0);
> + return GLRO(dl_minsigstacksize);
> +
> + case _SC_SIGSTKSZ:
> + {
> + /* Return MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4. */
> + long int minsigstacksize = GLRO(dl_minsigstacksize);
> + assert (minsigstacksize != 0);
> + _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
> + "MINSIGSTKSZ is constant");
> + if (minsigstacksize < MINSIGSTKSZ)
> + minsigstacksize = MINSIGSTKSZ;
> + return minsigstacksize * 4;
> + }
> +
> 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..d2dc436572
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h
> @@ -0,0 +1,77 @@
> +/* 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/>. */
> +
> +#include <unistd.h>
> +
> +/* Emulate AT_MINSIGSTKSZ with XSAVE. */
> +
> +static inline void
> +dl_check_minsigstacksize (void)
> +{
> + /* NB: Default to a constant MINSIGSTKSZ. */
> + _Static_assert (__builtin_constant_p (MINSIGSTKSZ),
> + "MINSIGSTKSZ is constant");
> + /* Return if AT_MINSIGSTKSZ is provide by kernel. */
> + if (GLRO(dl_minsigstacksize) != MINSIGSTKSZ)
> + return;
> +
> + /* 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;
> +}
> diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
> index 286ff96771..c80ab05cbd 100644
> --- a/sysdeps/x86/cpu-features.c
> +++ b/sysdeps/x86/cpu-features.c
> @@ -20,6 +20,7 @@
> #include <cpu-features.h>
> #include <dl-hwcap.h>
> #include <libc-pointer-arith.h>
> +#include <dl-minsigstacksize.h>
>
> #if HAVE_TUNABLES
> # define TUNABLE_NAMESPACE cpu
> @@ -350,11 +351,16 @@ get_common_indices (struct cpu_features *cpu_features,
> }
>
> if (cpu_features->basic.max_cpuid >= 0xd)
> - __cpuid_count (0xd, 1,
> - cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.eax,
> - cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.ebx,
> - cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.ecx,
> - cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.edx);
> + {
> + /* NB: OSXSAVE has been set in COMMON_CPUID_INDEX_1 above. */
> + if (CPU_FEATURES_CPU_P (cpu_features, OSXSAVE))
> + dl_check_minsigstacksize ();
> + __cpuid_count (0xd, 1,
> + cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.eax,
> + cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.ebx,
> + cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.ecx,
> + cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.edx);
> + }
>
> if (cpu_features->basic.max_cpuid >= 0x19)
> __cpuid_count (0x19, 0,
> diff --git a/sysdeps/x86/dl-minsigstacksize.h b/sysdeps/x86/dl-minsigstacksize.h
> new file mode 100644
> index 0000000000..da2e40ffd4
> --- /dev/null
> +++ b/sysdeps/x86/dl-minsigstacksize.h
> @@ -0,0 +1,23 @@
> +/* 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 (void)
> +{
> +}
> --
> 2.26.2
>
--
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.