]> git.ipfire.org Git - thirdparty/glibc.git/blame - debug/tst-longjmp_chk2.c
nptl/tst-cancel25 needs to be an internal test
[thirdparty/glibc.git] / debug / tst-longjmp_chk2.c
CommitLineData
5896c8bd
MF
1/* Verify longjmp fortify checking does not reject signal stacks.
2
3 Test case mostly written by Paolo Bonzini <pbonzini@redhat.com>. */
a9a04420
UD
4#include <assert.h>
5#include <setjmp.h>
6#include <signal.h>
7#include <stdio.h>
8#include <stdlib.h>
2c41b529 9#include <string.h>
a9a04420
UD
10#include <sys/types.h>
11#include <sys/time.h>
12#include <sys/resource.h>
2c41b529 13#include <unistd.h>
a9a04420 14
14699b6e
FW
15static int do_test (void);
16#define TEST_FUNCTION do_test ()
17#include "../test-skeleton.c"
a9a04420
UD
18
19static jmp_buf mainloop;
20static sigset_t mainsigset;
2c41b529 21static volatile sig_atomic_t pass;
a9a04420 22
2c41b529 23static void
14699b6e 24write_indented (const char *str)
2c41b529 25{
2c41b529 26 for (int i = 0; i < pass; ++i)
14699b6e
FW
27 write_message (" ");
28 write_message (str);
2c41b529 29}
a9a04420
UD
30
31static void
32stackoverflow_handler (int sig)
33{
34 stack_t altstack;
5896c8bd
MF
35 /* Sanity check to keep test from looping forever (in case the longjmp
36 chk code is slightly broken). */
a9a04420
UD
37 pass++;
38 sigaltstack (NULL, &altstack);
14699b6e 39 write_indented ("in signal handler\n");
a9a04420 40 if (altstack.ss_flags & SS_ONSTACK)
14699b6e 41 write_indented ("on alternate stack\n");
a9a04420
UD
42 siglongjmp (mainloop, pass);
43}
44
45
46static volatile int *
47recurse_1 (int n, volatile int *p)
48{
49 if (n >= 0)
50 *recurse_1 (n + 1, p) += n;
51 return p;
52}
53
54
55static int
56recurse (int n)
57{
58 int sum = 0;
59 return *recurse_1 (n, &sum);
60}
61
62
63static int
64do_test (void)
65{
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)
81 {
82 puts ("first sigaltstack failed");
83 return 0;
84 }
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);
91
92 /* Save the current signal mask. */
93 sigemptyset (&emptyset);
94 sigprocmask (SIG_BLOCK, &emptyset, &mainsigset);
95
96 /* Provoke two stack overflows in a row. */
97 if (sigsetjmp (mainloop, 1) != 0)
98 {
99 assert (pass != 0);
100 printf ("%*sout of signal handler\n", pass, "");
101 }
102 else
103 assert (pass == 0);
104
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, "");
110
111 if (pass < 2)
112 {
113 recurse (0);
114 puts ("recurse call returned");
115 return 2;
116 }
117
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");
123
2c41b529
FW
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);
128
a9a04420
UD
129 return 0;
130}