1 /* SPDX-License-Identifier: GPL-2.0 */
5 #include <linux/sched.h>
6 #include <linux/types.h>
13 #include <sys/resource.h>
15 #include <sys/types.h>
20 #include "../kselftest.h"
22 #define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
24 static pid_t sys_clone3(struct clone_args *args)
26 return syscall(__NR_clone3, args, sizeof(struct clone_args));
29 static int sys_waitid(int which, pid_t pid, siginfo_t *info, int options,
32 return syscall(__NR_waitid, which, pid, info, options, ru);
35 static int test_pidfd_wait_simple(void)
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,
52 pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
54 ksft_exit_fail_msg("%s test: failed to open /proc/self %s\n",
55 test_name, strerror(errno));
57 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
60 "%s test: succeeded to wait on invalid pidfd %s\n",
61 test_name, strerror(errno));
65 pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
67 ksft_exit_fail_msg("%s test: failed to open /dev/null %s\n",
68 test_name, strerror(errno));
70 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
73 "%s test: succeeded to wait on invalid pidfd %s\n",
74 test_name, strerror(errno));
78 pid = sys_clone3(&args);
80 ksft_exit_fail_msg("%s test: failed to create new process %s\n",
81 test_name, strerror(errno));
86 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
89 "%s test: failed to wait on process with pid %d and pidfd %d: %s\n",
90 test_name, parent_tid, pidfd, strerror(errno));
92 if (!WIFEXITED(info.si_status) || WEXITSTATUS(info.si_status))
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));
98 if (info.si_signo != SIGCHLD)
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,
104 if (info.si_code != CLD_EXITED)
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,
110 if (info.si_pid != parent_tid)
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,
116 ksft_test_result_pass("%s test: Passed\n", test_name);
120 static int test_pidfd_wait_states(void)
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,
137 pid = sys_clone3(&args);
139 ksft_exit_fail_msg("%s test: failed to create new process %s\n",
140 test_name, strerror(errno));
143 kill(getpid(), SIGSTOP);
144 kill(getpid(), SIGSTOP);
148 ret = sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL);
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));
154 if (info.si_signo != SIGCHLD)
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,
160 if (info.si_code != CLD_STOPPED)
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,
166 if (info.si_pid != parent_tid)
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,
172 ret = sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0);
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));
178 ret = sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL);
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));
184 if (info.si_signo != SIGCHLD)
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,
190 if (info.si_code != CLD_CONTINUED)
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,
196 if (info.si_pid != parent_tid)
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,
202 ret = sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL);
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));
208 if (info.si_signo != SIGCHLD)
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,
214 if (info.si_code != CLD_STOPPED)
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,
220 if (info.si_pid != parent_tid)
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,
226 ret = sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0);
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));
232 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
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));
238 if (info.si_signo != SIGCHLD)
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,
244 if (info.si_code != CLD_KILLED)
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,
250 if (info.si_pid != parent_tid)
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,
258 ksft_test_result_pass("%s test: Passed\n", test_name);
262 int main(int argc, char **argv)
267 test_pidfd_wait_simple();
268 test_pidfd_wait_states();
270 return ksft_exit_pass();