From b4bb5c8ae79eebc3d5ec829b932c04df35881ef2 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 14 May 2021 22:48:20 -0700 Subject: [PATCH] c-stack: work around Solaris 11 bugs Problem reported by Bruno Haible in: https://lists.gnu.org/r/bug-gnulib/2021-05/msg00062.html * lib/c-stack.c: Always include sigsegv.h if HAVE_LIBSIGSEGV. (USE_LIBSIGSEGV): Do not use libsigsegv if the kernel has the si_addr bug and libsigsegv is too old to work around it. (segv_handler) [!USE_LIBSIGSEGV]: Do not trust si_addr if BOGUS_SI_ADDR_UPON_STACK_OVERFLOW. * m4/c-stack.m4 (AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC): Define BOGUS_SI_ADDR_UPON_STACK_OVERFLOW on Solaris 2.11 SPARC. And do not define HAVE_XSI_STACK_OVERFLOW_HEURISTIC. --- ChangeLog | 15 +++++++++++++++ lib/c-stack.c | 25 +++++++++++++++++-------- m4/c-stack.m4 | 14 ++++++++++++-- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index e3f1d8220..b802233cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2021-05-14 Paul Eggert + + c-stack: work around Solaris 11 bugs + Problem reported by Bruno Haible in: + https://lists.gnu.org/r/bug-gnulib/2021-05/msg00062.html + * lib/c-stack.c: Always include sigsegv.h if HAVE_LIBSIGSEGV. + (USE_LIBSIGSEGV): Do not use libsigsegv if the kernel + has the si_addr bug and libsigsegv is too old to work + around it. + (segv_handler) [!USE_LIBSIGSEGV]: Do not trust si_addr + if BOGUS_SI_ADDR_UPON_STACK_OVERFLOW. + * m4/c-stack.m4 (AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC): + Define BOGUS_SI_ADDR_UPON_STACK_OVERFLOW on Solaris 2.11 SPARC. + And do not define HAVE_XSI_STACK_OVERFLOW_HEURISTIC. + 2021-05-14 Bruno Haible fcntl tests: Avoid failure in MacPorts. diff --git a/lib/c-stack.c b/lib/c-stack.c index c0da7f404..3e8cd2565 100644 --- a/lib/c-stack.c +++ b/lib/c-stack.c @@ -66,14 +66,19 @@ typedef struct sigaltstack stack_t; #include "gettext.h" #define _(msgid) gettext (msgid) -/* Use libsigsegv only if needed; kernels like Solaris can detect - stack overflow without the overhead of an external library. */ -#define USE_LIBSIGSEGV (!HAVE_XSI_STACK_OVERFLOW_HEURISTIC && HAVE_LIBSIGSEGV) - -#if USE_LIBSIGSEGV +#if HAVE_LIBSIGSEGV # include #endif +/* Use libsigsegv only if needed; kernels like Solaris can detect + stack overflow without the overhead of an external library. + However, BOGUS_SI_ADDR_ON_STACK_OVERFLOW indicates a buggy + Solaris kernel, and a too-small LIBSIGSEGV_VERSION indicates a + libsigsegv so old that it does not work around the bug. */ +#define USE_LIBSIGSEGV (!HAVE_XSI_STACK_OVERFLOW_HEURISTIC && HAVE_LIBSIGSEGV \ + && ! (BOGUS_SI_ADDR_UPON_STACK_OVERFLOW \ + && LIBSIGSEGV_VERSION < 0x020D)) + #include "exitfail.h" #include "ignore-value.h" #include "intprops.h" @@ -277,6 +282,9 @@ segv_handler (int signo, siginfo_t *info, void *context _GL_UNUSED) of the current stack. */ if (!cannot_be_stack_overflow) { +# if BOGUS_SI_ADDR_UPON_STACK_OVERFLOW + signo = 0; +# else /* If the faulting address is within the stack, or within one page of the stack, assume that it is a stack overflow. */ uintptr_t faulting_address = (uintptr_t) info->si_addr; @@ -286,12 +294,12 @@ segv_handler (int signo, siginfo_t *info, void *context _GL_UNUSED) pages might be in the stack. */ void *stack_base = (void *) (uintptr_t) page_size; uintptr_t stack_size = 0; stack_size -= page_size; -# if HAVE_XSI_STACK_OVERFLOW_HEURISTIC +# if HAVE_XSI_STACK_OVERFLOW_HEURISTIC /* Tighten the stack bounds via the XSI heuristic. */ ucontext_t const *user_context = context; stack_base = user_context->uc_stack.ss_sp; stack_size = user_context->uc_stack.ss_size; -# endif +# endif uintptr_t base = (uintptr_t) stack_base, lo = (INT_SUBTRACT_WRAPV (base, page_size, &lo) || lo < page_size ? page_size : lo), @@ -300,8 +308,9 @@ segv_handler (int signo, siginfo_t *info, void *context _GL_UNUSED) ? UINTPTR_MAX : hi); if (lo <= faulting_address && faulting_address <= hi) signo = 0; +# endif -# if DEBUG +# if DEBUG { char buf[1024]; ignore_value (write (STDERR_FILENO, buf, diff --git a/m4/c-stack.m4 b/m4/c-stack.m4 index df8dc52ca..06b2594d4 100644 --- a/m4/c-stack.m4 +++ b/m4/c-stack.m4 @@ -199,14 +199,24 @@ int main () rather than as the lowest address.]) fi + case $host_os--$host_cpu in + solaris2.11--sparc*) + AC_DEFINE([BOGUS_SI_ADDR_UPON_STACK_OVERFLOW], [1], + [Define to 1 if the faulting address (info->si_addr) + might be incorrect on stack overflow.]) + gl_bogus_si_addr=1;; + *) gl_bogus_si_addr=0;; + esac + AC_CACHE_CHECK([for precise C stack overflow detection], [gl_cv_sys_xsi_stack_overflow_heuristic], [dnl On Linux/sparc64 (both in 32-bit and 64-bit mode), it would be wrong dnl to set HAVE_XSI_STACK_OVERFLOW_HEURISTIC to 1, because the third dnl argument passed to the segv_handler is a 'struct sigcontext *', not dnl an 'ucontext_t *'. It would lead to a failure of test-c-stack2.sh. - case "${host_os}--${host_cpu}" in - linux*--sparc*) + dnl If $gl_bogus_si_addr is 1, there is no point to the heuristic. + case "${host_os}--${host_cpu}--${gl_bogus_si_addr}" in + linux*--sparc* | *--1) gl_cv_sys_xsi_stack_overflow_heuristic=no ;; *) -- 2.31.1