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