This source file includes following definitions.
- sys_clone3
- sys_waitid
- test_pidfd_wait_simple
- test_pidfd_wait_states
- main
1
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.h"
21
22 #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
23
24 static pid_t sys_clone3(struct clone_args *args)
25 {
26 return syscall(__NR_clone3, args, sizeof(struct clone_args));
27 }
28
29 static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options,
30 struct rusage *ru)
31 {
32 return syscall(__NR_waitid, which, pid, info, options, ru);
33 }
34
35 static int test_pidfd_wait_simple(void)
36 {
37 const char *test_name = "pidfd wait simple";
38 int pidfd = -1, status = 0;
39 pid_t parent_tid = -1;
40 struct clone_args args = {
41 .parent_tid = ptr_to_u64(&parent_tid),
42 .pidfd = ptr_to_u64(&pidfd),
43 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
44 .exit_signal = SIGCHLD,
45 };
46 int ret;
47 pid_t pid;
48 siginfo_t info = {
49 .si_signo = 0,
50 };
51
52 pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
53 if (pidfd < 0)
54 ksft_exit_fail_msg("%s test: failed to open /proc/self %s\n",
55 test_name, strerror(errno));
56
57 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
58 if (pid == 0)
59 ksft_exit_fail_msg(
60 "%s test: succeeded to wait on invalid pidfd %s\n",
61 test_name, strerror(errno));
62 close(pidfd);
63 pidfd = -1;
64
65 pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
66 if (pidfd == 0)
67 ksft_exit_fail_msg("%s test: failed to open /dev/null %s\n",
68 test_name, strerror(errno));
69
70 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
71 if (pid == 0)
72 ksft_exit_fail_msg(
73 "%s test: succeeded to wait on invalid pidfd %s\n",
74 test_name, strerror(errno));
75 close(pidfd);
76 pidfd = -1;
77
78 pid = sys_clone3(&args);
79 if (pid < 0)
80 ksft_exit_fail_msg("%s test: failed to create new process %s\n",
81 test_name, strerror(errno));
82
83 if (pid == 0)
84 exit(EXIT_SUCCESS);
85
86 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
87 if (pid < 0)
88 ksft_exit_fail_msg(
89 "%s test: failed to wait on process with pid %d and pidfd %d: %s\n",
90 test_name, parent_tid, pidfd, strerror(errno));
91
92 if (!WIFEXITED(info.si_status) || WEXITSTATUS(info.si_status))
93 ksft_exit_fail_msg(
94 "%s test: unexpected status received after waiting on process with pid %d and pidfd %d: %s\n",
95 test_name, parent_tid, pidfd, strerror(errno));
96 close(pidfd);
97
98 if (info.si_signo != SIGCHLD)
99 ksft_exit_fail_msg(
100 "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
101 test_name, info.si_signo, parent_tid, pidfd,
102 strerror(errno));
103
104 if (info.si_code != CLD_EXITED)
105 ksft_exit_fail_msg(
106 "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
107 test_name, info.si_code, parent_tid, pidfd,
108 strerror(errno));
109
110 if (info.si_pid != parent_tid)
111 ksft_exit_fail_msg(
112 "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
113 test_name, info.si_pid, parent_tid, pidfd,
114 strerror(errno));
115
116 ksft_test_result_pass("%s test: Passed\n", test_name);
117 return 0;
118 }
119
120 static int test_pidfd_wait_states(void)
121 {
122 const char *test_name = "pidfd wait states";
123 int pidfd = -1, status = 0;
124 pid_t parent_tid = -1;
125 struct clone_args args = {
126 .parent_tid = ptr_to_u64(&parent_tid),
127 .pidfd = ptr_to_u64(&pidfd),
128 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
129 .exit_signal = SIGCHLD,
130 };
131 int ret;
132 pid_t pid;
133 siginfo_t info = {
134 .si_signo = 0,
135 };
136
137 pid = sys_clone3(&args);
138 if (pid < 0)
139 ksft_exit_fail_msg("%s test: failed to create new process %s\n",
140 test_name, strerror(errno));
141
142 if (pid == 0) {
143 kill(getpid(), SIGSTOP);
144 kill(getpid(), SIGSTOP);
145 exit(EXIT_SUCCESS);
146 }
147
148 ret = sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL);
149 if (ret < 0)
150 ksft_exit_fail_msg(
151 "%s test: failed to wait on WSTOPPED process with pid %d and pidfd %d: %s\n",
152 test_name, parent_tid, pidfd, strerror(errno));
153
154 if (info.si_signo != SIGCHLD)
155 ksft_exit_fail_msg(
156 "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
157 test_name, info.si_signo, parent_tid, pidfd,
158 strerror(errno));
159
160 if (info.si_code != CLD_STOPPED)
161 ksft_exit_fail_msg(
162 "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
163 test_name, info.si_code, parent_tid, pidfd,
164 strerror(errno));
165
166 if (info.si_pid != parent_tid)
167 ksft_exit_fail_msg(
168 "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
169 test_name, info.si_pid, parent_tid, pidfd,
170 strerror(errno));
171
172 ret = sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0);
173 if (ret < 0)
174 ksft_exit_fail_msg(
175 "%s test: failed to send signal to process with pid %d and pidfd %d: %s\n",
176 test_name, parent_tid, pidfd, strerror(errno));
177
178 ret = sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL);
179 if (ret < 0)
180 ksft_exit_fail_msg(
181 "%s test: failed to wait WCONTINUED on process with pid %d and pidfd %d: %s\n",
182 test_name, parent_tid, pidfd, strerror(errno));
183
184 if (info.si_signo != SIGCHLD)
185 ksft_exit_fail_msg(
186 "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
187 test_name, info.si_signo, parent_tid, pidfd,
188 strerror(errno));
189
190 if (info.si_code != CLD_CONTINUED)
191 ksft_exit_fail_msg(
192 "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
193 test_name, info.si_code, parent_tid, pidfd,
194 strerror(errno));
195
196 if (info.si_pid != parent_tid)
197 ksft_exit_fail_msg(
198 "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
199 test_name, info.si_pid, parent_tid, pidfd,
200 strerror(errno));
201
202 ret = sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL);
203 if (ret < 0)
204 ksft_exit_fail_msg(
205 "%s test: failed to wait on WUNTRACED process with pid %d and pidfd %d: %s\n",
206 test_name, parent_tid, pidfd, strerror(errno));
207
208 if (info.si_signo != SIGCHLD)
209 ksft_exit_fail_msg(
210 "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
211 test_name, info.si_signo, parent_tid, pidfd,
212 strerror(errno));
213
214 if (info.si_code != CLD_STOPPED)
215 ksft_exit_fail_msg(
216 "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
217 test_name, info.si_code, parent_tid, pidfd,
218 strerror(errno));
219
220 if (info.si_pid != parent_tid)
221 ksft_exit_fail_msg(
222 "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
223 test_name, info.si_pid, parent_tid, pidfd,
224 strerror(errno));
225
226 ret = sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0);
227 if (ret < 0)
228 ksft_exit_fail_msg(
229 "%s test: failed to send SIGKILL to process with pid %d and pidfd %d: %s\n",
230 test_name, parent_tid, pidfd, strerror(errno));
231
232 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
233 if (ret < 0)
234 ksft_exit_fail_msg(
235 "%s test: failed to wait on WEXITED process with pid %d and pidfd %d: %s\n",
236 test_name, parent_tid, pidfd, strerror(errno));
237
238 if (info.si_signo != SIGCHLD)
239 ksft_exit_fail_msg(
240 "%s test: unexpected si_signo value %d received after waiting on process with pid %d and pidfd %d: %s\n",
241 test_name, info.si_signo, parent_tid, pidfd,
242 strerror(errno));
243
244 if (info.si_code != CLD_KILLED)
245 ksft_exit_fail_msg(
246 "%s test: unexpected si_code value %d received after waiting on process with pid %d and pidfd %d: %s\n",
247 test_name, info.si_code, parent_tid, pidfd,
248 strerror(errno));
249
250 if (info.si_pid != parent_tid)
251 ksft_exit_fail_msg(
252 "%s test: unexpected si_pid value %d received after waiting on process with pid %d and pidfd %d: %s\n",
253 test_name, info.si_pid, parent_tid, pidfd,
254 strerror(errno));
255
256 close(pidfd);
257
258 ksft_test_result_pass("%s test: Passed\n", test_name);
259 return 0;
260 }
261
262 int main(int argc, char **argv)
263 {
264 ksft_print_header();
265 ksft_set_plan(2);
266
267 test_pidfd_wait_simple();
268 test_pidfd_wait_states();
269
270 return ksft_exit_pass();
271 }