blob: 17999e082aa715525f013f194b278e1bdf6786ad [file] [log] [blame]
Christian Braunere63f3082019-07-28 00:22:30 +02001/* 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"
Christian Brauner09d1de12020-09-02 12:21:29 +020020#include "../kselftest_harness.h"
Christian Braunere63f3082019-07-28 00:22:30 +020021
22#define ptr_to_u64(ptr) ((__u64)((uintptr_t)(ptr)))
23
Christian Braunercd895972020-09-02 12:21:30 +020024/* Attempt to de-conflict with the selftests tree. */
25#ifndef SKIP
26#define SKIP(s, ...) XFAIL(s, ##__VA_ARGS__)
27#endif
28
Christian Braunere63f3082019-07-28 00:22:30 +020029static pid_t sys_clone3(struct clone_args *args)
30{
31 return syscall(__NR_clone3, args, sizeof(struct clone_args));
32}
33
34static 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
Christian Brauner09d1de12020-09-02 12:21:29 +020040TEST(wait_simple)
Christian Braunere63f3082019-07-28 00:22:30 +020041{
Axel Rasmussene2aa5e62022-01-27 14:11:15 -080042 int pidfd = -1;
Christian Braunere63f3082019-07-28 00:22:30 +020043 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 };
Christian Braunere63f3082019-07-28 00:22:30 +020050 pid_t pid;
51 siginfo_t info = {
52 .si_signo = 0,
53 };
54
55 pidfd = open("/proc/self", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
Christian Brauner09d1de12020-09-02 12:21:29 +020056 ASSERT_GE(pidfd, 0);
Christian Braunere63f3082019-07-28 00:22:30 +020057
58 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
Christian Brauner09d1de12020-09-02 12:21:29 +020059 ASSERT_NE(pid, 0);
60 EXPECT_EQ(close(pidfd), 0);
Christian Braunere63f3082019-07-28 00:22:30 +020061 pidfd = -1;
62
63 pidfd = open("/dev/null", O_RDONLY | O_CLOEXEC);
Christian Brauner09d1de12020-09-02 12:21:29 +020064 ASSERT_GE(pidfd, 0);
Christian Braunere63f3082019-07-28 00:22:30 +020065
66 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
Christian Brauner09d1de12020-09-02 12:21:29 +020067 ASSERT_NE(pid, 0);
68 EXPECT_EQ(close(pidfd), 0);
Christian Braunere63f3082019-07-28 00:22:30 +020069 pidfd = -1;
70
71 pid = sys_clone3(&args);
Christian Braunercd895972020-09-02 12:21:30 +020072 ASSERT_GE(pid, 0);
Christian Braunere63f3082019-07-28 00:22:30 +020073
74 if (pid == 0)
75 exit(EXIT_SUCCESS);
76
77 pid = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
Christian Brauner09d1de12020-09-02 12:21:29 +020078 ASSERT_GE(pid, 0);
79 ASSERT_EQ(WIFEXITED(info.si_status), true);
80 ASSERT_EQ(WEXITSTATUS(info.si_status), 0);
81 EXPECT_EQ(close(pidfd), 0);
Christian Braunere63f3082019-07-28 00:22:30 +020082
Christian Brauner09d1de12020-09-02 12:21:29 +020083 ASSERT_EQ(info.si_signo, SIGCHLD);
84 ASSERT_EQ(info.si_code, CLD_EXITED);
85 ASSERT_EQ(info.si_pid, parent_tid);
Christian Braunere63f3082019-07-28 00:22:30 +020086}
87
Christian Brauner09d1de12020-09-02 12:21:29 +020088TEST(wait_states)
Christian Braunere63f3082019-07-28 00:22:30 +020089{
Axel Rasmussene2aa5e62022-01-27 14:11:15 -080090 int pidfd = -1;
Christian Braunere63f3082019-07-28 00:22:30 +020091 pid_t parent_tid = -1;
92 struct clone_args args = {
93 .parent_tid = ptr_to_u64(&parent_tid),
94 .pidfd = ptr_to_u64(&pidfd),
95 .flags = CLONE_PIDFD | CLONE_PARENT_SETTID,
96 .exit_signal = SIGCHLD,
97 };
98 int ret;
99 pid_t pid;
100 siginfo_t info = {
101 .si_signo = 0,
102 };
103
104 pid = sys_clone3(&args);
Christian Brauner09d1de12020-09-02 12:21:29 +0200105 ASSERT_GE(pid, 0);
Christian Braunere63f3082019-07-28 00:22:30 +0200106
107 if (pid == 0) {
108 kill(getpid(), SIGSTOP);
109 kill(getpid(), SIGSTOP);
110 exit(EXIT_SUCCESS);
111 }
112
Christian Brauner09d1de12020-09-02 12:21:29 +0200113 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
114 ASSERT_EQ(info.si_signo, SIGCHLD);
115 ASSERT_EQ(info.si_code, CLD_STOPPED);
116 ASSERT_EQ(info.si_pid, parent_tid);
Christian Braunere63f3082019-07-28 00:22:30 +0200117
Christian Brauner09d1de12020-09-02 12:21:29 +0200118 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
Christian Braunere63f3082019-07-28 00:22:30 +0200119
Christian Brauner09d1de12020-09-02 12:21:29 +0200120 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WCONTINUED, NULL), 0);
121 ASSERT_EQ(info.si_signo, SIGCHLD);
122 ASSERT_EQ(info.si_code, CLD_CONTINUED);
123 ASSERT_EQ(info.si_pid, parent_tid);
Christian Braunere63f3082019-07-28 00:22:30 +0200124
Christian Brauner09d1de12020-09-02 12:21:29 +0200125 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WUNTRACED, NULL), 0);
126 ASSERT_EQ(info.si_signo, SIGCHLD);
127 ASSERT_EQ(info.si_code, CLD_STOPPED);
128 ASSERT_EQ(info.si_pid, parent_tid);
Christian Braunere63f3082019-07-28 00:22:30 +0200129
Christian Brauner09d1de12020-09-02 12:21:29 +0200130 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0), 0);
Christian Braunere63f3082019-07-28 00:22:30 +0200131
Christian Brauner09d1de12020-09-02 12:21:29 +0200132 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL), 0);
133 ASSERT_EQ(info.si_signo, SIGCHLD);
134 ASSERT_EQ(info.si_code, CLD_KILLED);
135 ASSERT_EQ(info.si_pid, parent_tid);
Christian Braunere63f3082019-07-28 00:22:30 +0200136
Christian Brauner09d1de12020-09-02 12:21:29 +0200137 EXPECT_EQ(close(pidfd), 0);
Christian Braunere63f3082019-07-28 00:22:30 +0200138}
139
Christian Braunercd895972020-09-02 12:21:30 +0200140TEST(wait_nonblock)
141{
142 int pidfd, status = 0;
143 unsigned int flags = 0;
144 pid_t parent_tid = -1;
145 struct clone_args args = {
146 .parent_tid = ptr_to_u64(&parent_tid),
147 .flags = CLONE_PARENT_SETTID,
148 .exit_signal = SIGCHLD,
149 };
150 int ret;
151 pid_t pid;
152 siginfo_t info = {
153 .si_signo = 0,
154 };
155
156 /*
157 * Callers need to see ECHILD with non-blocking pidfds when no child
158 * processes exists.
159 */
160 pidfd = sys_pidfd_open(getpid(), PIDFD_NONBLOCK);
161 EXPECT_GE(pidfd, 0) {
162 /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
163 ASSERT_EQ(errno, EINVAL);
164 SKIP(return, "Skipping PIDFD_NONBLOCK test");
165 }
166
167 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
168 ASSERT_LT(ret, 0);
169 ASSERT_EQ(errno, ECHILD);
170 EXPECT_EQ(close(pidfd), 0);
171
172 pid = sys_clone3(&args);
173 ASSERT_GE(pid, 0);
174
175 if (pid == 0) {
176 kill(getpid(), SIGSTOP);
177 exit(EXIT_SUCCESS);
178 }
179
180 pidfd = sys_pidfd_open(pid, PIDFD_NONBLOCK);
181 EXPECT_GE(pidfd, 0) {
182 /* pidfd_open() doesn't support PIDFD_NONBLOCK. */
183 ASSERT_EQ(errno, EINVAL);
184 SKIP(return, "Skipping PIDFD_NONBLOCK test");
185 }
186
187 flags = fcntl(pidfd, F_GETFL, 0);
188 ASSERT_GT(flags, 0);
189 ASSERT_GT((flags & O_NONBLOCK), 0);
190
191 /*
192 * Callers need to see EAGAIN/EWOULDBLOCK with non-blocking pidfd when
193 * child processes exist but none have exited.
194 */
195 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL);
196 ASSERT_LT(ret, 0);
197 ASSERT_EQ(errno, EAGAIN);
198
199 /*
200 * Callers need to continue seeing 0 with non-blocking pidfd and
201 * WNOHANG raised explicitly when child processes exist but none have
202 * exited.
203 */
204 ret = sys_waitid(P_PIDFD, pidfd, &info, WEXITED | WNOHANG, NULL);
205 ASSERT_EQ(ret, 0);
206
Christian Brauner01361b62020-10-09 11:52:22 +0200207 ASSERT_EQ(fcntl(pidfd, F_SETFL, (flags & ~O_NONBLOCK)), 0);
208
Christian Braunercd895972020-09-02 12:21:30 +0200209 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WSTOPPED, NULL), 0);
210 ASSERT_EQ(info.si_signo, SIGCHLD);
211 ASSERT_EQ(info.si_code, CLD_STOPPED);
212 ASSERT_EQ(info.si_pid, parent_tid);
213
214 ASSERT_EQ(sys_pidfd_send_signal(pidfd, SIGCONT, NULL, 0), 0);
215
Christian Braunercd895972020-09-02 12:21:30 +0200216 ASSERT_EQ(sys_waitid(P_PIDFD, pidfd, &info, WEXITED, NULL), 0);
217 ASSERT_EQ(info.si_signo, SIGCHLD);
218 ASSERT_EQ(info.si_code, CLD_EXITED);
219 ASSERT_EQ(info.si_pid, parent_tid);
220
221 EXPECT_EQ(close(pidfd), 0);
222}
223
Christian Brauner09d1de12020-09-02 12:21:29 +0200224TEST_HARNESS_MAIN