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