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