Message ID | 20201015115728.GA64160@gmail.com |
---|---|
State | New |
Headers | show |
Series | V6 [PATCH] sysconf: Add _SC_MINSIGSTKSZ/_SC_SIGSTKSZ [BZ #20305] | expand |
On Thu, Oct 15, 2020 at 04:57:28AM -0700, H.J. Lu via Libc-alpha wrote: > On Wed, Oct 14, 2020 at 06:47:01PM +0100, Dave Martin wrote: > > > [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..38b528e027 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. > > > + > > > > Maybe "correct (but non compiletime constant)" > > > > Fixed. > > > > diff --git a/sysdeps/unix/sysv/linux/bits/sigstksz.h b/sysdeps/unix/sysv/linux/bits/sigstksz.h > > > new file mode 100644 > > > index 0000000000..cd5b3cc895 > > > --- /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 __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 > > > > To help raise awareness, is it worth adding deprecation warnings on > > these? > > > > Could we still consider them deprecated even with _SC_SIGSTKSZ_SOURCE? > > Ideally they should be (or even removed), since even if these values are > > "correct", using them is still a potential portability problem when > > building for other library stacks. > > > > I think the rule ought to be to use these only if _SC_SIGSTKSZ / > > _SC_MINSIGSTKSZ aren't available, and with the caveat that the values > > may be wrong -- similar to the situation with PAGESIZE. > > > > > > It could be worth making this feature test macro more general and > > harvesting any other broken legacy macros we're aware of (such as > > PAGESIZE, but there are probably others). Probably out of scope for > > this patch, though. > > I will investigate to deprecate MINSIGSTKSZ and SIGSTKSZ after my patch > has been merged into master branch. > > > > diff --git a/sysdeps/unix/sysv/linux/sysconf-sigstksz.h b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h > > > new file mode 100644 > > > index 0000000000..64d450b22c > > > --- /dev/null > > > +++ b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h > > > @@ -0,0 +1,38 @@ > > > +/* sysconf_sigstksz (). Linux version. > > > + Copyright (C) 2020 Free Software Foundation, Inc. > > > + This file is part of the GNU C Library. > > > + > > > + The GNU C Library is free software; you can redistribute it and/or > > > + modify it under the terms of the GNU Lesser General Public > > > + License as published by the Free Software Foundation; either > > > + version 2.1 of the License, or (at your option) any later version. > > > + > > > + The GNU C Library is distributed in the hope that it will be useful, > > > + but WITHOUT ANY WARRANTY; without even the implied warranty of > > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > > + Lesser General Public License for more details. > > > + > > > + You should have received a copy of the GNU Lesser General Public > > > + License along with the GNU C Library; if not, see > > > + <https://www.gnu.org/licenses/>. */ > > > + > > > +/* Return sysconf (_SC_SIGSTKSZ). */ > > > + > > > +static long int > > > +sysconf_sigstksz (void) > > > +{ > > > + long int minsigstacksize = GLRO(dl_minsigstacksize); > > > + assert (minsigstacksize != 0); > > > + _Static_assert (__builtin_constant_p (MINSIGSTKSZ), > > > + "MINSIGSTKSZ is constant"); > > > + if (minsigstacksize < MINSIGSTKSZ) > > > + minsigstacksize = MINSIGSTKSZ; > > > + /* MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4. */ > > > + long int sigstacksize = minsigstacksize * 4; > > > + /* Return MAX (SIGSTKSZ, sigstacksize). */ > > > + _Static_assert (__builtin_constant_p (SIGSTKSZ), > > > + "SIGSTKSZ is constant"); > > > + if (sigstacksize < SIGSTKSZ) > > > + sigstacksize = SIGSTKSZ; > > > + return sigstacksize; > > > +} > > > diff --git a/sysdeps/unix/sysv/linux/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; > > > > Couldn't the kernel actually yield MINSIGSTKSZ or a smaller value, say, > > if running on hardware that doesn't have AVX-512? > > > It is OK for MINSIGSTKSZ > AT_MINSIGSTKSZ. For _SC_SIGSTKSZ_SOURCE, > dynamic MINSIGSTKSZ is defined as sysconf (_SC_SIGSTKSZ) which is > > MAX (SIGSTKSZ, MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4) > > and dynamic MINSIGSTKSZ is always > MINSIGSTKSZ. > > > We might want a separate flag to indicate whether we obtained a value > > from the auxv, rather relying on MINSIGSTKSZ having this magic meaning. > > AT_MINSIGSTKSZ is the only way for GLRO(dl_minsigstacksize) != MINSIGSTKSZ. Yes, but reading AT_MINSIGSTKSZ doesn't guarantee that GLRO(dl_minsigstkszsize) != MINSIGSTKSZ, no? What if the value reported for AT_MINSIGSTKSZ is actually the same as MINSIGSTKSZ? This could be the case on some arches in future even if it's never true today. But the code here assumes that AT_MINSIGSTKSZ wasn't available in this case, and reverts to a fallback guess. [...] Cheers ---Dave
On Mon, Oct 19, 2020 at 8:08 AM Dave Martin <Dave.Martin@arm.com> wrote: > > On Thu, Oct 15, 2020 at 04:57:28AM -0700, H.J. Lu via Libc-alpha wrote: > > On Wed, Oct 14, 2020 at 06:47:01PM +0100, Dave Martin wrote: > > > > [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..38b528e027 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. > > > > + > > > > > > Maybe "correct (but non compiletime constant)" > > > > > > > Fixed. > > > > > > diff --git a/sysdeps/unix/sysv/linux/bits/sigstksz.h b/sysdeps/unix/sysv/linux/bits/sigstksz.h > > > > new file mode 100644 > > > > index 0000000000..cd5b3cc895 > > > > --- /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 __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 > > > > > > To help raise awareness, is it worth adding deprecation warnings on > > > these? > > > > > > Could we still consider them deprecated even with _SC_SIGSTKSZ_SOURCE? > > > Ideally they should be (or even removed), since even if these values are > > > "correct", using them is still a potential portability problem when > > > building for other library stacks. > > > > > > I think the rule ought to be to use these only if _SC_SIGSTKSZ / > > > _SC_MINSIGSTKSZ aren't available, and with the caveat that the values > > > may be wrong -- similar to the situation with PAGESIZE. > > > > > > > > > It could be worth making this feature test macro more general and > > > harvesting any other broken legacy macros we're aware of (such as > > > PAGESIZE, but there are probably others). Probably out of scope for > > > this patch, though. > > > > I will investigate to deprecate MINSIGSTKSZ and SIGSTKSZ after my patch > > has been merged into master branch. > > > > > > diff --git a/sysdeps/unix/sysv/linux/sysconf-sigstksz.h b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h > > > > new file mode 100644 > > > > index 0000000000..64d450b22c > > > > --- /dev/null > > > > +++ b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h > > > > @@ -0,0 +1,38 @@ > > > > +/* sysconf_sigstksz (). Linux version. > > > > + Copyright (C) 2020 Free Software Foundation, Inc. > > > > + This file is part of the GNU C Library. > > > > + > > > > + The GNU C Library is free software; you can redistribute it and/or > > > > + modify it under the terms of the GNU Lesser General Public > > > > + License as published by the Free Software Foundation; either > > > > + version 2.1 of the License, or (at your option) any later version. > > > > + > > > > + The GNU C Library is distributed in the hope that it will be useful, > > > > + but WITHOUT ANY WARRANTY; without even the implied warranty of > > > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > > > + Lesser General Public License for more details. > > > > + > > > > + You should have received a copy of the GNU Lesser General Public > > > > + License along with the GNU C Library; if not, see > > > > + <https://www.gnu.org/licenses/>. */ > > > > + > > > > +/* Return sysconf (_SC_SIGSTKSZ). */ > > > > + > > > > +static long int > > > > +sysconf_sigstksz (void) > > > > +{ > > > > + long int minsigstacksize = GLRO(dl_minsigstacksize); > > > > + assert (minsigstacksize != 0); > > > > + _Static_assert (__builtin_constant_p (MINSIGSTKSZ), > > > > + "MINSIGSTKSZ is constant"); > > > > + if (minsigstacksize < MINSIGSTKSZ) > > > > + minsigstacksize = MINSIGSTKSZ; > > > > + /* MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4. */ > > > > + long int sigstacksize = minsigstacksize * 4; > > > > + /* Return MAX (SIGSTKSZ, sigstacksize). */ > > > > + _Static_assert (__builtin_constant_p (SIGSTKSZ), > > > > + "SIGSTKSZ is constant"); > > > > + if (sigstacksize < SIGSTKSZ) > > > > + sigstacksize = SIGSTKSZ; > > > > + return sigstacksize; > > > > +} > > > > diff --git a/sysdeps/unix/sysv/linux/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; > > > > > > Couldn't the kernel actually yield MINSIGSTKSZ or a smaller value, say, > > > if running on hardware that doesn't have AVX-512? > > > > > It is OK for MINSIGSTKSZ > AT_MINSIGSTKSZ. For _SC_SIGSTKSZ_SOURCE, > > dynamic MINSIGSTKSZ is defined as sysconf (_SC_SIGSTKSZ) which is > > > > MAX (SIGSTKSZ, MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4) > > > > and dynamic MINSIGSTKSZ is always > MINSIGSTKSZ. > > > > > We might want a separate flag to indicate whether we obtained a value > > > from the auxv, rather relying on MINSIGSTKSZ having this magic meaning. > > > > AT_MINSIGSTKSZ is the only way for GLRO(dl_minsigstacksize) != MINSIGSTKSZ. > > Yes, but reading AT_MINSIGSTKSZ doesn't guarantee that > GLRO(dl_minsigstkszsize) != MINSIGSTKSZ, no? > > What if the value reported for AT_MINSIGSTKSZ is actually the same as > MINSIGSTKSZ? This could be the case on some arches in future even if > it's never true today. But the code here assumes that AT_MINSIGSTKSZ > wasn't available in this case, and reverts to a fallback guess. Since the fallback tracks what the kernel does, if AT_MINSIGSTKSZ is 2KB, the fallback will be 2KB or slightly larger.
On Mon, Oct 19, 2020 at 02:32:35PM -0700, H.J. Lu via Libc-alpha wrote: > On Mon, Oct 19, 2020 at 8:08 AM Dave Martin <Dave.Martin@arm.com> wrote: > > > > On Thu, Oct 15, 2020 at 04:57:28AM -0700, H.J. Lu via Libc-alpha wrote: [...] > > > > > diff --git a/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h b/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.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; > > > > > > > > Couldn't the kernel actually yield MINSIGSTKSZ or a smaller value, say, > > > > if running on hardware that doesn't have AVX-512? > > > > > > > It is OK for MINSIGSTKSZ > AT_MINSIGSTKSZ. For _SC_SIGSTKSZ_SOURCE, > > > dynamic MINSIGSTKSZ is defined as sysconf (_SC_SIGSTKSZ) which is > > > > > > MAX (SIGSTKSZ, MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4) > > > > > > and dynamic MINSIGSTKSZ is always > MINSIGSTKSZ. > > > > > > > We might want a separate flag to indicate whether we obtained a value > > > > from the auxv, rather relying on MINSIGSTKSZ having this magic meaning. > > > > > > AT_MINSIGSTKSZ is the only way for GLRO(dl_minsigstacksize) != MINSIGSTKSZ. > > > > Yes, but reading AT_MINSIGSTKSZ doesn't guarantee that > > GLRO(dl_minsigstkszsize) != MINSIGSTKSZ, no? > > > > What if the value reported for AT_MINSIGSTKSZ is actually the same as > > MINSIGSTKSZ? This could be the case on some arches in future even if > > it's never true today. But the code here assumes that AT_MINSIGSTKSZ > > wasn't available in this case, and reverts to a fallback guess. > > Since the fallback tracks what the kernel does, if AT_MINSIGSTKSZ > is 2KB, the fallback will be 2KB or slightly larger. Well, I guess that should be safe. It still feels a bit like it works by accident, but I may be being too paranoid. Separate question: How are we going to raise awareness of this issue? We do want people to at least be aware that they should consider migrating. Ideally _GNU_SOURCE should imply _SC_SIGSTKSZ_SOURCE -- if not now, then eventually. Is this likely to be too disruptive? Alternatively we could emit warnings for use of MINSIGSTKSZ and SIGSTKSZ even without _SC_SIGSTKSZ_SOURCE, while keeping the old compiletime- constant values in this case. Cheers ---Dave
On Tue, Oct 20, 2020 at 2:19 AM Dave Martin <Dave.Martin@arm.com> wrote: > > On Mon, Oct 19, 2020 at 02:32:35PM -0700, H.J. Lu via Libc-alpha wrote: > > On Mon, Oct 19, 2020 at 8:08 AM Dave Martin <Dave.Martin@arm.com> wrote: > > > > > > On Thu, Oct 15, 2020 at 04:57:28AM -0700, H.J. Lu via Libc-alpha wrote: > > [...] > > > > > > > diff --git a/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h b/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.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; > > > > > > > > > > Couldn't the kernel actually yield MINSIGSTKSZ or a smaller value, say, > > > > > if running on hardware that doesn't have AVX-512? > > > > > > > > > It is OK for MINSIGSTKSZ > AT_MINSIGSTKSZ. For _SC_SIGSTKSZ_SOURCE, > > > > dynamic MINSIGSTKSZ is defined as sysconf (_SC_SIGSTKSZ) which is > > > > > > > > MAX (SIGSTKSZ, MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4) > > > > > > > > and dynamic MINSIGSTKSZ is always > MINSIGSTKSZ. > > > > > > > > > We might want a separate flag to indicate whether we obtained a value > > > > > from the auxv, rather relying on MINSIGSTKSZ having this magic meaning. > > > > > > > > AT_MINSIGSTKSZ is the only way for GLRO(dl_minsigstacksize) != MINSIGSTKSZ. > > > > > > Yes, but reading AT_MINSIGSTKSZ doesn't guarantee that > > > GLRO(dl_minsigstkszsize) != MINSIGSTKSZ, no? > > > > > > What if the value reported for AT_MINSIGSTKSZ is actually the same as > > > MINSIGSTKSZ? This could be the case on some arches in future even if > > > it's never true today. But the code here assumes that AT_MINSIGSTKSZ > > > wasn't available in this case, and reverts to a fallback guess. > > > > Since the fallback tracks what the kernel does, if AT_MINSIGSTKSZ > > is 2KB, the fallback will be 2KB or slightly larger. > > Well, I guess that should be safe. It still feels a bit like it works > by accident, but I may be being too paranoid. Let me work on that. > > Separate question: > > How are we going to raise awareness of this issue? We do want people to > at least be aware that they should consider migrating. > > Ideally _GNU_SOURCE should imply _SC_SIGSTKSZ_SOURCE -- if not now, then > eventually. Is this likely to be too disruptive? I guess so. > Alternatively we could emit warnings for use of MINSIGSTKSZ and SIGSTKSZ > even without _SC_SIGSTKSZ_SOURCE, while keeping the old compiletime- > constant values in this case. Is there a way to deprecate a constant?
On Tue, Oct 20, 2020 at 07:59:01AM -0700, H.J. Lu via Libc-alpha wrote: > On Tue, Oct 20, 2020 at 2:19 AM Dave Martin <Dave.Martin@arm.com> wrote: > > > > On Mon, Oct 19, 2020 at 02:32:35PM -0700, H.J. Lu via Libc-alpha wrote: > > > On Mon, Oct 19, 2020 at 8:08 AM Dave Martin <Dave.Martin@arm.com> wrote: > > > > > > > > On Thu, Oct 15, 2020 at 04:57:28AM -0700, H.J. Lu via Libc-alpha wrote: > > > > [...] > > > > > > > > > diff --git a/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h b/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.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; > > > > > > > > > > > > Couldn't the kernel actually yield MINSIGSTKSZ or a smaller value, say, > > > > > > if running on hardware that doesn't have AVX-512? > > > > > > > > > > > It is OK for MINSIGSTKSZ > AT_MINSIGSTKSZ. For _SC_SIGSTKSZ_SOURCE, > > > > > dynamic MINSIGSTKSZ is defined as sysconf (_SC_SIGSTKSZ) which is > > > > > > > > > > MAX (SIGSTKSZ, MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4) > > > > > > > > > > and dynamic MINSIGSTKSZ is always > MINSIGSTKSZ. > > > > > > > > > > > We might want a separate flag to indicate whether we obtained a value > > > > > > from the auxv, rather relying on MINSIGSTKSZ having this magic meaning. > > > > > > > > > > AT_MINSIGSTKSZ is the only way for GLRO(dl_minsigstacksize) != MINSIGSTKSZ. > > > > > > > > Yes, but reading AT_MINSIGSTKSZ doesn't guarantee that > > > > GLRO(dl_minsigstkszsize) != MINSIGSTKSZ, no? > > > > > > > > What if the value reported for AT_MINSIGSTKSZ is actually the same as > > > > MINSIGSTKSZ? This could be the case on some arches in future even if > > > > it's never true today. But the code here assumes that AT_MINSIGSTKSZ > > > > wasn't available in this case, and reverts to a fallback guess. > > > > > > Since the fallback tracks what the kernel does, if AT_MINSIGSTKSZ > > > is 2KB, the fallback will be 2KB or slightly larger. > > > > Well, I guess that should be safe. It still feels a bit like it works > > by accident, but I may be being too paranoid. > > Let me work on that. > > > > > Separate question: > > > > How are we going to raise awareness of this issue? We do want people to > > at least be aware that they should consider migrating. > > > > Ideally _GNU_SOURCE should imply _SC_SIGSTKSZ_SOURCE -- if not now, then > > eventually. Is this likely to be too disruptive? > > I guess so. > > > Alternatively we could emit warnings for use of MINSIGSTKSZ and SIGSTKSZ > > even without _SC_SIGSTKSZ_SOURCE, while keeping the old compiletime- > > constant values in this case. > > Is there a way to deprecate a constant? Hmm, possibly not. I had hoped that a const variable or a function marked with __attribute_const could be used as a compiletime-constant value, but GCC at least doesn't support this. (It works in C++, but that doesn't help us here...) Cheers ---Dave
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/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..b202301ad8 100644 --- a/include/features.h +++ b/include/features.h @@ -55,6 +55,9 @@ _FORTIFY_SOURCE Add security hardening to many library functions. Set to 1 or 2; 2 performs stricter checks than 1. + _SC_SIGSTKSZ_SOURCE Select correct (but non compile-time constant) + MINSIGSTKSZ and SIGSTKSZ. + _REENTRANT, _THREAD_SAFE Obsolete; equivalent to _POSIX_C_SOURCE=199506L. @@ -96,6 +99,8 @@ __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 correct (but non compile-time constant) + MINSIGSTKSZ and SIGSTKSZ. The macros `__GNU_LIBRARY__', `__GLIBC__', and `__GLIBC_MINOR__' are defined by this file unconditionally. `__GNU_LIBRARY__' is provided @@ -139,6 +144,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 +413,12 @@ # define __USE_FORTIFY_LEVEL 0 #endif +#ifdef _SC_SIGSTKSZ_SOURCE +# define __USE_SC_SIGSTKSZ 1 +#else +# define __USE_SC_SIGSTKSZ 0 +#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}. + +@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 be5050468b..8fef4150fa 100644 --- a/manual/creature.texi +++ b/manual/creature.texi @@ -257,6 +257,12 @@ various library functions. If defined to @math{2}, even stricter checks are applied. @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 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..d657d2f4e6 --- /dev/null +++ b/signal/tst-minsigstksz-5.c @@ -0,0 +1,84 @@ +/* Test of signal delivery on an alternate stack with MINSIGSTKSZ size. + Copyright (C) 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <support/check.h> +#include <support/support.h> + +static volatile sig_atomic_t handler_run; + +static void +handler (int signo) +{ + /* Clear a bit of on-stack memory. */ + volatile char buffer[256]; + for (size_t i = 0; i < sizeof (buffer); ++i) + buffer[i] = 0; + handler_run = 1; +} + +int +do_test (void) +{ + size_t stack_buffer_size = 64 * 1024 * 1024; + void *stack_buffer = xmalloc (stack_buffer_size); + void *stack_end = stack_buffer + stack_buffer_size; + memset (stack_buffer, 0xCC, stack_buffer_size); + + void *stack_bottom = stack_buffer + (stack_buffer_size + MINSIGSTKSZ) / 2; + void *stack_top = stack_bottom + MINSIGSTKSZ; + stack_t stack = + { + .ss_sp = stack_bottom, + .ss_size = MINSIGSTKSZ, + }; + if (sigaltstack (&stack, NULL) < 0) + FAIL_RET ("sigaltstack: %m\n"); + + struct sigaction act = + { + .sa_handler = handler, + .sa_flags = SA_ONSTACK, + }; + if (sigaction (SIGUSR1, &act, NULL) < 0) + FAIL_RET ("sigaction: %m\n"); + + if (kill (getpid (), SIGUSR1) < 0) + FAIL_RET ("kill: %m\n"); + + if (handler_run != 1) + FAIL_RET ("handler did not run\n"); + + for (void *p = stack_buffer; p < stack_bottom; ++p) + if (*(unsigned char *) p != 0xCC) + FAIL_RET ("changed byte %ld bytes below configured stack\n", + (long) (stack_bottom - p)); + for (void *p = stack_top; p < stack_end; ++p) + if (*(unsigned char *) p != 0xCC) + FAIL_RET ("changed byte %ld bytes above configured stack\n", + (long) (p - stack_top)); + + free (stack_buffer); + + return 0; +} + +#include <support/test-driver.c> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 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 09604e128b..b51a02a6e6 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..cd5b3cc895 --- /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 __USE_SC_SIGSTKSZ +# include <unistd.h> + +/* Default stack size for a signal handler: sysconf (SC_SIGSTKSZ). */ +# undef SIGSTKSZ +# define SIGSTKSZ sysconf (_SC_SIGSTKSZ) + +/* Minimum stack size for a signal handler: SIGSTKSZ. */ +# undef MINSIGSTKSZ +# define MINSIGSTKSZ SIGSTKSZ +#endif diff --git a/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h b/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h new file mode 100644 index 0000000000..7e5ceba151 --- /dev/null +++ b/sysdeps/unix/sysv/linux/ia64/sysconf-sigstksz.h @@ -0,0 +1,27 @@ +/* sysconf_sigstksz (). Linux/ia64 version. + Copyright (C) 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +/* Return sysconf (_SC_SIGSTKSZ). */ + +static long int +sysconf_sigstksz (void) +{ + _Static_assert (__builtin_constant_p (SIGSTKSZ), + "SIGSTKSZ is constant"); + return SIGSTKSZ; +} diff --git a/sysdeps/unix/sysv/linux/sysconf-sigstksz.h b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h new file mode 100644 index 0000000000..64d450b22c --- /dev/null +++ b/sysdeps/unix/sysv/linux/sysconf-sigstksz.h @@ -0,0 +1,38 @@ +/* sysconf_sigstksz (). Linux version. + Copyright (C) 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +/* Return sysconf (_SC_SIGSTKSZ). */ + +static long int +sysconf_sigstksz (void) +{ + long int minsigstacksize = GLRO(dl_minsigstacksize); + assert (minsigstacksize != 0); + _Static_assert (__builtin_constant_p (MINSIGSTKSZ), + "MINSIGSTKSZ is constant"); + if (minsigstacksize < MINSIGSTKSZ) + minsigstacksize = MINSIGSTKSZ; + /* MAX (MINSIGSTKSZ, sysconf (_SC_MINSIGSTKSZ)) * 4. */ + long int sigstacksize = minsigstacksize * 4; + /* Return MAX (SIGSTKSZ, sigstacksize). */ + _Static_assert (__builtin_constant_p (SIGSTKSZ), + "SIGSTKSZ is constant"); + if (sigstacksize < SIGSTKSZ) + sigstacksize = SIGSTKSZ; + return sigstacksize; +} diff --git a/sysdeps/unix/sysv/linux/sysconf.c b/sysdeps/unix/sysv/linux/sysconf.c index 7958a74164..d1d86df3fb 100644 --- a/sysdeps/unix/sysv/linux/sysconf.c +++ b/sysdeps/unix/sysv/linux/sysconf.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ +#include <assert.h> #include <errno.h> #include <fcntl.h> #include <stdlib.h> @@ -26,6 +27,7 @@ #include <sys/param.h> #include <not-cancel.h> #include <ldsodefs.h> +#include <sysconf-sigstksz.h> /* Legacy value of ARG_MAX. The macro is now not defined since the actual value varies based on the stack size. */ @@ -75,6 +77,13 @@ __sysconf (int name) } break; + case _SC_MINSIGSTKSZ: + assert (GLRO(dl_minsigstacksize) != 0); + return GLRO(dl_minsigstacksize); + + case _SC_SIGSTKSZ: + return sysconf_sigstksz (); + default: break; } diff --git a/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h b/sysdeps/unix/sysv/linux/x86/dl-minsigstacksize.h new file mode 100644 index 0000000000..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) +{ +}