2 * Copyright (c) 2012 The FreeBSD Foundation
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/capsicum.h>
35 #include <sys/ioctl.h>
36 #include <sys/procdesc.h>
37 #include <sys/socket.h>
52 unsigned long cmds[2];
54 CHECK(cap_ioctls_get(fd, NULL, 0) == CAP_IOCTLS_ALL);
56 CHECK(fcntl(fd, F_GETFD) == 0);
57 CHECK(ioctl(fd, FIOCLEX) == 0);
58 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
59 CHECK(ioctl(fd, FIONCLEX) == 0);
60 CHECK(fcntl(fd, F_GETFD) == 0);
64 CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
65 cmds[0] = cmds[1] = 0;
66 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == nitems(cmds));
67 CHECK((cmds[0] == FIOCLEX && cmds[1] == FIONCLEX) ||
68 (cmds[0] == FIONCLEX && cmds[1] == FIOCLEX));
71 CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
72 cmds[0] = cmds[1] = 0;
73 CHECK(cap_ioctls_get(fd, cmds, 1) == nitems(cmds));
74 CHECK(cmds[0] == FIOCLEX || cmds[0] == FIONCLEX);
77 CHECK(fcntl(fd, F_GETFD) == 0);
78 CHECK(ioctl(fd, FIOCLEX) == 0);
79 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
80 CHECK(ioctl(fd, FIONCLEX) == 0);
81 CHECK(fcntl(fd, F_GETFD) == 0);
84 CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
85 cmds[0] = cmds[1] = 0;
86 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
87 CHECK(cmds[0] == FIOCLEX);
91 CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
92 CHECK(errno == ENOTCAPABLE);
93 cmds[0] = cmds[1] = 0;
94 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
95 CHECK(cmds[0] == FIOCLEX);
97 CHECK(fcntl(fd, F_GETFD) == 0);
98 CHECK(ioctl(fd, FIOCLEX) == 0);
99 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
101 CHECK(ioctl(fd, FIONCLEX) == -1);
102 CHECK(errno == ENOTCAPABLE);
103 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
104 CHECK(fcntl(fd, F_SETFD, 0) == 0);
105 CHECK(fcntl(fd, F_GETFD) == 0);
107 CHECK(cap_ioctls_limit(fd, NULL, 0) == 0);
108 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
111 CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
112 CHECK(errno == ENOTCAPABLE);
113 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
115 CHECK(fcntl(fd, F_GETFD) == 0);
117 CHECK(ioctl(fd, FIOCLEX) == -1);
118 CHECK(errno == ENOTCAPABLE);
119 CHECK(fcntl(fd, F_GETFD) == 0);
120 CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
121 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
123 CHECK(ioctl(fd, FIONCLEX) == -1);
124 CHECK(errno == ENOTCAPABLE);
125 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
126 CHECK(fcntl(fd, F_SETFD, 0) == 0);
127 CHECK(fcntl(fd, F_GETFD) == 0);
131 ioctl_tests_1(int fd)
133 unsigned long cmds[2];
137 CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
138 cmds[0] = cmds[1] = 0;
139 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
140 CHECK(cmds[0] == FIOCLEX);
144 cap_rights_clear(&rights, CAP_IOCTL);
146 CHECK(cap_rights_limit(fd, &rights) == 0);
147 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
152 CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
153 CHECK(errno == ENOTCAPABLE);
154 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
157 CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
158 CHECK(errno == ENOTCAPABLE);
159 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
161 CHECK(fcntl(fd, F_GETFD) == 0);
163 CHECK(ioctl(fd, FIOCLEX) == -1);
164 CHECK(errno == ENOTCAPABLE);
165 CHECK(fcntl(fd, F_GETFD) == 0);
166 CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
167 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
169 CHECK(ioctl(fd, FIONCLEX) == -1);
170 CHECK(errno == ENOTCAPABLE);
171 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
172 CHECK(fcntl(fd, F_SETFD, 0) == 0);
173 CHECK(fcntl(fd, F_GETFD) == 0);
177 ioctl_tests_2(int fd)
179 unsigned long cmds[2];
183 cap_rights_clear(&rights, CAP_IOCTL);
185 CHECK(cap_rights_limit(fd, &rights) == 0);
186 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
191 CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
192 CHECK(errno == ENOTCAPABLE);
193 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
196 CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
197 CHECK(errno == ENOTCAPABLE);
198 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
200 CHECK(fcntl(fd, F_GETFD) == 0);
202 CHECK(ioctl(fd, FIOCLEX) == -1);
203 CHECK(errno == ENOTCAPABLE);
204 CHECK(fcntl(fd, F_GETFD) == 0);
205 CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
206 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
208 CHECK(ioctl(fd, FIONCLEX) == -1);
209 CHECK(errno == ENOTCAPABLE);
210 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
211 CHECK(fcntl(fd, F_SETFD, 0) == 0);
212 CHECK(fcntl(fd, F_GETFD) == 0);
216 ioctl_tests_send_0(int sock)
218 unsigned long cmds[2];
221 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
222 CHECK(descriptor_send(sock, fd) == 0);
223 CHECK(close(fd) == 0);
225 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
228 CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
229 CHECK(descriptor_send(sock, fd) == 0);
230 CHECK(close(fd) == 0);
232 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
234 CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
235 CHECK(descriptor_send(sock, fd) == 0);
236 CHECK(close(fd) == 0);
238 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
239 CHECK(cap_ioctls_limit(fd, NULL, 0) == 0);
240 CHECK(descriptor_send(sock, fd) == 0);
241 CHECK(close(fd) == 0);
245 ioctl_tests_recv_0(int sock)
247 unsigned long cmds[2];
250 CHECK(descriptor_recv(sock, &fd) == 0);
252 CHECK(cap_ioctls_get(fd, NULL, 0) == CAP_IOCTLS_ALL);
254 CHECK(fcntl(fd, F_GETFD) == 0);
255 CHECK(ioctl(fd, FIOCLEX) == 0);
256 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
257 CHECK(ioctl(fd, FIONCLEX) == 0);
258 CHECK(fcntl(fd, F_GETFD) == 0);
260 CHECK(close(fd) == 0);
262 CHECK(descriptor_recv(sock, &fd) == 0);
264 cmds[0] = cmds[1] = 0;
265 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == nitems(cmds));
266 CHECK((cmds[0] == FIOCLEX && cmds[1] == FIONCLEX) ||
267 (cmds[0] == FIONCLEX && cmds[1] == FIOCLEX));
269 CHECK(fcntl(fd, F_GETFD) == 0);
270 CHECK(ioctl(fd, FIOCLEX) == 0);
271 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
272 CHECK(ioctl(fd, FIONCLEX) == 0);
273 CHECK(fcntl(fd, F_GETFD) == 0);
275 CHECK(close(fd) == 0);
277 CHECK(descriptor_recv(sock, &fd) == 0);
279 cmds[0] = cmds[1] = 0;
280 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
281 CHECK(cmds[0] == FIOCLEX);
283 CHECK(fcntl(fd, F_GETFD) == 0);
284 CHECK(ioctl(fd, FIOCLEX) == 0);
285 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
287 CHECK(ioctl(fd, FIONCLEX) == -1);
288 CHECK(errno == ENOTCAPABLE);
289 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
290 CHECK(fcntl(fd, F_SETFD, 0) == 0);
291 CHECK(fcntl(fd, F_GETFD) == 0);
293 CHECK(close(fd) == 0);
295 CHECK(descriptor_recv(sock, &fd) == 0);
297 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
299 CHECK(fcntl(fd, F_GETFD) == 0);
301 CHECK(ioctl(fd, FIOCLEX) == -1);
302 CHECK(errno == ENOTCAPABLE);
303 CHECK(fcntl(fd, F_GETFD) == 0);
304 CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
305 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
307 CHECK(ioctl(fd, FIONCLEX) == -1);
308 CHECK(errno == ENOTCAPABLE);
309 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
310 CHECK(fcntl(fd, F_SETFD, 0) == 0);
311 CHECK(fcntl(fd, F_GETFD) == 0);
313 CHECK(close(fd) == 0);
324 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
326 CHECK(close(fd) == 0);
328 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
330 CHECK(close(fd) == 0);
332 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
334 CHECK(close(fd) == 0);
336 /* Child inherits descriptor and operates on it first. */
337 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
341 err(1, "fork() failed");
344 CHECK(close(fd) == 0);
347 if (waitpid(pid, NULL, 0) == -1)
348 err(1, "waitpid() failed");
351 CHECK(close(fd) == 0);
353 /* Child inherits descriptor, but operates on it after parent. */
354 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
358 err(1, "fork() failed");
362 CHECK(close(fd) == 0);
366 if (waitpid(pid, NULL, 0) == -1)
367 err(1, "waitpid() failed");
369 CHECK(close(fd) == 0);
371 /* Child inherits descriptor and operates on it first. */
372 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
373 pid = pdfork(&pfd, 0);
376 err(1, "pdfork() failed");
381 if (pdwait(pfd) == -1)
382 err(1, "pdwait() failed");
386 CHECK(close(fd) == 0);
388 /* Child inherits descriptor, but operates on it after parent. */
389 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
390 pid = pdfork(&pfd, 0);
393 err(1, "pdfork() failed");
400 if (pdwait(pfd) == -1)
401 err(1, "pdwait() failed");
404 CHECK(close(fd) == 0);
406 /* Child inherits descriptor and operates on it first. */
407 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
411 err(1, "fork() failed");
416 if (waitpid(pid, NULL, 0) == -1)
417 err(1, "waitpid() failed");
420 CHECK(close(fd) == 0);
422 /* Child inherits descriptor, but operates on it after parent. */
423 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
427 err(1, "fork() failed");
434 if (waitpid(pid, NULL, 0) == -1)
435 err(1, "waitpid() failed");
437 CHECK(close(fd) == 0);
439 /* Send descriptors from parent to child. */
440 CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
441 CHECK((pid = fork()) >= 0);
443 CHECK(close(sp[0]) == 0);
444 ioctl_tests_recv_0(sp[1]);
445 CHECK(close(sp[1]) == 0);
448 CHECK(close(sp[1]) == 0);
449 ioctl_tests_send_0(sp[0]);
450 CHECK(waitpid(pid, NULL, 0) == pid);
451 CHECK(close(sp[0]) == 0);
454 /* Send descriptors from child to parent. */
455 CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
456 CHECK((pid = fork()) >= 0);
458 CHECK(close(sp[0]) == 0);
459 ioctl_tests_send_0(sp[1]);
460 CHECK(close(sp[1]) == 0);
463 CHECK(close(sp[1]) == 0);
464 ioctl_tests_recv_0(sp[0]);
465 CHECK(waitpid(pid, NULL, 0) == pid);
466 CHECK(close(sp[0]) == 0);