Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/kern/pdwait.c
96290 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2026 ConnectWise
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <sys/types.h>
29
#include <sys/capsicum.h>
30
#include <sys/procdesc.h>
31
#include <sys/resource.h>
32
#include <sys/time.h>
33
#include <sys/user.h>
34
#include <sys/wait.h>
35
36
#include <atf-c.h>
37
#include <signal.h>
38
#include <string.h>
39
40
/* basic usage */
41
ATF_TC_WITHOUT_HEAD(basic);
42
ATF_TC_BODY(basic, tc)
43
{
44
int fdp = -1;
45
pid_t pid;
46
int r, status;
47
struct __wrusage ru;
48
siginfo_t si;
49
50
bzero(&ru, sizeof(ru));
51
52
pid = pdfork(&fdp, 0);
53
if (pid == 0)
54
_exit(42);
55
ATF_REQUIRE_MSG(pid >= 0, "pdfork failed: %s", strerror(errno));
56
ATF_REQUIRE_MSG(fdp >= 0, "pdfork didn't return a process descriptor");
57
58
r = pdwait(fdp, &status, WEXITED, &ru, &si);
59
ATF_CHECK_EQ(r, 0);
60
ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42);
61
ATF_CHECK(ru.wru_self.ru_stime.tv_usec > 0);
62
ATF_CHECK_EQ(si.si_signo, SIGCHLD);
63
ATF_CHECK_EQ(si.si_pid, pid);
64
ATF_CHECK_EQ(si.si_status, WEXITSTATUS(status));
65
66
close(fdp);
67
}
68
69
/* pdwait should work in capability mode */
70
ATF_TC_WITHOUT_HEAD(capsicum);
71
ATF_TC_BODY(capsicum, tc)
72
{
73
int fdp = -1;
74
pid_t pid;
75
int status, r;
76
77
pid = pdfork(&fdp, 0);
78
if (pid == 0)
79
_exit(42);
80
ATF_REQUIRE_MSG(pid >= 0, "pdfork failed: %s", strerror(errno));
81
ATF_REQUIRE_MSG(fdp >= 0, "pdfork didn't return a process descriptor");
82
83
ATF_CHECK_EQ_MSG(0, cap_enter(), "cap_enter: %s", strerror(errno));
84
r = pdwait(fdp, &status, WEXITED, NULL, NULL);
85
ATF_CHECK_EQ(r, 0);
86
ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42);
87
88
close(fdp);
89
}
90
91
/* pdwait should return EBADF if its argument is not a file descriptor */
92
ATF_TC_WITHOUT_HEAD(ebadf);
93
ATF_TC_BODY(ebadf, tc)
94
{
95
ATF_REQUIRE_ERRNO(EBADF, pdwait(99999, NULL, WEXITED, NULL, NULL) < 0);
96
}
97
98
/* pdwait should return efault if the status argument is invalid. */
99
ATF_TC_WITHOUT_HEAD(efault1);
100
ATF_TC_BODY(efault1, tc)
101
{
102
int fdp = -1;
103
pid_t pid;
104
105
pid = pdfork(&fdp, 0);
106
if (pid == 0)
107
_exit(42);
108
ATF_REQUIRE_MSG(pid >= 0, "pdfork failed: %s", strerror(errno));
109
ATF_REQUIRE_MSG(fdp >= 0, "pdfork didn't return a process descriptor");
110
111
ATF_CHECK_ERRNO(EFAULT, pdwait(fdp, (int*)-1, WEXITED, NULL, NULL) < 0);
112
113
close(fdp);
114
}
115
116
/* pdwait should return efault2 if the usage argument is invalid. */
117
ATF_TC_WITHOUT_HEAD(efault2);
118
ATF_TC_BODY(efault2, tc)
119
{
120
int fdp = -1;
121
pid_t pid;
122
123
pid = pdfork(&fdp, 0);
124
if (pid == 0)
125
_exit(42);
126
ATF_REQUIRE_MSG(pid >= 0, "pdfork failed: %s", strerror(errno));
127
ATF_REQUIRE_MSG(fdp >= 0, "pdfork didn't return a process descriptor");
128
129
ATF_CHECK_ERRNO(EFAULT,
130
pdwait(fdp, NULL, WEXITED, (struct __wrusage*)-1, NULL) < 0);
131
132
close(fdp);
133
}
134
135
/* pdwait should return efault if the siginfo argument is invalid. */
136
ATF_TC_WITHOUT_HEAD(efault3);
137
ATF_TC_BODY(efault3, tc)
138
{
139
int fdp = -1;
140
pid_t pid;
141
142
pid = pdfork(&fdp, 0);
143
if (pid == 0)
144
_exit(42);
145
ATF_REQUIRE_MSG(pid >= 0, "pdfork failed: %s", strerror(errno));
146
ATF_REQUIRE_MSG(fdp >= 0, "pdfork didn't return a process descriptor");
147
148
ATF_CHECK_ERRNO(EFAULT,
149
pdwait(fdp, NULL, WEXITED, NULL, (struct __siginfo*)-1) < 0);
150
151
close(fdp);
152
}
153
154
/* pdwait should return einval if the arguments are bad */
155
ATF_TC_WITHOUT_HEAD(einval);
156
ATF_TC_BODY(einval, tc)
157
{
158
int fdp = -1;
159
pid_t pid;
160
161
pid = pdfork(&fdp, 0);
162
if (pid == 0)
163
_exit(42);
164
ATF_REQUIRE_MSG(pid >= 0, "pdfork failed: %s", strerror(errno));
165
ATF_REQUIRE_MSG(fdp >= 0, "pdfork didn't return a process descriptor");
166
167
ATF_CHECK_ERRNO(EINVAL, pdwait(fdp, NULL, 0, NULL, NULL) < 0);
168
ATF_CHECK_ERRNO(EINVAL, pdwait(fdp, NULL, -1, NULL, NULL) < 0);
169
ATF_CHECK_ERRNO(EINVAL,
170
pdwait(STDERR_FILENO, NULL, WEXITED, NULL, NULL) < 0);
171
172
close(fdp);
173
}
174
175
/* pdwait should fail without the cap_pdwait_rights bit */
176
ATF_TC_WITHOUT_HEAD(enotcap);
177
ATF_TC_BODY(enotcap, tc)
178
{
179
cap_rights_t rights;
180
int fdp = -1;
181
pid_t pid;
182
int status;
183
184
/*cap_rights_init(&rights, CAP_RIGHTS_ALL);*/
185
CAP_ALL(&rights);
186
cap_rights_clear(&rights, CAP_PDWAIT);
187
188
pid = pdfork(&fdp, 0);
189
if (pid == 0)
190
_exit(42);
191
ATF_REQUIRE_MSG(pid >= 0, "pdfork failed: %s", strerror(errno));
192
ATF_REQUIRE_MSG(fdp >= 0, "pdfork didn't return a process descriptor");
193
194
ATF_CHECK_EQ_MSG(0, cap_enter(), "cap_enter: %s", strerror(errno));
195
ATF_REQUIRE_EQ_MSG(0, cap_rights_limit(fdp, &rights),
196
"cap_rights_limit %s", strerror(errno));
197
198
ATF_REQUIRE_ERRNO(ENOTCAPABLE,
199
pdwait(fdp, &status, WEXITED, NULL, NULL) < 0);
200
201
close(fdp);
202
}
203
204
/*
205
* Even though the process descriptor is still open, there is no more process
206
* to signal after pdwait() has returned.
207
*/
208
ATF_TC_WITHOUT_HEAD(pdkill_after_pdwait);
209
ATF_TC_BODY(pdkill_after_pdwait, tc)
210
{
211
int fdp = -1;
212
pid_t pid;
213
int r, status;
214
215
pid = pdfork(&fdp, 0);
216
if (pid == 0)
217
_exit(42);
218
ATF_REQUIRE_MSG(pid >= 0, "pdfork failed: %s", strerror(errno));
219
ATF_REQUIRE_MSG(fdp >= 0, "pdfork didn't return a process descriptor");
220
221
r = pdwait(fdp, &status, WEXITED, NULL, NULL);
222
ATF_CHECK_EQ(r, 0);
223
ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42);
224
225
ATF_REQUIRE_ERRNO(ESRCH, pdkill(fdp, SIGTERM) < 0);
226
227
close(fdp);
228
}
229
230
/*
231
* Even though the process descriptor is still open, there is no more status to
232
* return after a pid-based wait() function has already returned it.
233
*/
234
ATF_TC_WITHOUT_HEAD(pdwait_after_waitpid);
235
ATF_TC_BODY(pdwait_after_waitpid, tc)
236
{
237
int fdp = -1;
238
pid_t pid, waited_pid;
239
int status;
240
241
pid = pdfork(&fdp, 0);
242
if (pid == 0)
243
_exit(42);
244
ATF_REQUIRE_MSG(pid >= 0, "pdfork failed: %s", strerror(errno));
245
ATF_REQUIRE_MSG(fdp >= 0, "pdfork didn't return a process descriptor");
246
247
waited_pid = waitpid(pid, &status, WEXITED);
248
249
ATF_CHECK_EQ(pid, waited_pid);
250
ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42);
251
252
ATF_REQUIRE_ERRNO(ESRCH, pdwait(fdp, NULL, WEXITED, NULL, NULL) < 0);
253
254
close(fdp);
255
}
256
257
/* Called twice, waitpid should return ESRCH the second time */
258
ATF_TC_WITHOUT_HEAD(twice);
259
ATF_TC_BODY(twice, tc)
260
{
261
int fdp = -1;
262
pid_t pid;
263
int r, status;
264
265
pid = pdfork(&fdp, 0);
266
if (pid == 0)
267
_exit(42);
268
ATF_REQUIRE_MSG(pid >= 0, "pdfork failed: %s", strerror(errno));
269
ATF_REQUIRE_MSG(fdp >= 0, "pdfork didn't return a process descriptor");
270
271
r = pdwait(fdp, &status, WEXITED, NULL, NULL);
272
ATF_CHECK_EQ(r, 0);
273
ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42);
274
275
ATF_REQUIRE_ERRNO(ESRCH, pdwait(fdp, NULL, WEXITED, NULL, NULL) < 0);
276
277
close(fdp);
278
}
279
280
ATF_TP_ADD_TCS(tp)
281
{
282
ATF_TP_ADD_TC(tp, basic);
283
ATF_TP_ADD_TC(tp, capsicum);
284
ATF_TP_ADD_TC(tp, ebadf);
285
ATF_TP_ADD_TC(tp, enotcap);
286
ATF_TP_ADD_TC(tp, twice);
287
ATF_TP_ADD_TC(tp, efault1);
288
ATF_TP_ADD_TC(tp, efault2);
289
ATF_TP_ADD_TC(tp, efault3);
290
ATF_TP_ADD_TC(tp, einval);
291
ATF_TP_ADD_TC(tp, pdwait_after_waitpid);
292
ATF_TP_ADD_TC(tp, pdkill_after_pdwait);
293
294
return (atf_no_error());
295
}
296
297