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
check_capsicum(void)49 check_capsicum(void)
50 {
51 ATF_REQUIRE_FEATURE("security_capabilities");
52 ATF_REQUIRE_FEATURE("security_capability_mode");
53 }
54
55 static void
prepare_files(size_t num,bool create)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
clear_files(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
test_file_open(fileargs_t * fa,const char * file,int * fdp)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
test_file_fopen(fileargs_t * fa,const char * file,const char * mode,FILE ** retfile)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
test_file_lstat(fileargs_t * fa,const char * file)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
test_file_realpath_static(fileargs_t * fa,const char * file)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
test_file_realpath_alloc(fileargs_t * fa,const char * file)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
test_file_realpath(fileargs_t * fa,const char * file)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
test_file_mode(int fd,int mode)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
test_file_cap(int fd,cap_rights_t * rights)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
test_file_write(int fd)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
test_file_read(int fd)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
test_file_fwrite(FILE * pfile)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
test_file_fread(FILE * pfile)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);
ATF_TC_HEAD(fileargs__open_read,tc)282 ATF_TC_HEAD(fileargs__open_read, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_read,tc)323 ATF_TC_CLEANUP(fileargs__open_read, tc)
324 {
325 clear_files();
326 }
327
328 ATF_TC_WITH_CLEANUP(fileargs__open_write);
ATF_TC_HEAD(fileargs__open_write,tc)329 ATF_TC_HEAD(fileargs__open_write, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_write,tc)370 ATF_TC_CLEANUP(fileargs__open_write, tc)
371 {
372 clear_files();
373 }
374
375 ATF_TC_WITH_CLEANUP(fileargs__open_create);
ATF_TC_HEAD(fileargs__open_create,tc)376 ATF_TC_HEAD(fileargs__open_create, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_create,tc)414 ATF_TC_CLEANUP(fileargs__open_create, tc)
415 {
416 clear_files();
417 }
418
419 ATF_TC_WITH_CLEANUP(fileargs__open_with_casper);
ATF_TC_HEAD(fileargs__open_with_casper,tc)420 ATF_TC_HEAD(fileargs__open_with_casper, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_with_casper,tc)450 ATF_TC_CLEANUP(fileargs__open_with_casper, tc)
451 {
452 clear_files();
453 }
454
455 ATF_TC_WITH_CLEANUP(fileargs__fopen_read);
ATF_TC_HEAD(fileargs__fopen_read,tc)456 ATF_TC_HEAD(fileargs__fopen_read, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__fopen_read,tc)500 ATF_TC_CLEANUP(fileargs__fopen_read, tc)
501 {
502 clear_files();
503 }
504
505 ATF_TC_WITH_CLEANUP(fileargs__fopen_write);
ATF_TC_HEAD(fileargs__fopen_write,tc)506 ATF_TC_HEAD(fileargs__fopen_write, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__fopen_write,tc)550 ATF_TC_CLEANUP(fileargs__fopen_write, tc)
551 {
552 clear_files();
553 }
554
555 ATF_TC_WITH_CLEANUP(fileargs__fopen_create);
ATF_TC_HEAD(fileargs__fopen_create,tc)556 ATF_TC_HEAD(fileargs__fopen_create, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__fopen_create,tc)595 ATF_TC_CLEANUP(fileargs__fopen_create, tc)
596 {
597 clear_files();
598 }
599
600 ATF_TC_WITH_CLEANUP(fileargs__lstat);
ATF_TC_HEAD(fileargs__lstat,tc)601 ATF_TC_HEAD(fileargs__lstat, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__lstat,tc)627 ATF_TC_CLEANUP(fileargs__lstat, tc)
628 {
629 clear_files();
630 }
631
632 ATF_TC_WITH_CLEANUP(fileargs__realpath);
ATF_TC_HEAD(fileargs__realpath,tc)633 ATF_TC_HEAD(fileargs__realpath, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__realpath,tc)657 ATF_TC_CLEANUP(fileargs__realpath, tc)
658 {
659 clear_files();
660 }
661
662 ATF_TC_WITH_CLEANUP(fileargs__open_lstat);
ATF_TC_HEAD(fileargs__open_lstat,tc)663 ATF_TC_HEAD(fileargs__open_lstat, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_lstat,tc)705 ATF_TC_CLEANUP(fileargs__open_lstat, tc)
706 {
707 clear_files();
708 }
709
710 ATF_TC_WITH_CLEANUP(fileargs__open_realpath);
ATF_TC_HEAD(fileargs__open_realpath,tc)711 ATF_TC_HEAD(fileargs__open_realpath, tc) {}
ATF_TC_BODY(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 }
ATF_TC_CLEANUP(fileargs__open_realpath,tc)752 ATF_TC_CLEANUP(fileargs__open_realpath, tc)
753 {
754 clear_files();
755 }
756
ATF_TP_ADD_TCS(tp)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