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