Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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 <pthread.h>
  8#include <sched.h>
  9#include <signal.h>
 10#include <stdio.h>
 11#include <stdbool.h>
 12#include <stdlib.h>
 13#include <string.h>
 14#include <syscall.h>
 15#include <sys/epoll.h>
 16#include <sys/mman.h>
 17#include <sys/mount.h>
 18#include <sys/wait.h>
 19#include <time.h>
 20#include <unistd.h>
 21
 22#include "pidfd.h"
 23#include "../kselftest.h"
 24
 25#define str(s) _str(s)
 26#define _str(s) #s
 27#define CHILD_THREAD_MIN_WAIT 3 /* seconds */
 28
 29#define MAX_EVENTS 5
 30
 31static bool have_pidfd_send_signal;
 32
 33static pid_t pidfd_clone(int flags, int *pidfd, int (*fn)(void *))
 34{
 35	size_t stack_size = 1024;
 36	char *stack[1024] = { 0 };
 37
 38#ifdef __ia64__
 39	return __clone2(fn, stack, stack_size, flags | SIGCHLD, NULL, pidfd);
 40#else
 41	return clone(fn, stack + stack_size, flags | SIGCHLD, NULL, pidfd);
 42#endif
 43}
 44
 45static int signal_received;
 46
 47static void set_signal_received_on_sigusr1(int sig)
 48{
 49	if (sig == SIGUSR1)
 50		signal_received = 1;
 51}
 52
 53/*
 54 * Straightforward test to see whether pidfd_send_signal() works is to send
 55 * a signal to ourself.
 56 */
 57static int test_pidfd_send_signal_simple_success(void)
 58{
 59	int pidfd, ret;
 60	const char *test_name = "pidfd_send_signal send SIGUSR1";
 61
 62	if (!have_pidfd_send_signal) {
 63		ksft_test_result_skip(
 64			"%s test: pidfd_send_signal() syscall not supported\n",
 65			test_name);
 66		return 0;
 67	}
 68
 69	pidfd = open("/proc/self", O_DIRECTORY | O_CLOEXEC);
 70	if (pidfd < 0)
 71		ksft_exit_fail_msg(
 72			"%s test: Failed to open process file descriptor\n",
 73			test_name);
 74
 75	signal(SIGUSR1, set_signal_received_on_sigusr1);
 76
 77	ret = sys_pidfd_send_signal(pidfd, SIGUSR1, NULL, 0);
 78	close(pidfd);
 79	if (ret < 0)
 80		ksft_exit_fail_msg("%s test: Failed to send signal\n",
 81				   test_name);
 82
 83	if (signal_received != 1)
 84		ksft_exit_fail_msg("%s test: Failed to receive signal\n",
 85				   test_name);
 86
 87	signal_received = 0;
 88	ksft_test_result_pass("%s test: Sent signal\n", test_name);
 89	return 0;
 90}
 91
 92static int test_pidfd_send_signal_exited_fail(void)
 93{
 94	int pidfd, ret, saved_errno;
 95	char buf[256];
 96	pid_t pid;
 97	const char *test_name = "pidfd_send_signal signal exited process";
 98
 99	if (!have_pidfd_send_signal) {
100		ksft_test_result_skip(
101			"%s test: pidfd_send_signal() syscall not supported\n",
102			test_name);
103		return 0;
104	}
105
106	pid = fork();
107	if (pid < 0)
108		ksft_exit_fail_msg("%s test: Failed to create new process\n",
109				   test_name);
110
111	if (pid == 0)
112		_exit(EXIT_SUCCESS);
113
114	snprintf(buf, sizeof(buf), "/proc/%d", pid);
115
116	pidfd = open(buf, O_DIRECTORY | O_CLOEXEC);
117
118	(void)wait_for_pid(pid);
119
120	if (pidfd < 0)
121		ksft_exit_fail_msg(
122			"%s test: Failed to open process file descriptor\n",
123			test_name);
124
125	ret = sys_pidfd_send_signal(pidfd, 0, NULL, 0);
126	saved_errno = errno;
127	close(pidfd);
128	if (ret == 0)
129		ksft_exit_fail_msg(
130			"%s test: Managed to send signal to process even though it should have failed\n",
131			test_name);
132
133	if (saved_errno != ESRCH)
134		ksft_exit_fail_msg(
135			"%s test: Expected to receive ESRCH as errno value but received %d instead\n",
136			test_name, saved_errno);
137
138	ksft_test_result_pass("%s test: Failed to send signal as expected\n",
139			      test_name);
140	return 0;
141}
142
143/*
144 * Maximum number of cycles we allow. This is equivalent to PID_MAX_DEFAULT.
145 * If users set a higher limit or we have cycled PIDFD_MAX_DEFAULT number of
146 * times then we skip the test to not go into an infinite loop or block for a
147 * long time.
148 */
149#define PIDFD_MAX_DEFAULT 0x8000
150
151static int test_pidfd_send_signal_recycled_pid_fail(void)
152{
153	int i, ret;
154	pid_t pid1;
155	const char *test_name = "pidfd_send_signal signal recycled pid";
156
157	if (!have_pidfd_send_signal) {
158		ksft_test_result_skip(
159			"%s test: pidfd_send_signal() syscall not supported\n",
160			test_name);
161		return 0;
162	}
163
164	ret = unshare(CLONE_NEWPID);
165	if (ret < 0) {
166		if (errno == EPERM) {
167			ksft_test_result_skip("%s test: Unsharing pid namespace not permitted\n",
168					      test_name);
169			return 0;
170		}
171		ksft_exit_fail_msg("%s test: Failed to unshare pid namespace\n",
172				   test_name);
173	}
174
175	ret = unshare(CLONE_NEWNS);
176	if (ret < 0) {
177		if (errno == EPERM) {
178			ksft_test_result_skip("%s test: Unsharing mount namespace not permitted\n",
179					      test_name);
180			return 0;
181		}
182		ksft_exit_fail_msg("%s test: Failed to unshare mount namespace\n",
183				   test_name);
184	}
185
186	ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0);
187	if (ret < 0)
188		ksft_exit_fail_msg("%s test: Failed to remount / private\n",
189				   test_name);
190
191	/* pid 1 in new pid namespace */
192	pid1 = fork();
193	if (pid1 < 0)
194		ksft_exit_fail_msg("%s test: Failed to create new process\n",
195				   test_name);
196
197	if (pid1 == 0) {
198		char buf[256];
199		pid_t pid2;
200		int pidfd = -1;
201
202		(void)umount2("/proc", MNT_DETACH);
203		ret = mount("proc", "/proc", "proc", 0, NULL);
204		if (ret < 0)
205			_exit(PIDFD_ERROR);
206
207		/* grab pid PID_RECYCLE */
208		for (i = 0; i <= PIDFD_MAX_DEFAULT; i++) {
209			pid2 = fork();
210			if (pid2 < 0)
211				_exit(PIDFD_ERROR);
212
213			if (pid2 == 0)
214				_exit(PIDFD_PASS);
215
216			if (pid2 == PID_RECYCLE) {
217				snprintf(buf, sizeof(buf), "/proc/%d", pid2);
218				ksft_print_msg("pid to recycle is %d\n", pid2);
219				pidfd = open(buf, O_DIRECTORY | O_CLOEXEC);
220			}
221
222			if (wait_for_pid(pid2))
223				_exit(PIDFD_ERROR);
224
225			if (pid2 >= PID_RECYCLE)
226				break;
227		}
228
229		/*
230		 * We want to be as predictable as we can so if we haven't been
231		 * able to grab pid PID_RECYCLE skip the test.
232		 */
233		if (pid2 != PID_RECYCLE) {
234			/* skip test */
235			close(pidfd);
236			_exit(PIDFD_SKIP);
237		}
238
239		if (pidfd < 0)
240			_exit(PIDFD_ERROR);
241
242		for (i = 0; i <= PIDFD_MAX_DEFAULT; i++) {
243			char c;
244			int pipe_fds[2];
245			pid_t recycled_pid;
246			int child_ret = PIDFD_PASS;
247
248			ret = pipe2(pipe_fds, O_CLOEXEC);
249			if (ret < 0)
250				_exit(PIDFD_ERROR);
251
252			recycled_pid = fork();
253			if (recycled_pid < 0)
254				_exit(PIDFD_ERROR);
255
256			if (recycled_pid == 0) {
257				close(pipe_fds[1]);
258				(void)read(pipe_fds[0], &c, 1);
259				close(pipe_fds[0]);
260
261				_exit(PIDFD_PASS);
262			}
263
264			/*
265			 * Stop the child so we can inspect whether we have
266			 * recycled pid PID_RECYCLE.
267			 */
268			close(pipe_fds[0]);
269			ret = kill(recycled_pid, SIGSTOP);
270			close(pipe_fds[1]);
271			if (ret) {
272				(void)wait_for_pid(recycled_pid);
273				_exit(PIDFD_ERROR);
274			}
275
276			/*
277			 * We have recycled the pid. Try to signal it. This
278			 * needs to fail since this is a different process than
279			 * the one the pidfd refers to.
280			 */
281			if (recycled_pid == PID_RECYCLE) {
282				ret = sys_pidfd_send_signal(pidfd, SIGCONT,
283							    NULL, 0);
284				if (ret && errno == ESRCH)
285					child_ret = PIDFD_XFAIL;
286				else
287					child_ret = PIDFD_FAIL;
288			}
289
290			/* let the process move on */
291			ret = kill(recycled_pid, SIGCONT);
292			if (ret)
293				(void)kill(recycled_pid, SIGKILL);
294
295			if (wait_for_pid(recycled_pid))
296				_exit(PIDFD_ERROR);
297
298			switch (child_ret) {
299			case PIDFD_FAIL:
300				/* fallthrough */
301			case PIDFD_XFAIL:
302				_exit(child_ret);
303			case PIDFD_PASS:
304				break;
305			default:
306				/* not reached */
307				_exit(PIDFD_ERROR);
308			}
309
310			/*
311			 * If the user set a custom pid_max limit we could be
312			 * in the millions.
313			 * Skip the test in this case.
314			 */
315			if (recycled_pid > PIDFD_MAX_DEFAULT)
316				_exit(PIDFD_SKIP);
317		}
318
319		/* failed to recycle pid */
320		_exit(PIDFD_SKIP);
321	}
322
323	ret = wait_for_pid(pid1);
324	switch (ret) {
325	case PIDFD_FAIL:
326		ksft_exit_fail_msg(
327			"%s test: Managed to signal recycled pid %d\n",
328			test_name, PID_RECYCLE);
329	case PIDFD_PASS:
330		ksft_exit_fail_msg("%s test: Failed to recycle pid %d\n",
331				   test_name, PID_RECYCLE);
332	case PIDFD_SKIP:
333		ksft_print_msg("%s test: Skipping test\n", test_name);
334		ret = 0;
335		break;
336	case PIDFD_XFAIL:
337		ksft_test_result_pass(
338			"%s test: Failed to signal recycled pid as expected\n",
339			test_name);
340		ret = 0;
341		break;
342	default /* PIDFD_ERROR */:
343		ksft_exit_fail_msg("%s test: Error while running tests\n",
344				   test_name);
345	}
346
347	return ret;
348}
349
350static int test_pidfd_send_signal_syscall_support(void)
351{
352	int pidfd, ret;
353	const char *test_name = "pidfd_send_signal check for support";
354
355	pidfd = open("/proc/self", O_DIRECTORY | O_CLOEXEC);
356	if (pidfd < 0)
357		ksft_exit_fail_msg(
358			"%s test: Failed to open process file descriptor\n",
359			test_name);
360
361	ret = sys_pidfd_send_signal(pidfd, 0, NULL, 0);
362	if (ret < 0) {
363		if (errno == ENOSYS) {
364			ksft_test_result_skip(
365				"%s test: pidfd_send_signal() syscall not supported\n",
366				test_name);
367			return 0;
368		}
369		ksft_exit_fail_msg("%s test: Failed to send signal\n",
370				   test_name);
371	}
372
373	have_pidfd_send_signal = true;
374	close(pidfd);
375	ksft_test_result_pass(
376		"%s test: pidfd_send_signal() syscall is supported. Tests can be executed\n",
377		test_name);
378	return 0;
379}
380
381static void *test_pidfd_poll_exec_thread(void *priv)
382{
383	ksft_print_msg("Child Thread: starting. pid %d tid %d ; and sleeping\n",
384			getpid(), syscall(SYS_gettid));
385	ksft_print_msg("Child Thread: doing exec of sleep\n");
386
387	execl("/bin/sleep", "sleep", str(CHILD_THREAD_MIN_WAIT), (char *)NULL);
388
389	ksft_print_msg("Child Thread: DONE. pid %d tid %d\n",
390			getpid(), syscall(SYS_gettid));
391	return NULL;
392}
393
394static void poll_pidfd(const char *test_name, int pidfd)
395{
396	int c;
397	int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
398	struct epoll_event event, events[MAX_EVENTS];
399
400	if (epoll_fd == -1)
401		ksft_exit_fail_msg("%s test: Failed to create epoll file descriptor "
402				   "(errno %d)\n",
403				   test_name, errno);
404
405	event.events = EPOLLIN;
406	event.data.fd = pidfd;
407
408	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pidfd, &event)) {
409		ksft_exit_fail_msg("%s test: Failed to add epoll file descriptor "
410				   "(errno %d)\n",
411				   test_name, errno);
412	}
413
414	c = epoll_wait(epoll_fd, events, MAX_EVENTS, 5000);
415	if (c != 1 || !(events[0].events & EPOLLIN))
416		ksft_exit_fail_msg("%s test: Unexpected epoll_wait result (c=%d, events=%x) ",
417				   "(errno %d)\n",
418				   test_name, c, events[0].events, errno);
419
420	close(epoll_fd);
421	return;
422
423}
424
425static int child_poll_exec_test(void *args)
426{
427	pthread_t t1;
428
429	ksft_print_msg("Child (pidfd): starting. pid %d tid %d\n", getpid(),
430			syscall(SYS_gettid));
431	pthread_create(&t1, NULL, test_pidfd_poll_exec_thread, NULL);
432	/*
433	 * Exec in the non-leader thread will destroy the leader immediately.
434	 * If the wait in the parent returns too soon, the test fails.
435	 */
436	while (1)
437		sleep(1);
438}
439
440static void test_pidfd_poll_exec(int use_waitpid)
441{
442	int pid, pidfd = 0;
443	int status, ret;
444	pthread_t t1;
445	time_t prog_start = time(NULL);
446	const char *test_name = "pidfd_poll check for premature notification on child thread exec";
447
448	ksft_print_msg("Parent: pid: %d\n", getpid());
449	pid = pidfd_clone(CLONE_PIDFD, &pidfd, child_poll_exec_test);
450	if (pid < 0)
451		ksft_exit_fail_msg("%s test: pidfd_clone failed (ret %d, errno %d)\n",
452				   test_name, pid, errno);
453
454	ksft_print_msg("Parent: Waiting for Child (%d) to complete.\n", pid);
455
456	if (use_waitpid) {
457		ret = waitpid(pid, &status, 0);
458		if (ret == -1)
459			ksft_print_msg("Parent: error\n");
460
461		if (ret == pid)
462			ksft_print_msg("Parent: Child process waited for.\n");
463	} else {
464		poll_pidfd(test_name, pidfd);
465	}
466
467	time_t prog_time = time(NULL) - prog_start;
468
469	ksft_print_msg("Time waited for child: %lu\n", prog_time);
470
471	close(pidfd);
472
473	if (prog_time < CHILD_THREAD_MIN_WAIT || prog_time > CHILD_THREAD_MIN_WAIT + 2)
474		ksft_exit_fail_msg("%s test: Failed\n", test_name);
475	else
476		ksft_test_result_pass("%s test: Passed\n", test_name);
477}
478
479static void *test_pidfd_poll_leader_exit_thread(void *priv)
480{
481	ksft_print_msg("Child Thread: starting. pid %d tid %d ; and sleeping\n",
482			getpid(), syscall(SYS_gettid));
483	sleep(CHILD_THREAD_MIN_WAIT);
484	ksft_print_msg("Child Thread: DONE. pid %d tid %d\n", getpid(), syscall(SYS_gettid));
485	return NULL;
486}
487
488static time_t *child_exit_secs;
489static int child_poll_leader_exit_test(void *args)
490{
491	pthread_t t1, t2;
492
493	ksft_print_msg("Child: starting. pid %d tid %d\n", getpid(), syscall(SYS_gettid));
494	pthread_create(&t1, NULL, test_pidfd_poll_leader_exit_thread, NULL);
495	pthread_create(&t2, NULL, test_pidfd_poll_leader_exit_thread, NULL);
496
497	/*
498	 * glibc exit calls exit_group syscall, so explicity call exit only
499	 * so that only the group leader exits, leaving the threads alone.
500	 */
501	*child_exit_secs = time(NULL);
502	syscall(SYS_exit, 0);
503}
504
505static void test_pidfd_poll_leader_exit(int use_waitpid)
506{
507	int pid, pidfd = 0;
508	int status, ret;
509	time_t prog_start = time(NULL);
510	const char *test_name = "pidfd_poll check for premature notification on non-empty"
511				"group leader exit";
512
513	child_exit_secs = mmap(NULL, sizeof *child_exit_secs, PROT_READ | PROT_WRITE,
514			MAP_SHARED | MAP_ANONYMOUS, -1, 0);
515
516	if (child_exit_secs == MAP_FAILED)
517		ksft_exit_fail_msg("%s test: mmap failed (errno %d)\n",
518				   test_name, errno);
519
520	ksft_print_msg("Parent: pid: %d\n", getpid());
521	pid = pidfd_clone(CLONE_PIDFD, &pidfd, child_poll_leader_exit_test);
522	if (pid < 0)
523		ksft_exit_fail_msg("%s test: pidfd_clone failed (ret %d, errno %d)\n",
524				   test_name, pid, errno);
525
526	ksft_print_msg("Parent: Waiting for Child (%d) to complete.\n", pid);
527
528	if (use_waitpid) {
529		ret = waitpid(pid, &status, 0);
530		if (ret == -1)
531			ksft_print_msg("Parent: error\n");
532	} else {
533		/*
534		 * This sleep tests for the case where if the child exits, and is in
535		 * EXIT_ZOMBIE, but the thread group leader is non-empty, then the poll
536		 * doesn't prematurely return even though there are active threads
537		 */
538		sleep(1);
539		poll_pidfd(test_name, pidfd);
540	}
541
542	if (ret == pid)
543		ksft_print_msg("Parent: Child process waited for.\n");
544
545	time_t since_child_exit = time(NULL) - *child_exit_secs;
546
547	ksft_print_msg("Time since child exit: %lu\n", since_child_exit);
548
549	close(pidfd);
550
551	if (since_child_exit < CHILD_THREAD_MIN_WAIT ||
552			since_child_exit > CHILD_THREAD_MIN_WAIT + 2)
553		ksft_exit_fail_msg("%s test: Failed\n", test_name);
554	else
555		ksft_test_result_pass("%s test: Passed\n", test_name);
556}
557
558int main(int argc, char **argv)
559{
560	ksft_print_header();
561	ksft_set_plan(8);
562
563	test_pidfd_poll_exec(0);
564	test_pidfd_poll_exec(1);
565	test_pidfd_poll_leader_exit(0);
566	test_pidfd_poll_leader_exit(1);
567	test_pidfd_send_signal_syscall_support();
568	test_pidfd_send_signal_simple_success();
569	test_pidfd_send_signal_exited_fail();
570	test_pidfd_send_signal_recycled_pid_fail();
571
572	return ksft_exit_pass();
573}