(root)/
glibc-2.38/
debug/
tst-longjmp_chk2.c
       1  /* Verify longjmp fortify checking does not reject signal stacks.  */
       2  #include <assert.h>
       3  #include <setjmp.h>
       4  #include <signal.h>
       5  #include <stdio.h>
       6  #include <stdlib.h>
       7  #include <string.h>
       8  #include <sys/types.h>
       9  #include <sys/time.h>
      10  #include <sys/resource.h>
      11  #include <unistd.h>
      12  
      13  static int do_test (void);
      14  #define TEST_FUNCTION do_test ()
      15  #include "../test-skeleton.c"
      16  
      17  static jmp_buf mainloop;
      18  static sigset_t mainsigset;
      19  static volatile sig_atomic_t pass;
      20  
      21  static void
      22  write_indented (const char *str)
      23  {
      24    for (int i = 0; i < pass; ++i)
      25      write_message (" ");
      26    write_message (str);
      27  }
      28  
      29  static void
      30  stackoverflow_handler (int sig)
      31  {
      32    stack_t altstack;
      33    /* Sanity check to keep test from looping forever (in case the longjmp
      34       chk code is slightly broken).  */
      35    pass++;
      36    sigaltstack (NULL, &altstack);
      37    write_indented ("in signal handler\n");
      38    if (altstack.ss_flags & SS_ONSTACK)
      39      write_indented ("on alternate stack\n");
      40    siglongjmp (mainloop, pass);
      41  }
      42  
      43  
      44  static volatile int *
      45  recurse_1 (int n, volatile int *p)
      46  {
      47    if (n >= 0)
      48      *recurse_1 (n + 1, p) += n;
      49    return p;
      50  }
      51  
      52  
      53  static int
      54  recurse (int n)
      55  {
      56    int sum = 0;
      57    return *recurse_1 (n, &sum);
      58  }
      59  
      60  
      61  static int
      62  do_test (void)
      63  {
      64    char mystack[SIGSTKSZ];
      65    stack_t altstack;
      66    struct sigaction action;
      67    sigset_t emptyset;
      68    /* Before starting the endless recursion, try to be friendly to the user's
      69       machine.  On some Linux 2.2.x systems, there is no stack limit for user
      70       processes at all.  We don't want to kill such systems.  */
      71    struct rlimit rl;
      72    rl.rlim_cur = rl.rlim_max = 0x100000; /* 1 MB */
      73    setrlimit (RLIMIT_STACK, &rl);
      74    /* Install the alternate stack.  */
      75    altstack.ss_sp = mystack;
      76    altstack.ss_size = sizeof (mystack);
      77    altstack.ss_flags = 0; /* no SS_DISABLE */
      78    if (sigaltstack (&altstack, NULL) < 0)
      79      {
      80        puts ("first sigaltstack failed");
      81        return 0;
      82      }
      83    /* Install the SIGSEGV handler.  */
      84    sigemptyset (&action.sa_mask);
      85    action.sa_handler = &stackoverflow_handler;
      86    action.sa_flags = SA_ONSTACK;
      87    sigaction (SIGSEGV, &action, (struct sigaction *) NULL);
      88    sigaction (SIGBUS, &action, (struct sigaction *) NULL);
      89  
      90    /* Save the current signal mask.  */
      91    sigemptyset (&emptyset);
      92    sigprocmask (SIG_BLOCK, &emptyset, &mainsigset);
      93  
      94    /* Provoke two stack overflows in a row.  */
      95    if (sigsetjmp (mainloop, 1) != 0)
      96      {
      97        assert (pass != 0);
      98        printf ("%*sout of signal handler\n", pass, "");
      99      }
     100    else
     101      assert (pass == 0);
     102  
     103    sigaltstack (NULL, &altstack);
     104    if (altstack.ss_flags & SS_ONSTACK)
     105      printf ("%*son alternate stack\n", pass, "");
     106    else
     107      printf ("%*snot on alternate stack\n", pass, "");
     108  
     109    if (pass < 2)
     110      {
     111        recurse (0);
     112        puts ("recurse call returned");
     113        return 2;
     114      }
     115  
     116    altstack.ss_flags |= SS_DISABLE;
     117    if (sigaltstack (&altstack, NULL) == -1)
     118      printf ("disabling alternate stack failed\n");
     119    else
     120      printf ("disabling alternate stack succeeded \n");
     121  
     122    /* Restore the signal handlers, in case we trigger a crash after the
     123       tests above.  */
     124    signal (SIGBUS, SIG_DFL);
     125    signal (SIGSEGV, SIG_DFL);
     126  
     127    return 0;
     128  }