1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2021 The FreeBSD Foundation 5 * 6 * This software was developed by Mark Johnston under sponsorship from 7 * the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions are 11 * met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * Basic regression tests for handling of O_PATH descriptors. 33 */ 34 35 #include <sys/param.h> 36 #include <sys/capsicum.h> 37 #include <sys/event.h> 38 #include <sys/ioctl.h> 39 #include <sys/memrange.h> 40 #include <sys/mman.h> 41 #include <sys/ptrace.h> 42 #include <sys/socket.h> 43 #include <sys/stat.h> 44 #include <sys/time.h> 45 #include <sys/uio.h> 46 #include <sys/un.h> 47 #include <sys/wait.h> 48 49 #include <aio.h> 50 #include <dirent.h> 51 #include <errno.h> 52 #include <fcntl.h> 53 #include <poll.h> 54 #include <signal.h> 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <unistd.h> 58 59 #include <atf-c.h> 60 61 #define FMT_ERR(s) s ": %s", strerror(errno) 62 63 #define CHECKED_CLOSE(fd) \ 64 ATF_REQUIRE_MSG(close(fd) == 0, FMT_ERR("close")) 65 66 /* Create a temporary regular file containing some data. */ 67 static void 68 mktfile(char path[PATH_MAX], const char *template) 69 { 70 char buf[BUFSIZ]; 71 int fd; 72 73 snprintf(path, PATH_MAX, "%s", template); 74 fd = mkstemp(path); 75 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("mkstemp")); 76 memset(buf, 0, sizeof(buf)); 77 ATF_REQUIRE_MSG(write(fd, buf, sizeof(buf)) == sizeof(buf), 78 FMT_ERR("write")); 79 CHECKED_CLOSE(fd); 80 } 81 82 /* Make a temporary directory. */ 83 static void 84 mktdir(char path[PATH_MAX], const char *template) 85 { 86 snprintf(path, PATH_MAX, "%s", template); 87 ATF_REQUIRE_MSG(mkdtemp(path) == path, FMT_ERR("mkdtemp")); 88 } 89 90 /* Wait for a child process to exit with status 0. */ 91 static void 92 waitchild(pid_t child, int exstatus) 93 { 94 int error, status; 95 96 error = waitpid(child, &status, 0); 97 ATF_REQUIRE_MSG(error != -1, FMT_ERR("waitpid")); 98 ATF_REQUIRE_MSG(WIFEXITED(status), "child exited abnormally, status %d", 99 status); 100 ATF_REQUIRE_MSG(WEXITSTATUS(status) == exstatus, 101 "child exit status is %d, expected %d", 102 WEXITSTATUS(status), exstatus); 103 } 104 105 ATF_TC_WITHOUT_HEAD(path_access); 106 ATF_TC_BODY(path_access, tc) 107 { 108 char path[PATH_MAX]; 109 struct stat sb; 110 struct timespec ts[2]; 111 struct timeval tv[2]; 112 int pathfd; 113 114 mktfile(path, "path_access.XXXXXX"); 115 116 pathfd = open(path, O_PATH); 117 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 118 119 ATF_REQUIRE_ERRNO(EBADF, fchmod(pathfd, 0666) == -1); 120 ATF_REQUIRE_ERRNO(EBADF, fchown(pathfd, getuid(), getgid()) == -1); 121 ATF_REQUIRE_ERRNO(EBADF, fchflags(pathfd, UF_NODUMP) == -1); 122 memset(tv, 0, sizeof(tv)); 123 ATF_REQUIRE_ERRNO(EBADF, futimes(pathfd, tv) == -1); 124 memset(ts, 0, sizeof(ts)); 125 ATF_REQUIRE_ERRNO(EBADF, futimens(pathfd, ts) == -1); 126 127 /* fpathconf(2) and fstat(2) are permitted. */ 128 ATF_REQUIRE_MSG(fstat(pathfd, &sb) == 0, FMT_ERR("fstat")); 129 ATF_REQUIRE_MSG(fpathconf(pathfd, _PC_LINK_MAX) != -1, 130 FMT_ERR("fpathconf")); 131 132 CHECKED_CLOSE(pathfd); 133 } 134 135 /* Basic tests to verify that AIO operations fail. */ 136 ATF_TC_WITHOUT_HEAD(path_aio); 137 ATF_TC_BODY(path_aio, tc) 138 { 139 struct aiocb aio; 140 char buf[BUFSIZ], path[PATH_MAX]; 141 int pathfd; 142 143 mktfile(path, "path_aio.XXXXXX"); 144 145 pathfd = open(path, O_PATH); 146 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 147 148 memset(&aio, 0, sizeof(aio)); 149 aio.aio_buf = buf; 150 aio.aio_nbytes = sizeof(buf); 151 aio.aio_fildes = pathfd; 152 aio.aio_offset = 0; 153 154 ATF_REQUIRE_ERRNO(EBADF, aio_read(&aio) == -1); 155 ATF_REQUIRE_ERRNO(EBADF, aio_write(&aio) == -1); 156 ATF_REQUIRE_ERRNO(EBADF, aio_fsync(O_SYNC, &aio) == -1); 157 ATF_REQUIRE_ERRNO(EBADF, aio_fsync(O_DSYNC, &aio) == -1); 158 159 CHECKED_CLOSE(pathfd); 160 } 161 162 /* Basic tests to verify that Capsicum restrictions apply to path fds. */ 163 ATF_TC_WITHOUT_HEAD(path_capsicum); 164 ATF_TC_BODY(path_capsicum, tc) 165 { 166 char path[PATH_MAX]; 167 cap_rights_t rights; 168 int truefd; 169 pid_t child; 170 171 mktfile(path, "path_capsicum.XXXXXX"); 172 173 /* Make sure that filesystem namespace restrictions apply to O_PATH. */ 174 child = fork(); 175 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork")); 176 if (child == 0) { 177 if (cap_enter() != 0) 178 _exit(1); 179 if (open(path, O_PATH) >= 0) 180 _exit(2); 181 if (errno != ECAPMODE) 182 _exit(3); 183 if (open("/usr/bin/true", O_PATH | O_EXEC) >= 0) 184 _exit(4); 185 if (errno != ECAPMODE) 186 _exit(5); 187 _exit(0); 188 } 189 waitchild(child, 0); 190 191 /* Make sure that CAP_FEXECVE is required. */ 192 child = fork(); 193 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork")); 194 if (child == 0) { 195 truefd = open("/usr/bin/true", O_PATH | O_EXEC); 196 if (truefd < 0) 197 _exit(1); 198 cap_rights_init(&rights); 199 if (cap_rights_limit(truefd, &rights) != 0) 200 _exit(2); 201 (void)fexecve(truefd, 202 (char * const[]){__DECONST(char *, "/usr/bin/true"), NULL}, 203 NULL); 204 if (errno != ENOTCAPABLE) 205 _exit(3); 206 _exit(4); 207 } 208 waitchild(child, 4); 209 } 210 211 /* 212 * Check that a pathfd can be converted to a regular fd using openat() in 213 * capability mode, but that rights on the pathfd are respected. 214 */ 215 ATF_TC_WITHOUT_HEAD(path_capsicum_empty); 216 ATF_TC_BODY(path_capsicum_empty, tc) 217 { 218 char path[PATH_MAX]; 219 cap_rights_t rights; 220 int dfd, fd, pathfd, pathdfd; 221 222 mktfile(path, "path_capsicum.XXXXXX"); 223 224 pathdfd = open(".", O_PATH); 225 ATF_REQUIRE_MSG(pathdfd >= 0, FMT_ERR("open")); 226 pathfd = open(path, O_PATH); 227 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 228 229 ATF_REQUIRE(cap_enter() == 0); 230 231 dfd = openat(pathdfd, "", O_DIRECTORY | O_EMPTY_PATH); 232 ATF_REQUIRE(dfd >= 0); 233 CHECKED_CLOSE(dfd); 234 235 /* 236 * CAP_READ and CAP_LOOKUP should be sufficient to open a directory. 237 */ 238 cap_rights_init(&rights, CAP_READ, CAP_LOOKUP); 239 ATF_REQUIRE(cap_rights_limit(pathdfd, &rights) == 0); 240 dfd = openat(pathdfd, "", O_DIRECTORY | O_EMPTY_PATH); 241 ATF_REQUIRE(dfd >= 0); 242 CHECKED_CLOSE(dfd); 243 244 /* 245 * ... CAP_READ on its own is not. 246 */ 247 cap_rights_init(&rights, CAP_READ); 248 ATF_REQUIRE(cap_rights_limit(pathdfd, &rights) == 0); 249 dfd = openat(pathdfd, "", O_DIRECTORY | O_EMPTY_PATH); 250 ATF_REQUIRE_ERRNO(ENOTCAPABLE, dfd == -1); 251 252 /* 253 * Now try with a regular file. 254 */ 255 fd = openat(pathfd, "", O_RDWR | O_EMPTY_PATH); 256 ATF_REQUIRE(fd >= 0); 257 CHECKED_CLOSE(fd); 258 259 cap_rights_init(&rights, CAP_READ, CAP_LOOKUP, CAP_WRITE); 260 ATF_REQUIRE(cap_rights_limit(pathfd, &rights) == 0); 261 fd = openat(pathfd, "", O_RDWR | O_EMPTY_PATH | O_APPEND); 262 ATF_REQUIRE(fd >= 0); 263 CHECKED_CLOSE(fd); 264 265 /* 266 * CAP_SEEK is needed to open a file for writing without O_APPEND. 267 */ 268 cap_rights_init(&rights, CAP_READ, CAP_LOOKUP, CAP_WRITE); 269 ATF_REQUIRE(cap_rights_limit(pathfd, &rights) == 0); 270 fd = openat(pathfd, "", O_RDWR | O_EMPTY_PATH); 271 ATF_REQUIRE_ERRNO(ENOTCAPABLE, fd == -1); 272 273 /* 274 * CAP_LOOKUP isn't sufficient to open a file for reading. 275 */ 276 cap_rights_init(&rights, CAP_LOOKUP); 277 ATF_REQUIRE(cap_rights_limit(pathfd, &rights) == 0); 278 fd = openat(pathfd, "", O_RDONLY | O_EMPTY_PATH); 279 ATF_REQUIRE_ERRNO(ENOTCAPABLE, fd == -1); 280 281 CHECKED_CLOSE(pathfd); 282 CHECKED_CLOSE(pathdfd); 283 } 284 285 /* Make sure that ptrace(PT_COREDUMP) cannot be used to write to a path fd. */ 286 ATF_TC_WITHOUT_HEAD(path_coredump); 287 ATF_TC_BODY(path_coredump, tc) 288 { 289 char path[PATH_MAX]; 290 struct ptrace_coredump pc; 291 int error, pathfd, status; 292 pid_t child; 293 294 mktdir(path, "path_coredump.XXXXXX"); 295 296 child = fork(); 297 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork")); 298 if (child == 0) { 299 while (true) 300 (void)sleep(1); 301 } 302 303 pathfd = open(path, O_PATH); 304 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 305 306 error = ptrace(PT_ATTACH, child, 0, 0); 307 ATF_REQUIRE_MSG(error == 0, FMT_ERR("ptrace")); 308 error = waitpid(child, &status, 0); 309 ATF_REQUIRE_MSG(error != -1, FMT_ERR("waitpid")); 310 ATF_REQUIRE_MSG(WIFSTOPPED(status), "unexpected status %d", status); 311 312 pc.pc_fd = pathfd; 313 pc.pc_flags = 0; 314 pc.pc_limit = 0; 315 error = ptrace(PT_COREDUMP, child, (void *)&pc, sizeof(pc)); 316 ATF_REQUIRE_ERRNO(EBADF, error == -1); 317 318 error = ptrace(PT_DETACH, child, 0, 0); 319 ATF_REQUIRE_MSG(error == 0, FMT_ERR("ptrace")); 320 321 ATF_REQUIRE_MSG(kill(child, SIGKILL) == 0, FMT_ERR("kill")); 322 323 CHECKED_CLOSE(pathfd); 324 } 325 326 /* Verify operations on directory path descriptors. */ 327 ATF_TC_WITHOUT_HEAD(path_directory); 328 ATF_TC_BODY(path_directory, tc) 329 { 330 struct dirent de; 331 struct stat sb; 332 char path[PATH_MAX]; 333 int fd, pathfd; 334 335 mktdir(path, "path_directory.XXXXXX"); 336 337 pathfd = open(path, O_PATH | O_DIRECTORY); 338 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 339 340 /* Should not be possible to list directory entries. */ 341 ATF_REQUIRE_ERRNO(EBADF, 342 getdirentries(pathfd, (char *)&de, sizeof(de), NULL) == -1); 343 344 /* It should be possible to create files under pathfd. */ 345 fd = openat(pathfd, "test", O_RDWR | O_CREAT, 0600); 346 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("open")); 347 ATF_REQUIRE_MSG(fstatat(pathfd, "test", &sb, 0) == 0, 348 FMT_ERR("fstatat")); 349 CHECKED_CLOSE(fd); 350 351 /* ... but doing so requires write access. */ 352 if (geteuid() != 0) { 353 ATF_REQUIRE_ERRNO(EBADF, fchmod(pathfd, 0500) == -1); 354 ATF_REQUIRE_MSG(chmod(path, 0500) == 0, FMT_ERR("chmod")); 355 ATF_REQUIRE_ERRNO(EACCES, 356 openat(pathfd, "test2", O_RDWR | O_CREAT, 0600) < 0); 357 } 358 359 /* fchdir(2) is permitted. */ 360 ATF_REQUIRE_MSG(fchdir(pathfd) == 0, FMT_ERR("fchdir")); 361 362 CHECKED_CLOSE(pathfd); 363 } 364 365 /* Verify access permission checking for a directory path fd. */ 366 ATF_TC_WITH_CLEANUP(path_directory_not_root); 367 ATF_TC_HEAD(path_directory_not_root, tc) 368 { 369 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 370 } 371 ATF_TC_BODY(path_directory_not_root, tc) 372 { 373 char path[PATH_MAX]; 374 int pathfd; 375 376 mktdir(path, "path_directory.XXXXXX"); 377 378 pathfd = open(path, O_PATH | O_DIRECTORY); 379 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 380 381 ATF_REQUIRE_ERRNO(EBADF, fchmod(pathfd, 0500) == -1); 382 ATF_REQUIRE_MSG(chmod(path, 0500) == 0, FMT_ERR("chmod")); 383 ATF_REQUIRE_ERRNO(EACCES, 384 openat(pathfd, "test2", O_RDWR | O_CREAT, 0600) < 0); 385 386 CHECKED_CLOSE(pathfd); 387 } 388 ATF_TC_CLEANUP(path_directory_not_root, tc) 389 { 390 } 391 392 /* Validate system calls that handle AT_EMPTY_PATH. */ 393 ATF_TC_WITHOUT_HEAD(path_empty); 394 ATF_TC_BODY(path_empty, tc) 395 { 396 char path[PATH_MAX]; 397 struct timespec ts[2]; 398 struct stat sb; 399 int pathfd; 400 401 mktfile(path, "path_empty.XXXXXX"); 402 403 pathfd = open(path, O_PATH); 404 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 405 406 /* Various *at operations should work on path fds. */ 407 ATF_REQUIRE_MSG(faccessat(pathfd, "", F_OK, AT_EMPTY_PATH) == 0, 408 FMT_ERR("faccessat")); 409 ATF_REQUIRE_MSG(chflagsat(pathfd, "", UF_NODUMP, AT_EMPTY_PATH) == 0, 410 FMT_ERR("chflagsat")); 411 ATF_REQUIRE_MSG(fchmodat(pathfd, "", 0600, AT_EMPTY_PATH) == 0, 412 FMT_ERR("fchmodat")); 413 ATF_REQUIRE_MSG(fchownat(pathfd, "", getuid(), getgid(), 414 AT_EMPTY_PATH) == 0, FMT_ERR("fchownat")); 415 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 416 FMT_ERR("fstatat")); 417 ATF_REQUIRE_MSG(sb.st_size == BUFSIZ, 418 "unexpected size %ju", (uintmax_t)sb.st_size); 419 memset(ts, 0, sizeof(ts)); 420 ATF_REQUIRE_MSG(utimensat(pathfd, "", ts, AT_EMPTY_PATH) == 0, 421 FMT_ERR("utimensat")); 422 423 CHECKED_CLOSE(pathfd); 424 } 425 426 /* Verify that various operations on a path fd have access checks. */ 427 ATF_TC_WITH_CLEANUP(path_empty_not_root); 428 ATF_TC_HEAD(path_empty_not_root, tc) 429 { 430 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 431 } 432 ATF_TC_BODY(path_empty_not_root, tc) 433 { 434 int pathfd; 435 436 pathfd = open("/dev/null", O_PATH); 437 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 438 439 ATF_REQUIRE_ERRNO(EPERM, 440 chflagsat(pathfd, "", UF_NODUMP, AT_EMPTY_PATH) == -1); 441 ATF_REQUIRE_ERRNO(EPERM, 442 fchownat(pathfd, "", getuid(), getgid(), AT_EMPTY_PATH) == -1); 443 ATF_REQUIRE_ERRNO(EPERM, 444 fchmodat(pathfd, "", 0600, AT_EMPTY_PATH) == -1); 445 ATF_REQUIRE_ERRNO(EPERM, 446 linkat(pathfd, "", AT_FDCWD, "test", AT_EMPTY_PATH) == -1); 447 448 CHECKED_CLOSE(pathfd); 449 } 450 ATF_TC_CLEANUP(path_empty_not_root, tc) 451 { 452 } 453 454 /* Test linkat(2) with AT_EMPTY_PATH, which requires privileges. */ 455 ATF_TC_WITH_CLEANUP(path_empty_root); 456 ATF_TC_HEAD(path_empty_root, tc) 457 { 458 atf_tc_set_md_var(tc, "require.user", "root"); 459 } 460 ATF_TC_BODY(path_empty_root, tc) 461 { 462 char path[PATH_MAX]; 463 struct stat sb, sb2; 464 int pathfd; 465 466 mktfile(path, "path_empty_root.XXXXXX"); 467 468 pathfd = open(path, O_PATH); 469 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 470 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 471 FMT_ERR("fstatat")); 472 473 ATF_REQUIRE_MSG(linkat(pathfd, "", AT_FDCWD, "test", AT_EMPTY_PATH) == 474 0, FMT_ERR("linkat")); 475 ATF_REQUIRE_MSG(fstatat(AT_FDCWD, "test", &sb2, 0) == 0, 476 FMT_ERR("fstatat")); 477 ATF_REQUIRE_MSG(sb.st_dev == sb2.st_dev, "st_dev mismatch"); 478 ATF_REQUIRE_MSG(sb.st_ino == sb2.st_ino, "st_ino mismatch"); 479 480 CHECKED_CLOSE(pathfd); 481 482 } 483 ATF_TC_CLEANUP(path_empty_root, tc) 484 { 485 } 486 487 /* poll(2) never returns an event for path fds, but kevent(2) does. */ 488 ATF_TC_WITHOUT_HEAD(path_event); 489 ATF_TC_BODY(path_event, tc) 490 { 491 char buf[BUFSIZ], path[PATH_MAX]; 492 struct kevent ev; 493 struct pollfd pollfd; 494 int kq, pathfd; 495 496 mktfile(path, "path_event.XXXXXX"); 497 498 pathfd = open(path, O_PATH); 499 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 500 501 /* poll(2) should return POLLNVAL. */ 502 pollfd.fd = pathfd; 503 pollfd.events = POLLIN; 504 pollfd.revents = 0; 505 ATF_REQUIRE_MSG(poll(&pollfd, 1, 0) == 1, FMT_ERR("poll")); 506 ATF_REQUIRE_MSG(pollfd.revents == POLLNVAL, "unexpected revents %x", 507 pollfd.revents); 508 pollfd.events = POLLOUT; 509 pollfd.revents = 0; 510 ATF_REQUIRE_MSG(poll(&pollfd, 1, 0) == 1, FMT_ERR("poll")); 511 ATF_REQUIRE_MSG(pollfd.revents == POLLNVAL, "unexpected revents %x", 512 pollfd.revents); 513 514 /* Try to get a EVFILT_READ event through a path fd. */ 515 kq = kqueue(); 516 ATF_REQUIRE_MSG(kq >= 0, FMT_ERR("kqueue")); 517 EV_SET(&ev, pathfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); 518 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 519 FMT_ERR("kevent")); 520 ATF_REQUIRE_MSG(kevent(kq, NULL, 0, &ev, 1, NULL) == 1, 521 FMT_ERR("kevent")); 522 ATF_REQUIRE_MSG((ev.flags & EV_ERROR) == 0, "EV_ERROR is set"); 523 ATF_REQUIRE_MSG(ev.data == sizeof(buf), 524 "data is %jd", (intmax_t)ev.data); 525 EV_SET(&ev, pathfd, EVFILT_READ, EV_DELETE, 0, 0, 0); 526 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 527 FMT_ERR("kevent")); 528 529 /* Try to get a EVFILT_VNODE/NOTE_DELETE event through a path fd. */ 530 EV_SET(&ev, pathfd, EVFILT_VNODE, EV_ADD | EV_ENABLE, NOTE_DELETE, 0, 531 0); 532 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 533 FMT_ERR("kevent")); 534 ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0, 535 FMT_ERR("funlinkat")); 536 ATF_REQUIRE_MSG(kevent(kq, NULL, 0, &ev, 1, NULL) == 1, 537 FMT_ERR("kevent")); 538 ATF_REQUIRE_MSG(ev.fflags == NOTE_DELETE, 539 "unexpected fflags %#x", ev.fflags); 540 EV_SET(&ev, pathfd, EVFILT_VNODE, EV_DELETE, 0, 0, 0); 541 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 542 FMT_ERR("kevent")); 543 544 CHECKED_CLOSE(kq); 545 CHECKED_CLOSE(pathfd); 546 } 547 548 /* Check various fcntl(2) operations on a path desriptor. */ 549 ATF_TC_WITHOUT_HEAD(path_fcntl); 550 ATF_TC_BODY(path_fcntl, tc) 551 { 552 char path[PATH_MAX]; 553 int flags, pathfd, pathfd2; 554 555 mktfile(path, "path_fcntl.XXXXXX"); 556 557 pathfd = open(path, O_PATH); 558 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 559 560 /* O_PATH should appear in the fd flags. */ 561 flags = fcntl(pathfd, F_GETFL); 562 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 563 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set"); 564 565 ATF_REQUIRE_ERRNO(EBADF, 566 fcntl(pathfd, F_SETFL, flags & ~O_PATH)); 567 ATF_REQUIRE_ERRNO(EBADF, 568 fcntl(pathfd, F_SETFL, flags | O_APPEND)); 569 570 /* A dup'ed O_PATH fd had better have O_PATH set too. */ 571 pathfd2 = fcntl(pathfd, F_DUPFD, 0); 572 ATF_REQUIRE_MSG(pathfd2 >= 0, FMT_ERR("fcntl")); 573 flags = fcntl(pathfd2, F_GETFL); 574 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 575 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set"); 576 CHECKED_CLOSE(pathfd2); 577 578 /* Double check with dup(2). */ 579 pathfd2 = dup(pathfd); 580 ATF_REQUIRE_MSG(pathfd2 >= 0, FMT_ERR("dup")); 581 flags = fcntl(pathfd2, F_GETFL); 582 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 583 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set"); 584 CHECKED_CLOSE(pathfd2); 585 586 /* It should be possible to set O_CLOEXEC. */ 587 ATF_REQUIRE_MSG(fcntl(pathfd, F_SETFD, FD_CLOEXEC) == 0, 588 FMT_ERR("fcntl")); 589 ATF_REQUIRE_MSG(fcntl(pathfd, F_GETFD) == FD_CLOEXEC, 590 FMT_ERR("fcntl")); 591 592 CHECKED_CLOSE(pathfd); 593 } 594 595 /* Verify that we can execute a file opened with O_PATH. */ 596 ATF_TC_WITHOUT_HEAD(path_fexecve); 597 ATF_TC_BODY(path_fexecve, tc) 598 { 599 char path[PATH_MAX]; 600 pid_t child; 601 int fd, pathfd; 602 603 child = fork(); 604 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork")); 605 if (child == 0) { 606 pathfd = open("/usr/bin/true", O_PATH | O_EXEC); 607 if (pathfd < 0) 608 _exit(1); 609 fexecve(pathfd, 610 (char * const[]){__DECONST(char *, "/usr/bin/true"), NULL}, 611 NULL); 612 _exit(2); 613 } 614 waitchild(child, 0); 615 616 /* 617 * Also verify that access permissions are checked when opening with 618 * O_PATH. 619 */ 620 snprintf(path, sizeof(path), "path_fexecve.XXXXXX"); 621 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 622 623 fd = open(path, O_CREAT | O_RDONLY, 0600); 624 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("open")); 625 626 pathfd = open(path, O_PATH | O_EXEC); 627 ATF_REQUIRE_ERRNO(EACCES, pathfd < 0); 628 } 629 630 /* Make sure that O_PATH restrictions apply to named pipes as well. */ 631 ATF_TC_WITHOUT_HEAD(path_fifo); 632 ATF_TC_BODY(path_fifo, tc) 633 { 634 char path[PATH_MAX], buf[BUFSIZ]; 635 struct kevent ev; 636 int kq, pathfd; 637 638 snprintf(path, sizeof(path), "path_fifo.XXXXXX"); 639 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 640 641 ATF_REQUIRE_MSG(mkfifo(path, 0666) == 0, FMT_ERR("mkfifo")); 642 643 pathfd = open(path, O_PATH); 644 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 645 memset(buf, 0, sizeof(buf)); 646 ATF_REQUIRE_ERRNO(EBADF, write(pathfd, buf, sizeof(buf))); 647 ATF_REQUIRE_ERRNO(EBADF, read(pathfd, buf, sizeof(buf))); 648 649 kq = kqueue(); 650 ATF_REQUIRE_MSG(kq >= 0, FMT_ERR("kqueue")); 651 EV_SET(&ev, pathfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); 652 ATF_REQUIRE_ERRNO(EBADF, kevent(kq, &ev, 1, NULL, 0, NULL) == -1); 653 654 CHECKED_CLOSE(pathfd); 655 } 656 657 /* Files may be unlinked using a path fd. */ 658 ATF_TC_WITHOUT_HEAD(path_funlinkat); 659 ATF_TC_BODY(path_funlinkat, tc) 660 { 661 char path[PATH_MAX]; 662 struct stat sb; 663 int pathfd; 664 665 mktfile(path, "path_rights.XXXXXX"); 666 667 pathfd = open(path, O_PATH); 668 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 669 670 ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0, 671 FMT_ERR("funlinkat")); 672 ATF_REQUIRE_ERRNO(ENOENT, stat(path, &sb) == -1); 673 674 CHECKED_CLOSE(pathfd); 675 } 676 677 /* Verify that various I/O operations fail on an O_PATH descriptor. */ 678 ATF_TC_WITHOUT_HEAD(path_io); 679 ATF_TC_BODY(path_io, tc) 680 { 681 char path[PATH_MAX], path2[PATH_MAX]; 682 char buf[BUFSIZ]; 683 struct iovec iov; 684 size_t page_size; 685 int error, fd, pathfd, sd[2]; 686 687 /* It shouldn't be possible to create new files with O_PATH. */ 688 snprintf(path, sizeof(path), "path_io.XXXXXX"); 689 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 690 ATF_REQUIRE_ERRNO(ENOENT, open(path, O_PATH | O_CREAT, 0600) < 0); 691 692 /* Create a non-empty file for use in the rest of the tests. */ 693 mktfile(path, "path_io.XXXXXX"); 694 695 pathfd = open(path, O_PATH); 696 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 697 698 /* Make sure that basic I/O operations aren't possible. */ 699 iov.iov_base = path; 700 iov.iov_len = strlen(path); 701 ATF_REQUIRE_ERRNO(EBADF, 702 write(pathfd, iov.iov_base, iov.iov_len) == -1); 703 ATF_REQUIRE_ERRNO(EBADF, 704 pwrite(pathfd, iov.iov_base, iov.iov_len, 0) == -1); 705 ATF_REQUIRE_ERRNO(EBADF, 706 writev(pathfd, &iov, 1) == -1); 707 ATF_REQUIRE_ERRNO(EBADF, 708 pwritev(pathfd, &iov, 1, 0) == -1); 709 ATF_REQUIRE_ERRNO(EBADF, 710 read(pathfd, path, 1) == -1); 711 ATF_REQUIRE_ERRNO(EBADF, 712 pread(pathfd, path, 1, 0) == -1); 713 ATF_REQUIRE_ERRNO(EBADF, 714 readv(pathfd, &iov, 1) == -1); 715 ATF_REQUIRE_ERRNO(EBADF, 716 preadv(pathfd, &iov, 1, 0) == -1); 717 718 /* copy_file_range() should not be permitted. */ 719 mktfile(path2, "path_io.XXXXXX"); 720 fd = open(path2, O_RDWR); 721 ATF_REQUIRE_ERRNO(EBADF, 722 copy_file_range(fd, NULL, pathfd, NULL, sizeof(buf), 0) == -1); 723 ATF_REQUIRE_ERRNO(EBADF, 724 copy_file_range(pathfd, NULL, fd, NULL, sizeof(buf), 0) == -1); 725 CHECKED_CLOSE(fd); 726 727 /* sendfile() should not be permitted. */ 728 ATF_REQUIRE_MSG(socketpair(PF_LOCAL, SOCK_STREAM, 0, sd) == 0, 729 FMT_ERR("socketpair")); 730 ATF_REQUIRE_ERRNO(EBADF, 731 sendfile(pathfd, sd[0], 0, 0, NULL, NULL, 0)); 732 CHECKED_CLOSE(sd[0]); 733 CHECKED_CLOSE(sd[1]); 734 735 /* No seeking. */ 736 ATF_REQUIRE_ERRNO(ESPIPE, 737 lseek(pathfd, 0, SEEK_SET) == -1); 738 739 /* No operations on the file extent. */ 740 ATF_REQUIRE_ERRNO(EINVAL, 741 ftruncate(pathfd, 0) == -1); 742 error = posix_fallocate(pathfd, 0, sizeof(buf) * 2); 743 ATF_REQUIRE_MSG(error == ESPIPE, "posix_fallocate() returned %d", error); 744 error = posix_fadvise(pathfd, 0, sizeof(buf), POSIX_FADV_NORMAL); 745 ATF_REQUIRE_MSG(error == ESPIPE, "posix_fadvise() returned %d", error); 746 747 /* mmap() is not allowed. */ 748 page_size = getpagesize(); 749 ATF_REQUIRE_ERRNO(ENODEV, 750 mmap(NULL, page_size, PROT_READ, MAP_SHARED, pathfd, 0) == 751 MAP_FAILED); 752 ATF_REQUIRE_ERRNO(ENODEV, 753 mmap(NULL, page_size, PROT_NONE, MAP_SHARED, pathfd, 0) == 754 MAP_FAILED); 755 ATF_REQUIRE_ERRNO(ENODEV, 756 mmap(NULL, page_size, PROT_READ, MAP_PRIVATE, pathfd, 0) == 757 MAP_FAILED); 758 759 /* No fsync() or fdatasync(). */ 760 ATF_REQUIRE_ERRNO(EBADF, fsync(pathfd) == -1); 761 ATF_REQUIRE_ERRNO(EBADF, fdatasync(pathfd) == -1); 762 763 CHECKED_CLOSE(pathfd); 764 } 765 766 /* ioctl(2) is not permitted on path fds. */ 767 ATF_TC_WITHOUT_HEAD(path_ioctl); 768 ATF_TC_BODY(path_ioctl, tc) 769 { 770 char path[PATH_MAX]; 771 struct mem_extract me; 772 int pathfd, val; 773 774 mktfile(path, "path_ioctl.XXXXXX"); 775 776 /* Standard file descriptor ioctls should fail. */ 777 pathfd = open(path, O_PATH); 778 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 779 780 val = 0; 781 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONBIO, &val) == -1); 782 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONREAD, &val) == -1); 783 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONWRITE, &val) == -1); 784 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONSPACE, &val) == -1); 785 786 CHECKED_CLOSE(pathfd); 787 788 /* Device ioctls should fail. */ 789 pathfd = open("/dev/mem", O_PATH); 790 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 791 792 me.me_vaddr = (uintptr_t)&me; 793 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, MEM_EXTRACT_PADDR, &me) == -1); 794 795 CHECKED_CLOSE(pathfd); 796 } 797 798 ATF_TC_WITHOUT_HEAD(path_lock); 799 ATF_TC_BODY(path_lock, tc) 800 { 801 char buf[BUFSIZ], path[PATH_MAX]; 802 struct flock flk; 803 int fd, pathfd; 804 805 snprintf(path, sizeof(path), "path_rights.XXXXXX"); 806 fd = mkostemp(path, O_SHLOCK); 807 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("mkostemp")); 808 memset(buf, 0, sizeof(buf)); 809 ATF_REQUIRE_MSG(write(fd, buf, sizeof(buf)) == sizeof(buf), 810 FMT_ERR("write()")); 811 812 /* Verify that O_EXLOCK is ignored when combined with O_PATH. */ 813 pathfd = open(path, O_PATH | O_EXLOCK); 814 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 815 816 CHECKED_CLOSE(fd); 817 818 /* flock(2) is prohibited. */ 819 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_SH) == -1); 820 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_EX) == -1); 821 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_SH | LOCK_NB) == -1); 822 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_EX | LOCK_NB) == -1); 823 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_UN) == -1); 824 825 /* fcntl(2) file locks are prohibited. */ 826 memset(&flk, 0, sizeof(flk)); 827 flk.l_whence = SEEK_CUR; 828 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_GETLK, &flk) == -1); 829 flk.l_type = F_RDLCK; 830 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLK, &flk) == -1); 831 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLKW, &flk) == -1); 832 flk.l_type = F_WRLCK; 833 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLK, &flk) == -1); 834 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLKW, &flk) == -1); 835 836 CHECKED_CLOSE(pathfd); 837 } 838 839 /* 840 * Verify fstatat(AT_EMPTY_PATH) on non-regular dirfd. 841 * Verify that fstatat(AT_EMPTY_PATH) on NULL path returns EFAULT. 842 */ 843 ATF_TC_WITHOUT_HEAD(path_pipe_fstatat); 844 ATF_TC_BODY(path_pipe_fstatat, tc) 845 { 846 struct stat sb; 847 int fd[2]; 848 849 ATF_REQUIRE_MSG(pipe(fd) == 0, FMT_ERR("pipe")); 850 ATF_REQUIRE_MSG(fstatat(fd[0], "", &sb, AT_EMPTY_PATH) == 0, 851 FMT_ERR("fstatat pipe")); 852 ATF_REQUIRE_ERRNO(EFAULT, fstatat(fd[0], NULL, &sb, 853 AT_EMPTY_PATH) == -1); 854 CHECKED_CLOSE(fd[0]); 855 CHECKED_CLOSE(fd[1]); 856 } 857 858 /* Verify that we can send an O_PATH descriptor over a unix socket. */ 859 ATF_TC_WITHOUT_HEAD(path_rights); 860 ATF_TC_BODY(path_rights, tc) 861 { 862 char path[PATH_MAX]; 863 struct cmsghdr *cmsg; 864 struct msghdr msg; 865 struct iovec iov; 866 int flags, pathfd, pathfd_copy, sd[2]; 867 char c; 868 869 ATF_REQUIRE_MSG(socketpair(PF_LOCAL, SOCK_STREAM, 0, sd) == 0, 870 FMT_ERR("socketpair")); 871 872 mktfile(path, "path_rights.XXXXXX"); 873 874 pathfd = open(path, O_PATH); 875 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 876 877 /* Package up the O_PATH and send it over the socket pair. */ 878 cmsg = malloc(CMSG_SPACE(sizeof(pathfd))); 879 ATF_REQUIRE_MSG(cmsg != NULL, FMT_ERR("malloc")); 880 881 cmsg->cmsg_len = CMSG_LEN(sizeof(pathfd)); 882 cmsg->cmsg_level = SOL_SOCKET; 883 cmsg->cmsg_type = SCM_RIGHTS; 884 *(int *)(void *)CMSG_DATA(cmsg) = pathfd; 885 886 c = 0; 887 iov.iov_base = &c; 888 iov.iov_len = 1; 889 890 memset(&msg, 0, sizeof(msg)); 891 msg.msg_iov = &iov; 892 msg.msg_iovlen = 1; 893 msg.msg_control = cmsg; 894 msg.msg_controllen = CMSG_SPACE(sizeof(pathfd)); 895 896 ATF_REQUIRE_MSG(sendmsg(sd[0], &msg, 0) == sizeof(c), 897 FMT_ERR("sendmsg")); 898 899 /* Grab the pathfd copy from the other end of the pair. */ 900 memset(&msg, 0, sizeof(msg)); 901 msg.msg_iov = &iov; 902 msg.msg_iovlen = 1; 903 msg.msg_control = cmsg; 904 msg.msg_controllen = CMSG_SPACE(sizeof(pathfd)); 905 906 ATF_REQUIRE_MSG(recvmsg(sd[1], &msg, 0) == 1, 907 FMT_ERR("recvmsg")); 908 pathfd_copy = *(int *)(void *)CMSG_DATA(cmsg); 909 ATF_REQUIRE_MSG(pathfd_copy != pathfd, 910 "pathfd and pathfd_copy are equal"); 911 912 /* Verify that the copy has O_PATH properties. */ 913 flags = fcntl(pathfd_copy, F_GETFL); 914 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 915 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH is not set"); 916 ATF_REQUIRE_ERRNO(EBADF, 917 read(pathfd_copy, &c, 1) == -1); 918 ATF_REQUIRE_ERRNO(EBADF, 919 write(pathfd_copy, &c, 1) == -1); 920 921 CHECKED_CLOSE(pathfd); 922 CHECKED_CLOSE(pathfd_copy); 923 CHECKED_CLOSE(sd[0]); 924 CHECKED_CLOSE(sd[1]); 925 } 926 927 /* Verify that a local socket can be opened with O_PATH. */ 928 ATF_TC_WITHOUT_HEAD(path_unix); 929 ATF_TC_BODY(path_unix, tc) 930 { 931 char buf[BUFSIZ], path[PATH_MAX]; 932 struct kevent ev; 933 struct sockaddr_un sun; 934 struct stat sb; 935 int kq, pathfd, sd; 936 937 snprintf(path, sizeof(path), "path_unix.XXXXXX"); 938 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 939 940 sd = socket(PF_LOCAL, SOCK_STREAM, 0); 941 ATF_REQUIRE_MSG(sd >= 0, FMT_ERR("socket")); 942 943 memset(&sun, 0, sizeof(sun)); 944 sun.sun_family = PF_LOCAL; 945 (void)strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 946 ATF_REQUIRE_MSG(bind(sd, (struct sockaddr *)&sun, SUN_LEN(&sun)) == 0, 947 FMT_ERR("bind")); 948 949 pathfd = open(path, O_PATH); 950 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 951 952 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 953 FMT_ERR("fstatat")); 954 ATF_REQUIRE_MSG(sb.st_mode & S_IFSOCK, "socket mode %#x", sb.st_mode); 955 ATF_REQUIRE_MSG(sb.st_ino != 0, "socket has inode number 0"); 956 957 memset(buf, 0, sizeof(buf)); 958 ATF_REQUIRE_ERRNO(EBADF, write(pathfd, buf, sizeof(buf))); 959 ATF_REQUIRE_ERRNO(EBADF, read(pathfd, buf, sizeof(buf))); 960 961 /* kevent() is disallowed with sockets. */ 962 kq = kqueue(); 963 ATF_REQUIRE_MSG(kq >= 0, FMT_ERR("kqueue")); 964 EV_SET(&ev, pathfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); 965 ATF_REQUIRE_ERRNO(EBADF, kevent(kq, &ev, 1, NULL, 0, NULL) == -1); 966 967 /* Should not be able to open a socket without O_PATH. */ 968 ATF_REQUIRE_ERRNO(EOPNOTSUPP, openat(pathfd, "", O_EMPTY_PATH) == -1); 969 970 ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0, 971 FMT_ERR("funlinkat")); 972 973 CHECKED_CLOSE(sd); 974 CHECKED_CLOSE(pathfd); 975 } 976 977 /* 978 * Check that we can perform operations using an O_PATH fd for an unlinked file. 979 */ 980 ATF_TC_WITHOUT_HEAD(path_unlinked); 981 ATF_TC_BODY(path_unlinked, tc) 982 { 983 char path[PATH_MAX]; 984 struct stat sb; 985 int pathfd; 986 987 mktfile(path, "path_rights.XXXXXX"); 988 989 pathfd = open(path, O_PATH); 990 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 991 992 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 993 FMT_ERR("fstatat")); 994 ATF_REQUIRE(sb.st_nlink == 1); 995 ATF_REQUIRE_MSG(fstat(pathfd, &sb) == 0, FMT_ERR("fstat")); 996 ATF_REQUIRE(sb.st_nlink == 1); 997 998 ATF_REQUIRE_MSG(unlink(path) == 0, FMT_ERR("unlink")); 999 1000 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 1001 FMT_ERR("fstatat")); 1002 ATF_REQUIRE(sb.st_nlink == 0); 1003 ATF_REQUIRE_MSG(fstat(pathfd, &sb) == 0, FMT_ERR("fstat")); 1004 ATF_REQUIRE(sb.st_nlink == 0); 1005 1006 CHECKED_CLOSE(pathfd); 1007 } 1008 1009 ATF_TP_ADD_TCS(tp) 1010 { 1011 ATF_TP_ADD_TC(tp, path_access); 1012 ATF_TP_ADD_TC(tp, path_aio); 1013 ATF_TP_ADD_TC(tp, path_capsicum); 1014 ATF_TP_ADD_TC(tp, path_capsicum_empty); 1015 ATF_TP_ADD_TC(tp, path_coredump); 1016 ATF_TP_ADD_TC(tp, path_directory); 1017 ATF_TP_ADD_TC(tp, path_directory_not_root); 1018 ATF_TP_ADD_TC(tp, path_empty); 1019 ATF_TP_ADD_TC(tp, path_empty_not_root); 1020 ATF_TP_ADD_TC(tp, path_empty_root); 1021 ATF_TP_ADD_TC(tp, path_event); 1022 ATF_TP_ADD_TC(tp, path_fcntl); 1023 ATF_TP_ADD_TC(tp, path_fexecve); 1024 ATF_TP_ADD_TC(tp, path_fifo); 1025 ATF_TP_ADD_TC(tp, path_funlinkat); 1026 ATF_TP_ADD_TC(tp, path_io); 1027 ATF_TP_ADD_TC(tp, path_ioctl); 1028 ATF_TP_ADD_TC(tp, path_lock); 1029 ATF_TP_ADD_TC(tp, path_pipe_fstatat); 1030 ATF_TP_ADD_TC(tp, path_rights); 1031 ATF_TP_ADD_TC(tp, path_unix); 1032 ATF_TP_ADD_TC(tp, path_unlinked); 1033 1034 return (atf_no_error()); 1035 } 1036