root/tools/testing/selftests/pidfd/pidfd_test.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pidfd_clone
  2. set_signal_received_on_sigusr1
  3. test_pidfd_send_signal_simple_success
  4. test_pidfd_send_signal_exited_fail
  5. test_pidfd_send_signal_recycled_pid_fail
  6. test_pidfd_send_signal_syscall_support
  7. test_pidfd_poll_exec_thread
  8. poll_pidfd
  9. child_poll_exec_test
  10. test_pidfd_poll_exec
  11. test_pidfd_poll_leader_exit_thread
  12. child_poll_leader_exit_test
  13. test_pidfd_poll_leader_exit
  14. main

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

/* [<][>][^][v][top][bottom][index][help] */