1 #include <sys/param.h>
2 #include <sys/stat.h>
3 #include <sys/resource.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <stdbool.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <assert.h>
13 #include <err.h>
14 #include <removefile.h>
15
16 #include <sys/xattr.h>
17 #include <sys/attr.h>
18 #include <sys/fsgetpath.h>
19 #include <sys/fsgetpath_private.h>
20
21 #include <darwintest.h>
22 #include <darwintest_utils.h>
23
24 #define MAXLONGPATHLEN 8192 /* From sys/syslimits.h */
25
26 #define nelem(x) (sizeof((x))/sizeof((x)[0]))
27
28 #define DEBUG 1
29 #define DPRINT(fmt, ...) do {\
30 if (DEBUG) fprintf(stderr, "%s | " fmt "\n", __func__, ## __VA_ARGS__);\
31 }while(0)
32
33 #define onoffstr(x) ((x) ? "on" : "off")
34
35 // helpers for printing test context on errors
36 #define CTXFMT "[len: %zd, pol: %s]"
37 #define CTXARGS pathlen, onoffstr(policy)
38 #define CTXSTR CTXFMT, CTXARGS
39
40 T_GLOBAL_META(
41 T_META_NAMESPACE("xnu.vfs"),
42 T_META_RADAR_COMPONENT_NAME("xnu"),
43 T_META_RADAR_COMPONENT_VERSION("vfs"));
44
45 static void *
emalloc(size_t n)46 emalloc(size_t n)
47 {
48 void *p = malloc(n);
49 T_QUIET; T_ASSERT_NE(p, NULL, "malloced %zd bytes", n);
50 return p;
51 }
52
53 static size_t
generatename(char * outstr,size_t maxlen,size_t depth)54 generatename(char *outstr, size_t maxlen, size_t depth)
55 {
56 static char letters[] = {
57 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
58 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
59 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
60 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
61 };
62
63 T_QUIET; T_ASSERT_TRUE(depth >= 0 && depth < sizeof(letters),
64 "0 <= %zd < %zd", depth, sizeof(letters));
65
66 size_t len = MIN(NAME_MAX, maxlen);
67 memset(outstr, letters[depth], len);
68 return len;
69 }
70
71 static char *
createpath(size_t pathlen,bool leafisdir,struct stat * st)72 createpath(size_t pathlen, bool leafisdir, struct stat *st)
73 {
74 // If we generate names exactly NAME_MAX long, the only difference between
75 // paths of e.g. length 1023 and 1024 are the trailing slash.
76 // NAME_MAX - 1 avoids that.
77 enum {
78 MAXINTERLEN = NAME_MAX - 1
79 };
80
81 char *path = emalloc(pathlen + 1);
82 char *p = path;
83 int dirfd = AT_FDCWD;
84 size_t depth = 0;
85
86 // Plus one below to account for the slash
87 size_t intermediaries = pathlen / (MAXINTERLEN + 1);
88 size_t leaflen = pathlen % (MAXINTERLEN + 1);
89 if (leaflen == 0) {
90 // Prevent trying to create an empty leaf when pathlen is an
91 // exact divisor of MAXINTERLEN + 1
92 leaflen = pathlen;
93 intermediaries--;
94 }
95
96 // leaflen > MAXINTERLEN when pathlen is an exact divisor MAXINTERLEN + 1
97 char name[MAX(MAXINTERLEN, leaflen) + 1];
98
99 while (intermediaries-- > 0) {
100 size_t n = generatename(name, MAXINTERLEN, depth);
101 name[n] = '\0';
102 memmove(p, name, n);
103 p += n;
104 *p++ = '/';
105 depth++;
106
107 T_QUIET; T_ASSERT_POSIX_SUCCESS(mkdirat(dirfd, name, 0700),
108 "[len: %zd] failed to create dir '%s' at %.*s",
109 pathlen, name, (int)MAXINTERLEN, path);
110
111 int fd = openat(dirfd, name, O_RDONLY | O_DIRECTORY);
112 T_QUIET; T_ASSERT_GE(fd, 0,
113 "[len: %zd] failed to open dir %s: %s", pathlen, name, strerror(errno));
114 if (dirfd != AT_FDCWD) {
115 close(dirfd);
116 }
117 dirfd = fd;
118 }
119
120 size_t n = generatename(name, leaflen, depth);
121 name[n] = '\0';
122 memmove(p, name, n);
123 p += n;
124 *p = '\0';
125
126 T_QUIET; T_ASSERT_TRUE(strlen(path) == pathlen, "%zd != %zd", strlen(path), pathlen);
127
128 if (leafisdir) {
129 T_QUIET; T_ASSERT_POSIX_SUCCESS(mkdirat(dirfd, name, 0700),
130 "[len: %zd] failed to create leaf dir '%s' at '%s'", pathlen, name, path);
131
132 if (st != NULL) {
133 T_QUIET; T_ASSERT_POSIX_SUCCESS(fstatat(dirfd, name, st, 0),
134 "[len: %zd] failed to stat leaf dir '%s' at '%s'", pathlen, name, path);
135 }
136 } else {
137 int fd = openat(dirfd, name, O_CREAT | O_TRUNC | O_WRONLY, 0600);
138 T_QUIET; T_ASSERT_GE(fd, 0,
139 "[len: %zd] failed to create file '%s' leaf at '%s'", pathlen, name, path);
140
141 if (st != NULL) {
142 T_QUIET; T_ASSERT_POSIX_SUCCESS(fstat(fd, st),
143 "[len: %zd] failed to stat leaf file '%s' at '%s'", pathlen, name, path);
144 }
145 close(fd);
146 }
147
148 if (dirfd != AT_FDCWD) {
149 close(dirfd);
150 }
151 return path;
152 }
153
154 static int
openlongpath(const char * path,int flag)155 openlongpath(const char *path, int flag)
156 {
157 const char *p = path;
158 int dirfd = AT_FDCWD;
159 int fd = -1;
160 char *sep;
161
162 while (p != NULL && *p != '\0' && (sep = strchr(p, '/')) != NULL) {
163 size_t namelen = (size_t)(sep - p);
164 T_QUIET; T_ASSERT_LT(namelen, (size_t)NAME_MAX, "%zd >= NAME_MAX", namelen);
165 char name[NAME_MAX];
166 strlcpy(name, p, namelen + 1);
167
168 fd = openat(dirfd, name, O_EVTONLY);
169 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, "failed to open intermediate %s", name);
170 close(dirfd);
171 dirfd = fd;
172 p = sep + 1;
173 }
174
175 fd = openat(dirfd, p, flag);
176 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, "failed to open final component %s", p);
177 close(dirfd);
178 return fd;
179 }
180
181 static char *
setup_test_dir(char * name)182 setup_test_dir(char *name)
183 {
184 char *dir = NULL;
185 asprintf(&dir, "%s/longpaths-%s-XXXXXX", dt_tmpdir(), name);
186 T_QUIET; T_ASSERT_NOTNULL(mkdtemp(dir), NULL);
187 T_LOG("test dir: %s", dir);
188 chdir(dir);
189 return dir;
190 }
191
192 static void
setup_case_dir(size_t pathlen,bool policy)193 setup_case_dir(size_t pathlen, bool policy)
194 {
195 char casedir[64];
196 snprintf(casedir, sizeof(casedir), "len-%zd-policy-%s",
197 pathlen, onoffstr(policy));
198
199 T_QUIET; T_ASSERT_POSIX_SUCCESS(mkdir(casedir, 0700),
200 "failed to create case dir %s", casedir);
201 chdir(casedir);
202 }
203
204 #ifndef IOPOL_TYPE_VFS_SUPPORT_LONG_PATHS
205 #define IOPOL_TYPE_VFS_SUPPORT_LONG_PATHS 13
206 #define IOPOL_VFS_SUPPORT_LONG_PATHS_DEFAULT 0
207 #define IOPOL_VFS_SUPPORT_LONG_PATHS_ON 1
208 #endif
209
210 T_DECL(longpaths_set_policy_test, "Test combinations of policy settings in process and thread")
211 {
212 char *testdir = setup_test_dir("set_policy_test");
213
214 char *path = createpath(MAXPATHLEN + 10, false, NULL);
215 int fd = -1;
216
217 // Enable policy for thread
218 T_ASSERT_POSIX_SUCCESS(setiopolicy_np(IOPOL_TYPE_VFS_SUPPORT_LONG_PATHS,
219 IOPOL_SCOPE_THREAD, IOPOL_VFS_SUPPORT_LONG_PATHS_ON),
220 "[thread: on, proc: off]");
221
222 T_ASSERT_POSIX_SUCCESS(fd = open(path, O_EVTONLY), "open long path");
223 close(fd);
224
225 // Enable policy for process
226 T_ASSERT_POSIX_SUCCESS(setiopolicy_np(IOPOL_TYPE_VFS_SUPPORT_LONG_PATHS,
227 IOPOL_SCOPE_PROCESS, IOPOL_VFS_SUPPORT_LONG_PATHS_ON),
228 "[thread: on, proc: on]");
229
230 T_ASSERT_POSIX_SUCCESS(fd = open(path, O_EVTONLY), "open long path");
231 close(fd);
232
233 // Disable policy for thread
234 T_ASSERT_POSIX_SUCCESS(setiopolicy_np(IOPOL_TYPE_VFS_SUPPORT_LONG_PATHS,
235 IOPOL_SCOPE_THREAD, IOPOL_VFS_SUPPORT_LONG_PATHS_DEFAULT),
236 "[thread: off, proc: on]");
237
238 T_ASSERT_POSIX_SUCCESS(fd = open(path, O_EVTONLY), "open long path");
239 close(fd);
240
241 // Disable policy for process
242 T_ASSERT_POSIX_SUCCESS(setiopolicy_np(IOPOL_TYPE_VFS_SUPPORT_LONG_PATHS,
243 IOPOL_SCOPE_PROCESS, IOPOL_VFS_SUPPORT_LONG_PATHS_DEFAULT),
244 "[thread: off, proc: off]");
245
246 T_ASSERT_POSIX_FAILURE(fd = open(path, O_EVTONLY), ENAMETOOLONG,
247 "ENAMETOOLONG when opening long path");
248
249 free(path);
250 removefile(testdir, NULL, REMOVEFILE_RECURSIVE | REMOVEFILE_ALLOW_LONG_PATHS);
251 free(testdir);
252 }
253
254 static void
enable_policy(void)255 enable_policy(void)
256 {
257 T_QUIET;
258 T_ASSERT_POSIX_SUCCESS(setiopolicy_np(IOPOL_TYPE_VFS_SUPPORT_LONG_PATHS,
259 IOPOL_SCOPE_PROCESS, IOPOL_VFS_SUPPORT_LONG_PATHS_ON),
260 "failed to enable i/o policy");
261 }
262
263 static void
disable_policy(void)264 disable_policy(void)
265 {
266 T_QUIET;
267 T_ASSERT_POSIX_SUCCESS(setiopolicy_np(IOPOL_TYPE_VFS_SUPPORT_LONG_PATHS,
268 IOPOL_SCOPE_PROCESS, IOPOL_VFS_SUPPORT_LONG_PATHS_DEFAULT),
269 "failed to disable i/o policy");
270 }
271
272 static size_t pathlengths[] = {
273 64,
274 NAME_MAX,
275 MAXPATHLEN - 1,
276 MAXPATHLEN,
277 MAXPATHLEN + 1,
278 2 * MAXPATHLEN,
279 2 * MAXPATHLEN + 64,
280 MAXLONGPATHLEN - 1,
281 MAXLONGPATHLEN,
282 MAXLONGPATHLEN + 1,
283 MAXLONGPATHLEN + MAXPATHLEN,
284 };
285
286 // Expected results for syscalls that return status code (0 or < 0)
287 static int common_errno_off[] = {
288 /* 64 */ 0,
289 /* NAME_MAX */ 0,
290 /* MAXPATHLEN - 1 */ 0,
291 /* MAXPATHLEN */ ENAMETOOLONG,
292 /* MAXPATHLEN + 1 */ ENAMETOOLONG,
293 /* 2 * MAXPATHLEN */ ENAMETOOLONG,
294 /* 2 * MAXPATHLEN + 64 */ ENAMETOOLONG,
295 /* MAXLONGPATHLEN - 1 */ ENAMETOOLONG,
296 /* MAXLONGPATHLEN */ ENAMETOOLONG,
297 /* MAXLONGPATHLEN + 1 */ ENAMETOOLONG,
298 /* MAXLONGPATHLEN + MAXPATHLEN */ ENAMETOOLONG,
299 };
300
301 static int common_errno_on[] = {
302 /* 64 */ 0,
303 /* NAME_MAX */ 0,
304 /* MAXPATHLEN - 1 */ 0,
305 /* MAXPATHLEN */ 0,
306 /* MAXPATHLEN + 1 */ 0,
307 /* 2 * MAXPATHLEN */ 0,
308 /* 2 * MAXPATHLEN + 64 */ 0,
309 /* MAXLONGPATHLEN - 1 */ 0,
310 /* MAXLONGPATHLEN */ ENAMETOOLONG,
311 /* MAXLONGPATHLEN + 1 */ ENAMETOOLONG,
312 /* MAXLONGPATHLEN + MAXPATHLEN */ ENAMETOOLONG,
313 };
314
315 static void
test_access(size_t pathlen,bool policy,int expected_errno)316 test_access(size_t pathlen, bool policy, int expected_errno)
317 {
318 char *path = createpath(pathlen, false, NULL);
319 int rc = access(path, F_OK);
320 free(path);
321
322 if (expected_errno == 0) {
323 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
324 } else {
325 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
326 }
327 }
328
329 static void
test_faccessat(size_t pathlen,bool policy,int expected_errno)330 test_faccessat(size_t pathlen, bool policy, int expected_errno)
331 {
332 char *path = createpath(pathlen, false, NULL);
333 int rc = faccessat(AT_FDCWD, path, F_OK, 0);
334 free(path);
335
336 if (expected_errno == 0) {
337 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
338 } else {
339 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
340 }
341 }
342
343 // F_GETPATH must *not* consider the i/o policy
344 static int F_GETPATH_errno[] = {
345 /* 64 */ 0,
346 /* NAME_MAX */ 0,
347 /* MAXPATHLEN - 1 */ ENOSPC,
348 /* MAXPATHLEN */ ENOSPC,
349 /* MAXPATHLEN + 1 */ ENOSPC,
350 /* 2 * MAXPATHLEN */ ENOSPC,
351 /* 2 * MAXPATHLEN + 64 */ ENOSPC,
352 /* MAXLONGPATHLEN - 1 */ ENOSPC,
353 /* MAXLONGPATHLEN */ ENOSPC,
354 /* MAXLONGPATHLEN + 1 */ ENOSPC,
355 /* MAXLONGPATHLEN + MAXPATHLEN */ ENOSPC,
356 };
357
358 static void
test_F_GETPATH(size_t pathlen,bool policy,int expected_errno)359 test_F_GETPATH(size_t pathlen, bool policy, int expected_errno)
360 {
361 struct stat st;
362 char *path = createpath(pathlen, false, &st);
363
364 int fd = openlongpath(path, O_EVTONLY);
365 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, "failed to open path %s", path);
366 free(path);
367
368 char buf[PATH_MAX];
369 int rc = fcntl(fd, F_GETPATH, buf);
370 close(fd);
371
372 if (expected_errno == 0) {
373 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
374 } else {
375 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
376 }
377 }
378
379 static void
test_fstatat(size_t pathlen,bool policy,int expected_errno)380 test_fstatat(size_t pathlen, bool policy, int expected_errno)
381 {
382 struct stat st;
383 char *path = createpath(pathlen, false, NULL);
384 int rc = fstatat(AT_FDCWD, path, &st, 0);
385 free(path);
386
387 if (expected_errno == 0) {
388 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
389 } else {
390 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
391 }
392 }
393
394 static void
test_getattrlist_fileID(size_t pathlen,bool policy,int expected_errno)395 test_getattrlist_fileID(size_t pathlen, bool policy, int expected_errno)
396 {
397 struct stat st;
398 char *path = createpath(pathlen, false, &st);
399
400 struct {
401 uint32_t size;
402 uint64_t fileID;
403 } __attribute__((aligned(4), packed)) buf;
404
405 struct attrlist al = {
406 .bitmapcount = ATTR_BIT_MAP_COUNT,
407 .commonattr = ATTR_CMN_FILEID,
408 };
409
410 int rc = getattrlist(path, &al, &buf, sizeof(buf), FSOPT_ATTR_CMN_EXTENDED);
411 free(path);
412
413 if (expected_errno == 0) {
414 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
415 } else {
416 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
417 }
418 }
419
420 static void
test_getattrlist_fullpath(size_t pathlen,bool policy,int expected_errno)421 test_getattrlist_fullpath(size_t pathlen, bool policy, int expected_errno)
422 {
423 char *cwd = getcwd(NULL, 0);
424 size_t cwdlen = strlen(cwd);
425
426 if (pathlen + 1 <= cwdlen) {
427 // Test dir is longer than pathlen + slash, no sense running the test
428 return;
429 }
430
431 char *testrelpath = createpath(pathlen - cwdlen - 1, false, NULL); // -1 for the slash
432 char *inpath = NULL;
433 asprintf(&inpath, "%s/%s", cwd, testrelpath);
434 free(cwd);
435 free(testrelpath);
436 T_QUIET; T_ASSERT_EQ(strlen(inpath), pathlen, CTXSTR);
437
438 struct {
439 uint32_t size;
440 attrreference_t attr;
441 char path[MAXLONGPATHLEN];
442 } __attribute__((aligned(4), packed)) buf;
443
444 struct attrlist al = {
445 .bitmapcount = ATTR_BIT_MAP_COUNT,
446 .commonattr = ATTR_CMN_FULLPATH,
447 };
448
449 int rc = getattrlist(inpath, &al, &buf, sizeof(buf), FSOPT_ATTR_CMN_EXTENDED);
450
451 if (expected_errno == 0) {
452 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
453
454 char *retpath = (char *)&buf.attr + buf.attr.attr_dataoffset;
455 T_QUIET; T_ASSERT_LT(retpath, (char *)&buf + buf.size, CTXSTR);
456 T_QUIET; T_ASSERT_LE(retpath + buf.attr.attr_length, (char *)&buf + buf.size, CTXSTR);
457 T_QUIET; T_ASSERT_EQ(strcmp(retpath, inpath), 0, CTXSTR);
458 } else {
459 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
460 }
461 free(inpath);
462 }
463
464 static void
test_getattrlist_relpath(size_t pathlen,bool policy,int expected_errno)465 test_getattrlist_relpath(size_t pathlen, bool policy, int expected_errno)
466 {
467 char *cwd = getcwd(NULL, 0);
468 size_t cwdlen = strlen(cwd);
469
470 if (pathlen + 1 <= cwdlen) {
471 // Test dir is longer than pathlen + slash, no sense running the test
472 return;
473 }
474
475 struct stat st;
476 char *testrelpath = createpath(pathlen - cwdlen - 1, false, &st); // -1 for the slash
477 char *inpath = NULL;
478 asprintf(&inpath, "%s/%s", cwd, testrelpath);
479 free(cwd);
480 free(testrelpath);
481 T_QUIET; T_ASSERT_EQ(strlen(inpath), pathlen, NULL);
482
483 struct {
484 uint32_t size;
485 dev_t dev;
486 uint64_t fileID;
487 attrreference_t attr;
488 char path[MAXLONGPATHLEN];
489 } __attribute__((aligned(4), packed)) buf;
490
491 struct attrlist al = {
492 .bitmapcount = ATTR_BIT_MAP_COUNT,
493 .commonattr = ATTR_CMN_DEVID | ATTR_CMN_FILEID,
494 .forkattr = ATTR_CMNEXT_RELPATH,
495 };
496
497 int rc = getattrlist(inpath, &al, &buf, sizeof(buf), FSOPT_ATTR_CMN_EXTENDED);
498
499 if (expected_errno == 0) {
500 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
501
502 char *retpath = (char *)&buf.attr + buf.attr.attr_dataoffset;
503 T_QUIET; T_ASSERT_LT(retpath, (char *)&buf + buf.size, CTXSTR);
504 T_QUIET; T_ASSERT_LE(retpath + buf.attr.attr_length, (char *)&buf + buf.size, CTXSTR);
505 T_QUIET; T_ASSERT_TRUE(buf.dev == st.st_dev && buf.fileID == st.st_ino, CTXSTR);
506 } else {
507 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
508 }
509 free(inpath);
510 }
511
512 static void
test_getattrlist_nofirmlinkpath(size_t pathlen,bool policy,int expected_errno)513 test_getattrlist_nofirmlinkpath(size_t pathlen, bool policy, int expected_errno)
514 {
515 #if !TARGET_OS_OSX
516 T_QUIET; T_PASS(NULL);
517 return;
518 #else
519 char *cwd = getcwd(NULL, 0);
520 size_t cwdlen = strlen(cwd);
521
522 struct {
523 uint32_t size;
524 attrreference_t attr;
525 char mtpt[MAXPATHLEN];
526 } __attribute__((aligned(4), packed)) mtptbuf;
527
528 struct attrlist mtptal = {
529 .bitmapcount = ATTR_BIT_MAP_COUNT,
530 .volattr = ATTR_VOL_MOUNTPOINT,
531 };
532 T_QUIET; T_ASSERT_POSIX_SUCCESS(getattrlist(cwd, &mtptal, &mtptbuf, sizeof(mtptbuf), 0), NULL);
533
534 char *mtpt = (char *)&mtptbuf.attr + mtptbuf.attr.attr_dataoffset;
535 size_t mtptlen = strlen(mtpt);
536
537 if (pathlen + 1 <= mtptlen + cwdlen) {
538 // Test dir + mount point is longer than pathlen + slash, no sense running the test
539 return;
540 }
541
542 /*
543 * cwd already has a leading slash, so the -1 below is for the slash that will be put
544 * after cwd when build inpath
545 */
546 char *testrelpath = createpath(pathlen - mtptlen - cwdlen - 1, false, NULL);
547 char *inpath = NULL;
548 asprintf(&inpath, "%s%s/%s", mtpt, cwd, testrelpath);
549 free(cwd);
550 free(testrelpath);
551 T_QUIET; T_ASSERT_EQ(strlen(inpath), pathlen, CTXSTR);
552
553 struct {
554 uint32_t size;
555 attrreference_t attr;
556 char path[MAXLONGPATHLEN];
557 } __attribute__((aligned(4), packed)) buf;
558
559 struct attrlist al = {
560 .bitmapcount = ATTR_BIT_MAP_COUNT,
561 .forkattr = ATTR_CMNEXT_NOFIRMLINKPATH,
562 };
563
564 int rc = getattrlist(inpath, &al, &buf, sizeof(buf), FSOPT_ATTR_CMN_EXTENDED);
565
566 if (expected_errno == 0) {
567 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
568
569 char *retpath = (char *)&buf.attr + buf.attr.attr_dataoffset;
570 T_QUIET; T_ASSERT_LT(retpath, (char *)&buf + buf.size, CTXSTR);
571 T_QUIET; T_ASSERT_LE(retpath + buf.attr.attr_length, (char *)&buf + buf.size, CTXSTR);
572 T_QUIET; T_ASSERT_EQ(strcmp(retpath, inpath), 0, CTXSTR);
573 } else {
574 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
575 }
576 free(inpath);
577 #endif /* !TARGET_OS_OSX */
578 }
579
580 static void
test_lstat(size_t pathlen,bool policy,int expected_errno)581 test_lstat(size_t pathlen, bool policy, int expected_errno)
582 {
583 struct stat st;
584 char *path = createpath(pathlen, false, NULL);
585 int rc = lstat(path, &st);
586 free(path);
587
588 if (expected_errno == 0) {
589 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
590 } else {
591 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
592 }
593 }
594
595 static void
test_mkdirat(size_t pathlen,bool policy,int expected_errno)596 test_mkdirat(size_t pathlen, bool policy, int expected_errno)
597 {
598 char *name = "newdir";
599 size_t parentlen = pathlen - strlen(name) - 1;
600 char *parent = createpath(parentlen, true, NULL);
601 char *path = NULL;
602 asprintf(&path, "%s/%s", parent, name);
603
604 int rc = mkdirat(AT_FDCWD, path, 0700);
605 free(parent);
606 free(path);
607
608 if (expected_errno == 0) {
609 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
610 } else {
611 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
612 }
613 }
614
615 static void
test_open(size_t pathlen,bool policy,int expected_errno)616 test_open(size_t pathlen, bool policy, int expected_errno)
617 {
618 char *path = createpath(pathlen, false, NULL);
619 int fd = open(path, O_EVTONLY);
620 free(path);
621
622 if (expected_errno == 0) {
623 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
624 } else {
625 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
626 }
627 if (fd >= 0) {
628 close(fd);
629 }
630 }
631
632 static void
test_open_create(size_t pathlen,bool policy,int expected_errno)633 test_open_create(size_t pathlen, bool policy, int expected_errno)
634 {
635 char *name = "newfile";
636 size_t parentlen = pathlen - strlen(name) - 1;
637 char *parent = createpath(parentlen, true, NULL);
638 char *path = NULL;
639 asprintf(&path, "%s/%s", parent, name);
640
641 int fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
642 free(parent);
643 free(path);
644
645 if (expected_errno == 0) {
646 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
647 } else {
648 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
649 }
650 if (fd >= 0) {
651 close(fd);
652 }
653 }
654
655 static void
test_open_volfs(size_t pathlen,bool policy,int expected_errno)656 test_open_volfs(size_t pathlen, bool policy, int expected_errno)
657 {
658 #if !TARGET_OS_OSX
659 T_QUIET; T_PASS(NULL);
660 return;
661 #else
662 char *cwd = getcwd(NULL, 0);
663 size_t cwdlen = strlen(cwd);
664 free(cwd);
665
666 if (pathlen + 1 <= cwdlen) {
667 // Test dir is longer than pathlen + slash, no sense running the test
668 return;
669 }
670 size_t relpathlen = pathlen - cwdlen - 1; // -1 for the slash
671
672 struct stat st, volst;
673 free(createpath(relpathlen, false, &st));
674
675 char *path = NULL;
676 asprintf(&path, "/.vol/%d/%llu", st.st_dev, st.st_ino);
677 int fd = open(path, O_EVTONLY);
678 free(path);
679
680 if (expected_errno == 0) {
681 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
682 T_QUIET; T_ASSERT_POSIX_SUCCESS(fstat(fd, &volst), CTXSTR);
683 T_QUIET; T_ASSERT_TRUE(volst.st_dev == st.st_dev && volst.st_ino == st.st_ino,
684 CTXFMT " dev %d != %d, ino %llu != %llu",
685 CTXARGS, volst.st_dev, st.st_dev, volst.st_ino, st.st_ino);
686 } else {
687 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
688 }
689 if (fd >= 0) {
690 close(fd);
691 }
692 #endif /* !TARGET_OS_OSX */
693 }
694
695 static void
test_openat(size_t pathlen,bool policy,int expected_errno)696 test_openat(size_t pathlen, bool policy, int expected_errno)
697 {
698 char *path = createpath(pathlen, false, NULL);
699 int fd = openat(AT_FDCWD, path, O_EVTONLY);
700 free(path);
701
702 if (expected_errno == 0) {
703 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
704 } else {
705 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
706 }
707 if (fd >= 0) {
708 close(fd);
709 }
710 }
711
712 static void
test_openat_create(size_t pathlen,bool policy,int expected_errno)713 test_openat_create(size_t pathlen, bool policy, int expected_errno)
714 {
715 char *name = "newfile";
716 size_t parentlen = pathlen - strlen(name) - 1;
717 char *parent = createpath(parentlen, true, NULL);
718 char *path = NULL;
719 asprintf(&path, "%s/%s", parent, name);
720
721 int fd = openat(AT_FDCWD, path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
722 free(parent);
723 free(path);
724
725 if (expected_errno == 0) {
726 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
727 } else {
728 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
729 }
730 if (fd >= 0) {
731 close(fd);
732 }
733 }
734
735 static int openbyid_errno_off[] = {
736 /* 64 */ 0,
737 /* NAME_MAX */ 0,
738 /* MAXPATHLEN - 1 */ ENAMETOOLONG,
739 /* MAXPATHLEN */ ENAMETOOLONG,
740 /* MAXPATHLEN + 1 */ ENAMETOOLONG,
741 /* 2 * MAXPATHLEN */ ENAMETOOLONG,
742 /* 2 * MAXPATHLEN + 64 */ ENAMETOOLONG,
743 /* MAXLONGPATHLEN - 1 */ EINVAL,
744 /* MAXLONGPATHLEN */ EINVAL,
745 /* MAXLONGPATHLEN + 1 */ EINVAL,
746 /* MAXLONGPATHLEN + MAXPATHLEN */ EINVAL,
747 };
748
749 static int openbyid_errno_on[] = {
750 /* 64 */ 0,
751 /* NAME_MAX */ 0,
752 /* MAXPATHLEN - 1 */ 0,
753 /* MAXPATHLEN */ 0,
754 /* MAXPATHLEN + 1 */ 0,
755 /* 2 * MAXPATHLEN */ 0,
756 /* 2 * MAXPATHLEN + 64 */ 0,
757 /* MAXLONGPATHLEN - 1 */ EINVAL,
758 /* MAXLONGPATHLEN */ EINVAL,
759 /* MAXLONGPATHLEN + 1 */ EINVAL,
760 /* MAXLONGPATHLEN + MAXPATHLEN */ EINVAL,
761 };
762
763 static void
test_openbyid_np(size_t pathlen,bool policy,int expected_errno)764 test_openbyid_np(size_t pathlen, bool policy, int expected_errno)
765 {
766 struct stat st;
767 char *path = createpath(pathlen, false, &st);
768 free(path);
769
770 fsid_t fsid = {st.st_dev, 0};
771 uint64_t fsobjid = st.st_ino;
772 int fd = openbyid_np(&fsid, (fsobj_id_t *)&fsobjid, O_EVTONLY);
773
774 if (expected_errno == 0) {
775 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
776 } else {
777 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
778 }
779 if (fd >= 0) {
780 close(fd);
781 }
782 }
783
784 /*
785 * The full paths here are length + strlen("link/") = length + 5
786 */
787 static int path_after_link_errno_off[] = {
788 /* 64 */ 0,
789 /* NAME_MAX */ 0,
790 /* MAXPATHLEN - 1 */ ENAMETOOLONG,
791 /* MAXPATHLEN */ ENAMETOOLONG,
792 /* MAXPATHLEN + 1 */ ENAMETOOLONG,
793 /* 2 * MAXPATHLEN */ ENAMETOOLONG,
794 /* 2 * MAXPATHLEN + 64 */ ENAMETOOLONG,
795 /* MAXLONGPATHLEN - 1 */ ENAMETOOLONG,
796 /* MAXLONGPATHLEN */ ENAMETOOLONG,
797 /* MAXLONGPATHLEN + 1 */ ENAMETOOLONG,
798 /* MAXLONGPATHLEN + MAXPATHLEN */ ENAMETOOLONG,
799 };
800
801 static int path_after_link_errno_on[] = {
802 /* 64 */ 0,
803 /* NAME_MAX */ 0,
804 /* MAXPATHLEN - 1 */ 0,
805 /* MAXPATHLEN */ 0,
806 /* MAXPATHLEN + 1 */ 0,
807 /* 2 * MAXPATHLEN */ 0,
808 /* 2 * MAXPATHLEN + 64 */ 0,
809 /* MAXLONGPATHLEN - 1 */ ENAMETOOLONG,
810 /* MAXLONGPATHLEN */ ENAMETOOLONG,
811 /* MAXLONGPATHLEN + 1 */ ENAMETOOLONG,
812 /* MAXLONGPATHLEN + MAXPATHLEN */ ENAMETOOLONG,
813 };
814
815 static void
test_path_after_link(size_t remaininglen,bool policy,int expected_errno)816 test_path_after_link(size_t remaininglen, bool policy, int expected_errno)
817 {
818 /*
819 * Create path of the form link/... where ... has remaininglen length.
820 */
821
822 T_QUIET; T_ASSERT_POSIX_SUCCESS(mkdir("base", 0700), CTXFMT, remaininglen, onoffstr(policy));
823 T_QUIET; T_ASSERT_POSIX_SUCCESS(symlink("base", "link"), CTXFMT, remaininglen, onoffstr(policy));
824
825 chdir("base");
826 struct stat origst;
827 char *remainingpath = createpath(remaininglen - 1, false, &origst); // -1 for the slash
828 chdir("..");
829
830 char *path = NULL;
831 asprintf(&path, "link/%s", remainingpath);
832 free(remainingpath);
833
834 struct stat st;
835 int rc = fstatat(AT_FDCWD, path, &st, 0);
836 free(path);
837
838 if (expected_errno == 0) {
839 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXFMT, remaininglen, onoffstr(policy));
840 T_QUIET; T_ASSERT_TRUE(st.st_dev == origst.st_dev && st.st_ino == origst.st_ino,
841 CTXFMT, remaininglen, onoffstr(policy));
842 } else {
843 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXFMT, remaininglen, onoffstr(policy));
844 }
845 }
846
847 static void
test_renameatx_np(size_t pathlen,bool policy,int expected_errno)848 test_renameatx_np(size_t pathlen, bool policy, int expected_errno)
849 {
850 char *src = createpath(pathlen, false, NULL);
851 char *dst = strdup(src);
852
853 // Change last character in name
854 dst[pathlen - 1] = '9';
855
856 int rc = renameatx_np(AT_FDCWD, src, AT_FDCWD, dst, 0);
857 free(src);
858 free(dst);
859
860 if (expected_errno == 0) {
861 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
862 } else {
863 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
864 }
865 }
866
867 static void
test_symlink_long2long(size_t pathlen,bool policy,int expected_errno)868 test_symlink_long2long(size_t pathlen, bool policy, int expected_errno)
869 {
870 char *linkname = "link";
871 size_t parentlen = pathlen - strlen(linkname) - 1;
872 char *parent = createpath(parentlen, true, NULL);
873 char *linkpath = NULL;
874 asprintf(&linkpath, "%s/%s", parent, linkname);
875 char *targetpath = NULL;
876 asprintf(&targetpath, "%s/xpto", parent);
877 size_t targetlen = strlen(targetpath);
878
879 int rc = symlink(targetpath, linkpath);
880 free(parent);
881
882 if (expected_errno == 0) {
883 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
884
885 char *buf = emalloc(targetlen + 1);
886 ssize_t linklen;
887
888 T_QUIET; T_ASSERT_POSIX_SUCCESS((linklen = readlink(linkpath, buf, targetlen)), CTXSTR);
889 T_QUIET; T_ASSERT_EQ((size_t)linklen, targetlen,
890 CTXFMT " linklen %zd", CTXARGS, (size_t)linklen);
891 buf[linklen] = '\0';
892
893 T_QUIET; T_ASSERT_EQ(strcmp(buf, targetpath), 0, CTXSTR);
894 free(targetpath);
895 free(linkpath);
896 free(buf);
897 } else {
898 free(targetpath);
899 free(linkpath);
900 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
901 }
902 }
903
904 static void
test_symlink_long2short(size_t pathlen,bool policy,int expected_errno)905 test_symlink_long2short(size_t pathlen, bool policy, int expected_errno)
906 {
907 char *name = "long-link";
908 size_t parentlen = pathlen - strlen(name) - 1;
909 char *parent = createpath(parentlen, true, NULL);
910 char *path = NULL;
911 asprintf(&path, "%s/%s", parent, name);
912
913 char *targetname = "destination.txt";
914 size_t targetlen = strlen(targetname);
915 int rc = symlink(targetname, path);
916 free(parent);
917
918 if (expected_errno == 0) {
919 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
920
921 char *buf = emalloc(targetlen + 1);
922 ssize_t linklen;
923
924 T_QUIET; T_ASSERT_POSIX_SUCCESS((linklen = readlink(path, buf, targetlen)), CTXSTR);
925 T_QUIET; T_ASSERT_EQ((size_t)linklen, targetlen,
926 CTXFMT " linklen %zd", CTXARGS, (size_t)linklen);
927 buf[linklen] = '\0';
928
929 T_QUIET; T_ASSERT_EQ(strcmp(buf, targetname), 0, CTXSTR);
930 free(path);
931 free(buf);
932 } else {
933 free(path);
934 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
935 }
936 }
937
938 static void
test_symlink_short2long(size_t pathlen,bool policy,int expected_errno)939 test_symlink_short2long(size_t pathlen, bool policy, int expected_errno)
940 {
941 char *path = createpath(pathlen, false, NULL);
942 int rc = symlink(path, "short-link");
943
944 if (expected_errno == 0) {
945 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
946
947 char *buf = emalloc(pathlen + 1);
948 ssize_t linklen;
949
950 T_QUIET; T_ASSERT_POSIX_SUCCESS((linklen = readlink("short-link", buf, pathlen)), CTXSTR);
951 T_QUIET; T_ASSERT_EQ((size_t)linklen, pathlen,
952 CTXFMT " linklen %zd", CTXARGS, (size_t)linklen);
953 buf[linklen] = '\0';
954
955 T_QUIET; T_ASSERT_EQ(strcmp(buf, path), 0, CTXSTR);
956 free(path);
957 free(buf);
958 } else {
959 free(path);
960 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
961 }
962 }
963
964 static void
test_symlink_intermediate(size_t pathlen,bool policy,int expected_errno)965 test_symlink_intermediate(size_t pathlen, bool policy, int expected_errno)
966 {
967 /*
968 * Create path with intermediate symlinks so that linked and original paths
969 * are of the same length.
970 */
971 char *path = createpath(pathlen, false, NULL);
972
973 // Find parent of path
974 char *lastslash = strrchr(path, '/');
975 if (lastslash == NULL || lastslash == path) {
976 return;
977 }
978
979 size_t leaflen = strlen(lastslash + 1);
980
981 char *p = lastslash - 1;
982 while (p - 1 != path && *(p - 1) != '/') {
983 p--;
984 }
985
986 size_t parentlen = (uintptr_t)(lastslash - p);
987 char *parentname = emalloc(parentlen + 1);
988 memmove(parentname, p, parentlen);
989 parentname[parentlen] = '\0';
990
991 // Find grandparent of path, which will be the base path where to create a symlink
992 size_t baselen = pathlen - parentlen - 1 - 1 - leaflen;
993 char *basepath = emalloc(baselen + 1);
994 memmove(basepath, path, baselen);
995 basepath[baselen] = '\0';
996
997 // Create symlink
998 char *linkname = emalloc(parentlen + 1);
999 size_t n = generatename(linkname, parentlen, 49); // repeating Xs
1000 linkname[n] = '\0';
1001
1002 char *linkpath = NULL;
1003 asprintf(&linkpath, "%s/%s", basepath, linkname);
1004 free(linkname);
1005
1006 T_QUIET; T_ASSERT_EQ(strlen(linkpath) + 1 + leaflen, pathlen, NULL);
1007
1008 int rc = symlink(parentname, linkpath);
1009 free(parentname);
1010
1011 if (!policy) {
1012 if (strlen(linkpath) < MAXPATHLEN) {
1013 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
1014 } else {
1015 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, ENAMETOOLONG, CTXSTR);
1016 }
1017 } else {
1018 if (strlen(linkpath) < MAXLONGPATHLEN) {
1019 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
1020 } else {
1021 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, ENAMETOOLONG, CTXSTR);
1022 }
1023 }
1024
1025 char *linkedpath = NULL;
1026 asprintf(&linkedpath, "%s/%s", linkpath, lastslash + 1);
1027 T_QUIET; T_ASSERT_EQ(strlen(linkedpath), pathlen, NULL);
1028 free(linkpath);
1029
1030 int fd = open(linkedpath, O_EVTONLY);
1031 free(linkedpath);
1032
1033 if (expected_errno == 0) {
1034 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
1035 } else {
1036 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
1037 }
1038 if (fd >= 0) {
1039 close(fd);
1040 }
1041 }
1042
1043 static void
test_unlinkat(size_t pathlen,bool policy,int expected_errno)1044 test_unlinkat(size_t pathlen, bool policy, int expected_errno)
1045 {
1046 char *path = createpath(pathlen, false, NULL);
1047 int rc = unlinkat(AT_FDCWD, path, 0);
1048 free(path);
1049
1050 if (expected_errno == 0) {
1051 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
1052 } else {
1053 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
1054 }
1055 }
1056
1057 static void
test_xattr(size_t pathlen,bool policy,int expected_errno)1058 test_xattr(size_t pathlen, bool policy, int expected_errno)
1059 {
1060 char *path = createpath(pathlen, false, NULL);
1061 char *name = "lpattr";
1062 char *value = "xpto";
1063 ssize_t valuelen = strlen(value);
1064
1065 int rc = setxattr(path, name, value, valuelen, 0, XATTR_CREATE);
1066 if (expected_errno == 0) {
1067 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
1068 } else {
1069 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
1070 }
1071
1072 char *buf = emalloc(valuelen);
1073 ssize_t attrlen = getxattr(path, name, buf, valuelen, 0, XATTR_CREATE);
1074 free(path);
1075 if (expected_errno == 0) {
1076 T_QUIET; T_ASSERT_POSIX_SUCCESS(attrlen, CTXSTR);
1077 T_QUIET; T_ASSERT_EQ(attrlen, valuelen, CTXSTR);
1078 T_QUIET; T_ASSERT_EQ(0, memcmp(buf, value, valuelen), CTXSTR);
1079 } else {
1080 T_QUIET; T_ASSERT_POSIX_FAILURE(attrlen, expected_errno, CTXSTR);
1081 }
1082 free(buf);
1083 }
1084
1085 #define SYSCALL_TEST(name, expected_errno_off, expected_errno_on) \
1086 T_DECL(longpaths_ ## name ## _test, "Test " #name " with long paths") \
1087 {\
1088 char *testdir = setup_test_dir(#name);\
1089 \
1090 disable_policy();\
1091 bool policy = false;\
1092 for (size_t i = 0; i < nelem(pathlengths); i++) {\
1093 size_t pathlen = pathlengths[i];\
1094 setup_case_dir(pathlen, policy);\
1095 test_ ## name (pathlen, policy, (expected_errno_off)[i]);\
1096 chdir("..");\
1097 }\
1098 \
1099 enable_policy();\
1100 policy = true;\
1101 for (size_t i = 0; i < nelem(pathlengths); i++) {\
1102 size_t pathlen = pathlengths[i];\
1103 setup_case_dir(pathlen, policy);\
1104 test_ ##name (pathlen, policy, (expected_errno_on)[i]);\
1105 chdir("..");\
1106 }\
1107 \
1108 removefile(testdir, NULL, REMOVEFILE_RECURSIVE | REMOVEFILE_ALLOW_LONG_PATHS);\
1109 free(testdir);\
1110 }
1111
1112 SYSCALL_TEST(access, common_errno_off, common_errno_on)
1113 SYSCALL_TEST(faccessat, common_errno_off, common_errno_on)
1114 SYSCALL_TEST(fstatat, common_errno_off, common_errno_on)
1115 SYSCALL_TEST(F_GETPATH, F_GETPATH_errno, F_GETPATH_errno)
1116
1117 SYSCALL_TEST(getattrlist_fileID, common_errno_off, common_errno_on)
1118 SYSCALL_TEST(getattrlist_nofirmlinkpath, common_errno_off, common_errno_on)
1119 SYSCALL_TEST(getattrlist_fullpath, common_errno_off, common_errno_on)
1120 SYSCALL_TEST(getattrlist_relpath, common_errno_off, common_errno_on)
1121
1122 SYSCALL_TEST(lstat, common_errno_off, common_errno_on)
1123 SYSCALL_TEST(mkdirat, common_errno_off, common_errno_on)
1124
1125 SYSCALL_TEST(open, common_errno_off, common_errno_on)
1126 SYSCALL_TEST(open_create, common_errno_off, common_errno_on)
1127 SYSCALL_TEST(open_volfs, common_errno_on, common_errno_on)
1128
1129 SYSCALL_TEST(openat, common_errno_off, common_errno_on)
1130 SYSCALL_TEST(openat_create, common_errno_off, common_errno_on)
1131
1132 SYSCALL_TEST(openbyid_np, openbyid_errno_off, openbyid_errno_on)
1133 SYSCALL_TEST(path_after_link, path_after_link_errno_off, path_after_link_errno_on)
1134 SYSCALL_TEST(renameatx_np, common_errno_off, common_errno_on)
1135
1136 SYSCALL_TEST(symlink_intermediate, common_errno_off, common_errno_on)
1137 // Even with the policy on, we should fail when symlinks target long paths
1138 SYSCALL_TEST(symlink_long2long, common_errno_off, common_errno_off)
1139 SYSCALL_TEST(symlink_long2short, common_errno_off, common_errno_on)
1140 SYSCALL_TEST(symlink_short2long, common_errno_off, common_errno_off)
1141
1142 SYSCALL_TEST(unlinkat, common_errno_off, common_errno_on)
1143 SYSCALL_TEST(xattr, common_errno_off, common_errno_on)
1144