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