Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 
0003 #define _GNU_SOURCE
0004 #include <errno.h>
0005 #include <fcntl.h>
0006 #include <linux/types.h>
0007 #include <pthread.h>
0008 #include <sched.h>
0009 #include <signal.h>
0010 #include <stdio.h>
0011 #include <stdbool.h>
0012 #include <stdlib.h>
0013 #include <string.h>
0014 #include <syscall.h>
0015 #include <sys/epoll.h>
0016 #include <sys/mman.h>
0017 #include <sys/mount.h>
0018 #include <sys/wait.h>
0019 #include <time.h>
0020 #include <unistd.h>
0021 
0022 #include "pidfd.h"
0023 #include "../kselftest.h"
0024 
0025 #define str(s) _str(s)
0026 #define _str(s) #s
0027 #define CHILD_THREAD_MIN_WAIT 3 /* seconds */
0028 
0029 #define MAX_EVENTS 5
0030 
0031 static bool have_pidfd_send_signal;
0032 
0033 static pid_t pidfd_clone(int flags, int *pidfd, int (*fn)(void *))
0034 {
0035     size_t stack_size = 1024;
0036     char *stack[1024] = { 0 };
0037 
0038 #ifdef __ia64__
0039     return __clone2(fn, stack, stack_size, flags | SIGCHLD, NULL, pidfd);
0040 #else
0041     return clone(fn, stack + stack_size, flags | SIGCHLD, NULL, pidfd);
0042 #endif
0043 }
0044 
0045 static int signal_received;
0046 
0047 static void set_signal_received_on_sigusr1(int sig)
0048 {
0049     if (sig == SIGUSR1)
0050         signal_received = 1;
0051 }
0052 
0053 /*
0054  * Straightforward test to see whether pidfd_send_signal() works is to send
0055  * a signal to ourself.
0056  */
0057 static int test_pidfd_send_signal_simple_success(void)
0058 {
0059     int pidfd, ret;
0060     const char *test_name = "pidfd_send_signal send SIGUSR1";
0061 
0062     if (!have_pidfd_send_signal) {
0063         ksft_test_result_skip(
0064             "%s test: pidfd_send_signal() syscall not supported\n",
0065             test_name);
0066         return 0;
0067     }
0068 
0069     pidfd = open("/proc/self", O_DIRECTORY | O_CLOEXEC);
0070     if (pidfd < 0)
0071         ksft_exit_fail_msg(
0072             "%s test: Failed to open process file descriptor\n",
0073             test_name);
0074 
0075     signal(SIGUSR1, set_signal_received_on_sigusr1);
0076 
0077     ret = sys_pidfd_send_signal(pidfd, SIGUSR1, NULL, 0);
0078     close(pidfd);
0079     if (ret < 0)
0080         ksft_exit_fail_msg("%s test: Failed to send signal\n",
0081                    test_name);
0082 
0083     if (signal_received != 1)
0084         ksft_exit_fail_msg("%s test: Failed to receive signal\n",
0085                    test_name);
0086 
0087     signal_received = 0;
0088     ksft_test_result_pass("%s test: Sent signal\n", test_name);
0089     return 0;
0090 }
0091 
0092 static int test_pidfd_send_signal_exited_fail(void)
0093 {
0094     int pidfd, ret, saved_errno;
0095     char buf[256];
0096     pid_t pid;
0097     const char *test_name = "pidfd_send_signal signal exited process";
0098 
0099     if (!have_pidfd_send_signal) {
0100         ksft_test_result_skip(
0101             "%s test: pidfd_send_signal() syscall not supported\n",
0102             test_name);
0103         return 0;
0104     }
0105 
0106     pid = fork();
0107     if (pid < 0)
0108         ksft_exit_fail_msg("%s test: Failed to create new process\n",
0109                    test_name);
0110 
0111     if (pid == 0)
0112         _exit(EXIT_SUCCESS);
0113 
0114     snprintf(buf, sizeof(buf), "/proc/%d", pid);
0115 
0116     pidfd = open(buf, O_DIRECTORY | O_CLOEXEC);
0117 
0118     (void)wait_for_pid(pid);
0119 
0120     if (pidfd < 0)
0121         ksft_exit_fail_msg(
0122             "%s test: Failed to open process file descriptor\n",
0123             test_name);
0124 
0125     ret = sys_pidfd_send_signal(pidfd, 0, NULL, 0);
0126     saved_errno = errno;
0127     close(pidfd);
0128     if (ret == 0)
0129         ksft_exit_fail_msg(
0130             "%s test: Managed to send signal to process even though it should have failed\n",
0131             test_name);
0132 
0133     if (saved_errno != ESRCH)
0134         ksft_exit_fail_msg(
0135             "%s test: Expected to receive ESRCH as errno value but received %d instead\n",
0136             test_name, saved_errno);
0137 
0138     ksft_test_result_pass("%s test: Failed to send signal as expected\n",
0139                   test_name);
0140     return 0;
0141 }
0142 
0143 /*
0144  * Maximum number of cycles we allow. This is equivalent to PID_MAX_DEFAULT.
0145  * If users set a higher limit or we have cycled PIDFD_MAX_DEFAULT number of
0146  * times then we skip the test to not go into an infinite loop or block for a
0147  * long time.
0148  */
0149 #define PIDFD_MAX_DEFAULT 0x8000
0150 
0151 static int test_pidfd_send_signal_recycled_pid_fail(void)
0152 {
0153     int i, ret;
0154     pid_t pid1;
0155     const char *test_name = "pidfd_send_signal signal recycled pid";
0156 
0157     if (!have_pidfd_send_signal) {
0158         ksft_test_result_skip(
0159             "%s test: pidfd_send_signal() syscall not supported\n",
0160             test_name);
0161         return 0;
0162     }
0163 
0164     ret = unshare(CLONE_NEWPID);
0165     if (ret < 0) {
0166         if (errno == EPERM) {
0167             ksft_test_result_skip("%s test: Unsharing pid namespace not permitted\n",
0168                           test_name);
0169             return 0;
0170         }
0171         ksft_exit_fail_msg("%s test: Failed to unshare pid namespace\n",
0172                    test_name);
0173     }
0174 
0175     ret = unshare(CLONE_NEWNS);
0176     if (ret < 0) {
0177         if (errno == EPERM) {
0178             ksft_test_result_skip("%s test: Unsharing mount namespace not permitted\n",
0179                           test_name);
0180             return 0;
0181         }
0182         ksft_exit_fail_msg("%s test: Failed to unshare mount namespace\n",
0183                    test_name);
0184     }
0185 
0186     ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0);
0187     if (ret < 0)
0188         ksft_exit_fail_msg("%s test: Failed to remount / private\n",
0189                    test_name);
0190 
0191     /* pid 1 in new pid namespace */
0192     pid1 = fork();
0193     if (pid1 < 0)
0194         ksft_exit_fail_msg("%s test: Failed to create new process\n",
0195                    test_name);
0196 
0197     if (pid1 == 0) {
0198         char buf[256];
0199         pid_t pid2;
0200         int pidfd = -1;
0201 
0202         (void)umount2("/proc", MNT_DETACH);
0203         ret = mount("proc", "/proc", "proc", 0, NULL);
0204         if (ret < 0)
0205             _exit(PIDFD_ERROR);
0206 
0207         /* grab pid PID_RECYCLE */
0208         for (i = 0; i <= PIDFD_MAX_DEFAULT; i++) {
0209             pid2 = fork();
0210             if (pid2 < 0)
0211                 _exit(PIDFD_ERROR);
0212 
0213             if (pid2 == 0)
0214                 _exit(PIDFD_PASS);
0215 
0216             if (pid2 == PID_RECYCLE) {
0217                 snprintf(buf, sizeof(buf), "/proc/%d", pid2);
0218                 ksft_print_msg("pid to recycle is %d\n", pid2);
0219                 pidfd = open(buf, O_DIRECTORY | O_CLOEXEC);
0220             }
0221 
0222             if (wait_for_pid(pid2))
0223                 _exit(PIDFD_ERROR);
0224 
0225             if (pid2 >= PID_RECYCLE)
0226                 break;
0227         }
0228 
0229         /*
0230          * We want to be as predictable as we can so if we haven't been
0231          * able to grab pid PID_RECYCLE skip the test.
0232          */
0233         if (pid2 != PID_RECYCLE) {
0234             /* skip test */
0235             close(pidfd);
0236             _exit(PIDFD_SKIP);
0237         }
0238 
0239         if (pidfd < 0)
0240             _exit(PIDFD_ERROR);
0241 
0242         for (i = 0; i <= PIDFD_MAX_DEFAULT; i++) {
0243             char c;
0244             int pipe_fds[2];
0245             pid_t recycled_pid;
0246             int child_ret = PIDFD_PASS;
0247 
0248             ret = pipe2(pipe_fds, O_CLOEXEC);
0249             if (ret < 0)
0250                 _exit(PIDFD_ERROR);
0251 
0252             recycled_pid = fork();
0253             if (recycled_pid < 0)
0254                 _exit(PIDFD_ERROR);
0255 
0256             if (recycled_pid == 0) {
0257                 close(pipe_fds[1]);
0258                 (void)read(pipe_fds[0], &c, 1);
0259                 close(pipe_fds[0]);
0260 
0261                 _exit(PIDFD_PASS);
0262             }
0263 
0264             /*
0265              * Stop the child so we can inspect whether we have
0266              * recycled pid PID_RECYCLE.
0267              */
0268             close(pipe_fds[0]);
0269             ret = kill(recycled_pid, SIGSTOP);
0270             close(pipe_fds[1]);
0271             if (ret) {
0272                 (void)wait_for_pid(recycled_pid);
0273                 _exit(PIDFD_ERROR);
0274             }
0275 
0276             /*
0277              * We have recycled the pid. Try to signal it. This
0278              * needs to fail since this is a different process than
0279              * the one the pidfd refers to.
0280              */
0281             if (recycled_pid == PID_RECYCLE) {
0282                 ret = sys_pidfd_send_signal(pidfd, SIGCONT,
0283                                 NULL, 0);
0284                 if (ret && errno == ESRCH)
0285                     child_ret = PIDFD_XFAIL;
0286                 else
0287                     child_ret = PIDFD_FAIL;
0288             }
0289 
0290             /* let the process move on */
0291             ret = kill(recycled_pid, SIGCONT);
0292             if (ret)
0293                 (void)kill(recycled_pid, SIGKILL);
0294 
0295             if (wait_for_pid(recycled_pid))
0296                 _exit(PIDFD_ERROR);
0297 
0298             switch (child_ret) {
0299             case PIDFD_FAIL:
0300                 /* fallthrough */
0301             case PIDFD_XFAIL:
0302                 _exit(child_ret);
0303             case PIDFD_PASS:
0304                 break;
0305             default:
0306                 /* not reached */
0307                 _exit(PIDFD_ERROR);
0308             }
0309 
0310             /*
0311              * If the user set a custom pid_max limit we could be
0312              * in the millions.
0313              * Skip the test in this case.
0314              */
0315             if (recycled_pid > PIDFD_MAX_DEFAULT)
0316                 _exit(PIDFD_SKIP);
0317         }
0318 
0319         /* failed to recycle pid */
0320         _exit(PIDFD_SKIP);
0321     }
0322 
0323     ret = wait_for_pid(pid1);
0324     switch (ret) {
0325     case PIDFD_FAIL:
0326         ksft_exit_fail_msg(
0327             "%s test: Managed to signal recycled pid %d\n",
0328             test_name, PID_RECYCLE);
0329     case PIDFD_PASS:
0330         ksft_exit_fail_msg("%s test: Failed to recycle pid %d\n",
0331                    test_name, PID_RECYCLE);
0332     case PIDFD_SKIP:
0333         ksft_test_result_skip("%s test: Skipping test\n", test_name);
0334         ret = 0;
0335         break;
0336     case PIDFD_XFAIL:
0337         ksft_test_result_pass(
0338             "%s test: Failed to signal recycled pid as expected\n",
0339             test_name);
0340         ret = 0;
0341         break;
0342     default /* PIDFD_ERROR */:
0343         ksft_exit_fail_msg("%s test: Error while running tests\n",
0344                    test_name);
0345     }
0346 
0347     return ret;
0348 }
0349 
0350 static int test_pidfd_send_signal_syscall_support(void)
0351 {
0352     int pidfd, ret;
0353     const char *test_name = "pidfd_send_signal check for support";
0354 
0355     pidfd = open("/proc/self", O_DIRECTORY | O_CLOEXEC);
0356     if (pidfd < 0)
0357         ksft_exit_fail_msg(
0358             "%s test: Failed to open process file descriptor\n",
0359             test_name);
0360 
0361     ret = sys_pidfd_send_signal(pidfd, 0, NULL, 0);
0362     if (ret < 0) {
0363         if (errno == ENOSYS) {
0364             ksft_test_result_skip(
0365                 "%s test: pidfd_send_signal() syscall not supported\n",
0366                 test_name);
0367             return 0;
0368         }
0369         ksft_exit_fail_msg("%s test: Failed to send signal\n",
0370                    test_name);
0371     }
0372 
0373     have_pidfd_send_signal = true;
0374     close(pidfd);
0375     ksft_test_result_pass(
0376         "%s test: pidfd_send_signal() syscall is supported. Tests can be executed\n",
0377         test_name);
0378     return 0;
0379 }
0380 
0381 static void *test_pidfd_poll_exec_thread(void *priv)
0382 {
0383     ksft_print_msg("Child Thread: starting. pid %d tid %d ; and sleeping\n",
0384             getpid(), syscall(SYS_gettid));
0385     ksft_print_msg("Child Thread: doing exec of sleep\n");
0386 
0387     execl("/bin/sleep", "sleep", str(CHILD_THREAD_MIN_WAIT), (char *)NULL);
0388 
0389     ksft_print_msg("Child Thread: DONE. pid %d tid %d\n",
0390             getpid(), syscall(SYS_gettid));
0391     return NULL;
0392 }
0393 
0394 static void poll_pidfd(const char *test_name, int pidfd)
0395 {
0396     int c;
0397     int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
0398     struct epoll_event event, events[MAX_EVENTS];
0399 
0400     if (epoll_fd == -1)
0401         ksft_exit_fail_msg("%s test: Failed to create epoll file descriptor "
0402                    "(errno %d)\n",
0403                    test_name, errno);
0404 
0405     event.events = EPOLLIN;
0406     event.data.fd = pidfd;
0407 
0408     if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pidfd, &event)) {
0409         ksft_exit_fail_msg("%s test: Failed to add epoll file descriptor "
0410                    "(errno %d)\n",
0411                    test_name, errno);
0412     }
0413 
0414     c = epoll_wait(epoll_fd, events, MAX_EVENTS, 5000);
0415     if (c != 1 || !(events[0].events & EPOLLIN))
0416         ksft_exit_fail_msg("%s test: Unexpected epoll_wait result (c=%d, events=%x) ",
0417                    "(errno %d)\n",
0418                    test_name, c, events[0].events, errno);
0419 
0420     close(epoll_fd);
0421     return;
0422 
0423 }
0424 
0425 static int child_poll_exec_test(void *args)
0426 {
0427     pthread_t t1;
0428 
0429     ksft_print_msg("Child (pidfd): starting. pid %d tid %d\n", getpid(),
0430             syscall(SYS_gettid));
0431     pthread_create(&t1, NULL, test_pidfd_poll_exec_thread, NULL);
0432     /*
0433      * Exec in the non-leader thread will destroy the leader immediately.
0434      * If the wait in the parent returns too soon, the test fails.
0435      */
0436     while (1)
0437         sleep(1);
0438 }
0439 
0440 static void test_pidfd_poll_exec(int use_waitpid)
0441 {
0442     int pid, pidfd = 0;
0443     int status, ret;
0444     time_t prog_start = time(NULL);
0445     const char *test_name = "pidfd_poll check for premature notification on child thread exec";
0446 
0447     ksft_print_msg("Parent: pid: %d\n", getpid());
0448     pid = pidfd_clone(CLONE_PIDFD, &pidfd, child_poll_exec_test);
0449     if (pid < 0)
0450         ksft_exit_fail_msg("%s test: pidfd_clone failed (ret %d, errno %d)\n",
0451                    test_name, pid, errno);
0452 
0453     ksft_print_msg("Parent: Waiting for Child (%d) to complete.\n", pid);
0454 
0455     if (use_waitpid) {
0456         ret = waitpid(pid, &status, 0);
0457         if (ret == -1)
0458             ksft_print_msg("Parent: error\n");
0459 
0460         if (ret == pid)
0461             ksft_print_msg("Parent: Child process waited for.\n");
0462     } else {
0463         poll_pidfd(test_name, pidfd);
0464     }
0465 
0466     time_t prog_time = time(NULL) - prog_start;
0467 
0468     ksft_print_msg("Time waited for child: %lu\n", prog_time);
0469 
0470     close(pidfd);
0471 
0472     if (prog_time < CHILD_THREAD_MIN_WAIT || prog_time > CHILD_THREAD_MIN_WAIT + 2)
0473         ksft_exit_fail_msg("%s test: Failed\n", test_name);
0474     else
0475         ksft_test_result_pass("%s test: Passed\n", test_name);
0476 }
0477 
0478 static void *test_pidfd_poll_leader_exit_thread(void *priv)
0479 {
0480     ksft_print_msg("Child Thread: starting. pid %d tid %d ; and sleeping\n",
0481             getpid(), syscall(SYS_gettid));
0482     sleep(CHILD_THREAD_MIN_WAIT);
0483     ksft_print_msg("Child Thread: DONE. pid %d tid %d\n", getpid(), syscall(SYS_gettid));
0484     return NULL;
0485 }
0486 
0487 static time_t *child_exit_secs;
0488 static int child_poll_leader_exit_test(void *args)
0489 {
0490     pthread_t t1, t2;
0491 
0492     ksft_print_msg("Child: starting. pid %d tid %d\n", getpid(), syscall(SYS_gettid));
0493     pthread_create(&t1, NULL, test_pidfd_poll_leader_exit_thread, NULL);
0494     pthread_create(&t2, NULL, test_pidfd_poll_leader_exit_thread, NULL);
0495 
0496     /*
0497      * glibc exit calls exit_group syscall, so explicity call exit only
0498      * so that only the group leader exits, leaving the threads alone.
0499      */
0500     *child_exit_secs = time(NULL);
0501     syscall(SYS_exit, 0);
0502     /* Never reached, but appeases compiler thinking we should return. */
0503     exit(0);
0504 }
0505 
0506 static void test_pidfd_poll_leader_exit(int use_waitpid)
0507 {
0508     int pid, pidfd = 0;
0509     int status, ret = 0;
0510     const char *test_name = "pidfd_poll check for premature notification on non-empty"
0511                 "group leader exit";
0512 
0513     child_exit_secs = mmap(NULL, sizeof *child_exit_secs, PROT_READ | PROT_WRITE,
0514             MAP_SHARED | MAP_ANONYMOUS, -1, 0);
0515 
0516     if (child_exit_secs == MAP_FAILED)
0517         ksft_exit_fail_msg("%s test: mmap failed (errno %d)\n",
0518                    test_name, errno);
0519 
0520     ksft_print_msg("Parent: pid: %d\n", getpid());
0521     pid = pidfd_clone(CLONE_PIDFD, &pidfd, child_poll_leader_exit_test);
0522     if (pid < 0)
0523         ksft_exit_fail_msg("%s test: pidfd_clone failed (ret %d, errno %d)\n",
0524                    test_name, pid, errno);
0525 
0526     ksft_print_msg("Parent: Waiting for Child (%d) to complete.\n", pid);
0527 
0528     if (use_waitpid) {
0529         ret = waitpid(pid, &status, 0);
0530         if (ret == -1)
0531             ksft_print_msg("Parent: error\n");
0532     } else {
0533         /*
0534          * This sleep tests for the case where if the child exits, and is in
0535          * EXIT_ZOMBIE, but the thread group leader is non-empty, then the poll
0536          * doesn't prematurely return even though there are active threads
0537          */
0538         sleep(1);
0539         poll_pidfd(test_name, pidfd);
0540     }
0541 
0542     if (ret == pid)
0543         ksft_print_msg("Parent: Child process waited for.\n");
0544 
0545     time_t since_child_exit = time(NULL) - *child_exit_secs;
0546 
0547     ksft_print_msg("Time since child exit: %lu\n", since_child_exit);
0548 
0549     close(pidfd);
0550 
0551     if (since_child_exit < CHILD_THREAD_MIN_WAIT ||
0552             since_child_exit > CHILD_THREAD_MIN_WAIT + 2)
0553         ksft_exit_fail_msg("%s test: Failed\n", test_name);
0554     else
0555         ksft_test_result_pass("%s test: Passed\n", test_name);
0556 }
0557 
0558 int main(int argc, char **argv)
0559 {
0560     ksft_print_header();
0561     ksft_set_plan(8);
0562 
0563     test_pidfd_poll_exec(0);
0564     test_pidfd_poll_exec(1);
0565     test_pidfd_poll_leader_exit(0);
0566     test_pidfd_poll_leader_exit(1);
0567     test_pidfd_send_signal_syscall_support();
0568     test_pidfd_send_signal_simple_success();
0569     test_pidfd_send_signal_exited_fail();
0570     test_pidfd_send_signal_recycled_pid_fail();
0571 
0572     return ksft_exit_pass();
0573 }