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 free(cwd);
429 return;
430 }
431
432 char *testrelpath = createpath(pathlen - cwdlen - 1, false, NULL); // -1 for the slash
433 char *inpath = NULL;
434 asprintf(&inpath, "%s/%s", cwd, testrelpath);
435 free(cwd);
436 free(testrelpath);
437 T_QUIET; T_ASSERT_EQ(strlen(inpath), pathlen, CTXSTR);
438
439 struct {
440 uint32_t size;
441 attrreference_t attr;
442 char path[MAXLONGPATHLEN];
443 } __attribute__((aligned(4), packed)) buf;
444
445 struct attrlist al = {
446 .bitmapcount = ATTR_BIT_MAP_COUNT,
447 .commonattr = ATTR_CMN_FULLPATH,
448 };
449
450 int rc = getattrlist(inpath, &al, &buf, sizeof(buf), FSOPT_ATTR_CMN_EXTENDED);
451
452 if (expected_errno == 0) {
453 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
454
455 char *retpath = (char *)&buf.attr + buf.attr.attr_dataoffset;
456 T_QUIET; T_ASSERT_LT(retpath, (char *)&buf + buf.size, CTXSTR);
457 T_QUIET; T_ASSERT_LE(retpath + buf.attr.attr_length, (char *)&buf + buf.size, CTXSTR);
458 T_QUIET; T_ASSERT_EQ(strcmp(retpath, inpath), 0, CTXSTR);
459 } else {
460 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
461 }
462 free(inpath);
463 }
464
465 static void
test_getattrlist_relpath(size_t pathlen,bool policy,int expected_errno)466 test_getattrlist_relpath(size_t pathlen, bool policy, int expected_errno)
467 {
468 char *cwd = getcwd(NULL, 0);
469 size_t cwdlen = strlen(cwd);
470
471 if (pathlen + 1 <= cwdlen) {
472 // Test dir is longer than pathlen + slash, no sense running the test
473 free(cwd);
474 return;
475 }
476
477 struct stat st;
478 char *testrelpath = createpath(pathlen - cwdlen - 1, false, &st); // -1 for the slash
479 char *inpath = NULL;
480 asprintf(&inpath, "%s/%s", cwd, testrelpath);
481 free(cwd);
482 free(testrelpath);
483 T_QUIET; T_ASSERT_EQ(strlen(inpath), pathlen, NULL);
484
485 struct {
486 uint32_t size;
487 dev_t dev;
488 uint64_t fileID;
489 attrreference_t attr;
490 char path[MAXLONGPATHLEN];
491 } __attribute__((aligned(4), packed)) buf;
492
493 struct attrlist al = {
494 .bitmapcount = ATTR_BIT_MAP_COUNT,
495 .commonattr = ATTR_CMN_DEVID | ATTR_CMN_FILEID,
496 .forkattr = ATTR_CMNEXT_RELPATH,
497 };
498
499 int rc = getattrlist(inpath, &al, &buf, sizeof(buf), FSOPT_ATTR_CMN_EXTENDED);
500
501 if (expected_errno == 0) {
502 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
503
504 char *retpath = (char *)&buf.attr + buf.attr.attr_dataoffset;
505 T_QUIET; T_ASSERT_LT(retpath, (char *)&buf + buf.size, CTXSTR);
506 T_QUIET; T_ASSERT_LE(retpath + buf.attr.attr_length, (char *)&buf + buf.size, CTXSTR);
507 T_QUIET; T_ASSERT_TRUE(buf.dev == st.st_dev && buf.fileID == st.st_ino, CTXSTR);
508 } else {
509 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
510 }
511 free(inpath);
512 }
513
514 static void
test_getattrlist_nofirmlinkpath(size_t pathlen,bool policy,int expected_errno)515 test_getattrlist_nofirmlinkpath(size_t pathlen, bool policy, int expected_errno)
516 {
517 #if !TARGET_OS_OSX
518 T_QUIET; T_PASS(NULL);
519 return;
520 #else
521 char *cwd = getcwd(NULL, 0);
522 size_t cwdlen = strlen(cwd);
523
524 struct {
525 uint32_t size;
526 attrreference_t attr;
527 char mtpt[MAXPATHLEN];
528 } __attribute__((aligned(4), packed)) mtptbuf;
529
530 struct attrlist mtptal = {
531 .bitmapcount = ATTR_BIT_MAP_COUNT,
532 .volattr = ATTR_VOL_MOUNTPOINT,
533 };
534 T_QUIET; T_ASSERT_POSIX_SUCCESS(getattrlist(cwd, &mtptal, &mtptbuf, sizeof(mtptbuf), 0), NULL);
535
536 char *mtpt = (char *)&mtptbuf.attr + mtptbuf.attr.attr_dataoffset;
537 size_t mtptlen = strlen(mtpt);
538
539 if (pathlen + 1 <= mtptlen + cwdlen) {
540 // Test dir + mount point is longer than pathlen + slash, no sense running the test
541 free(cwd);
542 return;
543 }
544
545 /*
546 * cwd already has a leading slash, so the -1 below is for the slash that will be put
547 * after cwd when build inpath
548 */
549 char *testrelpath = createpath(pathlen - mtptlen - cwdlen - 1, false, NULL);
550 char *inpath = NULL;
551 asprintf(&inpath, "%s%s/%s", mtpt, cwd, testrelpath);
552 free(cwd);
553 free(testrelpath);
554 T_QUIET; T_ASSERT_EQ(strlen(inpath), pathlen, CTXSTR);
555
556 struct {
557 uint32_t size;
558 attrreference_t attr;
559 char path[MAXLONGPATHLEN];
560 } __attribute__((aligned(4), packed)) buf;
561
562 struct attrlist al = {
563 .bitmapcount = ATTR_BIT_MAP_COUNT,
564 .forkattr = ATTR_CMNEXT_NOFIRMLINKPATH,
565 };
566
567 int rc = getattrlist(inpath, &al, &buf, sizeof(buf), FSOPT_ATTR_CMN_EXTENDED);
568
569 if (expected_errno == 0) {
570 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
571
572 char *retpath = (char *)&buf.attr + buf.attr.attr_dataoffset;
573 T_QUIET; T_ASSERT_LT(retpath, (char *)&buf + buf.size, CTXSTR);
574 T_QUIET; T_ASSERT_LE(retpath + buf.attr.attr_length, (char *)&buf + buf.size, CTXSTR);
575 T_QUIET; T_ASSERT_EQ(strcmp(retpath, inpath), 0, CTXSTR);
576 } else {
577 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
578 }
579 free(inpath);
580 #endif /* !TARGET_OS_OSX */
581 }
582
583 static void
test_lstat(size_t pathlen,bool policy,int expected_errno)584 test_lstat(size_t pathlen, bool policy, int expected_errno)
585 {
586 struct stat st;
587 char *path = createpath(pathlen, false, NULL);
588 int rc = lstat(path, &st);
589 free(path);
590
591 if (expected_errno == 0) {
592 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
593 } else {
594 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
595 }
596 }
597
598 static void
test_mkdirat(size_t pathlen,bool policy,int expected_errno)599 test_mkdirat(size_t pathlen, bool policy, int expected_errno)
600 {
601 char *name = "newdir";
602 size_t parentlen = pathlen - strlen(name) - 1;
603 char *parent = createpath(parentlen, true, NULL);
604 char *path = NULL;
605 asprintf(&path, "%s/%s", parent, name);
606
607 int rc = mkdirat(AT_FDCWD, path, 0700);
608 free(parent);
609 free(path);
610
611 if (expected_errno == 0) {
612 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
613 } else {
614 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
615 }
616 }
617
618 static void
test_open(size_t pathlen,bool policy,int expected_errno)619 test_open(size_t pathlen, bool policy, int expected_errno)
620 {
621 char *path = createpath(pathlen, false, NULL);
622 int fd = open(path, O_EVTONLY);
623 free(path);
624
625 if (expected_errno == 0) {
626 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
627 } else {
628 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
629 }
630 if (fd >= 0) {
631 close(fd);
632 }
633 }
634
635 static void
test_open_create(size_t pathlen,bool policy,int expected_errno)636 test_open_create(size_t pathlen, bool policy, int expected_errno)
637 {
638 char *name = "newfile";
639 size_t parentlen = pathlen - strlen(name) - 1;
640 char *parent = createpath(parentlen, true, NULL);
641 char *path = NULL;
642 asprintf(&path, "%s/%s", parent, name);
643
644 int fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
645 free(parent);
646 free(path);
647
648 if (expected_errno == 0) {
649 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
650 } else {
651 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
652 }
653 if (fd >= 0) {
654 close(fd);
655 }
656 }
657
658 static void
test_open_volfs(size_t pathlen,bool policy,int expected_errno)659 test_open_volfs(size_t pathlen, bool policy, int expected_errno)
660 {
661 #if !TARGET_OS_OSX
662 T_QUIET; T_PASS(NULL);
663 return;
664 #else
665 char *cwd = getcwd(NULL, 0);
666 size_t cwdlen = strlen(cwd);
667 free(cwd);
668
669 if (pathlen + 1 <= cwdlen) {
670 // Test dir is longer than pathlen + slash, no sense running the test
671 return;
672 }
673 size_t relpathlen = pathlen - cwdlen - 1; // -1 for the slash
674
675 struct stat st, volst;
676 free(createpath(relpathlen, false, &st));
677
678 char *path = NULL;
679 asprintf(&path, "/.vol/%d/%llu", st.st_dev, st.st_ino);
680 int fd = open(path, O_EVTONLY);
681 free(path);
682
683 if (expected_errno == 0) {
684 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
685 T_QUIET; T_ASSERT_POSIX_SUCCESS(fstat(fd, &volst), CTXSTR);
686 T_QUIET; T_ASSERT_TRUE(volst.st_dev == st.st_dev && volst.st_ino == st.st_ino,
687 CTXFMT " dev %d != %d, ino %llu != %llu",
688 CTXARGS, volst.st_dev, st.st_dev, volst.st_ino, st.st_ino);
689 } else {
690 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
691 }
692 if (fd >= 0) {
693 close(fd);
694 }
695 #endif /* !TARGET_OS_OSX */
696 }
697
698 static void
test_openat(size_t pathlen,bool policy,int expected_errno)699 test_openat(size_t pathlen, bool policy, int expected_errno)
700 {
701 char *path = createpath(pathlen, false, NULL);
702 int fd = openat(AT_FDCWD, path, O_EVTONLY);
703 free(path);
704
705 if (expected_errno == 0) {
706 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
707 } else {
708 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
709 }
710 if (fd >= 0) {
711 close(fd);
712 }
713 }
714
715 static void
test_openat_create(size_t pathlen,bool policy,int expected_errno)716 test_openat_create(size_t pathlen, bool policy, int expected_errno)
717 {
718 char *name = "newfile";
719 size_t parentlen = pathlen - strlen(name) - 1;
720 char *parent = createpath(parentlen, true, NULL);
721 char *path = NULL;
722 asprintf(&path, "%s/%s", parent, name);
723
724 int fd = openat(AT_FDCWD, path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
725 free(parent);
726 free(path);
727
728 if (expected_errno == 0) {
729 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
730 } else {
731 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
732 }
733 if (fd >= 0) {
734 close(fd);
735 }
736 }
737
738 static int openbyid_errno_off[] = {
739 /* 64 */ 0,
740 /* NAME_MAX */ 0,
741 /* MAXPATHLEN - 1 */ ENAMETOOLONG,
742 /* MAXPATHLEN */ ENAMETOOLONG,
743 /* MAXPATHLEN + 1 */ ENAMETOOLONG,
744 /* 2 * MAXPATHLEN */ ENAMETOOLONG,
745 /* 2 * MAXPATHLEN + 64 */ ENAMETOOLONG,
746 /* MAXLONGPATHLEN - 1 */ EINVAL,
747 /* MAXLONGPATHLEN */ EINVAL,
748 /* MAXLONGPATHLEN + 1 */ EINVAL,
749 /* MAXLONGPATHLEN + MAXPATHLEN */ EINVAL,
750 };
751
752 static int openbyid_errno_on[] = {
753 /* 64 */ 0,
754 /* NAME_MAX */ 0,
755 /* MAXPATHLEN - 1 */ 0,
756 /* MAXPATHLEN */ 0,
757 /* MAXPATHLEN + 1 */ 0,
758 /* 2 * MAXPATHLEN */ 0,
759 /* 2 * MAXPATHLEN + 64 */ 0,
760 /* MAXLONGPATHLEN - 1 */ EINVAL,
761 /* MAXLONGPATHLEN */ EINVAL,
762 /* MAXLONGPATHLEN + 1 */ EINVAL,
763 /* MAXLONGPATHLEN + MAXPATHLEN */ EINVAL,
764 };
765
766 static void
test_openbyid_np(size_t pathlen,bool policy,int expected_errno)767 test_openbyid_np(size_t pathlen, bool policy, int expected_errno)
768 {
769 struct stat st;
770 char *path = createpath(pathlen, false, &st);
771 free(path);
772
773 fsid_t fsid = {st.st_dev, 0};
774 uint64_t fsobjid = st.st_ino;
775 int fd = openbyid_np(&fsid, (fsobj_id_t *)&fsobjid, O_EVTONLY);
776
777 if (expected_errno == 0) {
778 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
779 } else {
780 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
781 }
782 if (fd >= 0) {
783 close(fd);
784 }
785 }
786
787 /*
788 * The full paths here are length + strlen("link/") = length + 5
789 */
790 static int path_after_link_errno_off[] = {
791 /* 64 */ 0,
792 /* NAME_MAX */ 0,
793 /* MAXPATHLEN - 1 */ ENAMETOOLONG,
794 /* MAXPATHLEN */ ENAMETOOLONG,
795 /* MAXPATHLEN + 1 */ ENAMETOOLONG,
796 /* 2 * MAXPATHLEN */ ENAMETOOLONG,
797 /* 2 * MAXPATHLEN + 64 */ ENAMETOOLONG,
798 /* MAXLONGPATHLEN - 1 */ ENAMETOOLONG,
799 /* MAXLONGPATHLEN */ ENAMETOOLONG,
800 /* MAXLONGPATHLEN + 1 */ ENAMETOOLONG,
801 /* MAXLONGPATHLEN + MAXPATHLEN */ ENAMETOOLONG,
802 };
803
804 static int path_after_link_errno_on[] = {
805 /* 64 */ 0,
806 /* NAME_MAX */ 0,
807 /* MAXPATHLEN - 1 */ 0,
808 /* MAXPATHLEN */ 0,
809 /* MAXPATHLEN + 1 */ 0,
810 /* 2 * MAXPATHLEN */ 0,
811 /* 2 * MAXPATHLEN + 64 */ 0,
812 /* MAXLONGPATHLEN - 1 */ ENAMETOOLONG,
813 /* MAXLONGPATHLEN */ ENAMETOOLONG,
814 /* MAXLONGPATHLEN + 1 */ ENAMETOOLONG,
815 /* MAXLONGPATHLEN + MAXPATHLEN */ ENAMETOOLONG,
816 };
817
818 static void
test_path_after_link(size_t remaininglen,bool policy,int expected_errno)819 test_path_after_link(size_t remaininglen, bool policy, int expected_errno)
820 {
821 /*
822 * Create path of the form link/... where ... has remaininglen length.
823 */
824
825 T_QUIET; T_ASSERT_POSIX_SUCCESS(mkdir("base", 0700), CTXFMT, remaininglen, onoffstr(policy));
826 T_QUIET; T_ASSERT_POSIX_SUCCESS(symlink("base", "link"), CTXFMT, remaininglen, onoffstr(policy));
827
828 chdir("base");
829 struct stat origst;
830 char *remainingpath = createpath(remaininglen - 1, false, &origst); // -1 for the slash
831 chdir("..");
832
833 char *path = NULL;
834 asprintf(&path, "link/%s", remainingpath);
835 free(remainingpath);
836
837 struct stat st;
838 int rc = fstatat(AT_FDCWD, path, &st, 0);
839 free(path);
840
841 if (expected_errno == 0) {
842 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXFMT, remaininglen, onoffstr(policy));
843 T_QUIET; T_ASSERT_TRUE(st.st_dev == origst.st_dev && st.st_ino == origst.st_ino,
844 CTXFMT, remaininglen, onoffstr(policy));
845 } else {
846 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXFMT, remaininglen, onoffstr(policy));
847 }
848 }
849
850 static void
test_renameatx_np(size_t pathlen,bool policy,int expected_errno)851 test_renameatx_np(size_t pathlen, bool policy, int expected_errno)
852 {
853 char *src = createpath(pathlen, false, NULL);
854 char *dst = strdup(src);
855
856 // Change last character in name
857 dst[pathlen - 1] = '9';
858
859 int rc = renameatx_np(AT_FDCWD, src, AT_FDCWD, dst, 0);
860 free(src);
861 free(dst);
862
863 if (expected_errno == 0) {
864 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
865 } else {
866 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
867 }
868 }
869
870 static void
test_symlink_long2long(size_t pathlen,bool policy,int expected_errno)871 test_symlink_long2long(size_t pathlen, bool policy, int expected_errno)
872 {
873 char *linkname = "link";
874 size_t parentlen = pathlen - strlen(linkname) - 1;
875 char *parent = createpath(parentlen, true, NULL);
876 char *linkpath = NULL;
877 asprintf(&linkpath, "%s/%s", parent, linkname);
878 char *targetpath = NULL;
879 asprintf(&targetpath, "%s/xpto", parent);
880 size_t targetlen = strlen(targetpath);
881
882 int rc = symlink(targetpath, linkpath);
883 free(parent);
884
885 if (expected_errno == 0) {
886 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
887
888 char *buf = emalloc(targetlen + 1);
889 ssize_t linklen;
890
891 T_QUIET; T_ASSERT_POSIX_SUCCESS((linklen = readlink(linkpath, buf, targetlen)), CTXSTR);
892 T_QUIET; T_ASSERT_EQ((size_t)linklen, targetlen,
893 CTXFMT " linklen %zd", CTXARGS, (size_t)linklen);
894 buf[linklen] = '\0';
895
896 T_QUIET; T_ASSERT_EQ(strcmp(buf, targetpath), 0, CTXSTR);
897 free(targetpath);
898 free(linkpath);
899 free(buf);
900 } else {
901 free(targetpath);
902 free(linkpath);
903 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
904 }
905 }
906
907 static void
test_symlink_long2short(size_t pathlen,bool policy,int expected_errno)908 test_symlink_long2short(size_t pathlen, bool policy, int expected_errno)
909 {
910 char *name = "long-link";
911 size_t parentlen = pathlen - strlen(name) - 1;
912 char *parent = createpath(parentlen, true, NULL);
913 char *path = NULL;
914 asprintf(&path, "%s/%s", parent, name);
915
916 char *targetname = "destination.txt";
917 size_t targetlen = strlen(targetname);
918 int rc = symlink(targetname, path);
919 free(parent);
920
921 if (expected_errno == 0) {
922 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
923
924 char *buf = emalloc(targetlen + 1);
925 ssize_t linklen;
926
927 T_QUIET; T_ASSERT_POSIX_SUCCESS((linklen = readlink(path, buf, targetlen)), CTXSTR);
928 T_QUIET; T_ASSERT_EQ((size_t)linklen, targetlen,
929 CTXFMT " linklen %zd", CTXARGS, (size_t)linklen);
930 buf[linklen] = '\0';
931
932 T_QUIET; T_ASSERT_EQ(strcmp(buf, targetname), 0, CTXSTR);
933 free(path);
934 free(buf);
935 } else {
936 free(path);
937 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
938 }
939 }
940
941 static void
test_symlink_short2long(size_t pathlen,bool policy,int expected_errno)942 test_symlink_short2long(size_t pathlen, bool policy, int expected_errno)
943 {
944 char *path = createpath(pathlen, false, NULL);
945 int rc = symlink(path, "short-link");
946
947 if (expected_errno == 0) {
948 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
949
950 char *buf = emalloc(pathlen + 1);
951 ssize_t linklen;
952
953 T_QUIET; T_ASSERT_POSIX_SUCCESS((linklen = readlink("short-link", buf, pathlen)), CTXSTR);
954 T_QUIET; T_ASSERT_EQ((size_t)linklen, pathlen,
955 CTXFMT " linklen %zd", CTXARGS, (size_t)linklen);
956 buf[linklen] = '\0';
957
958 T_QUIET; T_ASSERT_EQ(strcmp(buf, path), 0, CTXSTR);
959 free(path);
960 free(buf);
961 } else {
962 free(path);
963 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
964 }
965 }
966
967 static void
test_symlink_intermediate(size_t pathlen,bool policy,int expected_errno)968 test_symlink_intermediate(size_t pathlen, bool policy, int expected_errno)
969 {
970 /*
971 * Create path with intermediate symlinks so that linked and original paths
972 * are of the same length.
973 */
974 char *path = createpath(pathlen, false, NULL);
975
976 // Find parent of path
977 char *lastslash = strrchr(path, '/');
978 if (lastslash == NULL || lastslash == path) {
979 free(path);
980 return;
981 }
982
983 size_t leaflen = strlen(lastslash + 1);
984
985 char *p = lastslash - 1;
986 while (p - 1 != path && *(p - 1) != '/') {
987 p--;
988 }
989
990 size_t parentlen = (uintptr_t)(lastslash - p);
991 char *parentname = emalloc(parentlen + 1);
992 memmove(parentname, p, parentlen);
993 parentname[parentlen] = '\0';
994
995 // Find grandparent of path, which will be the base path where to create a symlink
996 size_t baselen = pathlen - parentlen - 1 - 1 - leaflen;
997 char *basepath = emalloc(baselen + 1);
998 memmove(basepath, path, baselen);
999 basepath[baselen] = '\0';
1000
1001 // Create symlink
1002 char *linkname = emalloc(parentlen + 1);
1003 size_t n = generatename(linkname, parentlen, 49); // repeating Xs
1004 linkname[n] = '\0';
1005
1006 char *linkpath = NULL;
1007 asprintf(&linkpath, "%s/%s", basepath, linkname);
1008 free(linkname);
1009
1010 T_QUIET; T_ASSERT_EQ(strlen(linkpath) + 1 + leaflen, pathlen, NULL);
1011
1012 int rc = symlink(parentname, linkpath);
1013 free(parentname);
1014
1015 if (!policy) {
1016 if (strlen(linkpath) < MAXPATHLEN) {
1017 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
1018 } else {
1019 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, ENAMETOOLONG, CTXSTR);
1020 }
1021 } else {
1022 if (strlen(linkpath) < MAXLONGPATHLEN) {
1023 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
1024 } else {
1025 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, ENAMETOOLONG, CTXSTR);
1026 }
1027 }
1028
1029 char *linkedpath = NULL;
1030 asprintf(&linkedpath, "%s/%s", linkpath, lastslash + 1);
1031 T_QUIET; T_ASSERT_EQ(strlen(linkedpath), pathlen, NULL);
1032 free(linkpath);
1033
1034 int fd = open(linkedpath, O_EVTONLY);
1035 free(linkedpath);
1036
1037 if (expected_errno == 0) {
1038 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, CTXSTR);
1039 } else {
1040 T_QUIET; T_ASSERT_POSIX_FAILURE(fd, expected_errno, CTXSTR);
1041 }
1042 if (fd >= 0) {
1043 close(fd);
1044 }
1045 free(basepath);
1046 free(path);
1047 }
1048
1049 static void
test_unlinkat(size_t pathlen,bool policy,int expected_errno)1050 test_unlinkat(size_t pathlen, bool policy, int expected_errno)
1051 {
1052 char *path = createpath(pathlen, false, NULL);
1053 int rc = unlinkat(AT_FDCWD, path, 0);
1054 free(path);
1055
1056 if (expected_errno == 0) {
1057 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
1058 } else {
1059 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
1060 }
1061 }
1062
1063 static void
test_xattr(size_t pathlen,bool policy,int expected_errno)1064 test_xattr(size_t pathlen, bool policy, int expected_errno)
1065 {
1066 char *path = createpath(pathlen, false, NULL);
1067 char *name = "lpattr";
1068 char *value = "xpto";
1069 ssize_t valuelen = strlen(value);
1070
1071 int rc = setxattr(path, name, value, valuelen, 0, XATTR_CREATE);
1072 if (expected_errno == 0) {
1073 T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, CTXSTR);
1074 } else {
1075 T_QUIET; T_ASSERT_POSIX_FAILURE(rc, expected_errno, CTXSTR);
1076 }
1077
1078 char *buf = emalloc(valuelen);
1079 ssize_t attrlen = getxattr(path, name, buf, valuelen, 0, XATTR_CREATE);
1080 free(path);
1081 if (expected_errno == 0) {
1082 T_QUIET; T_ASSERT_POSIX_SUCCESS(attrlen, CTXSTR);
1083 T_QUIET; T_ASSERT_EQ(attrlen, valuelen, CTXSTR);
1084 T_QUIET; T_ASSERT_EQ(0, memcmp(buf, value, valuelen), CTXSTR);
1085 } else {
1086 T_QUIET; T_ASSERT_POSIX_FAILURE(attrlen, expected_errno, CTXSTR);
1087 }
1088 free(buf);
1089 }
1090
1091 #define SYSCALL_TEST(name, expected_errno_off, expected_errno_on) \
1092 T_DECL(longpaths_ ## name ## _test, "Test " #name " with long paths") \
1093 {\
1094 char *testdir = setup_test_dir(#name);\
1095 \
1096 disable_policy();\
1097 bool policy = false;\
1098 for (size_t i = 0; i < nelem(pathlengths); i++) {\
1099 size_t pathlen = pathlengths[i];\
1100 setup_case_dir(pathlen, policy);\
1101 test_ ## name (pathlen, policy, (expected_errno_off)[i]);\
1102 chdir("..");\
1103 }\
1104 \
1105 enable_policy();\
1106 policy = true;\
1107 for (size_t i = 0; i < nelem(pathlengths); i++) {\
1108 size_t pathlen = pathlengths[i];\
1109 setup_case_dir(pathlen, policy);\
1110 test_ ##name (pathlen, policy, (expected_errno_on)[i]);\
1111 chdir("..");\
1112 }\
1113 \
1114 removefile(testdir, NULL, REMOVEFILE_RECURSIVE | REMOVEFILE_ALLOW_LONG_PATHS);\
1115 free(testdir);\
1116 }
1117
1118 SYSCALL_TEST(access, common_errno_off, common_errno_on)
1119 SYSCALL_TEST(faccessat, common_errno_off, common_errno_on)
1120 SYSCALL_TEST(fstatat, common_errno_off, common_errno_on)
1121 SYSCALL_TEST(F_GETPATH, F_GETPATH_errno, F_GETPATH_errno)
1122
1123 SYSCALL_TEST(getattrlist_fileID, common_errno_off, common_errno_on)
1124 SYSCALL_TEST(getattrlist_nofirmlinkpath, common_errno_off, common_errno_on)
1125 SYSCALL_TEST(getattrlist_fullpath, common_errno_off, common_errno_on)
1126 SYSCALL_TEST(getattrlist_relpath, common_errno_off, common_errno_on)
1127
1128 SYSCALL_TEST(lstat, common_errno_off, common_errno_on)
1129 SYSCALL_TEST(mkdirat, common_errno_off, common_errno_on)
1130
1131 SYSCALL_TEST(open, common_errno_off, common_errno_on)
1132 SYSCALL_TEST(open_create, common_errno_off, common_errno_on)
1133 SYSCALL_TEST(open_volfs, common_errno_on, common_errno_on)
1134
1135 SYSCALL_TEST(openat, common_errno_off, common_errno_on)
1136 SYSCALL_TEST(openat_create, common_errno_off, common_errno_on)
1137
1138 SYSCALL_TEST(openbyid_np, openbyid_errno_off, openbyid_errno_on)
1139 SYSCALL_TEST(path_after_link, path_after_link_errno_off, path_after_link_errno_on)
1140 SYSCALL_TEST(renameatx_np, common_errno_off, common_errno_on)
1141
1142 SYSCALL_TEST(symlink_intermediate, common_errno_off, common_errno_on)
1143 // Even with the policy on, we should fail when symlinks target long paths
1144 SYSCALL_TEST(symlink_long2long, common_errno_off, common_errno_off)
1145 SYSCALL_TEST(symlink_long2short, common_errno_off, common_errno_on)
1146 SYSCALL_TEST(symlink_short2long, common_errno_off, common_errno_off)
1147
1148 SYSCALL_TEST(unlinkat, common_errno_off, common_errno_on)
1149 SYSCALL_TEST(xattr, common_errno_off, common_errno_on)
1150