From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS22989 209.51.188.0/24 X-Spam-Status: No, score=-3.8 required=3.0 tests=AWL,BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS, SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 467B81F5AE for ; Mon, 17 May 2021 01:50:05 +0000 (UTC) Received: from localhost ([::1]:53146 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1liSOR-0000Iy-Mg for normalperson@yhbt.net; Sun, 16 May 2021 21:50:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:42620) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1liSOO-0000IP-3c for bug-gnulib@gnu.org; Sun, 16 May 2021 21:50:00 -0400 Received: from mo4-p00-ob.smtp.rzone.de ([85.215.255.25]:12722) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1liSOK-0005Hy-7N for bug-gnulib@gnu.org; Sun, 16 May 2021 21:49:59 -0400 ARC-Seal: i=1; a=rsa-sha256; t=1621216192; cv=none; d=strato.com; s=strato-dkim-0002; b=j0+hwX2GfA4vjvZemchfya+IrKd0ZxAqmgw9o4chWQC8sqU7bZvxopxtnH6dZP668f UCx+QyzzmAAs217wxEObp2Yvqmw7vzdiWlT1Or/7F9Va1uIU28DPxSFxTFxW3iE3eRGH lOTYesWy5Q1C7DRkF7kzaMI2Z33cFlUSpS0YIKqCS8EJi36IMZ3BfUQrOMx7EMdQDNy3 B9ByLXka4PR8jkPIdRfKvOwdeI13TgmwcUo/oEe9Ih+mgSjbgXs5eqQAjGDPVl2dBAwK C66QfU1o99vEKcAzeXP1xxPbNXeKfM84koIThJtIpXsVTVFcJnBE9ZOUtuVxq78IylGA aupg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1621216192; s=strato-dkim-0002; d=strato.com; h=Message-ID:Date:Subject:Cc:To:From:Cc:Date:From:Subject:Sender; bh=+l9/xRmG48dluPg68gv+Hfw+PeAxsJpXYp9BdpCK5JU=; b=DWHASymijIjmWnHawD6RsiPBhvvWWiUcnzYIm3o8UWew9Az/pK5hqTp7FmNVn0SFmM oZCIdo4V2KO/lSdNmbmHCickivHXW4YlV9afk++GL70Qx5knaHsVSBqwJ4Bl+eQh2Lde R93M8oP74vEn5wAvj2r3iEbJfiPvmRNWLNep3RHYShdYKX+ugd3ag5iPairXWtE757VB io5olgpj0EaGUEt2j/uU0nEgrN9+jG019o5nLKyX9SS04lpEx7mT5kFnb7rRZnom5t4N 7Nm4TSJmuNJtUAePXxpDGJxckPK/I3s/zo8RM5zxhb3yWpcdQ0ZWWs23d8Xx6L00gler anWw== ARC-Authentication-Results: i=1; strato.com; dkim=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1621216192; s=strato-dkim-0002; d=clisp.org; h=Message-ID:Date:Subject:Cc:To:From:Cc:Date:From:Subject:Sender; bh=+l9/xRmG48dluPg68gv+Hfw+PeAxsJpXYp9BdpCK5JU=; b=l5ZR2dJvfIoKRsuUns1dSrnDVwP6eY8DYF3QITkJt63GnWgTRilux8NJ8dbTEv3POJ RWT9uoBejG9b1ucR2dIRolom4RMQVLbaV52GsYB76E3bLExgsyv9NJOfLZGlZ49LC27/ afSGmiTejZF4lTwXiRXdrG0WVarxQKjFJ6IkgjNprbyX0ODvTufJy5xufty6l/Lg9xCr 7fGQeYlotiriKPPpDqDJLec69J78DhZ9Of9NqF22xmOjziq5NnGLWsmxlLUBpJjicabj dY6Dehz/3yJ54bCPvFDkdcnKDm6WRWlQ6Rs88yEevz3mNX64RPkUBJ6Okj/DOrhyethJ hJPw== Authentication-Results: strato.com; dkim=none X-RZG-AUTH: ":Ln4Re0+Ic/6oZXR1YgKryK8brlshOcZlIWs+iCP5vnk6shH+AHjwLuWOHqf3z5NW" X-RZG-CLASS-ID: mo00 Received: from bruno.haible.de by smtp.strato.de (RZmta 47.26.0 DYNA|AUTH) with ESMTPSA id e0b483x4H1np0LB (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (curve X9_62_prime256v1 with 256 ECDH bits, eq. 3072 bits RSA)) (Client did not present a certificate); Mon, 17 May 2021 03:49:51 +0200 (CEST) From: Bruno Haible To: Paul Eggert Subject: c-stack: Catching stack overflow on most platforms without libsigsegv Date: Mon, 17 May 2021 03:49:50 +0200 Message-ID: <1929088.Mkc5n7ySbz@omega> User-Agent: KMail/5.1.3 (Linux/4.4.0-206-generic; KDE/5.18.0; x86_64; ; ) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="nextPart7579430.Bj6nBJWQ3l" Content-Transfer-Encoding: 7Bit Received-SPF: none client-ip=85.215.255.25; envelope-from=bruno@clisp.org; helo=mo4-p00-ob.smtp.rzone.de X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_PASS=-0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: bug-gnulib@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Gnulib discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: bug-gnulib@gnu.org Errors-To: bug-gnulib-bounces+normalperson=yhbt.net@gnu.org Sender: "bug-gnulib" This is a multi-part message in MIME format. --nextPart7579430.Bj6nBJWQ3l Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Hi Paul, Here is a proposed patch to make use of the new 'sigsegv' module (quasi a mini libsigsegv without library dependencies), so that * On most systems, catching stack overflow becomes possible without link dependencies. (The only notable exceptions, where GNU libsigsegv are still needed, are native Windows and older versions of various OSes: Mac OS X 10.5, probably NetBSD 7, and such.) * In particular, glibc systems are no longer left behind, compared to Solaris. I have verified this patch by building and m4 snapshot with it on - glibc - newest glibc > 2.33 snapshot - Solaris 11/sparc64 - Cygwin - Minix (just to test a case where catching stack overflow is not supported). And I had tested the 'sigsegv' module on ca. 58 platforms, from IRIX 6.5 to musl libc on Linux/s390x. Bruno --nextPart7579430.Bj6nBJWQ3l Content-Disposition: attachment; filename="0001-c-stack-Catching-stack-overflow-on-most-platforms-wi.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0001-c-stack-Catching-stack-overflow-on-most-platforms-wi.patch" >From 7832467d9d79753185664f702c50fb91dd5311eb Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Mon, 17 May 2021 03:36:35 +0200 Subject: [PATCH] c-stack: Catching stack overflow on most platforms without libsigsegv. * lib/c-stack.c: Remove all Solaris-specific code. Include always. * m4/c-stack.m4: Remove all Solaris-specific code. (gl_C_STACK): Test $with_libsigsegv from module 'sigsegv'. * modules/c-stack (Files): Remove m4/libsigsegv.m4. (Depends-on): Add sigsegv. Remove havelib, intprops, inttypes, mempcpy, sigaction, stdbool. --- ChangeLog | 11 ++ lib/c-stack.c | 188 +------------------------- m4/c-stack.m4 | 413 ++------------------------------------------------------ modules/c-stack | 8 +- 4 files changed, 27 insertions(+), 593 deletions(-) diff --git a/ChangeLog b/ChangeLog index e3ab1ff..ae60171 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2021-05-16 Bruno Haible + c-stack: Catching stack overflow on most platforms without libsigsegv. + * lib/c-stack.c: Remove all Solaris-specific code. Include + always. + * m4/c-stack.m4: Remove all Solaris-specific code. + (gl_C_STACK): Test $with_libsigsegv from module 'sigsegv'. + * modules/c-stack (Files): Remove m4/libsigsegv.m4. + (Depends-on): Add sigsegv. Remove havelib, intprops, inttypes, mempcpy, + sigaction, stdbool. + +2021-05-16 Bruno Haible + sigsegv, c-stack: Avoid compilation error with glibc >= 2.34. * lib/sigsegv.in.h (SIGSTKSZ): On glibc systems, redefine to a suitable constant. diff --git a/lib/c-stack.c b/lib/c-stack.c index 3e8cd25..1965bdd 100644 --- a/lib/c-stack.c +++ b/lib/c-stack.c @@ -39,59 +39,27 @@ #include #include - #include -#if ! HAVE_STACK_T && ! defined stack_t -typedef struct sigaltstack stack_t; -#endif - -#include #include #include #include - -/* Pre-2008 POSIX declared ucontext_t in ucontext.h instead of signal.h. */ -#if HAVE_UCONTEXT_H -# include -#endif - #include #if DEBUG # include #endif +#include + +#include "exitfail.h" +#include "getprogname.h" #include "idx.h" +#include "ignore-value.h" #include "gettext.h" #define _(msgid) gettext (msgid) -#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" -#include "getprogname.h" - -#if defined SA_ONSTACK && defined SA_SIGINFO -# define SIGINFO_WORKS 1 -#else -# define SIGINFO_WORKS 0 -# ifndef SA_ONSTACK -# define SA_ONSTACK 0 -# endif -#endif +#if HAVE_STACK_OVERFLOW_RECOVERY /* Storage for the alternate signal stack. 64 KiB is not too large for Gnulib-using apps, and is large enough @@ -113,9 +81,6 @@ static _GL_ASYNC_SAFE void (* volatile segv_action) (int); static char const * volatile program_error_message; static char const * volatile stack_overflow_message; -#if (USE_LIBSIGSEGV \ - || (HAVE_DECL_SIGALTSTACK && HAVE_STACK_OVERFLOW_HANDLING)) - /* Output an error message, then exit with status EXIT_FAILURE if it appears to have been a stack overflow, or with a core dump otherwise. This function is async-signal-safe. */ @@ -125,12 +90,6 @@ static char const * volatile progname; static _GL_ASYNC_SAFE _Noreturn void die (int signo) { -# if !SIGINFO_WORKS && !USE_LIBSIGSEGV - /* We can't easily determine whether it is a stack overflow; so - assume that the rest of our program is perfect (!) and that - this segmentation violation is a stack overflow. */ - signo = 0; -# endif segv_action (signo); char const *message = signo ? program_error_message : stack_overflow_message; @@ -171,10 +130,6 @@ null_action (int signo _GL_UNUSED) { } -#endif /* SIGALTSTACK || LIBSIGSEGV */ - -#if USE_LIBSIGSEGV - /* Pacify GCC 9.3.1, which otherwise would complain about segv_handler. */ # if 4 < __GNUC__ + (6 <= __GNUC_MINOR__) # pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" @@ -247,136 +202,7 @@ c_stack_action (_GL_ASYNC_SAFE void (*action) (int)) return 0; } -#elif HAVE_DECL_SIGALTSTACK && HAVE_STACK_OVERFLOW_HANDLING - -# if SIGINFO_WORKS - -static size_t volatile page_size; - -/* Handle a segmentation violation and exit. This function is - async-signal-safe. */ - -static _GL_ASYNC_SAFE _Noreturn void -segv_handler (int signo, siginfo_t *info, void *context _GL_UNUSED) -{ - /* Clear SIGNO if it seems to have been a stack overflow. */ - - /* If si_code is nonpositive, something like raise (SIGSEGV) occurred - so it cannot be a stack overflow. */ - bool cannot_be_stack_overflow = info->si_code <= 0; - - /* An unaligned address cannot be a stack overflow. */ -# if FAULT_YIELDS_SIGBUS - cannot_be_stack_overflow |= signo == SIGBUS && info->si_code == BUS_ADRALN; -# endif - - /* If we can't easily determine that it is not a stack overflow, - assume that the rest of our program is perfect (!) and that - this segmentation violation is a stack overflow. - - Note that although both Linux and Solaris provide - sigaltstack, SA_ONSTACK, and SA_SIGINFO, currently only - Solaris satisfies the XSI heuristic. This is because - Solaris populates uc_stack with the details of the - interrupted stack, while Linux populates it with the details - 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; - - /* On all platforms we know of, the first page is not in the - stack to catch null pointer dereferening. However, all other - 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 - /* 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 - uintptr_t base = (uintptr_t) stack_base, - lo = (INT_SUBTRACT_WRAPV (base, page_size, &lo) || lo < page_size - ? page_size : lo), - hi = ((INT_ADD_WRAPV (base, stack_size, &hi) - || INT_ADD_WRAPV (hi, page_size - 1, &hi)) - ? UINTPTR_MAX : hi); - if (lo <= faulting_address && faulting_address <= hi) - signo = 0; -# endif - -# if DEBUG - { - char buf[1024]; - ignore_value (write (STDERR_FILENO, buf, - sprintf (buf, - ("segv_handler code=%d fault=%p base=%p" - " size=0x%zx page=0x%zx signo=%d\n"), - info->si_code, info->si_addr, stack_base, - stack_size, page_size, signo))); - } -# endif - } - - die (signo); -} -# endif - -int -c_stack_action (_GL_ASYNC_SAFE void (*action) (int)) -{ - stack_t st; - st.ss_flags = 0; - st.ss_sp = alternate_signal_stack; - st.ss_size = sizeof alternate_signal_stack; -# if SIGALTSTACK_SS_REVERSED - /* Irix mistakenly treats ss_sp as the upper bound, rather than - lower bound, of the alternate stack. */ - st.ss_size -= sizeof (void *); - char *ss_sp = st.ss_sp; - st.ss_sp = ss_sp + st.ss_size; -# endif - int r = sigaltstack (&st, NULL); - if (r != 0) - return r; - - segv_action = action ? action : null_action; - program_error_message = _("program error"); - stack_overflow_message = _("stack overflow"); - progname = getprogname (); - -# if SIGINFO_WORKS - page_size = sysconf (_SC_PAGESIZE); -# endif - - struct sigaction act; - sigemptyset (&act.sa_mask); - -# if SIGINFO_WORKS - /* POSIX 1003.1-2001 says SA_RESETHAND implies SA_NODEFER, but - this is not true on Solaris 8 at least. It doesn't hurt to use - SA_NODEFER here, so leave it in. */ - act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO; - act.sa_sigaction = segv_handler; -# else - act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND; - act.sa_handler = die; -# endif - -# if FAULT_YIELDS_SIGBUS - if (sigaction (SIGBUS, &act, NULL) < 0) - return -1; -# endif - return sigaction (SIGSEGV, &act, NULL); -} - -#else /* ! (USE_LIBSIGSEGV - || (HAVE_DECL_SIGALTSTACK && HAVE_STACK_OVERFLOW_HANDLING)) */ +#else /* !HAVE_STACK_OVERFLOW_RECOVERY */ int c_stack_action (_GL_ASYNC_SAFE void (*action) (int) _GL_UNUSED) diff --git a/m4/c-stack.m4 b/m4/c-stack.m4 index 3131dd5..7cccb06 100644 --- a/m4/c-stack.m4 +++ b/m4/c-stack.m4 @@ -7,412 +7,15 @@ # Written by Paul Eggert. -# serial 22 - -AC_DEFUN([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC], - [ - AC_REQUIRE([AC_CANONICAL_HOST]) - AC_CHECK_FUNCS_ONCE([setrlimit]) - AC_CHECK_HEADERS_ONCE([ucontext.h]) - - dnl List of signals that are sent when an invalid virtual memory address - dnl is accessed, or when the stack overflows. - dnl Either { SIGSEGV } or { SIGSEGV, SIGBUS }. - case "$host_os" in - sunos4* | freebsd* | dragonfly* | midnightbsd* | openbsd* | mirbsd* | netbsd* | kfreebsd* | knetbsd*) # BSD systems - FAULT_YIELDS_SIGBUS=1 ;; - hpux*) # HP-UX - FAULT_YIELDS_SIGBUS=1 ;; - macos* | darwin*) # Mac OS X - FAULT_YIELDS_SIGBUS=1 ;; - gnu*) # Hurd - FAULT_YIELDS_SIGBUS=1 ;; - *) - FAULT_YIELDS_SIGBUS=0 ;; - esac - AC_DEFINE_UNQUOTED([FAULT_YIELDS_SIGBUS], [$FAULT_YIELDS_SIGBUS], - [Define to 1 if an invalid memory address access may yield a SIGBUS.]) - - AC_CACHE_CHECK([for working C stack overflow detection], - [gl_cv_sys_stack_overflow_works], - [AC_RUN_IFELSE([AC_LANG_SOURCE( - [[ - #include - #include - #if HAVE_SETRLIMIT - # include - # include - # include - #endif - /* In glibc >= 2.34, when _GNU_SOURCE is defined, SIGSTKSZ is - no longer a compile-time constant. But we need a simple - constant here. */ - #if __GLIBC__ >= 2 - # undef SIGSTKSZ - # if defined __ia64__ - # define SIGSTKSZ 262144 - # else - # define SIGSTKSZ 16384 - # endif - #endif - #ifndef SIGSTKSZ - # define SIGSTKSZ 16384 - #endif - - static union - { - char buffer[2 * SIGSTKSZ]; - long double ld; - long u; - void *p; - } alternate_signal_stack; - - static void - segv_handler (int signo) - { - _exit (0); - } - - static int - c_stack_action () - { - stack_t st; - struct sigaction act; - int r; - - st.ss_flags = 0; - /* Use the midpoint to avoid Irix sigaltstack bug. */ - st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ; - st.ss_size = SIGSTKSZ; - r = sigaltstack (&st, 0); - if (r != 0) - return 1; - - sigemptyset (&act.sa_mask); - act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND; - act.sa_handler = segv_handler; - #if FAULT_YIELDS_SIGBUS - if (sigaction (SIGBUS, &act, 0) < 0) - return 2; - #endif - if (sigaction (SIGSEGV, &act, 0) < 0) - return 3; - return 0; - } - static volatile int * - recurse_1 (volatile int n, volatile int *p) - { - if (n >= 0) - *recurse_1 (n + 1, p) += n; - return p; - } - static int - recurse (volatile int n) - { - int sum = 0; - return *recurse_1 (n, &sum); - } - int - main () - { - int result; - #if HAVE_SETRLIMIT && defined RLIMIT_STACK - /* Before starting the endless recursion, try to be friendly - to the user's machine. On some Linux 2.2.x systems, there - is no stack limit for user processes at all. We don't want - to kill such systems. */ - struct rlimit rl; - rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */ - setrlimit (RLIMIT_STACK, &rl); - #endif - - result = c_stack_action (); - if (result != 0) - return result; - return recurse (0); - } - ]])], - [gl_cv_sys_stack_overflow_works=yes], - [gl_cv_sys_stack_overflow_works=no], - [case "$host_os" in - # Guess no on native Windows. - mingw*) gl_cv_sys_stack_overflow_works="guessing no" ;; - *) gl_cv_sys_stack_overflow_works=cross-compiling ;; - esac - ]) - ]) - - if test "$gl_cv_sys_stack_overflow_works" = yes; then - AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1], - [Define to 1 if extending the stack slightly past the limit causes - a SIGSEGV which can be handled on an alternate stack established - with sigaltstack.]) - - dnl The ss_sp field of a stack_t is, according to POSIX, the lowest address - dnl of the memory block designated as an alternate stack. But IRIX 5.3 - dnl interprets it as the highest address! - AC_CACHE_CHECK([for correct stack_t interpretation], - [gl_cv_sigaltstack_low_base], [ - AC_RUN_IFELSE([ - AC_LANG_SOURCE([[ -#include -#include -#if HAVE_SYS_SIGNAL_H -# include -#endif -/* In glibc >= 2.34, when _GNU_SOURCE is defined, SIGSTKSZ is no longer a - compile-time constant. But we need a simple constant here. */ -#if __GLIBC__ >= 2 -# undef SIGSTKSZ -# if defined __ia64__ -# define SIGSTKSZ 262144 -# else -# define SIGSTKSZ 16384 -# endif -#endif -#ifndef SIGSTKSZ -# define SIGSTKSZ 16384 -#endif -volatile char *stack_lower_bound; -volatile char *stack_upper_bound; -static void check_stack_location (volatile char *addr) -{ - if (addr >= stack_lower_bound && addr <= stack_upper_bound) - exit (0); - else - exit (1); -} -static void stackoverflow_handler (int sig) -{ - char dummy; - check_stack_location (&dummy); -} -int main () -{ - char mystack[2 * SIGSTKSZ]; - stack_t altstack; - struct sigaction action; - /* Install the alternate stack. */ - altstack.ss_sp = mystack + SIGSTKSZ; - altstack.ss_size = SIGSTKSZ; - stack_lower_bound = (char *) altstack.ss_sp; - stack_upper_bound = (char *) altstack.ss_sp + altstack.ss_size - 1; - altstack.ss_flags = 0; /* no SS_DISABLE */ - if (sigaltstack (&altstack, NULL) < 0) - exit (2); - /* Install the SIGSEGV handler. */ - sigemptyset (&action.sa_mask); - action.sa_handler = &stackoverflow_handler; - action.sa_flags = SA_ONSTACK; - if (sigaction (SIGSEGV, &action, (struct sigaction *) NULL) < 0) - exit(3); - /* Provoke a SIGSEGV. */ - raise (SIGSEGV); - exit (4); -}]])], - [gl_cv_sigaltstack_low_base=yes], - [gl_cv_sigaltstack_low_base=no], - [gl_cv_sigaltstack_low_base=cross-compiling])]) - if test "$gl_cv_sigaltstack_low_base" = no; then - AC_DEFINE([SIGALTSTACK_SS_REVERSED], [1], - [Define if sigaltstack() interprets the stack_t.ss_sp field - incorrectly, as the highest address of the alternate stack range - 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. - 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 - ;; - *) - AC_RUN_IFELSE( - [AC_LANG_SOURCE( - [[ - #include - #include - #if HAVE_UCONTEXT_H - # include - #endif - #if HAVE_SETRLIMIT - # include - # include - # include - #endif - /* In glibc >= 2.34, when _GNU_SOURCE is defined, SIGSTKSZ is - no longer a compile-time constant. But we need a simple - constant here. */ - #if __GLIBC__ >= 2 - # undef SIGSTKSZ - # if defined __ia64__ - # define SIGSTKSZ 262144 - # else - # define SIGSTKSZ 16384 - # endif - #endif - #ifndef SIGSTKSZ - # define SIGSTKSZ 16384 - #endif - - static union - { - char buffer[2 * SIGSTKSZ]; - long double ld; - long u; - void *p; - } alternate_signal_stack; - - #if STACK_DIRECTION - # define find_stack_direction(ptr) STACK_DIRECTION - #else - static int - find_stack_direction (char const *addr) - { - char dummy; - return (! addr ? find_stack_direction (&dummy) - : addr < &dummy ? 1 : -1); - } - #endif - - static void - segv_handler (int signo, siginfo_t *info, void *context) - { - if (0 < info->si_code) - { - /* For XSI heuristics to work, we need uc_stack to - describe the interrupted stack (as on Solaris), and - not the currently executing stack (as on Linux). */ - ucontext_t const *user_context = context; - char const *stack_min = user_context->uc_stack.ss_sp; - size_t stack_size = user_context->uc_stack.ss_size; - char const *faulting_address = info->si_addr; - size_t s = faulting_address - stack_min; - size_t page_size = sysconf (_SC_PAGESIZE); - if (find_stack_direction (0) < 0) - s += page_size; - if (s < stack_size + page_size) - _exit (0); - _exit (4); - } - _exit (5); - } - - static int - c_stack_action () - { - stack_t st; - struct sigaction act; - int r; - - st.ss_flags = 0; - /* Use the midpoint to avoid Irix sigaltstack bug. */ - st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ; - st.ss_size = SIGSTKSZ; - r = sigaltstack (&st, 0); - if (r != 0) - return 1; - - sigemptyset (&act.sa_mask); - act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO; - act.sa_sigaction = segv_handler; - #if FAULT_YIELDS_SIGBUS - if (sigaction (SIGBUS, &act, 0) < 0) - return 2; - #endif - if (sigaction (SIGSEGV, &act, 0) < 0) - return 3; - return 0; - } - static volatile int * - recurse_1 (volatile int n, volatile int *p) - { - if (n >= 0) - *recurse_1 (n + 1, p) += n; - return p; - } - static int - recurse (volatile int n) - { - int sum = 0; - return *recurse_1 (n, &sum); - } - int - main () - { - int result; - #if HAVE_SETRLIMIT && defined RLIMIT_STACK - /* Before starting the endless recursion, try to be friendly - to the user's machine. On some Linux 2.2.x systems, there - is no stack limit for user processes at all. We don't want - to kill such systems. */ - struct rlimit rl; - rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */ - setrlimit (RLIMIT_STACK, &rl); - #endif - - result = c_stack_action (); - if (result != 0) - return result; - return recurse (0); - } - ]])], - [gl_cv_sys_xsi_stack_overflow_heuristic=yes], - [gl_cv_sys_xsi_stack_overflow_heuristic=no], - [gl_cv_sys_xsi_stack_overflow_heuristic=cross-compiling]) - ;; - esac - ]) - - if test "$gl_cv_sys_xsi_stack_overflow_heuristic" = yes; then - AC_DEFINE([HAVE_XSI_STACK_OVERFLOW_HEURISTIC], [1], - [Define to 1 if extending the stack slightly past the limit causes - a SIGSEGV, and an alternate stack can be established with sigaltstack, - and the signal handler is passed a context that specifies the - run time stack. This behavior is defined by POSIX 1003.1-2001 - with the X/Open System Interface (XSI) option - and is a standardized way to implement a SEGV-based stack - overflow detection heuristic.]) - fi - fi]) - - -AC_DEFUN([gl_PREREQ_C_STACK], - [AC_REQUIRE([AC_SYS_XSI_STACK_OVERFLOW_HEURISTIC]) - - AC_CHECK_FUNCS_ONCE([sigaltstack]) - AC_CHECK_DECLS([sigaltstack], , , [[#include ]]) - - AC_CHECK_HEADERS_ONCE([ucontext.h]) - - AC_CHECK_TYPES([stack_t], , , [[#include ]]) - - dnl c-stack does not need -lsigsegv if the system has XSI heuristics. - if test "$gl_cv_sys_xsi_stack_overflow_heuristic" != yes; then - gl_LIBSIGSEGV - if test "$gl_cv_lib_sigsegv" = yes; then - AC_SUBST([LIBCSTACK], [$LIBSIGSEGV]) - AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV]) - fi - fi -]) +# serial 23 AC_DEFUN([gl_C_STACK], [ - dnl Prerequisites of lib/c-stack.c. - gl_PREREQ_C_STACK + dnl 'c-stack' needs -lsigsegv if and only if the 'sigsegv' module needs it. + if test "$with_libsigsegv" = yes; then + if test "$gl_cv_lib_sigsegv" = yes; then + AC_SUBST([LIBCSTACK], [$LIBSIGSEGV]) + AC_SUBST([LTLIBCSTACK], [$LTLIBSIGSEGV]) + fi + fi ]) diff --git a/modules/c-stack b/modules/c-stack index 4c80f31..32a4120 100644 --- a/modules/c-stack +++ b/modules/c-stack @@ -5,7 +5,6 @@ Files: lib/c-stack.h lib/c-stack.c m4/c-stack.m4 -m4/libsigsegv.m4 Depends-on: c99 @@ -13,15 +12,10 @@ errno exitfail getprogname gettext-h -havelib idx ignore-value -intprops -inttypes -mempcpy raise -sigaction -stdbool +sigsegv stddef unistd -- 2.7.4 --nextPart7579430.Bj6nBJWQ3l--