0001
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
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
0055
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
0145
0146
0147
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
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
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
0231
0232
0233 if (pid2 != PID_RECYCLE) {
0234
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
0266
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
0278
0279
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
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
0301 case PIDFD_XFAIL:
0302 _exit(child_ret);
0303 case PIDFD_PASS:
0304 break;
0305 default:
0306
0307 _exit(PIDFD_ERROR);
0308 }
0309
0310
0311
0312
0313
0314
0315 if (recycled_pid > PIDFD_MAX_DEFAULT)
0316 _exit(PIDFD_SKIP);
0317 }
0318
0319
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 :
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
0434
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
0498
0499
0500 *child_exit_secs = time(NULL);
0501 syscall(SYS_exit, 0);
0502
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
0535
0536
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 }