]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/file/path_test.c
zfs: merge openzfs/zfs@3b89d9518 (master) into main
[FreeBSD/FreeBSD.git] / tests / sys / file / path_test.c
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 }