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