xref: /freebsd/tools/regression/capsicum/syscalls/cap_ioctls_limit.c (revision de503941768ff3ac147dfaf2b48bae4637777f53)
1*de503941SPawel Jakub Dawidek /*-
2*de503941SPawel Jakub Dawidek  * Copyright (c) 2012 The FreeBSD Foundation
3*de503941SPawel Jakub Dawidek  * All rights reserved.
4*de503941SPawel Jakub Dawidek  *
5*de503941SPawel Jakub Dawidek  * This software was developed by Pawel Jakub Dawidek under sponsorship from
6*de503941SPawel Jakub Dawidek  * the FreeBSD Foundation.
7*de503941SPawel Jakub Dawidek  *
8*de503941SPawel Jakub Dawidek  * Redistribution and use in source and binary forms, with or without
9*de503941SPawel Jakub Dawidek  * modification, are permitted provided that the following conditions
10*de503941SPawel Jakub Dawidek  * are met:
11*de503941SPawel Jakub Dawidek  * 1. Redistributions of source code must retain the above copyright
12*de503941SPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer.
13*de503941SPawel Jakub Dawidek  * 2. Redistributions in binary form must reproduce the above copyright
14*de503941SPawel Jakub Dawidek  *    notice, this list of conditions and the following disclaimer in the
15*de503941SPawel Jakub Dawidek  *    documentation and/or other materials provided with the distribution.
16*de503941SPawel Jakub Dawidek  *
17*de503941SPawel Jakub Dawidek  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18*de503941SPawel Jakub Dawidek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*de503941SPawel Jakub Dawidek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*de503941SPawel Jakub Dawidek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21*de503941SPawel Jakub Dawidek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*de503941SPawel Jakub Dawidek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*de503941SPawel Jakub Dawidek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*de503941SPawel Jakub Dawidek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*de503941SPawel Jakub Dawidek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*de503941SPawel Jakub Dawidek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*de503941SPawel Jakub Dawidek  * SUCH DAMAGE.
28*de503941SPawel Jakub Dawidek  */
29*de503941SPawel Jakub Dawidek 
30*de503941SPawel Jakub Dawidek #include <sys/cdefs.h>
31*de503941SPawel Jakub Dawidek __FBSDID("$FreeBSD$");
32*de503941SPawel Jakub Dawidek 
33*de503941SPawel Jakub Dawidek #include <sys/param.h>
34*de503941SPawel Jakub Dawidek #include <sys/capability.h>
35*de503941SPawel Jakub Dawidek #include <sys/ioctl.h>
36*de503941SPawel Jakub Dawidek #include <sys/procdesc.h>
37*de503941SPawel Jakub Dawidek #include <sys/socket.h>
38*de503941SPawel Jakub Dawidek #include <sys/wait.h>
39*de503941SPawel Jakub Dawidek 
40*de503941SPawel Jakub Dawidek #include <err.h>
41*de503941SPawel Jakub Dawidek #include <errno.h>
42*de503941SPawel Jakub Dawidek #include <limits.h>
43*de503941SPawel Jakub Dawidek #include <stdio.h>
44*de503941SPawel Jakub Dawidek #include <stdlib.h>
45*de503941SPawel Jakub Dawidek #include <unistd.h>
46*de503941SPawel Jakub Dawidek 
47*de503941SPawel Jakub Dawidek #include "misc.h"
48*de503941SPawel Jakub Dawidek 
49*de503941SPawel Jakub Dawidek static void
50*de503941SPawel Jakub Dawidek ioctl_tests_0(int fd)
51*de503941SPawel Jakub Dawidek {
52*de503941SPawel Jakub Dawidek 	unsigned long cmds[2];
53*de503941SPawel Jakub Dawidek 
54*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, NULL, 0) == INT_MAX);
55*de503941SPawel Jakub Dawidek 
56*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
57*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIOCLEX) == 0);
58*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
59*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIONCLEX) == 0);
60*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
61*de503941SPawel Jakub Dawidek 
62*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
63*de503941SPawel Jakub Dawidek 	cmds[1] = FIONCLEX;
64*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
65*de503941SPawel Jakub Dawidek 	cmds[0] = cmds[1] = 0;
66*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == nitems(cmds));
67*de503941SPawel Jakub Dawidek 	CHECK((cmds[0] == FIOCLEX && cmds[1] == FIONCLEX) ||
68*de503941SPawel Jakub Dawidek 	    (cmds[0] == FIONCLEX && cmds[1] == FIOCLEX));
69*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
70*de503941SPawel Jakub Dawidek 	cmds[1] = FIONCLEX;
71*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
72*de503941SPawel Jakub Dawidek 	cmds[0] = cmds[1] = 0;
73*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, 1) == nitems(cmds));
74*de503941SPawel Jakub Dawidek 	CHECK(cmds[0] == FIOCLEX || cmds[0] == FIONCLEX);
75*de503941SPawel Jakub Dawidek 	CHECK(cmds[1] == 0);
76*de503941SPawel Jakub Dawidek 
77*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
78*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIOCLEX) == 0);
79*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
80*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIONCLEX) == 0);
81*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
82*de503941SPawel Jakub Dawidek 
83*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
84*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
85*de503941SPawel Jakub Dawidek 	cmds[0] = cmds[1] = 0;
86*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
87*de503941SPawel Jakub Dawidek 	CHECK(cmds[0] == FIOCLEX);
88*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
89*de503941SPawel Jakub Dawidek 	cmds[1] = FIONCLEX;
90*de503941SPawel Jakub Dawidek 	errno = 0;
91*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
92*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
93*de503941SPawel Jakub Dawidek 	cmds[0] = cmds[1] = 0;
94*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
95*de503941SPawel Jakub Dawidek 	CHECK(cmds[0] == FIOCLEX);
96*de503941SPawel Jakub Dawidek 
97*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
98*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIOCLEX) == 0);
99*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
100*de503941SPawel Jakub Dawidek 	errno = 0;
101*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIONCLEX) == -1);
102*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
103*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
104*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_SETFD, 0) == 0);
105*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
106*de503941SPawel Jakub Dawidek 
107*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, NULL, 0) == 0);
108*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
109*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
110*de503941SPawel Jakub Dawidek 	errno = 0;
111*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
112*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
113*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
114*de503941SPawel Jakub Dawidek 
115*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
116*de503941SPawel Jakub Dawidek 	errno = 0;
117*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIOCLEX) == -1);
118*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
119*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
120*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
121*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
122*de503941SPawel Jakub Dawidek 	errno = 0;
123*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIONCLEX) == -1);
124*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
125*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
126*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_SETFD, 0) == 0);
127*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
128*de503941SPawel Jakub Dawidek }
129*de503941SPawel Jakub Dawidek 
130*de503941SPawel Jakub Dawidek static void
131*de503941SPawel Jakub Dawidek ioctl_tests_1(int fd)
132*de503941SPawel Jakub Dawidek {
133*de503941SPawel Jakub Dawidek 	unsigned long cmds[2];
134*de503941SPawel Jakub Dawidek 
135*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
136*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
137*de503941SPawel Jakub Dawidek 	cmds[0] = cmds[1] = 0;
138*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
139*de503941SPawel Jakub Dawidek 	CHECK(cmds[0] == FIOCLEX);
140*de503941SPawel Jakub Dawidek 	CHECK(cmds[1] == 0);
141*de503941SPawel Jakub Dawidek 
142*de503941SPawel Jakub Dawidek 	CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_IOCTL) == 0);
143*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
144*de503941SPawel Jakub Dawidek 
145*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
146*de503941SPawel Jakub Dawidek 	cmds[1] = FIONCLEX;
147*de503941SPawel Jakub Dawidek 	errno = 0;
148*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
149*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
150*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
151*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
152*de503941SPawel Jakub Dawidek 	errno = 0;
153*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
154*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
155*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
156*de503941SPawel Jakub Dawidek 
157*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
158*de503941SPawel Jakub Dawidek 	errno = 0;
159*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIOCLEX) == -1);
160*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
161*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
162*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
163*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
164*de503941SPawel Jakub Dawidek 	errno = 0;
165*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIONCLEX) == -1);
166*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
167*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
168*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_SETFD, 0) == 0);
169*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
170*de503941SPawel Jakub Dawidek }
171*de503941SPawel Jakub Dawidek 
172*de503941SPawel Jakub Dawidek static void
173*de503941SPawel Jakub Dawidek ioctl_tests_2(int fd)
174*de503941SPawel Jakub Dawidek {
175*de503941SPawel Jakub Dawidek 	unsigned long cmds[2];
176*de503941SPawel Jakub Dawidek 
177*de503941SPawel Jakub Dawidek 	CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_IOCTL) == 0);
178*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
179*de503941SPawel Jakub Dawidek 
180*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
181*de503941SPawel Jakub Dawidek 	cmds[1] = FIONCLEX;
182*de503941SPawel Jakub Dawidek 	errno = 0;
183*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
184*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
185*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
186*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
187*de503941SPawel Jakub Dawidek 	errno = 0;
188*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
189*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
190*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
191*de503941SPawel Jakub Dawidek 
192*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
193*de503941SPawel Jakub Dawidek 	errno = 0;
194*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIOCLEX) == -1);
195*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
196*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
197*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
198*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
199*de503941SPawel Jakub Dawidek 	errno = 0;
200*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIONCLEX) == -1);
201*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
202*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
203*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_SETFD, 0) == 0);
204*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
205*de503941SPawel Jakub Dawidek }
206*de503941SPawel Jakub Dawidek 
207*de503941SPawel Jakub Dawidek static void
208*de503941SPawel Jakub Dawidek ioctl_tests_send_0(int sock)
209*de503941SPawel Jakub Dawidek {
210*de503941SPawel Jakub Dawidek 	unsigned long cmds[2];
211*de503941SPawel Jakub Dawidek 	int fd;
212*de503941SPawel Jakub Dawidek 
213*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
214*de503941SPawel Jakub Dawidek 	CHECK(descriptor_send(sock, fd) == 0);
215*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
216*de503941SPawel Jakub Dawidek 
217*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
218*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
219*de503941SPawel Jakub Dawidek 	cmds[1] = FIONCLEX;
220*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
221*de503941SPawel Jakub Dawidek 	CHECK(descriptor_send(sock, fd) == 0);
222*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
223*de503941SPawel Jakub Dawidek 
224*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
225*de503941SPawel Jakub Dawidek 	cmds[0] = FIOCLEX;
226*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
227*de503941SPawel Jakub Dawidek 	CHECK(descriptor_send(sock, fd) == 0);
228*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
229*de503941SPawel Jakub Dawidek 
230*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
231*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_limit(fd, NULL, 0) == 0);
232*de503941SPawel Jakub Dawidek 	CHECK(descriptor_send(sock, fd) == 0);
233*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
234*de503941SPawel Jakub Dawidek }
235*de503941SPawel Jakub Dawidek 
236*de503941SPawel Jakub Dawidek static void
237*de503941SPawel Jakub Dawidek ioctl_tests_recv_0(int sock)
238*de503941SPawel Jakub Dawidek {
239*de503941SPawel Jakub Dawidek 	unsigned long cmds[2];
240*de503941SPawel Jakub Dawidek 	int fd;
241*de503941SPawel Jakub Dawidek 
242*de503941SPawel Jakub Dawidek 	CHECK(descriptor_recv(sock, &fd) == 0);
243*de503941SPawel Jakub Dawidek 
244*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, NULL, 0) == INT_MAX);
245*de503941SPawel Jakub Dawidek 
246*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
247*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIOCLEX) == 0);
248*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
249*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIONCLEX) == 0);
250*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
251*de503941SPawel Jakub Dawidek 
252*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
253*de503941SPawel Jakub Dawidek 
254*de503941SPawel Jakub Dawidek 	CHECK(descriptor_recv(sock, &fd) == 0);
255*de503941SPawel Jakub Dawidek 
256*de503941SPawel Jakub Dawidek 	cmds[0] = cmds[1] = 0;
257*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == nitems(cmds));
258*de503941SPawel Jakub Dawidek 	CHECK((cmds[0] == FIOCLEX && cmds[1] == FIONCLEX) ||
259*de503941SPawel Jakub Dawidek 	    (cmds[0] == FIONCLEX && cmds[1] == FIOCLEX));
260*de503941SPawel Jakub Dawidek 
261*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
262*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIOCLEX) == 0);
263*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
264*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIONCLEX) == 0);
265*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
266*de503941SPawel Jakub Dawidek 
267*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
268*de503941SPawel Jakub Dawidek 
269*de503941SPawel Jakub Dawidek 	CHECK(descriptor_recv(sock, &fd) == 0);
270*de503941SPawel Jakub Dawidek 
271*de503941SPawel Jakub Dawidek 	cmds[0] = cmds[1] = 0;
272*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
273*de503941SPawel Jakub Dawidek 	CHECK(cmds[0] == FIOCLEX);
274*de503941SPawel Jakub Dawidek 
275*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
276*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIOCLEX) == 0);
277*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
278*de503941SPawel Jakub Dawidek 	errno = 0;
279*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIONCLEX) == -1);
280*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
281*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
282*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_SETFD, 0) == 0);
283*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
284*de503941SPawel Jakub Dawidek 
285*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
286*de503941SPawel Jakub Dawidek 
287*de503941SPawel Jakub Dawidek 	CHECK(descriptor_recv(sock, &fd) == 0);
288*de503941SPawel Jakub Dawidek 
289*de503941SPawel Jakub Dawidek 	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
290*de503941SPawel Jakub Dawidek 
291*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
292*de503941SPawel Jakub Dawidek 	errno = 0;
293*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIOCLEX) == -1);
294*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
295*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
296*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
297*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
298*de503941SPawel Jakub Dawidek 	errno = 0;
299*de503941SPawel Jakub Dawidek 	CHECK(ioctl(fd, FIONCLEX) == -1);
300*de503941SPawel Jakub Dawidek 	CHECK(errno == ENOTCAPABLE);
301*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
302*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_SETFD, 0) == 0);
303*de503941SPawel Jakub Dawidek 	CHECK(fcntl(fd, F_GETFD) == 0);
304*de503941SPawel Jakub Dawidek 
305*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
306*de503941SPawel Jakub Dawidek }
307*de503941SPawel Jakub Dawidek 
308*de503941SPawel Jakub Dawidek int
309*de503941SPawel Jakub Dawidek main(void)
310*de503941SPawel Jakub Dawidek {
311*de503941SPawel Jakub Dawidek 	int fd, pfd, sp[2];
312*de503941SPawel Jakub Dawidek 	pid_t pid;
313*de503941SPawel Jakub Dawidek 
314*de503941SPawel Jakub Dawidek 	printf("1..607\n");
315*de503941SPawel Jakub Dawidek 
316*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
317*de503941SPawel Jakub Dawidek 	ioctl_tests_0(fd);
318*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
319*de503941SPawel Jakub Dawidek 
320*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
321*de503941SPawel Jakub Dawidek 	ioctl_tests_1(fd);
322*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
323*de503941SPawel Jakub Dawidek 
324*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
325*de503941SPawel Jakub Dawidek 	ioctl_tests_2(fd);
326*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
327*de503941SPawel Jakub Dawidek 
328*de503941SPawel Jakub Dawidek 	/* Child inherits descriptor and operates on it first. */
329*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
330*de503941SPawel Jakub Dawidek 	pid = fork();
331*de503941SPawel Jakub Dawidek 	switch (pid) {
332*de503941SPawel Jakub Dawidek 	case -1:
333*de503941SPawel Jakub Dawidek 		err(1, "fork() failed");
334*de503941SPawel Jakub Dawidek 	case 0:
335*de503941SPawel Jakub Dawidek 		ioctl_tests_0(fd);
336*de503941SPawel Jakub Dawidek 		CHECK(close(fd) == 0);
337*de503941SPawel Jakub Dawidek 		exit(0);
338*de503941SPawel Jakub Dawidek 	default:
339*de503941SPawel Jakub Dawidek 		if (waitpid(pid, NULL, 0) == -1)
340*de503941SPawel Jakub Dawidek 			err(1, "waitpid() failed");
341*de503941SPawel Jakub Dawidek 		ioctl_tests_0(fd);
342*de503941SPawel Jakub Dawidek 	}
343*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
344*de503941SPawel Jakub Dawidek 
345*de503941SPawel Jakub Dawidek 	/* Child inherits descriptor, but operates on it after parent. */
346*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
347*de503941SPawel Jakub Dawidek 	pid = fork();
348*de503941SPawel Jakub Dawidek 	switch (pid) {
349*de503941SPawel Jakub Dawidek 	case -1:
350*de503941SPawel Jakub Dawidek 		err(1, "fork() failed");
351*de503941SPawel Jakub Dawidek 	case 0:
352*de503941SPawel Jakub Dawidek 		sleep(1);
353*de503941SPawel Jakub Dawidek 		ioctl_tests_0(fd);
354*de503941SPawel Jakub Dawidek 		CHECK(close(fd) == 0);
355*de503941SPawel Jakub Dawidek 		exit(0);
356*de503941SPawel Jakub Dawidek 	default:
357*de503941SPawel Jakub Dawidek 		ioctl_tests_0(fd);
358*de503941SPawel Jakub Dawidek 		if (waitpid(pid, NULL, 0) == -1)
359*de503941SPawel Jakub Dawidek 			err(1, "waitpid() failed");
360*de503941SPawel Jakub Dawidek 	}
361*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
362*de503941SPawel Jakub Dawidek 
363*de503941SPawel Jakub Dawidek 	/* Child inherits descriptor and operates on it first. */
364*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
365*de503941SPawel Jakub Dawidek 	pid = pdfork(&pfd, 0);
366*de503941SPawel Jakub Dawidek 	switch (pid) {
367*de503941SPawel Jakub Dawidek 	case -1:
368*de503941SPawel Jakub Dawidek 		err(1, "pdfork() failed");
369*de503941SPawel Jakub Dawidek 	case 0:
370*de503941SPawel Jakub Dawidek 		ioctl_tests_1(fd);
371*de503941SPawel Jakub Dawidek 		exit(0);
372*de503941SPawel Jakub Dawidek 	default:
373*de503941SPawel Jakub Dawidek 		if (pdwait(pfd) == -1)
374*de503941SPawel Jakub Dawidek 			err(1, "pdwait() failed");
375*de503941SPawel Jakub Dawidek 		close(pfd);
376*de503941SPawel Jakub Dawidek 		ioctl_tests_1(fd);
377*de503941SPawel Jakub Dawidek 	}
378*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
379*de503941SPawel Jakub Dawidek 
380*de503941SPawel Jakub Dawidek 	/* Child inherits descriptor, but operates on it after parent. */
381*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
382*de503941SPawel Jakub Dawidek 	pid = pdfork(&pfd, 0);
383*de503941SPawel Jakub Dawidek 	switch (pid) {
384*de503941SPawel Jakub Dawidek 	case -1:
385*de503941SPawel Jakub Dawidek 		err(1, "pdfork() failed");
386*de503941SPawel Jakub Dawidek 	case 0:
387*de503941SPawel Jakub Dawidek 		sleep(1);
388*de503941SPawel Jakub Dawidek 		ioctl_tests_1(fd);
389*de503941SPawel Jakub Dawidek 		exit(0);
390*de503941SPawel Jakub Dawidek 	default:
391*de503941SPawel Jakub Dawidek 		ioctl_tests_1(fd);
392*de503941SPawel Jakub Dawidek 		if (pdwait(pfd) == -1)
393*de503941SPawel Jakub Dawidek 			err(1, "pdwait() failed");
394*de503941SPawel Jakub Dawidek 		close(pfd);
395*de503941SPawel Jakub Dawidek 	}
396*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
397*de503941SPawel Jakub Dawidek 
398*de503941SPawel Jakub Dawidek 	/* Child inherits descriptor and operates on it first. */
399*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
400*de503941SPawel Jakub Dawidek 	pid = fork();
401*de503941SPawel Jakub Dawidek 	switch (pid) {
402*de503941SPawel Jakub Dawidek 	case -1:
403*de503941SPawel Jakub Dawidek 		err(1, "fork() failed");
404*de503941SPawel Jakub Dawidek 	case 0:
405*de503941SPawel Jakub Dawidek 		ioctl_tests_2(fd);
406*de503941SPawel Jakub Dawidek 		exit(0);
407*de503941SPawel Jakub Dawidek 	default:
408*de503941SPawel Jakub Dawidek 		if (waitpid(pid, NULL, 0) == -1)
409*de503941SPawel Jakub Dawidek 			err(1, "waitpid() failed");
410*de503941SPawel Jakub Dawidek 		ioctl_tests_2(fd);
411*de503941SPawel Jakub Dawidek 	}
412*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
413*de503941SPawel Jakub Dawidek 
414*de503941SPawel Jakub Dawidek 	/* Child inherits descriptor, but operates on it after parent. */
415*de503941SPawel Jakub Dawidek 	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
416*de503941SPawel Jakub Dawidek 	pid = fork();
417*de503941SPawel Jakub Dawidek 	switch (pid) {
418*de503941SPawel Jakub Dawidek 	case -1:
419*de503941SPawel Jakub Dawidek 		err(1, "fork() failed");
420*de503941SPawel Jakub Dawidek 	case 0:
421*de503941SPawel Jakub Dawidek 		sleep(1);
422*de503941SPawel Jakub Dawidek 		ioctl_tests_2(fd);
423*de503941SPawel Jakub Dawidek 		exit(0);
424*de503941SPawel Jakub Dawidek 	default:
425*de503941SPawel Jakub Dawidek 		ioctl_tests_2(fd);
426*de503941SPawel Jakub Dawidek 		if (waitpid(pid, NULL, 0) == -1)
427*de503941SPawel Jakub Dawidek 			err(1, "waitpid() failed");
428*de503941SPawel Jakub Dawidek 	}
429*de503941SPawel Jakub Dawidek 	CHECK(close(fd) == 0);
430*de503941SPawel Jakub Dawidek 
431*de503941SPawel Jakub Dawidek 	/* Send descriptors from parent to child. */
432*de503941SPawel Jakub Dawidek 	CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
433*de503941SPawel Jakub Dawidek 	CHECK((pid = fork()) >= 0);
434*de503941SPawel Jakub Dawidek 	if (pid == 0) {
435*de503941SPawel Jakub Dawidek 		CHECK(close(sp[0]) == 0);
436*de503941SPawel Jakub Dawidek 		ioctl_tests_recv_0(sp[1]);
437*de503941SPawel Jakub Dawidek 		CHECK(close(sp[1]) == 0);
438*de503941SPawel Jakub Dawidek 		exit(0);
439*de503941SPawel Jakub Dawidek 	} else {
440*de503941SPawel Jakub Dawidek 		CHECK(close(sp[1]) == 0);
441*de503941SPawel Jakub Dawidek 		ioctl_tests_send_0(sp[0]);
442*de503941SPawel Jakub Dawidek 		CHECK(waitpid(pid, NULL, 0) == pid);
443*de503941SPawel Jakub Dawidek 		CHECK(close(sp[0]) == 0);
444*de503941SPawel Jakub Dawidek 	}
445*de503941SPawel Jakub Dawidek 
446*de503941SPawel Jakub Dawidek 	/* Send descriptors from child to parent. */
447*de503941SPawel Jakub Dawidek 	CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
448*de503941SPawel Jakub Dawidek 	CHECK((pid = fork()) >= 0);
449*de503941SPawel Jakub Dawidek 	if (pid == 0) {
450*de503941SPawel Jakub Dawidek 		CHECK(close(sp[0]) == 0);
451*de503941SPawel Jakub Dawidek 		ioctl_tests_send_0(sp[1]);
452*de503941SPawel Jakub Dawidek 		CHECK(close(sp[1]) == 0);
453*de503941SPawel Jakub Dawidek 		exit(0);
454*de503941SPawel Jakub Dawidek 	} else {
455*de503941SPawel Jakub Dawidek 		CHECK(close(sp[1]) == 0);
456*de503941SPawel Jakub Dawidek 		ioctl_tests_recv_0(sp[0]);
457*de503941SPawel Jakub Dawidek 		CHECK(waitpid(pid, NULL, 0) == pid);
458*de503941SPawel Jakub Dawidek 		CHECK(close(sp[0]) == 0);
459*de503941SPawel Jakub Dawidek 	}
460*de503941SPawel Jakub Dawidek 
461*de503941SPawel Jakub Dawidek 	exit(0);
462*de503941SPawel Jakub Dawidek }
463