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

source code of glibc/debug/tst-longjmp_chk2.c