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