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 /* 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 /* Make sure that ptrace(PT_COREDUMP) cannot be used to write to a path fd. */ 212 ATF_TC_WITHOUT_HEAD(path_coredump); 213 ATF_TC_BODY(path_coredump, tc) 214 { 215 char path[PATH_MAX]; 216 struct ptrace_coredump pc; 217 int error, pathfd, status; 218 pid_t child; 219 220 mktdir(path, "path_coredump.XXXXXX"); 221 222 child = fork(); 223 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork")); 224 if (child == 0) { 225 while (true) 226 (void)sleep(1); 227 } 228 229 pathfd = open(path, O_PATH); 230 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 231 232 error = ptrace(PT_ATTACH, child, 0, 0); 233 ATF_REQUIRE_MSG(error == 0, FMT_ERR("ptrace")); 234 error = waitpid(child, &status, 0); 235 ATF_REQUIRE_MSG(error != -1, FMT_ERR("waitpid")); 236 ATF_REQUIRE_MSG(WIFSTOPPED(status), "unexpected status %d", status); 237 238 pc.pc_fd = pathfd; 239 pc.pc_flags = 0; 240 pc.pc_limit = 0; 241 error = ptrace(PT_COREDUMP, child, (void *)&pc, sizeof(pc)); 242 ATF_REQUIRE_ERRNO(EBADF, error == -1); 243 244 error = ptrace(PT_DETACH, child, 0, 0); 245 ATF_REQUIRE_MSG(error == 0, FMT_ERR("ptrace")); 246 247 ATF_REQUIRE_MSG(kill(child, SIGKILL) == 0, FMT_ERR("kill")); 248 249 CHECKED_CLOSE(pathfd); 250 } 251 252 /* Verify operations on directory path descriptors. */ 253 ATF_TC_WITHOUT_HEAD(path_directory); 254 ATF_TC_BODY(path_directory, tc) 255 { 256 struct dirent de; 257 struct stat sb; 258 char path[PATH_MAX]; 259 int fd, pathfd; 260 261 mktdir(path, "path_directory.XXXXXX"); 262 263 pathfd = open(path, O_PATH | O_DIRECTORY); 264 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 265 266 /* Should not be possible to list directory entries. */ 267 ATF_REQUIRE_ERRNO(EBADF, 268 getdirentries(pathfd, (char *)&de, sizeof(de), NULL) == -1); 269 270 /* It should be possible to create files under pathfd. */ 271 fd = openat(pathfd, "test", O_RDWR | O_CREAT, 0600); 272 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("open")); 273 ATF_REQUIRE_MSG(fstatat(pathfd, "test", &sb, 0) == 0, 274 FMT_ERR("fstatat")); 275 CHECKED_CLOSE(fd); 276 277 /* ... but doing so requires write access. */ 278 if (geteuid() != 0) { 279 ATF_REQUIRE_ERRNO(EBADF, fchmod(pathfd, 0500) == -1); 280 ATF_REQUIRE_MSG(chmod(path, 0500) == 0, FMT_ERR("chmod")); 281 ATF_REQUIRE_ERRNO(EACCES, 282 openat(pathfd, "test2", O_RDWR | O_CREAT, 0600) < 0); 283 } 284 285 /* fchdir(2) is permitted. */ 286 ATF_REQUIRE_MSG(fchdir(pathfd) == 0, FMT_ERR("fchdir")); 287 288 CHECKED_CLOSE(pathfd); 289 } 290 291 /* Verify access permission checking for a directory path fd. */ 292 ATF_TC_WITH_CLEANUP(path_directory_not_root); 293 ATF_TC_HEAD(path_directory_not_root, tc) 294 { 295 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 296 } 297 ATF_TC_BODY(path_directory_not_root, tc) 298 { 299 char path[PATH_MAX]; 300 int pathfd; 301 302 mktdir(path, "path_directory.XXXXXX"); 303 304 pathfd = open(path, O_PATH | O_DIRECTORY); 305 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 306 307 ATF_REQUIRE_ERRNO(EBADF, fchmod(pathfd, 0500) == -1); 308 ATF_REQUIRE_MSG(chmod(path, 0500) == 0, FMT_ERR("chmod")); 309 ATF_REQUIRE_ERRNO(EACCES, 310 openat(pathfd, "test2", O_RDWR | O_CREAT, 0600) < 0); 311 312 CHECKED_CLOSE(pathfd); 313 } 314 ATF_TC_CLEANUP(path_directory_not_root, tc) 315 { 316 } 317 318 /* Validate system calls that handle AT_EMPTY_PATH. */ 319 ATF_TC_WITHOUT_HEAD(path_empty); 320 ATF_TC_BODY(path_empty, tc) 321 { 322 char path[PATH_MAX]; 323 struct timespec ts[2]; 324 struct stat sb; 325 int pathfd; 326 327 mktfile(path, "path_empty.XXXXXX"); 328 329 pathfd = open(path, O_PATH); 330 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 331 332 /* Various *at operations should work on path fds. */ 333 ATF_REQUIRE_MSG(faccessat(pathfd, "", F_OK, AT_EMPTY_PATH) == 0, 334 FMT_ERR("faccessat")); 335 ATF_REQUIRE_MSG(chflagsat(pathfd, "", UF_NODUMP, AT_EMPTY_PATH) == 0, 336 FMT_ERR("chflagsat")); 337 ATF_REQUIRE_MSG(fchmodat(pathfd, "", 0600, AT_EMPTY_PATH) == 0, 338 FMT_ERR("fchmodat")); 339 ATF_REQUIRE_MSG(fchownat(pathfd, "", getuid(), getgid(), 340 AT_EMPTY_PATH) == 0, FMT_ERR("fchownat")); 341 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 342 FMT_ERR("fstatat")); 343 ATF_REQUIRE_MSG(sb.st_size == BUFSIZ, 344 "unexpected size %ju", (uintmax_t)sb.st_size); 345 memset(ts, 0, sizeof(ts)); 346 ATF_REQUIRE_MSG(utimensat(pathfd, "", ts, AT_EMPTY_PATH) == 0, 347 FMT_ERR("utimensat")); 348 349 CHECKED_CLOSE(pathfd); 350 } 351 352 /* Verify that various operations on a path fd have access checks. */ 353 ATF_TC_WITH_CLEANUP(path_empty_not_root); 354 ATF_TC_HEAD(path_empty_not_root, tc) 355 { 356 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 357 } 358 ATF_TC_BODY(path_empty_not_root, tc) 359 { 360 int pathfd; 361 362 pathfd = open("/dev/null", O_PATH); 363 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 364 365 ATF_REQUIRE_ERRNO(EPERM, 366 chflagsat(pathfd, "", UF_NODUMP, AT_EMPTY_PATH) == -1); 367 ATF_REQUIRE_ERRNO(EPERM, 368 fchownat(pathfd, "", getuid(), getgid(), AT_EMPTY_PATH) == -1); 369 ATF_REQUIRE_ERRNO(EPERM, 370 fchmodat(pathfd, "", 0600, AT_EMPTY_PATH) == -1); 371 ATF_REQUIRE_ERRNO(EPERM, 372 linkat(pathfd, "", AT_FDCWD, "test", AT_EMPTY_PATH) == -1); 373 374 CHECKED_CLOSE(pathfd); 375 } 376 ATF_TC_CLEANUP(path_empty_not_root, tc) 377 { 378 } 379 380 /* Test linkat(2) with AT_EMPTY_PATH, which requires privileges. */ 381 ATF_TC_WITH_CLEANUP(path_empty_root); 382 ATF_TC_HEAD(path_empty_root, tc) 383 { 384 atf_tc_set_md_var(tc, "require.user", "root"); 385 } 386 ATF_TC_BODY(path_empty_root, tc) 387 { 388 char path[PATH_MAX]; 389 struct stat sb, sb2; 390 int pathfd; 391 392 mktfile(path, "path_empty_root.XXXXXX"); 393 394 pathfd = open(path, O_PATH); 395 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 396 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 397 FMT_ERR("fstatat")); 398 399 ATF_REQUIRE_MSG(linkat(pathfd, "", AT_FDCWD, "test", AT_EMPTY_PATH) == 400 0, FMT_ERR("linkat")); 401 ATF_REQUIRE_MSG(fstatat(AT_FDCWD, "test", &sb2, 0) == 0, 402 FMT_ERR("fstatat")); 403 ATF_REQUIRE_MSG(sb.st_dev == sb2.st_dev, "st_dev mismatch"); 404 ATF_REQUIRE_MSG(sb.st_ino == sb2.st_ino, "st_ino mismatch"); 405 406 CHECKED_CLOSE(pathfd); 407 408 } 409 ATF_TC_CLEANUP(path_empty_root, tc) 410 { 411 } 412 413 /* poll(2) never returns an event for path fds, but kevent(2) does. */ 414 ATF_TC_WITHOUT_HEAD(path_event); 415 ATF_TC_BODY(path_event, tc) 416 { 417 char buf[BUFSIZ], path[PATH_MAX]; 418 struct kevent ev; 419 struct pollfd pollfd; 420 int kq, pathfd; 421 422 mktfile(path, "path_event.XXXXXX"); 423 424 pathfd = open(path, O_PATH); 425 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 426 427 /* poll(2) should return POLLNVAL. */ 428 pollfd.fd = pathfd; 429 pollfd.events = POLLIN; 430 pollfd.revents = 0; 431 ATF_REQUIRE_MSG(poll(&pollfd, 1, 0) == 1, FMT_ERR("poll")); 432 ATF_REQUIRE_MSG(pollfd.revents == POLLNVAL, "unexpected revents %x", 433 pollfd.revents); 434 pollfd.events = POLLOUT; 435 pollfd.revents = 0; 436 ATF_REQUIRE_MSG(poll(&pollfd, 1, 0) == 1, FMT_ERR("poll")); 437 ATF_REQUIRE_MSG(pollfd.revents == POLLNVAL, "unexpected revents %x", 438 pollfd.revents); 439 440 /* Try to get a EVFILT_READ event through a path fd. */ 441 kq = kqueue(); 442 ATF_REQUIRE_MSG(kq >= 0, FMT_ERR("kqueue")); 443 EV_SET(&ev, pathfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); 444 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 445 FMT_ERR("kevent")); 446 ATF_REQUIRE_MSG(kevent(kq, NULL, 0, &ev, 1, NULL) == 1, 447 FMT_ERR("kevent")); 448 ATF_REQUIRE_MSG((ev.flags & EV_ERROR) == 0, "EV_ERROR is set"); 449 ATF_REQUIRE_MSG(ev.data == sizeof(buf), 450 "data is %jd", (intmax_t)ev.data); 451 EV_SET(&ev, pathfd, EVFILT_READ, EV_DELETE, 0, 0, 0); 452 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 453 FMT_ERR("kevent")); 454 455 /* Try to get a EVFILT_VNODE/NOTE_DELETE event through a path fd. */ 456 EV_SET(&ev, pathfd, EVFILT_VNODE, EV_ADD | EV_ENABLE, NOTE_DELETE, 0, 457 0); 458 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 459 FMT_ERR("kevent")); 460 ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0, 461 FMT_ERR("funlinkat")); 462 ATF_REQUIRE_MSG(kevent(kq, NULL, 0, &ev, 1, NULL) == 1, 463 FMT_ERR("kevent")); 464 ATF_REQUIRE_MSG(ev.fflags == NOTE_DELETE, 465 "unexpected fflags %#x", ev.fflags); 466 EV_SET(&ev, pathfd, EVFILT_VNODE, EV_DELETE, 0, 0, 0); 467 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0, 468 FMT_ERR("kevent")); 469 470 CHECKED_CLOSE(kq); 471 CHECKED_CLOSE(pathfd); 472 } 473 474 /* Check various fcntl(2) operations on a path desriptor. */ 475 ATF_TC_WITHOUT_HEAD(path_fcntl); 476 ATF_TC_BODY(path_fcntl, tc) 477 { 478 char path[PATH_MAX]; 479 int flags, pathfd, pathfd2; 480 481 mktfile(path, "path_fcntl.XXXXXX"); 482 483 pathfd = open(path, O_PATH); 484 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 485 486 /* O_PATH should appear in the fd flags. */ 487 flags = fcntl(pathfd, F_GETFL); 488 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 489 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set"); 490 491 ATF_REQUIRE_ERRNO(EBADF, 492 fcntl(pathfd, F_SETFL, flags & ~O_PATH)); 493 ATF_REQUIRE_ERRNO(EBADF, 494 fcntl(pathfd, F_SETFL, flags | O_APPEND)); 495 496 /* A dup'ed O_PATH fd had better have O_PATH set too. */ 497 pathfd2 = fcntl(pathfd, F_DUPFD, 0); 498 ATF_REQUIRE_MSG(pathfd2 >= 0, FMT_ERR("fcntl")); 499 flags = fcntl(pathfd2, F_GETFL); 500 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 501 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set"); 502 CHECKED_CLOSE(pathfd2); 503 504 /* Double check with dup(2). */ 505 pathfd2 = dup(pathfd); 506 ATF_REQUIRE_MSG(pathfd2 >= 0, FMT_ERR("dup")); 507 flags = fcntl(pathfd2, F_GETFL); 508 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 509 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set"); 510 CHECKED_CLOSE(pathfd2); 511 512 /* It should be possible to set O_CLOEXEC. */ 513 ATF_REQUIRE_MSG(fcntl(pathfd, F_SETFD, FD_CLOEXEC) == 0, 514 FMT_ERR("fcntl")); 515 ATF_REQUIRE_MSG(fcntl(pathfd, F_GETFD) == FD_CLOEXEC, 516 FMT_ERR("fcntl")); 517 518 CHECKED_CLOSE(pathfd); 519 } 520 521 /* Verify that we can execute a file opened with O_PATH. */ 522 ATF_TC_WITHOUT_HEAD(path_fexecve); 523 ATF_TC_BODY(path_fexecve, tc) 524 { 525 char path[PATH_MAX]; 526 pid_t child; 527 int fd, pathfd; 528 529 child = fork(); 530 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork")); 531 if (child == 0) { 532 pathfd = open("/usr/bin/true", O_PATH | O_EXEC); 533 if (pathfd < 0) 534 _exit(1); 535 fexecve(pathfd, 536 (char * const[]){__DECONST(char *, "/usr/bin/true"), NULL}, 537 NULL); 538 _exit(2); 539 } 540 waitchild(child, 0); 541 542 /* 543 * Also verify that access permissions are checked when opening with 544 * O_PATH. 545 */ 546 snprintf(path, sizeof(path), "path_fexecve.XXXXXX"); 547 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 548 549 fd = open(path, O_CREAT | O_RDONLY, 0600); 550 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("open")); 551 552 pathfd = open(path, O_PATH | O_EXEC); 553 ATF_REQUIRE_ERRNO(EACCES, pathfd < 0); 554 } 555 556 /* Make sure that O_PATH restrictions apply to named pipes as well. */ 557 ATF_TC_WITHOUT_HEAD(path_fifo); 558 ATF_TC_BODY(path_fifo, tc) 559 { 560 char path[PATH_MAX], buf[BUFSIZ]; 561 struct kevent ev; 562 int kq, pathfd; 563 564 snprintf(path, sizeof(path), "path_fifo.XXXXXX"); 565 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 566 567 ATF_REQUIRE_MSG(mkfifo(path, 0666) == 0, FMT_ERR("mkfifo")); 568 569 pathfd = open(path, O_PATH); 570 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 571 memset(buf, 0, sizeof(buf)); 572 ATF_REQUIRE_ERRNO(EBADF, write(pathfd, buf, sizeof(buf))); 573 ATF_REQUIRE_ERRNO(EBADF, read(pathfd, buf, sizeof(buf))); 574 575 kq = kqueue(); 576 ATF_REQUIRE_MSG(kq >= 0, FMT_ERR("kqueue")); 577 EV_SET(&ev, pathfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); 578 ATF_REQUIRE_ERRNO(EBADF, kevent(kq, &ev, 1, NULL, 0, NULL) == -1); 579 580 CHECKED_CLOSE(pathfd); 581 } 582 583 /* Files may be unlinked using a path fd. */ 584 ATF_TC_WITHOUT_HEAD(path_funlinkat); 585 ATF_TC_BODY(path_funlinkat, tc) 586 { 587 char path[PATH_MAX]; 588 struct stat sb; 589 int pathfd; 590 591 mktfile(path, "path_rights.XXXXXX"); 592 593 pathfd = open(path, O_PATH); 594 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 595 596 ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0, 597 FMT_ERR("funlinkat")); 598 ATF_REQUIRE_ERRNO(ENOENT, stat(path, &sb) == -1); 599 600 CHECKED_CLOSE(pathfd); 601 } 602 603 /* Verify that various I/O operations fail on an O_PATH descriptor. */ 604 ATF_TC_WITHOUT_HEAD(path_io); 605 ATF_TC_BODY(path_io, tc) 606 { 607 char path[PATH_MAX], path2[PATH_MAX]; 608 char buf[BUFSIZ]; 609 struct iovec iov; 610 size_t page_size; 611 int error, fd, pathfd, sd[2]; 612 613 /* It shouldn't be possible to create new files with O_PATH. */ 614 snprintf(path, sizeof(path), "path_io.XXXXXX"); 615 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 616 ATF_REQUIRE_ERRNO(ENOENT, open(path, O_PATH | O_CREAT, 0600) < 0); 617 618 /* Create a non-empty file for use in the rest of the tests. */ 619 mktfile(path, "path_io.XXXXXX"); 620 621 pathfd = open(path, O_PATH); 622 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 623 624 /* Make sure that basic I/O operations aren't possible. */ 625 iov.iov_base = path; 626 iov.iov_len = strlen(path); 627 ATF_REQUIRE_ERRNO(EBADF, 628 write(pathfd, iov.iov_base, iov.iov_len) == -1); 629 ATF_REQUIRE_ERRNO(EBADF, 630 pwrite(pathfd, iov.iov_base, iov.iov_len, 0) == -1); 631 ATF_REQUIRE_ERRNO(EBADF, 632 writev(pathfd, &iov, 1) == -1); 633 ATF_REQUIRE_ERRNO(EBADF, 634 pwritev(pathfd, &iov, 1, 0) == -1); 635 ATF_REQUIRE_ERRNO(EBADF, 636 read(pathfd, path, 1) == -1); 637 ATF_REQUIRE_ERRNO(EBADF, 638 pread(pathfd, path, 1, 0) == -1); 639 ATF_REQUIRE_ERRNO(EBADF, 640 readv(pathfd, &iov, 1) == -1); 641 ATF_REQUIRE_ERRNO(EBADF, 642 preadv(pathfd, &iov, 1, 0) == -1); 643 644 /* copy_file_range() should not be permitted. */ 645 mktfile(path2, "path_io.XXXXXX"); 646 fd = open(path2, O_RDWR); 647 ATF_REQUIRE_ERRNO(EBADF, 648 copy_file_range(fd, NULL, pathfd, NULL, sizeof(buf), 0) == -1); 649 ATF_REQUIRE_ERRNO(EBADF, 650 copy_file_range(pathfd, NULL, fd, NULL, sizeof(buf), 0) == -1); 651 CHECKED_CLOSE(fd); 652 653 /* sendfile() should not be permitted. */ 654 ATF_REQUIRE_MSG(socketpair(PF_LOCAL, SOCK_STREAM, 0, sd) == 0, 655 FMT_ERR("socketpair")); 656 ATF_REQUIRE_ERRNO(EBADF, 657 sendfile(pathfd, sd[0], 0, 0, NULL, NULL, 0)); 658 CHECKED_CLOSE(sd[0]); 659 CHECKED_CLOSE(sd[1]); 660 661 /* No seeking. */ 662 ATF_REQUIRE_ERRNO(ESPIPE, 663 lseek(pathfd, 0, SEEK_SET) == -1); 664 665 /* No operations on the file extent. */ 666 ATF_REQUIRE_ERRNO(EINVAL, 667 ftruncate(pathfd, 0) == -1); 668 error = posix_fallocate(pathfd, 0, sizeof(buf) * 2); 669 ATF_REQUIRE_MSG(error == ESPIPE, "posix_fallocate() returned %d", error); 670 error = posix_fadvise(pathfd, 0, sizeof(buf), POSIX_FADV_NORMAL); 671 ATF_REQUIRE_MSG(error == ESPIPE, "posix_fadvise() returned %d", error); 672 673 /* mmap() is not allowed. */ 674 page_size = getpagesize(); 675 ATF_REQUIRE_ERRNO(ENODEV, 676 mmap(NULL, page_size, PROT_READ, MAP_SHARED, pathfd, 0) == 677 MAP_FAILED); 678 ATF_REQUIRE_ERRNO(ENODEV, 679 mmap(NULL, page_size, PROT_NONE, MAP_SHARED, pathfd, 0) == 680 MAP_FAILED); 681 ATF_REQUIRE_ERRNO(ENODEV, 682 mmap(NULL, page_size, PROT_READ, MAP_PRIVATE, pathfd, 0) == 683 MAP_FAILED); 684 685 /* No fsync() or fdatasync(). */ 686 ATF_REQUIRE_ERRNO(EBADF, fsync(pathfd) == -1); 687 ATF_REQUIRE_ERRNO(EBADF, fdatasync(pathfd) == -1); 688 689 CHECKED_CLOSE(pathfd); 690 } 691 692 /* ioctl(2) is not permitted on path fds. */ 693 ATF_TC_WITHOUT_HEAD(path_ioctl); 694 ATF_TC_BODY(path_ioctl, tc) 695 { 696 char path[PATH_MAX]; 697 struct mem_extract me; 698 int pathfd, val; 699 700 mktfile(path, "path_ioctl.XXXXXX"); 701 702 /* Standard file descriptor ioctls should fail. */ 703 pathfd = open(path, O_PATH); 704 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 705 706 val = 0; 707 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONBIO, &val) == -1); 708 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONREAD, &val) == -1); 709 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONWRITE, &val) == -1); 710 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONSPACE, &val) == -1); 711 712 CHECKED_CLOSE(pathfd); 713 714 /* Device ioctls should fail. */ 715 pathfd = open("/dev/mem", O_PATH); 716 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 717 718 me.me_vaddr = (uintptr_t)&me; 719 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, MEM_EXTRACT_PADDR, &me) == -1); 720 721 CHECKED_CLOSE(pathfd); 722 } 723 724 ATF_TC_WITHOUT_HEAD(path_lock); 725 ATF_TC_BODY(path_lock, tc) 726 { 727 char buf[BUFSIZ], path[PATH_MAX]; 728 struct flock flk; 729 int fd, pathfd; 730 731 snprintf(path, sizeof(path), "path_rights.XXXXXX"); 732 fd = mkostemp(path, O_SHLOCK); 733 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("mkostemp")); 734 memset(buf, 0, sizeof(buf)); 735 ATF_REQUIRE_MSG(write(fd, buf, sizeof(buf)) == sizeof(buf), 736 FMT_ERR("write()")); 737 738 /* Verify that O_EXLOCK is ignored when combined with O_PATH. */ 739 pathfd = open(path, O_PATH | O_EXLOCK); 740 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 741 742 CHECKED_CLOSE(fd); 743 744 /* flock(2) is prohibited. */ 745 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_SH) == -1); 746 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_EX) == -1); 747 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_SH | LOCK_NB) == -1); 748 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_EX | LOCK_NB) == -1); 749 ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_UN) == -1); 750 751 /* fcntl(2) file locks are prohibited. */ 752 memset(&flk, 0, sizeof(flk)); 753 flk.l_whence = SEEK_CUR; 754 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_GETLK, &flk) == -1); 755 flk.l_type = F_RDLCK; 756 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLK, &flk) == -1); 757 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLKW, &flk) == -1); 758 flk.l_type = F_WRLCK; 759 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLK, &flk) == -1); 760 ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLKW, &flk) == -1); 761 762 CHECKED_CLOSE(pathfd); 763 } 764 765 /* 766 * Verify fstatat(AT_EMPTY_PATH) on non-regular dirfd. 767 * Verify that fstatat(AT_EMPTY_PATH) on NULL path returns EFAULT. 768 */ 769 ATF_TC_WITHOUT_HEAD(path_pipe_fstatat); 770 ATF_TC_BODY(path_pipe_fstatat, tc) 771 { 772 struct stat sb; 773 int fd[2]; 774 775 ATF_REQUIRE_MSG(pipe(fd) == 0, FMT_ERR("pipe")); 776 ATF_REQUIRE_MSG(fstatat(fd[0], "", &sb, AT_EMPTY_PATH) == 0, 777 FMT_ERR("fstatat pipe")); 778 ATF_REQUIRE_ERRNO(EFAULT, fstatat(fd[0], NULL, &sb, 779 AT_EMPTY_PATH) == -1); 780 CHECKED_CLOSE(fd[0]); 781 CHECKED_CLOSE(fd[1]); 782 } 783 784 /* Verify that we can send an O_PATH descriptor over a unix socket. */ 785 ATF_TC_WITHOUT_HEAD(path_rights); 786 ATF_TC_BODY(path_rights, tc) 787 { 788 char path[PATH_MAX]; 789 struct cmsghdr *cmsg; 790 struct msghdr msg; 791 struct iovec iov; 792 int flags, pathfd, pathfd_copy, sd[2]; 793 char c; 794 795 ATF_REQUIRE_MSG(socketpair(PF_LOCAL, SOCK_STREAM, 0, sd) == 0, 796 FMT_ERR("socketpair")); 797 798 mktfile(path, "path_rights.XXXXXX"); 799 800 pathfd = open(path, O_PATH); 801 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 802 803 /* Package up the O_PATH and send it over the socket pair. */ 804 cmsg = malloc(CMSG_SPACE(sizeof(pathfd))); 805 ATF_REQUIRE_MSG(cmsg != NULL, FMT_ERR("malloc")); 806 807 cmsg->cmsg_len = CMSG_LEN(sizeof(pathfd)); 808 cmsg->cmsg_level = SOL_SOCKET; 809 cmsg->cmsg_type = SCM_RIGHTS; 810 *(int *)(void *)CMSG_DATA(cmsg) = pathfd; 811 812 c = 0; 813 iov.iov_base = &c; 814 iov.iov_len = 1; 815 816 memset(&msg, 0, sizeof(msg)); 817 msg.msg_iov = &iov; 818 msg.msg_iovlen = 1; 819 msg.msg_control = cmsg; 820 msg.msg_controllen = CMSG_SPACE(sizeof(pathfd)); 821 822 ATF_REQUIRE_MSG(sendmsg(sd[0], &msg, 0) == sizeof(c), 823 FMT_ERR("sendmsg")); 824 825 /* Grab the pathfd copy from the other end of the pair. */ 826 memset(&msg, 0, sizeof(msg)); 827 msg.msg_iov = &iov; 828 msg.msg_iovlen = 1; 829 msg.msg_control = cmsg; 830 msg.msg_controllen = CMSG_SPACE(sizeof(pathfd)); 831 832 ATF_REQUIRE_MSG(recvmsg(sd[1], &msg, 0) == 1, 833 FMT_ERR("recvmsg")); 834 pathfd_copy = *(int *)(void *)CMSG_DATA(cmsg); 835 ATF_REQUIRE_MSG(pathfd_copy != pathfd, 836 "pathfd and pathfd_copy are equal"); 837 838 /* Verify that the copy has O_PATH properties. */ 839 flags = fcntl(pathfd_copy, F_GETFL); 840 ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl")); 841 ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH is not set"); 842 ATF_REQUIRE_ERRNO(EBADF, 843 read(pathfd_copy, &c, 1) == -1); 844 ATF_REQUIRE_ERRNO(EBADF, 845 write(pathfd_copy, &c, 1) == -1); 846 847 CHECKED_CLOSE(pathfd); 848 CHECKED_CLOSE(pathfd_copy); 849 CHECKED_CLOSE(sd[0]); 850 CHECKED_CLOSE(sd[1]); 851 } 852 853 /* Verify that a local socket can be opened with O_PATH. */ 854 ATF_TC_WITHOUT_HEAD(path_unix); 855 ATF_TC_BODY(path_unix, tc) 856 { 857 char buf[BUFSIZ], path[PATH_MAX]; 858 struct kevent ev; 859 struct sockaddr_un sun; 860 struct stat sb; 861 int kq, pathfd, sd; 862 863 snprintf(path, sizeof(path), "path_unix.XXXXXX"); 864 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp")); 865 866 sd = socket(PF_LOCAL, SOCK_STREAM, 0); 867 ATF_REQUIRE_MSG(sd >= 0, FMT_ERR("socket")); 868 869 memset(&sun, 0, sizeof(sun)); 870 sun.sun_family = PF_LOCAL; 871 (void)strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); 872 ATF_REQUIRE_MSG(bind(sd, (struct sockaddr *)&sun, SUN_LEN(&sun)) == 0, 873 FMT_ERR("bind")); 874 875 pathfd = open(path, O_PATH); 876 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 877 878 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 879 FMT_ERR("fstatat")); 880 ATF_REQUIRE_MSG(sb.st_mode & S_IFSOCK, "socket mode %#x", sb.st_mode); 881 ATF_REQUIRE_MSG(sb.st_ino != 0, "socket has inode number 0"); 882 883 memset(buf, 0, sizeof(buf)); 884 ATF_REQUIRE_ERRNO(EBADF, write(pathfd, buf, sizeof(buf))); 885 ATF_REQUIRE_ERRNO(EBADF, read(pathfd, buf, sizeof(buf))); 886 887 /* kevent() is disallowed with sockets. */ 888 kq = kqueue(); 889 ATF_REQUIRE_MSG(kq >= 0, FMT_ERR("kqueue")); 890 EV_SET(&ev, pathfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); 891 ATF_REQUIRE_ERRNO(EBADF, kevent(kq, &ev, 1, NULL, 0, NULL) == -1); 892 893 /* Should not be able to open a socket without O_PATH. */ 894 ATF_REQUIRE_ERRNO(EOPNOTSUPP, openat(pathfd, "", O_EMPTY_PATH) == -1); 895 896 ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0, 897 FMT_ERR("funlinkat")); 898 899 CHECKED_CLOSE(sd); 900 CHECKED_CLOSE(pathfd); 901 } 902 903 /* 904 * Check that we can perform operations using an O_PATH fd for an unlinked file. 905 */ 906 ATF_TC_WITHOUT_HEAD(path_unlinked); 907 ATF_TC_BODY(path_unlinked, tc) 908 { 909 char path[PATH_MAX]; 910 struct stat sb; 911 int pathfd; 912 913 mktfile(path, "path_rights.XXXXXX"); 914 915 pathfd = open(path, O_PATH); 916 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open")); 917 918 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 919 FMT_ERR("fstatat")); 920 ATF_REQUIRE(sb.st_nlink == 1); 921 ATF_REQUIRE_MSG(fstat(pathfd, &sb) == 0, FMT_ERR("fstat")); 922 ATF_REQUIRE(sb.st_nlink == 1); 923 924 ATF_REQUIRE_MSG(unlink(path) == 0, FMT_ERR("unlink")); 925 926 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0, 927 FMT_ERR("fstatat")); 928 ATF_REQUIRE(sb.st_nlink == 0); 929 ATF_REQUIRE_MSG(fstat(pathfd, &sb) == 0, FMT_ERR("fstat")); 930 ATF_REQUIRE(sb.st_nlink == 0); 931 932 CHECKED_CLOSE(pathfd); 933 } 934 935 ATF_TP_ADD_TCS(tp) 936 { 937 ATF_TP_ADD_TC(tp, path_access); 938 ATF_TP_ADD_TC(tp, path_aio); 939 ATF_TP_ADD_TC(tp, path_capsicum); 940 ATF_TP_ADD_TC(tp, path_coredump); 941 ATF_TP_ADD_TC(tp, path_directory); 942 ATF_TP_ADD_TC(tp, path_directory_not_root); 943 ATF_TP_ADD_TC(tp, path_empty); 944 ATF_TP_ADD_TC(tp, path_empty_not_root); 945 ATF_TP_ADD_TC(tp, path_empty_root); 946 ATF_TP_ADD_TC(tp, path_event); 947 ATF_TP_ADD_TC(tp, path_fcntl); 948 ATF_TP_ADD_TC(tp, path_fexecve); 949 ATF_TP_ADD_TC(tp, path_fifo); 950 ATF_TP_ADD_TC(tp, path_funlinkat); 951 ATF_TP_ADD_TC(tp, path_io); 952 ATF_TP_ADD_TC(tp, path_ioctl); 953 ATF_TP_ADD_TC(tp, path_lock); 954 ATF_TP_ADD_TC(tp, path_pipe_fstatat); 955 ATF_TP_ADD_TC(tp, path_rights); 956 ATF_TP_ADD_TC(tp, path_unix); 957 ATF_TP_ADD_TC(tp, path_unlinked); 958 959 return (atf_no_error()); 960 } 961