|
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.