• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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