xref: /xnu-12377.1.9/tests/vfs/resolve_beneath.c (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
1 /*
2  * Copyright (c) 2024 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 /* compile: xcrun -sdk macosx.internal clang -ldarwintest -o resolve_beneath resolve_beneath.c -g -Weverything */
30 
31 #include <stdio.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <sys/mount.h>
35 #include <sys/attr.h>
36 #include <sys/stat.h>
37 #include <sys/param.h>
38 #include <sys/xattr.h>
39 #include <sys/clonefile.h>
40 
41 #include <darwintest.h>
42 #include <darwintest/utils.h>
43 
44 static char template[MAXPATHLEN];
45 static char *testdir = NULL;
46 static int testdir_fd = -1, test_fd = -1;
47 
48 #ifndef ENOTCAPABLE
49 #define ENOTCAPABLE             107
50 #endif
51 
52 #ifndef O_RESOLVE_BENEATH
53 #define O_RESOLVE_BENEATH       0x1000
54 #endif
55 
56 #ifndef AT_RESOLVE_BENEATH
57 #define AT_RESOLVE_BENEATH      0x2000
58 #endif
59 
60 #ifndef XATTR_RESOLVE_BENEATH
61 #define XATTR_RESOLVE_BENEATH   0x0080
62 #endif
63 
64 #ifndef CLONE_RESOLVE_BENEATH
65 #define CLONE_RESOLVE_BENEATH   0x0010
66 #endif
67 
68 #ifndef RENAME_RESOLVE_BENEATH
69 #define RENAME_RESOLVE_BENEATH  0x0020
70 #endif
71 
72 #ifndef FSOPT_RESOLVE_BENEATH
73 #define FSOPT_RESOLVE_BENEATH   0x1000
74 #endif
75 
76 #define TEST_DIR "test_dir"
77 #define NESTED_DIR "test_dir/nested"
78 #define OUTSIDE_FILE "outside_file.txt"
79 #define INSIDE_FILE "test_dir/inside_file.txt"
80 #define NESTED_FILE "test_dir/nested/nested_file.txt"
81 #define SYMLINK "test_dir/symlink"
82 #define SYMLINK_TO_NESTED "test_dir/symlink_to_nested"
83 #define PARENT_SYMLINK "test_dir/parent_symlink"
84 #define CIRCULAR_SYMLINK "test_dir/circular_symlink"
85 #define SYMLINK_ABSOLUTE "test_dir/symlink_absolute"
86 
87 #define SYMLINK_FROM "../outside_file.txt"
88 #define SYMLINK_TO_NESTED_FROM "nested/nested_file.txt"
89 #define PARENT_SYMLINK_FROM ".."
90 #define CIRCULAR_SYMLINK_FROM "circular_symlink"
91 
92 T_GLOBAL_META(
93 	T_META_NAMESPACE("xnu.vfs"),
94 	T_META_RADAR_COMPONENT_NAME("xnu"),
95 	T_META_RADAR_COMPONENT_VERSION("vfs"),
96 	T_META_ASROOT(false),
97 	T_META_CHECK_LEAKS(false));
98 
99 static void
setup(const char * dirname)100 setup(const char *dirname)
101 {
102 	int fd;
103 
104 	testdir_fd = test_fd = -1;
105 
106 	/* Create test root directory */
107 	snprintf(template, sizeof(template), "%s/%s-XXXXXX", dt_tmpdir(), dirname);
108 	T_ASSERT_POSIX_NOTNULL((testdir = mkdtemp(template)), "Creating test root directory");
109 	T_ASSERT_POSIX_SUCCESS((testdir_fd = open(testdir, O_SEARCH, 0777)), "Opening test root directory %s", testdir);
110 
111 	/* Create test directories */
112 	T_ASSERT_POSIX_SUCCESS(mkdirat(testdir_fd, TEST_DIR, 0777), "Creating %s/%s", testdir, TEST_DIR);
113 	T_ASSERT_POSIX_SUCCESS((test_fd = openat(testdir_fd, TEST_DIR, O_SEARCH, 0777)), "Opening test directory %s/%s", testdir, TEST_DIR);
114 	T_ASSERT_POSIX_SUCCESS(mkdirat(testdir_fd, NESTED_DIR, 0777), "Creating %s/%s", testdir, NESTED_DIR);
115 
116 	/* Create test files */
117 	T_ASSERT_POSIX_SUCCESS((fd = openat(testdir_fd, OUTSIDE_FILE, O_CREAT | O_RDWR, 0777)), "Creating file %s/%s", testdir, OUTSIDE_FILE);
118 	T_ASSERT_POSIX_SUCCESS(close(fd), "Closing %s", OUTSIDE_FILE);
119 
120 	T_ASSERT_POSIX_SUCCESS((fd = openat(testdir_fd, INSIDE_FILE, O_CREAT | O_RDWR, 0777)), "Creating file %s/%s", testdir, INSIDE_FILE);
121 	T_ASSERT_POSIX_SUCCESS(close(fd), "Closing %s", INSIDE_FILE);
122 
123 	T_ASSERT_POSIX_SUCCESS((fd = openat(testdir_fd, NESTED_FILE, O_CREAT | O_RDWR, 0777)), "Creating file %s/%s", testdir, NESTED_FILE);
124 	T_ASSERT_POSIX_SUCCESS(close(fd), "Closing %s", NESTED_FILE);
125 
126 	/* Create test symlinks */
127 	T_ASSERT_POSIX_SUCCESS(symlinkat(SYMLINK_FROM, testdir_fd, SYMLINK), "Creating symlink %s/%s -> %s", testdir, SYMLINK, SYMLINK_FROM);
128 	T_ASSERT_POSIX_SUCCESS(symlinkat(SYMLINK_TO_NESTED_FROM, testdir_fd, SYMLINK_TO_NESTED), "Creating symlink %s/%s -> %s", testdir, SYMLINK_TO_NESTED, SYMLINK_TO_NESTED_FROM);
129 	T_ASSERT_POSIX_SUCCESS(symlinkat(PARENT_SYMLINK_FROM, testdir_fd, PARENT_SYMLINK), "Creating symlink %s/%s -> %s", testdir, PARENT_SYMLINK, PARENT_SYMLINK_FROM);
130 	T_ASSERT_POSIX_SUCCESS(symlinkat(CIRCULAR_SYMLINK_FROM, testdir_fd, CIRCULAR_SYMLINK), "Creating symlink %s/%s -> %s", testdir, CIRCULAR_SYMLINK, CIRCULAR_SYMLINK_FROM);
131 	T_ASSERT_POSIX_SUCCESS(symlinkat(testdir, testdir_fd, SYMLINK_ABSOLUTE), "Creating symlink %s/%s -> %s", testdir, SYMLINK_ABSOLUTE, testdir);
132 }
133 
134 static void
cleanup(void)135 cleanup(void)
136 {
137 	if (test_fd != -1) {
138 		close(test_fd);
139 	}
140 	if (testdir_fd != -1) {
141 		unlinkat(testdir_fd, SYMLINK_ABSOLUTE, 0);
142 		unlinkat(testdir_fd, CIRCULAR_SYMLINK, 0);
143 		unlinkat(testdir_fd, PARENT_SYMLINK, 0);
144 		unlinkat(testdir_fd, SYMLINK_TO_NESTED, 0);
145 		unlinkat(testdir_fd, SYMLINK, 0);
146 		unlinkat(testdir_fd, NESTED_FILE, 0);
147 		unlinkat(testdir_fd, NESTED_DIR, AT_REMOVEDIR);
148 		unlinkat(testdir_fd, INSIDE_FILE, 0);
149 		unlinkat(testdir_fd, TEST_DIR, AT_REMOVEDIR);
150 		unlinkat(testdir_fd, OUTSIDE_FILE, 0);
151 
152 		close(testdir_fd);
153 		if (rmdir(testdir)) {
154 			T_FAIL("Unable to remove the test directory (%s)", testdir);
155 		}
156 	}
157 }
158 
159 T_DECL(resolve_beneath_open,
160     "test open()/openat() using the O_RESOLVE_BENEATH flag")
161 {
162 	int fd, root_fd;
163 	char path[MAXPATHLEN];
164 
165 	T_SETUPBEGIN;
166 
167 	T_ATEND(cleanup);
168 	setup("resolve_beneath_open");
169 
170 	T_ASSERT_POSIX_SUCCESS((root_fd = open("/", O_SEARCH, 0777)), "Opening the root directory");
171 
172 	T_SETUPEND;
173 
174 	T_LOG("Testing the openat() syscall using O_RESOLVE_BENEATH");
175 
176 	/* Test Case 1: File within the directory */
177 	T_EXPECT_POSIX_SUCCESS((fd = openat(test_fd, "inside_file.txt", O_RDONLY | O_RESOLVE_BENEATH, 0777)), "Test Case 1: File within the directory");
178 	if (fd >= 0) {
179 		close(fd);
180 	}
181 
182 	/* Test Case 2: File using a symlink pointing outside */
183 	T_EXPECT_POSIX_FAILURE(openat(test_fd, "symlink", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
184 
185 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
186 	T_EXPECT_POSIX_FAILURE(openat(test_fd, "../outside_file.txt", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
187 
188 	/* Test Case 4: File within a nested directory */
189 	T_EXPECT_POSIX_SUCCESS((fd = openat(test_fd, "nested/nested_file.txt", O_RDONLY | O_RESOLVE_BENEATH, 0777)), "Test Case 4: File within a nested directory");
190 	if (fd >= 0) {
191 		close(fd);
192 	}
193 
194 	/* Test Case 5: Symlink to a file in a nested directory */
195 	T_EXPECT_POSIX_SUCCESS((fd = openat(test_fd, "symlink_to_nested", O_RDONLY | O_RESOLVE_BENEATH, 0777)), "Test Case 5: Symlink to a file within the same directory");
196 	if (fd >= 0) {
197 		close(fd);
198 	}
199 
200 	/* Test Case 6: File using an absolute path */
201 	T_EXPECT_POSIX_FAILURE(openat(test_fd, "/etc/passwd", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
202 
203 	/* Test Case 7: Valid symlink to parent directory */
204 	T_EXPECT_POSIX_FAILURE(openat(test_fd, "parent_symlink/outside_file.txt", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
205 
206 	/* Test Case 8: Circular symlink within directory */
207 	T_EXPECT_POSIX_FAILURE(openat(test_fd, "circular_symlink", O_RDONLY | O_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
208 
209 	/* Test Case 9: Path can not escape outside at any point of the resolution */
210 	T_EXPECT_POSIX_FAILURE(openat(test_fd, "../test_dir/inside_file.txt", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
211 
212 	/* Test Case 10: File using a symlink pointing to absolute path */
213 	T_EXPECT_POSIX_FAILURE(openat(test_fd, "symlink_absolute/test_dir/inside_file.txt", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
214 
215 	/* Test Case 11: Absolute path relative to the root directory */
216 	T_EXPECT_POSIX_FAILURE(openat(root_fd, "/etc/passwd", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 11: Absolute path relative to the root directory");
217 
218 	/* Test Case 12: Path can not escape outside of the root directory using dotdot */
219 	T_EXPECT_POSIX_FAILURE((fd = openat(root_fd, "../private", O_RESOLVE_BENEATH)), ENOTCAPABLE, "Test Case 12: Path can not escape outside of the root directory using dotdot");
220 
221 	/* Changing current directory to the test directory */
222 	T_ASSERT_POSIX_SUCCESS(fchdir(test_fd), "Changing directory to %s/%s", testdir, TEST_DIR);
223 
224 	T_LOG("Testing the open() syscall using O_RESOLVE_BENEATH");
225 
226 	/* Test Case 13: Open a file within the directory */
227 	T_EXPECT_POSIX_SUCCESS((fd = open("inside_file.txt", O_RDONLY | O_RESOLVE_BENEATH, 0777)), "Test Case 13: Open a file within the directory");
228 	if (fd >= 0) {
229 		close(fd);
230 	}
231 
232 	/* Test Case 14: Attempt to open a file using a symlink pointing outside */
233 	T_EXPECT_POSIX_FAILURE(open("symlink", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 14: Attempt to open a file using a symlink pointing outside");
234 
235 	/* Test Case 15: Attempt to open a file using ".." to navigate outside */
236 	T_EXPECT_POSIX_FAILURE(open("../outside_file.txt", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 15: Attempt to open a file using \"..\" to navigate outside");
237 
238 	/* Test Case 16: Open a file within a nested directory */
239 	T_EXPECT_POSIX_SUCCESS((fd = open("nested/nested_file.txt", O_RDONLY | O_RESOLVE_BENEATH, 0777)), "Test Case 16: Open a file within a nested directory");
240 	if (fd >= 0) {
241 		close(fd);
242 	}
243 
244 	/* Test Case 17: Symlink to a file in a nested directory */
245 	T_EXPECT_POSIX_SUCCESS((fd = open("symlink_to_nested", O_RDONLY | O_RESOLVE_BENEATH, 0777)), "Test Case 17: Symlink to a file within the same directory");
246 	if (fd >= 0) {
247 		close(fd);
248 	}
249 
250 	/* Test Case 18: Attempt to open a file using an absolute path */
251 	T_EXPECT_POSIX_FAILURE(open("/etc/passwd", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 18: Attempt to open a file using an absolute path");
252 
253 	/* Test Case 19: Valid symlink to parent directory */
254 	T_EXPECT_POSIX_FAILURE(open("parent_symlink/outside_file.txt", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 19: Valid symlink to parent directory");
255 
256 	/* Test Case 20: Circular symlink within directory */
257 	T_EXPECT_POSIX_FAILURE(open("circular_symlink", O_RDONLY | O_RESOLVE_BENEATH), ELOOP, "Test Case 20: Circular symlink within directory");
258 
259 	/* Test Case 21: Path can not escape outside at any point of the resolution */
260 	T_EXPECT_POSIX_FAILURE(open("../test_dir/inside_file.txt", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 21: Path can not escape outside at any point of the resolution");
261 
262 	/* Test Case 22: Attempt to open a file using a symlink pointing to absolute path */
263 	T_EXPECT_POSIX_FAILURE(open("symlink_absolute/test_dir/inside_file.txt", O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 22: Attempt to open a file using a symlink pointing to absolute path");
264 
265 	/* Test Case 23: Path can not escape outside at any point of the resolution using absolute path */
266 	snprintf(path, sizeof(path), "%s/%s", testdir, INSIDE_FILE);
267 	T_EXPECT_POSIX_FAILURE(open(path, O_RDONLY | O_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 23: Path can not escape outside at any point of the resolution using absolute path");
268 
269 	T_EXPECT_POSIX_SUCCESS(close(root_fd), "Closing the root directory");
270 }
271 
272 T_DECL(resolve_beneath_faccessat,
273     "test faccessat() using the AT_RESOLVE_BENEATH flag")
274 {
275 	T_SETUPBEGIN;
276 
277 	T_ATEND(cleanup);
278 	setup("resolve_beneath_faccessat");
279 
280 	T_SETUPEND;
281 
282 	T_LOG("Testing the faccessat() syscall using AT_RESOLVE_BENEATH");
283 
284 	/* Test Case 1: File within the directory */
285 	T_EXPECT_POSIX_SUCCESS(faccessat(test_fd, "inside_file.txt", R_OK, AT_RESOLVE_BENEATH), "Test Case 1: File within the directory");
286 
287 	/* Test Case 2: File using a symlink pointing outside */
288 	T_EXPECT_POSIX_FAILURE(faccessat(test_fd, "symlink", R_OK, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
289 
290 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
291 	T_EXPECT_POSIX_FAILURE(faccessat(test_fd, "../outside_file.txt", R_OK, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
292 
293 	/* Test Case 4: File within a nested directory */
294 	T_EXPECT_POSIX_SUCCESS(faccessat(test_fd, "nested/nested_file.txt", R_OK, AT_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
295 
296 	/* Test Case 5: Symlink to a file in a nested directory */
297 	T_EXPECT_POSIX_SUCCESS(faccessat(test_fd, "symlink_to_nested", R_OK, AT_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
298 
299 	/* Test Case 6: File using an absolute path */
300 	T_EXPECT_POSIX_FAILURE(faccessat(test_fd, "/etc/passwd", R_OK, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
301 
302 	/* Test Case 7: Valid symlink to parent directory */
303 	T_EXPECT_POSIX_FAILURE(faccessat(test_fd, "parent_symlink/outside_file.txt", R_OK, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
304 
305 	/* Test Case 8: Circular symlink within directory */
306 	T_EXPECT_POSIX_FAILURE(faccessat(test_fd, "circular_symlink", R_OK, AT_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
307 
308 	/* Test Case 9: Path can not escape outside at any point of the resolution */
309 	T_EXPECT_POSIX_FAILURE(faccessat(test_fd, "../test_dir/inside_file.txt", R_OK, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
310 
311 	/* Test Case 10: File using a symlink pointing to absolute path */
312 	T_EXPECT_POSIX_FAILURE(faccessat(test_fd, "symlink_absolute/test_dir/inside_file.txt", R_OK, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
313 }
314 
315 T_DECL(resolve_beneath_fstatat,
316     "test fstatat() using the AT_RESOLVE_BENEATH flag")
317 {
318 	struct stat buf;
319 
320 	T_SETUPBEGIN;
321 
322 	T_ATEND(cleanup);
323 	setup("resolve_beneath_fstatat");
324 
325 	T_SETUPEND;
326 
327 	T_LOG("Testing the fstatat() syscall using AT_RESOLVE_BENEATH");
328 
329 	/* Test Case 1: File within the directory */
330 	T_EXPECT_POSIX_SUCCESS(fstatat(test_fd, "inside_file.txt", &buf, AT_RESOLVE_BENEATH), "Test Case 1: File within the directory");
331 
332 	/* Test Case 2: File using a symlink pointing outside */
333 	T_EXPECT_POSIX_FAILURE(fstatat(test_fd, "symlink", &buf, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
334 
335 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
336 	T_EXPECT_POSIX_FAILURE(fstatat(test_fd, "../outside_file.txt", &buf, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
337 
338 	/* Test Case 4: File within a nested directory */
339 	T_EXPECT_POSIX_SUCCESS(fstatat(test_fd, "nested/nested_file.txt", &buf, AT_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
340 
341 	/* Test Case 5: Symlink to a file in a nested directory */
342 	T_EXPECT_POSIX_SUCCESS(fstatat(test_fd, "symlink_to_nested", &buf, AT_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
343 
344 	/* Test Case 6: File using an absolute path */
345 	T_EXPECT_POSIX_FAILURE(fstatat(test_fd, "/etc/passwd", &buf, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
346 
347 	/* Test Case 7: Valid symlink to parent directory */
348 	T_EXPECT_POSIX_FAILURE(fstatat(test_fd, "parent_symlink/outside_file.txt", &buf, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
349 
350 	/* Test Case 8: Circular symlink within directory */
351 	T_EXPECT_POSIX_FAILURE(fstatat(test_fd, "circular_symlink", &buf, AT_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
352 
353 	/* Test Case 9: Path can not escape outside at any point of the resolution */
354 	T_EXPECT_POSIX_FAILURE(fstatat(test_fd, "../test_dir/inside_file.txt", &buf, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
355 
356 	/* Test Case 10: File using a symlink pointing to absolute path */
357 	T_EXPECT_POSIX_FAILURE(fstatat(test_fd, "symlink_absolute/test_dir/inside_file.txt", &buf, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
358 }
359 
360 T_DECL(resolve_beneath_fchmodat,
361     "test fchmodat() using the AT_RESOLVE_BENEATH flag")
362 {
363 	T_SETUPBEGIN;
364 
365 	T_ATEND(cleanup);
366 	setup("resolve_beneath_fchmodat");
367 
368 	T_SETUPEND;
369 
370 	T_LOG("Testing the fchmodat() syscall using AT_RESOLVE_BENEATH");
371 
372 	/* Test Case 1: File within the directory */
373 	T_EXPECT_POSIX_SUCCESS(fchmodat(test_fd, "inside_file.txt", S_IRWXU, AT_RESOLVE_BENEATH), "Test Case 1: File within the directory");
374 
375 	/* Test Case 2: File using a symlink pointing outside */
376 	T_EXPECT_POSIX_FAILURE(fchmodat(test_fd, "symlink", S_IRWXU, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
377 
378 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
379 	T_EXPECT_POSIX_FAILURE(fchmodat(test_fd, "../outside_file.txt", S_IRWXU, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
380 
381 	/* Test Case 4: File within a nested directory */
382 	T_EXPECT_POSIX_SUCCESS(fchmodat(test_fd, "nested/nested_file.txt", S_IRWXU, AT_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
383 
384 	/* Test Case 5: Symlink to a file in a nested directory */
385 	T_EXPECT_POSIX_SUCCESS(fchmodat(test_fd, "symlink_to_nested", S_IRWXU, AT_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
386 
387 	/* Test Case 6: File using an absolute path */
388 	T_EXPECT_POSIX_FAILURE(fchmodat(test_fd, "/etc/passwd", S_IRWXU, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
389 
390 	/* Test Case 7: Valid symlink to parent directory */
391 	T_EXPECT_POSIX_FAILURE(fchmodat(test_fd, "parent_symlink/outside_file.txt", S_IRWXU, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
392 
393 	/* Test Case 8: Circular symlink within directory */
394 	T_EXPECT_POSIX_FAILURE(fchmodat(test_fd, "circular_symlink", S_IRWXU, AT_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
395 
396 	/* Test Case 9: Path can not escape outside at any point of the resolution */
397 	T_EXPECT_POSIX_FAILURE(fchmodat(test_fd, "../test_dir/inside_file.txt", S_IRWXU, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
398 
399 	/* Test Case 10: File using a symlink pointing to absolute path */
400 	T_EXPECT_POSIX_FAILURE(fchmodat(test_fd, "symlink_absolute/test_dir/inside_file.txt", S_IRWXU, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
401 }
402 
403 T_DECL(resolve_beneath_fchownat,
404     "test fchownat() using the AT_RESOLVE_BENEATH flag")
405 {
406 	T_SETUPBEGIN;
407 
408 	T_ATEND(cleanup);
409 	setup("resolve_beneath_fchownat");
410 
411 	T_SETUPEND;
412 
413 	T_LOG("Testing the fchownat() syscall using AT_RESOLVE_BENEATH");
414 
415 	/* Test Case 1: File within the directory */
416 	T_EXPECT_POSIX_SUCCESS(fchownat(test_fd, "inside_file.txt", geteuid(), getgid(), AT_RESOLVE_BENEATH), "Test Case 1: File within the directory");
417 
418 	/* Test Case 2: File using a symlink pointing outside */
419 	T_EXPECT_POSIX_FAILURE(fchownat(test_fd, "symlink", geteuid(), getgid(), AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
420 
421 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
422 	T_EXPECT_POSIX_FAILURE(fchownat(test_fd, "../outside_file.txt", geteuid(), getgid(), AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
423 
424 	/* Test Case 4: File within a nested directory */
425 	T_EXPECT_POSIX_SUCCESS(fchownat(test_fd, "nested/nested_file.txt", geteuid(), getgid(), AT_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
426 
427 	/* Test Case 5: Symlink to a file in a nested directory */
428 	T_EXPECT_POSIX_SUCCESS(fchownat(test_fd, "symlink_to_nested", geteuid(), getgid(), AT_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
429 
430 	/* Test Case 6: File using an absolute path */
431 	T_EXPECT_POSIX_FAILURE(fchownat(test_fd, "/etc/passwd", geteuid(), getgid(), AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
432 
433 	/* Test Case 7: Valid symlink to parent directory */
434 	T_EXPECT_POSIX_FAILURE(fchownat(test_fd, "parent_symlink/outside_file.txt", geteuid(), getgid(), AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
435 
436 	/* Test Case 8: Circular symlink within directory */
437 	T_EXPECT_POSIX_FAILURE(fchownat(test_fd, "circular_symlink", geteuid(), getgid(), AT_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
438 
439 	/* Test Case 9: Path can not escape outside at any point of the resolution */
440 	T_EXPECT_POSIX_FAILURE(fchownat(test_fd, "../test_dir/inside_file.txt", geteuid(), getgid(), AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
441 
442 	/* Test Case 10: File using a symlink pointing to absolute path */
443 	T_EXPECT_POSIX_FAILURE(fchownat(test_fd, "symlink_absolute/test_dir/inside_file.txt", geteuid(), getgid(), AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
444 }
445 
446 T_DECL(resolve_beneath_linkat,
447     "test linkat() using the AT_RESOLVE_BENEATH flag")
448 {
449 	T_SETUPBEGIN;
450 
451 	T_ATEND(cleanup);
452 	setup("resolve_beneath_linkat");
453 
454 	T_SETUPEND;
455 
456 	T_LOG("Testing the linkat() syscall using AT_RESOLVE_BENEATH");
457 
458 	/* Test Case 1: File within the directory */
459 	T_EXPECT_POSIX_SUCCESS(linkat(test_fd, "inside_file.txt", test_fd, "inside_file_2.txt", AT_RESOLVE_BENEATH), "Test Case 1: File within the directory");
460 	unlinkat(test_fd, "inside_file_2.txt", 0);
461 
462 	/* Test Case 2: File using a symlink pointing outside */
463 	T_EXPECT_POSIX_FAILURE(linkat(test_fd, "symlink/.", test_fd, "inside_file_2.txt", AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
464 
465 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
466 	T_EXPECT_POSIX_FAILURE(linkat(test_fd, "inside_file.txt", test_fd, "../outside_file.txt", AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
467 
468 	/* Test Case 4: File within a nested directory */
469 	T_EXPECT_POSIX_SUCCESS(linkat(test_fd, "nested/nested_file.txt", test_fd, "nested/nested_file_2.txt", AT_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
470 	unlinkat(test_fd, "nested/nested_file_2.txt", 0);
471 
472 	/* Test Case 5: Symlink to a file in a nested directory */
473 	T_EXPECT_POSIX_SUCCESS(linkat(test_fd, "symlink_to_nested", test_fd, "nested/nested_file_2.txt", AT_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
474 	unlinkat(test_fd, "nested/nested_file_2.txt", 0);
475 
476 	/* Test Case 6: File using an absolute path */
477 	T_EXPECT_POSIX_FAILURE(linkat(test_fd, "/etc/passwd", test_fd, "inside_file_2.txt", AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
478 }
479 
480 T_DECL(resolve_beneath_unlinkat,
481     "test unlinkat() using the AT_RESOLVE_BENEATH flag")
482 {
483 	int fd;
484 
485 	T_SETUPBEGIN;
486 
487 	T_ATEND(cleanup);
488 	setup("resolve_beneath_unlinkat");
489 
490 	T_SETUPEND;
491 
492 	T_LOG("Testing the unlinkat() syscall using AT_RESOLVE_BENEATH");
493 
494 	/* Test Case 1: File within the directory */
495 	T_EXPECT_POSIX_SUCCESS(unlinkat(test_fd, "inside_file.txt", AT_RESOLVE_BENEATH), "Test Case 1: File within the directory");
496 	if ((fd = openat(testdir_fd, INSIDE_FILE, O_CREAT | O_RDWR, 0777)) < 0) {
497 		T_FAIL("Unable to recreate %s", INSIDE_FILE);
498 	}
499 	close(fd);
500 
501 	/* Test Case 2: File using a symlink pointing outside */
502 	T_EXPECT_POSIX_SUCCESS(unlinkat(test_fd, "symlink", AT_RESOLVE_BENEATH), "Test Case 2: File using a symlink pointing outside");
503 	if (symlinkat(SYMLINK_FROM, testdir_fd, SYMLINK) < 0) {
504 		T_FAIL("Unable to recreate %s", INSIDE_FILE);
505 	}
506 
507 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
508 	T_EXPECT_POSIX_FAILURE(unlinkat(test_fd, "../outside_file.txt", AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
509 
510 	/* Test Case 4: File within a nested directory */
511 	T_EXPECT_POSIX_SUCCESS(unlinkat(test_fd, "nested/nested_file.txt", AT_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
512 	if ((fd = openat(testdir_fd, NESTED_FILE, O_CREAT | O_RDWR, 0777)) < 0) {
513 		T_FAIL("Unable to recreate %s", NESTED_FILE);
514 	}
515 	close(fd);
516 
517 	/* Test Case 5: Symlink to a file in a nested directory */
518 	T_EXPECT_POSIX_SUCCESS(unlinkat(test_fd, "symlink_to_nested", AT_RESOLVE_BENEATH), "Test Case 5: Symlink //to a file within the same directory");
519 	if (symlinkat(SYMLINK_TO_NESTED_FROM, testdir_fd, SYMLINK_TO_NESTED) < 0) {
520 		T_FAIL("Unable to recreate %s", SYMLINK_TO_NESTED);
521 	}
522 
523 	/* Test Case 6: File using an absolute path */
524 	T_EXPECT_POSIX_FAILURE(unlinkat(test_fd, "/etc/passwd", AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
525 
526 	/* Test Case 7: Valid symlink to parent directory */
527 	T_EXPECT_POSIX_FAILURE(unlinkat(test_fd, "parent_symlink/outside_file.txt", AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
528 
529 	/* Test Case 8: Circular symlink within directory */
530 	T_EXPECT_POSIX_SUCCESS(unlinkat(test_fd, "circular_symlink", AT_RESOLVE_BENEATH), "Test Case 8: Circular symlink within directory");
531 	if (symlinkat(CIRCULAR_SYMLINK_FROM, testdir_fd, CIRCULAR_SYMLINK) < 0) {
532 		T_FAIL("Unable to recreate %s", CIRCULAR_SYMLINK);
533 	}
534 
535 	/* Test Case 9: Path can not escape outside at any point of the resolution */
536 	T_EXPECT_POSIX_FAILURE(unlinkat(test_fd, "../test_dir/inside_file.txt", AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
537 
538 	/* Test Case 10: File using a symlink pointing to absolute path */
539 	T_EXPECT_POSIX_FAILURE(unlinkat(test_fd, "symlink_absolute/test_dir/inside_file.txt", AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
540 }
541 
542 T_DECL(resolve_beneath_utimensat,
543     "test utimensat() using the AT_RESOLVE_BENEATH flag")
544 {
545 	static const struct timespec tptr[] = {
546 		{ 0x12345678, 987654321 },
547 		{ 0x15263748, 123456789 },
548 	};
549 
550 	T_SETUPBEGIN;
551 
552 	T_ATEND(cleanup);
553 	setup("resolve_beneath_utimensat");
554 
555 	T_SETUPEND;
556 
557 	T_LOG("Testing the utimensat() syscall using AT_RESOLVE_BENEATH");
558 
559 	/* Test Case 1: File within the directory */
560 	T_EXPECT_POSIX_SUCCESS(utimensat(test_fd, "inside_file.txt", tptr, AT_RESOLVE_BENEATH), "Test Case 1: File within the directory");
561 
562 	/* Test Case 2: File using a symlink pointing outside */
563 	T_EXPECT_POSIX_FAILURE(utimensat(test_fd, "symlink", tptr, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
564 
565 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
566 	T_EXPECT_POSIX_FAILURE(utimensat(test_fd, "../outside_file.txt", tptr, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
567 
568 	/* Test Case 4: File within a nested directory */
569 	T_EXPECT_POSIX_SUCCESS(utimensat(test_fd, "nested/nested_file.txt", tptr, AT_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
570 
571 	/* Test Case 5: Symlink to a file in a nested directory */
572 	T_EXPECT_POSIX_SUCCESS(utimensat(test_fd, "symlink_to_nested", tptr, AT_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
573 
574 	/* Test Case 6: File using an absolute path */
575 	T_EXPECT_POSIX_FAILURE(utimensat(test_fd, "/etc/passwd", tptr, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
576 
577 	/* Test Case 7: Valid symlink to parent directory */
578 	T_EXPECT_POSIX_FAILURE(utimensat(test_fd, "parent_symlink/outside_file.txt", tptr, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
579 
580 	/* Test Case 8: Circular symlink within directory */
581 	T_EXPECT_POSIX_FAILURE(utimensat(test_fd, "circular_symlink", tptr, AT_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
582 
583 	/* Test Case 9: Path can not escape outside at any point of the resolution */
584 	T_EXPECT_POSIX_FAILURE(utimensat(test_fd, "../test_dir/inside_file.txt", tptr, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
585 
586 	/* Test Case 10: File using a symlink pointing to absolute path */
587 	T_EXPECT_POSIX_FAILURE(utimensat(test_fd, "symlink_absolute/test_dir/inside_file.txt", tptr, AT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
588 }
589 
590 T_DECL(resolve_beneath_getxattr,
591     "test getxattr()/fgetxattr() using the XATTR_RESOLVE_BENEATH flag")
592 {
593 	char xattr_buff[100];
594 	const char *xattr = "test1234";
595 	size_t xattr_len = strlen(xattr);
596 
597 	T_SETUPBEGIN;
598 
599 	T_ATEND(cleanup);
600 	setup("resolve_beneath_getxattr");
601 
602 	/* Changing current directory to the test directory */
603 	T_ASSERT_POSIX_SUCCESS(fchdir(test_fd), "Changing directory to %s/%s", testdir, TEST_DIR);
604 
605 	/* Setting extended attributes */
606 	T_ASSERT_POSIX_SUCCESS(setxattr("inside_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, 0), "Setting extended attributes to inside_file.txt");
607 	T_ASSERT_POSIX_SUCCESS(setxattr("../outside_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, 0), "Setting extended attributes to outside_file.txt");
608 	T_ASSERT_POSIX_SUCCESS(setxattr("nested/nested_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, 0), "Setting extended attributes to nested_file.txt");
609 
610 	T_SETUPEND;
611 
612 	T_LOG("Testing the getxattr() syscall using XATTR_RESOLVE_BENEATH");
613 
614 	/* Test Case 1: File within the directory */
615 	T_EXPECT_POSIX_SUCCESS(getxattr("inside_file.txt", XATTR_RESOURCEFORK_NAME, xattr_buff, sizeof(xattr_buff), 0, XATTR_RESOLVE_BENEATH), "Test Case 1: File within the directory");
616 
617 	/* Test Case 2: File using a symlink pointing outside */
618 	T_EXPECT_POSIX_FAILURE(getxattr("symlink", XATTR_RESOURCEFORK_NAME, xattr_buff, sizeof(xattr_buff), 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
619 
620 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
621 	T_EXPECT_POSIX_FAILURE(getxattr("../outside_file.txt", XATTR_RESOURCEFORK_NAME, xattr_buff, sizeof(xattr_buff), 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
622 
623 	/* Test Case 4: File within a nested directory */
624 	T_EXPECT_POSIX_SUCCESS(getxattr("nested/nested_file.txt", XATTR_RESOURCEFORK_NAME, xattr_buff, sizeof(xattr_buff), 0, XATTR_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
625 
626 	/* Test Case 5: Symlink to a file in a nested directory */
627 	T_EXPECT_POSIX_SUCCESS(getxattr("symlink_to_nested", XATTR_RESOURCEFORK_NAME, xattr_buff, sizeof(xattr_buff), 0, XATTR_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
628 
629 	/* Test Case 6: File using an absolute path */
630 	T_EXPECT_POSIX_FAILURE(getxattr("/etc/passwd", XATTR_RESOURCEFORK_NAME, xattr_buff, sizeof(xattr_buff), 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
631 
632 	/* Test Case 7: Valid symlink to parent directory */
633 	T_EXPECT_POSIX_FAILURE(getxattr("parent_symlink/outside_file.txt", XATTR_RESOURCEFORK_NAME, xattr_buff, sizeof(xattr_buff), 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
634 
635 	/* Test Case 8: Circular symlink within directory */
636 	T_EXPECT_POSIX_FAILURE(getxattr("circular_symlink", XATTR_RESOURCEFORK_NAME, xattr_buff, sizeof(xattr_buff), 0, XATTR_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
637 
638 	/* Test Case 9: Path can not escape outside at any point of the resolution */
639 	T_EXPECT_POSIX_FAILURE(getxattr("../test_dir/inside_file.txt", XATTR_RESOURCEFORK_NAME, xattr_buff, sizeof(xattr_buff), 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
640 
641 	/* Test Case 10: File using a symlink pointing to absolute path */
642 	T_EXPECT_POSIX_FAILURE(getxattr("symlink_absolute/test_dir/inside_file.txt", XATTR_RESOURCEFORK_NAME, xattr_buff, sizeof(xattr_buff), 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
643 
644 	T_LOG("Testing the fgetxattr() syscall using XATTR_RESOLVE_BENEATH");
645 
646 	/* Test Case 11: Verifying that fgetxattr() fails with EINVAL */
647 	T_EXPECT_POSIX_FAILURE(fgetxattr(test_fd, XATTR_RESOURCEFORK_NAME, xattr_buff, sizeof(xattr_buff), 0, XATTR_RESOLVE_BENEATH), EINVAL, "Test Case 11: Verifying that fgetxattr() fails with EINVAL");
648 }
649 
650 T_DECL(resolve_beneath_setxattr,
651     "test setxattr()/fsetxattr() using the XATTR_RESOLVE_BENEATH flag")
652 {
653 	const char *xattr = "test1234";
654 	size_t xattr_len = strlen(xattr);
655 
656 	T_SETUPBEGIN;
657 
658 	T_ATEND(cleanup);
659 	setup("resolve_beneath_setxattr");
660 
661 	/* Changing current directory to the test directory */
662 	T_ASSERT_POSIX_SUCCESS(fchdir(test_fd), "Changing directory to %s/%s", testdir, TEST_DIR);
663 
664 	T_SETUPEND;
665 
666 	T_LOG("Testing the setxattr() syscall using XATTR_RESOLVE_BENEATH");
667 
668 	/* Test Case 1: File within the directory */
669 	T_EXPECT_POSIX_SUCCESS(setxattr("inside_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, XATTR_RESOLVE_BENEATH), "Test Case 1: File within the directory");
670 
671 	/* Test Case 2: File using a symlink pointing outside */
672 	T_EXPECT_POSIX_FAILURE(setxattr("symlink", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
673 
674 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
675 	T_EXPECT_POSIX_FAILURE(setxattr("../outside_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
676 
677 	/* Test Case 4: File within a nested directory */
678 	T_EXPECT_POSIX_SUCCESS(setxattr("nested/nested_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, XATTR_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
679 
680 	/* Test Case 5: Symlink to a file in a nested directory */
681 	T_EXPECT_POSIX_SUCCESS(setxattr("symlink_to_nested", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, XATTR_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
682 
683 	/* Test Case 6: File using an absolute path */
684 	T_EXPECT_POSIX_FAILURE(setxattr("/etc/passwd", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
685 
686 	/* Test Case 7: Valid symlink to parent directory */
687 	T_EXPECT_POSIX_FAILURE(setxattr("parent_symlink/outside_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
688 
689 	/* Test Case 8: Circular symlink within directory */
690 	T_EXPECT_POSIX_FAILURE(setxattr("circular_symlink", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, XATTR_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
691 
692 	/* Test Case 9: Path can not escape outside at any point of the resolution */
693 	T_EXPECT_POSIX_FAILURE(setxattr("../test_dir/inside_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
694 
695 	/* Test Case 10: File using a symlink pointing to absolute path */
696 	T_EXPECT_POSIX_FAILURE(setxattr("symlink_absolute/test_dir/inside_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
697 
698 	T_LOG("Testing the fsetxattr() syscall using XATTR_RESOLVE_BENEATH");
699 
700 	/* Test Case 11: Verifying that fsetxattr() fails with EINVAL */
701 	T_EXPECT_POSIX_FAILURE(fsetxattr(test_fd, XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, XATTR_RESOLVE_BENEATH), EINVAL, "Test Case 11: Verifying that fsetxattr() fails with EINVAL");
702 }
703 
704 T_DECL(resolve_beneath_listxattr,
705     "test listxattr()/flistxattr() using the XATTR_RESOLVE_BENEATH flag")
706 {
707 	char xattr_buff[100];
708 
709 	T_SETUPBEGIN;
710 
711 	T_ATEND(cleanup);
712 	setup("resolve_beneath_listxattr");
713 
714 	/* Changing current directory to the test directory */
715 	T_ASSERT_POSIX_SUCCESS(fchdir(test_fd), "Changing directory to %s/%s", testdir, TEST_DIR);
716 
717 	T_SETUPEND;
718 
719 	T_LOG("Testing the listxattr() syscall using XATTR_RESOLVE_BENEATH");
720 
721 	/* Test Case 1: File within the directory */
722 	T_EXPECT_POSIX_SUCCESS(listxattr("inside_file.txt", xattr_buff, sizeof(xattr_buff), XATTR_RESOLVE_BENEATH), "Test Case 1: File within the directory");
723 
724 	/* Test Case 2: File using a symlink pointing outside */
725 	T_EXPECT_POSIX_FAILURE(listxattr("symlink", xattr_buff, sizeof(xattr_buff), XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
726 
727 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
728 	T_EXPECT_POSIX_FAILURE(listxattr("../outside_file.txt", xattr_buff, sizeof(xattr_buff), XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
729 
730 	/* Test Case 4: File within a nested directory */
731 	T_EXPECT_POSIX_SUCCESS(listxattr("nested/nested_file.txt", xattr_buff, sizeof(xattr_buff), XATTR_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
732 
733 	/* Test Case 5: Symlink to a file in a nested directory */
734 	T_EXPECT_POSIX_SUCCESS(listxattr("symlink_to_nested", xattr_buff, sizeof(xattr_buff), XATTR_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
735 
736 	/* Test Case 6: File using an absolute path */
737 	T_EXPECT_POSIX_FAILURE(listxattr("/etc/passwd", xattr_buff, sizeof(xattr_buff), XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
738 
739 	/* Test Case 7: Valid symlink to parent directory */
740 	T_EXPECT_POSIX_FAILURE(listxattr("parent_symlink/outside_file.txt", xattr_buff, sizeof(xattr_buff), XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
741 
742 	/* Test Case 8: Circular symlink within directory */
743 	T_EXPECT_POSIX_FAILURE(listxattr("circular_symlink", xattr_buff, sizeof(xattr_buff), XATTR_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
744 
745 	/* Test Case 9: Path can not escape outside at any point of the resolution */
746 	T_EXPECT_POSIX_FAILURE(listxattr("../test_dir/inside_file.txt", xattr_buff, sizeof(xattr_buff), XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
747 
748 	/* Test Case 10: File using a symlink pointing to absolute path */
749 	T_EXPECT_POSIX_FAILURE(listxattr("symlink_absolute/test_dir/inside_file.txt", xattr_buff, sizeof(xattr_buff), XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
750 
751 	T_LOG("Testing the flistxattr() syscall using XATTR_RESOLVE_BENEATH");
752 
753 	/* Test Case 11: Verifying that flistxattr() fails with EINVAL */
754 	T_EXPECT_POSIX_FAILURE(flistxattr(test_fd, xattr_buff, sizeof(xattr_buff), XATTR_RESOLVE_BENEATH), EINVAL, "Test Case 11: Verifying that flistxattr() fails with EINVAL");
755 }
756 
757 T_DECL(resolve_beneath_removexattr,
758     "test removexattr()/fremovexattr() using the XATTR_RESOLVE_BENEATH flag")
759 {
760 	const char *xattr = "test1234";
761 	size_t xattr_len = strlen(xattr);
762 
763 	T_SETUPBEGIN;
764 
765 	T_ATEND(cleanup);
766 	setup("resolve_beneath_removexattr");
767 
768 	/* Changing current directory to the test directory */
769 	T_ASSERT_POSIX_SUCCESS(fchdir(test_fd), "Changing directory to %s/%s", testdir, TEST_DIR);
770 
771 	/* Setting extended attributes */
772 	T_ASSERT_POSIX_SUCCESS(setxattr("inside_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, 0), "Setting extended attributes to inside_file.txt");
773 	T_ASSERT_POSIX_SUCCESS(setxattr("../outside_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, 0), "Setting extended attributes to outside_file.txt");
774 	T_ASSERT_POSIX_SUCCESS(setxattr("nested/nested_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, 0), "Setting extended attributes to nested_file.txt");
775 
776 	T_SETUPEND;
777 
778 	T_LOG("Testing the removexattr() syscall using XATTR_RESOLVE_BENEATH");
779 
780 	/* Test Case 1: File within the directory */
781 	T_EXPECT_POSIX_SUCCESS(removexattr("inside_file.txt", XATTR_RESOURCEFORK_NAME, XATTR_RESOLVE_BENEATH), "Test Case 1: File within the directory");
782 
783 	/* Test Case 2: File using a symlink pointing outside */
784 	T_EXPECT_POSIX_FAILURE(removexattr("symlink", XATTR_RESOURCEFORK_NAME, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
785 
786 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
787 	T_EXPECT_POSIX_FAILURE(removexattr("../outside_file.txt", XATTR_RESOURCEFORK_NAME, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
788 
789 	/* Test Case 4: File within a nested directory */
790 	T_EXPECT_POSIX_SUCCESS(removexattr("nested/nested_file.txt", XATTR_RESOURCEFORK_NAME, XATTR_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
791 
792 	if (setxattr("nested/nested_file.txt", XATTR_RESOURCEFORK_NAME, xattr, xattr_len, 0, 0) < 0) {
793 		T_FAIL("Unable to setxattr to nested_file.txt");
794 	}
795 
796 	/* Test Case 5: Symlink to a file in a nested directory */
797 	T_EXPECT_POSIX_SUCCESS(removexattr("symlink_to_nested", XATTR_RESOURCEFORK_NAME, XATTR_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
798 
799 	/* Test Case 6: File using an absolute path */
800 	T_EXPECT_POSIX_FAILURE(removexattr("/etc/passwd", XATTR_RESOURCEFORK_NAME, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
801 
802 	/* Test Case 7: Valid symlink to parent directory */
803 	T_EXPECT_POSIX_FAILURE(removexattr("parent_symlink/outside_file.txt", XATTR_RESOURCEFORK_NAME, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
804 
805 	/* Test Case 8: Circular symlink within directory */
806 	T_EXPECT_POSIX_FAILURE(removexattr("circular_symlink", XATTR_RESOURCEFORK_NAME, XATTR_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
807 
808 	/* Test Case 9: Path can not escape outside at any point of the resolution */
809 	T_EXPECT_POSIX_FAILURE(removexattr("../test_dir/inside_file.txt", XATTR_RESOURCEFORK_NAME, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
810 
811 	/* Test Case 10: File using a symlink pointing to absolute path */
812 	T_EXPECT_POSIX_FAILURE(removexattr("symlink_absolute/test_dir/inside_file.txt", XATTR_RESOURCEFORK_NAME, XATTR_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
813 
814 	T_LOG("Testing the fremovexattr() syscall using XATTR_RESOLVE_BENEATH");
815 
816 	/* Test Case 11: Verifying that fremovexattr() fails with EINVAL */
817 	T_EXPECT_POSIX_FAILURE(fremovexattr(test_fd, XATTR_RESOURCEFORK_NAME, XATTR_RESOLVE_BENEATH), EINVAL, "Test Case 11: Verifying that fremovexattr() fails with EINVAL");
818 }
819 
820 T_DECL(resolve_beneath_clonefile,
821     "test clonefile()/clonefileat()/fclonefileat() using the CLONE_RESOLVE_BENEATH flag")
822 {
823 	int fd;
824 	T_SETUPBEGIN;
825 
826 	T_ATEND(cleanup);
827 	setup("resolve_beneath_clonefile");
828 
829 	/* Changing current directory to the test directory */
830 	T_ASSERT_POSIX_SUCCESS(fchdir(test_fd), "Changing directory to %s/%s", testdir, TEST_DIR);
831 
832 	/* Open test file */
833 	T_ASSERT_POSIX_SUCCESS((fd = open("inside_file.txt", O_RDWR, 0777)), "Opening %s", INSIDE_FILE);
834 
835 	T_SETUPEND;
836 
837 	T_LOG("Testing the clonefile() syscall using CLONE_RESOLVE_BENEATH");
838 
839 	/* Test Case 1: File within the directory */
840 	T_EXPECT_POSIX_SUCCESS(clonefile("inside_file.txt", "inside_file_2.txt", CLONE_RESOLVE_BENEATH), "Test Case 1: File within the directory");
841 	unlink("inside_file_2.txt");
842 
843 	/* Test Case 2: File using a symlink pointing outside */
844 	T_EXPECT_POSIX_FAILURE(clonefile("symlink", "inside_file_2.txt", CLONE_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
845 
846 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
847 	T_EXPECT_POSIX_FAILURE(clonefile("inside_file.txt", "../outside_file.txt", CLONE_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
848 
849 	/* Test Case 4: File within a nested directory */
850 	T_EXPECT_POSIX_SUCCESS(clonefile("nested/nested_file.txt", "nested/nested_file_2.txt", CLONE_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
851 	unlinkat(test_fd, "nested/nested_file_2.txt", 0);
852 
853 	/* Test Case 5: Symlink to a file in a nested directory */
854 	T_EXPECT_POSIX_SUCCESS(clonefile("symlink_to_nested", "nested/nested_file_2.txt", CLONE_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
855 	unlinkat(test_fd, "nested/nested_file_2.txt", 0);
856 
857 	/* Test Case 6: File using an absolute path */
858 	T_EXPECT_POSIX_FAILURE(clonefile("/etc/passwd", "inside_file_2.txt", CLONE_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
859 
860 	T_LOG("Testing the clonefileat() syscall using CLONE_RESOLVE_BENEATH");
861 
862 	/* Test Case 7: File within the directory */
863 	T_EXPECT_POSIX_SUCCESS(clonefileat(test_fd, "inside_file.txt", test_fd, "inside_file_2.txt", CLONE_RESOLVE_BENEATH), "Test Case 7: File within the directory");
864 	unlinkat(test_fd, "inside_file_2.txt", 0);
865 
866 	/* Test Case 8: File using a symlink pointing outside */
867 	T_EXPECT_POSIX_FAILURE(clonefileat(test_fd, "symlink", test_fd, "inside_file_2.txt", CLONE_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 8: File using a symlink pointing outside");
868 
869 	/* Test Case 9: Attempt to open a file using ".." to navigate outside */
870 	T_EXPECT_POSIX_FAILURE(clonefileat(test_fd, "inside_file.txt", test_fd, "../outside_file.txt", CLONE_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: File using \"..\" to navigate outside");
871 
872 	/* Test Case 10: File within a nested directory */
873 	T_EXPECT_POSIX_SUCCESS(clonefileat(test_fd, "nested/nested_file.txt", test_fd, "nested/nested_file_2.txt", CLONE_RESOLVE_BENEATH), "Test Case 10: File within a nested directory");
874 	unlinkat(test_fd, "nested/nested_file_2.txt", 0);
875 
876 	/* Test Case 11: Symlink to a file in a nested directory */
877 	T_EXPECT_POSIX_SUCCESS(clonefileat(test_fd, "symlink_to_nested", test_fd, "nested/nested_file_2.txt", CLONE_RESOLVE_BENEATH), "Test Case 11: Symlink to a file within the same directory");
878 	unlinkat(test_fd, "nested/nested_file_2.txt", 0);
879 
880 	/* Test Case 12: File using an absolute path */
881 	T_EXPECT_POSIX_FAILURE(clonefileat(test_fd, "/etc/passwd", test_fd, "inside_file_2.txt", CLONE_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 12: File using an absolute path");
882 
883 	T_LOG("Testing the fclonefileat() syscall using CLONE_RESOLVE_BENEATH");
884 
885 	/* Test Case 13: File within the directory */
886 	T_EXPECT_POSIX_SUCCESS(fclonefileat(fd, test_fd, "inside_file_2.txt", CLONE_RESOLVE_BENEATH), "Test Case 13: File within the directory");
887 	unlinkat(test_fd, "inside_file_2.txt", 0);
888 
889 	/* Test Case 14: File using a symlink pointing outside */
890 	T_EXPECT_POSIX_FAILURE(fclonefileat(fd, test_fd, "symlink_absolute/test_dir/inside_file.txt", CLONE_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 14: File using a symlink pointing outside");
891 
892 	/* Test Case 15: Attempt to open a file using ".." to navigate outside */
893 	T_EXPECT_POSIX_FAILURE(fclonefileat(fd, test_fd, "../outside_file.txt", CLONE_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 15: File using \"..\" to navigate outside");
894 
895 	/* Test Case 16: File within a nested directory */
896 	T_EXPECT_POSIX_SUCCESS(fclonefileat(fd, test_fd, "nested/nested_file_2.txt", CLONE_RESOLVE_BENEATH), "Test Case 16: File within a nested directory");
897 	unlinkat(test_fd, "nested/nested_file_2.txt", 0);
898 
899 	/* Test Case 17: Symlink to a file in a nested directory */
900 	T_EXPECT_POSIX_SUCCESS(fclonefileat(fd, test_fd, "nested/nested_file_2.txt", CLONE_RESOLVE_BENEATH), "Test Case 17: Symlink to a file within the same directory");
901 	unlinkat(test_fd, "nested/nested_file_2.txt", 0);
902 
903 	/* Test Case 18: File using an absolute path */
904 	T_EXPECT_POSIX_FAILURE(fclonefileat(fd, test_fd, "/etc/inside_file_2.txt", CLONE_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 18: File using an absolute path");
905 
906 	T_EXPECT_POSIX_SUCCESS(close(fd), "Closing %s", INSIDE_FILE);
907 }
908 
909 T_DECL(resolve_beneath_renamex_np,
910     "test renamex_np()/renameatx_np() using the RENAME_RESOLVE_BENEATH flag")
911 {
912 	T_SETUPBEGIN;
913 
914 	T_ATEND(cleanup);
915 	setup("resolve_beneath_renamex_np");
916 
917 	/* Changing current directory to the test directory */
918 	T_ASSERT_POSIX_SUCCESS(fchdir(test_fd), "Changing directory to %s/%s", testdir, TEST_DIR);
919 
920 	T_SETUPEND;
921 
922 	T_LOG("Testing the renamex_np() syscall using RENAME_RESOLVE_BENEATH");
923 
924 	/* Test Case 1: File within the directory */
925 	T_EXPECT_POSIX_SUCCESS(renamex_np("inside_file.txt", "inside_file_2.txt", RENAME_RESOLVE_BENEATH), "Test Case 1: File within the directory");
926 	if (renamex_np("inside_file_2.txt", "inside_file.txt", 0)) {
927 		T_FAIL("Unable to rename inside_file_2.txt to inside_file.txt");
928 	}
929 
930 	/* Test Case 2: File using a symlink pointing outside */
931 	T_EXPECT_POSIX_FAILURE(renamex_np("symlink/.", "inside_file_2.txt", RENAME_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
932 
933 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
934 	T_EXPECT_POSIX_FAILURE(renamex_np("inside_file.txt", "../outside_file.txt", RENAME_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
935 
936 	/* Test Case 4: File within a nested directory */
937 	T_EXPECT_POSIX_SUCCESS(renamex_np("nested/nested_file.txt", "nested/nested_file_2.txt", RENAME_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
938 	if (renamex_np("nested/nested_file_2.txt", "nested/nested_file.txt", 0)) {
939 		T_FAIL("Unable to rename nested/nested_file_2.txt to nested/nested_file.txt");
940 	}
941 
942 	/* Test Case 5: Symlink to a file in a nested directory */
943 	T_EXPECT_POSIX_SUCCESS(renamex_np("symlink_to_nested", "nested/nested_file_2.txt", RENAME_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
944 	if (renamex_np("nested/nested_file_2.txt", "symlink_to_nested", 0)) {
945 		T_FAIL("Unable to rename nested/nested_file_2.txt to symlink_to_nested");
946 	}
947 
948 	/* Test Case 6: File using an absolute path */
949 	T_EXPECT_POSIX_FAILURE(renamex_np("/etc/passwd", "inside_file_2.txt", RENAME_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
950 
951 	T_LOG("Testing the renameatx_np() syscall using RENAME_RESOLVE_BENEATH");
952 
953 	/* Test Case 7: File within the directory */
954 	T_EXPECT_POSIX_SUCCESS(renameatx_np(test_fd, "inside_file.txt", test_fd, "inside_file_2.txt", RENAME_RESOLVE_BENEATH), "Test Case 7: File within the directory");
955 	if (renamex_np("inside_file_2.txt", "inside_file.txt", 0)) {
956 		T_FAIL("Unable to rename inside_file_2.txt to inside_file.txt");
957 	}
958 
959 	/* Test Case 8: File using a symlink pointing outside */
960 	T_EXPECT_POSIX_FAILURE(renameatx_np(test_fd, "symlink/.", test_fd, "inside_file_2.txt", RENAME_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 8: File using a symlink pointing outside");
961 
962 	/* Test Case 9: Attempt to open a file using ".." to navigate outside */
963 	T_EXPECT_POSIX_FAILURE(renameatx_np(test_fd, "inside_file.txt", test_fd, "../outside_file.txt", RENAME_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: File using \"..\" to navigate outside");
964 
965 	/* Test Case 10: File within a nested directory */
966 	T_EXPECT_POSIX_SUCCESS(renameatx_np(test_fd, "nested/nested_file.txt", test_fd, "nested/nested_file_2.txt", RENAME_RESOLVE_BENEATH), "Test Case 10: File within a nested directory");
967 	if (renamex_np("nested/nested_file_2.txt", "nested/nested_file.txt", 0)) {
968 		T_FAIL("Unable to rename nested/nested_file_2.txt to nested/nested_file.txt");
969 	}
970 
971 	/* Test Case 11: Symlink to a file in a nested directory */
972 	T_EXPECT_POSIX_SUCCESS(renameatx_np(test_fd, "symlink_to_nested", test_fd, "nested/nested_file_2.txt", RENAME_RESOLVE_BENEATH), "Test Case 11: Symlink to a file within the same directory");
973 	if (renamex_np("nested/nested_file_2.txt", "symlink_to_nested", 0)) {
974 		T_FAIL("Unable to rename nested/nested_file_2.txt to symlink_to_nested");
975 	}
976 
977 	/* Test Case 12: File using an absolute path */
978 	T_EXPECT_POSIX_FAILURE(renameatx_np(test_fd, "/etc/passwd", test_fd, "inside_file_2.txt", RENAME_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 12: File using an absolute path");
979 }
980 
981 T_DECL(resolve_beneath_getattrlist,
982     "test getattrlist()/fgetattrlist()/getattrlistat() using the FSOPT_RESOLVE_BENEATH flag")
983 {
984 	int fd;
985 
986 	struct myattrbuf {
987 		uint32_t length;
988 		attribute_set_t returned_attrs;
989 		vol_attributes_attr_t vol_attributes;
990 		attrreference_t fstypename_ref;
991 		uint32_t fssubtype;
992 		char fstypename[MFSTYPENAMELEN];
993 	} attrbuf;
994 
995 	struct attrlist attrs = {
996 		.bitmapcount = ATTR_BIT_MAP_COUNT,
997 		.commonattr = ATTR_CMN_RETURNED_ATTRS,
998 		/*
999 		 * Request ATTR_VOL_ATTRIBUTES to ensure that
1000 		 * ATTR_VOL_FSTYPENAME and ATTR_VOL_FSSUBTYPE
1001 		 * are packed into the buffer *after*.
1002 		 */
1003 		.volattr = ATTR_VOL_INFO | ATTR_VOL_ATTRIBUTES |
1004 	    ATTR_VOL_FSTYPENAME | ATTR_VOL_FSSUBTYPE,
1005 	};
1006 
1007 	T_SETUPBEGIN;
1008 
1009 	T_ATEND(cleanup);
1010 	setup("resolve_beneath_getattrlist");
1011 
1012 	/* Changing current directory to the test directory */
1013 	T_ASSERT_POSIX_SUCCESS(fchdir(test_fd), "Changing directory to %s/%s", testdir, TEST_DIR);
1014 
1015 	/* Open test file */
1016 	T_ASSERT_POSIX_SUCCESS((fd = open("inside_file.txt", O_RDWR, 0777)), "Opening %s", INSIDE_FILE);
1017 
1018 	T_SETUPEND;
1019 
1020 	T_LOG("Testing the getattrlist() syscall using FSOPT_RESOLVE_BENEATH");
1021 
1022 	/* Test Case 1: File within the directory */
1023 	T_EXPECT_POSIX_SUCCESS(getattrlist("inside_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), "Test Case 1: File within the directory");
1024 
1025 	/* Test Case 2: File using a symlink pointing outside */
1026 	T_EXPECT_POSIX_FAILURE(getattrlist("symlink", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
1027 
1028 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
1029 	T_EXPECT_POSIX_FAILURE(getattrlist("../outside_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
1030 
1031 	/* Test Case 4: File within a nested directory */
1032 	T_EXPECT_POSIX_SUCCESS(getattrlist("nested/nested_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
1033 
1034 	/* Test Case 5: Symlink to a file in a nested directory */
1035 	T_EXPECT_POSIX_SUCCESS(getattrlist("symlink_to_nested", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
1036 
1037 	/* Test Case 6: File using an absolute path */
1038 	T_EXPECT_POSIX_FAILURE(getattrlist("/etc/passwd", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
1039 
1040 	/* Test Case 7: Valid symlink to parent directory */
1041 	T_EXPECT_POSIX_FAILURE(getattrlist("parent_symlink/outside_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
1042 
1043 	/* Test Case 8: Circular symlink within directory */
1044 	T_EXPECT_POSIX_FAILURE(getattrlist("circular_symlink", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
1045 
1046 	/* Test Case 9: Path can not escape outside at any point of the resolution */
1047 	T_EXPECT_POSIX_FAILURE(getattrlist("../test_dir/inside_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
1048 
1049 	/* Test Case 10: File using a symlink pointing to absolute path */
1050 	T_EXPECT_POSIX_FAILURE(getattrlist("symlink_absolute/test_dir/inside_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
1051 
1052 	T_LOG("Testing the fgetattrlist() syscall using FSOPT_RESOLVE_BENEATH");
1053 
1054 	/* Test Case 11: fgetattrlist() syscall using FSOPT_RESOLVE_BENEATH */
1055 	T_EXPECT_POSIX_SUCCESS(fgetattrlist(fd, &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), "Test Case 11: fgetattrlist() syscall using FSOPT_RESOLVE_BENEATH");
1056 
1057 	T_LOG("Testing the getattrlistat() syscall using FSOPT_RESOLVE_BENEATH");
1058 
1059 	/* Test Case 12: File within the directory */
1060 	T_EXPECT_POSIX_SUCCESS(getattrlistat(test_fd, "inside_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), "Test Case 12: File within the directory");
1061 
1062 	/* Test Case 13: File using a symlink pointing outside */
1063 	T_EXPECT_POSIX_FAILURE(getattrlistat(test_fd, "symlink", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 13: File using a symlink pointing outside");
1064 
1065 	/* Test Case 14: Attempt to open a file using ".." to navigate outside */
1066 	T_EXPECT_POSIX_FAILURE(getattrlistat(test_fd, "../outside_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 14: File using \"..\" to navigate outside");
1067 
1068 	/* Test Case 15: File within a nested directory */
1069 	T_EXPECT_POSIX_SUCCESS(getattrlistat(test_fd, "nested/nested_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), "Test Case 15: File within a nested directory");
1070 
1071 	/* Test Case 16: Symlink to a file in a nested directory */
1072 	T_EXPECT_POSIX_SUCCESS(getattrlistat(test_fd, "symlink_to_nested", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), "Test Case 16: Symlink to a file within the same directory");
1073 
1074 	/* Test Case 17: File using an absolute path */
1075 	T_EXPECT_POSIX_FAILURE(getattrlistat(test_fd, "/etc/passwd", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 17: File using an absolute path");
1076 
1077 	/* Test Case 18: Valid symlink to parent directory */
1078 	T_EXPECT_POSIX_FAILURE(getattrlistat(test_fd, "parent_symlink/outside_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 18: Valid symlink to parent directory");
1079 
1080 	/* Test Case 19: Circular symlink within directory */
1081 	T_EXPECT_POSIX_FAILURE(getattrlistat(test_fd, "circular_symlink", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ELOOP, "Test Case 19: Circular symlink within directory");
1082 
1083 	/* Test Case 20: Path can not escape outside at any point of the resolution */
1084 	T_EXPECT_POSIX_FAILURE(getattrlistat(test_fd, "../test_dir/inside_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 20: Path can not escape outside at any point of the resolution");
1085 
1086 	/* Test Case 21: File using a symlink pointing to absolute path */
1087 	T_EXPECT_POSIX_FAILURE(getattrlistat(test_fd, "symlink_absolute/test_dir/inside_file.txt", &attrs, &attrbuf, sizeof(attrbuf), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 21: File using a symlink pointing to absolute path");
1088 
1089 	T_EXPECT_POSIX_SUCCESS(close(fd), "Closing %s", INSIDE_FILE);
1090 }
1091 
1092 T_DECL(resolve_beneath_setattrlist,
1093     "test setattrlist()/fsetattrlist()/setattrlistat() using the FSOPT_RESOLVE_BENEATH flag")
1094 {
1095 	int fd;
1096 	int flags;
1097 	struct attrlist attrlist;
1098 
1099 	T_SETUPBEGIN;
1100 
1101 	flags = 0;
1102 	memset(&attrlist, 0, sizeof(attrlist));
1103 	attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
1104 	attrlist.commonattr = ATTR_CMN_FLAGS;
1105 
1106 	T_ATEND(cleanup);
1107 	setup("resolve_beneath_setattrlist");
1108 
1109 	/* Changing current directory to the test directory */
1110 	T_ASSERT_POSIX_SUCCESS(fchdir(test_fd), "Changing directory to %s/%s", testdir, TEST_DIR);
1111 
1112 	/* Open test file */
1113 	T_ASSERT_POSIX_SUCCESS((fd = open("inside_file.txt", O_RDWR, 0777)), "Opening %s", INSIDE_FILE);
1114 
1115 	T_SETUPEND;
1116 
1117 	T_LOG("Testing the setattrlist() syscall using FSOPT_RESOLVE_BENEATH");
1118 
1119 	/* Test Case 1: File within the directory */
1120 	T_EXPECT_POSIX_SUCCESS(setattrlist("inside_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), "Test Case 1: File within the directory");
1121 
1122 	/* Test Case 2: File using a symlink pointing outside */
1123 	T_EXPECT_POSIX_FAILURE(setattrlist("symlink", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 2: File using a symlink pointing outside");
1124 
1125 	/* Test Case 3: Attempt to open a file using ".." to navigate outside */
1126 	T_EXPECT_POSIX_FAILURE(setattrlist("../outside_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 3: File using \"..\" to navigate outside");
1127 
1128 	/* Test Case 4: File within a nested directory */
1129 	T_EXPECT_POSIX_SUCCESS(setattrlist("nested/nested_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), "Test Case 4: File within a nested directory");
1130 
1131 	/* Test Case 5: Symlink to a file in a nested directory */
1132 	T_EXPECT_POSIX_SUCCESS(setattrlist("symlink_to_nested", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), "Test Case 5: Symlink to a file within the same directory");
1133 
1134 	/* Test Case 6: File using an absolute path */
1135 	T_EXPECT_POSIX_FAILURE(setattrlist("/etc/passwd", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 6: File using an absolute path");
1136 
1137 	/* Test Case 7: Valid symlink to parent directory */
1138 	T_EXPECT_POSIX_FAILURE(setattrlist("parent_symlink/outside_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 7: Valid symlink to parent directory");
1139 
1140 	/* Test Case 8: Circular symlink within directory */
1141 	T_EXPECT_POSIX_FAILURE(setattrlist("circular_symlink", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ELOOP, "Test Case 8: Circular symlink within directory");
1142 
1143 	/* Test Case 9: Path can not escape outside at any point of the resolution */
1144 	T_EXPECT_POSIX_FAILURE(setattrlist("../test_dir/inside_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 9: Path can not escape outside at any point of the resolution");
1145 
1146 	/* Test Case 10: File using a symlink pointing to absolute path */
1147 	T_EXPECT_POSIX_FAILURE(setattrlist("symlink_absolute/test_dir/inside_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 10: File using a symlink pointing to absolute path");
1148 
1149 	T_LOG("Testing the fsetattrlist() syscall using FSOPT_RESOLVE_BENEATH");
1150 
1151 	/* Test Case 11: fsetattrlist() syscall using FSOPT_RESOLVE_BENEATH */
1152 	T_EXPECT_POSIX_SUCCESS(fsetattrlist(fd, &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), "Test Case 11: fsetattrlist() syscall using FSOPT_RESOLVE_BENEATH");
1153 
1154 	T_LOG("Testing the setattrlistat() syscall using FSOPT_RESOLVE_BENEATH");
1155 
1156 	/* Test Case 12: File within the directory */
1157 	T_EXPECT_POSIX_SUCCESS(setattrlistat(test_fd, "inside_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), "Test Case 12: File within the directory");
1158 
1159 	/* Test Case 13: File using a symlink pointing outside */
1160 	T_EXPECT_POSIX_FAILURE(setattrlistat(test_fd, "symlink", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 13: File using a symlink pointing outside");
1161 
1162 	/* Test Case 14: Attempt to open a file using ".." to navigate outside */
1163 	T_EXPECT_POSIX_FAILURE(setattrlistat(test_fd, "../outside_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 14: File using \"..\" to navigate outside");
1164 
1165 	/* Test Case 15: File within a nested directory */
1166 	T_EXPECT_POSIX_SUCCESS(setattrlistat(test_fd, "nested/nested_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), "Test Case 15: File within a nested directory");
1167 
1168 	/* Test Case 16: Symlink to a file in a nested directory */
1169 	T_EXPECT_POSIX_SUCCESS(setattrlistat(test_fd, "symlink_to_nested", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), "Test Case 16: Symlink to a file within the same directory");
1170 
1171 	/* Test Case 17: File using an absolute path */
1172 	T_EXPECT_POSIX_FAILURE(setattrlistat(test_fd, "/etc/passwd", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 17: File using an absolute path");
1173 
1174 	/* Test Case 18: Valid symlink to parent directory */
1175 	T_EXPECT_POSIX_FAILURE(setattrlistat(test_fd, "parent_symlink/outside_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 18: Valid symlink to parent directory");
1176 
1177 	/* Test Case 19: Circular symlink within directory */
1178 	T_EXPECT_POSIX_FAILURE(setattrlistat(test_fd, "circular_symlink", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ELOOP, "Test Case 19: Circular symlink within directory");
1179 
1180 	/* Test Case 20: Path can not escape outside at any point of the resolution */
1181 	T_EXPECT_POSIX_FAILURE(setattrlistat(test_fd, "../test_dir/inside_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 20: Path can not escape outside at any point of the resolution");
1182 
1183 	/* Test Case 21: File using a symlink pointing to absolute path */
1184 	T_EXPECT_POSIX_FAILURE(setattrlistat(test_fd, "symlink_absolute/test_dir/inside_file.txt", &attrlist, &flags, sizeof(flags), FSOPT_RESOLVE_BENEATH), ENOTCAPABLE, "Test Case 21: File using a symlink pointing to absolute path");
1185 
1186 	T_EXPECT_POSIX_SUCCESS(close(fd), "Closing %s", INSIDE_FILE);
1187 }
1188