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