diff options
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | bits/confname.h | 8 | ||||
-rw-r--r-- | bits/sigstksz.h | 21 | ||||
-rw-r--r-- | elf/dl-support.c | 5 | ||||
-rw-r--r-- | elf/dl-sysdep.c | 9 | ||||
-rw-r--r-- | include/bits/sigstack.h | 5 | ||||
-rw-r--r-- | include/bits/sigstksz.h | 7 | ||||
-rw-r--r-- | include/features.h | 11 | ||||
-rw-r--r-- | manual/conf.texi | 21 | ||||
-rw-r--r-- | manual/creature.texi | 6 | ||||
-rw-r--r-- | posix/sysconf.c | 3 | ||||
-rw-r--r-- | signal/Makefile | 5 | ||||
-rw-r--r-- | signal/signal.h | 1 | ||||
-rw-r--r-- | signal/tst-minsigstksz-5.c | 84 | ||||
-rw-r--r-- | sysdeps/generic/ldsodefs.h | 3 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/bits/sigstksz.h | 33 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h | 27 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/sysconf-sigstksz.h | 38 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/sysconf.c | 9 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h | 83 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/x86/include/bits/sigstack.h | 5 | ||||
-rw-r--r-- | sysdeps/x86/cpu-features.c | 3 | ||||
-rw-r--r-- | sysdeps/x86/dl-minsigstacksize.h | 27 |
23 files changed, 416 insertions, 3 deletions
@@ -33,6 +33,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 8068bda..ec6cd07 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 0000000..5535d87 --- /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 7abb65d..7fc2ee7 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 0658c17..bd5066f 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 0000000..eea939f --- /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 0000000..2ca891e --- /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 c6ff971..eb97470 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 f959b00..ba9847a 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 31208cc..5090735 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 bb9e132..67d17ca 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 e89c308..3d8cab1 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 6463c98..b17203c 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 0000000..d657d2f --- /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 aab7245..9720a4e 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 0000000..926508f --- /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 0000000..7e5ceba --- /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 0000000..64d450b --- /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 bfad5b6..366fcef 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 0000000..6088bbc --- /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 0000000..208754c --- /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 73b0a4d..7996ed0 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 *) @@ -364,6 +365,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 0000000..959871c --- /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; +} |