xref: /illumos-gate/usr/src/test/os-tests/tests/oclo/oclo.c (revision 0250c53ad267726f2438e3c6556199a0bbf588a2)
1*0250c53aSRobert Mustacchi /*
2*0250c53aSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*0250c53aSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*0250c53aSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*0250c53aSRobert Mustacchi  * 1.0 of the CDDL.
6*0250c53aSRobert Mustacchi  *
7*0250c53aSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*0250c53aSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*0250c53aSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*0250c53aSRobert Mustacchi  */
11*0250c53aSRobert Mustacchi 
12*0250c53aSRobert Mustacchi /*
13*0250c53aSRobert Mustacchi  * Copyright 2024 Oxide Computer Company
14*0250c53aSRobert Mustacchi  */
15*0250c53aSRobert Mustacchi 
16*0250c53aSRobert Mustacchi /*
17*0250c53aSRobert Mustacchi  * Verify the behavior of the various O_CLOFORK and O_CLOEXEC variants. In
18*0250c53aSRobert Mustacchi  * particular getting this via:
19*0250c53aSRobert Mustacchi  *
20*0250c53aSRobert Mustacchi  *  - open(2): O_CLOFORK/O_CLOEXEC
21*0250c53aSRobert Mustacchi  *  - fcntl(2): F_SETFD FD_CLOFORK/FD_CLOEXEC
22*0250c53aSRobert Mustacchi  *  - fcntl(2): F_DUPFD_CLOFORK/F_DUPFD_CLOEXEC
23*0250c53aSRobert Mustacchi  *  - fcntl(2): F_DUP2FD_CLOFORK/F_DUP2FD_CLOEXEC
24*0250c53aSRobert Mustacchi  *  - dup2(3C)
25*0250c53aSRobert Mustacchi  *  - dup3(3C): argument translation
26*0250c53aSRobert Mustacchi  *  - pipe2(2)
27*0250c53aSRobert Mustacchi  *  - socket(2): SOCK_CLOEXEC/SOCK_CLOFORK
28*0250c53aSRobert Mustacchi  *  - accept(2): flags on the listen socket aren't inherited on accept
29*0250c53aSRobert Mustacchi  *  - socketpair(3SOCKET)
30*0250c53aSRobert Mustacchi  *  - accept4(2): SOCK_CLOEXEC/SOCK_CLOFORK
31*0250c53aSRobert Mustacchi  *  - recvmsg(2): SCM_RIGHTS MSG_CMSG_CLOFORK/MSG_CMSG_CLOEXEC
32*0250c53aSRobert Mustacchi  *
33*0250c53aSRobert Mustacchi  * The test is designed such that we have an array of functions that are used to
34*0250c53aSRobert Mustacchi  * create file descriptors with different rules. This is found in the
35*0250c53aSRobert Mustacchi  * oclo_create array. Each file descriptor that is created is then registered
36*0250c53aSRobert Mustacchi  * with information about what is expected about it. A given creation function
37*0250c53aSRobert Mustacchi  * can create more than one file descriptor; however, our expectation is that
38*0250c53aSRobert Mustacchi  * every file descriptor is accounted for (ignoring stdin, stdout, and stderr).
39*0250c53aSRobert Mustacchi  *
40*0250c53aSRobert Mustacchi  * We pass a record of each file descriptor that was recorded to a verification
41*0250c53aSRobert Mustacchi  * program that will verify everything is correctly honored after an exec.
42*0250c53aSRobert Mustacchi  */
43*0250c53aSRobert Mustacchi 
44*0250c53aSRobert Mustacchi #include <stdlib.h>
45*0250c53aSRobert Mustacchi #include <unistd.h>
46*0250c53aSRobert Mustacchi #include <stdbool.h>
47*0250c53aSRobert Mustacchi #include <err.h>
48*0250c53aSRobert Mustacchi #include <sys/types.h>
49*0250c53aSRobert Mustacchi #include <sys/stat.h>
50*0250c53aSRobert Mustacchi #include <fcntl.h>
51*0250c53aSRobert Mustacchi #include <sys/sysmacros.h>
52*0250c53aSRobert Mustacchi #include <sys/fork.h>
53*0250c53aSRobert Mustacchi #include <wait.h>
54*0250c53aSRobert Mustacchi #include <errno.h>
55*0250c53aSRobert Mustacchi #include <string.h>
56*0250c53aSRobert Mustacchi #include <limits.h>
57*0250c53aSRobert Mustacchi #include <libgen.h>
58*0250c53aSRobert Mustacchi #include <sys/socket.h>
59*0250c53aSRobert Mustacchi 
60*0250c53aSRobert Mustacchi /*
61*0250c53aSRobert Mustacchi  * Verification program name.
62*0250c53aSRobert Mustacchi  */
63*0250c53aSRobert Mustacchi #define	OCLO_VERIFY	"ocloexec_verify"
64*0250c53aSRobert Mustacchi 
65*0250c53aSRobert Mustacchi /*
66*0250c53aSRobert Mustacchi  * This structure represents a table of ways we expect to create file
67*0250c53aSRobert Mustacchi  * descriptors that should have the resulting flags set when done. The table is
68*0250c53aSRobert Mustacchi  * ordered and subsequent iterations are allowed to assume that the ones that
69*0250c53aSRobert Mustacchi  * have gone ahead of them have run and are therefore allowed to access them.
70*0250c53aSRobert Mustacchi  * The create function is expected to return the created fd.
71*0250c53aSRobert Mustacchi  */
72*0250c53aSRobert Mustacchi typedef struct clo_create clo_create_t;
73*0250c53aSRobert Mustacchi struct clo_create {
74*0250c53aSRobert Mustacchi 	const char *clo_desc;
75*0250c53aSRobert Mustacchi 	int clo_flags;
76*0250c53aSRobert Mustacchi 	void (*clo_func)(const clo_create_t *);
77*0250c53aSRobert Mustacchi };
78*0250c53aSRobert Mustacchi 
79*0250c53aSRobert Mustacchi /*
80*0250c53aSRobert Mustacchi  * This is our run-time data. We expect all file descriptors to be registered by
81*0250c53aSRobert Mustacchi  * our calling functions through oclo_record().
82*0250c53aSRobert Mustacchi  */
83*0250c53aSRobert Mustacchi typedef struct clo_rtdata {
84*0250c53aSRobert Mustacchi 	const clo_create_t *crt_data;
85*0250c53aSRobert Mustacchi 	size_t crt_idx;
86*0250c53aSRobert Mustacchi 	int crt_fd;
87*0250c53aSRobert Mustacchi 	int crt_flags;
88*0250c53aSRobert Mustacchi 	const char *crt_desc;
89*0250c53aSRobert Mustacchi } clo_rtdata_t;
90*0250c53aSRobert Mustacchi 
91*0250c53aSRobert Mustacchi static clo_rtdata_t *oclo_rtdata;
92*0250c53aSRobert Mustacchi size_t oclo_rtdata_nents = 0;
93*0250c53aSRobert Mustacchi size_t oclo_rtdata_next = 0;
94*0250c53aSRobert Mustacchi static int oclo_nextfd = STDERR_FILENO + 1;
95*0250c53aSRobert Mustacchi 
96*0250c53aSRobert Mustacchi static bool
oclo_flags_match(const clo_rtdata_t * rt,bool child)97*0250c53aSRobert Mustacchi oclo_flags_match(const clo_rtdata_t *rt, bool child)
98*0250c53aSRobert Mustacchi {
99*0250c53aSRobert Mustacchi 	const char *pass = child ? "post-fork" : "pre-fork";
100*0250c53aSRobert Mustacchi 	bool fail = child && (rt->crt_flags & FD_CLOFORK) != 0;
101*0250c53aSRobert Mustacchi 	int flags = fcntl(rt->crt_fd, F_GETFD, NULL);
102*0250c53aSRobert Mustacchi 
103*0250c53aSRobert Mustacchi 	if (flags < 0) {
104*0250c53aSRobert Mustacchi 		int e = errno;
105*0250c53aSRobert Mustacchi 
106*0250c53aSRobert Mustacchi 		if (fail) {
107*0250c53aSRobert Mustacchi 			if (e == EBADF) {
108*0250c53aSRobert Mustacchi 				(void) printf("TEST PASSED: %s (%s): fd %d: "
109*0250c53aSRobert Mustacchi 				    "correctly closed\n",
110*0250c53aSRobert Mustacchi 				    rt->crt_data->clo_desc, pass, rt->crt_fd);
111*0250c53aSRobert Mustacchi 				return (true);
112*0250c53aSRobert Mustacchi 			}
113*0250c53aSRobert Mustacchi 
114*0250c53aSRobert Mustacchi 			warn("TEST FAILED: %s (%s): fd %d: expected fcntl to "
115*0250c53aSRobert Mustacchi 			    "fail with EBADF, but found %s",
116*0250c53aSRobert Mustacchi 			    rt->crt_data->clo_desc, pass, rt->crt_fd,
117*0250c53aSRobert Mustacchi 			    strerrorname_np(e));
118*0250c53aSRobert Mustacchi 			return (false);
119*0250c53aSRobert Mustacchi 		}
120*0250c53aSRobert Mustacchi 
121*0250c53aSRobert Mustacchi 		warnx("TEST FAILED: %s (%s): fd %d: fcntl(F_GETFD) "
122*0250c53aSRobert Mustacchi 		    "unexpectedly failed", rt->crt_data->clo_desc, pass,
123*0250c53aSRobert Mustacchi 		    rt->crt_fd);
124*0250c53aSRobert Mustacchi 		return (false);
125*0250c53aSRobert Mustacchi 	}
126*0250c53aSRobert Mustacchi 
127*0250c53aSRobert Mustacchi 	if (fail) {
128*0250c53aSRobert Mustacchi 		warnx("TEST FAILED: %s (%s): fd %d: received flags %d, but "
129*0250c53aSRobert Mustacchi 		    "expected to fail based on flags %d",
130*0250c53aSRobert Mustacchi 		    rt->crt_data->clo_desc, pass, rt->crt_fd, flags,
131*0250c53aSRobert Mustacchi 		    rt->crt_fd);
132*0250c53aSRobert Mustacchi 		return (false);
133*0250c53aSRobert Mustacchi 	}
134*0250c53aSRobert Mustacchi 
135*0250c53aSRobert Mustacchi 	if (flags != rt->crt_flags) {
136*0250c53aSRobert Mustacchi 		warnx("TEST FAILED: %s (%s): fd %d: discovered flags 0x%x do "
137*0250c53aSRobert Mustacchi 		    "not match expected flags 0x%x", rt->crt_data->clo_desc,
138*0250c53aSRobert Mustacchi 		    pass, rt->crt_fd, flags, rt->crt_fd);
139*0250c53aSRobert Mustacchi 		return (false);
140*0250c53aSRobert Mustacchi 	}
141*0250c53aSRobert Mustacchi 
142*0250c53aSRobert Mustacchi 	(void) printf("TEST PASSED: %s (%s): fd %d discovered flags match "
143*0250c53aSRobert Mustacchi 	    "(0x%x)\n", rt->crt_data->clo_desc, pass, rt->crt_fd, flags);
144*0250c53aSRobert Mustacchi 	return (true);
145*0250c53aSRobert Mustacchi }
146*0250c53aSRobert Mustacchi 
147*0250c53aSRobert Mustacchi 
148*0250c53aSRobert Mustacchi static void
oclo_record(const clo_create_t * c,int fd,int exp_flags,const char * desc)149*0250c53aSRobert Mustacchi oclo_record(const clo_create_t *c, int fd, int exp_flags, const char *desc)
150*0250c53aSRobert Mustacchi {
151*0250c53aSRobert Mustacchi 	if (oclo_rtdata_next == oclo_rtdata_nents) {
152*0250c53aSRobert Mustacchi 		size_t newrt = oclo_rtdata_nents + 8;
153*0250c53aSRobert Mustacchi 		clo_rtdata_t *rt;
154*0250c53aSRobert Mustacchi 		rt = recallocarray(oclo_rtdata, oclo_rtdata_nents, newrt,
155*0250c53aSRobert Mustacchi 		    sizeof (clo_rtdata_t));
156*0250c53aSRobert Mustacchi 		if (rt == NULL) {
157*0250c53aSRobert Mustacchi 			err(EXIT_FAILURE, "TEST_FAILED: internal error "
158*0250c53aSRobert Mustacchi 			    "expanding fd records to %zu entries", newrt);
159*0250c53aSRobert Mustacchi 		}
160*0250c53aSRobert Mustacchi 
161*0250c53aSRobert Mustacchi 		oclo_rtdata_nents = newrt;
162*0250c53aSRobert Mustacchi 		oclo_rtdata = rt;
163*0250c53aSRobert Mustacchi 	}
164*0250c53aSRobert Mustacchi 
165*0250c53aSRobert Mustacchi 	if (fd != oclo_nextfd) {
166*0250c53aSRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: internal test error: expected "
167*0250c53aSRobert Mustacchi 		    "to record next fd %d, given %d", oclo_nextfd, fd);
168*0250c53aSRobert Mustacchi 	}
169*0250c53aSRobert Mustacchi 
170*0250c53aSRobert Mustacchi 	oclo_rtdata[oclo_rtdata_next].crt_data = c;
171*0250c53aSRobert Mustacchi 	oclo_rtdata[oclo_rtdata_next].crt_fd = fd;
172*0250c53aSRobert Mustacchi 	oclo_rtdata[oclo_rtdata_next].crt_flags = exp_flags;
173*0250c53aSRobert Mustacchi 	oclo_rtdata[oclo_rtdata_next].crt_desc = desc;
174*0250c53aSRobert Mustacchi 
175*0250c53aSRobert Mustacchi 	/*
176*0250c53aSRobert Mustacchi 	 * Matching errors at this phase are fatal as it means we screwed up the
177*0250c53aSRobert Mustacchi 	 * program pretty badly.
178*0250c53aSRobert Mustacchi 	 */
179*0250c53aSRobert Mustacchi 	if (!oclo_flags_match(&oclo_rtdata[oclo_rtdata_next], false)) {
180*0250c53aSRobert Mustacchi 		exit(EXIT_FAILURE);
181*0250c53aSRobert Mustacchi 	}
182*0250c53aSRobert Mustacchi 
183*0250c53aSRobert Mustacchi 	oclo_rtdata_next++;
184*0250c53aSRobert Mustacchi 	oclo_nextfd++;
185*0250c53aSRobert Mustacchi }
186*0250c53aSRobert Mustacchi 
187*0250c53aSRobert Mustacchi static int
oclo_file(const clo_create_t * c)188*0250c53aSRobert Mustacchi oclo_file(const clo_create_t *c)
189*0250c53aSRobert Mustacchi {
190*0250c53aSRobert Mustacchi 	int flags = O_RDWR, fd;
191*0250c53aSRobert Mustacchi 
192*0250c53aSRobert Mustacchi 	if ((c->clo_flags & FD_CLOEXEC) != 0)
193*0250c53aSRobert Mustacchi 		flags |= O_CLOEXEC;
194*0250c53aSRobert Mustacchi 	if ((c->clo_flags & FD_CLOFORK) != 0)
195*0250c53aSRobert Mustacchi 		flags |= O_CLOFORK;
196*0250c53aSRobert Mustacchi 	fd = open("/dev/null", flags);
197*0250c53aSRobert Mustacchi 	if (fd < 0) {
198*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to open /dev/null",
199*0250c53aSRobert Mustacchi 		    c->clo_desc);
200*0250c53aSRobert Mustacchi 	}
201*0250c53aSRobert Mustacchi 
202*0250c53aSRobert Mustacchi 	return (fd);
203*0250c53aSRobert Mustacchi }
204*0250c53aSRobert Mustacchi 
205*0250c53aSRobert Mustacchi static void
oclo_open(const clo_create_t * c)206*0250c53aSRobert Mustacchi oclo_open(const clo_create_t *c)
207*0250c53aSRobert Mustacchi {
208*0250c53aSRobert Mustacchi 	oclo_record(c, oclo_file(c), c->clo_flags, NULL);
209*0250c53aSRobert Mustacchi }
210*0250c53aSRobert Mustacchi 
211*0250c53aSRobert Mustacchi static void
oclo_setfd_common(const clo_create_t * c,int targ_flags)212*0250c53aSRobert Mustacchi oclo_setfd_common(const clo_create_t *c, int targ_flags)
213*0250c53aSRobert Mustacchi {
214*0250c53aSRobert Mustacchi 	int fd = oclo_file(c);
215*0250c53aSRobert Mustacchi 	if (fcntl(fd, F_SETFD, targ_flags) < 0) {
216*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: F_SETFD failed to set "
217*0250c53aSRobert Mustacchi 		    "flags to %d", c->clo_desc, targ_flags);
218*0250c53aSRobert Mustacchi 	}
219*0250c53aSRobert Mustacchi 
220*0250c53aSRobert Mustacchi 	oclo_record(c, fd, targ_flags, NULL);
221*0250c53aSRobert Mustacchi }
222*0250c53aSRobert Mustacchi 
223*0250c53aSRobert Mustacchi static void
oclo_setfd_none(const clo_create_t * c)224*0250c53aSRobert Mustacchi oclo_setfd_none(const clo_create_t *c)
225*0250c53aSRobert Mustacchi {
226*0250c53aSRobert Mustacchi 	oclo_setfd_common(c, 0);
227*0250c53aSRobert Mustacchi }
228*0250c53aSRobert Mustacchi 
229*0250c53aSRobert Mustacchi static void
oclo_setfd_exec(const clo_create_t * c)230*0250c53aSRobert Mustacchi oclo_setfd_exec(const clo_create_t *c)
231*0250c53aSRobert Mustacchi {
232*0250c53aSRobert Mustacchi 	oclo_setfd_common(c, FD_CLOEXEC);
233*0250c53aSRobert Mustacchi }
234*0250c53aSRobert Mustacchi 
235*0250c53aSRobert Mustacchi static void
oclo_setfd_fork(const clo_create_t * c)236*0250c53aSRobert Mustacchi oclo_setfd_fork(const clo_create_t *c)
237*0250c53aSRobert Mustacchi {
238*0250c53aSRobert Mustacchi 	oclo_setfd_common(c, FD_CLOFORK);
239*0250c53aSRobert Mustacchi }
240*0250c53aSRobert Mustacchi 
241*0250c53aSRobert Mustacchi static void
oclo_setfd_both(const clo_create_t * c)242*0250c53aSRobert Mustacchi oclo_setfd_both(const clo_create_t *c)
243*0250c53aSRobert Mustacchi {
244*0250c53aSRobert Mustacchi 	oclo_setfd_common(c, FD_CLOFORK | FD_CLOEXEC);
245*0250c53aSRobert Mustacchi }
246*0250c53aSRobert Mustacchi 
247*0250c53aSRobert Mustacchi /*
248*0250c53aSRobert Mustacchi  * Open an fd with flags in a certain form and then use one of the F_DUPFD or
249*0250c53aSRobert Mustacchi  * F_DUP2FD variants and ensure that flags are properly propagated as expected.
250*0250c53aSRobert Mustacchi  */
251*0250c53aSRobert Mustacchi static void
oclo_fdup_common(const clo_create_t * c,int targ_flags,int cmd)252*0250c53aSRobert Mustacchi oclo_fdup_common(const clo_create_t *c, int targ_flags, int cmd)
253*0250c53aSRobert Mustacchi {
254*0250c53aSRobert Mustacchi 	int dup, fd;
255*0250c53aSRobert Mustacchi 
256*0250c53aSRobert Mustacchi 	fd = oclo_file(c);
257*0250c53aSRobert Mustacchi 	oclo_record(c, fd, c->clo_flags, "base");
258*0250c53aSRobert Mustacchi 	switch (cmd) {
259*0250c53aSRobert Mustacchi 	case F_DUPFD:
260*0250c53aSRobert Mustacchi 	case F_DUPFD_CLOEXEC:
261*0250c53aSRobert Mustacchi 	case F_DUPFD_CLOFORK:
262*0250c53aSRobert Mustacchi 		dup = fcntl(fd, cmd, fd);
263*0250c53aSRobert Mustacchi 		break;
264*0250c53aSRobert Mustacchi 	case F_DUP2FD:
265*0250c53aSRobert Mustacchi 	case F_DUP2FD_CLOEXEC:
266*0250c53aSRobert Mustacchi 	case F_DUP2FD_CLOFORK:
267*0250c53aSRobert Mustacchi 		dup = fcntl(fd, cmd, fd + 1);
268*0250c53aSRobert Mustacchi 		break;
269*0250c53aSRobert Mustacchi 	case F_DUP3FD:
270*0250c53aSRobert Mustacchi 		dup = fcntl(fd, cmd, fd + 1, targ_flags);
271*0250c53aSRobert Mustacchi 		break;
272*0250c53aSRobert Mustacchi 	default:
273*0250c53aSRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILURE: %s: internal error: "
274*0250c53aSRobert Mustacchi 		    "unexpected fcntl cmd: 0x%x", c->clo_desc, cmd);
275*0250c53aSRobert Mustacchi 	}
276*0250c53aSRobert Mustacchi 
277*0250c53aSRobert Mustacchi 	if (dup < 0) {
278*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILURE: %s: failed to dup fd with "
279*0250c53aSRobert Mustacchi 		    "fcntl command 0x%x", c->clo_desc, cmd);
280*0250c53aSRobert Mustacchi 	}
281*0250c53aSRobert Mustacchi 
282*0250c53aSRobert Mustacchi 	oclo_record(c, dup, targ_flags, "dup");
283*0250c53aSRobert Mustacchi }
284*0250c53aSRobert Mustacchi 
285*0250c53aSRobert Mustacchi static void
oclo_fdupfd(const clo_create_t * c)286*0250c53aSRobert Mustacchi oclo_fdupfd(const clo_create_t *c)
287*0250c53aSRobert Mustacchi {
288*0250c53aSRobert Mustacchi 	oclo_fdup_common(c, 0, F_DUPFD);
289*0250c53aSRobert Mustacchi }
290*0250c53aSRobert Mustacchi 
291*0250c53aSRobert Mustacchi static void
oclo_fdupfd_fork(const clo_create_t * c)292*0250c53aSRobert Mustacchi oclo_fdupfd_fork(const clo_create_t *c)
293*0250c53aSRobert Mustacchi {
294*0250c53aSRobert Mustacchi 	oclo_fdup_common(c, FD_CLOFORK, F_DUPFD_CLOFORK);
295*0250c53aSRobert Mustacchi }
296*0250c53aSRobert Mustacchi 
297*0250c53aSRobert Mustacchi static void
oclo_fdupfd_exec(const clo_create_t * c)298*0250c53aSRobert Mustacchi oclo_fdupfd_exec(const clo_create_t *c)
299*0250c53aSRobert Mustacchi {
300*0250c53aSRobert Mustacchi 	oclo_fdup_common(c, FD_CLOEXEC, F_DUPFD_CLOEXEC);
301*0250c53aSRobert Mustacchi }
302*0250c53aSRobert Mustacchi 
303*0250c53aSRobert Mustacchi static void
oclo_fdup2fd(const clo_create_t * c)304*0250c53aSRobert Mustacchi oclo_fdup2fd(const clo_create_t *c)
305*0250c53aSRobert Mustacchi {
306*0250c53aSRobert Mustacchi 	oclo_fdup_common(c, 0, F_DUP2FD);
307*0250c53aSRobert Mustacchi }
308*0250c53aSRobert Mustacchi 
309*0250c53aSRobert Mustacchi static void
oclo_fdup2fd_fork(const clo_create_t * c)310*0250c53aSRobert Mustacchi oclo_fdup2fd_fork(const clo_create_t *c)
311*0250c53aSRobert Mustacchi {
312*0250c53aSRobert Mustacchi 	oclo_fdup_common(c, FD_CLOFORK, F_DUP2FD_CLOFORK);
313*0250c53aSRobert Mustacchi }
314*0250c53aSRobert Mustacchi 
315*0250c53aSRobert Mustacchi static void
oclo_fdup2fd_exec(const clo_create_t * c)316*0250c53aSRobert Mustacchi oclo_fdup2fd_exec(const clo_create_t *c)
317*0250c53aSRobert Mustacchi {
318*0250c53aSRobert Mustacchi 	oclo_fdup_common(c, FD_CLOEXEC, F_DUP2FD_CLOEXEC);
319*0250c53aSRobert Mustacchi }
320*0250c53aSRobert Mustacchi 
321*0250c53aSRobert Mustacchi static void
oclo_fdup3fd_none(const clo_create_t * c)322*0250c53aSRobert Mustacchi oclo_fdup3fd_none(const clo_create_t *c)
323*0250c53aSRobert Mustacchi {
324*0250c53aSRobert Mustacchi 	oclo_fdup_common(c, 0, F_DUP3FD);
325*0250c53aSRobert Mustacchi }
326*0250c53aSRobert Mustacchi 
327*0250c53aSRobert Mustacchi static void
oclo_fdup3fd_exec(const clo_create_t * c)328*0250c53aSRobert Mustacchi oclo_fdup3fd_exec(const clo_create_t *c)
329*0250c53aSRobert Mustacchi {
330*0250c53aSRobert Mustacchi 	oclo_fdup_common(c, FD_CLOEXEC, F_DUP3FD);
331*0250c53aSRobert Mustacchi }
332*0250c53aSRobert Mustacchi 
333*0250c53aSRobert Mustacchi static void
oclo_fdup3fd_fork(const clo_create_t * c)334*0250c53aSRobert Mustacchi oclo_fdup3fd_fork(const clo_create_t *c)
335*0250c53aSRobert Mustacchi {
336*0250c53aSRobert Mustacchi 	oclo_fdup_common(c, FD_CLOFORK, F_DUP3FD);
337*0250c53aSRobert Mustacchi }
338*0250c53aSRobert Mustacchi 
339*0250c53aSRobert Mustacchi static void
oclo_fdup3fd_both(const clo_create_t * c)340*0250c53aSRobert Mustacchi oclo_fdup3fd_both(const clo_create_t *c)
341*0250c53aSRobert Mustacchi {
342*0250c53aSRobert Mustacchi 	oclo_fdup_common(c, FD_CLOEXEC | FD_CLOFORK, F_DUP3FD);
343*0250c53aSRobert Mustacchi }
344*0250c53aSRobert Mustacchi 
345*0250c53aSRobert Mustacchi static void
oclo_dup_common(const clo_create_t * c,int targ_flags,bool v3)346*0250c53aSRobert Mustacchi oclo_dup_common(const clo_create_t *c, int targ_flags, bool v3)
347*0250c53aSRobert Mustacchi {
348*0250c53aSRobert Mustacchi 	int dup, fd;
349*0250c53aSRobert Mustacchi 	fd = oclo_file(c);
350*0250c53aSRobert Mustacchi 	oclo_record(c, fd, c->clo_flags, "base");
351*0250c53aSRobert Mustacchi 	if (v3) {
352*0250c53aSRobert Mustacchi 		int dflags = 0;
353*0250c53aSRobert Mustacchi 		if ((targ_flags & FD_CLOEXEC) != 0)
354*0250c53aSRobert Mustacchi 			dflags |= O_CLOEXEC;
355*0250c53aSRobert Mustacchi 		if ((targ_flags & FD_CLOFORK) != 0)
356*0250c53aSRobert Mustacchi 			dflags |= O_CLOFORK;
357*0250c53aSRobert Mustacchi 		dup = dup3(fd, fd + 1, dflags);
358*0250c53aSRobert Mustacchi 	} else {
359*0250c53aSRobert Mustacchi 		dup = dup2(fd, fd + 1);
360*0250c53aSRobert Mustacchi 	}
361*0250c53aSRobert Mustacchi 
362*0250c53aSRobert Mustacchi 	oclo_record(c, dup, targ_flags, "dup");
363*0250c53aSRobert Mustacchi }
364*0250c53aSRobert Mustacchi 
365*0250c53aSRobert Mustacchi static void
oclo_dup2(const clo_create_t * c)366*0250c53aSRobert Mustacchi oclo_dup2(const clo_create_t *c)
367*0250c53aSRobert Mustacchi {
368*0250c53aSRobert Mustacchi 	oclo_dup_common(c, 0, false);
369*0250c53aSRobert Mustacchi }
370*0250c53aSRobert Mustacchi 
371*0250c53aSRobert Mustacchi static void
oclo_dup3_none(const clo_create_t * c)372*0250c53aSRobert Mustacchi oclo_dup3_none(const clo_create_t *c)
373*0250c53aSRobert Mustacchi {
374*0250c53aSRobert Mustacchi 	oclo_dup_common(c, 0, true);
375*0250c53aSRobert Mustacchi }
376*0250c53aSRobert Mustacchi 
377*0250c53aSRobert Mustacchi static void
oclo_dup3_exec(const clo_create_t * c)378*0250c53aSRobert Mustacchi oclo_dup3_exec(const clo_create_t *c)
379*0250c53aSRobert Mustacchi {
380*0250c53aSRobert Mustacchi 	oclo_dup_common(c, FD_CLOEXEC, true);
381*0250c53aSRobert Mustacchi }
382*0250c53aSRobert Mustacchi 
383*0250c53aSRobert Mustacchi static void
oclo_dup3_fork(const clo_create_t * c)384*0250c53aSRobert Mustacchi oclo_dup3_fork(const clo_create_t *c)
385*0250c53aSRobert Mustacchi {
386*0250c53aSRobert Mustacchi 	oclo_dup_common(c, FD_CLOFORK, true);
387*0250c53aSRobert Mustacchi }
388*0250c53aSRobert Mustacchi 
389*0250c53aSRobert Mustacchi static void
oclo_dup3_both(const clo_create_t * c)390*0250c53aSRobert Mustacchi oclo_dup3_both(const clo_create_t *c)
391*0250c53aSRobert Mustacchi {
392*0250c53aSRobert Mustacchi 	oclo_dup_common(c, FD_CLOEXEC | FD_CLOFORK, true);
393*0250c53aSRobert Mustacchi }
394*0250c53aSRobert Mustacchi 
395*0250c53aSRobert Mustacchi static void
oclo_pipe(const clo_create_t * c)396*0250c53aSRobert Mustacchi oclo_pipe(const clo_create_t *c)
397*0250c53aSRobert Mustacchi {
398*0250c53aSRobert Mustacchi 	int flags = 0, fds[2];
399*0250c53aSRobert Mustacchi 
400*0250c53aSRobert Mustacchi 	if ((c->clo_flags & FD_CLOEXEC) != 0)
401*0250c53aSRobert Mustacchi 		flags |= O_CLOEXEC;
402*0250c53aSRobert Mustacchi 	if ((c->clo_flags & FD_CLOFORK) != 0)
403*0250c53aSRobert Mustacchi 		flags |= O_CLOFORK;
404*0250c53aSRobert Mustacchi 
405*0250c53aSRobert Mustacchi 	if (pipe2(fds, flags) < 0) {
406*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: pipe2() with flags %d "
407*0250c53aSRobert Mustacchi 		    "failed", c->clo_desc, flags);
408*0250c53aSRobert Mustacchi 	}
409*0250c53aSRobert Mustacchi 
410*0250c53aSRobert Mustacchi 	oclo_record(c, fds[0], c->clo_flags, "pipe[0]");
411*0250c53aSRobert Mustacchi 	oclo_record(c, fds[1], c->clo_flags, "pipe[1]");
412*0250c53aSRobert Mustacchi }
413*0250c53aSRobert Mustacchi 
414*0250c53aSRobert Mustacchi static void
oclo_socket(const clo_create_t * c)415*0250c53aSRobert Mustacchi oclo_socket(const clo_create_t *c)
416*0250c53aSRobert Mustacchi {
417*0250c53aSRobert Mustacchi 	int type = SOCK_DGRAM, fd;
418*0250c53aSRobert Mustacchi 
419*0250c53aSRobert Mustacchi 	if ((c->clo_flags & FD_CLOEXEC) != 0)
420*0250c53aSRobert Mustacchi 		type |= SOCK_CLOEXEC;
421*0250c53aSRobert Mustacchi 	if ((c->clo_flags & FD_CLOFORK) != 0)
422*0250c53aSRobert Mustacchi 		type |= SOCK_CLOFORK;
423*0250c53aSRobert Mustacchi 	fd = socket(PF_INET, type, 0);
424*0250c53aSRobert Mustacchi 	if (fd < 0) {
425*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to create socket "
426*0250c53aSRobert Mustacchi 		    "with flags: 0x%x\n", c->clo_desc, c->clo_flags);
427*0250c53aSRobert Mustacchi 	}
428*0250c53aSRobert Mustacchi 
429*0250c53aSRobert Mustacchi 	oclo_record(c, fd, c->clo_flags, NULL);
430*0250c53aSRobert Mustacchi }
431*0250c53aSRobert Mustacchi 
432*0250c53aSRobert Mustacchi static void
oclo_accept_common(const clo_create_t * c,int targ_flags,bool a4)433*0250c53aSRobert Mustacchi oclo_accept_common(const clo_create_t *c, int targ_flags, bool a4)
434*0250c53aSRobert Mustacchi {
435*0250c53aSRobert Mustacchi 	int lsock, csock, asock;
436*0250c53aSRobert Mustacchi 	int ltype = SOCK_STREAM, atype = 0;
437*0250c53aSRobert Mustacchi 	struct sockaddr_in in;
438*0250c53aSRobert Mustacchi 	socklen_t slen;
439*0250c53aSRobert Mustacchi 
440*0250c53aSRobert Mustacchi 	if ((c->clo_flags & FD_CLOEXEC) != 0)
441*0250c53aSRobert Mustacchi 		ltype |= SOCK_CLOEXEC;
442*0250c53aSRobert Mustacchi 	if ((c->clo_flags & FD_CLOFORK) != 0)
443*0250c53aSRobert Mustacchi 		ltype |= SOCK_CLOFORK;
444*0250c53aSRobert Mustacchi 
445*0250c53aSRobert Mustacchi 	if ((targ_flags & FD_CLOEXEC) != 0)
446*0250c53aSRobert Mustacchi 		atype |= SOCK_CLOEXEC;
447*0250c53aSRobert Mustacchi 	if ((targ_flags & FD_CLOFORK) != 0)
448*0250c53aSRobert Mustacchi 		atype |= SOCK_CLOFORK;
449*0250c53aSRobert Mustacchi 
450*0250c53aSRobert Mustacchi 	lsock = socket(PF_INET, ltype, 0);
451*0250c53aSRobert Mustacchi 	if (lsock < 0) {
452*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to create listen "
453*0250c53aSRobert Mustacchi 		    "socket with flags: 0x%x\n", c->clo_desc, c->clo_flags);
454*0250c53aSRobert Mustacchi 	}
455*0250c53aSRobert Mustacchi 
456*0250c53aSRobert Mustacchi 	oclo_record(c, lsock, c->clo_flags, "listen");
457*0250c53aSRobert Mustacchi 	(void) memset(&in, 0, sizeof (in));
458*0250c53aSRobert Mustacchi 	in.sin_family = AF_INET;
459*0250c53aSRobert Mustacchi 	in.sin_port = 0;
460*0250c53aSRobert Mustacchi 	in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
461*0250c53aSRobert Mustacchi 
462*0250c53aSRobert Mustacchi 	if (bind(lsock, (struct sockaddr *)&in, sizeof (in)) != 0) {
463*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to bind socket",
464*0250c53aSRobert Mustacchi 		    c->clo_desc);
465*0250c53aSRobert Mustacchi 	}
466*0250c53aSRobert Mustacchi 
467*0250c53aSRobert Mustacchi 	slen = sizeof (struct sockaddr_in);
468*0250c53aSRobert Mustacchi 	if (getsockname(lsock, (struct sockaddr *)&in, &slen) != 0) {
469*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to discover bound "
470*0250c53aSRobert Mustacchi 		    "socket address", c->clo_desc);
471*0250c53aSRobert Mustacchi 	}
472*0250c53aSRobert Mustacchi 
473*0250c53aSRobert Mustacchi 	if (listen(lsock, 5) < 0) {
474*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to listen on socket",
475*0250c53aSRobert Mustacchi 		    c->clo_desc);
476*0250c53aSRobert Mustacchi 	}
477*0250c53aSRobert Mustacchi 
478*0250c53aSRobert Mustacchi 	csock = socket(PF_INET, SOCK_STREAM, 0);
479*0250c53aSRobert Mustacchi 	if (csock < 0) {
480*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to create client "
481*0250c53aSRobert Mustacchi 		    "socket", c->clo_desc);
482*0250c53aSRobert Mustacchi 	}
483*0250c53aSRobert Mustacchi 	oclo_record(c, csock, 0, "connect");
484*0250c53aSRobert Mustacchi 
485*0250c53aSRobert Mustacchi 	if (connect(csock, (struct sockaddr *)&in, sizeof (in)) != 0) {
486*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to connect to "
487*0250c53aSRobert Mustacchi 		    "server socket", c->clo_desc);
488*0250c53aSRobert Mustacchi 	}
489*0250c53aSRobert Mustacchi 
490*0250c53aSRobert Mustacchi 	if (a4) {
491*0250c53aSRobert Mustacchi 		asock = accept4(lsock, NULL, NULL, atype);
492*0250c53aSRobert Mustacchi 	} else {
493*0250c53aSRobert Mustacchi 		asock = accept(lsock, NULL, NULL);
494*0250c53aSRobert Mustacchi 	}
495*0250c53aSRobert Mustacchi 	if (asock < 0) {
496*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to accept client "
497*0250c53aSRobert Mustacchi 		    "connection", c->clo_desc);
498*0250c53aSRobert Mustacchi 	}
499*0250c53aSRobert Mustacchi 	oclo_record(c, asock, targ_flags, "accept");
500*0250c53aSRobert Mustacchi }
501*0250c53aSRobert Mustacchi 
502*0250c53aSRobert Mustacchi static void
oclo_accept(const clo_create_t * c)503*0250c53aSRobert Mustacchi oclo_accept(const clo_create_t *c)
504*0250c53aSRobert Mustacchi {
505*0250c53aSRobert Mustacchi 	oclo_accept_common(c, 0, false);
506*0250c53aSRobert Mustacchi }
507*0250c53aSRobert Mustacchi 
508*0250c53aSRobert Mustacchi static void
oclo_accept4_none(const clo_create_t * c)509*0250c53aSRobert Mustacchi oclo_accept4_none(const clo_create_t *c)
510*0250c53aSRobert Mustacchi {
511*0250c53aSRobert Mustacchi 	oclo_accept_common(c, 0, true);
512*0250c53aSRobert Mustacchi }
513*0250c53aSRobert Mustacchi 
514*0250c53aSRobert Mustacchi static void
oclo_accept4_fork(const clo_create_t * c)515*0250c53aSRobert Mustacchi oclo_accept4_fork(const clo_create_t *c)
516*0250c53aSRobert Mustacchi {
517*0250c53aSRobert Mustacchi 	oclo_accept_common(c, FD_CLOFORK, true);
518*0250c53aSRobert Mustacchi }
519*0250c53aSRobert Mustacchi 
520*0250c53aSRobert Mustacchi static void
oclo_accept4_exec(const clo_create_t * c)521*0250c53aSRobert Mustacchi oclo_accept4_exec(const clo_create_t *c)
522*0250c53aSRobert Mustacchi {
523*0250c53aSRobert Mustacchi 	oclo_accept_common(c, FD_CLOEXEC, true);
524*0250c53aSRobert Mustacchi }
525*0250c53aSRobert Mustacchi 
526*0250c53aSRobert Mustacchi static void
oclo_accept4_both(const clo_create_t * c)527*0250c53aSRobert Mustacchi oclo_accept4_both(const clo_create_t *c)
528*0250c53aSRobert Mustacchi {
529*0250c53aSRobert Mustacchi 	oclo_accept_common(c, FD_CLOEXEC | FD_CLOFORK, true);
530*0250c53aSRobert Mustacchi }
531*0250c53aSRobert Mustacchi 
532*0250c53aSRobert Mustacchi /*
533*0250c53aSRobert Mustacchi  * Go through the process of sending ourselves a file descriptor.
534*0250c53aSRobert Mustacchi  */
535*0250c53aSRobert Mustacchi static void
oclo_rights_common(const clo_create_t * c,int targ_flags)536*0250c53aSRobert Mustacchi oclo_rights_common(const clo_create_t *c, int targ_flags)
537*0250c53aSRobert Mustacchi {
538*0250c53aSRobert Mustacchi 	int pair[2], type = SOCK_DGRAM, sflags = 0;
539*0250c53aSRobert Mustacchi 	int tosend = oclo_file(c), recvfd;
540*0250c53aSRobert Mustacchi 	uint32_t data = 0x7777;
541*0250c53aSRobert Mustacchi 	struct iovec iov;
542*0250c53aSRobert Mustacchi 	struct msghdr msg;
543*0250c53aSRobert Mustacchi 	struct cmsghdr *cm;
544*0250c53aSRobert Mustacchi 
545*0250c53aSRobert Mustacchi 	if ((c->clo_flags & FD_CLOEXEC) != 0)
546*0250c53aSRobert Mustacchi 		type |= SOCK_CLOEXEC;
547*0250c53aSRobert Mustacchi 	if ((c->clo_flags & FD_CLOFORK) != 0)
548*0250c53aSRobert Mustacchi 		type |= SOCK_CLOFORK;
549*0250c53aSRobert Mustacchi 
550*0250c53aSRobert Mustacchi 	if (socketpair(PF_UNIX, type, 0, pair) < 0) {
551*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to create socket "
552*0250c53aSRobert Mustacchi 		    "pair", c->clo_desc);
553*0250c53aSRobert Mustacchi 	}
554*0250c53aSRobert Mustacchi 
555*0250c53aSRobert Mustacchi 	oclo_record(c, tosend, c->clo_flags, "send fd");
556*0250c53aSRobert Mustacchi 	oclo_record(c, pair[0], c->clo_flags, "pair[0]");
557*0250c53aSRobert Mustacchi 	oclo_record(c, pair[1], c->clo_flags, "pair[1]");
558*0250c53aSRobert Mustacchi 
559*0250c53aSRobert Mustacchi 	iov.iov_base = (void *)&data;
560*0250c53aSRobert Mustacchi 	iov.iov_len = sizeof (data);
561*0250c53aSRobert Mustacchi 
562*0250c53aSRobert Mustacchi 	(void) memset(&msg, 0, sizeof (msg));
563*0250c53aSRobert Mustacchi 	msg.msg_iov = &iov;
564*0250c53aSRobert Mustacchi 	msg.msg_iovlen = 1;
565*0250c53aSRobert Mustacchi 	msg.msg_controllen = CMSG_SPACE(sizeof (int));
566*0250c53aSRobert Mustacchi 
567*0250c53aSRobert Mustacchi 	msg.msg_control = calloc(1, msg.msg_controllen);
568*0250c53aSRobert Mustacchi 	if (msg.msg_control == NULL) {
569*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to allocate %u "
570*0250c53aSRobert Mustacchi 		    "bytes for SCM_RIGHTS control message", c->clo_desc,
571*0250c53aSRobert Mustacchi 		    msg.msg_controllen);
572*0250c53aSRobert Mustacchi 	}
573*0250c53aSRobert Mustacchi 
574*0250c53aSRobert Mustacchi 	cm = CMSG_FIRSTHDR(&msg);
575*0250c53aSRobert Mustacchi 	cm->cmsg_len = CMSG_LEN(sizeof (int));
576*0250c53aSRobert Mustacchi 	cm->cmsg_level = SOL_SOCKET;
577*0250c53aSRobert Mustacchi 	cm->cmsg_type = SCM_RIGHTS;
578*0250c53aSRobert Mustacchi 	(void) memcpy(CMSG_DATA(cm), &tosend, sizeof (tosend));
579*0250c53aSRobert Mustacchi 
580*0250c53aSRobert Mustacchi 	if ((targ_flags & FD_CLOEXEC) != 0)
581*0250c53aSRobert Mustacchi 		sflags |= MSG_CMSG_CLOEXEC;
582*0250c53aSRobert Mustacchi 	if ((targ_flags & FD_CLOFORK) != 0)
583*0250c53aSRobert Mustacchi 		sflags |= MSG_CMSG_CLOFORK;
584*0250c53aSRobert Mustacchi 
585*0250c53aSRobert Mustacchi 	if (sendmsg(pair[0], &msg, 0) < 0) {
586*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to send fd",
587*0250c53aSRobert Mustacchi 		    c->clo_desc);
588*0250c53aSRobert Mustacchi 	}
589*0250c53aSRobert Mustacchi 
590*0250c53aSRobert Mustacchi 	data = 0;
591*0250c53aSRobert Mustacchi 	if (recvmsg(pair[1], &msg, sflags) < 0) {
592*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: %s: failed to get fd",
593*0250c53aSRobert Mustacchi 		    c->clo_desc);
594*0250c53aSRobert Mustacchi 	}
595*0250c53aSRobert Mustacchi 
596*0250c53aSRobert Mustacchi 	if (data != 0x7777) {
597*0250c53aSRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: %s: did not receive correct "
598*0250c53aSRobert Mustacchi 		    "data: expected 0x7777, found 0x%x", c->clo_desc, data);
599*0250c53aSRobert Mustacchi 	}
600*0250c53aSRobert Mustacchi 
601*0250c53aSRobert Mustacchi 	if (msg.msg_controllen < CMSG_SPACE(sizeof (int))) {
602*0250c53aSRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: %s: found insufficient "
603*0250c53aSRobert Mustacchi 		    "message control length: expected at least 0x%x, found "
604*0250c53aSRobert Mustacchi 		    "0x%x", c->clo_desc, CMSG_SPACE(sizeof (int)),
605*0250c53aSRobert Mustacchi 		    msg.msg_controllen);
606*0250c53aSRobert Mustacchi 	}
607*0250c53aSRobert Mustacchi 
608*0250c53aSRobert Mustacchi 	cm = CMSG_FIRSTHDR(&msg);
609*0250c53aSRobert Mustacchi 	if (cm->cmsg_level != SOL_SOCKET || cm->cmsg_type != SCM_RIGHTS) {
610*0250c53aSRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: %s: found surprising cmsg "
611*0250c53aSRobert Mustacchi 		    "0x%x/0x%x, expected 0x%x/0x%x", c->clo_desc,
612*0250c53aSRobert Mustacchi 		    cm->cmsg_level, cm->cmsg_type, SOL_SOCKET, SCM_RIGHTS);
613*0250c53aSRobert Mustacchi 	}
614*0250c53aSRobert Mustacchi 
615*0250c53aSRobert Mustacchi 	if (cm->cmsg_len != CMSG_LEN(sizeof (int))) {
616*0250c53aSRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: %s: found unexpected "
617*0250c53aSRobert Mustacchi 		    "SCM_RIGHTS length 0x%x: expected 0x%zx", c->clo_desc,
618*0250c53aSRobert Mustacchi 		    cm->cmsg_len, CMSG_LEN(sizeof (int)));
619*0250c53aSRobert Mustacchi 	}
620*0250c53aSRobert Mustacchi 
621*0250c53aSRobert Mustacchi 	(void) memcpy(&recvfd, CMSG_DATA(cm), sizeof (recvfd));
622*0250c53aSRobert Mustacchi 	oclo_record(c, recvfd, targ_flags, "SCM_RIGHTS");
623*0250c53aSRobert Mustacchi }
624*0250c53aSRobert Mustacchi 
625*0250c53aSRobert Mustacchi static void
oclo_rights_none(const clo_create_t * c)626*0250c53aSRobert Mustacchi oclo_rights_none(const clo_create_t *c)
627*0250c53aSRobert Mustacchi {
628*0250c53aSRobert Mustacchi 	oclo_rights_common(c, 0);
629*0250c53aSRobert Mustacchi }
630*0250c53aSRobert Mustacchi 
631*0250c53aSRobert Mustacchi static void
oclo_rights_exec(const clo_create_t * c)632*0250c53aSRobert Mustacchi oclo_rights_exec(const clo_create_t *c)
633*0250c53aSRobert Mustacchi {
634*0250c53aSRobert Mustacchi 	oclo_rights_common(c, FD_CLOEXEC);
635*0250c53aSRobert Mustacchi }
636*0250c53aSRobert Mustacchi 
637*0250c53aSRobert Mustacchi static void
oclo_rights_fork(const clo_create_t * c)638*0250c53aSRobert Mustacchi oclo_rights_fork(const clo_create_t *c)
639*0250c53aSRobert Mustacchi {
640*0250c53aSRobert Mustacchi 	oclo_rights_common(c, FD_CLOFORK);
641*0250c53aSRobert Mustacchi }
642*0250c53aSRobert Mustacchi 
643*0250c53aSRobert Mustacchi static void
oclo_rights_both(const clo_create_t * c)644*0250c53aSRobert Mustacchi oclo_rights_both(const clo_create_t *c)
645*0250c53aSRobert Mustacchi {
646*0250c53aSRobert Mustacchi 	oclo_rights_common(c, FD_CLOEXEC | FD_CLOFORK);
647*0250c53aSRobert Mustacchi }
648*0250c53aSRobert Mustacchi 
649*0250c53aSRobert Mustacchi static const clo_create_t oclo_create[] = { {
650*0250c53aSRobert Mustacchi 	.clo_desc = "open(2), no flags",
651*0250c53aSRobert Mustacchi 	.clo_flags = 0,
652*0250c53aSRobert Mustacchi 	.clo_func = oclo_open
653*0250c53aSRobert Mustacchi }, {
654*0250c53aSRobert Mustacchi 	.clo_desc = "open(2), O_CLOEXEC",
655*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
656*0250c53aSRobert Mustacchi 	.clo_func = oclo_open
657*0250c53aSRobert Mustacchi }, {
658*0250c53aSRobert Mustacchi 	.clo_desc = "open(2), O_CLOFORK",
659*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
660*0250c53aSRobert Mustacchi 	.clo_func = oclo_open
661*0250c53aSRobert Mustacchi }, {
662*0250c53aSRobert Mustacchi 	.clo_desc = "open(2), O_CLOEXEC|O_CLOFORK",
663*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
664*0250c53aSRobert Mustacchi 	.clo_func = oclo_open
665*0250c53aSRobert Mustacchi }, {
666*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) no flags->no flags",
667*0250c53aSRobert Mustacchi 	.clo_flags = 0,
668*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_none
669*0250c53aSRobert Mustacchi }, {
670*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOFORK|O_CLOEXEC->no flags",
671*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOFORK | O_CLOEXEC,
672*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_none
673*0250c53aSRobert Mustacchi }, {
674*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOEXEC->no flags",
675*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOEXEC,
676*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_none
677*0250c53aSRobert Mustacchi }, {
678*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOFORK->no flags",
679*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOFORK,
680*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_none
681*0250c53aSRobert Mustacchi }, {
682*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) no flags->O_CLOEXEC",
683*0250c53aSRobert Mustacchi 	.clo_flags = 0,
684*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_exec
685*0250c53aSRobert Mustacchi }, {
686*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOFORK|O_CLOEXEC->O_CLOEXEC",
687*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOFORK | O_CLOEXEC,
688*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_exec
689*0250c53aSRobert Mustacchi }, {
690*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOEXEC->O_CLOEXEC",
691*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOEXEC,
692*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_exec
693*0250c53aSRobert Mustacchi }, {
694*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOFORK->O_CLOEXEC",
695*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOFORK,
696*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_exec
697*0250c53aSRobert Mustacchi }, {
698*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) no flags->O_CLOFORK",
699*0250c53aSRobert Mustacchi 	.clo_flags = 0,
700*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_fork
701*0250c53aSRobert Mustacchi }, {
702*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOFORK|O_CLOEXEC->O_CLOFORK",
703*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOFORK | O_CLOEXEC,
704*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_fork
705*0250c53aSRobert Mustacchi }, {
706*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOEXEC->O_CLOFORK",
707*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOEXEC,
708*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_fork
709*0250c53aSRobert Mustacchi }, {
710*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOFORK->O_CLOFORK",
711*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOFORK,
712*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_fork
713*0250c53aSRobert Mustacchi }, {
714*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) no flags->O_CLOFORK|O_CLOEXEC",
715*0250c53aSRobert Mustacchi 	.clo_flags = 0,
716*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_both
717*0250c53aSRobert Mustacchi }, {
718*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOFORK|O_CLOEXEC->O_CLOFORK|O_CLOEXEC",
719*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOFORK | O_CLOEXEC,
720*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_both
721*0250c53aSRobert Mustacchi }, {
722*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOEXEC->O_CLOFORK|O_CLOEXEC",
723*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOEXEC,
724*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_both
725*0250c53aSRobert Mustacchi }, {
726*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_SETFD) O_CLOFORK->O_CLOFORK|O_CLOEXEC",
727*0250c53aSRobert Mustacchi 	.clo_flags = O_CLOFORK,
728*0250c53aSRobert Mustacchi 	.clo_func = oclo_setfd_both
729*0250c53aSRobert Mustacchi }, {
730*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD) none->none",
731*0250c53aSRobert Mustacchi 	.clo_flags = 0,
732*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd
733*0250c53aSRobert Mustacchi }, {
734*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD) FD_CLOEXEC->none",
735*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
736*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd
737*0250c53aSRobert Mustacchi }, {
738*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD) FD_CLOFORK->none",
739*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
740*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd
741*0250c53aSRobert Mustacchi }, {
742*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD) FD_CLOEXEC|FD_CLOFORK->none",
743*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
744*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd
745*0250c53aSRobert Mustacchi }, {
746*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD_CLOFORK) none",
747*0250c53aSRobert Mustacchi 	.clo_flags = 0,
748*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd_fork
749*0250c53aSRobert Mustacchi }, {
750*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD_CLOFORK) FD_CLOEXEC",
751*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
752*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd_fork
753*0250c53aSRobert Mustacchi }, {
754*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD_CLOFORK) FD_CLOFORK",
755*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
756*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd_fork
757*0250c53aSRobert Mustacchi }, {
758*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD_CLOFORK) FD_CLOEXEC|FD_CLOFORK",
759*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
760*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd_fork
761*0250c53aSRobert Mustacchi }, {
762*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD_CLOEXEC) none",
763*0250c53aSRobert Mustacchi 	.clo_flags = 0,
764*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd_exec
765*0250c53aSRobert Mustacchi }, {
766*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD_CLOEXEC) FD_CLOEXEC",
767*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
768*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd_exec
769*0250c53aSRobert Mustacchi }, {
770*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD_CLOEXEC) FD_CLOFORK",
771*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
772*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd_exec
773*0250c53aSRobert Mustacchi }, {
774*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUPFD_CLOEXEC) FD_CLOEXEC|FD_CLOFORK",
775*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
776*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdupfd_exec
777*0250c53aSRobert Mustacchi }, {
778*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD) none->none",
779*0250c53aSRobert Mustacchi 	.clo_flags = 0,
780*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd
781*0250c53aSRobert Mustacchi }, {
782*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD) FD_CLOEXEC->none",
783*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
784*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd
785*0250c53aSRobert Mustacchi }, {
786*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD) FD_CLOFORK->none",
787*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
788*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd
789*0250c53aSRobert Mustacchi }, {
790*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD) FD_CLOEXEC|FD_CLOFORK->none",
791*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
792*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd
793*0250c53aSRobert Mustacchi }, {
794*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD_CLOFORK) none",
795*0250c53aSRobert Mustacchi 	.clo_flags = 0,
796*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd_fork
797*0250c53aSRobert Mustacchi }, {
798*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD_CLOFORK) FD_CLOEXEC",
799*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
800*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd_fork
801*0250c53aSRobert Mustacchi }, {
802*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD_CLOFORK) FD_CLOFORK",
803*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
804*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd_fork
805*0250c53aSRobert Mustacchi }, {
806*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD_CLOFORK) FD_CLOEXEC|FD_CLOFORK",
807*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
808*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd_fork
809*0250c53aSRobert Mustacchi }, {
810*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD_CLOEXEC) none",
811*0250c53aSRobert Mustacchi 	.clo_flags = 0,
812*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd_exec
813*0250c53aSRobert Mustacchi }, {
814*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD_CLOEXEC) FD_CLOEXEC",
815*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
816*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd_exec
817*0250c53aSRobert Mustacchi }, {
818*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD_CLOEXEC) FD_CLOFORK",
819*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
820*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd_exec
821*0250c53aSRobert Mustacchi }, {
822*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP2FD_CLOEXEC) FD_CLOEXEC|FD_CLOFORK",
823*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
824*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup2fd_exec
825*0250c53aSRobert Mustacchi }, {
826*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) none->none",
827*0250c53aSRobert Mustacchi 	.clo_flags = 0,
828*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_none
829*0250c53aSRobert Mustacchi }, {
830*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOEXEC->none",
831*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
832*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_none
833*0250c53aSRobert Mustacchi }, {
834*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOFORK->none",
835*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
836*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_none
837*0250c53aSRobert Mustacchi }, {
838*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOEXEC|FD_CLOFORK->none",
839*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
840*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_none
841*0250c53aSRobert Mustacchi }, {
842*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) none->FD_CLOEXEC",
843*0250c53aSRobert Mustacchi 	.clo_flags = 0,
844*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_exec
845*0250c53aSRobert Mustacchi }, {
846*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOEXEC->FD_CLOEXEC",
847*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
848*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_exec
849*0250c53aSRobert Mustacchi }, {
850*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOFORK->FD_CLOEXEC",
851*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
852*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_exec
853*0250c53aSRobert Mustacchi }, {
854*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOEXEC|FD_CLOFORK->FD_CLOEXEC",
855*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
856*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_exec
857*0250c53aSRobert Mustacchi }, {
858*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) none->FD_CLOFORK|FD_CLOEXEC",
859*0250c53aSRobert Mustacchi 	.clo_flags = 0,
860*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_both
861*0250c53aSRobert Mustacchi }, {
862*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOEXEC->FD_CLOFORK|FD_CLOEXEC",
863*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
864*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_both
865*0250c53aSRobert Mustacchi }, {
866*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOFORK->FD_CLOFORK|FD_CLOEXEC",
867*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
868*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_both
869*0250c53aSRobert Mustacchi }, {
870*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOEXEC|FD_CLOFORK->"
871*0250c53aSRobert Mustacchi 	    "FD_CLOFORK|FD_CLOEXEC",
872*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
873*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_both
874*0250c53aSRobert Mustacchi }, {
875*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) none->FD_CLOFORK",
876*0250c53aSRobert Mustacchi 	.clo_flags = 0,
877*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_fork
878*0250c53aSRobert Mustacchi }, {
879*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOEXEC->FD_CLOFORK",
880*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
881*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_fork
882*0250c53aSRobert Mustacchi }, {
883*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOFORK->FD_CLOFORK",
884*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
885*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_fork
886*0250c53aSRobert Mustacchi }, {
887*0250c53aSRobert Mustacchi 	.clo_desc = "fcntl(F_DUP3FD) FD_CLOEXEC|FD_CLOFORK->FD_CLOFORK",
888*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
889*0250c53aSRobert Mustacchi 	.clo_func = oclo_fdup3fd_fork
890*0250c53aSRobert Mustacchi }, {
891*0250c53aSRobert Mustacchi 	.clo_desc = "dup2() none->none",
892*0250c53aSRobert Mustacchi 	.clo_flags = 0,
893*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup2
894*0250c53aSRobert Mustacchi }, {
895*0250c53aSRobert Mustacchi 	.clo_desc = "dup2() FD_CLOEXEC->none",
896*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
897*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup2
898*0250c53aSRobert Mustacchi }, {
899*0250c53aSRobert Mustacchi 	.clo_desc = "dup2() FD_CLOFORK->none",
900*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
901*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup2
902*0250c53aSRobert Mustacchi }, {
903*0250c53aSRobert Mustacchi 	.clo_desc = "dup2() FD_CLOEXEC|FD_CLOFORK->none",
904*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
905*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup2
906*0250c53aSRobert Mustacchi }, {
907*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() none->none",
908*0250c53aSRobert Mustacchi 	.clo_flags = 0,
909*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_none
910*0250c53aSRobert Mustacchi }, {
911*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOEXEC->none",
912*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
913*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_none
914*0250c53aSRobert Mustacchi }, {
915*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOFORK->none",
916*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
917*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_none
918*0250c53aSRobert Mustacchi }, {
919*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOEXEC|FD_CLOFORK->none",
920*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
921*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_none
922*0250c53aSRobert Mustacchi }, {
923*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() none->FD_CLOEXEC",
924*0250c53aSRobert Mustacchi 	.clo_flags = 0,
925*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_exec
926*0250c53aSRobert Mustacchi }, {
927*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOEXEC->FD_CLOEXEC",
928*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
929*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_exec
930*0250c53aSRobert Mustacchi }, {
931*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOFORK->FD_CLOEXEC",
932*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
933*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_exec
934*0250c53aSRobert Mustacchi }, {
935*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOEXEC|FD_CLOFORK->FD_CLOEXEC",
936*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
937*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_exec
938*0250c53aSRobert Mustacchi }, {
939*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() none->FD_CLOFORK|FD_CLOEXEC",
940*0250c53aSRobert Mustacchi 	.clo_flags = 0,
941*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_both
942*0250c53aSRobert Mustacchi }, {
943*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOEXEC->FD_CLOFORK|FD_CLOEXEC",
944*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
945*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_both
946*0250c53aSRobert Mustacchi }, {
947*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOFORK->FD_CLOFORK|FD_CLOEXEC",
948*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
949*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_both
950*0250c53aSRobert Mustacchi }, {
951*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOEXEC|FD_CLOFORK->FD_CLOFORK|FD_CLOEXEC",
952*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
953*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_both
954*0250c53aSRobert Mustacchi }, {
955*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() none->FD_CLOFORK",
956*0250c53aSRobert Mustacchi 	.clo_flags = 0,
957*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_fork
958*0250c53aSRobert Mustacchi }, {
959*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOEXEC->FD_CLOFORK",
960*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
961*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_fork
962*0250c53aSRobert Mustacchi }, {
963*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOFORK->FD_CLOFORK",
964*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
965*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_fork
966*0250c53aSRobert Mustacchi }, {
967*0250c53aSRobert Mustacchi 	.clo_desc = "dup3() FD_CLOEXEC|FD_CLOFORK->FD_CLOFORK",
968*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
969*0250c53aSRobert Mustacchi 	.clo_func = oclo_dup3_fork
970*0250c53aSRobert Mustacchi }, {
971*0250c53aSRobert Mustacchi 	.clo_desc = "pipe(2), no flags",
972*0250c53aSRobert Mustacchi 	.clo_flags = 0,
973*0250c53aSRobert Mustacchi 	.clo_func = oclo_pipe
974*0250c53aSRobert Mustacchi }, {
975*0250c53aSRobert Mustacchi 	.clo_desc = "pipe(2), O_CLOEXEC",
976*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
977*0250c53aSRobert Mustacchi 	.clo_func = oclo_pipe
978*0250c53aSRobert Mustacchi }, {
979*0250c53aSRobert Mustacchi 	.clo_desc = "pipe(2), O_CLOFORK",
980*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
981*0250c53aSRobert Mustacchi 	.clo_func = oclo_pipe
982*0250c53aSRobert Mustacchi }, {
983*0250c53aSRobert Mustacchi 	.clo_desc = "pipe(2), O_CLOEXEC|O_CLOFORK",
984*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
985*0250c53aSRobert Mustacchi 	.clo_func = oclo_pipe
986*0250c53aSRobert Mustacchi }, {
987*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), no flags",
988*0250c53aSRobert Mustacchi 	.clo_flags = 0,
989*0250c53aSRobert Mustacchi 	.clo_func = oclo_socket
990*0250c53aSRobert Mustacchi }, {
991*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC",
992*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
993*0250c53aSRobert Mustacchi 	.clo_func = oclo_socket
994*0250c53aSRobert Mustacchi }, {
995*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOFORK",
996*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
997*0250c53aSRobert Mustacchi 	.clo_func = oclo_socket
998*0250c53aSRobert Mustacchi }, {
999*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC|O_CLOFORK",
1000*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
1001*0250c53aSRobert Mustacchi 	.clo_func = oclo_socket
1002*0250c53aSRobert Mustacchi }, {
1003*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), no flags->accept() none",
1004*0250c53aSRobert Mustacchi 	.clo_flags = 0,
1005*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept
1006*0250c53aSRobert Mustacchi }, {
1007*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC->accept() none",
1008*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
1009*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept
1010*0250c53aSRobert Mustacchi }, {
1011*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOFORK->accept() none",
1012*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
1013*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept
1014*0250c53aSRobert Mustacchi }, {
1015*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC|O_CLOFORK->accept() none",
1016*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
1017*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept
1018*0250c53aSRobert Mustacchi }, {
1019*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), no flags->accept4() none",
1020*0250c53aSRobert Mustacchi 	.clo_flags = 0,
1021*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_none
1022*0250c53aSRobert Mustacchi }, {
1023*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC->accept4() none",
1024*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
1025*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_none
1026*0250c53aSRobert Mustacchi }, {
1027*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOFORK->accept4() none",
1028*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
1029*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_none
1030*0250c53aSRobert Mustacchi }, {
1031*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC|O_CLOFORK->accept4() none",
1032*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
1033*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_none
1034*0250c53aSRobert Mustacchi }, {
1035*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), no flags->accept4() SOCK_CLOFORK|SOCK_CLOEXEC",
1036*0250c53aSRobert Mustacchi 	.clo_flags = 0,
1037*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_both
1038*0250c53aSRobert Mustacchi }, {
1039*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC->accept4() SOCK_CLOFORK|SOCK_CLOEXEC",
1040*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
1041*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_both
1042*0250c53aSRobert Mustacchi }, {
1043*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOFORK->accept4() SOCK_CLOFORK|SOCK_CLOEXEC",
1044*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
1045*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_both
1046*0250c53aSRobert Mustacchi }, {
1047*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC|O_CLOFORK->accept4() "
1048*0250c53aSRobert Mustacchi 	    "SOCK_CLOFORK|SOCK_CLOEXEC",
1049*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
1050*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_both
1051*0250c53aSRobert Mustacchi }, {
1052*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), no flags->accept4() SOCK_CLOFORK",
1053*0250c53aSRobert Mustacchi 	.clo_flags = 0,
1054*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_fork
1055*0250c53aSRobert Mustacchi }, {
1056*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC->accept4() SOCK_CLOFORK",
1057*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
1058*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_fork
1059*0250c53aSRobert Mustacchi }, {
1060*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOFORK->accept4() SOCK_CLOFORK",
1061*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
1062*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_fork
1063*0250c53aSRobert Mustacchi }, {
1064*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC|O_CLOFORK->accept4() SOCK_CLOFORK",
1065*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
1066*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_fork
1067*0250c53aSRobert Mustacchi }, {
1068*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), no flags->accept4() SOCK_CLOEXEC",
1069*0250c53aSRobert Mustacchi 	.clo_flags = 0,
1070*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_exec
1071*0250c53aSRobert Mustacchi }, {
1072*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC->accept4() SOCK_CLOEXEC",
1073*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
1074*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_exec
1075*0250c53aSRobert Mustacchi }, {
1076*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOFORK->accept4() SOCK_CLOEXEC",
1077*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
1078*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_exec
1079*0250c53aSRobert Mustacchi }, {
1080*0250c53aSRobert Mustacchi 	.clo_desc = "socket(2), O_CLOEXEC|O_CLOFORK->accept4() SOCK_CLOEXEC",
1081*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
1082*0250c53aSRobert Mustacchi 	.clo_func = oclo_accept4_exec
1083*0250c53aSRobert Mustacchi }, {
1084*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS none->none",
1085*0250c53aSRobert Mustacchi 	.clo_flags = 0,
1086*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_none
1087*0250c53aSRobert Mustacchi }, {
1088*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOFORK->none",
1089*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
1090*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_none
1091*0250c53aSRobert Mustacchi }, {
1092*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOEXEC->none",
1093*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
1094*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_none
1095*0250c53aSRobert Mustacchi }, {
1096*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOEXEC|FD_CLOFORK->none",
1097*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
1098*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_none
1099*0250c53aSRobert Mustacchi }, {
1100*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS none->MSG_CMSG_CLOEXEC",
1101*0250c53aSRobert Mustacchi 	.clo_flags = 0,
1102*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_exec
1103*0250c53aSRobert Mustacchi }, {
1104*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOFORK->MSG_CMSG_CLOEXEC",
1105*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
1106*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_exec
1107*0250c53aSRobert Mustacchi }, {
1108*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOEXEC->MSG_CMSG_CLOEXEC",
1109*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
1110*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_exec
1111*0250c53aSRobert Mustacchi }, {
1112*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOEXEC|FD_CLOFORK->MSG_CMSG_CLOEXEC",
1113*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
1114*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_exec
1115*0250c53aSRobert Mustacchi }, {
1116*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS MSG_CMSG_CLOFORK->nMSG_CMSG_CLOFORK",
1117*0250c53aSRobert Mustacchi 	.clo_flags = 0,
1118*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_fork
1119*0250c53aSRobert Mustacchi }, {
1120*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOFORK->MSG_CMSG_CLOFORK",
1121*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
1122*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_fork
1123*0250c53aSRobert Mustacchi }, {
1124*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOEXEC->MSG_CMSG_CLOFORK",
1125*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
1126*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_fork
1127*0250c53aSRobert Mustacchi }, {
1128*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOEXEC|FD_CLOFORK->MSG_CMSG_CLOFORK",
1129*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
1130*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_fork
1131*0250c53aSRobert Mustacchi }, {
1132*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS none->MSG_CMSG_CLOEXEC|MSG_CMSG_CLOFORK",
1133*0250c53aSRobert Mustacchi 	.clo_flags = 0,
1134*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_both
1135*0250c53aSRobert Mustacchi }, {
1136*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOFORK->MSG_CMSG_CLOEXEC|MSG_CMSG_CLOFORK",
1137*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOFORK,
1138*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_both
1139*0250c53aSRobert Mustacchi }, {
1140*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOEXEC->MSG_CMSG_CLOEXEC|MSG_CMSG_CLOFORK",
1141*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC,
1142*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_both
1143*0250c53aSRobert Mustacchi }, {
1144*0250c53aSRobert Mustacchi 	.clo_desc = "SCM_RIGHTS FD_CLOEXEC|FD_CLOFORK->"
1145*0250c53aSRobert Mustacchi 	    "MSG_CMSG_CLOEXEC|MSG_CMSG_CLOFORK",
1146*0250c53aSRobert Mustacchi 	.clo_flags = FD_CLOEXEC | FD_CLOFORK,
1147*0250c53aSRobert Mustacchi 	.clo_func = oclo_rights_both
1148*0250c53aSRobert Mustacchi } };
1149*0250c53aSRobert Mustacchi 
1150*0250c53aSRobert Mustacchi static bool
oclo_verify_fork(void)1151*0250c53aSRobert Mustacchi oclo_verify_fork(void)
1152*0250c53aSRobert Mustacchi {
1153*0250c53aSRobert Mustacchi 	bool ret = true;
1154*0250c53aSRobert Mustacchi 
1155*0250c53aSRobert Mustacchi 	for (size_t i = 0; i < oclo_rtdata_next; i++) {
1156*0250c53aSRobert Mustacchi 		if (!oclo_flags_match(&oclo_rtdata[i], true)) {
1157*0250c53aSRobert Mustacchi 			ret = false;
1158*0250c53aSRobert Mustacchi 		}
1159*0250c53aSRobert Mustacchi 	}
1160*0250c53aSRobert Mustacchi 
1161*0250c53aSRobert Mustacchi 	return (ret);
1162*0250c53aSRobert Mustacchi }
1163*0250c53aSRobert Mustacchi 
1164*0250c53aSRobert Mustacchi /*
1165*0250c53aSRobert Mustacchi  * Here we proceed to re-open any fd that was closed due to O_CLOFORK again to
1166*0250c53aSRobert Mustacchi  * make sure it makes it to our child verifier. This also serves as a test to
1167*0250c53aSRobert Mustacchi  * make sure that our opening of the lowest fd is correct. While this doesn't
1168*0250c53aSRobert Mustacchi  * actually use the same method as was done previously, While it might be ideal
1169*0250c53aSRobert Mustacchi  * to use the method as originally, this should get us most of the way there.
1170*0250c53aSRobert Mustacchi  */
1171*0250c53aSRobert Mustacchi static void
oclo_child_reopen(void)1172*0250c53aSRobert Mustacchi oclo_child_reopen(void)
1173*0250c53aSRobert Mustacchi {
1174*0250c53aSRobert Mustacchi 	for (size_t i = 0; i < oclo_rtdata_next; i++) {
1175*0250c53aSRobert Mustacchi 		int fd;
1176*0250c53aSRobert Mustacchi 		int flags = O_RDWR | O_CLOFORK;
1177*0250c53aSRobert Mustacchi 
1178*0250c53aSRobert Mustacchi 		if ((oclo_rtdata[i].crt_flags & FD_CLOFORK) == 0)
1179*0250c53aSRobert Mustacchi 			continue;
1180*0250c53aSRobert Mustacchi 
1181*0250c53aSRobert Mustacchi 		if ((oclo_rtdata[i].crt_flags & FD_CLOEXEC) != 0)
1182*0250c53aSRobert Mustacchi 			flags |= O_CLOEXEC;
1183*0250c53aSRobert Mustacchi 
1184*0250c53aSRobert Mustacchi 		fd = open("/dev/zero", flags);
1185*0250c53aSRobert Mustacchi 		if (fd < 0) {
1186*0250c53aSRobert Mustacchi 			err(EXIT_FAILURE, "TEST FAILED: failed to re-open fd "
1187*0250c53aSRobert Mustacchi 			    "%d with flags %d", oclo_rtdata[i].crt_fd, flags);
1188*0250c53aSRobert Mustacchi 		}
1189*0250c53aSRobert Mustacchi 
1190*0250c53aSRobert Mustacchi 		if (fd != oclo_rtdata[i].crt_fd) {
1191*0250c53aSRobert Mustacchi 			errx(EXIT_FAILURE, "TEST FAILED: re-opening fd %d "
1192*0250c53aSRobert Mustacchi 			    "returned fd %d: test design issue or lowest fd "
1193*0250c53aSRobert Mustacchi 			    "algorithm is broken", oclo_rtdata[i].crt_fd, fd);
1194*0250c53aSRobert Mustacchi 		}
1195*0250c53aSRobert Mustacchi 	}
1196*0250c53aSRobert Mustacchi 
1197*0250c53aSRobert Mustacchi 	(void) printf("TEST PASSED: successfully reopened fds post-fork");
1198*0250c53aSRobert Mustacchi }
1199*0250c53aSRobert Mustacchi 
1200*0250c53aSRobert Mustacchi /*
1201*0250c53aSRobert Mustacchi  * Look for the verification program in the same directory that this program is
1202*0250c53aSRobert Mustacchi  * found in. Note, that isn't the same thing as the current working directory.
1203*0250c53aSRobert Mustacchi  */
1204*0250c53aSRobert Mustacchi static void
oclo_exec(void)1205*0250c53aSRobert Mustacchi oclo_exec(void)
1206*0250c53aSRobert Mustacchi {
1207*0250c53aSRobert Mustacchi 	ssize_t ret;
1208*0250c53aSRobert Mustacchi 	char dir[PATH_MAX], file[PATH_MAX];
1209*0250c53aSRobert Mustacchi 	char **argv;
1210*0250c53aSRobert Mustacchi 
1211*0250c53aSRobert Mustacchi 	ret = readlink("/proc/self/path/a.out", dir, sizeof (dir));
1212*0250c53aSRobert Mustacchi 	if (ret < 0) {
1213*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: failed to read our a.out path "
1214*0250c53aSRobert Mustacchi 		    "from /proc");
1215*0250c53aSRobert Mustacchi 	} else if (ret == 0) {
1216*0250c53aSRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: reading /proc/self/path/a.out "
1217*0250c53aSRobert Mustacchi 		    "returned 0 bytes");
1218*0250c53aSRobert Mustacchi 	} else if (ret == sizeof (dir)) {
1219*0250c53aSRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: Using /proc/self/path/a.out "
1220*0250c53aSRobert Mustacchi 		    "requires truncation");
1221*0250c53aSRobert Mustacchi 	}
1222*0250c53aSRobert Mustacchi 
1223*0250c53aSRobert Mustacchi 	if (snprintf(file, sizeof (file), "%s/%s", dirname(dir), OCLO_VERIFY) >=
1224*0250c53aSRobert Mustacchi 	    sizeof (file)) {
1225*0250c53aSRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: cannot assemble exec path "
1226*0250c53aSRobert Mustacchi 		    "name: internal buffer overflow");
1227*0250c53aSRobert Mustacchi 	}
1228*0250c53aSRobert Mustacchi 
1229*0250c53aSRobert Mustacchi 	/* We need an extra for both the NULL terminator and the program name */
1230*0250c53aSRobert Mustacchi 	argv = calloc(oclo_rtdata_next + 2, sizeof (char *));
1231*0250c53aSRobert Mustacchi 	if (argv == NULL) {
1232*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: failed to allocate exec "
1233*0250c53aSRobert Mustacchi 		    "argument array");
1234*0250c53aSRobert Mustacchi 	}
1235*0250c53aSRobert Mustacchi 
1236*0250c53aSRobert Mustacchi 	argv[0] = file;
1237*0250c53aSRobert Mustacchi 	for (size_t i = 0; i < oclo_rtdata_next; i++) {
1238*0250c53aSRobert Mustacchi 		if (asprintf(&argv[i + 1], "0x%x", oclo_rtdata[i].crt_flags) ==
1239*0250c53aSRobert Mustacchi 		    -1) {
1240*0250c53aSRobert Mustacchi 			err(EXIT_FAILURE, "TEST FAILED: failed to assemble "
1241*0250c53aSRobert Mustacchi 			    "exec argument %zu", i + 1);
1242*0250c53aSRobert Mustacchi 		}
1243*0250c53aSRobert Mustacchi 	}
1244*0250c53aSRobert Mustacchi 
1245*0250c53aSRobert Mustacchi 	(void) execv(file, argv);
1246*0250c53aSRobert Mustacchi 	warn("TEST FAILED: failed to exec verifier %s", file);
1247*0250c53aSRobert Mustacchi }
1248*0250c53aSRobert Mustacchi 
1249*0250c53aSRobert Mustacchi int
main(void)1250*0250c53aSRobert Mustacchi main(void)
1251*0250c53aSRobert Mustacchi {
1252*0250c53aSRobert Mustacchi 	int ret = EXIT_SUCCESS;
1253*0250c53aSRobert Mustacchi 	siginfo_t cret;
1254*0250c53aSRobert Mustacchi 
1255*0250c53aSRobert Mustacchi 	/*
1256*0250c53aSRobert Mustacchi 	 * Before we do anything else close all FDs that aren't standard. We
1257*0250c53aSRobert Mustacchi 	 * don't want anything the test suite environment may have left behind.
1258*0250c53aSRobert Mustacchi 	 */
1259*0250c53aSRobert Mustacchi 	(void) closefrom(STDERR_FILENO + 1);
1260*0250c53aSRobert Mustacchi 
1261*0250c53aSRobert Mustacchi 	/*
1262*0250c53aSRobert Mustacchi 	 * Treat failure during this set up phase as a hard failure. There's no
1263*0250c53aSRobert Mustacchi 	 * reason to continue if we can't successfully create the FDs we expect.
1264*0250c53aSRobert Mustacchi 	 */
1265*0250c53aSRobert Mustacchi 	for (size_t i = 0; i < ARRAY_SIZE(oclo_create); i++) {
1266*0250c53aSRobert Mustacchi 		oclo_create[i].clo_func(&oclo_create[i]);
1267*0250c53aSRobert Mustacchi 	}
1268*0250c53aSRobert Mustacchi 
1269*0250c53aSRobert Mustacchi 	pid_t child = forkx(FORK_NOSIGCHLD | FORK_WAITPID);
1270*0250c53aSRobert Mustacchi 	if (child == 0) {
1271*0250c53aSRobert Mustacchi 		if (!oclo_verify_fork()) {
1272*0250c53aSRobert Mustacchi 			ret = EXIT_FAILURE;
1273*0250c53aSRobert Mustacchi 		}
1274*0250c53aSRobert Mustacchi 
1275*0250c53aSRobert Mustacchi 		oclo_child_reopen();
1276*0250c53aSRobert Mustacchi 
1277*0250c53aSRobert Mustacchi 		oclo_exec();
1278*0250c53aSRobert Mustacchi 		ret = EXIT_FAILURE;
1279*0250c53aSRobert Mustacchi 		_exit(ret);
1280*0250c53aSRobert Mustacchi 	}
1281*0250c53aSRobert Mustacchi 
1282*0250c53aSRobert Mustacchi 	if (waitid(P_PID, child, &cret, WEXITED) < 0) {
1283*0250c53aSRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: internal test failure waiting "
1284*0250c53aSRobert Mustacchi 		    "for forked child to report");
1285*0250c53aSRobert Mustacchi 	}
1286*0250c53aSRobert Mustacchi 
1287*0250c53aSRobert Mustacchi 	if (cret.si_code != CLD_EXITED) {
1288*0250c53aSRobert Mustacchi 		warnx("TEST FAILED: child process did not successfully exit: "
1289*0250c53aSRobert Mustacchi 		    "found si_code: %d", cret.si_code);
1290*0250c53aSRobert Mustacchi 		ret = EXIT_FAILURE;
1291*0250c53aSRobert Mustacchi 	} else if (cret.si_status != 0) {
1292*0250c53aSRobert Mustacchi 		warnx("TEST FAILED: child process did not exit with code 0: "
1293*0250c53aSRobert Mustacchi 		    "found %d", cret.si_status);
1294*0250c53aSRobert Mustacchi 		ret = EXIT_FAILURE;
1295*0250c53aSRobert Mustacchi 	}
1296*0250c53aSRobert Mustacchi 
1297*0250c53aSRobert Mustacchi 	if (ret == EXIT_SUCCESS) {
1298*0250c53aSRobert Mustacchi 		(void) printf("All tests passed successfully\n");
1299*0250c53aSRobert Mustacchi 	}
1300*0250c53aSRobert Mustacchi 
1301*0250c53aSRobert Mustacchi 	return (ret);
1302*0250c53aSRobert Mustacchi }
1303