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