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 25static inline struct timespec 26make_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 35static void 36dummy_sig_handler(int sig) 37{ 38 39} 40 41static void 42dummy_sigchld(int signo, siginfo_t *info, void *ctx) 43{ 44 45} 46 47static void 48support_signal(int sig, sig_t handler) 49{ 50 51 ATF_REQUIRE(signal(sig, handler) != SIG_ERR); 52} 53 54static void 55support_sysctlset(const char *name, int32_t val) 56{ 57 58 ATF_REQUIRE(sysctlbyname(name, NULL, NULL, &val, sizeof(val)) == 0); 59} 60 61static timer_t 62support_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 88static void 89support_delete_timer(timer_t timer) 90{ 91 92 ATF_REQUIRE(timer_delete(timer) == 0); 93 support_signal(SIGALRM, SIG_DFL); 94} 95 96static pid_t 97support_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 119static void 120test_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 147ATF_TC(test_sigtimedwait_timeout_eagain0); 148ATF_TC_HEAD(test_sigtimedwait_timeout_eagain0, tc) 149{ 150 151 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately"); 152} 153 154ATF_TC_BODY(test_sigtimedwait_timeout_eagain0, tc) 155{ 156 157 test_sigtimedwait_timeout_eagain(0, true); 158} 159 160ATF_TC(test_sigtimedwait_timeout_eagain1); 161ATF_TC_HEAD(test_sigtimedwait_timeout_eagain1, tc) 162{ 163 164 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately"); 165} 166 167ATF_TC_BODY(test_sigtimedwait_timeout_eagain1, tc) 168{ 169 170 test_sigtimedwait_timeout_eagain(-1, true); 171} 172 173ATF_TC(test_sigtimedwait_timeout_eagain2); 174ATF_TC_HEAD(test_sigtimedwait_timeout_eagain2, tc) 175{ 176 177 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately"); 178} 179 180ATF_TC_BODY(test_sigtimedwait_timeout_eagain2, tc) 181{ 182 183 test_sigtimedwait_timeout_eagain(-1, false); 184} 185 186ATF_TC(test_sigtimedwait_timeout_eagain3); 187ATF_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 193ATF_TC_BODY(test_sigtimedwait_timeout_eagain3, tc) 194{ 195 196 test_sigtimedwait_timeout_eagain(0, false); 197} 198 199ATF_TC(test_sigtimedwait_large_timeout_eintr); 200ATF_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 206ATF_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 227ATF_TC(test_sigtimedwait_infinity); 228ATF_TC_HEAD(test_sigtimedwait_infinity, tc) 229{ 230 231 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits with EINTR"); 232} 233 234ATF_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 253ATF_TC(test_sigtimedwait_einval); 254ATF_TC_HEAD(test_sigtimedwait_einval, tc) 255{ 256 257 atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits with EINVAL"); 258} 259 260ATF_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 281ATF_TC(test_sigwait_eintr); 282ATF_TC_HEAD(test_sigwait_eintr, tc) 283{ 284 285 atf_tc_set_md_var(tc, "descr", "Check if sigwait exits with EINTR"); 286} 287 288ATF_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 310ATF_TC(test_sigwaitinfo_eintr); 311ATF_TC_HEAD(test_sigwaitinfo_eintr, tc) 312{ 313 314 atf_tc_set_md_var(tc, "descr", "Check if sigwaitinfo exits with EINTR"); 315} 316 317ATF_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 */ 339static void 340test_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 375static void 376support_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 390static void 391support_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 415static void 416test_child(void) 417{ 418 419 raise(SIGSTOP); 420 while (1) 421 pause(); 422} 423 424/* 425 * Test kern.wait_dequeue_sigchld knob. 426 */ 427static void 428test_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 480ATF_TC_WITH_CLEANUP(test_sig_discard_ign_true); 481ATF_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 488ATF_TC_BODY(test_sig_discard_ign_true, tc) 489{ 490 491 test_sig_discard_ign(true); 492} 493 494ATF_TC_CLEANUP(test_sig_discard_ign_true, tc) 495{ 496 497 support_sysctlset("kern.sig_discard_ign", 1); 498} 499 500ATF_TC_WITH_CLEANUP(test_sig_discard_ign_false); 501ATF_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 508ATF_TC_BODY(test_sig_discard_ign_false, tc) 509{ 510 511 test_sig_discard_ign(false); 512} 513 514ATF_TC_CLEANUP(test_sig_discard_ign_false, tc) 515{ 516 517 support_sysctlset("kern.sig_discard_ign", 1); 518} 519 520ATF_TC_WITH_CLEANUP(test_wait_dequeue_sigchld_true); 521ATF_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 528ATF_TC_BODY(test_wait_dequeue_sigchld_true, tc) 529{ 530 531 test_wait_dequeue_sigchld(true); 532} 533 534ATF_TC_CLEANUP(test_wait_dequeue_sigchld_true, tc) 535{ 536 537 support_sysctlset("kern.wait_dequeue_sigchld", 1); 538} 539 540ATF_TC_WITH_CLEANUP(test_wait_dequeue_sigchld_false); 541ATF_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 548ATF_TC_BODY(test_wait_dequeue_sigchld_false, tc) 549{ 550 551 test_wait_dequeue_sigchld(false); 552} 553 554ATF_TC_CLEANUP(test_wait_dequeue_sigchld_false, tc) 555{ 556 557 support_sysctlset("kern.wait_dequeue_sigchld", 1); 558} 559 560ATF_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