summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_kill.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libc/sys/t_kill.c')
-rw-r--r--src/regress/lib/libc/sys/t_kill.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/src/regress/lib/libc/sys/t_kill.c b/src/regress/lib/libc/sys/t_kill.c
new file mode 100644
index 0000000000..c92bbdd18b
--- /dev/null
+++ b/src/regress/lib/libc/sys/t_kill.c
@@ -0,0 +1,316 @@
1/* $OpenBSD: t_kill.c,v 1.1.1.1 2019/11/19 19:57:03 bluhm Exp $ */
2/* $NetBSD: t_kill.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
3
4/*-
5 * Copyright (c) 2011 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jukka Ruohonen.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "macros.h"
34
35#include <sys/cdefs.h>
36__RCSID("$NetBSD: t_kill.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
37
38#include <sys/wait.h>
39
40#include <errno.h>
41#include <limits.h>
42#include <pwd.h>
43#include <signal.h>
44#include <stdlib.h>
45#include <unistd.h>
46
47#include "atf-c.h"
48
49ATF_TC(kill_basic);
50ATF_TC_HEAD(kill_basic, tc)
51{
52 atf_tc_set_md_var(tc, "descr", "Test that kill(2) works");
53}
54
55ATF_TC_BODY(kill_basic, tc)
56{
57 const int sig[] = { SIGHUP, SIGINT, SIGKILL, SIGTERM };
58 pid_t pid;
59 size_t i;
60 int sta;
61
62 for (i = 0; i < __arraycount(sig); i++) {
63
64 pid = fork();
65 ATF_REQUIRE(pid >= 0);
66
67 switch (pid) {
68
69 case 0:
70 pause();
71 break;
72
73 default:
74 ATF_REQUIRE(kill(pid, sig[i]) == 0);
75 }
76
77 (void)wait(&sta);
78
79 if (WIFSIGNALED(sta) == 0 || WTERMSIG(sta) != sig[i])
80 atf_tc_fail("kill(2) failed to kill child");
81 }
82}
83
84ATF_TC(kill_err);
85ATF_TC_HEAD(kill_err, tc)
86{
87 atf_tc_set_md_var(tc, "descr", "Test error conditions of kill(2)");
88}
89
90ATF_TC_BODY(kill_err, tc)
91{
92 int rv, sta;
93 pid_t pid;
94
95 pid = fork();
96 ATF_REQUIRE(pid >= 0);
97
98 if (pid == 0) {
99
100 errno = 0;
101 rv = kill(getpid(), -1);
102
103 if (rv == 0 || errno != EINVAL)
104 _exit(EINVAL);
105
106 errno = 0;
107 rv = kill(INT_MAX, SIGUSR1);
108
109 if (rv == 0 || errno != ESRCH)
110 _exit(ESRCH);
111
112 _exit(EXIT_SUCCESS);
113 }
114
115 (void)wait(&sta);
116
117 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) {
118
119 if (WEXITSTATUS(sta) == EINVAL)
120 atf_tc_fail("expected EINVAL, but kill(2) succeeded");
121
122 if (WEXITSTATUS(sta) == ESRCH)
123 atf_tc_fail("expected ESRCH, but kill(2) succeeded");
124
125 atf_tc_fail("unknown error from kill(2)");
126 }
127}
128
129ATF_TC(kill_perm);
130ATF_TC_HEAD(kill_perm, tc)
131{
132 atf_tc_set_md_var(tc, "descr", "Test kill(2) permissions");
133 atf_tc_set_md_var(tc, "require.user", "root");
134}
135
136ATF_TC_BODY(kill_perm, tc)
137{
138 struct passwd *pw;
139 pid_t cpid, ppid;
140 uid_t cuid = 0;
141 uid_t puid = 0;
142 int sta;
143
144 /*
145 * Test that kill(2) fails when called
146 * for a PID owned by another user.
147 */
148 pw = getpwnam("operator");
149
150 if (pw != NULL)
151 cuid = pw->pw_uid;
152
153 pw = getpwnam("nobody");
154
155 if (pw != NULL)
156 puid = pw->pw_uid;
157
158 if (cuid == 0 || puid == 0 || cuid == puid)
159 atf_tc_fail("getpwnam(3) failed");
160
161 ppid = fork();
162
163 if (ppid < 0)
164 _exit(EXIT_FAILURE);
165
166 if (ppid == 0) {
167
168 cpid = fork();
169
170 if (cpid < 0)
171 _exit(EXIT_FAILURE);
172
173 if (cpid == 0) {
174
175 if (setuid(cuid) < 0)
176 _exit(EXIT_FAILURE);
177 else {
178 (void)sleep(1);
179 }
180
181 _exit(EXIT_SUCCESS);
182 }
183
184 /*
185 * Try to kill the child after having
186 * set the real and effective UID.
187 */
188 if (setuid(puid) != 0)
189 _exit(EXIT_FAILURE);
190
191 errno = 0;
192
193 if (kill(cpid, SIGKILL) == 0)
194 _exit(EPERM);
195
196 if (errno != EPERM)
197 _exit(EPERM);
198
199 (void)waitpid(cpid, &sta, 0);
200
201 _exit(EXIT_SUCCESS);
202 }
203
204 (void)waitpid(ppid, &sta, 0);
205
206 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) == EPERM)
207 atf_tc_fail("killed a process of another user");
208
209 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
210 atf_tc_fail("unknown error from kill(2)");
211}
212
213ATF_TC(kill_pgrp_neg);
214ATF_TC_HEAD(kill_pgrp_neg, tc)
215{
216 atf_tc_set_md_var(tc, "descr", "Test kill(2) with process group, #2");
217}
218
219ATF_TC_BODY(kill_pgrp_neg, tc)
220{
221 const int maxiter = 3;
222 pid_t cpid, ppid;
223 int i, sta;
224
225 ppid = fork();
226 ATF_REQUIRE(ppid >= 0);
227
228 if (ppid == 0) {
229
230 ATF_REQUIRE(setpgid(0, 0) == 0);
231
232 for (i = 0; i < maxiter; i++) {
233
234 cpid = fork();
235 ATF_REQUIRE(cpid >= 0);
236
237 if (cpid == 0)
238 pause();
239 }
240
241 /*
242 * Test the variant of killpg(3); if the process number
243 * is negative but not -1, the signal should be sent to
244 * all processes whose process group ID is equal to the
245 * absolute value of the process number.
246 */
247 ATF_REQUIRE(kill(-getpgrp(), SIGKILL) == 0);
248
249 (void)sleep(1);
250
251 _exit(EXIT_SUCCESS);
252 }
253
254 (void)waitpid(ppid, &sta, 0);
255
256 if (WIFSIGNALED(sta) == 0 || WTERMSIG(sta) != SIGKILL)
257 atf_tc_fail("failed to kill(2) a process group");
258}
259
260ATF_TC(kill_pgrp_zero);
261ATF_TC_HEAD(kill_pgrp_zero, tc)
262{
263 atf_tc_set_md_var(tc, "descr", "Test kill(2) with process group, #1");
264}
265
266ATF_TC_BODY(kill_pgrp_zero, tc)
267{
268 const int maxiter = 3;
269 pid_t cpid, ppid;
270 int i, sta;
271
272 ppid = fork();
273 ATF_REQUIRE(ppid >= 0);
274
275 if (ppid == 0) {
276
277 ATF_REQUIRE(setpgid(0, 0) == 0);
278
279 for (i = 0; i < maxiter; i++) {
280
281 cpid = fork();
282 ATF_REQUIRE(cpid >= 0);
283
284 if (cpid == 0)
285 pause();
286 }
287
288 /*
289 * If the supplied process number is zero,
290 * the signal should be sent to all processes
291 * under the current process group.
292 */
293 ATF_REQUIRE(kill(0, SIGKILL) == 0);
294
295 (void)sleep(1);
296
297 _exit(EXIT_SUCCESS);
298 }
299
300 (void)waitpid(ppid, &sta, 0);
301
302 if (WIFSIGNALED(sta) == 0 || WTERMSIG(sta) != SIGKILL)
303 atf_tc_fail("failed to kill(2) a process group");
304}
305
306ATF_TP_ADD_TCS(tp)
307{
308
309 ATF_TP_ADD_TC(tp, kill_basic);
310 ATF_TP_ADD_TC(tp, kill_err);
311 ATF_TP_ADD_TC(tp, kill_perm);
312 ATF_TP_ADD_TC(tp, kill_pgrp_neg);
313 ATF_TP_ADD_TC(tp, kill_pgrp_zero);
314
315 return atf_no_error();
316}