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