1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * Test Name: sigalstack01
22 *
23 * Test Description:
24 * Send a signal using the main stack. While executing the signal handler
25 * compare a variable's address lying on the main stack with the stack
26 * boundaries returned by sigaltstack().
27 *
28 * Expected Result:
29 * sigaltstack() should succeed to get/set signal alternate stack context.
30 *
31 * Algorithm:
32 * Setup:
33 * Setup signal handling.
34 * Pause for SIGUSR1 if option specified.
35 *
36 * Test:
37 * Loop if the proper options are given.
38 * Execute system call
39 * Check return code, if system call failed (return=-1)
40 * Log the errno and Issue a FAIL message.
41 * Otherwise,
42 * Verify the Functionality of system call
43 * if successful,
44 * Issue Functionality-Pass message.
45 * Otherwise,
46 * Issue Functionality-Fail message.
47 * Cleanup:
48 * Print errno log and/or timing stats if options given
49 *
50 * Usage: <for command-line>
51 * sigaltstack01 [-c n] [-e] [-f] [-i n] [-I x] [-p x] [-t]
52 * where, -c n : Run n copies concurrently.
53 * -e : Turn on errno logging.
54 * -f : Turn off functionality Testing.
55 * -i n : Execute test n times.
56 * -I x : Execute test for x seconds.
57 * -P x : Pause for x seconds between iterations.
58 * -t : Turn on syscall timing.
59 *
60 * History
61 * 07/2001 John George
62 * -Ported
63 *
64 * Restrictions:
65 * This test should be run by 'super-user' (root) only and must run from
66 * shell which sets up for test.
67 *
68 */
69
70 #include <stdio.h>
71 #include <sys/types.h>
72 #include <unistd.h>
73 #include <signal.h>
74 #include <string.h>
75 #include <ucontext.h>
76 #include <errno.h>
77
78 #include "test.h"
79
80 char *TCID = "sigaltstack01";
81 int TST_TOTAL = 1;
82
83 void *addr, *main_stk; /* address of main stack for signal */
84 int got_signal = 0;
85 pid_t my_pid; /* test process id */
86
87 stack_t sigstk, osigstk; /* signal stack storing struct. */
88 struct sigaction act, oact; /* sigaction() struct. */
89
90 void setup(void); /* Main setup function of test */
91 void cleanup(void); /* cleanup function for the test */
92 void sig_handler(int); /* signal catching function */
93
main(int ac,char ** av)94 int main(int ac, char **av)
95 {
96 int lc;
97 void *alt_stk; /* address of alternate stack for signal */
98
99 tst_parse_opts(ac, av, NULL, NULL);
100
101 setup();
102
103 for (lc = 0; TEST_LOOPING(lc); lc++) {
104
105 tst_count = 0;
106
107 /* Call sigaltstack() to set up an alternate stack */
108 sigstk.ss_size = SIGSTKSZ;
109 sigstk.ss_flags = 0;
110 TEST(sigaltstack(&sigstk, &osigstk));
111
112 if (TEST_RETURN == -1) {
113 tst_resm(TFAIL,
114 "sigaltstack() Failed, errno=%d : %s",
115 TEST_ERRNO, strerror(TEST_ERRNO));
116 } else {
117 /* Set up the signal handler for 'SIGUSR1' */
118 act.sa_flags = SA_ONSTACK;
119 act.sa_handler = (void (*)())sig_handler;
120 if ((sigaction(SIGUSR1, &act, &oact)) == -1) {
121 tst_brkm(TFAIL, cleanup, "sigaction() "
122 "fails to trap signal "
123 "delivered on alt. stack, "
124 "error=%d", errno);
125 }
126
127 /* Deliver signal onto the alternate stack */
128 kill(my_pid, SIGUSR1);
129
130 /* wait till the signal arrives */
131 while (!got_signal) ;
132
133 got_signal = 0;
134 alt_stk = addr;
135
136 /*
137 * First,
138 * Check that alt_stk is within the
139 * alternate stk boundaries
140 *
141 * Second,
142 * Check that main_stk is outside the
143 * alternate stk boundaries.
144 */
145 if ((alt_stk < sigstk.ss_sp) &&
146 (alt_stk > (sigstk.ss_sp + SIGSTKSZ))) {
147 tst_resm(TFAIL,
148 "alt. stack is not within the "
149 "alternate stk boundaries");
150 } else if ((main_stk >= sigstk.ss_sp) &&
151 (main_stk <=
152 (sigstk.ss_sp + SIGSTKSZ))) {
153 tst_resm(TFAIL,
154 "main stk. not outside the "
155 "alt. stack boundaries");
156 } else {
157 tst_resm(TPASS,
158 "Functionality of "
159 "sigaltstack() successful");
160 }
161 }
162 tst_count++; /* incr. TEST_LOOP counter */
163 }
164
165 cleanup();
166 tst_exit();
167 }
168
169 /*
170 * void
171 * setup() - performs all ONE TIME setup for this test.
172 * Capture SIGUSR1 on the main stack.
173 * send the signal 'SIGUSER1' to the process.
174 * wait till the signal arrives.
175 * Allocate memory for the alternative stack.
176 */
setup(void)177 void setup(void)
178 {
179
180 tst_sig(FORK, DEF_HANDLER, cleanup);
181
182 TEST_PAUSE;
183
184 /* Get the process id of test process */
185 my_pid = getpid();
186
187 /* Capture SIGUSR1 on the main stack */
188 act.sa_handler = (void (*)(int))sig_handler;
189 if ((sigaction(SIGUSR1, &act, &oact)) == -1) {
190 tst_brkm(TFAIL, cleanup,
191 "sigaction() fails in setup, errno=%d", errno);
192 }
193
194 /* Send the signal to the test process */
195 kill(my_pid, SIGUSR1);
196
197 /* Wait till the signal arrives */
198 while (!got_signal) ;
199
200 got_signal = 0;
201 main_stk = addr;
202
203 /* Allocate memory for the alternate stack */
204 if ((sigstk.ss_sp = malloc(SIGSTKSZ)) == NULL) {
205 tst_brkm(TFAIL, cleanup,
206 "could not allocate memory for the alternate stack");
207 }
208 }
209
210 /*
211 * void
212 * sig_handler() - signal catching function.
213 * This functions is called when the signal 'SIGUSR1' is delivered to
214 * the test process and trapped by sigaction().
215 *
216 * This function updates 'addr' variable and sets got_signal value.
217 */
sig_handler(int n)218 void sig_handler(int n)
219 {
220 int i;
221
222 (void) n;
223 addr = &i;
224 got_signal = 1;
225 }
226
227 /*
228 * void
229 * cleanup() - performs all ONE TIME cleanup for this test at
230 * completion or premature exit.
231 * Free the memory allocated for alternate stack.
232 */
cleanup(void)233 void cleanup(void)
234 {
235
236 free(sigstk.ss_sp);
237
238 }
239