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/capability.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];
136 CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
137 cmds[0] = cmds[1] = 0;
138 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
139 CHECK(cmds[0] == FIOCLEX);
142 CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_IOCTL) == 0);
143 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
148 CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
149 CHECK(errno == ENOTCAPABLE);
150 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
153 CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
154 CHECK(errno == ENOTCAPABLE);
155 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
157 CHECK(fcntl(fd, F_GETFD) == 0);
159 CHECK(ioctl(fd, FIOCLEX) == -1);
160 CHECK(errno == ENOTCAPABLE);
161 CHECK(fcntl(fd, F_GETFD) == 0);
162 CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
163 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
165 CHECK(ioctl(fd, FIONCLEX) == -1);
166 CHECK(errno == ENOTCAPABLE);
167 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
168 CHECK(fcntl(fd, F_SETFD, 0) == 0);
169 CHECK(fcntl(fd, F_GETFD) == 0);
173 ioctl_tests_2(int fd)
175 unsigned long cmds[2];
177 CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_IOCTL) == 0);
178 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
183 CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
184 CHECK(errno == ENOTCAPABLE);
185 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
188 CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
189 CHECK(errno == ENOTCAPABLE);
190 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
192 CHECK(fcntl(fd, F_GETFD) == 0);
194 CHECK(ioctl(fd, FIOCLEX) == -1);
195 CHECK(errno == ENOTCAPABLE);
196 CHECK(fcntl(fd, F_GETFD) == 0);
197 CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
198 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
200 CHECK(ioctl(fd, FIONCLEX) == -1);
201 CHECK(errno == ENOTCAPABLE);
202 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
203 CHECK(fcntl(fd, F_SETFD, 0) == 0);
204 CHECK(fcntl(fd, F_GETFD) == 0);
208 ioctl_tests_send_0(int sock)
210 unsigned long cmds[2];
213 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
214 CHECK(descriptor_send(sock, fd) == 0);
215 CHECK(close(fd) == 0);
217 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
220 CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
221 CHECK(descriptor_send(sock, fd) == 0);
222 CHECK(close(fd) == 0);
224 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
226 CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
227 CHECK(descriptor_send(sock, fd) == 0);
228 CHECK(close(fd) == 0);
230 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
231 CHECK(cap_ioctls_limit(fd, NULL, 0) == 0);
232 CHECK(descriptor_send(sock, fd) == 0);
233 CHECK(close(fd) == 0);
237 ioctl_tests_recv_0(int sock)
239 unsigned long cmds[2];
242 CHECK(descriptor_recv(sock, &fd) == 0);
244 CHECK(cap_ioctls_get(fd, NULL, 0) == CAP_IOCTLS_ALL);
246 CHECK(fcntl(fd, F_GETFD) == 0);
247 CHECK(ioctl(fd, FIOCLEX) == 0);
248 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
249 CHECK(ioctl(fd, FIONCLEX) == 0);
250 CHECK(fcntl(fd, F_GETFD) == 0);
252 CHECK(close(fd) == 0);
254 CHECK(descriptor_recv(sock, &fd) == 0);
256 cmds[0] = cmds[1] = 0;
257 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == nitems(cmds));
258 CHECK((cmds[0] == FIOCLEX && cmds[1] == FIONCLEX) ||
259 (cmds[0] == FIONCLEX && cmds[1] == FIOCLEX));
261 CHECK(fcntl(fd, F_GETFD) == 0);
262 CHECK(ioctl(fd, FIOCLEX) == 0);
263 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
264 CHECK(ioctl(fd, FIONCLEX) == 0);
265 CHECK(fcntl(fd, F_GETFD) == 0);
267 CHECK(close(fd) == 0);
269 CHECK(descriptor_recv(sock, &fd) == 0);
271 cmds[0] = cmds[1] = 0;
272 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
273 CHECK(cmds[0] == FIOCLEX);
275 CHECK(fcntl(fd, F_GETFD) == 0);
276 CHECK(ioctl(fd, FIOCLEX) == 0);
277 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
279 CHECK(ioctl(fd, FIONCLEX) == -1);
280 CHECK(errno == ENOTCAPABLE);
281 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
282 CHECK(fcntl(fd, F_SETFD, 0) == 0);
283 CHECK(fcntl(fd, F_GETFD) == 0);
285 CHECK(close(fd) == 0);
287 CHECK(descriptor_recv(sock, &fd) == 0);
289 CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
291 CHECK(fcntl(fd, F_GETFD) == 0);
293 CHECK(ioctl(fd, FIOCLEX) == -1);
294 CHECK(errno == ENOTCAPABLE);
295 CHECK(fcntl(fd, F_GETFD) == 0);
296 CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
297 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
299 CHECK(ioctl(fd, FIONCLEX) == -1);
300 CHECK(errno == ENOTCAPABLE);
301 CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
302 CHECK(fcntl(fd, F_SETFD, 0) == 0);
303 CHECK(fcntl(fd, F_GETFD) == 0);
305 CHECK(close(fd) == 0);
316 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
318 CHECK(close(fd) == 0);
320 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
322 CHECK(close(fd) == 0);
324 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
326 CHECK(close(fd) == 0);
328 /* Child inherits descriptor and operates on it first. */
329 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
333 err(1, "fork() failed");
336 CHECK(close(fd) == 0);
339 if (waitpid(pid, NULL, 0) == -1)
340 err(1, "waitpid() failed");
343 CHECK(close(fd) == 0);
345 /* Child inherits descriptor, but operates on it after parent. */
346 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
350 err(1, "fork() failed");
354 CHECK(close(fd) == 0);
358 if (waitpid(pid, NULL, 0) == -1)
359 err(1, "waitpid() failed");
361 CHECK(close(fd) == 0);
363 /* Child inherits descriptor and operates on it first. */
364 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
365 pid = pdfork(&pfd, 0);
368 err(1, "pdfork() failed");
373 if (pdwait(pfd) == -1)
374 err(1, "pdwait() failed");
378 CHECK(close(fd) == 0);
380 /* Child inherits descriptor, but operates on it after parent. */
381 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
382 pid = pdfork(&pfd, 0);
385 err(1, "pdfork() failed");
392 if (pdwait(pfd) == -1)
393 err(1, "pdwait() failed");
396 CHECK(close(fd) == 0);
398 /* Child inherits descriptor and operates on it first. */
399 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
403 err(1, "fork() failed");
408 if (waitpid(pid, NULL, 0) == -1)
409 err(1, "waitpid() failed");
412 CHECK(close(fd) == 0);
414 /* Child inherits descriptor, but operates on it after parent. */
415 CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
419 err(1, "fork() failed");
426 if (waitpid(pid, NULL, 0) == -1)
427 err(1, "waitpid() failed");
429 CHECK(close(fd) == 0);
431 /* Send descriptors from parent to child. */
432 CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
433 CHECK((pid = fork()) >= 0);
435 CHECK(close(sp[0]) == 0);
436 ioctl_tests_recv_0(sp[1]);
437 CHECK(close(sp[1]) == 0);
440 CHECK(close(sp[1]) == 0);
441 ioctl_tests_send_0(sp[0]);
442 CHECK(waitpid(pid, NULL, 0) == pid);
443 CHECK(close(sp[0]) == 0);
446 /* Send descriptors from child to parent. */
447 CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
448 CHECK((pid = fork()) >= 0);
450 CHECK(close(sp[0]) == 0);
451 ioctl_tests_send_0(sp[1]);
452 CHECK(close(sp[1]) == 0);
455 CHECK(close(sp[1]) == 0);
456 ioctl_tests_recv_0(sp[0]);
457 CHECK(waitpid(pid, NULL, 0) == pid);
458 CHECK(close(sp[0]) == 0);