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 <sched.h> 8 #include <signal.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <syscall.h> 13 #include <sys/mount.h> 14 #include <sys/wait.h> 15 #include <unistd.h> 16 17 #include "../kselftest.h" 18 19 static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info, 20 unsigned int flags) 21 { 22 return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags); 23 } 24 25 static int signal_received; 26 27 static void set_signal_received_on_sigusr1(int sig) 28 { 29 if (sig == SIGUSR1) 30 signal_received = 1; 31 } 32 33 /* 34 * Straightforward test to see whether pidfd_send_signal() works is to send 35 * a signal to ourself. 36 */ 37 static int test_pidfd_send_signal_simple_success(void) 38 { 39 int pidfd, ret; 40 const char *test_name = "pidfd_send_signal send SIGUSR1"; 41 42 pidfd = open("/proc/self", O_DIRECTORY | O_CLOEXEC); 43 if (pidfd < 0) 44 ksft_exit_fail_msg( 45 "%s test: Failed to open process file descriptor\n", 46 test_name); 47 48 signal(SIGUSR1, set_signal_received_on_sigusr1); 49 50 ret = sys_pidfd_send_signal(pidfd, SIGUSR1, NULL, 0); 51 close(pidfd); 52 if (ret < 0) 53 ksft_exit_fail_msg("%s test: Failed to send signal\n", 54 test_name); 55 56 if (signal_received != 1) 57 ksft_exit_fail_msg("%s test: Failed to receive signal\n", 58 test_name); 59 60 signal_received = 0; 61 ksft_test_result_pass("%s test: Sent signal\n", test_name); 62 return 0; 63 } 64 65 static int wait_for_pid(pid_t pid) 66 { 67 int status, ret; 68 69 again: 70 ret = waitpid(pid, &status, 0); 71 if (ret == -1) { 72 if (errno == EINTR) 73 goto again; 74 75 return -1; 76 } 77 78 if (ret != pid) 79 goto again; 80 81 if (!WIFEXITED(status)) 82 return -1; 83 84 return WEXITSTATUS(status); 85 } 86 87 static int test_pidfd_send_signal_exited_fail(void) 88 { 89 int pidfd, ret, saved_errno; 90 char buf[256]; 91 pid_t pid; 92 const char *test_name = "pidfd_send_signal signal exited process"; 93 94 pid = fork(); 95 if (pid < 0) 96 ksft_exit_fail_msg("%s test: Failed to create new process\n", 97 test_name); 98 99 if (pid == 0) 100 _exit(EXIT_SUCCESS); 101 102 snprintf(buf, sizeof(buf), "/proc/%d", pid); 103 104 pidfd = open(buf, O_DIRECTORY | O_CLOEXEC); 105 106 (void)wait_for_pid(pid); 107 108 if (pidfd < 0) 109 ksft_exit_fail_msg( 110 "%s test: Failed to open process file descriptor\n", 111 test_name); 112 113 ret = sys_pidfd_send_signal(pidfd, 0, NULL, 0); 114 saved_errno = errno; 115 close(pidfd); 116 if (ret == 0) 117 ksft_exit_fail_msg( 118 "%s test: Managed to send signal to process even though it should have failed\n", 119 test_name); 120 121 if (saved_errno != ESRCH) 122 ksft_exit_fail_msg( 123 "%s test: Expected to receive ESRCH as errno value but received %d instead\n", 124 test_name, saved_errno); 125 126 ksft_test_result_pass("%s test: Failed to send signal as expected\n", 127 test_name); 128 return 0; 129 } 130 131 /* 132 * The kernel reserves 300 pids via RESERVED_PIDS in kernel/pid.c 133 * That means, when it wraps around any pid < 300 will be skipped. 134 * So we need to use a pid > 300 in order to test recycling. 135 */ 136 #define PID_RECYCLE 1000 137 138 /* 139 * Maximum number of cycles we allow. This is equivalent to PID_MAX_DEFAULT. 140 * If users set a higher limit or we have cycled PIDFD_MAX_DEFAULT number of 141 * times then we skip the test to not go into an infinite loop or block for a 142 * long time. 143 */ 144 #define PIDFD_MAX_DEFAULT 0x8000 145 146 /* 147 * Define a few custom error codes for the child process to clearly indicate 148 * what is happening. This way we can tell the difference between a system 149 * error, a test error, etc. 150 */ 151 #define PIDFD_PASS 0 152 #define PIDFD_FAIL 1 153 #define PIDFD_ERROR 2 154 #define PIDFD_SKIP 3 155 #define PIDFD_XFAIL 4 156 157 static int test_pidfd_send_signal_recycled_pid_fail(void) 158 { 159 int i, ret; 160 pid_t pid1; 161 const char *test_name = "pidfd_send_signal signal recycled pid"; 162 163 ret = unshare(CLONE_NEWPID); 164 if (ret < 0) 165 ksft_exit_fail_msg("%s test: Failed to unshare pid namespace\n", 166 test_name); 167 168 ret = unshare(CLONE_NEWNS); 169 if (ret < 0) 170 ksft_exit_fail_msg( 171 "%s test: Failed to unshare mount namespace\n", 172 test_name); 173 174 ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0); 175 if (ret < 0) 176 ksft_exit_fail_msg("%s test: Failed to remount / private\n", 177 test_name); 178 179 /* pid 1 in new pid namespace */ 180 pid1 = fork(); 181 if (pid1 < 0) 182 ksft_exit_fail_msg("%s test: Failed to create new process\n", 183 test_name); 184 185 if (pid1 == 0) { 186 char buf[256]; 187 pid_t pid2; 188 int pidfd = -1; 189 190 (void)umount2("/proc", MNT_DETACH); 191 ret = mount("proc", "/proc", "proc", 0, NULL); 192 if (ret < 0) 193 _exit(PIDFD_ERROR); 194 195 /* grab pid PID_RECYCLE */ 196 for (i = 0; i <= PIDFD_MAX_DEFAULT; i++) { 197 pid2 = fork(); 198 if (pid2 < 0) 199 _exit(PIDFD_ERROR); 200 201 if (pid2 == 0) 202 _exit(PIDFD_PASS); 203 204 if (pid2 == PID_RECYCLE) { 205 snprintf(buf, sizeof(buf), "/proc/%d", pid2); 206 ksft_print_msg("pid to recycle is %d\n", pid2); 207 pidfd = open(buf, O_DIRECTORY | O_CLOEXEC); 208 } 209 210 if (wait_for_pid(pid2)) 211 _exit(PIDFD_ERROR); 212 213 if (pid2 >= PID_RECYCLE) 214 break; 215 } 216 217 /* 218 * We want to be as predictable as we can so if we haven't been 219 * able to grab pid PID_RECYCLE skip the test. 220 */ 221 if (pid2 != PID_RECYCLE) { 222 /* skip test */ 223 close(pidfd); 224 _exit(PIDFD_SKIP); 225 } 226 227 if (pidfd < 0) 228 _exit(PIDFD_ERROR); 229 230 for (i = 0; i <= PIDFD_MAX_DEFAULT; i++) { 231 char c; 232 int pipe_fds[2]; 233 pid_t recycled_pid; 234 int child_ret = PIDFD_PASS; 235 236 ret = pipe2(pipe_fds, O_CLOEXEC); 237 if (ret < 0) 238 _exit(PIDFD_ERROR); 239 240 recycled_pid = fork(); 241 if (recycled_pid < 0) 242 _exit(PIDFD_ERROR); 243 244 if (recycled_pid == 0) { 245 close(pipe_fds[1]); 246 (void)read(pipe_fds[0], &c, 1); 247 close(pipe_fds[0]); 248 249 _exit(PIDFD_PASS); 250 } 251 252 /* 253 * Stop the child so we can inspect whether we have 254 * recycled pid PID_RECYCLE. 255 */ 256 close(pipe_fds[0]); 257 ret = kill(recycled_pid, SIGSTOP); 258 close(pipe_fds[1]); 259 if (ret) { 260 (void)wait_for_pid(recycled_pid); 261 _exit(PIDFD_ERROR); 262 } 263 264 /* 265 * We have recycled the pid. Try to signal it. This 266 * needs to fail since this is a different process than 267 * the one the pidfd refers to. 268 */ 269 if (recycled_pid == PID_RECYCLE) { 270 ret = sys_pidfd_send_signal(pidfd, SIGCONT, 271 NULL, 0); 272 if (ret && errno == ESRCH) 273 child_ret = PIDFD_XFAIL; 274 else 275 child_ret = PIDFD_FAIL; 276 } 277 278 /* let the process move on */ 279 ret = kill(recycled_pid, SIGCONT); 280 if (ret) 281 (void)kill(recycled_pid, SIGKILL); 282 283 if (wait_for_pid(recycled_pid)) 284 _exit(PIDFD_ERROR); 285 286 switch (child_ret) { 287 case PIDFD_FAIL: 288 /* fallthrough */ 289 case PIDFD_XFAIL: 290 _exit(child_ret); 291 case PIDFD_PASS: 292 break; 293 default: 294 /* not reached */ 295 _exit(PIDFD_ERROR); 296 } 297 298 /* 299 * If the user set a custom pid_max limit we could be 300 * in the millions. 301 * Skip the test in this case. 302 */ 303 if (recycled_pid > PIDFD_MAX_DEFAULT) 304 _exit(PIDFD_SKIP); 305 } 306 307 /* failed to recycle pid */ 308 _exit(PIDFD_SKIP); 309 } 310 311 ret = wait_for_pid(pid1); 312 switch (ret) { 313 case PIDFD_FAIL: 314 ksft_exit_fail_msg( 315 "%s test: Managed to signal recycled pid %d\n", 316 test_name, PID_RECYCLE); 317 case PIDFD_PASS: 318 ksft_exit_fail_msg("%s test: Failed to recycle pid %d\n", 319 test_name, PID_RECYCLE); 320 case PIDFD_SKIP: 321 ksft_print_msg("%s test: Skipping test\n", test_name); 322 ret = 0; 323 break; 324 case PIDFD_XFAIL: 325 ksft_test_result_pass( 326 "%s test: Failed to signal recycled pid as expected\n", 327 test_name); 328 ret = 0; 329 break; 330 default /* PIDFD_ERROR */: 331 ksft_exit_fail_msg("%s test: Error while running tests\n", 332 test_name); 333 } 334 335 return ret; 336 } 337 338 static int test_pidfd_send_signal_syscall_support(void) 339 { 340 int pidfd, ret; 341 const char *test_name = "pidfd_send_signal check for support"; 342 343 pidfd = open("/proc/self", O_DIRECTORY | O_CLOEXEC); 344 if (pidfd < 0) 345 ksft_exit_fail_msg( 346 "%s test: Failed to open process file descriptor\n", 347 test_name); 348 349 ret = sys_pidfd_send_signal(pidfd, 0, NULL, 0); 350 if (ret < 0) { 351 /* 352 * pidfd_send_signal() will currently return ENOSYS when 353 * CONFIG_PROC_FS is not set. 354 */ 355 if (errno == ENOSYS) 356 ksft_exit_skip( 357 "%s test: pidfd_send_signal() syscall not supported (Ensure that CONFIG_PROC_FS=y is set)\n", 358 test_name); 359 360 ksft_exit_fail_msg("%s test: Failed to send signal\n", 361 test_name); 362 } 363 364 close(pidfd); 365 ksft_test_result_pass( 366 "%s test: pidfd_send_signal() syscall is supported. Tests can be executed\n", 367 test_name); 368 return 0; 369 } 370 371 int main(int argc, char **argv) 372 { 373 ksft_print_header(); 374 375 test_pidfd_send_signal_syscall_support(); 376 test_pidfd_send_signal_simple_success(); 377 test_pidfd_send_signal_exited_fail(); 378 test_pidfd_send_signal_recycled_pid_fail(); 379 380 return ksft_exit_pass(); 381 } 382