V10 [PATCH] sysconf: Add _SC_MINSIGSTKSZ/_SC_SIGSTKSZ [BZ #20305]
Carlos O'Donell
carlos@redhat.com
Mon Jan 25 13:58:10 GMT 2021
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
>
--
Cheers,
Carlos.
More information about the Libc-alpha
mailing list