1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 /* 67 * Verify fstatat(AT_EMPTY_PATH) on non-regular dirfd. 68 * Verify that fstatat(AT_EMPTY_PATH) on NULL path returns EFAULT. 69 */ 70 ATF_TC_WITHOUT_HEAD(path_pipe_fstatat); 71 ATF_TC_BODY(path_pipe_fstatat, tc) 72 { 73 struct stat sb; 74 int fd[2]; 75 76 ATF_REQUIRE_MSG(pipe(fd) == 0, FMT_ERR("pipe")); 77 ATF_REQUIRE_MSG(fstatat(fd[0], "", &sb, AT_EMPTY_PATH) == 0, 78 FMT_ERR("fstatat pipe")); 79 ATF_REQUIRE_ERRNO(EFAULT, fstatat(fd[0], NULL, &sb, 80 AT_EMPTY_PATH) == -1); 81 CHECKED_CLOSE(fd[0]); 82 CHECKED_CLOSE(fd[1]); 83 } 84 85 /* Create a temporary regular file containing some data. */ 86 static void 87 mktfile(char path[PATH_MAX], const char *template) 88 { 89 char buf[BUFSIZ]; 90 int fd; 91 92 snprintf(path, PATH_MAX, "%s", template); 93 fd = mkstemp(path); 94 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("mkstemp")); 95 memset(buf, 0, sizeof(buf)); 96 ATF_REQUIRE_MSG(write(fd, buf, sizeof(buf)) == sizeof(buf), 97 FMT_ERR("write")); 98 CHECKED_CLOSE(fd); 99 } 100 101 /* Make a temporary directory. */ 102 static void 103 mktdir(char path[PATH_MAX], const char *template) 104 { 105 snprintf(path, PATH_MAX, "%s", template); 106 ATF_REQUIRE_MSG(mkdtemp(path) == path, FMT_ERR("mkdtemp")); 107 } 108 109 /* Wait for a child process to exit with status 0. */ 110 static void 111 waitchild(pid_t child, int exstatus) 112 { 113 int error, status; 114 115 error = waitpid(child, &status, 0); 116 ATF_REQUIRE_MSG(error != -1, FMT_ERR("waitpid")); 117 ATF_REQUIRE_MSG(WIFEXITED(status), "child exited abnormally, status %d", 118 status); 119 ATF_REQUIRE_MSG(WEXITSTATUS(status) == exstatus, 120 "child exit status is %d, expected %d", 121 WEXITSTATUS(status), exstatus); 122 } 123 124 ATF_TC_WITHOUT_HEAD(path_access); 125 ATF_TC_BODY(path_access, tc) 126 { 127 char path[PATH_MAX]; 128 struct stat sb; 129 struct timespec ts[2]; 130 struct timeval tv[2]; 131 int pathfd; 132 133 mktfile(path, "path_access.XXXXXX"); 134 135 pathfd = open(path, O_PATH); 136 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 137 138 ATF_REQUIRE_ERRNO(EBADF, fchmod(pathfd, 0666) == -1); 139 ATF_REQUIRE_ERRNO(EBADF, fchown(pathfd, getuid(), getgid()) == -1); 140 ATF_REQUIRE_ERRNO(EBADF, fchflags(pathfd, UF_NODUMP) == -1); 141 memset(tv, 0, sizeof(tv)); 142 ATF_REQUIRE_ERRNO(EBADF, futimes(pathfd, tv) == -1); 143 memset(ts, 0, sizeof(ts)); 144 ATF_REQUIRE_ERRNO(EBADF, futimens(pathfd, ts) == -1); 145 146 /* fpathconf(2) and fstat(2) are permitted. */ 147 ATF_REQUIRE_MSG(fstat(pathfd, &sb) == 0, FMT_ERR("fstat")); 148 ATF_REQUIRE_MSG(fpathconf(pathfd, _PC_LINK_MAX) != -1, 149 FMT_ERR("fpathconf")); 150 151 CHECKED_CLOSE(pathfd); 152 } 153 154 /* Basic tests to verify that AIO operations fail. */ 155 ATF_TC_WITHOUT_HEAD(path_aio); 156 ATF_TC_BODY(path_aio, tc) 157 { 158 struct aiocb aio; 159 char buf[BUFSIZ], path[PATH_MAX]; 160 int pathfd; 161 162 mktfile(path, "path_aio.XXXXXX"); 163 164 pathfd = open(path, O_PATH); 165 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 166 167 memset(&aio, 0, sizeof(aio)); 168 aio.aio_buf = buf; 169 aio.aio_nbytes = sizeof(buf); 170 aio.aio_fildes = pathfd; 171 aio.aio_offset = 0; 172 173 ATF_REQUIRE_ERRNO(EBADF, aio_read(&aio) == -1); 174 ATF_REQUIRE_ERRNO(EBADF, aio_write(&aio) == -1); 175 ATF_REQUIRE_ERRNO(EBADF, aio_fsync(O_SYNC, &aio) == -1); 176 ATF_REQUIRE_ERRNO(EBADF, aio_fsync(O_DSYNC, &aio) == -1); 177 178 CHECKED_CLOSE(pathfd); 179 } 180 181 /* Basic tests to verify that Capsicum restrictions apply to path fds. */ 182 ATF_TC_WITHOUT_HEAD(path_capsicum); 183 ATF_TC_BODY(path_capsicum, tc) 184 { 185 char path[PATH_MAX]; 186 cap_rights_t rights; 187 int truefd; 188 pid_t child; 189 190 mktfile(path, "path_capsicum.XXXXXX"); 191 192 /* Make sure that filesystem namespace restrictions apply to O_PATH. */ 193 child = fork(); 194 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork")); 195 if (child == 0) { 196 if (cap_enter() != 0) 197 _exit(1); 198 if (open(path, O_PATH) >= 0) 199 _exit(2); 200 if (errno != ECAPMODE) 201 _exit(3); 202 if (open("/usr/bin/true", O_PATH | O_EXEC) >= 0) 203 _exit(4); 204 if (errno != ECAPMODE) 205 _exit(5); 206 _exit(0); 207 } 208 waitchild(child, 0); 209 210 /* Make sure that CAP_FEXECVE is required. */ 211 child = fork(); 212 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork")); 213 if (child == 0) { 214 truefd = open("/usr/bin/true", O_PATH | O_EXEC); 215 if (truefd < 0) 216 _exit(1); 217 cap_rights_init(&rights); 218 if (cap_rights_limit(truefd, &rights) != 0) 219 _exit(2); 220 (void)fexecve(truefd, 221 (char * const[]){__DECONST(char *, "/usr/bin/true"), NULL}, 222 NULL); 223 if (errno != ENOTCAPABLE) 224 _exit(3); 225 _exit(4); 226 } 227 waitchild(child, 4); 228 } 229 230 /* Make sure that ptrace(PT_COREDUMP) cannot be used to write to a path fd. */ 231 ATF_TC_WITHOUT_HEAD(path_coredump); 232 ATF_TC_BODY(path_coredump, tc) 233 { 234 char path[PATH_MAX]; 235 struct ptrace_coredump pc; 236 int error, pathfd, status; 237 pid_t child; 238 239 mktdir(path, "path_coredump.XXXXXX"); 240 241 child = fork(); 242 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork")); 243 if (child == 0) { 244 while (true) 245 (void)sleep(1); 246 } 247 248 pathfd = open(path, O_PATH); 249 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 250 251 error = ptrace(PT_ATTACH, child, 0, 0); 252 ATF_REQUIRE_MSG(error == 0, FMT_ERR("ptrace")); 253 error = waitpid(child, &status, 0); 254 ATF_REQUIRE_MSG(error != -1, FMT_ERR("waitpid")); 255 ATF_REQUIRE_MSG(WIFSTOPPED(status), "unexpected status %d", status); 256 257 pc.pc_fd = pathfd; 258 pc.pc_flags = 0; 259 pc.pc_limit = 0; 260 error = ptrace(PT_COREDUMP, child, (void *)&pc, sizeof(pc)); 261 ATF_REQUIRE_ERRNO(EBADF, error == -1); 262 263 error = ptrace(PT_DETACH, child, 0, 0); 264 ATF_REQUIRE_MSG(error == 0, FMT_ERR("ptrace")); 265 266 ATF_REQUIRE_MSG(kill(child, SIGKILL) == 0, FMT_ERR("kill")); 267 268 CHECKED_CLOSE(pathfd); 269 } 270 271 /* Verify operations on directory path descriptors. */ 272 ATF_TC_WITHOUT_HEAD(path_directory); 273 ATF_TC_BODY(path_directory, tc) 274 { 275 struct dirent de; 276 struct stat sb; 277 char path[PATH_MAX]; 278 int fd, pathfd; 279 280 mktdir(path, "path_directory.XXXXXX"); 281 282 pathfd = open(path, O_PATH | O_DIRECTORY); 283 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 284 285 /* Should not be possible to list directory entries. */ 286 ATF_REQUIRE_ERRNO(EBADF, 287 getdirentries(pathfd, (char *)&de, sizeof(de), NULL) == -1); 288 289 /* It should be possible to create files under pathfd. */ 290 fd = openat(pathfd, "test", O_RDWR | O_CREAT, 0600); 291 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("open")); 292 ATF_REQUIRE_MSG(fstatat(pathfd, "test", &sb, 0) == 0, 293 FMT_ERR("fstatat")); 294 CHECKED_CLOSE(fd); 295 296 /* ... but doing so requires write access. */ 297 if (geteuid() != 0) { 298 ATF_REQUIRE_ERRNO(EBADF, fchmod(pathfd, 0500) == -1); 299 ATF_REQUIRE_MSG(chmod(path, 0500) == 0, FMT_ERR("chmod")); 300 ATF_REQUIRE_ERRNO(EACCES, 301 openat(pathfd, "test2", O_RDWR | O_CREAT, 0600) < 0); 302 } 303 304 /* fchdir(2) is permitted. */ 305 ATF_REQUIRE_MSG(fchdir(pathfd) == 0, FMT_ERR("fchdir")); 306 307 CHECKED_CLOSE(pathfd); 308 } 309 310 /* Verify access permission checking for a directory path fd. */ 311 ATF_TC_WITH_CLEANUP(path_directory_not_root); 312 ATF_TC_HEAD(path_directory_not_root, tc) 313 { 314 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 315 } 316 ATF_TC_BODY(path_directory_not_root, tc) 317 { 318 char path[PATH_MAX]; 319 int pathfd; 320 321 mktdir(path, "path_directory.XXXXXX"); 322 323 pathfd = open(path, O_PATH | O_DIRECTORY); 324 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 325 326 ATF_REQUIRE_ERRNO(EBADF, fchmod(pathfd, 0500) == -1); 327 ATF_REQUIRE_MSG(chmod(path, 0500) == 0, FMT_ERR("chmod")); 328 ATF_REQUIRE_ERRNO(EACCES, 329 openat(pathfd, "test2", O_RDWR | O_CREAT, 0600) < 0); 330 331 CHECKED_CLOSE(pathfd); 332 } 333 ATF_TC_CLEANUP(path_directory_not_root, tc) 334 { 335 } 336 337 /* Validate system calls that handle AT_EMPTY_PATH. */ 338 ATF_TC_WITHOUT_HEAD(path_empty); 339 ATF_TC_BODY(path_empty, tc) 340 { 341 char path[PATH_MAX]; 342 struct timespec ts[2]; 343 struct stat sb; 344 int pathfd; 345 346 mktfile(path, "path_empty.XXXXXX"); 347 348 pathfd = open(path, O_PATH); 349 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 350 351 /* Various *at operations should work on path fds. */ 352 ATF_REQUIRE_MSG(faccessat(pathfd, "", F_OK, AT_EMPTY_PATH) == 0, 353 FMT_ERR("faccessat")); 354 ATF_REQUIRE_MSG(chflagsat(pathfd, "", UF_NODUMP, AT_EMPTY_PATH) == 0, 355 FMT_ERR("chflagsat")); 356 ATF_REQUIRE_MSG(fchmodat(pathfd, "", 0600, AT_EMPTY_PATH) == 0, 357 FMT_ERR("fchmodat")); 358 ATF_REQUIRE_MSG(fchownat(pathfd, "", getuid(), getgid(), 359 AT_EMPTY_PATH) == 0, FMT_ERR("fchownat")); 360 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 361 FMT_ERR("fstatat")); 362 ATF_REQUIRE_MSG(sb.st_size == BUFSIZ, 363 "unexpected size %ju", (uintmax_t)sb.st_size); 364 memset(ts, 0, sizeof(ts)); 365 ATF_REQUIRE_MSG(utimensat(pathfd, "", ts, AT_EMPTY_PATH) == 0, 366 FMT_ERR("utimensat")); 367 368 CHECKED_CLOSE(pathfd); 369 } 370 371 /* Verify that various operations on a path fd have access checks. */ 372 ATF_TC_WITH_CLEANUP(path_empty_not_root); 373 ATF_TC_HEAD(path_empty_not_root, tc) 374 { 375 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 376 } 377 ATF_TC_BODY(path_empty_not_root, tc) 378 { 379 int pathfd; 380 381 pathfd = open("/dev/null", O_PATH); 382 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 383 384 ATF_REQUIRE_ERRNO(EPERM, 385 chflagsat(pathfd, "", UF_NODUMP, AT_EMPTY_PATH) == -1); 386 ATF_REQUIRE_ERRNO(EPERM, 387 fchownat(pathfd, "", getuid(), getgid(), AT_EMPTY_PATH) == -1); 388 ATF_REQUIRE_ERRNO(EPERM, 389 fchmodat(pathfd, "", 0600, AT_EMPTY_PATH) == -1); 390 ATF_REQUIRE_ERRNO(EPERM, 391 linkat(pathfd, "", AT_FDCWD, "test", AT_EMPTY_PATH) == -1); 392 393 CHECKED_CLOSE(pathfd); 394 } 395 ATF_TC_CLEANUP(path_empty_not_root, tc) 396 { 397 } 398 399 /* Test linkat(2) with AT_EMPTY_PATH, which requires privileges. */ 400 ATF_TC_WITH_CLEANUP(path_empty_root); 401 ATF_TC_HEAD(path_empty_root, tc) 402 { 403 atf_tc_set_md_var(tc, "require.user", "root"); 404 } 405 ATF_TC_BODY(path_empty_root, tc) 406 { 407 char path[PATH_MAX]; 408 struct stat sb, sb2; 409 int pathfd; 410 411 mktfile(path, "path_empty_root.XXXXXX"); 412 413 pathfd = open(path, O_PATH); 414 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 415 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 416 FMT_ERR("fstatat")); 417 418 ATF_REQUIRE_MSG(linkat(pathfd, "", AT_FDCWD, "test", AT_EMPTY_PATH) == 419 0, FMT_ERR("linkat")); 420 ATF_REQUIRE_MSG(fstatat(AT_FDCWD, "test", &sb2, 0) == 0, 421 FMT_ERR("fstatat")); 422 ATF_REQUIRE_MSG(sb.st_dev == sb2.st_dev, "st_dev mismatch"); 423 ATF_REQUIRE_MSG(sb.st_ino == sb2.st_ino, "st_ino mismatch"); 424 425 CHECKED_CLOSE(pathfd); 426 427 } 428 ATF_TC_CLEANUP(path_empty_root, tc) 429 { 430 } 431 432 /* poll(2) never returns an event for path fds, but kevent(2) does. */ 433 ATF_TC_WITHOUT_HEAD(path_event); 434 ATF_TC_BODY(path_event, tc) 435 { 436 char buf[BUFSIZ], path[PATH_MAX]; 437 struct kevent ev; 438 struct pollfd pollfd; 439 int kq, pathfd; 440 441 mktfile(path, "path_event.XXXXXX"); 442 443 pathfd = open(path, O_PATH); 444 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 445 446 /* poll(2) should return POLLNVAL. */ 447 pollfd.fd = pathfd; 448 pollfd.events = POLLIN; 449 pollfd.revents = 0; 450 ATF_REQUIRE_MSG(poll(&pollfd, 1, 0) == 1, FMT_ERR("poll")); 451 ATF_REQUIRE_MSG(pollfd.revents == POLLNVAL, "unexpected revents %x", 452 pollfd.revents); 453 pollfd.events = POLLOUT; 454 pollfd.revents = 0; 455 ATF_REQUIRE_MSG(poll(&pollfd, 1, 0) == 1, FMT_ERR("poll")); 456 ATF_REQUIRE_MSG(pollfd.revents == POLLNVAL, "unexpected revents %x", 457 pollfd.revents); 458 459 /* Try to get a EVFILT_READ event through a path fd. */ 460 kq = kqueue(); 461 ATF_REQUIRE_MSG(kq >= 0, FMT_ERR("kqueue")); 462 EV_SET(&ev, pathfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); 463 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 464 FMT_ERR("kevent")); 465 ATF_REQUIRE_MSG(kevent(kq, NULL, 0, &ev, 1, NULL) == 1, 466 FMT_ERR("kevent")); 467 ATF_REQUIRE_MSG((ev.flags & EV_ERROR) == 0, "EV_ERROR is set"); 468 ATF_REQUIRE_MSG(ev.data == sizeof(buf), 469 "data is %jd", (intmax_t)ev.data); 470 EV_SET(&ev, pathfd, EVFILT_READ, EV_DELETE, 0, 0, 0); 471 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 472 FMT_ERR("kevent")); 473 474 /* Try to get a EVFILT_VNODE/NOTE_LINK event through a path fd. */ 475 EV_SET(&ev, pathfd, EVFILT_VNODE, EV_ADD | EV_ENABLE, NOTE_LINK, 0, 0); 476 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 477 FMT_ERR("kevent")); 478 ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0, 479 FMT_ERR("funlinkat")); 480 ATF_REQUIRE_MSG(kevent(kq, NULL, 0, &ev, 1, NULL) == 1, 481 FMT_ERR("kevent")); 482 EV_SET(&ev, pathfd, EVFILT_VNODE, EV_DELETE, 0, 0, 0); 483 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 484 FMT_ERR("kevent")); 485 486 CHECKED_CLOSE(kq); 487 CHECKED_CLOSE(pathfd); 488 } 489 490 /* Check various fcntl(2) operations on a path desriptor. */ 491 ATF_TC_WITHOUT_HEAD(path_fcntl); 492 ATF_TC_BODY(path_fcntl, tc) 493 { 494 char path[PATH_MAX]; 495 int flags, pathfd, pathfd2; 496 497 mktfile(path, "path_fcntl.XXXXXX"); 498 499 pathfd = open(path, O_PATH); 500 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 501 502 /* O_PATH should appear in the fd flags. */ 503 flags = fcntl(pathfd, F_GETFL); 504 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 505 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set"); 506 507 ATF_REQUIRE_ERRNO(EBADF, 508 fcntl(pathfd, F_SETFL, flags & ~O_PATH)); 509 ATF_REQUIRE_ERRNO(EBADF, 510 fcntl(pathfd, F_SETFL, flags | O_APPEND)); 511 512 /* A dup'ed O_PATH fd had better have O_PATH set too. */ 513 pathfd2 = fcntl(pathfd, F_DUPFD, 0); 514 ATF_REQUIRE_MSG(pathfd2 >= 0, FMT_ERR("fcntl")); 515 flags = fcntl(pathfd2, F_GETFL); 516 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 517 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set"); 518 CHECKED_CLOSE(pathfd2); 519 520 /* Double check with dup(2). */ 521 pathfd2 = dup(pathfd); 522 ATF_REQUIRE_MSG(pathfd2 >= 0, FMT_ERR("dup")); 523 flags = fcntl(pathfd2, F_GETFL); 524 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 525 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set"); 526 CHECKED_CLOSE(pathfd2); 527 528 /* It should be possible to set O_CLOEXEC. */ 529 ATF_REQUIRE_MSG(fcntl(pathfd, F_SETFD, FD_CLOEXEC) == 0, 530 FMT_ERR("fcntl")); 531 ATF_REQUIRE_MSG(fcntl(pathfd, F_GETFD) == FD_CLOEXEC, 532 FMT_ERR("fcntl")); 533 534 CHECKED_CLOSE(pathfd); 535 } 536 537 /* Verify that we can execute a file opened with O_PATH. */ 538 ATF_TC_WITHOUT_HEAD(path_fexecve); 539 ATF_TC_BODY(path_fexecve, tc) 540 { 541 char path[PATH_MAX]; 542 pid_t child; 543 int fd, pathfd; 544 545 child = fork(); 546 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork")); 547 if (child == 0) { 548 pathfd = open("/usr/bin/true", O_PATH | O_EXEC); 549 if (pathfd < 0) 550 _exit(1); 551 fexecve(pathfd, 552 (char * const[]){__DECONST(char *, "/usr/bin/true"), NULL}, 553 NULL); 554 _exit(2); 555 } 556 waitchild(child, 0); 557 558 /* 559 * Also verify that access permissions are checked when opening with 560 * O_PATH. 561 */ 562 snprintf(path, sizeof(path), "path_fexecve.XXXXXX"); 563 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 564 565 fd = open(path, O_CREAT | O_RDONLY, 0600); 566 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("open")); 567 568 pathfd = open(path, O_PATH | O_EXEC); 569 ATF_REQUIRE_ERRNO(EACCES, pathfd < 0); 570 } 571 572 /* Make sure that O_PATH restrictions apply to named pipes as well. */ 573 ATF_TC_WITHOUT_HEAD(path_fifo); 574 ATF_TC_BODY(path_fifo, tc) 575 { 576 char path[PATH_MAX], buf[BUFSIZ]; 577 struct kevent ev; 578 int kq, pathfd; 579 580 snprintf(path, sizeof(path), "path_fifo.XXXXXX"); 581 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 582 583 ATF_REQUIRE_MSG(mkfifo(path, 0666) == 0, FMT_ERR("mkfifo")); 584 585 pathfd = open(path, O_PATH); 586 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 587 memset(buf, 0, sizeof(buf)); 588 ATF_REQUIRE_ERRNO(EBADF, write(pathfd, buf, sizeof(buf))); 589 ATF_REQUIRE_ERRNO(EBADF, read(pathfd, buf, sizeof(buf))); 590 591 kq = kqueue(); 592 ATF_REQUIRE_MSG(kq >= 0, FMT_ERR("kqueue")); 593 EV_SET(&ev, pathfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); 594 ATF_REQUIRE_ERRNO(EBADF, kevent(kq, &ev, 1, NULL, 0, NULL) == -1); 595 596 CHECKED_CLOSE(pathfd); 597 } 598 599 /* Files may be unlinked using a path fd. */ 600 ATF_TC_WITHOUT_HEAD(path_funlinkat); 601 ATF_TC_BODY(path_funlinkat, tc) 602 { 603 char path[PATH_MAX]; 604 struct stat sb; 605 int pathfd; 606 607 mktfile(path, "path_rights.XXXXXX"); 608 609 pathfd = open(path, O_PATH); 610 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 611 612 ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0, 613 FMT_ERR("funlinkat")); 614 ATF_REQUIRE_ERRNO(ENOENT, stat(path, &sb) == -1); 615 616 CHECKED_CLOSE(pathfd); 617 } 618 619 /* Verify that various I/O operations fail on an O_PATH descriptor. */ 620 ATF_TC_WITHOUT_HEAD(path_io); 621 ATF_TC_BODY(path_io, tc) 622 { 623 char path[PATH_MAX], path2[PATH_MAX]; 624 char buf[BUFSIZ]; 625 struct iovec iov; 626 int error, fd, pathfd, sd[2]; 627 628 /* It shouldn't be possible to create new files with O_PATH. */ 629 snprintf(path, sizeof(path), "path_io.XXXXXX"); 630 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 631 ATF_REQUIRE_ERRNO(ENOENT, open(path, O_PATH | O_CREAT, 0600) < 0); 632 633 /* Create a non-empty file for use in the rest of the tests. */ 634 mktfile(path, "path_io.XXXXXX"); 635 636 pathfd = open(path, O_PATH); 637 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 638 639 /* Make sure that basic I/O operations aren't possible. */ 640 iov.iov_base = path; 641 iov.iov_len = strlen(path); 642 ATF_REQUIRE_ERRNO(EBADF, 643 write(pathfd, iov.iov_base, iov.iov_len) == -1); 644 ATF_REQUIRE_ERRNO(EBADF, 645 pwrite(pathfd, iov.iov_base, iov.iov_len, 0) == -1); 646 ATF_REQUIRE_ERRNO(EBADF, 647 writev(pathfd, &iov, 1) == -1); 648 ATF_REQUIRE_ERRNO(EBADF, 649 pwritev(pathfd, &iov, 1, 0) == -1); 650 ATF_REQUIRE_ERRNO(EBADF, 651 read(pathfd, path, 1) == -1); 652 ATF_REQUIRE_ERRNO(EBADF, 653 pread(pathfd, path, 1, 0) == -1); 654 ATF_REQUIRE_ERRNO(EBADF, 655 readv(pathfd, &iov, 1) == -1); 656 ATF_REQUIRE_ERRNO(EBADF, 657 preadv(pathfd, &iov, 1, 0) == -1); 658 659 /* copy_file_range() should not be permitted. */ 660 mktfile(path2, "path_io.XXXXXX"); 661 fd = open(path2, O_RDWR); 662 ATF_REQUIRE_ERRNO(EBADF, 663 copy_file_range(fd, NULL, pathfd, NULL, sizeof(buf), 0) == -1); 664 ATF_REQUIRE_ERRNO(EBADF, 665 copy_file_range(pathfd, NULL, fd, NULL, sizeof(buf), 0) == -1); 666 CHECKED_CLOSE(fd); 667 668 /* sendfile() should not be permitted. */ 669 ATF_REQUIRE_MSG(socketpair(PF_LOCAL, SOCK_STREAM, 0, sd) == 0, 670 FMT_ERR("socketpair")); 671 ATF_REQUIRE_ERRNO(EBADF, 672 sendfile(pathfd, sd[0], 0, 0, NULL, NULL, 0)); 673 CHECKED_CLOSE(sd[0]); 674 CHECKED_CLOSE(sd[1]); 675 676 /* No seeking. */ 677 ATF_REQUIRE_ERRNO(ESPIPE, 678 lseek(pathfd, 0, SEEK_SET) == -1); 679 680 /* No operations on the file extent. */ 681 ATF_REQUIRE_ERRNO(EINVAL, 682 ftruncate(pathfd, 0) == -1); 683 error = posix_fallocate(pathfd, 0, sizeof(buf) * 2); 684 ATF_REQUIRE_MSG(error == ESPIPE, "posix_fallocate() returned %d", error); 685 error = posix_fadvise(pathfd, 0, sizeof(buf), POSIX_FADV_NORMAL); 686 ATF_REQUIRE_MSG(error == ESPIPE, "posix_fadvise() returned %d", error); 687 688 /* mmap() is not allowed. */ 689 ATF_REQUIRE_ERRNO(ENODEV, 690 mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, pathfd, 0) == 691 MAP_FAILED); 692 ATF_REQUIRE_ERRNO(ENODEV, 693 mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_SHARED, pathfd, 0) == 694 MAP_FAILED); 695 ATF_REQUIRE_ERRNO(ENODEV, 696 mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, pathfd, 0) == 697 MAP_FAILED); 698 699 /* No fsync() or fdatasync(). */ 700 ATF_REQUIRE_ERRNO(EBADF, fsync(pathfd) == -1); 701 ATF_REQUIRE_ERRNO(EBADF, fdatasync(pathfd) == -1); 702 703 CHECKED_CLOSE(pathfd); 704 } 705 706 /* ioctl(2) is not permitted on path fds. */ 707 ATF_TC_WITHOUT_HEAD(path_ioctl); 708 ATF_TC_BODY(path_ioctl, tc) 709 { 710 char path[PATH_MAX]; 711 struct mem_extract me; 712 int pathfd, val; 713 714 mktfile(path, "path_ioctl.XXXXXX"); 715 716 /* Standard file descriptor ioctls should fail. */ 717 pathfd = open(path, O_PATH); 718 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 719 720 val = 0; 721 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONBIO, &val) == -1); 722 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONREAD, &val) == -1); 723 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONWRITE, &val) == -1); 724 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONSPACE, &val) == -1); 725 726 CHECKED_CLOSE(pathfd); 727 728 /* Device ioctls should fail. */ 729 pathfd = open("/dev/mem", O_PATH); 730 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 731 732 me.me_vaddr = (uintptr_t)&me; 733 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, MEM_EXTRACT_PADDR, &me) == -1); 734 735 CHECKED_CLOSE(pathfd); 736 } 737 738 ATF_TC_WITHOUT_HEAD(path_lock); 739 ATF_TC_BODY(path_lock, tc) 740 { 741 char buf[BUFSIZ], path[PATH_MAX]; 742 struct flock flk; 743 int fd, pathfd; 744 745 snprintf(path, sizeof(path), "path_rights.XXXXXX"); 746 fd = mkostemp(path, O_SHLOCK); 747 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("mkostemp")); 748 memset(buf, 0, sizeof(buf)); 749 ATF_REQUIRE_MSG(write(fd, buf, sizeof(buf)) == sizeof(buf), 750 FMT_ERR("write()")); 751 752 /* Verify that O_EXLOCK is ignored when combined with O_PATH. */ 753 pathfd = open(path, O_PATH | O_EXLOCK); 754 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 755 756 CHECKED_CLOSE(fd); 757 758 /* flock(2) is prohibited. */ 759 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_SH) == -1); 760 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_EX) == -1); 761 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_SH | LOCK_NB) == -1); 762 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_EX | LOCK_NB) == -1); 763 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_UN) == -1); 764 765 /* fcntl(2) file locks are prohibited. */ 766 memset(&flk, 0, sizeof(flk)); 767 flk.l_whence = SEEK_CUR; 768 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_GETLK, &flk) == -1); 769 flk.l_type = F_RDLCK; 770 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLK, &flk) == -1); 771 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLKW, &flk) == -1); 772 flk.l_type = F_WRLCK; 773 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLK, &flk) == -1); 774 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLKW, &flk) == -1); 775 776 CHECKED_CLOSE(pathfd); 777 } 778 779 /* Verify that we can send an O_PATH descriptor over a unix socket. */ 780 ATF_TC_WITHOUT_HEAD(path_rights); 781 ATF_TC_BODY(path_rights, tc) 782 { 783 char path[PATH_MAX]; 784 struct cmsghdr *cmsg; 785 struct msghdr msg; 786 struct iovec iov; 787 int flags, pathfd, pathfd_copy, sd[2]; 788 char c; 789 790 ATF_REQUIRE_MSG(socketpair(PF_LOCAL, SOCK_STREAM, 0, sd) == 0, 791 FMT_ERR("socketpair")); 792 793 mktfile(path, "path_rights.XXXXXX"); 794 795 pathfd = open(path, O_PATH); 796 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 797 798 /* Package up the O_PATH and send it over the socket pair. */ 799 cmsg = malloc(CMSG_SPACE(sizeof(pathfd))); 800 ATF_REQUIRE_MSG(cmsg != NULL, FMT_ERR("malloc")); 801 802 cmsg->cmsg_len = CMSG_LEN(sizeof(pathfd)); 803 cmsg->cmsg_level = SOL_SOCKET; 804 cmsg->cmsg_type = SCM_RIGHTS; 805 *(int *)(void *)CMSG_DATA(cmsg) = pathfd; 806 807 c = 0; 808 iov.iov_base = &c; 809 iov.iov_len = 1; 810 811 memset(&msg, 0, sizeof(msg)); 812 msg.msg_iov = &iov; 813 msg.msg_iovlen = 1; 814 msg.msg_control = cmsg; 815 msg.msg_controllen = CMSG_SPACE(sizeof(pathfd)); 816 817 ATF_REQUIRE_MSG(sendmsg(sd[0], &msg, 0) == sizeof(c), 818 FMT_ERR("sendmsg")); 819 820 /* Grab the pathfd copy from the other end of the pair. */ 821 memset(&msg, 0, sizeof(msg)); 822 msg.msg_iov = &iov; 823 msg.msg_iovlen = 1; 824 msg.msg_control = cmsg; 825 msg.msg_controllen = CMSG_SPACE(sizeof(pathfd)); 826 827 ATF_REQUIRE_MSG(recvmsg(sd[1], &msg, 0) == 1, 828 FMT_ERR("recvmsg")); 829 pathfd_copy = *(int *)(void *)CMSG_DATA(cmsg); 830 ATF_REQUIRE_MSG(pathfd_copy != pathfd, 831 "pathfd and pathfd_copy are equal"); 832 833 /* Verify that the copy has O_PATH properties. */ 834 flags = fcntl(pathfd_copy, F_GETFL); 835 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 836 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH is not set"); 837 ATF_REQUIRE_ERRNO(EBADF, 838 read(pathfd_copy, &c, 1) == -1); 839 ATF_REQUIRE_ERRNO(EBADF, 840 write(pathfd_copy, &c, 1) == -1); 841 842 CHECKED_CLOSE(pathfd); 843 CHECKED_CLOSE(pathfd_copy); 844 CHECKED_CLOSE(sd[0]); 845 CHECKED_CLOSE(sd[1]); 846 } 847 848 /* Verify that a local socket can't be opened with O_PATH. */ 849 ATF_TC_WITHOUT_HEAD(path_unix); 850 ATF_TC_BODY(path_unix, tc) 851 { 852 char path[PATH_MAX]; 853 struct sockaddr_un sun; 854 int pathfd, sd; 855 856 snprintf(path, sizeof(path), "path_unix.XXXXXX"); 857 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 858 859 sd = socket(PF_LOCAL, SOCK_STREAM, 0); 860 ATF_REQUIRE_MSG(sd >= 0, FMT_ERR("socket")); 861 862 memset(&sun, 0, sizeof(sun)); 863 sun.sun_family = PF_LOCAL; 864 (void)strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 865 ATF_REQUIRE_MSG(bind(sd, (struct sockaddr *)&sun, SUN_LEN(&sun)) == 0, 866 FMT_ERR("bind")); 867 868 pathfd = open(path, O_RDONLY); 869 ATF_REQUIRE_ERRNO(EOPNOTSUPP, pathfd < 0); 870 871 CHECKED_CLOSE(sd); 872 } 873 874 ATF_TP_ADD_TCS(tp) 875 { 876 ATF_TP_ADD_TC(tp, path_access); 877 ATF_TP_ADD_TC(tp, path_aio); 878 ATF_TP_ADD_TC(tp, path_capsicum); 879 ATF_TP_ADD_TC(tp, path_coredump); 880 ATF_TP_ADD_TC(tp, path_directory); 881 ATF_TP_ADD_TC(tp, path_directory_not_root); 882 ATF_TP_ADD_TC(tp, path_empty); 883 ATF_TP_ADD_TC(tp, path_empty_not_root); 884 ATF_TP_ADD_TC(tp, path_empty_root); 885 ATF_TP_ADD_TC(tp, path_event); 886 ATF_TP_ADD_TC(tp, path_fcntl); 887 ATF_TP_ADD_TC(tp, path_fexecve); 888 ATF_TP_ADD_TC(tp, path_fifo); 889 ATF_TP_ADD_TC(tp, path_funlinkat); 890 ATF_TP_ADD_TC(tp, path_io); 891 ATF_TP_ADD_TC(tp, path_ioctl); 892 ATF_TP_ADD_TC(tp, path_lock); 893 ATF_TP_ADD_TC(tp, path_rights); 894 ATF_TP_ADD_TC(tp, path_unix); 895 ATF_TP_ADD_TC(tp, path_pipe_fstatat); 896 897 return (atf_no_error()); 898 } 899