xref: /freebsd/tests/sys/file/path_test.c (revision 16038816)
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_LINK event through a path fd. */
456 	EV_SET(&ev, pathfd, EVFILT_VNODE, EV_ADD | EV_ENABLE, NOTE_LINK, 0, 0);
457 	ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0,
458 	    FMT_ERR("kevent"));
459 	ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0,
460 	    FMT_ERR("funlinkat"));
461 	ATF_REQUIRE_MSG(kevent(kq, NULL, 0, &ev, 1, NULL) == 1,
462 	    FMT_ERR("kevent"));
463 	EV_SET(&ev, pathfd, EVFILT_VNODE, EV_DELETE, 0, 0, 0);
464 	ATF_REQUIRE_MSG(kevent(kq, &ev, 1, NULL, 0, NULL) == 0,
465 	    FMT_ERR("kevent"));
466 
467 	CHECKED_CLOSE(kq);
468 	CHECKED_CLOSE(pathfd);
469 }
470 
471 /* Check various fcntl(2) operations on a path desriptor. */
472 ATF_TC_WITHOUT_HEAD(path_fcntl);
473 ATF_TC_BODY(path_fcntl, tc)
474 {
475 	char path[PATH_MAX];
476 	int flags, pathfd, pathfd2;
477 
478 	mktfile(path, "path_fcntl.XXXXXX");
479 
480 	pathfd = open(path, O_PATH);
481 	ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
482 
483 	/* O_PATH should appear in the fd flags. */
484 	flags = fcntl(pathfd, F_GETFL);
485 	ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl"));
486 	ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set");
487 
488 	ATF_REQUIRE_ERRNO(EBADF,
489 	    fcntl(pathfd, F_SETFL, flags & ~O_PATH));
490 	ATF_REQUIRE_ERRNO(EBADF,
491 	    fcntl(pathfd, F_SETFL, flags | O_APPEND));
492 
493 	/* A dup'ed O_PATH fd had better have O_PATH set too. */
494 	pathfd2 = fcntl(pathfd, F_DUPFD, 0);
495 	ATF_REQUIRE_MSG(pathfd2 >= 0, FMT_ERR("fcntl"));
496 	flags = fcntl(pathfd2, F_GETFL);
497 	ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl"));
498 	ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set");
499 	CHECKED_CLOSE(pathfd2);
500 
501 	/* Double check with dup(2). */
502 	pathfd2 = dup(pathfd);
503 	ATF_REQUIRE_MSG(pathfd2 >= 0, FMT_ERR("dup"));
504 	flags = fcntl(pathfd2, F_GETFL);
505 	ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl"));
506 	ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH not set");
507 	CHECKED_CLOSE(pathfd2);
508 
509 	/* It should be possible to set O_CLOEXEC. */
510 	ATF_REQUIRE_MSG(fcntl(pathfd, F_SETFD, FD_CLOEXEC) == 0,
511 	    FMT_ERR("fcntl"));
512 	ATF_REQUIRE_MSG(fcntl(pathfd, F_GETFD) == FD_CLOEXEC,
513 	    FMT_ERR("fcntl"));
514 
515 	CHECKED_CLOSE(pathfd);
516 }
517 
518 /* Verify that we can execute a file opened with O_PATH. */
519 ATF_TC_WITHOUT_HEAD(path_fexecve);
520 ATF_TC_BODY(path_fexecve, tc)
521 {
522 	char path[PATH_MAX];
523 	pid_t child;
524 	int fd, pathfd;
525 
526 	child = fork();
527 	ATF_REQUIRE_MSG(child != -1, FMT_ERR("fork"));
528 	if (child == 0) {
529 		pathfd = open("/usr/bin/true", O_PATH | O_EXEC);
530 		if (pathfd < 0)
531 			_exit(1);
532 		fexecve(pathfd,
533 		    (char * const[]){__DECONST(char *, "/usr/bin/true"), NULL},
534 		    NULL);
535 		_exit(2);
536 	}
537 	waitchild(child, 0);
538 
539 	/*
540 	 * Also verify that access permissions are checked when opening with
541 	 * O_PATH.
542 	 */
543 	snprintf(path, sizeof(path), "path_fexecve.XXXXXX");
544 	ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp"));
545 
546 	fd = open(path, O_CREAT | O_RDONLY, 0600);
547 	ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("open"));
548 
549 	pathfd = open(path, O_PATH | O_EXEC);
550 	ATF_REQUIRE_ERRNO(EACCES, pathfd < 0);
551 }
552 
553 /* Make sure that O_PATH restrictions apply to named pipes as well. */
554 ATF_TC_WITHOUT_HEAD(path_fifo);
555 ATF_TC_BODY(path_fifo, tc)
556 {
557 	char path[PATH_MAX], buf[BUFSIZ];
558 	struct kevent ev;
559 	int kq, pathfd;
560 
561 	snprintf(path, sizeof(path), "path_fifo.XXXXXX");
562 	ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp"));
563 
564 	ATF_REQUIRE_MSG(mkfifo(path, 0666) == 0, FMT_ERR("mkfifo"));
565 
566 	pathfd = open(path, O_PATH);
567 	ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
568 	memset(buf, 0, sizeof(buf));
569 	ATF_REQUIRE_ERRNO(EBADF, write(pathfd, buf, sizeof(buf)));
570 	ATF_REQUIRE_ERRNO(EBADF, read(pathfd, buf, sizeof(buf)));
571 
572 	kq = kqueue();
573 	ATF_REQUIRE_MSG(kq >= 0, FMT_ERR("kqueue"));
574 	EV_SET(&ev, pathfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
575 	ATF_REQUIRE_ERRNO(EBADF, kevent(kq, &ev, 1, NULL, 0, NULL) == -1);
576 
577 	CHECKED_CLOSE(pathfd);
578 }
579 
580 /* Files may be unlinked using a path fd. */
581 ATF_TC_WITHOUT_HEAD(path_funlinkat);
582 ATF_TC_BODY(path_funlinkat, tc)
583 {
584 	char path[PATH_MAX];
585 	struct stat sb;
586 	int pathfd;
587 
588 	mktfile(path, "path_rights.XXXXXX");
589 
590 	pathfd = open(path, O_PATH);
591 	ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
592 
593 	ATF_REQUIRE_MSG(funlinkat(AT_FDCWD, path, pathfd, 0) == 0,
594 	    FMT_ERR("funlinkat"));
595 	ATF_REQUIRE_ERRNO(ENOENT, stat(path, &sb) == -1);
596 
597 	CHECKED_CLOSE(pathfd);
598 }
599 
600 /* Verify that various I/O operations fail on an O_PATH descriptor. */
601 ATF_TC_WITHOUT_HEAD(path_io);
602 ATF_TC_BODY(path_io, tc)
603 {
604 	char path[PATH_MAX], path2[PATH_MAX];
605 	char buf[BUFSIZ];
606 	struct iovec iov;
607 	int error, fd, pathfd, sd[2];
608 
609 	/* It shouldn't be possible to create new files with O_PATH. */
610 	snprintf(path, sizeof(path), "path_io.XXXXXX");
611 	ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp"));
612 	ATF_REQUIRE_ERRNO(ENOENT, open(path, O_PATH | O_CREAT, 0600) < 0);
613 
614 	/* Create a non-empty file for use in the rest of the tests. */
615 	mktfile(path, "path_io.XXXXXX");
616 
617 	pathfd = open(path, O_PATH);
618 	ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
619 
620 	/* Make sure that basic I/O operations aren't possible. */
621 	iov.iov_base = path;
622 	iov.iov_len = strlen(path);
623 	ATF_REQUIRE_ERRNO(EBADF,
624 	    write(pathfd, iov.iov_base, iov.iov_len) == -1);
625 	ATF_REQUIRE_ERRNO(EBADF,
626 	    pwrite(pathfd, iov.iov_base, iov.iov_len, 0) == -1);
627 	ATF_REQUIRE_ERRNO(EBADF,
628 	    writev(pathfd, &iov, 1) == -1);
629 	ATF_REQUIRE_ERRNO(EBADF,
630 	    pwritev(pathfd, &iov, 1, 0) == -1);
631 	ATF_REQUIRE_ERRNO(EBADF,
632 	    read(pathfd, path, 1) == -1);
633 	ATF_REQUIRE_ERRNO(EBADF,
634 	    pread(pathfd, path, 1, 0) == -1);
635 	ATF_REQUIRE_ERRNO(EBADF,
636 	    readv(pathfd, &iov, 1) == -1);
637 	ATF_REQUIRE_ERRNO(EBADF,
638 	    preadv(pathfd, &iov, 1, 0) == -1);
639 
640 	/* copy_file_range() should not be permitted. */
641 	mktfile(path2, "path_io.XXXXXX");
642 	fd = open(path2, O_RDWR);
643 	ATF_REQUIRE_ERRNO(EBADF,
644 	    copy_file_range(fd, NULL, pathfd, NULL, sizeof(buf), 0) == -1);
645 	ATF_REQUIRE_ERRNO(EBADF,
646 	    copy_file_range(pathfd, NULL, fd, NULL, sizeof(buf), 0) == -1);
647 	CHECKED_CLOSE(fd);
648 
649 	/* sendfile() should not be permitted. */
650 	ATF_REQUIRE_MSG(socketpair(PF_LOCAL, SOCK_STREAM, 0, sd) == 0,
651 	    FMT_ERR("socketpair"));
652 	ATF_REQUIRE_ERRNO(EBADF,
653 	    sendfile(pathfd, sd[0], 0, 0, NULL, NULL, 0));
654 	CHECKED_CLOSE(sd[0]);
655 	CHECKED_CLOSE(sd[1]);
656 
657 	/* No seeking. */
658 	ATF_REQUIRE_ERRNO(ESPIPE,
659 	    lseek(pathfd, 0, SEEK_SET) == -1);
660 
661 	/* No operations on the file extent. */
662 	ATF_REQUIRE_ERRNO(EINVAL,
663 	    ftruncate(pathfd, 0) == -1);
664 	error = posix_fallocate(pathfd, 0, sizeof(buf) * 2);
665 	ATF_REQUIRE_MSG(error == ESPIPE, "posix_fallocate() returned %d", error);
666 	error = posix_fadvise(pathfd, 0, sizeof(buf), POSIX_FADV_NORMAL);
667 	ATF_REQUIRE_MSG(error == ESPIPE, "posix_fadvise() returned %d", error);
668 
669 	/* mmap() is not allowed. */
670 	ATF_REQUIRE_ERRNO(ENODEV,
671 	    mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, pathfd, 0) ==
672 	    MAP_FAILED);
673 	ATF_REQUIRE_ERRNO(ENODEV,
674 	    mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_SHARED, pathfd, 0) ==
675 	    MAP_FAILED);
676 	ATF_REQUIRE_ERRNO(ENODEV,
677 	    mmap(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, pathfd, 0) ==
678 	    MAP_FAILED);
679 
680 	/* No fsync() or fdatasync(). */
681 	ATF_REQUIRE_ERRNO(EBADF, fsync(pathfd) == -1);
682 	ATF_REQUIRE_ERRNO(EBADF, fdatasync(pathfd) == -1);
683 
684 	CHECKED_CLOSE(pathfd);
685 }
686 
687 /* ioctl(2) is not permitted on path fds. */
688 ATF_TC_WITHOUT_HEAD(path_ioctl);
689 ATF_TC_BODY(path_ioctl, tc)
690 {
691 	char path[PATH_MAX];
692 	struct mem_extract me;
693 	int pathfd, val;
694 
695 	mktfile(path, "path_ioctl.XXXXXX");
696 
697 	/* Standard file descriptor ioctls should fail. */
698 	pathfd = open(path, O_PATH);
699 	ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
700 
701 	val = 0;
702 	ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONBIO, &val) == -1);
703 	ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONREAD, &val) == -1);
704 	ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONWRITE, &val) == -1);
705 	ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, FIONSPACE, &val) == -1);
706 
707 	CHECKED_CLOSE(pathfd);
708 
709 	/* Device ioctls should fail. */
710 	pathfd = open("/dev/mem", O_PATH);
711 	ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
712 
713 	me.me_vaddr = (uintptr_t)&me;
714 	ATF_REQUIRE_ERRNO(EBADF, ioctl(pathfd, MEM_EXTRACT_PADDR, &me) == -1);
715 
716 	CHECKED_CLOSE(pathfd);
717 }
718 
719 ATF_TC_WITHOUT_HEAD(path_lock);
720 ATF_TC_BODY(path_lock, tc)
721 {
722 	char buf[BUFSIZ], path[PATH_MAX];
723 	struct flock flk;
724 	int fd, pathfd;
725 
726 	snprintf(path, sizeof(path), "path_rights.XXXXXX");
727 	fd = mkostemp(path, O_SHLOCK);
728 	ATF_REQUIRE_MSG(fd >= 0, FMT_ERR("mkostemp"));
729 	memset(buf, 0, sizeof(buf));
730 	ATF_REQUIRE_MSG(write(fd, buf, sizeof(buf)) == sizeof(buf),
731 	    FMT_ERR("write()"));
732 
733 	/* Verify that O_EXLOCK is ignored when combined with O_PATH. */
734 	pathfd = open(path, O_PATH | O_EXLOCK);
735 	ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
736 
737 	CHECKED_CLOSE(fd);
738 
739 	/* flock(2) is prohibited. */
740 	ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_SH) == -1);
741 	ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_EX) == -1);
742 	ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_SH | LOCK_NB) == -1);
743 	ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_EX | LOCK_NB) == -1);
744 	ATF_REQUIRE_ERRNO(EOPNOTSUPP, flock(pathfd, LOCK_UN) == -1);
745 
746 	/* fcntl(2) file locks are prohibited. */
747 	memset(&flk, 0, sizeof(flk));
748 	flk.l_whence = SEEK_CUR;
749 	ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_GETLK, &flk) == -1);
750 	flk.l_type = F_RDLCK;
751 	ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLK, &flk) == -1);
752 	ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLKW, &flk) == -1);
753 	flk.l_type = F_WRLCK;
754 	ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLK, &flk) == -1);
755 	ATF_REQUIRE_ERRNO(EBADF, fcntl(pathfd, F_SETLKW, &flk) == -1);
756 
757 	CHECKED_CLOSE(pathfd);
758 }
759 
760 /* Verify that we can send an O_PATH descriptor over a unix socket. */
761 ATF_TC_WITHOUT_HEAD(path_rights);
762 ATF_TC_BODY(path_rights, tc)
763 {
764 	char path[PATH_MAX];
765 	struct cmsghdr *cmsg;
766 	struct msghdr msg;
767 	struct iovec iov;
768 	int flags, pathfd, pathfd_copy, sd[2];
769 	char c;
770 
771 	ATF_REQUIRE_MSG(socketpair(PF_LOCAL, SOCK_STREAM, 0, sd) == 0,
772 	    FMT_ERR("socketpair"));
773 
774 	mktfile(path, "path_rights.XXXXXX");
775 
776 	pathfd = open(path, O_PATH);
777 	ATF_REQUIRE_MSG(pathfd >= 0, FMT_ERR("open"));
778 
779 	/* Package up the O_PATH and send it over the socket pair. */
780 	cmsg = malloc(CMSG_SPACE(sizeof(pathfd)));
781 	ATF_REQUIRE_MSG(cmsg != NULL, FMT_ERR("malloc"));
782 
783 	cmsg->cmsg_len = CMSG_LEN(sizeof(pathfd));
784 	cmsg->cmsg_level = SOL_SOCKET;
785 	cmsg->cmsg_type = SCM_RIGHTS;
786 	*(int *)(void *)CMSG_DATA(cmsg) = pathfd;
787 
788 	c = 0;
789 	iov.iov_base = &c;
790 	iov.iov_len = 1;
791 
792 	memset(&msg, 0, sizeof(msg));
793 	msg.msg_iov = &iov;
794 	msg.msg_iovlen = 1;
795 	msg.msg_control = cmsg;
796 	msg.msg_controllen = CMSG_SPACE(sizeof(pathfd));
797 
798 	ATF_REQUIRE_MSG(sendmsg(sd[0], &msg, 0) == sizeof(c),
799 	    FMT_ERR("sendmsg"));
800 
801 	/* Grab the pathfd copy from the other end of the pair. */
802 	memset(&msg, 0, sizeof(msg));
803 	msg.msg_iov = &iov;
804 	msg.msg_iovlen = 1;
805 	msg.msg_control = cmsg;
806 	msg.msg_controllen = CMSG_SPACE(sizeof(pathfd));
807 
808 	ATF_REQUIRE_MSG(recvmsg(sd[1], &msg, 0) == 1,
809 	    FMT_ERR("recvmsg"));
810 	pathfd_copy = *(int *)(void *)CMSG_DATA(cmsg);
811 	ATF_REQUIRE_MSG(pathfd_copy != pathfd,
812 	    "pathfd and pathfd_copy are equal");
813 
814 	/* Verify that the copy has O_PATH properties. */
815 	flags = fcntl(pathfd_copy, F_GETFL);
816 	ATF_REQUIRE_MSG(flags != -1, FMT_ERR("fcntl"));
817 	ATF_REQUIRE_MSG((flags & O_PATH) != 0, "O_PATH is not set");
818 	ATF_REQUIRE_ERRNO(EBADF,
819 	    read(pathfd_copy, &c, 1) == -1);
820 	ATF_REQUIRE_ERRNO(EBADF,
821 	    write(pathfd_copy, &c, 1) == -1);
822 
823 	CHECKED_CLOSE(pathfd);
824 	CHECKED_CLOSE(pathfd_copy);
825 	CHECKED_CLOSE(sd[0]);
826 	CHECKED_CLOSE(sd[1]);
827 }
828 
829 /* Verify that a local socket can't be opened with O_PATH. */
830 ATF_TC_WITHOUT_HEAD(path_unix);
831 ATF_TC_BODY(path_unix, tc)
832 {
833 	char path[PATH_MAX];
834 	struct sockaddr_un sun;
835 	int pathfd, sd;
836 
837 	snprintf(path, sizeof(path), "path_unix.XXXXXX");
838 	ATF_REQUIRE_MSG(mktemp(path) == path, FMT_ERR("mktemp"));
839 
840 	sd = socket(PF_LOCAL, SOCK_STREAM, 0);
841 	ATF_REQUIRE_MSG(sd >= 0, FMT_ERR("socket"));
842 
843 	memset(&sun, 0, sizeof(sun));
844 	sun.sun_family = PF_LOCAL;
845 	(void)strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
846 	ATF_REQUIRE_MSG(bind(sd, (struct sockaddr *)&sun, SUN_LEN(&sun)) == 0,
847 	    FMT_ERR("bind"));
848 
849 	pathfd = open(path, O_RDONLY);
850 	ATF_REQUIRE_ERRNO(EOPNOTSUPP, pathfd < 0);
851 
852 	CHECKED_CLOSE(sd);
853 }
854 
855 ATF_TP_ADD_TCS(tp)
856 {
857 	ATF_TP_ADD_TC(tp, path_access);
858 	ATF_TP_ADD_TC(tp, path_aio);
859 	ATF_TP_ADD_TC(tp, path_capsicum);
860 	ATF_TP_ADD_TC(tp, path_coredump);
861 	ATF_TP_ADD_TC(tp, path_directory);
862 	ATF_TP_ADD_TC(tp, path_directory_not_root);
863 	ATF_TP_ADD_TC(tp, path_empty);
864 	ATF_TP_ADD_TC(tp, path_empty_not_root);
865 	ATF_TP_ADD_TC(tp, path_empty_root);
866 	ATF_TP_ADD_TC(tp, path_event);
867 	ATF_TP_ADD_TC(tp, path_fcntl);
868 	ATF_TP_ADD_TC(tp, path_fexecve);
869 	ATF_TP_ADD_TC(tp, path_fifo);
870 	ATF_TP_ADD_TC(tp, path_funlinkat);
871 	ATF_TP_ADD_TC(tp, path_io);
872 	ATF_TP_ADD_TC(tp, path_ioctl);
873 	ATF_TP_ADD_TC(tp, path_lock);
874 	ATF_TP_ADD_TC(tp, path_rights);
875 	ATF_TP_ADD_TC(tp, path_unix);
876 
877 	return (atf_no_error());
878 }
879