xref: /freebsd/lib/libcasper/services/cap_fileargs/tests/fileargs_test.c (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
1 /*-
2  * Copyright (c) 2021 Mariusz Zaborski <oshogbo@FreeBSD.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
14  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
15  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23  * POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include <sys/cdefs.h>
27 #include <sys/param.h>
28 #include <sys/capsicum.h>
29 #include <sys/stat.h>
30 
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <stdio.h>
34 
35 #include <atf-c.h>
36 
37 #include <libcasper.h>
38 #include <casper/cap_fileargs.h>
39 
40 #include "freebsd_test_suite/macros.h"
41 
42 #define MAX_FILES		200
43 
44 static char *files[MAX_FILES];
45 static int fds[MAX_FILES];
46 
47 #define	TEST_FILE	"/etc/passwd"
48 
49 static void
50 check_capsicum(void)
51 {
52 	ATF_REQUIRE_FEATURE("security_capabilities");
53 	ATF_REQUIRE_FEATURE("security_capability_mode");
54 }
55 
56 static void
57 prepare_files(size_t num, bool create)
58 {
59 	const char template[] = "testsfiles.XXXXXXXX";
60 	size_t i;
61 
62 	for (i = 0; i < num; i++) {
63 		files[i] = calloc(1, sizeof(template));
64 		ATF_REQUIRE(files[i] != NULL);
65 		strncpy(files[i], template, sizeof(template) - 1);
66 
67 		if (create) {
68 			fds[i] = mkstemp(files[i]);
69 			ATF_REQUIRE(fds[i] >= 0);
70 		} else {
71 			fds[i] = -1;
72 			ATF_REQUIRE(mktemp(files[i]) != NULL);
73 		}
74 	}
75 }
76 
77 static void
78 clear_files(void)
79 {
80 	size_t i;
81 
82 
83 	for (i = 0; files[i] != NULL; i++) {
84 		unlink(files[i]);
85 		free(files[i]);
86 		if (fds[i] != -1)
87 			close(fds[i]);
88 	}
89 }
90 
91 static int
92 test_file_open(fileargs_t *fa, const char *file, int *fdp)
93 {
94 	int fd;
95 
96 	fd = fileargs_open(fa, file);
97 	if (fd < 0)
98 		return (errno);
99 
100 	if (fdp != NULL) {
101 		*fdp = fd;
102 	}
103 
104 	return (0);
105 }
106 
107 static int
108 test_file_fopen(fileargs_t *fa, const char *file, const char *mode,
109     FILE **retfile)
110 {
111 	FILE *pfile;
112 
113 	pfile = fileargs_fopen(fa, file, mode);
114 	if (pfile == NULL)
115 		return (errno);
116 
117 	if (retfile != NULL) {
118 		*retfile = pfile;
119 	}
120 
121 	return (0);
122 }
123 
124 static int
125 test_file_lstat(fileargs_t *fa, const char *file)
126 {
127 	struct stat fasb, origsb;
128 	bool equals;
129 
130 	if (fileargs_lstat(fa, file, &fasb) < 0)
131 		return (errno);
132 
133 	ATF_REQUIRE(lstat(file, &origsb) == 0);
134 
135 	equals = true;
136 	equals &= (origsb.st_dev == fasb.st_dev);
137 	equals &= (origsb.st_ino == fasb.st_ino);
138 	equals &= (origsb.st_nlink == fasb.st_nlink);
139 	equals &= (origsb.st_flags == fasb.st_flags);
140 	equals &= (memcmp(&origsb.st_ctim, &fasb.st_ctim,
141 	    sizeof(fasb.st_ctim)) == 0);
142 	equals &= (memcmp(&origsb.st_birthtim, &fasb.st_birthtim,
143 	    sizeof(fasb.st_birthtim)) == 0);
144 	if (!equals) {
145 		return (EINVAL);
146 	}
147 
148 	return (0);
149 }
150 
151 static int
152 test_file_realpath_static(fileargs_t *fa, const char *file)
153 {
154 	char fapath[PATH_MAX], origpath[PATH_MAX];
155 
156 	if (fileargs_realpath(fa, file, fapath) == NULL)
157 		return (errno);
158 
159 	ATF_REQUIRE(realpath(file, origpath) != NULL);
160 
161 	if (strcmp(fapath, origpath) != 0)
162 		return (EINVAL);
163 
164 	return (0);
165 }
166 
167 static int
168 test_file_realpath_alloc(fileargs_t *fa, const char *file)
169 {
170 	char *fapath, *origpath;
171 	int serrno;
172 
173 	fapath = fileargs_realpath(fa, file, NULL);
174 	if (fapath == NULL)
175 		return (errno);
176 
177 	origpath = realpath(file, NULL);
178 	ATF_REQUIRE(origpath != NULL);
179 
180 	serrno = 0;
181 	if (strcmp(fapath, origpath) != 0)
182 		serrno = EINVAL;
183 
184 	free(fapath);
185 	free(origpath);
186 
187 	return (serrno);
188 }
189 
190 static int
191 test_file_realpath(fileargs_t *fa, const char *file)
192 {
193 	int serrno;
194 
195 	serrno = test_file_realpath_static(fa, file);
196 	if (serrno != 0)
197 		return serrno;
198 
199 	return (test_file_realpath_alloc(fa, file));
200 }
201 
202 static int
203 test_file_mode(int fd, int mode)
204 {
205 	int flags;
206 
207 	flags = fcntl(fd, F_GETFL, 0);
208 	if (flags < 0)
209 		return (errno);
210 
211 	if ((flags & O_ACCMODE) != mode)
212 		return (errno);
213 
214 	return (0);
215 }
216 
217 static bool
218 test_file_cap(int fd, cap_rights_t *rights)
219 {
220 	cap_rights_t fdrights;
221 
222 	ATF_REQUIRE(cap_rights_get(fd, &fdrights) == 0);
223 
224 	return (cap_rights_contains(&fdrights, rights));
225 }
226 
227 static int
228 test_file_write(int fd)
229 {
230 	char buf;
231 
232 	buf = 't';
233 	if (write(fd, &buf, sizeof(buf)) != sizeof(buf)) {
234 		return (errno);
235 	}
236 
237 	return (0);
238 }
239 
240 static int
241 test_file_read(int fd)
242 {
243 	char buf;
244 
245 	if (read(fd, &buf, sizeof(buf)) < 0) {
246 		return (errno);
247 	}
248 
249 	return (0);
250 }
251 
252 static int
253 test_file_fwrite(FILE *pfile)
254 {
255 	char buf;
256 
257 	buf = 't';
258 	if (fwrite(&buf, sizeof(buf), 1, pfile) != sizeof(buf))
259 		return (errno);
260 
261 	return (0);
262 }
263 
264 static int
265 test_file_fread(FILE *pfile)
266 {
267 	char buf;
268 	int ret, serrno;
269 
270 	errno = 0;
271 	ret = fread(&buf, sizeof(buf), 1, pfile);
272 	serrno = errno;
273 	if (ret < 0) {
274 		return (serrno);
275 	} else if (ret == 0 && feof(pfile) == 0) {
276 		return (serrno != 0 ? serrno : EINVAL);
277 	}
278 
279 	return (0);
280 }
281 
282 ATF_TC_WITH_CLEANUP(fileargs__open_read);
283 ATF_TC_HEAD(fileargs__open_read, tc) {}
284 ATF_TC_BODY(fileargs__open_read, tc)
285 {
286 	cap_rights_t rights, norights;
287 	fileargs_t *fa;
288 	size_t i;
289 	int fd;
290 
291 	check_capsicum();
292 
293 	prepare_files(MAX_FILES, true);
294 
295 	cap_rights_init(&rights, CAP_READ | CAP_FCNTL);
296 	cap_rights_init(&norights, CAP_WRITE);
297 	fa = fileargs_init(MAX_FILES, files, O_RDONLY, 0, &rights,
298 	    FA_OPEN);
299 	ATF_REQUIRE(fa != NULL);
300 
301 	for (i = 0; i < MAX_FILES; i++) {
302 		/* ALLOWED */
303 		/* We open file twice to check if we can. */
304 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
305 		ATF_REQUIRE(close(fd) == 0);
306 
307 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
308 		ATF_REQUIRE(test_file_mode(fd, O_RDONLY) == 0);
309 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
310 		ATF_REQUIRE(test_file_read(fd) == 0);
311 
312 		/* DISALLOWED */
313 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
314 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, NULL) == ENOTCAPABLE);
315 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
316 		ATF_REQUIRE(test_file_write(fd) == ENOTCAPABLE);
317 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
318 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
319 
320 		/* CLOSE */
321 		ATF_REQUIRE(close(fd) == 0);
322 	}
323 }
324 ATF_TC_CLEANUP(fileargs__open_read, tc)
325 {
326 	clear_files();
327 }
328 
329 ATF_TC_WITH_CLEANUP(fileargs__open_write);
330 ATF_TC_HEAD(fileargs__open_write, tc) {}
331 ATF_TC_BODY(fileargs__open_write, tc)
332 {
333 	cap_rights_t rights, norights;
334 	fileargs_t *fa;
335 	size_t i;
336 	int fd;
337 
338 	check_capsicum();
339 
340 	prepare_files(MAX_FILES, true);
341 
342 	cap_rights_init(&rights, CAP_WRITE | CAP_FCNTL);
343 	cap_rights_init(&norights, CAP_READ);
344 	fa = fileargs_init(MAX_FILES, files, O_WRONLY, 0, &rights,
345 	    FA_OPEN);
346 	ATF_REQUIRE(fa != NULL);
347 
348 	for (i = 0; i < MAX_FILES; i++) {
349 		/* ALLOWED */
350 		/* We open file twice to check if we can. */
351 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
352 		ATF_REQUIRE(close(fd) == 0);
353 
354 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
355 		ATF_REQUIRE(test_file_mode(fd, O_WRONLY) == 0);
356 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
357 		ATF_REQUIRE(test_file_write(fd) == 0);
358 
359 		/* DISALLOWED */
360 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
361 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, NULL) == ENOTCAPABLE);
362 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
363 		ATF_REQUIRE(test_file_read(fd) == ENOTCAPABLE);
364 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
365 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
366 
367 		/* CLOSE */
368 		ATF_REQUIRE(close(fd) == 0);
369 	}
370 }
371 ATF_TC_CLEANUP(fileargs__open_write, tc)
372 {
373 	clear_files();
374 }
375 
376 ATF_TC_WITH_CLEANUP(fileargs__open_create);
377 ATF_TC_HEAD(fileargs__open_create, tc) {}
378 ATF_TC_BODY(fileargs__open_create, tc)
379 {
380 	cap_rights_t rights, norights;
381 	fileargs_t *fa;
382 	size_t i;
383 	int fd;
384 
385 	check_capsicum();
386 
387 	prepare_files(MAX_FILES, false);
388 
389 	cap_rights_init(&rights, CAP_WRITE | CAP_FCNTL | CAP_READ);
390 	cap_rights_init(&norights, CAP_FCHMOD);
391 	fa = fileargs_init(MAX_FILES, files, O_RDWR | O_CREAT, 666,
392 	    &rights, FA_OPEN);
393 	ATF_REQUIRE(fa != NULL);
394 
395 	for (i = 0; i < MAX_FILES; i++) {
396 		/* ALLOWED */
397 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
398 
399 		ATF_REQUIRE(test_file_mode(fd, O_RDWR) == 0);
400 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
401 		ATF_REQUIRE(test_file_write(fd) == 0);
402 		ATF_REQUIRE(test_file_read(fd) == 0);
403 
404 		/* DISALLOWED */
405 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
406 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, NULL) == ENOTCAPABLE);
407 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
408 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
409 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
410 
411 		/* CLOSE */
412 		ATF_REQUIRE(close(fd) == 0);
413 	}
414 }
415 ATF_TC_CLEANUP(fileargs__open_create, tc)
416 {
417 	clear_files();
418 }
419 
420 ATF_TC_WITH_CLEANUP(fileargs__open_with_casper);
421 ATF_TC_HEAD(fileargs__open_with_casper, tc) {}
422 ATF_TC_BODY(fileargs__open_with_casper, tc)
423 {
424 	cap_channel_t *capcas;
425 	cap_rights_t rights;
426 	fileargs_t *fa;
427 	size_t i;
428 	int fd;
429 
430 	check_capsicum();
431 
432 	prepare_files(MAX_FILES, true);
433 
434 	capcas = cap_init();
435 	ATF_REQUIRE(capcas != NULL);
436 
437 	cap_rights_init(&rights, CAP_READ);
438 	fa = fileargs_cinit(capcas, MAX_FILES, files, O_RDONLY, 0, &rights,
439 	    FA_OPEN);
440 	ATF_REQUIRE(fa != NULL);
441 
442 	for (i = 0; i < MAX_FILES; i++) {
443 		/* ALLOWED */
444 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
445 		ATF_REQUIRE(test_file_read(fd) == 0);
446 
447 		/* CLOSE */
448 		ATF_REQUIRE(close(fd) == 0);
449 	}
450 }
451 ATF_TC_CLEANUP(fileargs__open_with_casper, tc)
452 {
453 	clear_files();
454 }
455 
456 ATF_TC_WITH_CLEANUP(fileargs__fopen_read);
457 ATF_TC_HEAD(fileargs__fopen_read, tc) {}
458 ATF_TC_BODY(fileargs__fopen_read, tc)
459 {
460 	cap_rights_t rights, norights;
461 	fileargs_t *fa;
462 	size_t i;
463 	FILE *pfile;
464 	int fd;
465 
466 	check_capsicum();
467 
468 	prepare_files(MAX_FILES, true);
469 
470 	cap_rights_init(&rights, CAP_READ | CAP_FCNTL);
471 	cap_rights_init(&norights, CAP_WRITE);
472 	fa = fileargs_init(MAX_FILES, files, O_RDONLY, 0, &rights,
473 	    FA_OPEN);
474 	ATF_REQUIRE(fa != NULL);
475 
476 	for (i = 0; i < MAX_FILES; i++) {
477 		/* ALLOWED */
478 		/* We fopen file twice to check if we can. */
479 		ATF_REQUIRE(test_file_fopen(fa, files[i], "r", &pfile) == 0);
480 		ATF_REQUIRE(fclose(pfile) == 0);
481 
482 		ATF_REQUIRE(test_file_fopen(fa, files[i], "r", &pfile) == 0);
483 		fd = fileno(pfile);
484 		ATF_REQUIRE(test_file_mode(fd, O_RDONLY) == 0);
485 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
486 		ATF_REQUIRE(test_file_fread(pfile) == 0);
487 
488 		/* DISALLOWED */
489 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
490 		ATF_REQUIRE(test_file_fopen(fa, TEST_FILE, "r", NULL) ==
491 		    ENOTCAPABLE);
492 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
493 		ATF_REQUIRE(test_file_fwrite(pfile) == EBADF);
494 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
495 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
496 
497 		/* CLOSE */
498 		ATF_REQUIRE(fclose(pfile) == 0);
499 	}
500 }
501 ATF_TC_CLEANUP(fileargs__fopen_read, tc)
502 {
503 	clear_files();
504 }
505 
506 ATF_TC_WITH_CLEANUP(fileargs__fopen_write);
507 ATF_TC_HEAD(fileargs__fopen_write, tc) {}
508 ATF_TC_BODY(fileargs__fopen_write, tc)
509 {
510 	cap_rights_t rights, norights;
511 	fileargs_t *fa;
512 	size_t i;
513 	FILE *pfile;
514 	int fd;
515 
516 	check_capsicum();
517 
518 	prepare_files(MAX_FILES, true);
519 
520 	cap_rights_init(&rights, CAP_WRITE | CAP_FCNTL);
521 	cap_rights_init(&norights, CAP_READ);
522 	fa = fileargs_init(MAX_FILES, files, O_WRONLY, 0, &rights,
523 	    FA_OPEN);
524 	ATF_REQUIRE(fa != NULL);
525 
526 	for (i = 0; i < MAX_FILES; i++) {
527 		/* ALLOWED */
528 		/* We fopen file twice to check if we can. */
529 		ATF_REQUIRE(test_file_fopen(fa, files[i], "w", &pfile) == 0);
530 		ATF_REQUIRE(fclose(pfile) == 0);
531 
532 		ATF_REQUIRE(test_file_fopen(fa, files[i], "w", &pfile) == 0);
533 		fd = fileno(pfile);
534 		ATF_REQUIRE(test_file_mode(fd, O_WRONLY) == 0);
535 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
536 		ATF_REQUIRE(test_file_fwrite(pfile) == 0);
537 
538 		/* DISALLOWED */
539 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
540 		ATF_REQUIRE(test_file_fopen(fa, TEST_FILE, "w", NULL) ==
541 		    ENOTCAPABLE);
542 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
543 		ATF_REQUIRE(test_file_fread(pfile) == EBADF);
544 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
545 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
546 
547 		/* CLOSE */
548 		ATF_REQUIRE(fclose(pfile) == 0);
549 	}
550 }
551 ATF_TC_CLEANUP(fileargs__fopen_write, tc)
552 {
553 	clear_files();
554 }
555 
556 ATF_TC_WITH_CLEANUP(fileargs__fopen_create);
557 ATF_TC_HEAD(fileargs__fopen_create, tc) {}
558 ATF_TC_BODY(fileargs__fopen_create, tc)
559 {
560 	cap_rights_t rights;
561 	fileargs_t *fa;
562 	size_t i;
563 	FILE *pfile;
564 	int fd;
565 
566 	check_capsicum();
567 
568 	prepare_files(MAX_FILES, false);
569 
570 	cap_rights_init(&rights, CAP_READ | CAP_WRITE | CAP_FCNTL);
571 	fa = fileargs_init(MAX_FILES, files, O_RDWR | O_CREAT, 0, &rights,
572 	    FA_OPEN);
573 	ATF_REQUIRE(fa != NULL);
574 
575 	for (i = 0; i < MAX_FILES; i++) {
576 		/* ALLOWED */
577 		/* We fopen file twice to check if we can. */
578 		ATF_REQUIRE(test_file_fopen(fa, files[i], "w+", &pfile) == 0);
579 		fd = fileno(pfile);
580 		ATF_REQUIRE(test_file_mode(fd, O_RDWR) == 0);
581 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
582 		ATF_REQUIRE(test_file_fwrite(pfile) == 0);
583 		ATF_REQUIRE(test_file_fread(pfile) == 0);
584 
585 		/* DISALLOWED */
586 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
587 		ATF_REQUIRE(test_file_fopen(fa, TEST_FILE, "w+", NULL) ==
588 		    ENOTCAPABLE);
589 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
590 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
591 
592 		/* CLOSE */
593 		ATF_REQUIRE(fclose(pfile) == 0);
594 	}
595 }
596 ATF_TC_CLEANUP(fileargs__fopen_create, tc)
597 {
598 	clear_files();
599 }
600 
601 ATF_TC_WITH_CLEANUP(fileargs__lstat);
602 ATF_TC_HEAD(fileargs__lstat, tc) {}
603 ATF_TC_BODY(fileargs__lstat, tc)
604 {
605 	fileargs_t *fa;
606 	size_t i;
607 	int fd;
608 
609 	check_capsicum();
610 
611 	prepare_files(MAX_FILES, true);
612 
613 	fa = fileargs_init(MAX_FILES, files, 0, 0, NULL, FA_LSTAT);
614 	ATF_REQUIRE(fa != NULL);
615 
616 	for (i = 0; i < MAX_FILES; i++) {
617 		/* ALLOWED */
618 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == 0);
619 
620 		/* DISALLOWED */
621 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == ENOTCAPABLE);
622 		ATF_REQUIRE(test_file_lstat(fa, TEST_FILE) == ENOTCAPABLE);
623 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, &fd) == ENOTCAPABLE);
624 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
625 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
626 	}
627 }
628 ATF_TC_CLEANUP(fileargs__lstat, tc)
629 {
630 	clear_files();
631 }
632 
633 ATF_TC_WITH_CLEANUP(fileargs__realpath);
634 ATF_TC_HEAD(fileargs__realpath, tc) {}
635 ATF_TC_BODY(fileargs__realpath, tc)
636 {
637 	fileargs_t *fa;
638 	size_t i;
639 	int fd;
640 
641 	prepare_files(MAX_FILES, true);
642 
643 	fa = fileargs_init(MAX_FILES, files, 0, 0, NULL, FA_REALPATH);
644 	ATF_REQUIRE(fa != NULL);
645 
646 	for (i = 0; i < MAX_FILES; i++) {
647 		/* ALLOWED */
648 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == 0);
649 
650 		/* DISALLOWED */
651 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == ENOTCAPABLE);
652 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
653 		ATF_REQUIRE(test_file_lstat(fa, TEST_FILE) == ENOTCAPABLE);
654 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, &fd) == ENOTCAPABLE);
655 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
656 	}
657 }
658 ATF_TC_CLEANUP(fileargs__realpath, tc)
659 {
660 	clear_files();
661 }
662 
663 ATF_TC_WITH_CLEANUP(fileargs__open_lstat);
664 ATF_TC_HEAD(fileargs__open_lstat, tc) {}
665 ATF_TC_BODY(fileargs__open_lstat, tc)
666 {
667 	cap_rights_t rights, norights;
668 	fileargs_t *fa;
669 	size_t i;
670 	int fd;
671 
672 	check_capsicum();
673 
674 	prepare_files(MAX_FILES, true);
675 
676 	cap_rights_init(&rights, CAP_READ | CAP_FCNTL);
677 	cap_rights_init(&norights, CAP_WRITE);
678 	fa = fileargs_init(MAX_FILES, files, O_RDONLY, 0, &rights,
679 	    FA_OPEN | FA_LSTAT);
680 	ATF_REQUIRE(fa != NULL);
681 
682 	for (i = 0; i < MAX_FILES; i++) {
683 		/* ALLOWED */
684 		/* We open file twice to check if we can. */
685 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == 0);
686 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
687 		ATF_REQUIRE(close(fd) == 0);
688 
689 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
690 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == 0);
691 		ATF_REQUIRE(test_file_mode(fd, O_RDONLY) == 0);
692 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
693 		ATF_REQUIRE(test_file_read(fd) == 0);
694 
695 		/* DISALLOWED */
696 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, NULL) == ENOTCAPABLE);
697 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
698 		ATF_REQUIRE(test_file_write(fd) == ENOTCAPABLE);
699 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == ENOTCAPABLE);
700 		ATF_REQUIRE(test_file_realpath(fa, TEST_FILE) == ENOTCAPABLE);
701 
702 		/* CLOSE */
703 		ATF_REQUIRE(close(fd) == 0);
704 	}
705 }
706 ATF_TC_CLEANUP(fileargs__open_lstat, tc)
707 {
708 	clear_files();
709 }
710 
711 ATF_TC_WITH_CLEANUP(fileargs__open_realpath);
712 ATF_TC_HEAD(fileargs__open_realpath, tc) {}
713 ATF_TC_BODY(fileargs__open_realpath, tc)
714 {
715 	cap_rights_t rights, norights;
716 	fileargs_t *fa;
717 	size_t i;
718 	int fd;
719 
720 	check_capsicum();
721 
722 	prepare_files(MAX_FILES, true);
723 
724 	cap_rights_init(&rights, CAP_READ | CAP_FCNTL);
725 	cap_rights_init(&norights, CAP_WRITE);
726 	fa = fileargs_init(MAX_FILES, files, O_RDONLY, 0, &rights,
727 	    FA_OPEN | FA_REALPATH);
728 	ATF_REQUIRE(fa != NULL);
729 
730 	for (i = 0; i < MAX_FILES; i++) {
731 		/* ALLOWED */
732 		/* We open file twice to check if we can. */
733 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == 0);
734 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
735 		ATF_REQUIRE(close(fd) == 0);
736 
737 		ATF_REQUIRE(test_file_open(fa, files[i], &fd) == 0);
738 		ATF_REQUIRE(test_file_realpath(fa, files[i]) == 0);
739 		ATF_REQUIRE(test_file_mode(fd, O_RDONLY) == 0);
740 		ATF_REQUIRE(test_file_cap(fd, &rights) == true);
741 		ATF_REQUIRE(test_file_read(fd) == 0);
742 
743 		/* DISALLOWED */
744 		ATF_REQUIRE(test_file_open(fa, TEST_FILE, NULL) == ENOTCAPABLE);
745 		ATF_REQUIRE(test_file_cap(fd, &norights) == false);
746 		ATF_REQUIRE(test_file_write(fd) == ENOTCAPABLE);
747 		ATF_REQUIRE(test_file_lstat(fa, files[i]) == ENOTCAPABLE);
748 
749 		/* CLOSE */
750 		ATF_REQUIRE(close(fd) == 0);
751 	}
752 }
753 ATF_TC_CLEANUP(fileargs__open_realpath, tc)
754 {
755 	clear_files();
756 }
757 
758 ATF_TP_ADD_TCS(tp)
759 {
760 
761 	ATF_TP_ADD_TC(tp, fileargs__open_create);
762 	ATF_TP_ADD_TC(tp, fileargs__open_read);
763 	ATF_TP_ADD_TC(tp, fileargs__open_write);
764 	ATF_TP_ADD_TC(tp, fileargs__open_with_casper);
765 
766 	ATF_TP_ADD_TC(tp, fileargs__fopen_create);
767 	ATF_TP_ADD_TC(tp, fileargs__fopen_read);
768 	ATF_TP_ADD_TC(tp, fileargs__fopen_write);
769 
770 	ATF_TP_ADD_TC(tp, fileargs__lstat);
771 
772 	ATF_TP_ADD_TC(tp, fileargs__realpath);
773 
774 	ATF_TP_ADD_TC(tp, fileargs__open_lstat);
775 	ATF_TP_ADD_TC(tp, fileargs__open_realpath);
776 
777 	return (atf_no_error());
778 }
779