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