Add test case for ____longjmp_chk vs signal stacks.

This commit is contained in:
Ulrich Drepper 2009-07-30 17:48:58 -07:00
parent 5ead9ce5c7
commit a9a0442081
3 changed files with 119 additions and 1 deletions

View File

@ -1,5 +1,8 @@
2009-07-30 Ulrich Drepper <drepper@redhat.com>
* debug/Makefile (tests): Add tst-longjmp_chk2.
* debug/tst-longjmp_chk2.c: New file.
* sysdeps/x86_64/__longjmp.S: Remove CHECK_RSP handling. Fix CFI.
Remove incorrect use of BP_SYM.
* sysdeps/x86_64/____longjmp_chk.S: Rewrite. Complete implementation

View File

@ -118,7 +118,8 @@ LDFLAGS-tst-lfschk6 = -lstdc++
tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \
tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \
tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6
tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \
tst-longjmp_chk2
extra-libs = libSegFault libpcprofile
extra-libs-others = $(extra-libs)

114
debug/tst-longjmp_chk2.c Normal file
View File

@ -0,0 +1,114 @@
/* Test case mostly written by Paolo Bonzini <pbonzini@redhat.com>. */
#include <assert.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
static jmp_buf mainloop;
static sigset_t mainsigset;
static int pass;
static void
stackoverflow_handler (int sig)
{
stack_t altstack;
pass++;
sigaltstack (NULL, &altstack);
/* Using printf is not really kosher in signal handlers but we know
it will work. */
printf ("%*sin signal handler\n", pass, "");
if (altstack.ss_flags & SS_ONSTACK)
printf ("%*son alternate stack\n", pass, "");
siglongjmp (mainloop, pass);
}
static volatile int *
recurse_1 (int n, volatile int *p)
{
if (n >= 0)
*recurse_1 (n + 1, p) += n;
return p;
}
static int
recurse (int n)
{
int sum = 0;
return *recurse_1 (n, &sum);
}
static int
do_test (void)
{
char mystack[SIGSTKSZ];
stack_t altstack;
struct sigaction action;
sigset_t emptyset;
/* 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);
/* Install the alternate stack. */
altstack.ss_sp = mystack;
altstack.ss_size = sizeof (mystack);
altstack.ss_flags = 0; /* no SS_DISABLE */
if (sigaltstack (&altstack, NULL) < 0)
{
puts ("first sigaltstack failed");
return 0;
}
/* Install the SIGSEGV handler. */
sigemptyset (&action.sa_mask);
action.sa_handler = &stackoverflow_handler;
action.sa_flags = SA_ONSTACK;
sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
sigaction (SIGBUS, &action, (struct sigaction *) NULL);
/* Save the current signal mask. */
sigemptyset (&emptyset);
sigprocmask (SIG_BLOCK, &emptyset, &mainsigset);
/* Provoke two stack overflows in a row. */
if (sigsetjmp (mainloop, 1) != 0)
{
assert (pass != 0);
printf ("%*sout of signal handler\n", pass, "");
}
else
assert (pass == 0);
sigaltstack (NULL, &altstack);
if (altstack.ss_flags & SS_ONSTACK)
printf ("%*son alternate stack\n", pass, "");
else
printf ("%*snot on alternate stack\n", pass, "");
if (pass < 2)
{
recurse (0);
puts ("recurse call returned");
return 2;
}
altstack.ss_flags |= SS_DISABLE;
if (sigaltstack (&altstack, NULL) == -1)
printf ("disabling alternate stack failed\n");
else
printf ("disabling alternate stack succeeded \n");
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"