]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/regression/capsicum/syscalls/cap_ioctls_limit.c
Merge ACPICA 20170929.
[FreeBSD/FreeBSD.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         cap_rights_t rights;
135
136         cmds[0] = FIOCLEX;
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);
141         CHECK(cmds[1] == 0);
142
143         CAP_ALL(&rights);
144         cap_rights_clear(&rights, CAP_IOCTL);
145
146         CHECK(cap_rights_limit(fd, &rights) == 0);
147         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
148
149         cmds[0] = FIOCLEX;
150         cmds[1] = FIONCLEX;
151         errno = 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);
155         cmds[0] = FIOCLEX;
156         errno = 0;
157         CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
158         CHECK(errno == ENOTCAPABLE);
159         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
160
161         CHECK(fcntl(fd, F_GETFD) == 0);
162         errno = 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);
168         errno = 0;
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);
174 }
175
176 static void
177 ioctl_tests_2(int fd)
178 {
179         unsigned long cmds[2];
180         cap_rights_t rights;
181
182         CAP_ALL(&rights);
183         cap_rights_clear(&rights, CAP_IOCTL);
184
185         CHECK(cap_rights_limit(fd, &rights) == 0);
186         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
187
188         cmds[0] = FIOCLEX;
189         cmds[1] = FIONCLEX;
190         errno = 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);
194         cmds[0] = FIOCLEX;
195         errno = 0;
196         CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
197         CHECK(errno == ENOTCAPABLE);
198         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
199
200         CHECK(fcntl(fd, F_GETFD) == 0);
201         errno = 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);
207         errno = 0;
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);
213 }
214
215 static void
216 ioctl_tests_send_0(int sock)
217 {
218         unsigned long cmds[2];
219         int fd;
220
221         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
222         CHECK(descriptor_send(sock, fd) == 0);
223         CHECK(close(fd) == 0);
224
225         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
226         cmds[0] = FIOCLEX;
227         cmds[1] = FIONCLEX;
228         CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
229         CHECK(descriptor_send(sock, fd) == 0);
230         CHECK(close(fd) == 0);
231
232         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
233         cmds[0] = FIOCLEX;
234         CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
235         CHECK(descriptor_send(sock, fd) == 0);
236         CHECK(close(fd) == 0);
237
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);
242 }
243
244 static void
245 ioctl_tests_recv_0(int sock)
246 {
247         unsigned long cmds[2];
248         int fd;
249
250         CHECK(descriptor_recv(sock, &fd) == 0);
251
252         CHECK(cap_ioctls_get(fd, NULL, 0) == CAP_IOCTLS_ALL);
253
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);
259
260         CHECK(close(fd) == 0);
261
262         CHECK(descriptor_recv(sock, &fd) == 0);
263
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));
268
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);
274
275         CHECK(close(fd) == 0);
276
277         CHECK(descriptor_recv(sock, &fd) == 0);
278
279         cmds[0] = cmds[1] = 0;
280         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
281         CHECK(cmds[0] == FIOCLEX);
282
283         CHECK(fcntl(fd, F_GETFD) == 0);
284         CHECK(ioctl(fd, FIOCLEX) == 0);
285         CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
286         errno = 0;
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);
292
293         CHECK(close(fd) == 0);
294
295         CHECK(descriptor_recv(sock, &fd) == 0);
296
297         CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
298
299         CHECK(fcntl(fd, F_GETFD) == 0);
300         errno = 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);
306         errno = 0;
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);
312
313         CHECK(close(fd) == 0);
314 }
315
316 int
317 main(void)
318 {
319         int fd, pfd, sp[2];
320         pid_t pid;
321
322         printf("1..607\n");
323
324         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
325         ioctl_tests_0(fd);
326         CHECK(close(fd) == 0);
327
328         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
329         ioctl_tests_1(fd);
330         CHECK(close(fd) == 0);
331
332         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
333         ioctl_tests_2(fd);
334         CHECK(close(fd) == 0);
335
336         /* Child inherits descriptor and operates on it first. */
337         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
338         pid = fork();
339         switch (pid) {
340         case -1:
341                 err(1, "fork() failed");
342         case 0:
343                 ioctl_tests_0(fd);
344                 CHECK(close(fd) == 0);
345                 exit(0);
346         default:
347                 if (waitpid(pid, NULL, 0) == -1)
348                         err(1, "waitpid() failed");
349                 ioctl_tests_0(fd);
350         }
351         CHECK(close(fd) == 0);
352
353         /* Child inherits descriptor, but operates on it after parent. */
354         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
355         pid = fork();
356         switch (pid) {
357         case -1:
358                 err(1, "fork() failed");
359         case 0:
360                 sleep(1);
361                 ioctl_tests_0(fd);
362                 CHECK(close(fd) == 0);
363                 exit(0);
364         default:
365                 ioctl_tests_0(fd);
366                 if (waitpid(pid, NULL, 0) == -1)
367                         err(1, "waitpid() failed");
368         }
369         CHECK(close(fd) == 0);
370
371         /* Child inherits descriptor and operates on it first. */
372         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
373         pid = pdfork(&pfd, 0);
374         switch (pid) {
375         case -1:
376                 err(1, "pdfork() failed");
377         case 0:
378                 ioctl_tests_1(fd);
379                 exit(0);
380         default:
381                 if (pdwait(pfd) == -1)
382                         err(1, "pdwait() failed");
383                 close(pfd);
384                 ioctl_tests_1(fd);
385         }
386         CHECK(close(fd) == 0);
387
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);
391         switch (pid) {
392         case -1:
393                 err(1, "pdfork() failed");
394         case 0:
395                 sleep(1);
396                 ioctl_tests_1(fd);
397                 exit(0);
398         default:
399                 ioctl_tests_1(fd);
400                 if (pdwait(pfd) == -1)
401                         err(1, "pdwait() failed");
402                 close(pfd);
403         }
404         CHECK(close(fd) == 0);
405
406         /* Child inherits descriptor and operates on it first. */
407         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
408         pid = fork();
409         switch (pid) {
410         case -1:
411                 err(1, "fork() failed");
412         case 0:
413                 ioctl_tests_2(fd);
414                 exit(0);
415         default:
416                 if (waitpid(pid, NULL, 0) == -1)
417                         err(1, "waitpid() failed");
418                 ioctl_tests_2(fd);
419         }
420         CHECK(close(fd) == 0);
421
422         /* Child inherits descriptor, but operates on it after parent. */
423         CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
424         pid = fork();
425         switch (pid) {
426         case -1:
427                 err(1, "fork() failed");
428         case 0:
429                 sleep(1);
430                 ioctl_tests_2(fd);
431                 exit(0);
432         default:
433                 ioctl_tests_2(fd);
434                 if (waitpid(pid, NULL, 0) == -1)
435                         err(1, "waitpid() failed");
436         }
437         CHECK(close(fd) == 0);
438
439         /* Send descriptors from parent to child. */
440         CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
441         CHECK((pid = fork()) >= 0);
442         if (pid == 0) {
443                 CHECK(close(sp[0]) == 0);
444                 ioctl_tests_recv_0(sp[1]);
445                 CHECK(close(sp[1]) == 0);
446                 exit(0);
447         } else {
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);
452         }
453
454         /* Send descriptors from child to parent. */
455         CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
456         CHECK((pid = fork()) >= 0);
457         if (pid == 0) {
458                 CHECK(close(sp[0]) == 0);
459                 ioctl_tests_send_0(sp[1]);
460                 CHECK(close(sp[1]) == 0);
461                 exit(0);
462         } else {
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);
467         }
468
469         exit(0);
470 }