1 /*-
2 * Copyright (c) 2021 Mariusz Zaborski <[email protected]>
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
check_capsicum(void)50 check_capsicum(void)
51 {
52 ATF_REQUIRE_FEATURE("security_capabilities");
53 ATF_REQUIRE_FEATURE("security_capability_mode");
54 }
55
56 static void
prepare_files(size_t num,bool create)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
clear_files(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
test_file_open(fileargs_t * fa,const char * file,int * fdp)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
test_file_fopen(fileargs_t * fa,const char * file,const char * mode,FILE ** retfile)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
test_file_lstat(fileargs_t * fa,const char * file)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
test_file_realpath_static(fileargs_t * fa,const char * file)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
test_file_realpath_alloc(fileargs_t * fa,const char * file)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
test_file_realpath(fileargs_t * fa,const char * file)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
test_file_mode(int fd,int mode)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
test_file_cap(int fd,cap_rights_t * rights)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
test_file_write(int fd)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
test_file_read(int fd)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
test_file_fwrite(FILE * pfile)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
test_file_fread(FILE * pfile)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);
ATF_TC_HEAD(fileargs__open_read,tc)283 ATF_TC_HEAD(fileargs__open_read, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_read,tc)324 ATF_TC_CLEANUP(fileargs__open_read, tc)
325 {
326 clear_files();
327 }
328
329 ATF_TC_WITH_CLEANUP(fileargs__open_write);
ATF_TC_HEAD(fileargs__open_write,tc)330 ATF_TC_HEAD(fileargs__open_write, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_write,tc)371 ATF_TC_CLEANUP(fileargs__open_write, tc)
372 {
373 clear_files();
374 }
375
376 ATF_TC_WITH_CLEANUP(fileargs__open_create);
ATF_TC_HEAD(fileargs__open_create,tc)377 ATF_TC_HEAD(fileargs__open_create, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_create,tc)415 ATF_TC_CLEANUP(fileargs__open_create, tc)
416 {
417 clear_files();
418 }
419
420 ATF_TC_WITH_CLEANUP(fileargs__open_with_casper);
ATF_TC_HEAD(fileargs__open_with_casper,tc)421 ATF_TC_HEAD(fileargs__open_with_casper, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_with_casper,tc)451 ATF_TC_CLEANUP(fileargs__open_with_casper, tc)
452 {
453 clear_files();
454 }
455
456 ATF_TC_WITH_CLEANUP(fileargs__fopen_read);
ATF_TC_HEAD(fileargs__fopen_read,tc)457 ATF_TC_HEAD(fileargs__fopen_read, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__fopen_read,tc)501 ATF_TC_CLEANUP(fileargs__fopen_read, tc)
502 {
503 clear_files();
504 }
505
506 ATF_TC_WITH_CLEANUP(fileargs__fopen_write);
ATF_TC_HEAD(fileargs__fopen_write,tc)507 ATF_TC_HEAD(fileargs__fopen_write, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__fopen_write,tc)551 ATF_TC_CLEANUP(fileargs__fopen_write, tc)
552 {
553 clear_files();
554 }
555
556 ATF_TC_WITH_CLEANUP(fileargs__fopen_create);
ATF_TC_HEAD(fileargs__fopen_create,tc)557 ATF_TC_HEAD(fileargs__fopen_create, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__fopen_create,tc)596 ATF_TC_CLEANUP(fileargs__fopen_create, tc)
597 {
598 clear_files();
599 }
600
601 ATF_TC_WITH_CLEANUP(fileargs__lstat);
ATF_TC_HEAD(fileargs__lstat,tc)602 ATF_TC_HEAD(fileargs__lstat, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__lstat,tc)628 ATF_TC_CLEANUP(fileargs__lstat, tc)
629 {
630 clear_files();
631 }
632
633 ATF_TC_WITH_CLEANUP(fileargs__realpath);
ATF_TC_HEAD(fileargs__realpath,tc)634 ATF_TC_HEAD(fileargs__realpath, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__realpath,tc)658 ATF_TC_CLEANUP(fileargs__realpath, tc)
659 {
660 clear_files();
661 }
662
663 ATF_TC_WITH_CLEANUP(fileargs__open_lstat);
ATF_TC_HEAD(fileargs__open_lstat,tc)664 ATF_TC_HEAD(fileargs__open_lstat, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_lstat,tc)706 ATF_TC_CLEANUP(fileargs__open_lstat, tc)
707 {
708 clear_files();
709 }
710
711 ATF_TC_WITH_CLEANUP(fileargs__open_realpath);
ATF_TC_HEAD(fileargs__open_realpath,tc)712 ATF_TC_HEAD(fileargs__open_realpath, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_realpath,tc)753 ATF_TC_CLEANUP(fileargs__open_realpath, tc)
754 {
755 clear_files();
756 }
757
ATF_TP_ADD_TCS(tp)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