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 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 */ 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 */ 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 */ 233 void cleanup(void) 234 { 235 236 free(sigstk.ss_sp); 237 238 } 239