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