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 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 36 dummy_sig_handler(int sig) 37 { 38 39 } 40 41 static void 42 dummy_sigchld(int signo, siginfo_t *info, void *ctx) 43 { 44 45 } 46 47 static void 48 support_signal(int sig, sig_t handler) 49 { 50 51 ATF_REQUIRE(signal(sig, handler) != SIG_ERR); 52 } 53 54 static void 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 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 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 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 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); 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 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); 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 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); 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 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); 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 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); 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 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); 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 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); 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 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); 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 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); 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 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 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 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 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 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 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); 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 488 ATF_TC_BODY(test_sig_discard_ign_true, tc) 489 { 490 491 test_sig_discard_ign(true); 492 } 493 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); 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 508 ATF_TC_BODY(test_sig_discard_ign_false, tc) 509 { 510 511 test_sig_discard_ign(false); 512 } 513 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); 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 528 ATF_TC_BODY(test_wait_dequeue_sigchld_true, tc) 529 { 530 531 test_wait_dequeue_sigchld(true); 532 } 533 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); 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 548 ATF_TC_BODY(test_wait_dequeue_sigchld_false, tc) 549 { 550 551 test_wait_dequeue_sigchld(false); 552 } 553 554 ATF_TC_CLEANUP(test_wait_dequeue_sigchld_false, tc) 555 { 556 557 support_sysctlset("kern.wait_dequeue_sigchld", 1); 558 } 559 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