1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #define _GNU_SOURCE 4 #include <errno.h> 5 #include <fcntl.h> 6 #include <linux/types.h> 7 #include <pthread.h> 8 #include <sched.h> 9 #include <signal.h> 10 #include <stdio.h> 11 #include <stdbool.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <syscall.h> 15 #include <sys/epoll.h> 16 #include <sys/mman.h> 17 #include <sys/mount.h> 18 #include <sys/wait.h> 19 #include <time.h> 20 #include <unistd.h> 21 22 #include "pidfd.h" 23 #include "../kselftest.h" 24 25 #define str(s) _str(s) 26 #define _str(s) #s 27 #define CHILD_THREAD_MIN_WAIT 3 /* seconds */ 28 29 #define MAX_EVENTS 5 30 31 static bool have_pidfd_send_signal; 32 33 static pid_t pidfd_clone(int flags, int *pidfd, int (*fn)(void *)) 34 { 35 size_t stack_size = 1024; 36 char *stack[1024] = { 0 }; 37 38 #ifdef __ia64__ 39 return __clone2(fn, stack, stack_size, flags | SIGCHLD, NULL, pidfd); 40 #else 41 return clone(fn, stack + stack_size, flags | SIGCHLD, NULL, pidfd); 42 #endif 43 } 44 45 static int signal_received; 46 47 static void set_signal_received_on_sigusr1(int sig) 48 { 49 if (sig == SIGUSR1) 50 signal_received = 1; 51 } 52 53 /* 54 * Straightforward test to see whether pidfd_send_signal() works is to send 55 * a signal to ourself. 56 */ 57 static int test_pidfd_send_signal_simple_success(void) 58 { 59 int pidfd, ret; 60 const char *test_name = "pidfd_send_signal send SIGUSR1"; 61 62 if (!have_pidfd_send_signal) { 63 ksft_test_result_skip( 64 "%s test: pidfd_send_signal() syscall not supported\n", 65 test_name); 66 return 0; 67 } 68 69 pidfd = open("/proc/self", O_DIRECTORY | O_CLOEXEC); 70 if (pidfd < 0) 71 ksft_exit_fail_msg( 72 "%s test: Failed to open process file descriptor\n", 73 test_name); 74 75 signal(SIGUSR1, set_signal_received_on_sigusr1); 76 77 ret = sys_pidfd_send_signal(pidfd, SIGUSR1, NULL, 0); 78 close(pidfd); 79 if (ret < 0) 80 ksft_exit_fail_msg("%s test: Failed to send signal\n", 81 test_name); 82 83 if (signal_received != 1) 84 ksft_exit_fail_msg("%s test: Failed to receive signal\n", 85 test_name); 86 87 signal_received = 0; 88 ksft_test_result_pass("%s test: Sent signal\n", test_name); 89 return 0; 90 } 91 92 static int test_pidfd_send_signal_exited_fail(void) 93 { 94 int pidfd, ret, saved_errno; 95 char buf[256]; 96 pid_t pid; 97 const char *test_name = "pidfd_send_signal signal exited process"; 98 99 if (!have_pidfd_send_signal) { 100 ksft_test_result_skip( 101 "%s test: pidfd_send_signal() syscall not supported\n", 102 test_name); 103 return 0; 104 } 105 106 pid = fork(); 107 if (pid < 0) 108 ksft_exit_fail_msg("%s test: Failed to create new process\n", 109 test_name); 110 111 if (pid == 0) 112 _exit(EXIT_SUCCESS); 113 114 snprintf(buf, sizeof(buf), "/proc/%d", pid); 115 116 pidfd = open(buf, O_DIRECTORY | O_CLOEXEC); 117 118 ret = wait_for_pid(pid); 119 ksft_print_msg("waitpid WEXITSTATUS=%d\n", ret); 120 121 if (pidfd < 0) 122 ksft_exit_fail_msg( 123 "%s test: Failed to open process file descriptor\n", 124 test_name); 125 126 ret = sys_pidfd_send_signal(pidfd, 0, NULL, 0); 127 saved_errno = errno; 128 close(pidfd); 129 if (ret == 0) 130 ksft_exit_fail_msg( 131 "%s test: Managed to send signal to process even though it should have failed\n", 132 test_name); 133 134 if (saved_errno != ESRCH) 135 ksft_exit_fail_msg( 136 "%s test: Expected to receive ESRCH as errno value but received %d instead\n", 137 test_name, saved_errno); 138 139 ksft_test_result_pass("%s test: Failed to send signal as expected\n", 140 test_name); 141 return 0; 142 } 143 144 /* 145 * Maximum number of cycles we allow. This is equivalent to PID_MAX_DEFAULT. 146 * If users set a higher limit or we have cycled PIDFD_MAX_DEFAULT number of 147 * times then we skip the test to not go into an infinite loop or block for a 148 * long time. 149 */ 150 #define PIDFD_MAX_DEFAULT 0x8000 151 152 static int test_pidfd_send_signal_recycled_pid_fail(void) 153 { 154 int i, ret; 155 pid_t pid1; 156 const char *test_name = "pidfd_send_signal signal recycled pid"; 157 158 if (!have_pidfd_send_signal) { 159 ksft_test_result_skip( 160 "%s test: pidfd_send_signal() syscall not supported\n", 161 test_name); 162 return 0; 163 } 164 165 ret = unshare(CLONE_NEWPID); 166 if (ret < 0) { 167 if (errno == EPERM) { 168 ksft_test_result_skip("%s test: Unsharing pid namespace not permitted\n", 169 test_name); 170 return 0; 171 } 172 ksft_exit_fail_msg("%s test: Failed to unshare pid namespace\n", 173 test_name); 174 } 175 176 ret = unshare(CLONE_NEWNS); 177 if (ret < 0) { 178 if (errno == EPERM) { 179 ksft_test_result_skip("%s test: Unsharing mount namespace not permitted\n", 180 test_name); 181 return 0; 182 } 183 ksft_exit_fail_msg("%s test: Failed to unshare mount namespace\n", 184 test_name); 185 } 186 187 ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0); 188 if (ret < 0) 189 ksft_exit_fail_msg("%s test: Failed to remount / private\n", 190 test_name); 191 192 /* pid 1 in new pid namespace */ 193 pid1 = fork(); 194 if (pid1 < 0) 195 ksft_exit_fail_msg("%s test: Failed to create new process\n", 196 test_name); 197 198 if (pid1 == 0) { 199 char buf[256]; 200 pid_t pid2; 201 int pidfd = -1; 202 203 (void)umount2("/proc", MNT_DETACH); 204 ret = mount("proc", "/proc", "proc", 0, NULL); 205 if (ret < 0) 206 _exit(PIDFD_ERROR); 207 208 /* grab pid PID_RECYCLE */ 209 for (i = 0; i <= PIDFD_MAX_DEFAULT; i++) { 210 pid2 = fork(); 211 if (pid2 < 0) 212 _exit(PIDFD_ERROR); 213 214 if (pid2 == 0) 215 _exit(PIDFD_PASS); 216 217 if (pid2 == PID_RECYCLE) { 218 snprintf(buf, sizeof(buf), "/proc/%d", pid2); 219 ksft_print_msg("pid to recycle is %d\n", pid2); 220 pidfd = open(buf, O_DIRECTORY | O_CLOEXEC); 221 } 222 223 if (wait_for_pid(pid2)) 224 _exit(PIDFD_ERROR); 225 226 if (pid2 >= PID_RECYCLE) 227 break; 228 } 229 230 /* 231 * We want to be as predictable as we can so if we haven't been 232 * able to grab pid PID_RECYCLE skip the test. 233 */ 234 if (pid2 != PID_RECYCLE) { 235 /* skip test */ 236 close(pidfd); 237 _exit(PIDFD_SKIP); 238 } 239 240 if (pidfd < 0) 241 _exit(PIDFD_ERROR); 242 243 for (i = 0; i <= PIDFD_MAX_DEFAULT; i++) { 244 char c; 245 int pipe_fds[2]; 246 pid_t recycled_pid; 247 int child_ret = PIDFD_PASS; 248 249 ret = pipe2(pipe_fds, O_CLOEXEC); 250 if (ret < 0) 251 _exit(PIDFD_ERROR); 252 253 recycled_pid = fork(); 254 if (recycled_pid < 0) 255 _exit(PIDFD_ERROR); 256 257 if (recycled_pid == 0) { 258 close(pipe_fds[1]); 259 (void)read(pipe_fds[0], &c, 1); 260 close(pipe_fds[0]); 261 262 _exit(PIDFD_PASS); 263 } 264 265 /* 266 * Stop the child so we can inspect whether we have 267 * recycled pid PID_RECYCLE. 268 */ 269 close(pipe_fds[0]); 270 ret = kill(recycled_pid, SIGSTOP); 271 close(pipe_fds[1]); 272 if (ret) { 273 (void)wait_for_pid(recycled_pid); 274 _exit(PIDFD_ERROR); 275 } 276 277 /* 278 * We have recycled the pid. Try to signal it. This 279 * needs to fail since this is a different process than 280 * the one the pidfd refers to. 281 */ 282 if (recycled_pid == PID_RECYCLE) { 283 ret = sys_pidfd_send_signal(pidfd, SIGCONT, 284 NULL, 0); 285 if (ret && errno == ESRCH) 286 child_ret = PIDFD_XFAIL; 287 else 288 child_ret = PIDFD_FAIL; 289 } 290 291 /* let the process move on */ 292 ret = kill(recycled_pid, SIGCONT); 293 if (ret) 294 (void)kill(recycled_pid, SIGKILL); 295 296 if (wait_for_pid(recycled_pid)) 297 _exit(PIDFD_ERROR); 298 299 switch (child_ret) { 300 case PIDFD_FAIL: 301 /* fallthrough */ 302 case PIDFD_XFAIL: 303 _exit(child_ret); 304 case PIDFD_PASS: 305 break; 306 default: 307 /* not reached */ 308 _exit(PIDFD_ERROR); 309 } 310 311 /* 312 * If the user set a custom pid_max limit we could be 313 * in the millions. 314 * Skip the test in this case. 315 */ 316 if (recycled_pid > PIDFD_MAX_DEFAULT) 317 _exit(PIDFD_SKIP); 318 } 319 320 /* failed to recycle pid */ 321 _exit(PIDFD_SKIP); 322 } 323 324 ret = wait_for_pid(pid1); 325 switch (ret) { 326 case PIDFD_FAIL: 327 ksft_exit_fail_msg( 328 "%s test: Managed to signal recycled pid %d\n", 329 test_name, PID_RECYCLE); 330 case PIDFD_PASS: 331 ksft_exit_fail_msg("%s test: Failed to recycle pid %d\n", 332 test_name, PID_RECYCLE); 333 case PIDFD_SKIP: 334 ksft_test_result_skip("%s test: Skipping test\n", test_name); 335 ret = 0; 336 break; 337 case PIDFD_XFAIL: 338 ksft_test_result_pass( 339 "%s test: Failed to signal recycled pid as expected\n", 340 test_name); 341 ret = 0; 342 break; 343 default /* PIDFD_ERROR */: 344 ksft_exit_fail_msg("%s test: Error while running tests\n", 345 test_name); 346 } 347 348 return ret; 349 } 350 351 static int test_pidfd_send_signal_syscall_support(void) 352 { 353 int pidfd, ret; 354 const char *test_name = "pidfd_send_signal check for support"; 355 356 pidfd = open("/proc/self", O_DIRECTORY | O_CLOEXEC); 357 if (pidfd < 0) 358 ksft_exit_fail_msg( 359 "%s test: Failed to open process file descriptor\n", 360 test_name); 361 362 ret = sys_pidfd_send_signal(pidfd, 0, NULL, 0); 363 if (ret < 0) { 364 if (errno == ENOSYS) { 365 ksft_test_result_skip( 366 "%s test: pidfd_send_signal() syscall not supported\n", 367 test_name); 368 return 0; 369 } 370 ksft_exit_fail_msg("%s test: Failed to send signal\n", 371 test_name); 372 } 373 374 have_pidfd_send_signal = true; 375 close(pidfd); 376 ksft_test_result_pass( 377 "%s test: pidfd_send_signal() syscall is supported. Tests can be executed\n", 378 test_name); 379 return 0; 380 } 381 382 static void *test_pidfd_poll_exec_thread(void *priv) 383 { 384 ksft_print_msg("Child Thread: starting. pid %d tid %ld ; and sleeping\n", 385 getpid(), syscall(SYS_gettid)); 386 ksft_print_msg("Child Thread: doing exec of sleep\n"); 387 388 execl("/bin/sleep", "sleep", str(CHILD_THREAD_MIN_WAIT), (char *)NULL); 389 390 ksft_print_msg("Child Thread: DONE. pid %d tid %ld\n", 391 getpid(), syscall(SYS_gettid)); 392 return NULL; 393 } 394 395 static void poll_pidfd(const char *test_name, int pidfd) 396 { 397 int c; 398 int epoll_fd = epoll_create1(EPOLL_CLOEXEC); 399 struct epoll_event event, events[MAX_EVENTS]; 400 401 if (epoll_fd == -1) 402 ksft_exit_fail_msg("%s test: Failed to create epoll file descriptor " 403 "(errno %d)\n", 404 test_name, errno); 405 406 event.events = EPOLLIN; 407 event.data.fd = pidfd; 408 409 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pidfd, &event)) { 410 ksft_exit_fail_msg("%s test: Failed to add epoll file descriptor " 411 "(errno %d)\n", 412 test_name, errno); 413 } 414 415 c = epoll_wait(epoll_fd, events, MAX_EVENTS, 5000); 416 if (c != 1 || !(events[0].events & EPOLLIN)) 417 ksft_exit_fail_msg("%s test: Unexpected epoll_wait result (c=%d, events=%x) " 418 "(errno %d)\n", 419 test_name, c, events[0].events, errno); 420 421 close(epoll_fd); 422 return; 423 424 } 425 426 static int child_poll_exec_test(void *args) 427 { 428 pthread_t t1; 429 430 ksft_print_msg("Child (pidfd): starting. pid %d tid %ld\n", getpid(), 431 syscall(SYS_gettid)); 432 pthread_create(&t1, NULL, test_pidfd_poll_exec_thread, NULL); 433 /* 434 * Exec in the non-leader thread will destroy the leader immediately. 435 * If the wait in the parent returns too soon, the test fails. 436 */ 437 while (1) 438 sleep(1); 439 440 return 0; 441 } 442 443 static void test_pidfd_poll_exec(int use_waitpid) 444 { 445 int pid, pidfd = 0; 446 int status, ret; 447 time_t prog_start = time(NULL); 448 const char *test_name = "pidfd_poll check for premature notification on child thread exec"; 449 450 ksft_print_msg("Parent: pid: %d\n", getpid()); 451 pid = pidfd_clone(CLONE_PIDFD, &pidfd, child_poll_exec_test); 452 if (pid < 0) 453 ksft_exit_fail_msg("%s test: pidfd_clone failed (ret %d, errno %d)\n", 454 test_name, pid, errno); 455 456 ksft_print_msg("Parent: Waiting for Child (%d) to complete.\n", pid); 457 458 if (use_waitpid) { 459 ret = waitpid(pid, &status, 0); 460 if (ret == -1) 461 ksft_print_msg("Parent: error\n"); 462 463 if (ret == pid) 464 ksft_print_msg("Parent: Child process waited for.\n"); 465 } else { 466 poll_pidfd(test_name, pidfd); 467 } 468 469 time_t prog_time = time(NULL) - prog_start; 470 471 ksft_print_msg("Time waited for child: %lu\n", prog_time); 472 473 close(pidfd); 474 475 if (prog_time < CHILD_THREAD_MIN_WAIT || prog_time > CHILD_THREAD_MIN_WAIT + 2) 476 ksft_exit_fail_msg("%s test: Failed\n", test_name); 477 else 478 ksft_test_result_pass("%s test: Passed\n", test_name); 479 } 480 481 static void *test_pidfd_poll_leader_exit_thread(void *priv) 482 { 483 ksft_print_msg("Child Thread: starting. pid %d tid %ld ; and sleeping\n", 484 getpid(), syscall(SYS_gettid)); 485 sleep(CHILD_THREAD_MIN_WAIT); 486 ksft_print_msg("Child Thread: DONE. pid %d tid %ld\n", getpid(), syscall(SYS_gettid)); 487 return NULL; 488 } 489 490 static time_t *child_exit_secs; 491 static int child_poll_leader_exit_test(void *args) 492 { 493 pthread_t t1, t2; 494 495 ksft_print_msg("Child: starting. pid %d tid %ld\n", getpid(), syscall(SYS_gettid)); 496 pthread_create(&t1, NULL, test_pidfd_poll_leader_exit_thread, NULL); 497 pthread_create(&t2, NULL, test_pidfd_poll_leader_exit_thread, NULL); 498 499 /* 500 * glibc exit calls exit_group syscall, so explicity call exit only 501 * so that only the group leader exits, leaving the threads alone. 502 */ 503 *child_exit_secs = time(NULL); 504 syscall(SYS_exit, 0); 505 /* Never reached, but appeases compiler thinking we should return. */ 506 exit(0); 507 } 508 509 static void test_pidfd_poll_leader_exit(int use_waitpid) 510 { 511 int pid, pidfd = 0; 512 int status, ret = 0; 513 const char *test_name = "pidfd_poll check for premature notification on non-empty" 514 "group leader exit"; 515 516 child_exit_secs = mmap(NULL, sizeof *child_exit_secs, PROT_READ | PROT_WRITE, 517 MAP_SHARED | MAP_ANONYMOUS, -1, 0); 518 519 if (child_exit_secs == MAP_FAILED) 520 ksft_exit_fail_msg("%s test: mmap failed (errno %d)\n", 521 test_name, errno); 522 523 ksft_print_msg("Parent: pid: %d\n", getpid()); 524 pid = pidfd_clone(CLONE_PIDFD, &pidfd, child_poll_leader_exit_test); 525 if (pid < 0) 526 ksft_exit_fail_msg("%s test: pidfd_clone failed (ret %d, errno %d)\n", 527 test_name, pid, errno); 528 529 ksft_print_msg("Parent: Waiting for Child (%d) to complete.\n", pid); 530 531 if (use_waitpid) { 532 ret = waitpid(pid, &status, 0); 533 if (ret == -1) 534 ksft_print_msg("Parent: error\n"); 535 } else { 536 /* 537 * This sleep tests for the case where if the child exits, and is in 538 * EXIT_ZOMBIE, but the thread group leader is non-empty, then the poll 539 * doesn't prematurely return even though there are active threads 540 */ 541 sleep(1); 542 poll_pidfd(test_name, pidfd); 543 } 544 545 if (ret == pid) 546 ksft_print_msg("Parent: Child process waited for.\n"); 547 548 time_t since_child_exit = time(NULL) - *child_exit_secs; 549 550 ksft_print_msg("Time since child exit: %lu\n", since_child_exit); 551 552 close(pidfd); 553 554 if (since_child_exit < CHILD_THREAD_MIN_WAIT || 555 since_child_exit > CHILD_THREAD_MIN_WAIT + 2) 556 ksft_exit_fail_msg("%s test: Failed\n", test_name); 557 else 558 ksft_test_result_pass("%s test: Passed\n", test_name); 559 } 560 561 int main(int argc, char **argv) 562 { 563 ksft_print_header(); 564 ksft_set_plan(8); 565 566 test_pidfd_poll_exec(0); 567 test_pidfd_poll_exec(1); 568 test_pidfd_poll_leader_exit(0); 569 test_pidfd_poll_leader_exit(1); 570 test_pidfd_send_signal_syscall_support(); 571 test_pidfd_send_signal_simple_success(); 572 test_pidfd_send_signal_exited_fail(); 573 test_pidfd_send_signal_recycled_pid_fail(); 574 575 ksft_exit_pass(); 576 } 577
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.