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