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 * NAME
22 * kill07.c
23 *
24 * DESCRIPTION
25 * Test case to check that SIGKILL can not be caught.
26 *
27 * ALGORITHM
28 * call setup
29 * setup some shared memory
30 * loop if the -i option was given
31 * set up to catch SIGKILL
32 * if SIGKILL is caught set the shared memory flag.
33 * fork a child
34 * execute the kill system call
35 * check the return value
36 * if return value is -1
37 * issue a FAIL message, break remaining tests and cleanup
38 * if we are doing functional testing
39 * if the process was terminated with the expected signal and the
40 * signal was not caught.
41 * issue a PASS message
42 * otherwise
43 * issue a FAIL message
44 * call cleanup
45 *
46 * USAGE
47 * kill07 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
48 * where, -c n : Run n copies concurrently.
49 * -f : Turn off functionality Testing.
50 * -i n : Execute test n times.
51 * -I x : Execute test for x seconds.
52 * -P x : Pause for x seconds between iterations.
53 * -t : Turn on syscall timing.
54 *
55 * HISTORY
56 * 07/2001 Ported by Wayne Boyer
57 *
58 * RESTRICTIONS
59 * This test should be run as a non-root user.
60 */
61
62 #include "test.h"
63
64 #include <signal.h>
65 #include <errno.h>
66 #include <sys/ipc.h>
67 #include <sys/shm.h>
68 #include <sys/wait.h>
69
70 void cleanup(void);
71 void setup(void);
72 void sighandler(int sig);
73 void do_child(void);
74
75 char *TCID = "kill07";
76 int TST_TOTAL = 1;
77 int shmid1;
78 extern key_t semkey;
79 int *flag;
80
81 extern int getipckey();
82 extern void rm_shm(int);
83
84 #define TEST_SIG SIGKILL
85
main(int ac,char ** av)86 int main(int ac, char **av)
87 {
88 int lc;
89 pid_t pid;
90 int exno, status, nsig, asig, ret;
91 struct sigaction my_act, old_act;
92
93 tst_parse_opts(ac, av, NULL, NULL);
94 #ifdef UCLINUX
95 maybe_run_child(&do_child, "");
96 #endif
97
98 setup(); /* global setup */
99
100 /* The following loop checks looping state if -i option given */
101 for (lc = 0; TEST_LOOPING(lc); lc++) {
102
103 /* reset tst_count in case we are looping */
104 tst_count = 0;
105 status = 1;
106 exno = 1;
107 my_act.sa_handler = sighandler;
108 my_act.sa_flags = SA_RESTART;
109 sigemptyset(&my_act.sa_mask);
110
111 if ((shmid1 = shmget(semkey, (int)getpagesize(),
112 0666 | IPC_CREAT)) == -1) {
113 tst_brkm(TBROK, cleanup,
114 "Failed to setup shared memory");
115 }
116
117 if (*(flag = shmat(shmid1, 0, 0)) == -1) {
118 tst_brkm(TBROK, cleanup,
119 "Failed to attatch shared memory:%d", *flag);
120 }
121
122 *flag = 0;
123
124 /* setup the signal handler */
125 ret = sigaction(TEST_SIG, &my_act, &old_act);
126
127 pid = FORK_OR_VFORK();
128 if (pid < 0) {
129 tst_brkm(TBROK, cleanup, "Fork of child failed");
130 } else if (pid == 0) {
131 #ifdef UCLINUX
132 if (self_exec(av[0], "") < 0) {
133 tst_brkm(TBROK, cleanup,
134 "self_exec of child failed");
135 }
136 #else
137 do_child();
138 #endif
139 } else {
140 /* sighandler should not catch this signal */
141 /* if it does flag will be set to 1 */
142 sleep(1);
143 TEST(kill(pid, TEST_SIG));
144 waitpid(pid, &status, 0);
145 }
146
147 if (TEST_RETURN == -1) {
148 tst_brkm(TFAIL, cleanup, "%s failed - errno = %d : %s",
149 TCID, TEST_ERRNO, strerror(TEST_ERRNO));
150 }
151
152 /*
153 * Check to see if the process was terminated with the
154 * expected signal.
155 */
156 nsig = WTERMSIG(status);
157 asig = WIFSIGNALED(status);
158 if ((asig == 0) & (*flag == 1)) {
159 tst_resm(TFAIL, "SIGKILL was unexpectedly"
160 " caught");
161 } else if ((asig == 1) & (nsig == TEST_SIG)) {
162 tst_resm(TINFO, "received expected signal %d",
163 nsig);
164 tst_resm(TPASS,
165 "Did not catch signal as expected");
166 } else if (nsig) {
167 tst_resm(TFAIL,
168 "expected signal %d received %d",
169 TEST_SIG, nsig);
170 } else {
171 tst_resm(TFAIL, "No signals received");
172 }
173
174 if (shmdt(flag)) {
175 tst_brkm(TBROK, cleanup, "shmdt failed ");
176 }
177 }
178
179 cleanup();
180 tst_exit();
181 }
182
183 /*
184 * sighandler() - try to catch SIGKILL
185 */
186
sighandler(int sig)187 void sighandler(int sig)
188 {
189 /* do nothing */
190 *flag = 1;
191 return;
192 }
193
194 /*
195 * do_child()
196 */
do_child(void)197 void do_child(void)
198 {
199 int exno = 1;
200
201 sleep(300);
202 tst_resm(TINFO, "Child never recieved a signal");
203 exit(exno);
204 }
205
206 /*
207 * setup() - performs all ONE TIME setup for this test
208 */
setup(void)209 void setup(void)
210 {
211
212 TEST_PAUSE;
213
214 /*
215 * Create a temporary directory and cd into it.
216 * This helps to ensure that a unique msgkey is created.
217 * See ../lib/libipc.c for more information.
218 */
219 tst_tmpdir();
220
221 /* get an IPC resource key */
222 semkey = getipckey();
223
224 }
225
226 /*
227 * cleanup() - performs all the ONE TIME cleanup for this test at completion
228 * or premature exit.
229 */
cleanup(void)230 void cleanup(void)
231 {
232
233 /*
234 * remove the shared memory
235 */
236 rm_shm(shmid1);
237
238 tst_rmdir();
239
240 }
241