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