Merge tag 'x86_microcode_update_for_v5.11' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-microblaze.git] / tools / testing / selftests / pidfd / pidfd_wait.c
1 /* SPDX-License-Identifier: GPL-2.0 */
2
3 #define _GNU_SOURCE
4 #include <errno.h>
5 #include <linux/sched.h>
6 #include <linux/types.h>
7 #include <signal.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sched.h>
12 #include <string.h>
13 #include <sys/resource.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <sys/wait.h>
17 #include <unistd.h>
18
19 #include "pidfd.h"
20 #include "../kselftest_harness.h"
21
22 #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
23
24 /* Attempt to de-conflict with the selftests tree. */
25 #ifndef SKIP
26 #define SKIP(s, ...)    XFAIL(s, ##__VA_ARGS__)
27 #endif
28
29 static pid_t sys_clone3(struct clone_args *args)
30 {
31         return syscall(__NR_clone3, args, sizeof(struct clone_args));
32 }
33
34 static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options,
35                       struct rusage *ru)
36 {
37         return syscall(__NR_waitid, which, pid, info, options, ru);
38 }
39
40 TEST(wait_simple)
41 {
42         int pidfd = -1, status = 0;
43         pid_t parent_tid = -1;
44         struct clone_args args = {
45                 .parent_tid = ptr_to_u64(&parent_tid),
46                 .pidfd = ptr_to_u64(&pidfd),
47                 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
48                 .exit_signal = SIGCHLD,
49         };
50         int ret;
51         pid_t pid;
52         siginfo_t info = {
53                 .si_signo = 0,
54         };
55
56         pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
57         ASSERT_GE(pidfd, 0);
58
59         pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
60         ASSERT_NE(pid, 0);
61         EXPECT_EQ(close(pidfd), 0);
62         pidfd = -1;
63
64         pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
65         ASSERT_GE(pidfd, 0);
66
67         pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
68         ASSERT_NE(pid, 0);
69         EXPECT_EQ(close(pidfd), 0);
70         pidfd = -1;
71
72         pid = sys_clone3(&args);
73         ASSERT_GE(pid, 0);
74
75         if (pid == 0)
76                 exit(EXIT_SUCCESS);
77
78         pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
79         ASSERT_GE(pid, 0);
80         ASSERT_EQ(WIFEXITED(info.si_status), true);
81         ASSERT_EQ(WEXITSTATUS(info.si_status), 0);
82         EXPECT_EQ(close(pidfd), 0);
83
84         ASSERT_EQ(info.si_signo, SIGCHLD);
85         ASSERT_EQ(info.si_code, CLD_EXITED);
86         ASSERT_EQ(info.si_pid, parent_tid);
87 }
88
89 TEST(wait_states)
90 {
91         int pidfd = -1, status = 0;
92         pid_t parent_tid = -1;
93         struct clone_args args = {
94                 .parent_tid = ptr_to_u64(&parent_tid),
95                 .pidfd = ptr_to_u64(&pidfd),
96                 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
97                 .exit_signal = SIGCHLD,
98         };
99         int ret;
100         pid_t pid;
101         siginfo_t info = {
102                 .si_signo = 0,
103         };
104
105         pid = sys_clone3(&args);
106         ASSERT_GE(pid, 0);
107
108         if (pid == 0) {
109                 kill(getpid(), SIGSTOP);
110                 kill(getpid(), SIGSTOP);
111                 exit(EXIT_SUCCESS);
112         }
113
114         ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
115         ASSERT_EQ(info.si_signo, SIGCHLD);
116         ASSERT_EQ(info.si_code, CLD_STOPPED);
117         ASSERT_EQ(info.si_pid, parent_tid);
118
119         ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
120
121         ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL), 0);
122         ASSERT_EQ(info.si_signo, SIGCHLD);
123         ASSERT_EQ(info.si_code, CLD_CONTINUED);
124         ASSERT_EQ(info.si_pid, parent_tid);
125
126         ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL), 0);
127         ASSERT_EQ(info.si_signo, SIGCHLD);
128         ASSERT_EQ(info.si_code, CLD_STOPPED);
129         ASSERT_EQ(info.si_pid, parent_tid);
130
131         ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0), 0);
132
133         ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL), 0);
134         ASSERT_EQ(info.si_signo, SIGCHLD);
135         ASSERT_EQ(info.si_code, CLD_KILLED);
136         ASSERT_EQ(info.si_pid, parent_tid);
137
138         EXPECT_EQ(close(pidfd), 0);
139 }
140
141 TEST(wait_nonblock)
142 {
143         int pidfd, status = 0;
144         unsigned int flags = 0;
145         pid_t parent_tid = -1;
146         struct clone_args args = {
147                 .parent_tid = ptr_to_u64(&parent_tid),
148                 .flags = CLONE_PARENT_SETTID,
149                 .exit_signal = SIGCHLD,
150         };
151         int ret;
152         pid_t pid;
153         siginfo_t info = {
154                 .si_signo = 0,
155         };
156
157         /*
158          * Callers need to see ECHILD with non-blocking pidfds when no child
159          * processes exists.
160          */
161         pidfd = sys_pidfd_open(getpid(), PIDFD_NONBLOCK);
162         EXPECT_GE(pidfd, 0) {
163                 /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
164                 ASSERT_EQ(errno, EINVAL);
165                 SKIP(return, "Skipping PIDFD_NONBLOCK test");
166         }
167
168         ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
169         ASSERT_LT(ret, 0);
170         ASSERT_EQ(errno, ECHILD);
171         EXPECT_EQ(close(pidfd), 0);
172
173         pid = sys_clone3(&args);
174         ASSERT_GE(pid, 0);
175
176         if (pid == 0) {
177                 kill(getpid(), SIGSTOP);
178                 exit(EXIT_SUCCESS);
179         }
180
181         pidfd = sys_pidfd_open(pid, PIDFD_NONBLOCK);
182         EXPECT_GE(pidfd, 0) {
183                 /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
184                 ASSERT_EQ(errno, EINVAL);
185                 SKIP(return, "Skipping PIDFD_NONBLOCK test");
186         }
187
188         flags = fcntl(pidfd, F_GETFL, 0);
189         ASSERT_GT(flags, 0);
190         ASSERT_GT((flags & O_NONBLOCK), 0);
191
192         /*
193          * Callers need to see EAGAIN/EWOULDBLOCK with non-blocking pidfd when
194          * child processes exist but none have exited.
195          */
196         ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
197         ASSERT_LT(ret, 0);
198         ASSERT_EQ(errno, EAGAIN);
199
200         /*
201          * Callers need to continue seeing 0 with non-blocking pidfd and
202          * WNOHANG raised explicitly when child processes exist but none have
203          * exited.
204          */
205         ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED | WNOHANG, NULL);
206         ASSERT_EQ(ret, 0);
207
208         ASSERT_EQ(fcntl(pidfd, F_SETFL, (flags & ~O_NONBLOCK)), 0);
209
210         ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
211         ASSERT_EQ(info.si_signo, SIGCHLD);
212         ASSERT_EQ(info.si_code, CLD_STOPPED);
213         ASSERT_EQ(info.si_pid, parent_tid);
214
215         ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
216
217         ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL), 0);
218         ASSERT_EQ(info.si_signo, SIGCHLD);
219         ASSERT_EQ(info.si_code, CLD_EXITED);
220         ASSERT_EQ(info.si_pid, parent_tid);
221
222         EXPECT_EQ(close(pidfd), 0);
223 }
224
225 TEST_HARNESS_MAIN