1 /*-
2 * Copyright (c) 2022 Dmitry Chagin <dchagin@FreeBSD.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6 #include <sys/cdefs.h>
7 #include <sys/limits.h>
8 #include <sys/time.h>
9 #include <sys/sysctl.h>
10 #include <sys/user.h>
11 #include <sys/wait.h>
12
13 #include <err.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <errno.h>
18 #include <signal.h>
19 #include <stdbool.h>
20 #include <unistd.h>
21
22 #include <atf-c.h>
23
24
25 static inline struct timespec
make_timespec(time_t s,long int ns)26 make_timespec(time_t s, long int ns)
27 {
28 struct timespec rts;
29
30 rts.tv_sec = s;
31 rts.tv_nsec = ns;
32 return (rts);
33 }
34
35 static void
dummy_sig_handler(int sig)36 dummy_sig_handler(int sig)
37 {
38
39 }
40
41 static void
dummy_sigchld(int signo,siginfo_t * info,void * ctx)42 dummy_sigchld(int signo, siginfo_t *info, void *ctx)
43 {
44
45 }
46
47 static void
support_signal(int sig,sig_t handler)48 support_signal(int sig, sig_t handler)
49 {
50
51 ATF_REQUIRE(signal(sig, handler) != SIG_ERR);
52 }
53
54 static void
support_sysctlset(const char * name,int32_t val)55 support_sysctlset(const char *name, int32_t val)
56 {
57
58 ATF_REQUIRE(sysctlbyname(name, NULL, NULL, &val, sizeof(val)) == 0);
59 }
60
61 static timer_t
support_create_timer(uint64_t sec,long int nsec,bool repeat,bool callback)62 support_create_timer(uint64_t sec, long int nsec, bool repeat,
63 bool callback)
64 {
65 struct sigevent ev = {
66 .sigev_notify = SIGEV_SIGNAL,
67 .sigev_signo = SIGALRM
68 };
69 struct itimerspec its =
70 {
71 { .tv_sec = repeat ? sec : 0, .tv_nsec = repeat ? nsec : 0 },
72 { .tv_sec = sec, .tv_nsec = nsec }
73 };
74 struct sigaction sa;
75 timer_t timerid;
76
77 if (callback) {
78 sa.sa_handler = dummy_sig_handler;
79 sigemptyset (&sa.sa_mask);
80 sa.sa_flags = 0;
81 ATF_REQUIRE(sigaction(SIGALRM, &sa, NULL) == 0);
82 }
83 ATF_REQUIRE(timer_create(CLOCK_REALTIME, &ev, &timerid) == 0);
84 ATF_REQUIRE(timer_settime(timerid, 0, &its, NULL) == 0);
85 return (timerid);
86 }
87
88 static void
support_delete_timer(timer_t timer)89 support_delete_timer(timer_t timer)
90 {
91
92 ATF_REQUIRE(timer_delete(timer) == 0);
93 support_signal(SIGALRM, SIG_DFL);
94 }
95
96 static pid_t
support_create_sig_proc(int sig,int count,unsigned int usec)97 support_create_sig_proc(int sig, int count, unsigned int usec)
98 {
99 pid_t pid, cpid;
100
101 pid = getpid();
102 ATF_REQUIRE(pid > 0);
103 cpid = fork();
104 ATF_REQUIRE(cpid >= 0);
105
106 if (cpid == 0) {
107 while (count-- > 0) {
108 usleep(usec);
109 if (kill(pid, sig) == -1)
110 break;
111 }
112 exit(0);
113 }
114 return (cpid);
115 }
116
117 #define TIMESPEC_HZ 1000000000
118
119 static void
test_sigtimedwait_timeout_eagain(time_t sec,bool zero_tmo)120 test_sigtimedwait_timeout_eagain(time_t sec, bool zero_tmo)
121 {
122 struct timespec ts, timeout, now;
123 sigset_t ss;
124 int rv;
125
126 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0);
127
128 timeout = make_timespec(sec, zero_tmo ? 0 : TIMESPEC_HZ/2);
129 timespecadd(&ts, &timeout, &ts);
130
131 sigemptyset(&ss);
132 sigaddset(&ss, SIGUSR1);
133 rv = sigtimedwait(&ss, NULL, &timeout);
134 ATF_REQUIRE_EQ_MSG(-1, rv,
135 "sigtimedwait () should fail: rv %d, errno %d", rv, errno);
136 ATF_REQUIRE_EQ_MSG(EAGAIN, errno,
137 "sigtimedwait() should fail with EAGAIN: rv %d, errno %d",
138 rv, errno);
139 /* now >= ts */
140 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0);
141 ATF_REQUIRE_MSG(timespeccmp(&now, &ts, >=) == true,
142 "timespeccmp: now { %jd.%ld } < ts { %jd.%ld }",
143 (intmax_t)now.tv_sec, now.tv_nsec,
144 (intmax_t)ts.tv_sec, ts.tv_nsec);
145 }
146
147 ATF_TC(test_sigtimedwait_timeout_eagain0);
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain0,tc)148 ATF_TC_HEAD(test_sigtimedwait_timeout_eagain0, tc)
149 {
150
151 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately");
152 }
153
ATF_TC_BODY(test_sigtimedwait_timeout_eagain0,tc)154 ATF_TC_BODY(test_sigtimedwait_timeout_eagain0, tc)
155 {
156
157 test_sigtimedwait_timeout_eagain(0, true);
158 }
159
160 ATF_TC(test_sigtimedwait_timeout_eagain1);
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain1,tc)161 ATF_TC_HEAD(test_sigtimedwait_timeout_eagain1, tc)
162 {
163
164 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately");
165 }
166
ATF_TC_BODY(test_sigtimedwait_timeout_eagain1,tc)167 ATF_TC_BODY(test_sigtimedwait_timeout_eagain1, tc)
168 {
169
170 test_sigtimedwait_timeout_eagain(-1, true);
171 }
172
173 ATF_TC(test_sigtimedwait_timeout_eagain2);
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain2,tc)174 ATF_TC_HEAD(test_sigtimedwait_timeout_eagain2, tc)
175 {
176
177 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately");
178 }
179
ATF_TC_BODY(test_sigtimedwait_timeout_eagain2,tc)180 ATF_TC_BODY(test_sigtimedwait_timeout_eagain2, tc)
181 {
182
183 test_sigtimedwait_timeout_eagain(-1, false);
184 }
185
186 ATF_TC(test_sigtimedwait_timeout_eagain3);
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain3,tc)187 ATF_TC_HEAD(test_sigtimedwait_timeout_eagain3, tc)
188 {
189
190 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits after specified timeout");
191 }
192
ATF_TC_BODY(test_sigtimedwait_timeout_eagain3,tc)193 ATF_TC_BODY(test_sigtimedwait_timeout_eagain3, tc)
194 {
195
196 test_sigtimedwait_timeout_eagain(0, false);
197 }
198
199 ATF_TC(test_sigtimedwait_large_timeout_eintr);
ATF_TC_HEAD(test_sigtimedwait_large_timeout_eintr,tc)200 ATF_TC_HEAD(test_sigtimedwait_large_timeout_eintr, tc)
201 {
202
203 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits with EINTR");
204 }
205
ATF_TC_BODY(test_sigtimedwait_large_timeout_eintr,tc)206 ATF_TC_BODY(test_sigtimedwait_large_timeout_eintr, tc)
207 {
208 struct timespec ts;
209 timer_t timerid;
210 sigset_t ss;
211 int rv;
212
213 ts = make_timespec(LONG_MAX, 0);
214 timerid = support_create_timer(0, 100000000, false, true);
215
216 sigemptyset(&ss);
217 sigaddset(&ss, SIGUSR1);
218 rv = sigtimedwait(&ss, NULL, &ts);
219 ATF_REQUIRE_EQ_MSG(-1, rv,
220 "sigtimedwait () should fail: rv %d, errno %d", rv, errno);
221 ATF_REQUIRE_EQ_MSG(EINTR, errno,
222 "sigtimedwait() should fail with EINTR: rv %d, errno %d",
223 rv, errno);
224 support_delete_timer(timerid);
225 }
226
227 ATF_TC(test_sigtimedwait_infinity);
ATF_TC_HEAD(test_sigtimedwait_infinity,tc)228 ATF_TC_HEAD(test_sigtimedwait_infinity, tc)
229 {
230
231 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits with EINTR");
232 }
233
ATF_TC_BODY(test_sigtimedwait_infinity,tc)234 ATF_TC_BODY(test_sigtimedwait_infinity, tc)
235 {
236 timer_t timerid;
237 sigset_t ss;
238 int rv;
239
240 timerid = support_create_timer(0, 100000000, false, true);
241
242 sigemptyset(&ss);
243 sigaddset(&ss, SIGUSR1);
244 rv = sigtimedwait(&ss, NULL, NULL);
245 ATF_REQUIRE_EQ_MSG(-1, rv,
246 "sigtimedwait () should fail: rv %d, errno %d", rv, errno);
247 ATF_REQUIRE_EQ_MSG(EINTR, errno,
248 "sigtimedwait() should fail with EINTR: rv %d, errno %d",
249 rv, errno);
250 support_delete_timer(timerid);
251 }
252
253 ATF_TC(test_sigtimedwait_einval);
ATF_TC_HEAD(test_sigtimedwait_einval,tc)254 ATF_TC_HEAD(test_sigtimedwait_einval, tc)
255 {
256
257 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits with EINVAL");
258 }
259
ATF_TC_BODY(test_sigtimedwait_einval,tc)260 ATF_TC_BODY(test_sigtimedwait_einval, tc)
261 {
262 struct timespec ts;
263 timer_t timerid;
264 sigset_t ss;
265 int rv;
266
267 ts = make_timespec(0, -1);
268 timerid = support_create_timer(0, 100000000, false, true);
269
270 sigemptyset(&ss);
271 sigaddset(&ss, SIGUSR1);
272 rv = sigtimedwait(&ss, NULL, &ts);
273 ATF_REQUIRE_EQ_MSG(-1, rv,
274 "sigtimedwait () should fail: rv %d, errno %d", rv, errno);
275 ATF_REQUIRE_EQ_MSG(EINVAL, errno,
276 "sigtimedwait() should fail with EINVAL: rv %d, errno %d",
277 rv, errno);
278 support_delete_timer(timerid);
279 }
280
281 ATF_TC(test_sigwait_eintr);
ATF_TC_HEAD(test_sigwait_eintr,tc)282 ATF_TC_HEAD(test_sigwait_eintr, tc)
283 {
284
285 atf_tc_set_md_var(tc, "descr", "Check if sigwait exits with EINTR");
286 }
287
ATF_TC_BODY(test_sigwait_eintr,tc)288 ATF_TC_BODY(test_sigwait_eintr, tc)
289 {
290 timer_t timerid;
291 sigset_t ss;
292 int rv, sig, pid;
293
294 support_signal(SIGUSR1, dummy_sig_handler);
295
296 pid = support_create_sig_proc(SIGUSR1, 1, 400000);
297 timerid = support_create_timer(0, 200000, false, true);
298
299 sigemptyset(&ss);
300 sigaddset(&ss, SIGUSR1);
301 rv = sigwait(&ss, &sig);
302 ATF_REQUIRE_EQ_MSG(0, rv,
303 "sigwait() should not fail: rv %d, errno %d", rv, errno);
304 ATF_REQUIRE_EQ_MSG(SIGUSR1, sig,
305 "sigwait() should return SIGUSR1: rv %d, sig %d", rv, sig);
306 ATF_REQUIRE(waitid(P_PID, pid, NULL, WEXITED) == 0);
307 support_delete_timer(timerid);
308 }
309
310 ATF_TC(test_sigwaitinfo_eintr);
ATF_TC_HEAD(test_sigwaitinfo_eintr,tc)311 ATF_TC_HEAD(test_sigwaitinfo_eintr, tc)
312 {
313
314 atf_tc_set_md_var(tc, "descr", "Check if sigwaitinfo exits with EINTR");
315 }
316
ATF_TC_BODY(test_sigwaitinfo_eintr,tc)317 ATF_TC_BODY(test_sigwaitinfo_eintr, tc)
318 {
319 timer_t timerid;
320 sigset_t ss;
321 int rv;
322
323 timerid = support_create_timer(0, 100000000, false, true);
324
325 sigemptyset(&ss);
326 sigaddset(&ss, SIGUSR1);
327 rv = sigwaitinfo(&ss, NULL);
328 ATF_REQUIRE_EQ_MSG(-1, rv,
329 "sigwaitinfo() should fail, rv %d != -1", rv);
330 ATF_REQUIRE_EQ_MSG(EINTR, errno,
331 "sigwaitinfo() should fail errno %d != EINTR", errno);
332 support_delete_timer(timerid);
333 }
334
335 /*
336 * Test kern.sig_discard_ign knob (default true).
337 * See commit bc387624
338 */
339 static void
test_sig_discard_ign(bool ignore)340 test_sig_discard_ign(bool ignore)
341 {
342 struct timespec ts;
343 sigset_t mask;
344 pid_t pid;
345 int rv;
346
347 support_signal(SIGUSR2, SIG_IGN);
348
349 if (ignore)
350 support_sysctlset("kern.sig_discard_ign", 1);
351 else
352 support_sysctlset("kern.sig_discard_ign", 0);
353
354 sigemptyset(&mask);
355 sigaddset(&mask, SIGUSR2);
356 ATF_REQUIRE(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
357
358 pid = support_create_sig_proc(SIGUSR2, 1, 100000);
359
360 ts = make_timespec(1, 0);
361 rv = sigtimedwait(&mask, NULL, &ts);
362 if (ignore == true) {
363 ATF_REQUIRE_EQ_MSG(-1, rv,
364 "sigtimedwait() ign=on should fail, rv %d != -1", rv);
365 ATF_REQUIRE_EQ_MSG(EAGAIN, errno,
366 "sigtimedwait() ign=on should fail with EAGAIN errno %d",
367 errno);
368 } else
369 ATF_REQUIRE_EQ_MSG(SIGUSR2, rv,
370 "sigtimedwait() ign=off should return SIGUSR2, rv %d errno %d",
371 rv, errno);
372 ATF_REQUIRE(waitid(P_PID, pid, NULL, WEXITED) == 0);
373 }
374
375 static void
support_check_siginfo(int code,int status,pid_t pid,siginfo_t * si,int sig)376 support_check_siginfo(int code, int status, pid_t pid,
377 siginfo_t *si, int sig)
378 {
379
380 ATF_REQUIRE_EQ_MSG(sig, si->si_signo,
381 "check_siginfo: si_signo %d != sig %d", si->si_signo, sig);
382 ATF_REQUIRE_EQ_MSG(code, si->si_code,
383 "check_siginfo: si_code %d != code %d", si->si_code, code);
384 ATF_REQUIRE_EQ_MSG(status, si->si_status,
385 "check_siginfo: si_status %d != status %d", si->si_status, status);
386 ATF_REQUIRE_EQ_MSG(pid, si->si_pid,
387 "check_siginfo: si_pid %d != pid %d", si->si_pid, pid);
388 }
389
390 static void
support_check_sigchld(sigset_t * set,int code,int status,pid_t pid,bool dequeue)391 support_check_sigchld(sigset_t *set, int code, int status, pid_t pid,
392 bool dequeue)
393 {
394 siginfo_t si;
395 int sig, kpid;
396
397 if (dequeue == true)
398 kpid = support_create_sig_proc(SIGUSR2, 1, 1000000);
399
400 sig = sigwaitinfo(set, &si);
401 if (dequeue == true) {
402 ATF_REQUIRE_EQ_MSG(-1, sig,
403 "sigwaitinfo() should fail, sig %d != -1", sig);
404 ATF_REQUIRE_EQ_MSG(EINTR, errno,
405 "sigwaitinfo() should fail errno %d != EINTR", errno);
406 } else
407 ATF_REQUIRE_EQ_MSG(SIGCHLD, sig,
408 "sigwaitinfo() %d != SIGCHLD", sig);
409 if (dequeue == false)
410 support_check_siginfo(code, status, pid, &si, SIGCHLD);
411 if (dequeue == true)
412 ATF_REQUIRE(waitid(P_PID, kpid, &si, WEXITED) == 0);
413 }
414
415 static void
test_child(void)416 test_child(void)
417 {
418
419 raise(SIGSTOP);
420 while (1)
421 pause();
422 }
423
424 /*
425 * Test kern.wait_dequeue_sigchld knob.
426 */
427 static void
test_wait_dequeue_sigchld(bool dequeue)428 test_wait_dequeue_sigchld(bool dequeue)
429 {
430 struct sigaction sa;
431 siginfo_t si;
432 sigset_t set;
433 pid_t pid;
434
435 sa.sa_flags = SA_SIGINFO | SA_RESTART;
436 sa.sa_sigaction = dummy_sigchld;
437 sigemptyset(&sa.sa_mask);
438 ATF_REQUIRE(sigaction(SIGCHLD, &sa, NULL) == 0);
439
440 support_signal(SIGUSR2, dummy_sig_handler);
441
442 sigemptyset(&set);
443 sigaddset(&set, SIGCHLD);
444 ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) == 0);
445
446 if (dequeue)
447 support_sysctlset("kern.wait_dequeue_sigchld", 1);
448 else
449 support_sysctlset("kern.wait_dequeue_sigchld", 0);
450
451 pid = fork();
452 ATF_REQUIRE(pid >= 0);
453 if (pid == 0) {
454 test_child();
455 exit(0);
456 }
457
458 bzero(&si, sizeof(si));
459 ATF_REQUIRE(waitid(P_PID, pid, &si, WSTOPPED) == 0);
460
461 support_check_siginfo(CLD_STOPPED, SIGSTOP, pid, &si, SIGCHLD);
462 support_check_sigchld(&set, CLD_STOPPED, SIGSTOP, pid, dequeue);
463
464 ATF_REQUIRE(kill(pid, SIGCONT) == 0);
465
466 bzero(&si, sizeof(si));
467 ATF_REQUIRE(waitid(P_PID, pid, &si, WCONTINUED) == 0);
468
469 support_check_siginfo(CLD_CONTINUED, SIGCONT, pid, &si, SIGCHLD);
470 support_check_sigchld(&set, CLD_CONTINUED, SIGCONT, pid, dequeue);
471
472 ATF_REQUIRE(kill(pid, SIGKILL) == 0);
473
474 bzero(&si, sizeof(si));
475 ATF_REQUIRE(waitid(P_PID, pid, &si, WEXITED) == 0);
476
477 support_check_siginfo(CLD_KILLED, SIGKILL, pid, &si, SIGCHLD);
478 }
479
480 ATF_TC_WITH_CLEANUP(test_sig_discard_ign_true);
ATF_TC_HEAD(test_sig_discard_ign_true,tc)481 ATF_TC_HEAD(test_sig_discard_ign_true, tc)
482 {
483
484 atf_tc_set_md_var(tc, "require.user", "root");
485 atf_tc_set_md_var(tc, "descr", "Test kern.sig_discard_ign on");
486 }
487
ATF_TC_BODY(test_sig_discard_ign_true,tc)488 ATF_TC_BODY(test_sig_discard_ign_true, tc)
489 {
490
491 test_sig_discard_ign(true);
492 }
493
ATF_TC_CLEANUP(test_sig_discard_ign_true,tc)494 ATF_TC_CLEANUP(test_sig_discard_ign_true, tc)
495 {
496
497 support_sysctlset("kern.sig_discard_ign", 1);
498 }
499
500 ATF_TC_WITH_CLEANUP(test_sig_discard_ign_false);
ATF_TC_HEAD(test_sig_discard_ign_false,tc)501 ATF_TC_HEAD(test_sig_discard_ign_false, tc)
502 {
503
504 atf_tc_set_md_var(tc, "require.user", "root");
505 atf_tc_set_md_var(tc, "descr", "Test kern.sig_discard_ign off");
506 }
507
ATF_TC_BODY(test_sig_discard_ign_false,tc)508 ATF_TC_BODY(test_sig_discard_ign_false, tc)
509 {
510
511 test_sig_discard_ign(false);
512 }
513
ATF_TC_CLEANUP(test_sig_discard_ign_false,tc)514 ATF_TC_CLEANUP(test_sig_discard_ign_false, tc)
515 {
516
517 support_sysctlset("kern.sig_discard_ign", 1);
518 }
519
520 ATF_TC_WITH_CLEANUP(test_wait_dequeue_sigchld_true);
ATF_TC_HEAD(test_wait_dequeue_sigchld_true,tc)521 ATF_TC_HEAD(test_wait_dequeue_sigchld_true, tc)
522 {
523
524 atf_tc_set_md_var(tc, "require.user", "root");
525 atf_tc_set_md_var(tc, "descr", "Test kern.wait_dequeue_sigchld on");
526 }
527
ATF_TC_BODY(test_wait_dequeue_sigchld_true,tc)528 ATF_TC_BODY(test_wait_dequeue_sigchld_true, tc)
529 {
530
531 test_wait_dequeue_sigchld(true);
532 }
533
ATF_TC_CLEANUP(test_wait_dequeue_sigchld_true,tc)534 ATF_TC_CLEANUP(test_wait_dequeue_sigchld_true, tc)
535 {
536
537 support_sysctlset("kern.wait_dequeue_sigchld", 1);
538 }
539
540 ATF_TC_WITH_CLEANUP(test_wait_dequeue_sigchld_false);
ATF_TC_HEAD(test_wait_dequeue_sigchld_false,tc)541 ATF_TC_HEAD(test_wait_dequeue_sigchld_false, tc)
542 {
543
544 atf_tc_set_md_var(tc, "require.user", "root");
545 atf_tc_set_md_var(tc, "descr", "Test kern.wait_dequeue_sigchld off");
546 }
547
ATF_TC_BODY(test_wait_dequeue_sigchld_false,tc)548 ATF_TC_BODY(test_wait_dequeue_sigchld_false, tc)
549 {
550
551 test_wait_dequeue_sigchld(false);
552 }
553
ATF_TC_CLEANUP(test_wait_dequeue_sigchld_false,tc)554 ATF_TC_CLEANUP(test_wait_dequeue_sigchld_false, tc)
555 {
556
557 support_sysctlset("kern.wait_dequeue_sigchld", 1);
558 }
559
ATF_TP_ADD_TCS(tp)560 ATF_TP_ADD_TCS(tp)
561 {
562
563 ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain0);
564 ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain1);
565 ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain2);
566 ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain3);
567
568 ATF_TP_ADD_TC(tp, test_sigtimedwait_large_timeout_eintr);
569 ATF_TP_ADD_TC(tp, test_sigtimedwait_infinity);
570
571 ATF_TP_ADD_TC(tp, test_sigtimedwait_einval);
572
573 ATF_TP_ADD_TC(tp, test_sigwait_eintr);
574 ATF_TP_ADD_TC(tp, test_sigwaitinfo_eintr);
575
576 ATF_TP_ADD_TC(tp, test_sig_discard_ign_true);
577 ATF_TP_ADD_TC(tp, test_sig_discard_ign_false);
578
579 ATF_TP_ADD_TC(tp, test_wait_dequeue_sigchld_true);
580 ATF_TP_ADD_TC(tp, test_wait_dequeue_sigchld_false);
581
582 return (atf_no_error());
583 }
584