1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #define _GNU_SOURCE 4 #include <errno.h> 5 #include <linux/sched.h> 6 #include <linux/types.h> 7 #include <signal.h> 8 #include <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <sched.h> 12 #include <string.h> 13 #include <sys/resource.h> 14 #include <sys/time.h> 15 #include <sys/types.h> 16 #include <sys/wait.h> 17 #include <unistd.h> 18 19 #include "pidfd.h" 20 #include "../kselftest_harness.h" 21 22 #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr))) 23 24 /* Attempt to de-conflict with the selftests tree. */ 25 #ifndef SKIP 26 #define SKIP(s, ...) XFAIL(s, ##__VA_ARGS__) 27 #endif 28 29 TEST(wait_simple) 30 { 31 int pidfd = -1; 32 pid_t parent_tid = -1; 33 struct __clone_args args = { 34 .parent_tid = ptr_to_u64(&parent_tid), 35 .pidfd = ptr_to_u64(&pidfd), 36 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID, 37 .exit_signal = SIGCHLD, 38 }; 39 pid_t pid; 40 siginfo_t info = { 41 .si_signo = 0, 42 }; 43 44 pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC); 45 ASSERT_GE(pidfd, 0); 46 47 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED); 48 ASSERT_NE(pid, 0); 49 EXPECT_EQ(close(pidfd), 0); 50 pidfd = -1; 51 52 pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC); 53 ASSERT_GE(pidfd, 0); 54 55 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED); 56 ASSERT_NE(pid, 0); 57 EXPECT_EQ(close(pidfd), 0); 58 pidfd = -1; 59 60 pid = sys_clone3(&args, sizeof(args)); 61 ASSERT_GE(pid, 0); 62 63 if (pid == 0) 64 exit(EXIT_SUCCESS); 65 66 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED); 67 ASSERT_GE(pid, 0); 68 ASSERT_EQ(WIFEXITED(info.si_status), true); 69 ASSERT_EQ(WEXITSTATUS(info.si_status), 0); 70 EXPECT_EQ(close(pidfd), 0); 71 72 ASSERT_EQ(info.si_signo, SIGCHLD); 73 ASSERT_EQ(info.si_code, CLD_EXITED); 74 ASSERT_EQ(info.si_pid, parent_tid); 75 } 76 77 TEST(wait_states) 78 { 79 int pidfd = -1; 80 pid_t parent_tid = -1; 81 struct __clone_args args = { 82 .parent_tid = ptr_to_u64(&parent_tid), 83 .pidfd = ptr_to_u64(&pidfd), 84 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID, 85 .exit_signal = SIGCHLD, 86 }; 87 int pfd[2]; 88 pid_t pid; 89 siginfo_t info = { 90 .si_signo = 0, 91 }; 92 93 ASSERT_EQ(pipe(pfd), 0); 94 pid = sys_clone3(&args, sizeof(args)); 95 ASSERT_GE(pid, 0); 96 97 if (pid == 0) { 98 char buf[2]; 99 100 close(pfd[1]); 101 kill(getpid(), SIGSTOP); 102 ASSERT_EQ(read(pfd[0], buf, 1), 1); 103 close(pfd[0]); 104 kill(getpid(), SIGSTOP); 105 exit(EXIT_SUCCESS); 106 } 107 108 close(pfd[0]); 109 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED), 0); 110 ASSERT_EQ(info.si_signo, SIGCHLD); 111 ASSERT_EQ(info.si_code, CLD_STOPPED); 112 ASSERT_EQ(info.si_pid, parent_tid); 113 114 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0); 115 116 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED), 0); 117 ASSERT_EQ(write(pfd[1], "C", 1), 1); 118 close(pfd[1]); 119 ASSERT_EQ(info.si_signo, SIGCHLD); 120 ASSERT_EQ(info.si_code, CLD_CONTINUED); 121 ASSERT_EQ(info.si_pid, parent_tid); 122 123 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED), 0); 124 ASSERT_EQ(info.si_signo, SIGCHLD); 125 ASSERT_EQ(info.si_code, CLD_STOPPED); 126 ASSERT_EQ(info.si_pid, parent_tid); 127 128 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0), 0); 129 130 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED), 0); 131 ASSERT_EQ(info.si_signo, SIGCHLD); 132 ASSERT_EQ(info.si_code, CLD_KILLED); 133 ASSERT_EQ(info.si_pid, parent_tid); 134 135 EXPECT_EQ(close(pidfd), 0); 136 } 137 138 TEST(wait_nonblock) 139 { 140 int pidfd; 141 unsigned int flags = 0; 142 pid_t parent_tid = -1; 143 struct __clone_args args = { 144 .parent_tid = ptr_to_u64(&parent_tid), 145 .flags = CLONE_PARENT_SETTID, 146 .exit_signal = SIGCHLD, 147 }; 148 int ret; 149 pid_t pid; 150 siginfo_t info = { 151 .si_signo = 0, 152 }; 153 154 /* 155 * Callers need to see ECHILD with non-blocking pidfds when no child 156 * processes exists. 157 */ 158 pidfd = sys_pidfd_open(getpid(), PIDFD_NONBLOCK); 159 EXPECT_GE(pidfd, 0) { 160 /* pidfd_open() doesn't support PIDFD_NONBLOCK. */ 161 ASSERT_EQ(errno, EINVAL); 162 SKIP(return, "Skipping PIDFD_NONBLOCK test"); 163 } 164 165 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED); 166 ASSERT_LT(ret, 0); 167 ASSERT_EQ(errno, ECHILD); 168 EXPECT_EQ(close(pidfd), 0); 169 170 pid = sys_clone3(&args, sizeof(args)); 171 ASSERT_GE(pid, 0); 172 173 if (pid == 0) { 174 kill(getpid(), SIGSTOP); 175 exit(EXIT_SUCCESS); 176 } 177 178 pidfd = sys_pidfd_open(pid, PIDFD_NONBLOCK); 179 EXPECT_GE(pidfd, 0) { 180 /* pidfd_open() doesn't support PIDFD_NONBLOCK. */ 181 ASSERT_EQ(errno, EINVAL); 182 SKIP(return, "Skipping PIDFD_NONBLOCK test"); 183 } 184 185 flags = fcntl(pidfd, F_GETFL, 0); 186 ASSERT_GT(flags, 0); 187 ASSERT_GT((flags & O_NONBLOCK), 0); 188 189 /* 190 * Callers need to see EAGAIN/EWOULDBLOCK with non-blocking pidfd when 191 * child processes exist but none have exited. 192 */ 193 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED); 194 ASSERT_LT(ret, 0); 195 ASSERT_EQ(errno, EAGAIN); 196 197 /* 198 * Callers need to continue seeing 0 with non-blocking pidfd and 199 * WNOHANG raised explicitly when child processes exist but none have 200 * exited. 201 */ 202 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED | WNOHANG); 203 ASSERT_EQ(ret, 0); 204 205 ASSERT_EQ(fcntl(pidfd, F_SETFL, (flags & ~O_NONBLOCK)), 0); 206 207 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED), 0); 208 ASSERT_EQ(info.si_signo, SIGCHLD); 209 ASSERT_EQ(info.si_code, CLD_STOPPED); 210 ASSERT_EQ(info.si_pid, parent_tid); 211 212 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0); 213 214 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED), 0); 215 ASSERT_EQ(info.si_signo, SIGCHLD); 216 ASSERT_EQ(info.si_code, CLD_EXITED); 217 ASSERT_EQ(info.si_pid, parent_tid); 218 219 EXPECT_EQ(close(pidfd), 0); 220 } 221 222 TEST_HARNESS_MAIN 223