2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2021 The FreeBSD Foundation
6 * This software was developed by Mark Johnston under sponsorship from
7 * the FreeBSD Foundation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
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.
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
32 * Basic regression tests for handling of O_PATH descriptors.
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>
41 #include <sys/ptrace.h>
42 #include <sys/socket.h>
61 #define FMT_ERR(s) s ": %s", strerror(errno)
63 #define CHECKED_CLOSE(fd) \
64 ATF_REQUIRE_MSG(close(fd) == 0, FMT_ERR("close"))
66 /* Create a temporary regular file containing some data. */
68 mktfile(char path[PATH_MAX], const char *template)
73 snprintf(path, PATH_MAX, "%s", template);
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),
82 /* Make a temporary directory. */
84 mktdir(char path[PATH_MAX], const char *template)
86 snprintf(path, PATH_MAX, "%s", template);
87 ATF_REQUIRE_MSG(mkdtemp(path) == path, FMT_ERR("mkdtemp"));
90 /* Wait for a child process to exit with status 0. */
92 waitchild(pid_t child, int exstatus)
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",
100 ATF_REQUIRE_MSG(WEXITSTATUS(status) == exstatus,
101 "child exit status is %d, expected %d",
102 WEXITSTATUS(status), exstatus);
105 ATF_TC_WITHOUT_HEAD(path_access);
106 ATF_TC_BODY(path_access, tc)
110 struct timespec ts[2];
111 struct timeval tv[2];
114 mktfile(path, "path_access.XXXXXX");
116 pathfd = open(path, O_PATH);
117 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
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);
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"));
132 CHECKED_CLOSE(pathfd);
135 /* Basic tests to verify that AIO operations fail. */
136 ATF_TC_WITHOUT_HEAD(path_aio);
137 ATF_TC_BODY(path_aio, tc)
140 char buf[BUFSIZ], path[PATH_MAX];
143 mktfile(path, "path_aio.XXXXXX");
145 pathfd = open(path, O_PATH);
146 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
148 memset(&aio, 0, sizeof(aio));
150 aio.aio_nbytes = sizeof(buf);
151 aio.aio_fildes = pathfd;
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);
159 CHECKED_CLOSE(pathfd);
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)
171 mktfile(path, "path_capsicum.XXXXXX");
173 /* Make sure that filesystem namespace restrictions apply to O_PATH. */
175 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork"));
177 if (cap_enter() != 0)
179 if (open(path, O_PATH) >= 0)
181 if (errno != ECAPMODE)
183 if (open("/usr/bin/true", O_PATH | O_EXEC) >= 0)
185 if (errno != ECAPMODE)
191 /* Make sure that CAP_FEXECVE is required. */
193 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork"));
195 truefd = open("/usr/bin/true", O_PATH | O_EXEC);
198 cap_rights_init(&rights);
199 if (cap_rights_limit(truefd, &rights) != 0)
201 (void)fexecve(truefd,
202 (char * const[]){__DECONST(char *, "/usr/bin/true"), NULL},
204 if (errno != ENOTCAPABLE)
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)
216 struct ptrace_coredump pc;
217 int error, pathfd, status;
220 mktdir(path, "path_coredump.XXXXXX");
223 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork"));
229 pathfd = open(path, O_PATH);
230 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
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);
241 error = ptrace(PT_COREDUMP, child, (void *)&pc, sizeof(pc));
242 ATF_REQUIRE_ERRNO(EBADF, error == -1);
244 error = ptrace(PT_DETACH, child, 0, 0);
245 ATF_REQUIRE_MSG(error == 0, FMT_ERR("ptrace"));
247 ATF_REQUIRE_MSG(kill(child, SIGKILL) == 0, FMT_ERR("kill"));
249 CHECKED_CLOSE(pathfd);
252 /* Verify operations on directory path descriptors. */
253 ATF_TC_WITHOUT_HEAD(path_directory);
254 ATF_TC_BODY(path_directory, tc)
261 mktdir(path, "path_directory.XXXXXX");
263 pathfd = open(path, O_PATH | O_DIRECTORY);
264 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
266 /* Should not be possible to list directory entries. */
267 ATF_REQUIRE_ERRNO(EBADF,
268 getdirentries(pathfd, (char *)&de, sizeof(de), NULL) == -1);
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,
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);
285 /* fchdir(2) is permitted. */
286 ATF_REQUIRE_MSG(fchdir(pathfd) == 0, FMT_ERR("fchdir"));
288 CHECKED_CLOSE(pathfd);
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)
295 atf_tc_set_md_var(tc, "require.user", "unprivileged");
297 ATF_TC_BODY(path_directory_not_root, tc)
302 mktdir(path, "path_directory.XXXXXX");
304 pathfd = open(path, O_PATH | O_DIRECTORY);
305 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
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);
312 CHECKED_CLOSE(pathfd);
314 ATF_TC_CLEANUP(path_directory_not_root, tc)
318 /* Validate system calls that handle AT_EMPTY_PATH. */
319 ATF_TC_WITHOUT_HEAD(path_empty);
320 ATF_TC_BODY(path_empty, tc)
323 struct timespec ts[2];
327 mktfile(path, "path_empty.XXXXXX");
329 pathfd = open(path, O_PATH);
330 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
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,
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"));
349 CHECKED_CLOSE(pathfd);
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)
356 atf_tc_set_md_var(tc, "require.user", "unprivileged");
358 ATF_TC_BODY(path_empty_not_root, tc)
362 pathfd = open("/dev/null", O_PATH);
363 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
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);
374 CHECKED_CLOSE(pathfd);
376 ATF_TC_CLEANUP(path_empty_not_root, tc)
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)
384 atf_tc_set_md_var(tc, "require.user", "root");
386 ATF_TC_BODY(path_empty_root, tc)
392 mktfile(path, "path_empty_root.XXXXXX");
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,
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,
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");
406 CHECKED_CLOSE(pathfd);
409 ATF_TC_CLEANUP(path_empty_root, tc)
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)
417 char buf[BUFSIZ], path[PATH_MAX];
419 struct pollfd pollfd;
422 mktfile(path, "path_event.XXXXXX");
424 pathfd = open(path, O_PATH);
425 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
427 /* poll(2) should return POLLNVAL. */
429 pollfd.events = POLLIN;
431 ATF_REQUIRE_MSG(poll(&pollfd, 1, 0) == 1, FMT_ERR("poll"));
432 ATF_REQUIRE_MSG(pollfd.revents == POLLNVAL, "unexpected revents %x",
434 pollfd.events = POLLOUT;
436 ATF_REQUIRE_MSG(poll(&pollfd, 1, 0) == 1, FMT_ERR("poll"));
437 ATF_REQUIRE_MSG(pollfd.revents == POLLNVAL, "unexpected revents %x",
440 /* Try to get a EVFILT_READ event through a path fd. */
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,
446 ATF_REQUIRE_MSG(kevent(kq, NULL, 0, &ev, 1, NULL) == 1,
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,
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,
458 ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0,
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,
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,
471 CHECKED_CLOSE(pathfd);
474 /* Check various fcntl(2) operations on a path desriptor. */
475 ATF_TC_WITHOUT_HEAD(path_fcntl);
476 ATF_TC_BODY(path_fcntl, tc)
479 int flags, pathfd, pathfd2;
481 mktfile(path, "path_fcntl.XXXXXX");
483 pathfd = open(path, O_PATH);
484 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
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");
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));
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);
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);
512 /* It should be possible to set O_CLOEXEC. */
513 ATF_REQUIRE_MSG(fcntl(pathfd, F_SETFD, FD_CLOEXEC) == 0,
515 ATF_REQUIRE_MSG(fcntl(pathfd, F_GETFD) == FD_CLOEXEC,
518 CHECKED_CLOSE(pathfd);
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)
530 ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork"));
532 pathfd = open("/usr/bin/true", O_PATH | O_EXEC);
536 (char * const[]){__DECONST(char *, "/usr/bin/true"), NULL},
543 * Also verify that access permissions are checked when opening with
546 snprintf(path, sizeof(path), "path_fexecve.XXXXXX");
547 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp"));
549 fd = open(path, O_CREAT | O_RDONLY, 0600);
550 ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("open"));
552 pathfd = open(path, O_PATH | O_EXEC);
553 ATF_REQUIRE_ERRNO(EACCES, pathfd < 0);
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)
560 char path[PATH_MAX], buf[BUFSIZ];
564 snprintf(path, sizeof(path), "path_fifo.XXXXXX");
565 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp"));
567 ATF_REQUIRE_MSG(mkfifo(path, 0666) == 0, FMT_ERR("mkfifo"));
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)));
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);
580 CHECKED_CLOSE(pathfd);
583 /* Files may be unlinked using a path fd. */
584 ATF_TC_WITHOUT_HEAD(path_funlinkat);
585 ATF_TC_BODY(path_funlinkat, tc)
591 mktfile(path, "path_rights.XXXXXX");
593 pathfd = open(path, O_PATH);
594 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
596 ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0,
597 FMT_ERR("funlinkat"));
598 ATF_REQUIRE_ERRNO(ENOENT, stat(path, &sb) == -1);
600 CHECKED_CLOSE(pathfd);
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)
607 char path[PATH_MAX], path2[PATH_MAX];
611 int error, fd, pathfd, sd[2];
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);
618 /* Create a non-empty file for use in the rest of the tests. */
619 mktfile(path, "path_io.XXXXXX");
621 pathfd = open(path, O_PATH);
622 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
624 /* Make sure that basic I/O operations aren't possible. */
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);
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);
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]);
662 ATF_REQUIRE_ERRNO(ESPIPE,
663 lseek(pathfd, 0, SEEK_SET) == -1);
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);
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) ==
678 ATF_REQUIRE_ERRNO(ENODEV,
679 mmap(NULL, page_size, PROT_NONE, MAP_SHARED, pathfd, 0) ==
681 ATF_REQUIRE_ERRNO(ENODEV,
682 mmap(NULL, page_size, PROT_READ, MAP_PRIVATE, pathfd, 0) ==
685 /* No fsync() or fdatasync(). */
686 ATF_REQUIRE_ERRNO(EBADF, fsync(pathfd) == -1);
687 ATF_REQUIRE_ERRNO(EBADF, fdatasync(pathfd) == -1);
689 CHECKED_CLOSE(pathfd);
692 /* ioctl(2) is not permitted on path fds. */
693 ATF_TC_WITHOUT_HEAD(path_ioctl);
694 ATF_TC_BODY(path_ioctl, tc)
697 struct mem_extract me;
700 mktfile(path, "path_ioctl.XXXXXX");
702 /* Standard file descriptor ioctls should fail. */
703 pathfd = open(path, O_PATH);
704 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
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);
712 CHECKED_CLOSE(pathfd);
714 /* Device ioctls should fail. */
715 pathfd = open("/dev/mem", O_PATH);
716 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
718 me.me_vaddr = (uintptr_t)&me;
719 ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, MEM_EXTRACT_PADDR, &me) == -1);
721 CHECKED_CLOSE(pathfd);
724 ATF_TC_WITHOUT_HEAD(path_lock);
725 ATF_TC_BODY(path_lock, tc)
727 char buf[BUFSIZ], path[PATH_MAX];
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),
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"));
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);
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);
762 CHECKED_CLOSE(pathfd);
766 * Verify fstatat(AT_EMPTY_PATH) on non-regular dirfd.
767 * Verify that fstatat(AT_EMPTY_PATH) on NULL path returns EFAULT.
769 ATF_TC_WITHOUT_HEAD(path_pipe_fstatat);
770 ATF_TC_BODY(path_pipe_fstatat, tc)
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]);
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)
789 struct cmsghdr *cmsg;
792 int flags, pathfd, pathfd_copy, sd[2];
795 ATF_REQUIRE_MSG(socketpair(PF_LOCAL, SOCK_STREAM, 0, sd) == 0,
796 FMT_ERR("socketpair"));
798 mktfile(path, "path_rights.XXXXXX");
800 pathfd = open(path, O_PATH);
801 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
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"));
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;
816 memset(&msg, 0, sizeof(msg));
819 msg.msg_control = cmsg;
820 msg.msg_controllen = CMSG_SPACE(sizeof(pathfd));
822 ATF_REQUIRE_MSG(sendmsg(sd[0], &msg, 0) == sizeof(c),
825 /* Grab the pathfd copy from the other end of the pair. */
826 memset(&msg, 0, sizeof(msg));
829 msg.msg_control = cmsg;
830 msg.msg_controllen = CMSG_SPACE(sizeof(pathfd));
832 ATF_REQUIRE_MSG(recvmsg(sd[1], &msg, 0) == 1,
834 pathfd_copy = *(int *)(void *)CMSG_DATA(cmsg);
835 ATF_REQUIRE_MSG(pathfd_copy != pathfd,
836 "pathfd and pathfd_copy are equal");
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);
847 CHECKED_CLOSE(pathfd);
848 CHECKED_CLOSE(pathfd_copy);
849 CHECKED_CLOSE(sd[0]);
850 CHECKED_CLOSE(sd[1]);
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)
857 char buf[BUFSIZ], path[PATH_MAX];
859 struct sockaddr_un sun;
863 snprintf(path, sizeof(path), "path_unix.XXXXXX");
864 ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp"));
866 sd = socket(PF_LOCAL, SOCK_STREAM, 0);
867 ATF_REQUIRE_MSG(sd >= 0, FMT_ERR("socket"));
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,
875 pathfd = open(path, O_PATH);
876 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
878 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0,
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");
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)));
887 /* kevent() is disallowed with sockets. */
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);
893 /* Should not be able to open a socket without O_PATH. */
894 ATF_REQUIRE_ERRNO(EOPNOTSUPP, openat(pathfd, "", O_EMPTY_PATH) == -1);
896 ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0,
897 FMT_ERR("funlinkat"));
900 CHECKED_CLOSE(pathfd);
904 * Check that we can perform operations using an O_PATH fd for an unlinked file.
906 ATF_TC_WITHOUT_HEAD(path_unlinked);
907 ATF_TC_BODY(path_unlinked, tc)
913 mktfile(path, "path_rights.XXXXXX");
915 pathfd = open(path, O_PATH);
916 ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
918 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0,
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);
924 ATF_REQUIRE_MSG(unlink(path) == 0, FMT_ERR("unlink"));
926 ATF_REQUIRE_MSG(fstatat(pathfd, "", &sb, AT_EMPTY_PATH) == 0,
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);
932 CHECKED_CLOSE(pathfd);
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);
959 return (atf_no_error());