Blame debug/tst-longjmp_chk2.c

Packit Service 82fcde
/* Verify longjmp fortify checking does not reject signal stacks.
Packit Service 82fcde
Packit Service 82fcde
   Test case mostly written by Paolo Bonzini <pbonzini@redhat.com>.  */
Packit Service 82fcde
#include <assert.h>
Packit Service 82fcde
#include <setjmp.h>
Packit Service 82fcde
#include <signal.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
#include <sys/time.h>
Packit Service 82fcde
#include <sys/resource.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
Packit Service 82fcde
static int do_test (void);
Packit Service 82fcde
#define TEST_FUNCTION do_test ()
Packit Service 82fcde
#include "../test-skeleton.c"
Packit Service 82fcde
Packit Service 82fcde
static jmp_buf mainloop;
Packit Service 82fcde
static sigset_t mainsigset;
Packit Service 82fcde
static volatile sig_atomic_t pass;
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
write_indented (const char *str)
Packit Service 82fcde
{
Packit Service 82fcde
  for (int i = 0; i < pass; ++i)
Packit Service 82fcde
    write_message (" ");
Packit Service 82fcde
  write_message (str);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
stackoverflow_handler (int sig)
Packit Service 82fcde
{
Packit Service 82fcde
  stack_t altstack;
Packit Service 82fcde
  /* Sanity check to keep test from looping forever (in case the longjmp
Packit Service 82fcde
     chk code is slightly broken).  */
Packit Service 82fcde
  pass++;
Packit Service 82fcde
  sigaltstack (NULL, &altstack);
Packit Service 82fcde
  write_indented ("in signal handler\n");
Packit Service 82fcde
  if (altstack.ss_flags & SS_ONSTACK)
Packit Service 82fcde
    write_indented ("on alternate stack\n");
Packit Service 82fcde
  siglongjmp (mainloop, pass);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static volatile int *
Packit Service 82fcde
recurse_1 (int n, volatile int *p)
Packit Service 82fcde
{
Packit Service 82fcde
  if (n >= 0)
Packit Service 82fcde
    *recurse_1 (n + 1, p) += n;
Packit Service 82fcde
  return p;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
recurse (int n)
Packit Service 82fcde
{
Packit Service 82fcde
  int sum = 0;
Packit Service 82fcde
  return *recurse_1 (n, &sum);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
do_test (void)
Packit Service 82fcde
{
Packit Service 82fcde
  char mystack[SIGSTKSZ];
Packit Service 82fcde
  stack_t altstack;
Packit Service 82fcde
  struct sigaction action;
Packit Service 82fcde
  sigset_t emptyset;
Packit Service 82fcde
  /* Before starting the endless recursion, try to be friendly to the user's
Packit Service 82fcde
     machine.  On some Linux 2.2.x systems, there is no stack limit for user
Packit Service 82fcde
     processes at all.  We don't want to kill such systems.  */
Packit Service 82fcde
  struct rlimit rl;
Packit Service 82fcde
  rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
Packit Service 82fcde
  setrlimit (RLIMIT_STACK, &rl);
Packit Service 82fcde
  /* Install the alternate stack.  */
Packit Service 82fcde
  altstack.ss_sp = mystack;
Packit Service 82fcde
  altstack.ss_size = sizeof (mystack);
Packit Service 82fcde
  altstack.ss_flags = 0; /* no SS_DISABLE */
Packit Service 82fcde
  if (sigaltstack (&altstack, NULL) < 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("first sigaltstack failed");
Packit Service 82fcde
      return 0;
Packit Service 82fcde
    }
Packit Service 82fcde
  /* Install the SIGSEGV handler.  */
Packit Service 82fcde
  sigemptyset (&action.sa_mask);
Packit Service 82fcde
  action.sa_handler = &stackoverflow_handler;
Packit Service 82fcde
  action.sa_flags = SA_ONSTACK;
Packit Service 82fcde
  sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
Packit Service 82fcde
  sigaction (SIGBUS, &action, (struct sigaction *) NULL);
Packit Service 82fcde
Packit Service 82fcde
  /* Save the current signal mask.  */
Packit Service 82fcde
  sigemptyset (&emptyset);
Packit Service 82fcde
  sigprocmask (SIG_BLOCK, &emptyset, &mainsigset);
Packit Service 82fcde
Packit Service 82fcde
  /* Provoke two stack overflows in a row.  */
Packit Service 82fcde
  if (sigsetjmp (mainloop, 1) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      assert (pass != 0);
Packit Service 82fcde
      printf ("%*sout of signal handler\n", pass, "");
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    assert (pass == 0);
Packit Service 82fcde
Packit Service 82fcde
  sigaltstack (NULL, &altstack);
Packit Service 82fcde
  if (altstack.ss_flags & SS_ONSTACK)
Packit Service 82fcde
    printf ("%*son alternate stack\n", pass, "");
Packit Service 82fcde
  else
Packit Service 82fcde
    printf ("%*snot on alternate stack\n", pass, "");
Packit Service 82fcde
Packit Service 82fcde
  if (pass < 2)
Packit Service 82fcde
    {
Packit Service 82fcde
      recurse (0);
Packit Service 82fcde
      puts ("recurse call returned");
Packit Service 82fcde
      return 2;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  altstack.ss_flags |= SS_DISABLE;
Packit Service 82fcde
  if (sigaltstack (&altstack, NULL) == -1)
Packit Service 82fcde
    printf ("disabling alternate stack failed\n");
Packit Service 82fcde
  else
Packit Service 82fcde
    printf ("disabling alternate stack succeeded \n");
Packit Service 82fcde
Packit Service 82fcde
  /* Restore the signal handlers, in case we trigger a crash after the
Packit Service 82fcde
     tests above.  */
Packit Service 82fcde
  signal (SIGBUS, SIG_DFL);
Packit Service 82fcde
  signal (SIGSEGV, SIG_DFL);
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}