]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - tools/regression/capsicum/syscalls/cap_ioctls_limit.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / tools / regression / capsicum / syscalls / cap_ioctls_limit.c
1 /*-
2  * Copyright (c) 2012 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Pawel Jakub Dawidek under sponsorship from
6  * the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
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.
16  *
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
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
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>
38 #include <sys/wait.h>
39
40 #include <err.h>
41 #include <errno.h>
42 #include <limits.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46
47 #include "misc.h"
48
49 static void
50 ioctl_tests_0(int fd)
51 {
52         unsigned long cmds[2];
53
54         CHECK(cap_ioctls_get(fd, NULL, 0) == CAP_IOCTLS_ALL);
55
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);
61
62         cmds[0] = FIOCLEX;
63         cmds[1] = FIONCLEX;
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));
69         cmds[0] = FIOCLEX;
70         cmds[1] = FIONCLEX;
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);
75         CHECK(cmds[1] == 0);
76
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);
82
83         cmds[0] = FIOCLEX;
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);
88         cmds[0] = FIOCLEX;
89         cmds[1] = FIONCLEX;
90         errno = 0;
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);
96
97         CHECK(fcntl(fd, F_GETFD) == 0);
98         CHECK(ioctl(fd, FIOCLEX) == 0);
99         CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
100         errno = 0;
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);
106
107         CHECK(cap_ioctls_limit(fd, NULL, 0) == 0);
108         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
109         cmds[0] = FIOCLEX;
110         errno = 0;
111         CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
112         CHECK(errno == ENOTCAPABLE);
113         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
114
115         CHECK(fcntl(fd, F_GETFD) == 0);
116         errno = 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);
122         errno = 0;
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);
128 }
129
130 static void
131 ioctl_tests_1(int fd)
132 {
133         unsigned long cmds[2];
134
135         cmds[0] = FIOCLEX;
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);
140         CHECK(cmds[1] == 0);
141
142         CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_IOCTL) == 0);
143         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
144
145         cmds[0] = FIOCLEX;
146         cmds[1] = FIONCLEX;
147         errno = 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);
151         cmds[0] = FIOCLEX;
152         errno = 0;
153         CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
154         CHECK(errno == ENOTCAPABLE);
155         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
156
157         CHECK(fcntl(fd, F_GETFD) == 0);
158         errno = 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);
164         errno = 0;
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);
170 }
171
172 static void
173 ioctl_tests_2(int fd)
174 {
175         unsigned long cmds[2];
176
177         CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_IOCTL) == 0);
178         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
179
180         cmds[0] = FIOCLEX;
181         cmds[1] = FIONCLEX;
182         errno = 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);
186         cmds[0] = FIOCLEX;
187         errno = 0;
188         CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
189         CHECK(errno == ENOTCAPABLE);
190         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
191
192         CHECK(fcntl(fd, F_GETFD) == 0);
193         errno = 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);
199         errno = 0;
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);
205 }
206
207 static void
208 ioctl_tests_send_0(int sock)
209 {
210         unsigned long cmds[2];
211         int fd;
212
213         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
214         CHECK(descriptor_send(sock, fd) == 0);
215         CHECK(close(fd) == 0);
216
217         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
218         cmds[0] = FIOCLEX;
219         cmds[1] = FIONCLEX;
220         CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
221         CHECK(descriptor_send(sock, fd) == 0);
222         CHECK(close(fd) == 0);
223
224         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
225         cmds[0] = FIOCLEX;
226         CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
227         CHECK(descriptor_send(sock, fd) == 0);
228         CHECK(close(fd) == 0);
229
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);
234 }
235
236 static void
237 ioctl_tests_recv_0(int sock)
238 {
239         unsigned long cmds[2];
240         int fd;
241
242         CHECK(descriptor_recv(sock, &fd) == 0);
243
244         CHECK(cap_ioctls_get(fd, NULL, 0) == CAP_IOCTLS_ALL);
245
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);
251
252         CHECK(close(fd) == 0);
253
254         CHECK(descriptor_recv(sock, &fd) == 0);
255
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));
260
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);
266
267         CHECK(close(fd) == 0);
268
269         CHECK(descriptor_recv(sock, &fd) == 0);
270
271         cmds[0] = cmds[1] = 0;
272         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
273         CHECK(cmds[0] == FIOCLEX);
274
275         CHECK(fcntl(fd, F_GETFD) == 0);
276         CHECK(ioctl(fd, FIOCLEX) == 0);
277         CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
278         errno = 0;
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);
284
285         CHECK(close(fd) == 0);
286
287         CHECK(descriptor_recv(sock, &fd) == 0);
288
289         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
290
291         CHECK(fcntl(fd, F_GETFD) == 0);
292         errno = 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);
298         errno = 0;
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);
304
305         CHECK(close(fd) == 0);
306 }
307
308 int
309 main(void)
310 {
311         int fd, pfd, sp[2];
312         pid_t pid;
313
314         printf("1..607\n");
315
316         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
317         ioctl_tests_0(fd);
318         CHECK(close(fd) == 0);
319
320         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
321         ioctl_tests_1(fd);
322         CHECK(close(fd) == 0);
323
324         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
325         ioctl_tests_2(fd);
326         CHECK(close(fd) == 0);
327
328         /* Child inherits descriptor and operates on it first. */
329         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
330         pid = fork();
331         switch (pid) {
332         case -1:
333                 err(1, "fork() failed");
334         case 0:
335                 ioctl_tests_0(fd);
336                 CHECK(close(fd) == 0);
337                 exit(0);
338         default:
339                 if (waitpid(pid, NULL, 0) == -1)
340                         err(1, "waitpid() failed");
341                 ioctl_tests_0(fd);
342         }
343         CHECK(close(fd) == 0);
344
345         /* Child inherits descriptor, but operates on it after parent. */
346         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
347         pid = fork();
348         switch (pid) {
349         case -1:
350                 err(1, "fork() failed");
351         case 0:
352                 sleep(1);
353                 ioctl_tests_0(fd);
354                 CHECK(close(fd) == 0);
355                 exit(0);
356         default:
357                 ioctl_tests_0(fd);
358                 if (waitpid(pid, NULL, 0) == -1)
359                         err(1, "waitpid() failed");
360         }
361         CHECK(close(fd) == 0);
362
363         /* Child inherits descriptor and operates on it first. */
364         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
365         pid = pdfork(&pfd, 0);
366         switch (pid) {
367         case -1:
368                 err(1, "pdfork() failed");
369         case 0:
370                 ioctl_tests_1(fd);
371                 exit(0);
372         default:
373                 if (pdwait(pfd) == -1)
374                         err(1, "pdwait() failed");
375                 close(pfd);
376                 ioctl_tests_1(fd);
377         }
378         CHECK(close(fd) == 0);
379
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);
383         switch (pid) {
384         case -1:
385                 err(1, "pdfork() failed");
386         case 0:
387                 sleep(1);
388                 ioctl_tests_1(fd);
389                 exit(0);
390         default:
391                 ioctl_tests_1(fd);
392                 if (pdwait(pfd) == -1)
393                         err(1, "pdwait() failed");
394                 close(pfd);
395         }
396         CHECK(close(fd) == 0);
397
398         /* Child inherits descriptor and operates on it first. */
399         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
400         pid = fork();
401         switch (pid) {
402         case -1:
403                 err(1, "fork() failed");
404         case 0:
405                 ioctl_tests_2(fd);
406                 exit(0);
407         default:
408                 if (waitpid(pid, NULL, 0) == -1)
409                         err(1, "waitpid() failed");
410                 ioctl_tests_2(fd);
411         }
412         CHECK(close(fd) == 0);
413
414         /* Child inherits descriptor, but operates on it after parent. */
415         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
416         pid = fork();
417         switch (pid) {
418         case -1:
419                 err(1, "fork() failed");
420         case 0:
421                 sleep(1);
422                 ioctl_tests_2(fd);
423                 exit(0);
424         default:
425                 ioctl_tests_2(fd);
426                 if (waitpid(pid, NULL, 0) == -1)
427                         err(1, "waitpid() failed");
428         }
429         CHECK(close(fd) == 0);
430
431         /* Send descriptors from parent to child. */
432         CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
433         CHECK((pid = fork()) >= 0);
434         if (pid == 0) {
435                 CHECK(close(sp[0]) == 0);
436                 ioctl_tests_recv_0(sp[1]);
437                 CHECK(close(sp[1]) == 0);
438                 exit(0);
439         } else {
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);
444         }
445
446         /* Send descriptors from child to parent. */
447         CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
448         CHECK((pid = fork()) >= 0);
449         if (pid == 0) {
450                 CHECK(close(sp[0]) == 0);
451                 ioctl_tests_send_0(sp[1]);
452                 CHECK(close(sp[1]) == 0);
453                 exit(0);
454         } else {
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);
459         }
460
461         exit(0);
462 }