t_cloexec.c revision 1.1 1 1.1 riastrad /* $NetBSD: t_cloexec.c,v 1.1 2024/11/10 15:57:32 riastradh Exp $ */
2 1.1 riastrad
3 1.1 riastrad /*-
4 1.1 riastrad * Copyright (c) 2024 The NetBSD Foundation, Inc.
5 1.1 riastrad * All rights reserved.
6 1.1 riastrad *
7 1.1 riastrad * Redistribution and use in source and binary forms, with or without
8 1.1 riastrad * modification, are permitted provided that the following conditions
9 1.1 riastrad * are met:
10 1.1 riastrad * 1. Redistributions of source code must retain the above copyright
11 1.1 riastrad * notice, this list of conditions and the following disclaimer.
12 1.1 riastrad * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 riastrad * notice, this list of conditions and the following disclaimer in the
14 1.1 riastrad * documentation and/or other materials provided with the distribution.
15 1.1 riastrad *
16 1.1 riastrad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 1.1 riastrad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.1 riastrad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.1 riastrad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 1.1 riastrad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 1.1 riastrad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 1.1 riastrad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 1.1 riastrad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 1.1 riastrad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 1.1 riastrad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 1.1 riastrad * POSSIBILITY OF SUCH DAMAGE.
27 1.1 riastrad */
28 1.1 riastrad
29 1.1 riastrad #include <sys/cdefs.h>
30 1.1 riastrad __RCSID("$NetBSD: t_cloexec.c,v 1.1 2024/11/10 15:57:32 riastradh Exp $");
31 1.1 riastrad
32 1.1 riastrad #include <sys/types.h>
33 1.1 riastrad
34 1.1 riastrad #include <sys/bitops.h>
35 1.1 riastrad #include <sys/event.h>
36 1.1 riastrad #include <sys/ioctl.h>
37 1.1 riastrad #include <sys/socket.h>
38 1.1 riastrad #include <sys/un.h>
39 1.1 riastrad #include <sys/wait.h>
40 1.1 riastrad
41 1.1 riastrad #include <atf-c.h>
42 1.1 riastrad #include <fcntl.h>
43 1.1 riastrad #include <limits.h>
44 1.1 riastrad #include <spawn.h>
45 1.1 riastrad #include <stdio.h>
46 1.1 riastrad #include <unistd.h>
47 1.1 riastrad
48 1.1 riastrad #include "h_macros.h"
49 1.1 riastrad
50 1.1 riastrad /*
51 1.1 riastrad * Test close-on-exec as set in various ways
52 1.1 riastrad */
53 1.1 riastrad
54 1.1 riastrad static int
55 1.1 riastrad open_via_accept4(void)
56 1.1 riastrad {
57 1.1 riastrad static const union {
58 1.1 riastrad struct sockaddr sa;
59 1.1 riastrad struct sockaddr_un sun;
60 1.1 riastrad } name = { .sun = {
61 1.1 riastrad .sun_family = AF_LOCAL,
62 1.1 riastrad .sun_path = "socket",
63 1.1 riastrad } };
64 1.1 riastrad int slisten, saccept, c;
65 1.1 riastrad
66 1.1 riastrad /*
67 1.1 riastrad * Create a listening server socket and bind it to the path.
68 1.1 riastrad */
69 1.1 riastrad RL(slisten = socket(PF_LOCAL, SOCK_STREAM, 0));
70 1.1 riastrad RL(bind(slisten, &name.sa, sizeof(name)));
71 1.1 riastrad RL(listen(slisten, SOMAXCONN));
72 1.1 riastrad
73 1.1 riastrad /*
74 1.1 riastrad * Create an active client socket and connect it to the path --
75 1.1 riastrad * nonblocking, so we don't deadlock here. If connect doesn't
76 1.1 riastrad * succeed immediately, it had better fail immediately with
77 1.1 riastrad * EINPROGRESS.
78 1.1 riastrad */
79 1.1 riastrad RL(c = socket(PF_LOCAL, SOCK_STREAM|SOCK_NONBLOCK, 0));
80 1.1 riastrad if (connect(c, &name.sa, sizeof(name)) == -1) {
81 1.1 riastrad ATF_CHECK_EQ_MSG(errno, EINPROGRESS, "connect failed %d: %s",
82 1.1 riastrad errno, strerror(errno));
83 1.1 riastrad }
84 1.1 riastrad
85 1.1 riastrad /*
86 1.1 riastrad * Accept a socket on the server side with SOCK_CLOEXEC.
87 1.1 riastrad */
88 1.1 riastrad RL(saccept = accept4(slisten, /*addr*/NULL, /*addrlen*/NULL,
89 1.1 riastrad SOCK_CLOEXEC));
90 1.1 riastrad return saccept;
91 1.1 riastrad }
92 1.1 riastrad
93 1.1 riastrad static int
94 1.1 riastrad open_via_clonedev(void)
95 1.1 riastrad {
96 1.1 riastrad int fd;
97 1.1 riastrad
98 1.1 riastrad RL(fd = open("/dev/drvctl", O_RDONLY|O_CLOEXEC));
99 1.1 riastrad
100 1.1 riastrad return fd;
101 1.1 riastrad }
102 1.1 riastrad
103 1.1 riastrad static int
104 1.1 riastrad open_via_dup3(void)
105 1.1 riastrad {
106 1.1 riastrad int fd3;
107 1.1 riastrad
108 1.1 riastrad RL(fd3 = dup3(STDIN_FILENO, 3, O_CLOEXEC));
109 1.1 riastrad ATF_REQUIRE_EQ_MSG(fd3, 3, "dup3(STDIN_FILENO, 3, ...)"
110 1.1 riastrad " failed to return 3: %d", fd3);
111 1.1 riastrad
112 1.1 riastrad return fd3;
113 1.1 riastrad }
114 1.1 riastrad
115 1.1 riastrad static int
116 1.1 riastrad open_via_fcntldupfd(void)
117 1.1 riastrad {
118 1.1 riastrad int fd;
119 1.1 riastrad
120 1.1 riastrad RL(fd = fcntl(STDIN_FILENO, F_DUPFD_CLOEXEC, 0));
121 1.1 riastrad
122 1.1 riastrad return fd;
123 1.1 riastrad }
124 1.1 riastrad
125 1.1 riastrad static int
126 1.1 riastrad open_via_kqueue(void)
127 1.1 riastrad {
128 1.1 riastrad int fd;
129 1.1 riastrad
130 1.1 riastrad RL(fd = kqueue1(O_CLOEXEC));
131 1.1 riastrad
132 1.1 riastrad return fd;
133 1.1 riastrad }
134 1.1 riastrad
135 1.1 riastrad static int
136 1.1 riastrad open_via_opencloexec(void)
137 1.1 riastrad {
138 1.1 riastrad int fd;
139 1.1 riastrad
140 1.1 riastrad RL(fd = open("file", O_RDWR|O_CREAT|O_CLOEXEC, 0644));
141 1.1 riastrad
142 1.1 riastrad return fd;
143 1.1 riastrad }
144 1.1 riastrad
145 1.1 riastrad static int
146 1.1 riastrad open_via_openfcntlcloexec(void)
147 1.1 riastrad {
148 1.1 riastrad int fd;
149 1.1 riastrad
150 1.1 riastrad RL(fd = open("file", O_RDWR|O_CREAT, 0644));
151 1.1 riastrad RL(fcntl(fd, F_SETFD, FD_CLOEXEC));
152 1.1 riastrad
153 1.1 riastrad return fd;
154 1.1 riastrad }
155 1.1 riastrad
156 1.1 riastrad static int
157 1.1 riastrad open_via_openioctlfioclex(void)
158 1.1 riastrad {
159 1.1 riastrad int fd;
160 1.1 riastrad
161 1.1 riastrad RL(fd = open("file", O_RDWR|O_CREAT, 0644));
162 1.1 riastrad RL(ioctl(fd, FIOCLEX));
163 1.1 riastrad
164 1.1 riastrad return fd;
165 1.1 riastrad }
166 1.1 riastrad
167 1.1 riastrad static int
168 1.1 riastrad open_via_pipe2rd(void)
169 1.1 riastrad {
170 1.1 riastrad int fd[2];
171 1.1 riastrad
172 1.1 riastrad RL(pipe2(fd, O_CLOEXEC));
173 1.1 riastrad
174 1.1 riastrad return fd[0];
175 1.1 riastrad }
176 1.1 riastrad
177 1.1 riastrad static int
178 1.1 riastrad open_via_pipe2wr(void)
179 1.1 riastrad {
180 1.1 riastrad int fd[2];
181 1.1 riastrad
182 1.1 riastrad RL(pipe2(fd, O_CLOEXEC));
183 1.1 riastrad
184 1.1 riastrad return fd[1];
185 1.1 riastrad }
186 1.1 riastrad
187 1.1 riastrad static int
188 1.1 riastrad open_via_paccept(void)
189 1.1 riastrad {
190 1.1 riastrad static const union {
191 1.1 riastrad struct sockaddr sa;
192 1.1 riastrad struct sockaddr_un sun;
193 1.1 riastrad } name = { .sun = {
194 1.1 riastrad .sun_family = AF_LOCAL,
195 1.1 riastrad .sun_path = "socket",
196 1.1 riastrad } };
197 1.1 riastrad int slisten, saccept, c;
198 1.1 riastrad
199 1.1 riastrad /*
200 1.1 riastrad * Create a listening server socket and bind it to the path.
201 1.1 riastrad */
202 1.1 riastrad RL(slisten = socket(PF_LOCAL, SOCK_STREAM, 0));
203 1.1 riastrad RL(bind(slisten, &name.sa, sizeof(name)));
204 1.1 riastrad RL(listen(slisten, SOMAXCONN));
205 1.1 riastrad
206 1.1 riastrad /*
207 1.1 riastrad * Create an active client socket and connect it to the path --
208 1.1 riastrad * nonblocking, so we don't deadlock here. If connect doesn't
209 1.1 riastrad * succeed immediately, it had better fail immediately with
210 1.1 riastrad * EINPROGRESS.
211 1.1 riastrad */
212 1.1 riastrad RL(c = socket(PF_LOCAL, SOCK_STREAM|SOCK_NONBLOCK, 0));
213 1.1 riastrad if (connect(c, &name.sa, sizeof(name)) == -1) {
214 1.1 riastrad ATF_CHECK_EQ_MSG(errno, EINPROGRESS, "connect failed %d: %s",
215 1.1 riastrad errno, strerror(errno));
216 1.1 riastrad }
217 1.1 riastrad
218 1.1 riastrad /*
219 1.1 riastrad * Accept a socket on the server side with SOCK_CLOEXEC.
220 1.1 riastrad */
221 1.1 riastrad RL(saccept = paccept(slisten, /*addr*/NULL, /*addrlen*/NULL,
222 1.1 riastrad /*sigmask*/NULL, SOCK_CLOEXEC));
223 1.1 riastrad return saccept;
224 1.1 riastrad }
225 1.1 riastrad
226 1.1 riastrad static int
227 1.1 riastrad open_via_socket(void)
228 1.1 riastrad {
229 1.1 riastrad int fd;
230 1.1 riastrad
231 1.1 riastrad RL(fd = socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0));
232 1.1 riastrad
233 1.1 riastrad return fd;
234 1.1 riastrad }
235 1.1 riastrad
236 1.1 riastrad static int
237 1.1 riastrad open_via_socketpair0(void)
238 1.1 riastrad {
239 1.1 riastrad int fd[2];
240 1.1 riastrad
241 1.1 riastrad RL(socketpair(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0, fd));
242 1.1 riastrad
243 1.1 riastrad return fd[0];
244 1.1 riastrad }
245 1.1 riastrad
246 1.1 riastrad static int
247 1.1 riastrad open_via_socketpair1(void)
248 1.1 riastrad {
249 1.1 riastrad int fd[2];
250 1.1 riastrad
251 1.1 riastrad RL(socketpair(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0, fd));
252 1.1 riastrad
253 1.1 riastrad return fd[1];
254 1.1 riastrad }
255 1.1 riastrad
256 1.1 riastrad /*
257 1.1 riastrad * XXX Close-on-exec paths still missing:
258 1.1 riastrad * XXX
259 1.1 riastrad * XXX compat_linux inotify
260 1.1 riastrad * XXX compat_linux close_range
261 1.1 riastrad * XXX drm i915_perf_open_ioctl
262 1.1 riastrad * XXX drm dma_buf
263 1.1 riastrad * XXX eventfd(2)
264 1.1 riastrad * XXX memfd(2)
265 1.1 riastrad * XXX timerfd(2)
266 1.1 riastrad * XXX recvmsg/recvmmsg with MSG_CMSG_CLOEXEC
267 1.1 riastrad */
268 1.1 riastrad
269 1.1 riastrad static void
270 1.1 riastrad check_cloexec(const struct atf_tc *tc, int fd,
271 1.1 riastrad pid_t (*execfn)(char *, char *const[]))
272 1.1 riastrad {
273 1.1 riastrad char h_cloexec[PATH_MAX];
274 1.1 riastrad char fdstr[(ilog2(INT_MAX) + 1)/(ilog2(10) - 1) + 1];
275 1.1 riastrad char *const argv[] = {__UNCONST("h_cloexec"), fdstr, NULL};
276 1.1 riastrad pid_t child, waitedpid;
277 1.1 riastrad int status;
278 1.1 riastrad
279 1.1 riastrad /*
280 1.1 riastrad * Format the h_cloexec helper executable path, which lives in
281 1.1 riastrad * the test's directory (typically /usr/tests/kernel), and the
282 1.1 riastrad * argument of a file descriptor in decimal.
283 1.1 riastrad */
284 1.1 riastrad snprintf(h_cloexec, sizeof(h_cloexec), "%s/h_cloexec",
285 1.1 riastrad atf_tc_get_config_var(tc, "srcdir"));
286 1.1 riastrad snprintf(fdstr, sizeof(fdstr), "%d", fd);
287 1.1 riastrad
288 1.1 riastrad /*
289 1.1 riastrad * Execute h_cloexec as a subprocess.
290 1.1 riastrad */
291 1.1 riastrad child = (*execfn)(h_cloexec, argv);
292 1.1 riastrad
293 1.1 riastrad /*
294 1.1 riastrad * Wait for the child to complete.
295 1.1 riastrad */
296 1.1 riastrad RL(waitedpid = waitpid(child, &status, 0));
297 1.1 riastrad ATF_CHECK_EQ_MSG(child, waitedpid, "waited for %jd, got %jd",
298 1.1 riastrad (intmax_t)child, (intmax_t)waitedpid);
299 1.1 riastrad
300 1.1 riastrad /*
301 1.1 riastrad * Verify the child exited normally.
302 1.1 riastrad */
303 1.1 riastrad if (WIFSIGNALED(status)) {
304 1.1 riastrad atf_tc_fail("subprocess terminated on signal %d",
305 1.1 riastrad WTERMSIG(status));
306 1.1 riastrad return;
307 1.1 riastrad } else if (!WIFEXITED(status)) {
308 1.1 riastrad atf_tc_fail("subprocess failed to exit normally: status=0x%x",
309 1.1 riastrad status);
310 1.1 riastrad return;
311 1.1 riastrad }
312 1.1 riastrad
313 1.1 riastrad /*
314 1.1 riastrad * h_cloexec is supposed to exit status 0 if an operation on
315 1.1 riastrad * the fd failed with EBADFD, 1 if it unexpectedly succeeded,
316 1.1 riastrad * 127 if exec returned, or something else if anything else
317 1.1 riastrad * happened.
318 1.1 riastrad */
319 1.1 riastrad switch (WEXITSTATUS(status)) {
320 1.1 riastrad case 0: /* success -- closed on exec */
321 1.1 riastrad return;
322 1.1 riastrad case 1: /* fail -- not closed on exec */
323 1.1 riastrad atf_tc_fail("fd was not closed on exec");
324 1.1 riastrad return;
325 1.1 riastrad case 127: /* exec failed */
326 1.1 riastrad atf_tc_fail("failed to exec h_cloexec");
327 1.1 riastrad return;
328 1.1 riastrad default: /* something else went wong */
329 1.1 riastrad atf_tc_fail("h_cloexec failed unexpectedly: %d",
330 1.1 riastrad WEXITSTATUS(status));
331 1.1 riastrad return;
332 1.1 riastrad }
333 1.1 riastrad }
334 1.1 riastrad
335 1.1 riastrad static pid_t
336 1.1 riastrad exec_via_forkexecve(char *prog, char *const argv[])
337 1.1 riastrad {
338 1.1 riastrad pid_t pid;
339 1.1 riastrad
340 1.1 riastrad RL(pid = fork());
341 1.1 riastrad if (pid == 0) { /* child */
342 1.1 riastrad if (execve(prog, argv, /*envp*/NULL) == -1)
343 1.1 riastrad _exit(127);
344 1.1 riastrad abort();
345 1.1 riastrad }
346 1.1 riastrad
347 1.1 riastrad /* parent */
348 1.1 riastrad return pid;
349 1.1 riastrad }
350 1.1 riastrad
351 1.1 riastrad static pid_t
352 1.1 riastrad exec_via_vforkexecve(char *prog, char *const argv[])
353 1.1 riastrad {
354 1.1 riastrad pid_t pid;
355 1.1 riastrad
356 1.1 riastrad RL(pid = vfork());
357 1.1 riastrad if (pid == 0) { /* child */
358 1.1 riastrad if (execve(prog, argv, /*envp*/NULL) == -1)
359 1.1 riastrad _exit(127);
360 1.1 riastrad abort();
361 1.1 riastrad }
362 1.1 riastrad
363 1.1 riastrad /* parent */
364 1.1 riastrad return pid;
365 1.1 riastrad }
366 1.1 riastrad
367 1.1 riastrad static pid_t
368 1.1 riastrad exec_via_posixspawn(char *prog, char *const argv[])
369 1.1 riastrad {
370 1.1 riastrad pid_t pid;
371 1.1 riastrad
372 1.1 riastrad RZ(posix_spawn(&pid, prog, /*file_actions*/NULL, /*attrp*/NULL, argv,
373 1.1 riastrad /*envp*/NULL));
374 1.1 riastrad
375 1.1 riastrad return pid;
376 1.1 riastrad }
377 1.1 riastrad
378 1.1 riastrad /*
379 1.1 riastrad * Full cartesian product is not really important here -- the paths for
380 1.1 riastrad * open and the paths for exec are independent. So we try
381 1.1 riastrad * pipe2(O_CLOEXEC) with each exec path, and we try each open path with
382 1.1 riastrad * posix_spawn.
383 1.1 riastrad */
384 1.1 riastrad
385 1.1 riastrad #define CLOEXEC_TEST(test, openvia, execvia, descr) \
386 1.1 riastrad ATF_TC(test); \
387 1.1 riastrad ATF_TC_HEAD(test, tc) \
388 1.1 riastrad { \
389 1.1 riastrad atf_tc_set_md_var(tc, "descr", descr); \
390 1.1 riastrad } \
391 1.1 riastrad ATF_TC_BODY(test, tc) \
392 1.1 riastrad { \
393 1.1 riastrad check_cloexec(tc, openvia(), &execvia); \
394 1.1 riastrad }
395 1.1 riastrad
396 1.1 riastrad CLOEXEC_TEST(pipe2rd_forkexecve, open_via_pipe2rd, exec_via_forkexecve,
397 1.1 riastrad "pipe2(O_CLOEXEC) reader is closed in child on fork/exec")
398 1.1 riastrad CLOEXEC_TEST(pipe2rd_vforkexecve, open_via_pipe2rd, exec_via_vforkexecve,
399 1.1 riastrad "pipe2(O_CLOEXEC) reader is closed in child on vfork/exec")
400 1.1 riastrad CLOEXEC_TEST(pipe2rd_posixspawn, open_via_pipe2rd, exec_via_posixspawn,
401 1.1 riastrad "pipe2(O_CLOEXEC) reader is closed in child on posix_spawn")
402 1.1 riastrad
403 1.1 riastrad CLOEXEC_TEST(accept4_posixspawn, open_via_accept4, exec_via_posixspawn,
404 1.1 riastrad "accept4(SOCK_CLOEXEC) is closed in child on posix_spawn");
405 1.1 riastrad CLOEXEC_TEST(clonedev_posixspawn, open_via_clonedev, exec_via_posixspawn,
406 1.1 riastrad "open(\"/dev/drvctl\") is closed in child on posix_spawn");
407 1.1 riastrad CLOEXEC_TEST(dup3_posixspawn, open_via_dup3, exec_via_posixspawn,
408 1.1 riastrad "dup3(..., O_CLOEXEC) is closed in child on posix_spawn");
409 1.1 riastrad CLOEXEC_TEST(fcntldupfd_posixspawn, open_via_fcntldupfd, exec_via_posixspawn,
410 1.1 riastrad "fcntl(STDIN_FILENO, F_DUPFD_CLOEXEC) is closed in child on posix_spawn");
411 1.1 riastrad CLOEXEC_TEST(kqueue_posixspawn, open_via_kqueue, exec_via_posixspawn,
412 1.1 riastrad "kqueue1(O_CLOEXEC) is closed in child on posix_spawn");
413 1.1 riastrad CLOEXEC_TEST(opencloexec_posixspawn, open_via_opencloexec, exec_via_posixspawn,
414 1.1 riastrad "open(O_CLOEXEC) is closed in child on posix_spawn");
415 1.1 riastrad CLOEXEC_TEST(openfcntlcloexec_posixspawn, open_via_openfcntlcloexec,
416 1.1 riastrad exec_via_posixspawn,
417 1.1 riastrad "fcntl(open(...), F_SETFD, O_CLOEXEC) is closed in child on posix_spawn");
418 1.1 riastrad CLOEXEC_TEST(openioctlfioclex_posixspawn, open_via_openioctlfioclex,
419 1.1 riastrad exec_via_posixspawn,
420 1.1 riastrad "ioctl(open(...), FIOCLEX) is closed in child on posix_spawn");
421 1.1 riastrad #if 0 /* already done above */
422 1.1 riastrad CLOEXEC_TEST(pipe2rd_posixspawn, open_via_pipe2rd, exec_via_posixspawn,
423 1.1 riastrad "pipe2(O_CLOEXEC) reader is closed in child on posix_spawn")
424 1.1 riastrad #endif
425 1.1 riastrad CLOEXEC_TEST(pipe2wr_posixspawn, open_via_pipe2wr, exec_via_posixspawn,
426 1.1 riastrad "pipe2(O_CLOEXEC) writer is closed in child on posix_spawn")
427 1.1 riastrad CLOEXEC_TEST(paccept_posixspawn, open_via_paccept, exec_via_posixspawn,
428 1.1 riastrad "paccept(..., SOCK_CLOEXEC) is closed in child on posix_spawn")
429 1.1 riastrad CLOEXEC_TEST(socket_posixspawn, open_via_socket, exec_via_posixspawn,
430 1.1 riastrad "socket(SOCK_CLOEXEC) is closed in child on posix_spawn")
431 1.1 riastrad CLOEXEC_TEST(socketpair0_posixspawn, open_via_socketpair0, exec_via_posixspawn,
432 1.1 riastrad "socketpair(SOCK_CLOEXEC) side 0 is closed in child on posix_spawn")
433 1.1 riastrad CLOEXEC_TEST(socketpair1_posixspawn, open_via_socketpair1, exec_via_posixspawn,
434 1.1 riastrad "socketpair(SOCK_CLOEXEC) side 1 is closed in child on posix_spawn")
435 1.1 riastrad
436 1.1 riastrad ATF_TP_ADD_TCS(tp)
437 1.1 riastrad {
438 1.1 riastrad
439 1.1 riastrad ATF_TP_ADD_TC(tp, accept4_posixspawn);
440 1.1 riastrad ATF_TP_ADD_TC(tp, clonedev_posixspawn);
441 1.1 riastrad ATF_TP_ADD_TC(tp, dup3_posixspawn);
442 1.1 riastrad ATF_TP_ADD_TC(tp, fcntldupfd_posixspawn);
443 1.1 riastrad ATF_TP_ADD_TC(tp, kqueue_posixspawn);
444 1.1 riastrad ATF_TP_ADD_TC(tp, opencloexec_posixspawn);
445 1.1 riastrad ATF_TP_ADD_TC(tp, openfcntlcloexec_posixspawn);
446 1.1 riastrad ATF_TP_ADD_TC(tp, openioctlfioclex_posixspawn);
447 1.1 riastrad ATF_TP_ADD_TC(tp, paccept_posixspawn);
448 1.1 riastrad ATF_TP_ADD_TC(tp, pipe2rd_forkexecve);
449 1.1 riastrad ATF_TP_ADD_TC(tp, pipe2rd_posixspawn);
450 1.1 riastrad ATF_TP_ADD_TC(tp, pipe2rd_vforkexecve);
451 1.1 riastrad ATF_TP_ADD_TC(tp, pipe2wr_posixspawn);
452 1.1 riastrad ATF_TP_ADD_TC(tp, socket_posixspawn);
453 1.1 riastrad ATF_TP_ADD_TC(tp, socketpair0_posixspawn);
454 1.1 riastrad ATF_TP_ADD_TC(tp, socketpair1_posixspawn);
455 1.1 riastrad
456 1.1 riastrad return atf_no_error();
457 1.1 riastrad }
458