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