xref: /linux/tools/testing/selftests/landlock/fs_test.c (revision dc75f890469401816fc8c492e11885409b5efd12)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Landlock tests - Filesystem
4  *
5  * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
6  * Copyright © 2020 ANSSI
7  * Copyright © 2020-2022 Microsoft Corporation
8  */
9 
10 #define _GNU_SOURCE
11 #include <asm/termbits.h>
12 #include <fcntl.h>
13 #include <libgen.h>
14 #include <linux/fiemap.h>
15 #include <linux/landlock.h>
16 #include <linux/magic.h>
17 #include <sched.h>
18 #include <stddef.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/capability.h>
22 #include <sys/ioctl.h>
23 #include <sys/mount.h>
24 #include <sys/prctl.h>
25 #include <sys/resource.h>
26 #include <sys/sendfile.h>
27 #include <sys/socket.h>
28 #include <sys/stat.h>
29 #include <sys/sysmacros.h>
30 #include <sys/un.h>
31 #include <sys/vfs.h>
32 #include <unistd.h>
33 
34 /*
35  * Intentionally included last to work around header conflict.
36  * See https://sourceware.org/glibc/wiki/Synchronizing_Headers.
37  */
38 #include <linux/fs.h>
39 #include <linux/mount.h>
40 
41 /* Defines AT_EXECVE_CHECK without type conflicts. */
42 #define _ASM_GENERIC_FCNTL_H
43 #include <linux/fcntl.h>
44 
45 #include "audit.h"
46 #include "common.h"
47 
48 #ifndef renameat2
49 int renameat2(int olddirfd, const char *oldpath, int newdirfd,
50 	      const char *newpath, unsigned int flags)
51 {
52 	return syscall(__NR_renameat2, olddirfd, oldpath, newdirfd, newpath,
53 		       flags);
54 }
55 #endif
56 
57 #ifndef open_tree
58 int open_tree(int dfd, const char *filename, unsigned int flags)
59 {
60 	return syscall(__NR_open_tree, dfd, filename, flags);
61 }
62 #endif
63 
64 static int sys_execveat(int dirfd, const char *pathname, char *const argv[],
65 			char *const envp[], int flags)
66 {
67 	return syscall(__NR_execveat, dirfd, pathname, argv, envp, flags);
68 }
69 
70 #ifndef RENAME_EXCHANGE
71 #define RENAME_EXCHANGE (1 << 1)
72 #endif
73 
74 static const char bin_true[] = "./true";
75 
76 /* Paths (sibling number and depth) */
77 static const char dir_s1d1[] = TMP_DIR "/s1d1";
78 static const char file1_s1d1[] = TMP_DIR "/s1d1/f1";
79 static const char file2_s1d1[] = TMP_DIR "/s1d1/f2";
80 static const char dir_s1d2[] = TMP_DIR "/s1d1/s1d2";
81 static const char file1_s1d2[] = TMP_DIR "/s1d1/s1d2/f1";
82 static const char file2_s1d2[] = TMP_DIR "/s1d1/s1d2/f2";
83 static const char dir_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3";
84 static const char file1_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f1";
85 static const char file2_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f2";
86 
87 static const char dir_s2d1[] = TMP_DIR "/s2d1";
88 static const char file1_s2d1[] = TMP_DIR "/s2d1/f1";
89 static const char dir_s2d2[] = TMP_DIR "/s2d1/s2d2";
90 static const char file1_s2d2[] = TMP_DIR "/s2d1/s2d2/f1";
91 static const char dir_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3";
92 static const char file1_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f1";
93 static const char file2_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f2";
94 
95 static const char dir_s3d1[] = TMP_DIR "/s3d1";
96 static const char file1_s3d1[] = TMP_DIR "/s3d1/f1";
97 /* dir_s3d2 is a mount point. */
98 static const char dir_s3d2[] = TMP_DIR "/s3d1/s3d2";
99 static const char dir_s3d3[] = TMP_DIR "/s3d1/s3d2/s3d3";
100 static const char file1_s3d3[] = TMP_DIR "/s3d1/s3d2/s3d3/f1";
101 static const char dir_s3d4[] = TMP_DIR "/s3d1/s3d2/s3d4";
102 static const char file1_s3d4[] = TMP_DIR "/s3d1/s3d2/s3d4/f1";
103 
104 /*
105  * layout1 hierarchy:
106  *
107  * tmp
108  * ├── s1d1
109  * │   ├── f1
110  * │   ├── f2
111  * │   └── s1d2
112  * │       ├── f1
113  * │       ├── f2
114  * │       └── s1d3
115  * │           ├── f1
116  * │           └── f2
117  * ├── s2d1
118  * │   ├── f1
119  * │   └── s2d2
120  * │       ├── f1
121  * │       └── s2d3
122  * │           ├── f1
123  * │           └── f2
124  * └── s3d1
125  *     ├── f1
126  *     └── s3d2 [mount point]
127  *         ├── s3d3
128  *         │   └── f1
129  *         └── s3d4
130  *             └── f1
131  */
132 
133 static bool fgrep(FILE *const inf, const char *const str)
134 {
135 	char line[32];
136 	const int slen = strlen(str);
137 
138 	while (!feof(inf)) {
139 		if (!fgets(line, sizeof(line), inf))
140 			break;
141 		if (strncmp(line, str, slen))
142 			continue;
143 
144 		return true;
145 	}
146 
147 	return false;
148 }
149 
150 static bool supports_filesystem(const char *const filesystem)
151 {
152 	char str[32];
153 	int len;
154 	bool res = true;
155 	FILE *const inf = fopen("/proc/filesystems", "r");
156 
157 	/*
158 	 * Consider that the filesystem is supported if we cannot get the
159 	 * supported ones.
160 	 */
161 	if (!inf)
162 		return true;
163 
164 	/* filesystem can be null for bind mounts. */
165 	if (!filesystem)
166 		goto out;
167 
168 	len = snprintf(str, sizeof(str), "nodev\t%s\n", filesystem);
169 	if (len >= sizeof(str))
170 		/* Ignores too-long filesystem names. */
171 		goto out;
172 
173 	res = fgrep(inf, str);
174 
175 out:
176 	fclose(inf);
177 	return res;
178 }
179 
180 static bool cwd_matches_fs(unsigned int fs_magic)
181 {
182 	struct statfs statfs_buf;
183 
184 	if (!fs_magic)
185 		return true;
186 
187 	if (statfs(".", &statfs_buf))
188 		return true;
189 
190 	return statfs_buf.f_type == fs_magic;
191 }
192 
193 static void mkdir_parents(struct __test_metadata *const _metadata,
194 			  const char *const path)
195 {
196 	char *walker;
197 	const char *parent;
198 	int i, err;
199 
200 	ASSERT_NE(path[0], '\0');
201 	walker = strdup(path);
202 	ASSERT_NE(NULL, walker);
203 	parent = walker;
204 	for (i = 1; walker[i]; i++) {
205 		if (walker[i] != '/')
206 			continue;
207 		walker[i] = '\0';
208 		err = mkdir(parent, 0700);
209 		ASSERT_FALSE(err && errno != EEXIST)
210 		{
211 			TH_LOG("Failed to create directory \"%s\": %s", parent,
212 			       strerror(errno));
213 		}
214 		walker[i] = '/';
215 	}
216 	free(walker);
217 }
218 
219 static void create_directory(struct __test_metadata *const _metadata,
220 			     const char *const path)
221 {
222 	mkdir_parents(_metadata, path);
223 	ASSERT_EQ(0, mkdir(path, 0700))
224 	{
225 		TH_LOG("Failed to create directory \"%s\": %s", path,
226 		       strerror(errno));
227 	}
228 }
229 
230 static void create_file(struct __test_metadata *const _metadata,
231 			const char *const path)
232 {
233 	mkdir_parents(_metadata, path);
234 	ASSERT_EQ(0, mknod(path, S_IFREG | 0700, 0))
235 	{
236 		TH_LOG("Failed to create file \"%s\": %s", path,
237 		       strerror(errno));
238 	}
239 }
240 
241 static int remove_path(const char *const path)
242 {
243 	char *walker;
244 	int i, ret, err = 0;
245 
246 	walker = strdup(path);
247 	if (!walker) {
248 		err = ENOMEM;
249 		goto out;
250 	}
251 	if (unlink(path) && rmdir(path)) {
252 		if (errno != ENOENT && errno != ENOTDIR)
253 			err = errno;
254 		goto out;
255 	}
256 	for (i = strlen(walker); i > 0; i--) {
257 		if (walker[i] != '/')
258 			continue;
259 		walker[i] = '\0';
260 		ret = rmdir(walker);
261 		if (ret) {
262 			if (errno != ENOTEMPTY && errno != EBUSY)
263 				err = errno;
264 			goto out;
265 		}
266 		if (strcmp(walker, TMP_DIR) == 0)
267 			goto out;
268 	}
269 
270 out:
271 	free(walker);
272 	return err;
273 }
274 
275 struct mnt_opt {
276 	const char *const source;
277 	const char *const type;
278 	const unsigned long flags;
279 	const char *const data;
280 };
281 
282 #define MNT_TMP_DATA "size=4m,mode=700"
283 
284 static const struct mnt_opt mnt_tmp = {
285 	.type = "tmpfs",
286 	.data = MNT_TMP_DATA,
287 };
288 
289 static int mount_opt(const struct mnt_opt *const mnt, const char *const target)
290 {
291 	return mount(mnt->source ?: mnt->type, target, mnt->type, mnt->flags,
292 		     mnt->data);
293 }
294 
295 static void prepare_layout_opt(struct __test_metadata *const _metadata,
296 			       const struct mnt_opt *const mnt)
297 {
298 	disable_caps(_metadata);
299 	umask(0077);
300 	create_directory(_metadata, TMP_DIR);
301 
302 	/*
303 	 * Do not pollute the rest of the system: creates a private mount point
304 	 * for tests relying on pivot_root(2) and move_mount(2).
305 	 */
306 	set_cap(_metadata, CAP_SYS_ADMIN);
307 	ASSERT_EQ(0, unshare(CLONE_NEWNS | CLONE_NEWCGROUP));
308 	ASSERT_EQ(0, mount_opt(mnt, TMP_DIR))
309 	{
310 		TH_LOG("Failed to mount the %s filesystem: %s", mnt->type,
311 		       strerror(errno));
312 		/*
313 		 * FIXTURE_TEARDOWN() is not called when FIXTURE_SETUP()
314 		 * failed, so we need to explicitly do a minimal cleanup to
315 		 * avoid cascading errors with other tests that don't depend on
316 		 * the same filesystem.
317 		 */
318 		remove_path(TMP_DIR);
319 	}
320 	ASSERT_EQ(0, mount(NULL, TMP_DIR, NULL, MS_PRIVATE | MS_REC, NULL));
321 	clear_cap(_metadata, CAP_SYS_ADMIN);
322 }
323 
324 static void prepare_layout(struct __test_metadata *const _metadata)
325 {
326 	prepare_layout_opt(_metadata, &mnt_tmp);
327 }
328 
329 static void cleanup_layout(struct __test_metadata *const _metadata)
330 {
331 	set_cap(_metadata, CAP_SYS_ADMIN);
332 	if (umount(TMP_DIR)) {
333 		/*
334 		 * According to the test environment, the mount point of the
335 		 * current directory may be shared or not, which changes the
336 		 * visibility of the nested TMP_DIR mount point for the test's
337 		 * parent process doing this cleanup.
338 		 */
339 		ASSERT_EQ(EINVAL, errno);
340 	}
341 	clear_cap(_metadata, CAP_SYS_ADMIN);
342 	EXPECT_EQ(0, remove_path(TMP_DIR));
343 }
344 
345 /* clang-format off */
346 FIXTURE(layout0) {};
347 /* clang-format on */
348 
349 FIXTURE_SETUP(layout0)
350 {
351 	prepare_layout(_metadata);
352 }
353 
354 FIXTURE_TEARDOWN_PARENT(layout0)
355 {
356 	cleanup_layout(_metadata);
357 }
358 
359 static void create_layout1(struct __test_metadata *const _metadata)
360 {
361 	create_file(_metadata, file1_s1d1);
362 	create_file(_metadata, file1_s1d2);
363 	create_file(_metadata, file1_s1d3);
364 	create_file(_metadata, file2_s1d1);
365 	create_file(_metadata, file2_s1d2);
366 	create_file(_metadata, file2_s1d3);
367 
368 	create_file(_metadata, file1_s2d1);
369 	create_file(_metadata, file1_s2d2);
370 	create_file(_metadata, file1_s2d3);
371 	create_file(_metadata, file2_s2d3);
372 
373 	create_file(_metadata, file1_s3d1);
374 	create_directory(_metadata, dir_s3d2);
375 	set_cap(_metadata, CAP_SYS_ADMIN);
376 	ASSERT_EQ(0, mount_opt(&mnt_tmp, dir_s3d2));
377 	clear_cap(_metadata, CAP_SYS_ADMIN);
378 
379 	create_file(_metadata, file1_s3d3);
380 	create_file(_metadata, file1_s3d4);
381 }
382 
383 static void remove_layout1(struct __test_metadata *const _metadata)
384 {
385 	EXPECT_EQ(0, remove_path(file2_s1d3));
386 	EXPECT_EQ(0, remove_path(file2_s1d2));
387 	EXPECT_EQ(0, remove_path(file2_s1d1));
388 	EXPECT_EQ(0, remove_path(file1_s1d3));
389 	EXPECT_EQ(0, remove_path(file1_s1d2));
390 	EXPECT_EQ(0, remove_path(file1_s1d1));
391 	EXPECT_EQ(0, remove_path(dir_s1d3));
392 
393 	EXPECT_EQ(0, remove_path(file2_s2d3));
394 	EXPECT_EQ(0, remove_path(file1_s2d3));
395 	EXPECT_EQ(0, remove_path(file1_s2d2));
396 	EXPECT_EQ(0, remove_path(file1_s2d1));
397 	EXPECT_EQ(0, remove_path(dir_s2d2));
398 
399 	EXPECT_EQ(0, remove_path(file1_s3d1));
400 	EXPECT_EQ(0, remove_path(file1_s3d3));
401 	EXPECT_EQ(0, remove_path(file1_s3d4));
402 	set_cap(_metadata, CAP_SYS_ADMIN);
403 	umount(dir_s3d2);
404 	clear_cap(_metadata, CAP_SYS_ADMIN);
405 	EXPECT_EQ(0, remove_path(dir_s3d2));
406 }
407 
408 /* clang-format off */
409 FIXTURE(layout1) {};
410 /* clang-format on */
411 
412 FIXTURE_SETUP(layout1)
413 {
414 	prepare_layout(_metadata);
415 
416 	create_layout1(_metadata);
417 }
418 
419 FIXTURE_TEARDOWN_PARENT(layout1)
420 {
421 	remove_layout1(_metadata);
422 
423 	cleanup_layout(_metadata);
424 }
425 
426 /*
427  * This helper enables to use the ASSERT_* macros and print the line number
428  * pointing to the test caller.
429  */
430 static int test_open_rel(const int dirfd, const char *const path,
431 			 const int flags)
432 {
433 	int fd;
434 
435 	/* Works with file and directories. */
436 	fd = openat(dirfd, path, flags | O_CLOEXEC);
437 	if (fd < 0)
438 		return errno;
439 	/*
440 	 * Mixing error codes from close(2) and open(2) should not lead to any
441 	 * (access type) confusion for this test.
442 	 */
443 	if (close(fd) != 0)
444 		return errno;
445 	return 0;
446 }
447 
448 static int test_open(const char *const path, const int flags)
449 {
450 	return test_open_rel(AT_FDCWD, path, flags);
451 }
452 
453 TEST_F_FORK(layout1, no_restriction)
454 {
455 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
456 	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
457 	ASSERT_EQ(0, test_open(file2_s1d1, O_RDONLY));
458 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
459 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
460 	ASSERT_EQ(0, test_open(file2_s1d2, O_RDONLY));
461 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
462 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
463 
464 	ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
465 	ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
466 	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
467 	ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
468 	ASSERT_EQ(0, test_open(dir_s2d3, O_RDONLY));
469 	ASSERT_EQ(0, test_open(file1_s2d3, O_RDONLY));
470 
471 	ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
472 	ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
473 	ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
474 }
475 
476 TEST_F_FORK(layout1, inval)
477 {
478 	struct landlock_path_beneath_attr path_beneath = {
479 		.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
480 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
481 		.parent_fd = -1,
482 	};
483 	struct landlock_ruleset_attr ruleset_attr = {
484 		.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |
485 				     LANDLOCK_ACCESS_FS_WRITE_FILE,
486 	};
487 	int ruleset_fd;
488 
489 	path_beneath.parent_fd =
490 		open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
491 	ASSERT_LE(0, path_beneath.parent_fd);
492 
493 	ruleset_fd = open(dir_s1d1, O_PATH | O_DIRECTORY | O_CLOEXEC);
494 	ASSERT_LE(0, ruleset_fd);
495 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
496 					&path_beneath, 0));
497 	/* Returns EBADF because ruleset_fd is not a landlock-ruleset FD. */
498 	ASSERT_EQ(EBADF, errno);
499 	ASSERT_EQ(0, close(ruleset_fd));
500 
501 	ruleset_fd = open(dir_s1d1, O_DIRECTORY | O_CLOEXEC);
502 	ASSERT_LE(0, ruleset_fd);
503 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
504 					&path_beneath, 0));
505 	/* Returns EBADFD because ruleset_fd is not a valid ruleset. */
506 	ASSERT_EQ(EBADFD, errno);
507 	ASSERT_EQ(0, close(ruleset_fd));
508 
509 	/* Gets a real ruleset. */
510 	ruleset_fd =
511 		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
512 	ASSERT_LE(0, ruleset_fd);
513 	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
514 				       &path_beneath, 0));
515 	ASSERT_EQ(0, close(path_beneath.parent_fd));
516 
517 	/* Tests without O_PATH. */
518 	path_beneath.parent_fd = open(dir_s1d2, O_DIRECTORY | O_CLOEXEC);
519 	ASSERT_LE(0, path_beneath.parent_fd);
520 	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
521 				       &path_beneath, 0));
522 	ASSERT_EQ(0, close(path_beneath.parent_fd));
523 
524 	/* Tests with a ruleset FD. */
525 	path_beneath.parent_fd = ruleset_fd;
526 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
527 					&path_beneath, 0));
528 	ASSERT_EQ(EBADFD, errno);
529 
530 	/* Checks unhandled allowed_access. */
531 	path_beneath.parent_fd =
532 		open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
533 	ASSERT_LE(0, path_beneath.parent_fd);
534 
535 	/* Test with legitimate values. */
536 	path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_EXECUTE;
537 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
538 					&path_beneath, 0));
539 	ASSERT_EQ(EINVAL, errno);
540 	path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_EXECUTE;
541 
542 	/* Tests with denied-by-default access right. */
543 	path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_REFER;
544 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
545 					&path_beneath, 0));
546 	ASSERT_EQ(EINVAL, errno);
547 	path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_REFER;
548 
549 	/* Test with unknown (64-bits) value. */
550 	path_beneath.allowed_access |= (1ULL << 60);
551 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
552 					&path_beneath, 0));
553 	ASSERT_EQ(EINVAL, errno);
554 	path_beneath.allowed_access &= ~(1ULL << 60);
555 
556 	/* Test with no access. */
557 	path_beneath.allowed_access = 0;
558 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
559 					&path_beneath, 0));
560 	ASSERT_EQ(ENOMSG, errno);
561 	path_beneath.allowed_access &= ~(1ULL << 60);
562 
563 	ASSERT_EQ(0, close(path_beneath.parent_fd));
564 
565 	/* Enforces the ruleset. */
566 	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
567 	ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
568 
569 	ASSERT_EQ(0, close(ruleset_fd));
570 }
571 
572 /* clang-format off */
573 
574 #define ACCESS_FILE ( \
575 	LANDLOCK_ACCESS_FS_EXECUTE | \
576 	LANDLOCK_ACCESS_FS_WRITE_FILE | \
577 	LANDLOCK_ACCESS_FS_READ_FILE | \
578 	LANDLOCK_ACCESS_FS_TRUNCATE | \
579 	LANDLOCK_ACCESS_FS_IOCTL_DEV | \
580 	LANDLOCK_ACCESS_FS_RESOLVE_UNIX)
581 
582 #define ACCESS_LAST LANDLOCK_ACCESS_FS_RESOLVE_UNIX
583 
584 #define ACCESS_ALL ( \
585 	ACCESS_FILE | \
586 	LANDLOCK_ACCESS_FS_READ_DIR | \
587 	LANDLOCK_ACCESS_FS_REMOVE_DIR | \
588 	LANDLOCK_ACCESS_FS_REMOVE_FILE | \
589 	LANDLOCK_ACCESS_FS_MAKE_CHAR | \
590 	LANDLOCK_ACCESS_FS_MAKE_DIR | \
591 	LANDLOCK_ACCESS_FS_MAKE_REG | \
592 	LANDLOCK_ACCESS_FS_MAKE_SOCK | \
593 	LANDLOCK_ACCESS_FS_MAKE_FIFO | \
594 	LANDLOCK_ACCESS_FS_MAKE_BLOCK | \
595 	LANDLOCK_ACCESS_FS_MAKE_SYM | \
596 	LANDLOCK_ACCESS_FS_REFER)
597 
598 /* clang-format on */
599 
600 TEST_F_FORK(layout1, file_and_dir_access_rights)
601 {
602 	__u64 access;
603 	int err;
604 	struct landlock_path_beneath_attr path_beneath_file = {},
605 					  path_beneath_dir = {};
606 	struct landlock_ruleset_attr ruleset_attr = {
607 		.handled_access_fs = ACCESS_ALL,
608 	};
609 	const int ruleset_fd =
610 		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
611 
612 	ASSERT_LE(0, ruleset_fd);
613 
614 	/* Tests access rights for files. */
615 	path_beneath_file.parent_fd = open(file1_s1d2, O_PATH | O_CLOEXEC);
616 	ASSERT_LE(0, path_beneath_file.parent_fd);
617 
618 	/* Tests access rights for directories. */
619 	path_beneath_dir.parent_fd =
620 		open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
621 	ASSERT_LE(0, path_beneath_dir.parent_fd);
622 
623 	for (access = 1; access <= ACCESS_LAST; access <<= 1) {
624 		path_beneath_dir.allowed_access = access;
625 		ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
626 					       LANDLOCK_RULE_PATH_BENEATH,
627 					       &path_beneath_dir, 0));
628 
629 		path_beneath_file.allowed_access = access;
630 		err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
631 					&path_beneath_file, 0);
632 		if (access & ACCESS_FILE) {
633 			ASSERT_EQ(0, err);
634 		} else {
635 			ASSERT_EQ(-1, err);
636 			ASSERT_EQ(EINVAL, errno);
637 		}
638 	}
639 	ASSERT_EQ(0, close(path_beneath_file.parent_fd));
640 	ASSERT_EQ(0, close(path_beneath_dir.parent_fd));
641 	ASSERT_EQ(0, close(ruleset_fd));
642 }
643 
644 TEST_F_FORK(layout0, ruleset_with_unknown_access)
645 {
646 	__u64 access_mask;
647 
648 	for (access_mask = 1ULL << 63; access_mask != ACCESS_LAST;
649 	     access_mask >>= 1) {
650 		struct landlock_ruleset_attr ruleset_attr = {
651 			.handled_access_fs = access_mask,
652 		};
653 
654 		ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
655 						      sizeof(ruleset_attr), 0));
656 		ASSERT_EQ(EINVAL, errno);
657 	}
658 }
659 
660 TEST_F_FORK(layout0, rule_with_unknown_access)
661 {
662 	__u64 access;
663 	struct landlock_path_beneath_attr path_beneath = {};
664 	const struct landlock_ruleset_attr ruleset_attr = {
665 		.handled_access_fs = ACCESS_ALL,
666 	};
667 	const int ruleset_fd =
668 		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
669 
670 	ASSERT_LE(0, ruleset_fd);
671 
672 	path_beneath.parent_fd =
673 		open(TMP_DIR, O_PATH | O_DIRECTORY | O_CLOEXEC);
674 	ASSERT_LE(0, path_beneath.parent_fd);
675 
676 	for (access = 1ULL << 63; access != ACCESS_LAST; access >>= 1) {
677 		path_beneath.allowed_access = access;
678 		EXPECT_EQ(-1, landlock_add_rule(ruleset_fd,
679 						LANDLOCK_RULE_PATH_BENEATH,
680 						&path_beneath, 0));
681 		EXPECT_EQ(EINVAL, errno);
682 	}
683 	ASSERT_EQ(0, close(path_beneath.parent_fd));
684 	ASSERT_EQ(0, close(ruleset_fd));
685 }
686 
687 TEST_F_FORK(layout1, rule_with_unhandled_access)
688 {
689 	struct landlock_ruleset_attr ruleset_attr = {
690 		.handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
691 	};
692 	struct landlock_path_beneath_attr path_beneath = {};
693 	int ruleset_fd;
694 	__u64 access;
695 
696 	ruleset_fd =
697 		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
698 	ASSERT_LE(0, ruleset_fd);
699 
700 	path_beneath.parent_fd = open(file1_s1d2, O_PATH | O_CLOEXEC);
701 	ASSERT_LE(0, path_beneath.parent_fd);
702 
703 	for (access = 1; access > 0; access <<= 1) {
704 		int err;
705 
706 		path_beneath.allowed_access = access;
707 		err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
708 					&path_beneath, 0);
709 		if (access == ruleset_attr.handled_access_fs) {
710 			EXPECT_EQ(0, err);
711 		} else {
712 			EXPECT_EQ(-1, err);
713 			EXPECT_EQ(EINVAL, errno);
714 		}
715 	}
716 
717 	EXPECT_EQ(0, close(path_beneath.parent_fd));
718 	EXPECT_EQ(0, close(ruleset_fd));
719 }
720 
721 static void add_path_beneath(struct __test_metadata *const _metadata,
722 			     const int ruleset_fd, const __u64 allowed_access,
723 			     const char *const path)
724 {
725 	struct landlock_path_beneath_attr path_beneath = {
726 		.allowed_access = allowed_access,
727 	};
728 
729 	path_beneath.parent_fd = open(path, O_PATH | O_CLOEXEC);
730 	ASSERT_LE(0, path_beneath.parent_fd)
731 	{
732 		TH_LOG("Failed to open directory \"%s\": %s", path,
733 		       strerror(errno));
734 	}
735 	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
736 				       &path_beneath, 0))
737 	{
738 		TH_LOG("Failed to update the ruleset with \"%s\": %s", path,
739 		       strerror(errno));
740 	}
741 	ASSERT_EQ(0, close(path_beneath.parent_fd));
742 }
743 
744 struct rule {
745 	const char *path;
746 	__u64 access;
747 };
748 
749 /* clang-format off */
750 
751 #define ACCESS_RO ( \
752 	LANDLOCK_ACCESS_FS_READ_FILE | \
753 	LANDLOCK_ACCESS_FS_READ_DIR)
754 
755 #define ACCESS_RW ( \
756 	ACCESS_RO | \
757 	LANDLOCK_ACCESS_FS_WRITE_FILE)
758 
759 /* clang-format on */
760 
761 static int create_ruleset(struct __test_metadata *const _metadata,
762 			  const __u64 handled_access_fs,
763 			  const struct rule rules[])
764 {
765 	int ruleset_fd, i;
766 	struct landlock_ruleset_attr ruleset_attr = {
767 		.handled_access_fs = handled_access_fs,
768 	};
769 
770 	ruleset_fd =
771 		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
772 	ASSERT_LE(0, ruleset_fd)
773 	{
774 		TH_LOG("Failed to create a ruleset: %s", strerror(errno));
775 	}
776 
777 	if (rules)
778 		for (i = 0; rules[i].path; i++) {
779 			if (!rules[i].access)
780 				continue;
781 
782 			add_path_beneath(_metadata, ruleset_fd, rules[i].access,
783 					 rules[i].path);
784 		}
785 	return ruleset_fd;
786 }
787 
788 static void enforce_fs(struct __test_metadata *const _metadata,
789 		       const __u64 access_fs, const struct rule rules[])
790 {
791 	const int ruleset_fd = create_ruleset(_metadata, access_fs, rules);
792 
793 	enforce_ruleset(_metadata, ruleset_fd);
794 	EXPECT_EQ(0, close(ruleset_fd));
795 }
796 
797 TEST_F_FORK(layout0, proc_nsfs)
798 {
799 	const struct rule rules[] = {
800 		{
801 			.path = "/dev/null",
802 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
803 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
804 		},
805 		{},
806 	};
807 	struct landlock_path_beneath_attr path_beneath;
808 	const int ruleset_fd = create_ruleset(
809 		_metadata, rules[0].access | LANDLOCK_ACCESS_FS_READ_DIR,
810 		rules);
811 
812 	ASSERT_LE(0, ruleset_fd);
813 	ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
814 
815 	enforce_ruleset(_metadata, ruleset_fd);
816 
817 	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
818 	ASSERT_EQ(EACCES, test_open("/dev", O_RDONLY));
819 	ASSERT_EQ(0, test_open("/dev/null", O_RDONLY));
820 	ASSERT_EQ(EACCES, test_open("/dev/full", O_RDONLY));
821 
822 	ASSERT_EQ(EACCES, test_open("/proc", O_RDONLY));
823 	ASSERT_EQ(EACCES, test_open("/proc/self", O_RDONLY));
824 	ASSERT_EQ(EACCES, test_open("/proc/self/ns", O_RDONLY));
825 	/*
826 	 * Because nsfs is an internal filesystem, /proc/self/ns/mnt is a
827 	 * disconnected path.  Such path cannot be identified and must then be
828 	 * allowed.
829 	 */
830 	ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
831 
832 	/*
833 	 * Checks that it is not possible to add nsfs-like filesystem
834 	 * references to a ruleset.
835 	 */
836 	path_beneath.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
837 				      LANDLOCK_ACCESS_FS_WRITE_FILE,
838 	path_beneath.parent_fd = open("/proc/self/ns/mnt", O_PATH | O_CLOEXEC);
839 	ASSERT_LE(0, path_beneath.parent_fd);
840 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
841 					&path_beneath, 0));
842 	ASSERT_EQ(EBADFD, errno);
843 	ASSERT_EQ(0, close(path_beneath.parent_fd));
844 }
845 
846 TEST_F_FORK(layout0, unpriv)
847 {
848 	const struct rule rules[] = {
849 		{
850 			.path = TMP_DIR,
851 			.access = ACCESS_RO,
852 		},
853 		{},
854 	};
855 	int ruleset_fd;
856 
857 	drop_caps(_metadata);
858 
859 	ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
860 	ASSERT_LE(0, ruleset_fd);
861 	ASSERT_EQ(-1, landlock_restrict_self(ruleset_fd, 0));
862 	ASSERT_EQ(EPERM, errno);
863 
864 	/* enforce_ruleset() calls prctl(no_new_privs). */
865 	enforce_ruleset(_metadata, ruleset_fd);
866 	ASSERT_EQ(0, close(ruleset_fd));
867 }
868 
869 TEST_F_FORK(layout1, effective_access)
870 {
871 	const struct rule rules[] = {
872 		{
873 			.path = dir_s1d2,
874 			.access = ACCESS_RO,
875 		},
876 		{
877 			.path = file1_s2d2,
878 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
879 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
880 		},
881 		{},
882 	};
883 	char buf;
884 	int reg_fd;
885 
886 	enforce_fs(_metadata, ACCESS_RW, rules);
887 
888 	/* Tests on a directory (with or without O_PATH). */
889 	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
890 	ASSERT_EQ(0, test_open("/", O_RDONLY | O_PATH));
891 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
892 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_PATH));
893 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
894 	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY | O_PATH));
895 
896 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
897 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
898 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
899 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
900 
901 	/* Tests on a file (with or without O_PATH). */
902 	ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY));
903 	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_PATH));
904 
905 	ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
906 
907 	/* Checks effective read and write actions. */
908 	reg_fd = open(file1_s2d2, O_RDWR | O_CLOEXEC);
909 	ASSERT_LE(0, reg_fd);
910 	ASSERT_EQ(1, write(reg_fd, ".", 1));
911 	ASSERT_LE(0, lseek(reg_fd, 0, SEEK_SET));
912 	ASSERT_EQ(1, read(reg_fd, &buf, 1));
913 	ASSERT_EQ('.', buf);
914 	ASSERT_EQ(0, close(reg_fd));
915 
916 	/* Just in case, double-checks effective actions. */
917 	reg_fd = open(file1_s2d2, O_RDONLY | O_CLOEXEC);
918 	ASSERT_LE(0, reg_fd);
919 	ASSERT_EQ(-1, write(reg_fd, &buf, 1));
920 	ASSERT_EQ(EBADF, errno);
921 	ASSERT_EQ(0, close(reg_fd));
922 }
923 
924 TEST_F_FORK(layout1, unhandled_access)
925 {
926 	const struct rule rules[] = {
927 		{
928 			.path = dir_s1d2,
929 			.access = ACCESS_RO,
930 		},
931 		{},
932 	};
933 
934 	/* Here, we only handle read accesses, not write accesses. */
935 	enforce_fs(_metadata, ACCESS_RO, rules);
936 
937 	/*
938 	 * Because the policy does not handle LANDLOCK_ACCESS_FS_WRITE_FILE,
939 	 * opening for write-only should be allowed, but not read-write.
940 	 */
941 	ASSERT_EQ(0, test_open(file1_s1d1, O_WRONLY));
942 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
943 
944 	ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
945 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
946 }
947 
948 TEST_F_FORK(layout1, ruleset_overlap)
949 {
950 	const struct rule rules[] = {
951 		/* These rules should be ORed among them. */
952 		{
953 			.path = dir_s1d2,
954 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
955 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
956 		},
957 		{
958 			.path = dir_s1d2,
959 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
960 				  LANDLOCK_ACCESS_FS_READ_DIR,
961 		},
962 		{},
963 	};
964 
965 	enforce_fs(_metadata, ACCESS_RW, rules);
966 
967 	/* Checks s1d1 hierarchy. */
968 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
969 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
970 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
971 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
972 
973 	/* Checks s1d2 hierarchy. */
974 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
975 	ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
976 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
977 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
978 
979 	/* Checks s1d3 hierarchy. */
980 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
981 	ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
982 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
983 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
984 }
985 
986 TEST_F_FORK(layout1, layer_rule_unions)
987 {
988 	const struct rule layer1[] = {
989 		{
990 			.path = dir_s1d2,
991 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
992 		},
993 		/* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
994 		{
995 			.path = dir_s1d3,
996 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
997 		},
998 		{},
999 	};
1000 	const struct rule layer2[] = {
1001 		/* Doesn't change anything from layer1. */
1002 		{
1003 			.path = dir_s1d2,
1004 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
1005 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
1006 		},
1007 		{},
1008 	};
1009 	const struct rule layer3[] = {
1010 		/* Only allows write (but not read) to dir_s1d3. */
1011 		{
1012 			.path = dir_s1d2,
1013 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
1014 		},
1015 		{},
1016 	};
1017 
1018 	enforce_fs(_metadata, ACCESS_RW, layer1);
1019 
1020 	/* Checks s1d1 hierarchy with layer1. */
1021 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1022 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1023 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
1024 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1025 
1026 	/* Checks s1d2 hierarchy with layer1. */
1027 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
1028 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1029 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
1030 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1031 
1032 	/* Checks s1d3 hierarchy with layer1. */
1033 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1034 	ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
1035 	/* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
1036 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1037 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1038 
1039 	/* Doesn't change anything from layer1. */
1040 	enforce_fs(_metadata, ACCESS_RW, layer2);
1041 
1042 	/* Checks s1d1 hierarchy with layer2. */
1043 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1044 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1045 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
1046 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1047 
1048 	/* Checks s1d2 hierarchy with layer2. */
1049 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
1050 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1051 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
1052 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1053 
1054 	/* Checks s1d3 hierarchy with layer2. */
1055 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1056 	ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
1057 	/* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
1058 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1059 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1060 
1061 	/* Only allows write (but not read) to dir_s1d3. */
1062 	enforce_fs(_metadata, ACCESS_RW, layer3);
1063 
1064 	/* Checks s1d1 hierarchy with layer3. */
1065 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1066 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1067 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
1068 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1069 
1070 	/* Checks s1d2 hierarchy with layer3. */
1071 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDONLY));
1072 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1073 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
1074 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1075 
1076 	/* Checks s1d3 hierarchy with layer3. */
1077 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
1078 	ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
1079 	/* dir_s1d3 should now deny READ_FILE and WRITE_FILE (O_RDWR). */
1080 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDWR));
1081 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1082 }
1083 
1084 TEST_F_FORK(layout1, non_overlapping_accesses)
1085 {
1086 	const struct rule layer1[] = {
1087 		{
1088 			.path = dir_s1d2,
1089 			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
1090 		},
1091 		{},
1092 	};
1093 	const struct rule layer2[] = {
1094 		{
1095 			.path = dir_s1d3,
1096 			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1097 		},
1098 		{},
1099 	};
1100 
1101 	ASSERT_EQ(0, unlink(file1_s1d1));
1102 	ASSERT_EQ(0, unlink(file1_s1d2));
1103 
1104 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, layer1);
1105 
1106 	ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
1107 	ASSERT_EQ(EACCES, errno);
1108 	ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
1109 	ASSERT_EQ(0, unlink(file1_s1d2));
1110 
1111 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_REMOVE_FILE, layer2);
1112 
1113 	/* Unchanged accesses for file creation. */
1114 	ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
1115 	ASSERT_EQ(EACCES, errno);
1116 	ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
1117 
1118 	/* Checks file removing. */
1119 	ASSERT_EQ(-1, unlink(file1_s1d2));
1120 	ASSERT_EQ(EACCES, errno);
1121 	ASSERT_EQ(0, unlink(file1_s1d3));
1122 }
1123 
1124 TEST_F_FORK(layout1, interleaved_masked_accesses)
1125 {
1126 	/*
1127 	 * Checks overly restrictive rules:
1128 	 * layer 1: allows R   s1d1/s1d2/s1d3/file1
1129 	 * layer 2: allows RW  s1d1/s1d2/s1d3
1130 	 *          allows  W  s1d1/s1d2
1131 	 *          denies R   s1d1/s1d2
1132 	 * layer 3: allows R   s1d1
1133 	 * layer 4: allows R   s1d1/s1d2
1134 	 *          denies  W  s1d1/s1d2
1135 	 * layer 5: allows R   s1d1/s1d2
1136 	 * layer 6: allows   X ----
1137 	 * layer 7: allows  W  s1d1/s1d2
1138 	 *          denies R   s1d1/s1d2
1139 	 */
1140 	const struct rule layer1_read[] = {
1141 		/* Allows read access to file1_s1d3 with the first layer. */
1142 		{
1143 			.path = file1_s1d3,
1144 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1145 		},
1146 		{},
1147 	};
1148 	/* First rule with write restrictions. */
1149 	const struct rule layer2_read_write[] = {
1150 		/* Start by granting read-write access via its parent directory... */
1151 		{
1152 			.path = dir_s1d3,
1153 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
1154 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
1155 		},
1156 		/* ...but also denies read access via its grandparent directory. */
1157 		{
1158 			.path = dir_s1d2,
1159 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
1160 		},
1161 		{},
1162 	};
1163 	const struct rule layer3_read[] = {
1164 		/* Allows read access via its great-grandparent directory. */
1165 		{
1166 			.path = dir_s1d1,
1167 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1168 		},
1169 		{},
1170 	};
1171 	const struct rule layer4_read_write[] = {
1172 		/*
1173 		 * Try to confuse the deny access by denying write (but not
1174 		 * read) access via its grandparent directory.
1175 		 */
1176 		{
1177 			.path = dir_s1d2,
1178 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1179 		},
1180 		{},
1181 	};
1182 	const struct rule layer5_read[] = {
1183 		/*
1184 		 * Try to override layer2's deny read access by explicitly
1185 		 * allowing read access via file1_s1d3's grandparent.
1186 		 */
1187 		{
1188 			.path = dir_s1d2,
1189 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1190 		},
1191 		{},
1192 	};
1193 	const struct rule layer6_execute[] = {
1194 		/*
1195 		 * Restricts an unrelated file hierarchy with a new access
1196 		 * (non-overlapping) type.
1197 		 */
1198 		{
1199 			.path = dir_s2d1,
1200 			.access = LANDLOCK_ACCESS_FS_EXECUTE,
1201 		},
1202 		{},
1203 	};
1204 	const struct rule layer7_read_write[] = {
1205 		/*
1206 		 * Finally, denies read access to file1_s1d3 via its
1207 		 * grandparent.
1208 		 */
1209 		{
1210 			.path = dir_s1d2,
1211 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
1212 		},
1213 		{},
1214 	};
1215 
1216 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_READ_FILE, layer1_read);
1217 
1218 	/* Checks that read access is granted for file1_s1d3 with layer 1. */
1219 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1220 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1221 	ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
1222 
1223 	enforce_fs(_metadata,
1224 		   LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE,
1225 		   layer2_read_write);
1226 
1227 	/* Checks that previous access rights are unchanged with layer 2. */
1228 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1229 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1230 	ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
1231 
1232 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_READ_FILE, layer3_read);
1233 
1234 	/* Checks that previous access rights are unchanged with layer 3. */
1235 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1236 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1237 	ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
1238 
1239 	/* This time, denies write access for the file hierarchy. */
1240 	enforce_fs(_metadata,
1241 		   LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE,
1242 		   layer4_read_write);
1243 
1244 	/*
1245 	 * Checks that the only change with layer 4 is that write access is
1246 	 * denied.
1247 	 */
1248 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1249 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1250 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1251 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1252 
1253 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_READ_FILE, layer5_read);
1254 
1255 	/* Checks that previous access rights are unchanged with layer 5. */
1256 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1257 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1258 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1259 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1260 
1261 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_EXECUTE, layer6_execute);
1262 
1263 	/* Checks that previous access rights are unchanged with layer 6. */
1264 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1265 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1266 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1267 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1268 
1269 	enforce_fs(_metadata,
1270 		   LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE,
1271 		   layer7_read_write);
1272 
1273 	/* Checks read access is now denied with layer 7. */
1274 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
1275 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1276 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1277 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1278 }
1279 
1280 TEST_F_FORK(layout1, inherit_subset)
1281 {
1282 	const struct rule rules[] = {
1283 		{
1284 			.path = dir_s1d2,
1285 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
1286 				  LANDLOCK_ACCESS_FS_READ_DIR,
1287 		},
1288 		{},
1289 	};
1290 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1291 
1292 	enforce_ruleset(_metadata, ruleset_fd);
1293 
1294 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1295 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1296 
1297 	/* Write access is forbidden. */
1298 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1299 	/* Readdir access is allowed. */
1300 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1301 
1302 	/* Write access is forbidden. */
1303 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1304 	/* Readdir access is allowed. */
1305 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1306 
1307 	/*
1308 	 * Tests shared rule extension: the following rules should not grant
1309 	 * any new access, only remove some.  Once enforced, these rules are
1310 	 * ANDed with the previous ones.
1311 	 */
1312 	add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
1313 			 dir_s1d2);
1314 	/*
1315 	 * According to ruleset_fd, dir_s1d2 should now have the
1316 	 * LANDLOCK_ACCESS_FS_READ_FILE and LANDLOCK_ACCESS_FS_WRITE_FILE
1317 	 * access rights (even if this directory is opened a second time).
1318 	 * However, when enforcing this updated ruleset, the ruleset tied to
1319 	 * the current process (i.e. its domain) will still only have the
1320 	 * dir_s1d2 with LANDLOCK_ACCESS_FS_READ_FILE and
1321 	 * LANDLOCK_ACCESS_FS_READ_DIR accesses, but
1322 	 * LANDLOCK_ACCESS_FS_WRITE_FILE must not be allowed because it would
1323 	 * be a privilege escalation.
1324 	 */
1325 	enforce_ruleset(_metadata, ruleset_fd);
1326 
1327 	/* Same tests and results as above. */
1328 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1329 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1330 
1331 	/* It is still forbidden to write in file1_s1d2. */
1332 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1333 	/* Readdir access is still allowed. */
1334 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1335 
1336 	/* It is still forbidden to write in file1_s1d3. */
1337 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1338 	/* Readdir access is still allowed. */
1339 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1340 
1341 	/*
1342 	 * Try to get more privileges by adding new access rights to the parent
1343 	 * directory: dir_s1d1.
1344 	 */
1345 	add_path_beneath(_metadata, ruleset_fd, ACCESS_RW, dir_s1d1);
1346 	enforce_ruleset(_metadata, ruleset_fd);
1347 
1348 	/* Same tests and results as above. */
1349 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1350 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1351 
1352 	/* It is still forbidden to write in file1_s1d2. */
1353 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1354 	/* Readdir access is still allowed. */
1355 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1356 
1357 	/* It is still forbidden to write in file1_s1d3. */
1358 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1359 	/* Readdir access is still allowed. */
1360 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1361 
1362 	/*
1363 	 * Now, dir_s1d3 get a new rule tied to it, only allowing
1364 	 * LANDLOCK_ACCESS_FS_WRITE_FILE.  The (kernel internal) difference is
1365 	 * that there was no rule tied to it before.
1366 	 */
1367 	add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
1368 			 dir_s1d3);
1369 	enforce_ruleset(_metadata, ruleset_fd);
1370 	ASSERT_EQ(0, close(ruleset_fd));
1371 
1372 	/*
1373 	 * Same tests and results as above, except for open(dir_s1d3) which is
1374 	 * now denied because the new rule mask the rule previously inherited
1375 	 * from dir_s1d2.
1376 	 */
1377 
1378 	/* Same tests and results as above. */
1379 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1380 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1381 
1382 	/* It is still forbidden to write in file1_s1d2. */
1383 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1384 	/* Readdir access is still allowed. */
1385 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1386 
1387 	/* It is still forbidden to write in file1_s1d3. */
1388 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1389 	/*
1390 	 * Readdir of dir_s1d3 is still allowed because of the OR policy inside
1391 	 * the same layer.
1392 	 */
1393 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1394 }
1395 
1396 TEST_F_FORK(layout1, inherit_superset)
1397 {
1398 	const struct rule rules[] = {
1399 		{
1400 			.path = dir_s1d3,
1401 			.access = ACCESS_RO,
1402 		},
1403 		{},
1404 	};
1405 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1406 
1407 	enforce_ruleset(_metadata, ruleset_fd);
1408 
1409 	/* Readdir access is denied for dir_s1d2. */
1410 	ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1411 	/* Readdir access is allowed for dir_s1d3. */
1412 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1413 	/* File access is allowed for file1_s1d3. */
1414 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1415 
1416 	/* Now dir_s1d2, parent of dir_s1d3, gets a new rule tied to it. */
1417 	add_path_beneath(_metadata, ruleset_fd,
1418 			 LANDLOCK_ACCESS_FS_READ_FILE |
1419 				 LANDLOCK_ACCESS_FS_READ_DIR,
1420 			 dir_s1d2);
1421 	enforce_ruleset(_metadata, ruleset_fd);
1422 	EXPECT_EQ(0, close(ruleset_fd));
1423 
1424 	/* Readdir access is still denied for dir_s1d2. */
1425 	ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1426 	/* Readdir access is still allowed for dir_s1d3. */
1427 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1428 	/* File access is still allowed for file1_s1d3. */
1429 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1430 }
1431 
1432 TEST_F_FORK(layout0, max_layers)
1433 {
1434 	int i, err;
1435 	const struct rule rules[] = {
1436 		{
1437 			.path = TMP_DIR,
1438 			.access = ACCESS_RO,
1439 		},
1440 		{},
1441 	};
1442 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1443 
1444 	for (i = 0; i < 16; i++)
1445 		enforce_ruleset(_metadata, ruleset_fd);
1446 
1447 	for (i = 0; i < 2; i++) {
1448 		err = landlock_restrict_self(ruleset_fd, 0);
1449 		ASSERT_EQ(-1, err);
1450 		ASSERT_EQ(E2BIG, errno);
1451 	}
1452 	EXPECT_EQ(0, close(ruleset_fd));
1453 }
1454 
1455 TEST_F_FORK(layout1, empty_or_same_ruleset)
1456 {
1457 	struct landlock_ruleset_attr ruleset_attr = {};
1458 	int ruleset_fd;
1459 
1460 	/* Tests empty handled_access_fs. */
1461 	ruleset_fd =
1462 		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
1463 	ASSERT_LE(-1, ruleset_fd);
1464 	ASSERT_EQ(ENOMSG, errno);
1465 
1466 	/* Enforces policy which denies read access to all files. */
1467 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_READ_FILE, NULL);
1468 
1469 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1470 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1471 
1472 	/* Nests a policy which denies read access to all directories. */
1473 	ruleset_fd =
1474 		create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_DIR, NULL);
1475 	enforce_ruleset(_metadata, ruleset_fd);
1476 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1477 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1478 
1479 	/* Enforces a second time with the same ruleset. */
1480 	enforce_ruleset(_metadata, ruleset_fd);
1481 	ASSERT_EQ(0, close(ruleset_fd));
1482 }
1483 
1484 TEST_F_FORK(layout1, rule_on_mountpoint)
1485 {
1486 	const struct rule rules[] = {
1487 		{
1488 			.path = dir_s1d1,
1489 			.access = ACCESS_RO,
1490 		},
1491 		{
1492 			/* dir_s3d2 is a mount point. */
1493 			.path = dir_s3d2,
1494 			.access = ACCESS_RO,
1495 		},
1496 		{},
1497 	};
1498 
1499 	enforce_fs(_metadata, ACCESS_RW, rules);
1500 
1501 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1502 
1503 	ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
1504 
1505 	ASSERT_EQ(EACCES, test_open(dir_s3d1, O_RDONLY));
1506 	ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
1507 	ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
1508 }
1509 
1510 TEST_F_FORK(layout1, rule_over_mountpoint)
1511 {
1512 	const struct rule rules[] = {
1513 		{
1514 			.path = dir_s1d1,
1515 			.access = ACCESS_RO,
1516 		},
1517 		{
1518 			/* dir_s3d2 is a mount point. */
1519 			.path = dir_s3d1,
1520 			.access = ACCESS_RO,
1521 		},
1522 		{},
1523 	};
1524 
1525 	enforce_fs(_metadata, ACCESS_RW, rules);
1526 
1527 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1528 
1529 	ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
1530 
1531 	ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
1532 	ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
1533 	ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
1534 }
1535 
1536 /*
1537  * This test verifies that we can apply a landlock rule on the root directory
1538  * (which might require special handling).
1539  */
1540 TEST_F_FORK(layout1, rule_over_root_allow_then_deny)
1541 {
1542 	struct rule rules[] = {
1543 		{
1544 			.path = "/",
1545 			.access = ACCESS_RO,
1546 		},
1547 		{},
1548 	};
1549 
1550 	enforce_fs(_metadata, ACCESS_RW, rules);
1551 
1552 	/* Checks allowed access. */
1553 	ASSERT_EQ(0, test_open("/", O_RDONLY));
1554 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1555 
1556 	rules[0].access = LANDLOCK_ACCESS_FS_READ_FILE;
1557 	enforce_fs(_metadata, ACCESS_RW, rules);
1558 
1559 	/* Checks denied access (on a directory). */
1560 	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1561 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1562 }
1563 
1564 TEST_F_FORK(layout1, rule_over_root_deny)
1565 {
1566 	const struct rule rules[] = {
1567 		{
1568 			.path = "/",
1569 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1570 		},
1571 		{},
1572 	};
1573 
1574 	enforce_fs(_metadata, ACCESS_RW, rules);
1575 
1576 	/* Checks denied access (on a directory). */
1577 	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1578 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1579 }
1580 
1581 TEST_F_FORK(layout1, rule_inside_mount_ns)
1582 {
1583 	const struct rule rules[] = {
1584 		{
1585 			.path = "s3d3",
1586 			.access = ACCESS_RO,
1587 		},
1588 		{},
1589 	};
1590 
1591 	set_cap(_metadata, CAP_SYS_ADMIN);
1592 	ASSERT_EQ(0, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3))
1593 	{
1594 		TH_LOG("Failed to pivot root: %s", strerror(errno));
1595 	};
1596 	ASSERT_EQ(0, chdir("/"));
1597 	clear_cap(_metadata, CAP_SYS_ADMIN);
1598 
1599 	enforce_fs(_metadata, ACCESS_RW, rules);
1600 
1601 	ASSERT_EQ(0, test_open("s3d3", O_RDONLY));
1602 	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1603 }
1604 
1605 TEST_F_FORK(layout1, mount_and_pivot)
1606 {
1607 	const struct rule rules[] = {
1608 		{
1609 			.path = dir_s3d2,
1610 			.access = ACCESS_RO,
1611 		},
1612 		{},
1613 	};
1614 
1615 	enforce_fs(_metadata, ACCESS_RW, rules);
1616 
1617 	set_cap(_metadata, CAP_SYS_ADMIN);
1618 	ASSERT_EQ(-1, mount(NULL, dir_s3d2, NULL, MS_RDONLY, NULL));
1619 	ASSERT_EQ(EPERM, errno);
1620 	ASSERT_EQ(-1, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3));
1621 	ASSERT_EQ(EPERM, errno);
1622 	clear_cap(_metadata, CAP_SYS_ADMIN);
1623 }
1624 
1625 TEST_F_FORK(layout1, move_mount)
1626 {
1627 	const struct rule rules[] = {
1628 		{
1629 			.path = dir_s3d2,
1630 			.access = ACCESS_RO,
1631 		},
1632 		{},
1633 	};
1634 
1635 	set_cap(_metadata, CAP_SYS_ADMIN);
1636 	ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1637 			     dir_s1d2, 0))
1638 	{
1639 		TH_LOG("Failed to move mount: %s", strerror(errno));
1640 	}
1641 
1642 	ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD,
1643 			     dir_s3d2, 0));
1644 	clear_cap(_metadata, CAP_SYS_ADMIN);
1645 
1646 	enforce_fs(_metadata, ACCESS_RW, rules);
1647 
1648 	set_cap(_metadata, CAP_SYS_ADMIN);
1649 	ASSERT_EQ(-1, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1650 			      dir_s1d2, 0));
1651 	ASSERT_EQ(EPERM, errno);
1652 	clear_cap(_metadata, CAP_SYS_ADMIN);
1653 }
1654 
1655 TEST_F_FORK(layout1, topology_changes_with_net_only)
1656 {
1657 	const struct landlock_ruleset_attr ruleset_net = {
1658 		.handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP |
1659 				      LANDLOCK_ACCESS_NET_CONNECT_TCP,
1660 	};
1661 
1662 	/* Add network restrictions. */
1663 	drop_access_rights(_metadata, &ruleset_net);
1664 
1665 	/* Mount, remount, move_mount, umount, and pivot_root checks. */
1666 	set_cap(_metadata, CAP_SYS_ADMIN);
1667 	ASSERT_EQ(0, mount_opt(&mnt_tmp, dir_s1d2));
1668 	ASSERT_EQ(0, mount(NULL, dir_s1d2, NULL, MS_PRIVATE | MS_REC, NULL));
1669 	ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD,
1670 			     dir_s2d2, 0));
1671 	ASSERT_EQ(0, umount(dir_s2d2));
1672 	ASSERT_EQ(0, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3));
1673 	ASSERT_EQ(0, chdir("/"));
1674 	clear_cap(_metadata, CAP_SYS_ADMIN);
1675 }
1676 
1677 TEST_F_FORK(layout1, topology_changes_with_net_and_fs)
1678 {
1679 	const struct landlock_ruleset_attr ruleset_net_fs = {
1680 		.handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP |
1681 				      LANDLOCK_ACCESS_NET_CONNECT_TCP,
1682 		.handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
1683 	};
1684 
1685 	/* Add network and filesystem restrictions. */
1686 	drop_access_rights(_metadata, &ruleset_net_fs);
1687 
1688 	/* Mount, remount, move_mount, umount, and pivot_root checks. */
1689 	set_cap(_metadata, CAP_SYS_ADMIN);
1690 	ASSERT_EQ(-1, mount_opt(&mnt_tmp, dir_s1d2));
1691 	ASSERT_EQ(EPERM, errno);
1692 	ASSERT_EQ(-1, mount(NULL, dir_s3d2, NULL, MS_PRIVATE | MS_REC, NULL));
1693 	ASSERT_EQ(EPERM, errno);
1694 	ASSERT_EQ(-1, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1695 			      dir_s2d2, 0));
1696 	ASSERT_EQ(EPERM, errno);
1697 	ASSERT_EQ(-1, umount(dir_s3d2));
1698 	ASSERT_EQ(EPERM, errno);
1699 	ASSERT_EQ(-1, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3));
1700 	ASSERT_EQ(EPERM, errno);
1701 	clear_cap(_metadata, CAP_SYS_ADMIN);
1702 }
1703 
1704 TEST_F_FORK(layout1, release_inodes)
1705 {
1706 	const struct rule rules[] = {
1707 		{
1708 			.path = dir_s1d1,
1709 			.access = ACCESS_RO,
1710 		},
1711 		{
1712 			.path = dir_s3d2,
1713 			.access = ACCESS_RO,
1714 		},
1715 		{
1716 			.path = dir_s3d3,
1717 			.access = ACCESS_RO,
1718 		},
1719 		{},
1720 	};
1721 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1722 
1723 	/* Unmount a file hierarchy while it is being used by a ruleset. */
1724 	set_cap(_metadata, CAP_SYS_ADMIN);
1725 	ASSERT_EQ(0, umount(dir_s3d2));
1726 	clear_cap(_metadata, CAP_SYS_ADMIN);
1727 
1728 	enforce_ruleset(_metadata, ruleset_fd);
1729 	EXPECT_EQ(0, close(ruleset_fd));
1730 
1731 	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
1732 	ASSERT_EQ(EACCES, test_open(dir_s3d2, O_RDONLY));
1733 	/* This dir_s3d3 would not be allowed and does not exist anyway. */
1734 	ASSERT_EQ(ENOENT, test_open(dir_s3d3, O_RDONLY));
1735 }
1736 
1737 /*
1738  * This test checks that a rule on a directory used as a mount point does not
1739  * grant access to the mount covering it.  It is a generalization of the bind
1740  * mount case in layout3_fs.hostfs.release_inodes that tests hidden mount points.
1741  */
1742 TEST_F_FORK(layout1, covered_rule)
1743 {
1744 	const struct rule layer1[] = {
1745 		{
1746 			.path = dir_s3d2,
1747 			.access = LANDLOCK_ACCESS_FS_READ_DIR,
1748 		},
1749 		{},
1750 	};
1751 	int ruleset_fd;
1752 
1753 	/* Unmount to simplify FIXTURE_TEARDOWN. */
1754 	set_cap(_metadata, CAP_SYS_ADMIN);
1755 	ASSERT_EQ(0, umount(dir_s3d2));
1756 	clear_cap(_metadata, CAP_SYS_ADMIN);
1757 
1758 	/* Creates a ruleset with the future hidden directory. */
1759 	ruleset_fd =
1760 		create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_DIR, layer1);
1761 
1762 	/* Covers with a new mount point. */
1763 	set_cap(_metadata, CAP_SYS_ADMIN);
1764 	ASSERT_EQ(0, mount_opt(&mnt_tmp, dir_s3d2));
1765 	clear_cap(_metadata, CAP_SYS_ADMIN);
1766 
1767 	ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
1768 
1769 	enforce_ruleset(_metadata, ruleset_fd);
1770 	ASSERT_EQ(0, close(ruleset_fd));
1771 
1772 	/* Checks that access to the new mount point is denied. */
1773 	ASSERT_EQ(EACCES, test_open(dir_s3d2, O_RDONLY));
1774 }
1775 
1776 enum relative_access {
1777 	REL_OPEN,
1778 	REL_CHDIR,
1779 	REL_CHROOT_ONLY,
1780 	REL_CHROOT_CHDIR,
1781 };
1782 
1783 static void test_relative_path(struct __test_metadata *const _metadata,
1784 			       const enum relative_access rel)
1785 {
1786 	/*
1787 	 * Common layer to check that chroot doesn't ignore it (i.e. a chroot
1788 	 * is not a disconnected root directory).
1789 	 */
1790 	const struct rule layer1_base[] = {
1791 		{
1792 			.path = TMP_DIR,
1793 			.access = ACCESS_RO,
1794 		},
1795 		{},
1796 	};
1797 	const struct rule layer2_subs[] = {
1798 		{
1799 			.path = dir_s1d2,
1800 			.access = ACCESS_RO,
1801 		},
1802 		{
1803 			.path = dir_s2d2,
1804 			.access = ACCESS_RO,
1805 		},
1806 		{},
1807 	};
1808 	int dirfd, ruleset_fd;
1809 
1810 	enforce_fs(_metadata, ACCESS_RW, layer1_base);
1811 
1812 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_subs);
1813 
1814 	ASSERT_LE(0, ruleset_fd);
1815 	switch (rel) {
1816 	case REL_OPEN:
1817 	case REL_CHDIR:
1818 		break;
1819 	case REL_CHROOT_ONLY:
1820 		ASSERT_EQ(0, chdir(dir_s2d2));
1821 		break;
1822 	case REL_CHROOT_CHDIR:
1823 		ASSERT_EQ(0, chdir(dir_s1d2));
1824 		break;
1825 	default:
1826 		ASSERT_TRUE(false);
1827 		return;
1828 	}
1829 
1830 	set_cap(_metadata, CAP_SYS_CHROOT);
1831 	enforce_ruleset(_metadata, ruleset_fd);
1832 
1833 	switch (rel) {
1834 	case REL_OPEN:
1835 		dirfd = open(dir_s1d2, O_DIRECTORY);
1836 		ASSERT_LE(0, dirfd);
1837 		break;
1838 	case REL_CHDIR:
1839 		ASSERT_EQ(0, chdir(dir_s1d2));
1840 		dirfd = AT_FDCWD;
1841 		break;
1842 	case REL_CHROOT_ONLY:
1843 		/* Do chroot into dir_s1d2 (relative to dir_s2d2). */
1844 		ASSERT_EQ(0, chroot("../../s1d1/s1d2"))
1845 		{
1846 			TH_LOG("Failed to chroot: %s", strerror(errno));
1847 		}
1848 		dirfd = AT_FDCWD;
1849 		break;
1850 	case REL_CHROOT_CHDIR:
1851 		/* Do chroot into dir_s1d2. */
1852 		ASSERT_EQ(0, chroot("."))
1853 		{
1854 			TH_LOG("Failed to chroot: %s", strerror(errno));
1855 		}
1856 		dirfd = AT_FDCWD;
1857 		break;
1858 	}
1859 
1860 	ASSERT_EQ((rel == REL_CHROOT_CHDIR) ? 0 : EACCES,
1861 		  test_open_rel(dirfd, "..", O_RDONLY));
1862 	ASSERT_EQ(0, test_open_rel(dirfd, ".", O_RDONLY));
1863 
1864 	if (rel == REL_CHROOT_ONLY) {
1865 		/* The current directory is dir_s2d2. */
1866 		ASSERT_EQ(0, test_open_rel(dirfd, "./s2d3", O_RDONLY));
1867 	} else {
1868 		/* The current directory is dir_s1d2. */
1869 		ASSERT_EQ(0, test_open_rel(dirfd, "./s1d3", O_RDONLY));
1870 	}
1871 
1872 	if (rel == REL_CHROOT_ONLY || rel == REL_CHROOT_CHDIR) {
1873 		/* Checks the root dir_s1d2. */
1874 		ASSERT_EQ(0, test_open_rel(dirfd, "/..", O_RDONLY));
1875 		ASSERT_EQ(0, test_open_rel(dirfd, "/", O_RDONLY));
1876 		ASSERT_EQ(0, test_open_rel(dirfd, "/f1", O_RDONLY));
1877 		ASSERT_EQ(0, test_open_rel(dirfd, "/s1d3", O_RDONLY));
1878 	}
1879 
1880 	if (rel != REL_CHROOT_CHDIR) {
1881 		ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s1d1", O_RDONLY));
1882 		ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2", O_RDONLY));
1883 		ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2/s1d3",
1884 					   O_RDONLY));
1885 
1886 		ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s2d1", O_RDONLY));
1887 		ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2", O_RDONLY));
1888 		ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2/s2d3",
1889 					   O_RDONLY));
1890 	}
1891 
1892 	if (rel == REL_OPEN)
1893 		ASSERT_EQ(0, close(dirfd));
1894 	ASSERT_EQ(0, close(ruleset_fd));
1895 }
1896 
1897 TEST_F_FORK(layout1, relative_open)
1898 {
1899 	test_relative_path(_metadata, REL_OPEN);
1900 }
1901 
1902 TEST_F_FORK(layout1, relative_chdir)
1903 {
1904 	test_relative_path(_metadata, REL_CHDIR);
1905 }
1906 
1907 TEST_F_FORK(layout1, relative_chroot_only)
1908 {
1909 	test_relative_path(_metadata, REL_CHROOT_ONLY);
1910 }
1911 
1912 TEST_F_FORK(layout1, relative_chroot_chdir)
1913 {
1914 	test_relative_path(_metadata, REL_CHROOT_CHDIR);
1915 }
1916 
1917 static void copy_file(struct __test_metadata *const _metadata,
1918 		      const char *const src_path, const char *const dst_path)
1919 {
1920 	int dst_fd, src_fd;
1921 	struct stat statbuf;
1922 
1923 	dst_fd = open(dst_path, O_WRONLY | O_TRUNC | O_CLOEXEC);
1924 	ASSERT_LE(0, dst_fd)
1925 	{
1926 		TH_LOG("Failed to open \"%s\": %s", dst_path, strerror(errno));
1927 	}
1928 	src_fd = open(src_path, O_RDONLY | O_CLOEXEC);
1929 	ASSERT_LE(0, src_fd)
1930 	{
1931 		TH_LOG("Failed to open \"%s\": %s", src_path, strerror(errno));
1932 	}
1933 	ASSERT_EQ(0, fstat(src_fd, &statbuf));
1934 	ASSERT_EQ(statbuf.st_size,
1935 		  sendfile(dst_fd, src_fd, 0, statbuf.st_size));
1936 	ASSERT_EQ(0, close(src_fd));
1937 	ASSERT_EQ(0, close(dst_fd));
1938 }
1939 
1940 static void test_execute(struct __test_metadata *const _metadata, const int err,
1941 			 const char *const path)
1942 {
1943 	int status;
1944 	char *const argv[] = { (char *)path, NULL };
1945 	const pid_t child = fork();
1946 
1947 	ASSERT_LE(0, child);
1948 	if (child == 0) {
1949 		ASSERT_EQ(err ? -1 : 0, execve(path, argv, NULL))
1950 		{
1951 			TH_LOG("Failed to execute \"%s\": %s", path,
1952 			       strerror(errno));
1953 		};
1954 		ASSERT_EQ(err, errno);
1955 		_exit(__test_passed(_metadata) ? 2 : 1);
1956 		return;
1957 	}
1958 	ASSERT_EQ(child, waitpid(child, &status, 0));
1959 	ASSERT_EQ(1, WIFEXITED(status));
1960 	ASSERT_EQ(err ? 2 : 0, WEXITSTATUS(status))
1961 	{
1962 		TH_LOG("Unexpected return code for \"%s\"", path);
1963 	};
1964 }
1965 
1966 static void test_check_exec(struct __test_metadata *const _metadata,
1967 			    const int err, const char *const path)
1968 {
1969 	int ret;
1970 	char *const argv[] = { (char *)path, NULL };
1971 
1972 	ret = sys_execveat(AT_FDCWD, path, argv, NULL,
1973 			   AT_EMPTY_PATH | AT_EXECVE_CHECK);
1974 	if (err) {
1975 		EXPECT_EQ(-1, ret);
1976 		EXPECT_EQ(errno, err);
1977 	} else {
1978 		EXPECT_EQ(0, ret);
1979 	}
1980 }
1981 
1982 TEST_F_FORK(layout1, execute)
1983 {
1984 	const struct rule rules[] = {
1985 		{
1986 			.path = dir_s1d2,
1987 			.access = LANDLOCK_ACCESS_FS_EXECUTE,
1988 		},
1989 		{},
1990 	};
1991 
1992 	copy_file(_metadata, bin_true, file1_s1d1);
1993 	copy_file(_metadata, bin_true, file1_s1d2);
1994 	copy_file(_metadata, bin_true, file1_s1d3);
1995 
1996 	/* Checks before file1_s1d1 being denied. */
1997 	test_execute(_metadata, 0, file1_s1d1);
1998 	test_check_exec(_metadata, 0, file1_s1d1);
1999 
2000 	enforce_fs(_metadata, rules[0].access, rules);
2001 
2002 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
2003 	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
2004 	test_execute(_metadata, EACCES, file1_s1d1);
2005 	test_check_exec(_metadata, EACCES, file1_s1d1);
2006 
2007 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
2008 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
2009 	test_execute(_metadata, 0, file1_s1d2);
2010 	test_check_exec(_metadata, 0, file1_s1d2);
2011 
2012 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
2013 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
2014 	test_execute(_metadata, 0, file1_s1d3);
2015 	test_check_exec(_metadata, 0, file1_s1d3);
2016 }
2017 
2018 TEST_F_FORK(layout1, umount_sandboxer)
2019 {
2020 	int pipe_child[2], pipe_parent[2];
2021 	char buf_parent;
2022 	pid_t child;
2023 	int status;
2024 
2025 	copy_file(_metadata, bin_sandbox_and_launch, file1_s3d3);
2026 	ASSERT_EQ(0, pipe2(pipe_child, 0));
2027 	ASSERT_EQ(0, pipe2(pipe_parent, 0));
2028 
2029 	child = fork();
2030 	ASSERT_LE(0, child);
2031 	if (child == 0) {
2032 		char pipe_child_str[12], pipe_parent_str[12];
2033 		char *const argv[] = { (char *)file1_s3d3,
2034 				       (char *)bin_wait_pipe, pipe_child_str,
2035 				       pipe_parent_str, NULL };
2036 
2037 		/* Passes the pipe FDs to the executed binary and its child. */
2038 		EXPECT_EQ(0, close(pipe_child[0]));
2039 		EXPECT_EQ(0, close(pipe_parent[1]));
2040 		snprintf(pipe_child_str, sizeof(pipe_child_str), "%d",
2041 			 pipe_child[1]);
2042 		snprintf(pipe_parent_str, sizeof(pipe_parent_str), "%d",
2043 			 pipe_parent[0]);
2044 
2045 		/*
2046 		 * We need bin_sandbox_and_launch (copied inside the mount as
2047 		 * file1_s3d3) to execute bin_wait_pipe (outside the mount) to
2048 		 * make sure the mount point will not be EBUSY because of
2049 		 * file1_s3d3 being in use.  This avoids a potential race
2050 		 * condition between the following read() and umount() calls.
2051 		 */
2052 		ASSERT_EQ(0, execve(argv[0], argv, NULL))
2053 		{
2054 			TH_LOG("Failed to execute \"%s\": %s", argv[0],
2055 			       strerror(errno));
2056 		};
2057 		_exit(1);
2058 		return;
2059 	}
2060 
2061 	EXPECT_EQ(0, close(pipe_child[1]));
2062 	EXPECT_EQ(0, close(pipe_parent[0]));
2063 
2064 	/* Waits for the child to sandbox itself. */
2065 	EXPECT_EQ(1, read(pipe_child[0], &buf_parent, 1));
2066 
2067 	/* Tests that the sandboxer is tied to its mount point. */
2068 	set_cap(_metadata, CAP_SYS_ADMIN);
2069 	EXPECT_EQ(-1, umount(dir_s3d2));
2070 	EXPECT_EQ(EBUSY, errno);
2071 	clear_cap(_metadata, CAP_SYS_ADMIN);
2072 
2073 	/* Signals the child to launch a grandchild. */
2074 	EXPECT_EQ(1, write(pipe_parent[1], ".", 1));
2075 
2076 	/* Waits for the grandchild. */
2077 	EXPECT_EQ(1, read(pipe_child[0], &buf_parent, 1));
2078 
2079 	/* Tests that the domain's sandboxer is not tied to its mount point. */
2080 	set_cap(_metadata, CAP_SYS_ADMIN);
2081 	EXPECT_EQ(0, umount(dir_s3d2))
2082 	{
2083 		TH_LOG("Failed to umount \"%s\": %s", dir_s3d2,
2084 		       strerror(errno));
2085 	};
2086 	clear_cap(_metadata, CAP_SYS_ADMIN);
2087 
2088 	/* Signals the grandchild to terminate. */
2089 	EXPECT_EQ(1, write(pipe_parent[1], ".", 1));
2090 	ASSERT_EQ(child, waitpid(child, &status, 0));
2091 	ASSERT_EQ(1, WIFEXITED(status));
2092 	ASSERT_EQ(0, WEXITSTATUS(status));
2093 }
2094 
2095 TEST_F_FORK(layout1, link)
2096 {
2097 	const struct rule layer1[] = {
2098 		{
2099 			.path = dir_s1d2,
2100 			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2101 		},
2102 		{},
2103 	};
2104 	const struct rule layer2[] = {
2105 		{
2106 			.path = dir_s1d3,
2107 			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
2108 		},
2109 		{},
2110 	};
2111 
2112 	ASSERT_EQ(0, unlink(file1_s1d1));
2113 	ASSERT_EQ(0, unlink(file1_s1d2));
2114 	ASSERT_EQ(0, unlink(file1_s1d3));
2115 
2116 	enforce_fs(_metadata, layer1[0].access, layer1);
2117 
2118 	ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
2119 	ASSERT_EQ(EACCES, errno);
2120 
2121 	/* Denies linking because of reparenting. */
2122 	ASSERT_EQ(-1, link(file1_s2d1, file1_s1d2));
2123 	ASSERT_EQ(EXDEV, errno);
2124 	ASSERT_EQ(-1, link(file2_s1d2, file1_s1d3));
2125 	ASSERT_EQ(EXDEV, errno);
2126 	ASSERT_EQ(-1, link(file2_s1d3, file1_s1d2));
2127 	ASSERT_EQ(EXDEV, errno);
2128 
2129 	ASSERT_EQ(0, link(file2_s1d2, file1_s1d2));
2130 	ASSERT_EQ(0, link(file2_s1d3, file1_s1d3));
2131 
2132 	/* Prepares for next unlinks. */
2133 	ASSERT_EQ(0, unlink(file2_s1d2));
2134 	ASSERT_EQ(0, unlink(file2_s1d3));
2135 
2136 	enforce_fs(_metadata, layer2[0].access, layer2);
2137 
2138 	/* Checks that linkind doesn't require the ability to delete a file. */
2139 	ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
2140 	ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
2141 }
2142 
2143 static int test_rename(const char *const oldpath, const char *const newpath)
2144 {
2145 	if (rename(oldpath, newpath))
2146 		return errno;
2147 	return 0;
2148 }
2149 
2150 static int test_exchange(const char *const oldpath, const char *const newpath)
2151 {
2152 	if (renameat2(AT_FDCWD, oldpath, AT_FDCWD, newpath, RENAME_EXCHANGE))
2153 		return errno;
2154 	return 0;
2155 }
2156 
2157 static int test_renameat(int olddirfd, const char *oldpath, int newdirfd,
2158 			 const char *newpath)
2159 {
2160 	if (renameat2(olddirfd, oldpath, newdirfd, newpath, 0))
2161 		return errno;
2162 	return 0;
2163 }
2164 
2165 static int test_exchangeat(int olddirfd, const char *oldpath, int newdirfd,
2166 			   const char *newpath)
2167 {
2168 	if (renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_EXCHANGE))
2169 		return errno;
2170 	return 0;
2171 }
2172 
2173 TEST_F_FORK(layout1, rename_file)
2174 {
2175 	const struct rule rules[] = {
2176 		{
2177 			.path = dir_s1d3,
2178 			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
2179 		},
2180 		{
2181 			.path = dir_s2d2,
2182 			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
2183 		},
2184 		{},
2185 	};
2186 
2187 	ASSERT_EQ(0, unlink(file1_s1d2));
2188 
2189 	enforce_fs(_metadata, rules[0].access, rules);
2190 
2191 	/*
2192 	 * Tries to replace a file, from a directory that allows file removal,
2193 	 * but to a different directory (which also allows file removal).
2194 	 */
2195 	ASSERT_EQ(-1, rename(file1_s2d3, file1_s1d3));
2196 	ASSERT_EQ(EXDEV, errno);
2197 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d3,
2198 				RENAME_EXCHANGE));
2199 	ASSERT_EQ(EXDEV, errno);
2200 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, dir_s1d3,
2201 				RENAME_EXCHANGE));
2202 	ASSERT_EQ(EXDEV, errno);
2203 
2204 	/*
2205 	 * Tries to replace a file, from a directory that denies file removal,
2206 	 * to a different directory (which allows file removal).
2207 	 */
2208 	ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
2209 	ASSERT_EQ(EACCES, errno);
2210 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file1_s1d3,
2211 				RENAME_EXCHANGE));
2212 	ASSERT_EQ(EACCES, errno);
2213 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s1d3,
2214 				RENAME_EXCHANGE));
2215 	ASSERT_EQ(EXDEV, errno);
2216 
2217 	/* Exchanges files and directories that partially allow removal. */
2218 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s2d1,
2219 				RENAME_EXCHANGE));
2220 	ASSERT_EQ(EACCES, errno);
2221 	/* Checks that file1_s2d1 cannot be removed (instead of ENOTDIR). */
2222 	ASSERT_EQ(-1, rename(dir_s2d2, file1_s2d1));
2223 	ASSERT_EQ(EACCES, errno);
2224 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, dir_s2d2,
2225 				RENAME_EXCHANGE));
2226 	ASSERT_EQ(EACCES, errno);
2227 	/* Checks that file1_s1d1 cannot be removed (instead of EISDIR). */
2228 	ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
2229 	ASSERT_EQ(EACCES, errno);
2230 
2231 	/* Renames files with different parents. */
2232 	ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d2));
2233 	ASSERT_EQ(EXDEV, errno);
2234 	ASSERT_EQ(0, unlink(file1_s1d3));
2235 	ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
2236 	ASSERT_EQ(EACCES, errno);
2237 
2238 	/* Exchanges and renames files with same parent. */
2239 	ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s2d3,
2240 			       RENAME_EXCHANGE));
2241 	ASSERT_EQ(0, rename(file2_s2d3, file1_s2d3));
2242 
2243 	/* Exchanges files and directories with same parent, twice. */
2244 	ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
2245 			       RENAME_EXCHANGE));
2246 	ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
2247 			       RENAME_EXCHANGE));
2248 }
2249 
2250 TEST_F_FORK(layout1, rename_dir)
2251 {
2252 	const struct rule rules[] = {
2253 		{
2254 			.path = dir_s1d2,
2255 			.access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
2256 		},
2257 		{
2258 			.path = dir_s2d1,
2259 			.access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
2260 		},
2261 		{},
2262 	};
2263 
2264 	/* Empties dir_s1d3 to allow renaming. */
2265 	ASSERT_EQ(0, unlink(file1_s1d3));
2266 	ASSERT_EQ(0, unlink(file2_s1d3));
2267 
2268 	enforce_fs(_metadata, rules[0].access, rules);
2269 
2270 	/* Exchanges and renames directory to a different parent. */
2271 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
2272 				RENAME_EXCHANGE));
2273 	ASSERT_EQ(EXDEV, errno);
2274 	ASSERT_EQ(-1, rename(dir_s2d3, dir_s1d3));
2275 	ASSERT_EQ(EXDEV, errno);
2276 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
2277 				RENAME_EXCHANGE));
2278 	ASSERT_EQ(EXDEV, errno);
2279 
2280 	/*
2281 	 * Exchanges directory to the same parent, which doesn't allow
2282 	 * directory removal.
2283 	 */
2284 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d1, AT_FDCWD, dir_s2d1,
2285 				RENAME_EXCHANGE));
2286 	ASSERT_EQ(EACCES, errno);
2287 	/* Checks that dir_s1d2 cannot be removed (instead of ENOTDIR). */
2288 	ASSERT_EQ(-1, rename(dir_s1d2, file1_s1d1));
2289 	ASSERT_EQ(EACCES, errno);
2290 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s1d2,
2291 				RENAME_EXCHANGE));
2292 	ASSERT_EQ(EACCES, errno);
2293 	/* Checks that dir_s1d2 cannot be removed (instead of EISDIR). */
2294 	ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
2295 	ASSERT_EQ(EACCES, errno);
2296 
2297 	/*
2298 	 * Exchanges and renames directory to the same parent, which allows
2299 	 * directory removal.
2300 	 */
2301 	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, file1_s1d2,
2302 			       RENAME_EXCHANGE));
2303 	ASSERT_EQ(0, unlink(dir_s1d3));
2304 	ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
2305 	ASSERT_EQ(0, rename(file1_s1d2, dir_s1d3));
2306 	ASSERT_EQ(0, rmdir(dir_s1d3));
2307 }
2308 
2309 TEST_F_FORK(layout1, reparent_refer)
2310 {
2311 	const struct rule layer1[] = {
2312 		{
2313 			.path = dir_s1d2,
2314 			.access = LANDLOCK_ACCESS_FS_REFER,
2315 		},
2316 		{
2317 			.path = dir_s2d2,
2318 			.access = LANDLOCK_ACCESS_FS_REFER,
2319 		},
2320 		{},
2321 	};
2322 
2323 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_REFER, layer1);
2324 
2325 	ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d1));
2326 	ASSERT_EQ(EXDEV, errno);
2327 	ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d2));
2328 	ASSERT_EQ(EXDEV, errno);
2329 	ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d3));
2330 	ASSERT_EQ(EXDEV, errno);
2331 
2332 	ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d1));
2333 	ASSERT_EQ(EXDEV, errno);
2334 	ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d2));
2335 	ASSERT_EQ(EXDEV, errno);
2336 	/*
2337 	 * Moving should only be allowed when the source and the destination
2338 	 * parent directory have REFER.
2339 	 */
2340 	ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d3));
2341 	ASSERT_EQ(ENOTEMPTY, errno);
2342 	ASSERT_EQ(0, unlink(file1_s2d3));
2343 	ASSERT_EQ(0, unlink(file2_s2d3));
2344 	ASSERT_EQ(0, rename(dir_s1d3, dir_s2d3));
2345 }
2346 
2347 /* Checks renames beneath dir_s1d1. */
2348 static void refer_denied_by_default(struct __test_metadata *const _metadata,
2349 				    const struct rule layer1[],
2350 				    const int layer1_err,
2351 				    const struct rule layer2[])
2352 {
2353 	ASSERT_EQ(0, unlink(file1_s1d2));
2354 
2355 	enforce_fs(_metadata, layer1[0].access, layer1);
2356 
2357 	/*
2358 	 * If the first layer handles LANDLOCK_ACCESS_FS_REFER (according to
2359 	 * layer1_err), then it allows some different-parent renames and links.
2360 	 */
2361 	ASSERT_EQ(layer1_err, test_rename(file1_s1d1, file1_s1d2));
2362 	if (layer1_err == 0)
2363 		ASSERT_EQ(layer1_err, test_rename(file1_s1d2, file1_s1d1));
2364 	ASSERT_EQ(layer1_err, test_exchange(file2_s1d1, file2_s1d2));
2365 	ASSERT_EQ(layer1_err, test_exchange(file2_s1d2, file2_s1d1));
2366 
2367 	enforce_fs(_metadata, layer2[0].access, layer2);
2368 
2369 	/*
2370 	 * Now, either the first or the second layer does not handle
2371 	 * LANDLOCK_ACCESS_FS_REFER, which means that any different-parent
2372 	 * renames and links are denied, thus making the layer handling
2373 	 * LANDLOCK_ACCESS_FS_REFER null and void.
2374 	 */
2375 	ASSERT_EQ(EXDEV, test_rename(file1_s1d1, file1_s1d2));
2376 	ASSERT_EQ(EXDEV, test_exchange(file2_s1d1, file2_s1d2));
2377 	ASSERT_EQ(EXDEV, test_exchange(file2_s1d2, file2_s1d1));
2378 }
2379 
2380 const struct rule layer_dir_s1d1_refer[] = {
2381 	{
2382 		.path = dir_s1d1,
2383 		.access = LANDLOCK_ACCESS_FS_REFER,
2384 	},
2385 	{},
2386 };
2387 
2388 const struct rule layer_dir_s1d1_execute[] = {
2389 	{
2390 		/* Matches a parent directory. */
2391 		.path = dir_s1d1,
2392 		.access = LANDLOCK_ACCESS_FS_EXECUTE,
2393 	},
2394 	{},
2395 };
2396 
2397 const struct rule layer_dir_s2d1_execute[] = {
2398 	{
2399 		/* Does not match a parent directory. */
2400 		.path = dir_s2d1,
2401 		.access = LANDLOCK_ACCESS_FS_EXECUTE,
2402 	},
2403 	{},
2404 };
2405 
2406 /*
2407  * Tests precedence over renames: denied by default for different parent
2408  * directories, *with* a rule matching a parent directory, but not directly
2409  * denying access (with MAKE_REG nor REMOVE).
2410  */
2411 TEST_F_FORK(layout1, refer_denied_by_default1)
2412 {
2413 	refer_denied_by_default(_metadata, layer_dir_s1d1_refer, 0,
2414 				layer_dir_s1d1_execute);
2415 }
2416 
2417 /*
2418  * Same test but this time turning around the ABI version order: the first
2419  * layer does not handle LANDLOCK_ACCESS_FS_REFER.
2420  */
2421 TEST_F_FORK(layout1, refer_denied_by_default2)
2422 {
2423 	refer_denied_by_default(_metadata, layer_dir_s1d1_execute, EXDEV,
2424 				layer_dir_s1d1_refer);
2425 }
2426 
2427 /*
2428  * Tests precedence over renames: denied by default for different parent
2429  * directories, *without* a rule matching a parent directory, but not directly
2430  * denying access (with MAKE_REG nor REMOVE).
2431  */
2432 TEST_F_FORK(layout1, refer_denied_by_default3)
2433 {
2434 	refer_denied_by_default(_metadata, layer_dir_s1d1_refer, 0,
2435 				layer_dir_s2d1_execute);
2436 }
2437 
2438 /*
2439  * Same test but this time turning around the ABI version order: the first
2440  * layer does not handle LANDLOCK_ACCESS_FS_REFER.
2441  */
2442 TEST_F_FORK(layout1, refer_denied_by_default4)
2443 {
2444 	refer_denied_by_default(_metadata, layer_dir_s2d1_execute, EXDEV,
2445 				layer_dir_s1d1_refer);
2446 }
2447 
2448 /*
2449  * Tests walking through a denied root mount.
2450  */
2451 TEST_F_FORK(layout1, refer_mount_root_deny)
2452 {
2453 	int root_fd;
2454 
2455 	/* Creates a mount object from a non-mount point. */
2456 	set_cap(_metadata, CAP_SYS_ADMIN);
2457 	root_fd =
2458 		open_tree(AT_FDCWD, dir_s1d1,
2459 			  AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
2460 	clear_cap(_metadata, CAP_SYS_ADMIN);
2461 	ASSERT_LE(0, root_fd);
2462 
2463 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_MAKE_DIR, NULL);
2464 
2465 	/* Link denied by Landlock: EACCES. */
2466 	EXPECT_EQ(-1, linkat(root_fd, ".", root_fd, "does_not_exist", 0));
2467 	EXPECT_EQ(EACCES, errno);
2468 
2469 	/* renameat2() always returns EBUSY. */
2470 	EXPECT_EQ(-1, renameat2(root_fd, ".", root_fd, "does_not_exist", 0));
2471 	EXPECT_EQ(EBUSY, errno);
2472 
2473 	EXPECT_EQ(0, close(root_fd));
2474 }
2475 
2476 TEST_F_FORK(layout1, refer_part_mount_tree_is_allowed)
2477 {
2478 	const struct rule layer1[] = {
2479 		{
2480 			/* Parent mount point. */
2481 			.path = dir_s3d1,
2482 			.access = LANDLOCK_ACCESS_FS_REFER |
2483 				  LANDLOCK_ACCESS_FS_MAKE_REG,
2484 		},
2485 		{
2486 			/*
2487 			 * Removing the source file is allowed because its
2488 			 * access rights are already a superset of the
2489 			 * destination.
2490 			 */
2491 			.path = dir_s3d4,
2492 			.access = LANDLOCK_ACCESS_FS_REFER |
2493 				  LANDLOCK_ACCESS_FS_MAKE_REG |
2494 				  LANDLOCK_ACCESS_FS_REMOVE_FILE,
2495 		},
2496 		{},
2497 	};
2498 
2499 	ASSERT_EQ(0, unlink(file1_s3d3));
2500 	enforce_fs(_metadata,
2501 		   LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG |
2502 			   LANDLOCK_ACCESS_FS_REMOVE_FILE,
2503 		   layer1);
2504 
2505 	ASSERT_EQ(0, rename(file1_s3d4, file1_s3d3));
2506 }
2507 
2508 TEST_F_FORK(layout1, reparent_link)
2509 {
2510 	const struct rule layer1[] = {
2511 		{
2512 			.path = dir_s1d2,
2513 			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2514 		},
2515 		{
2516 			.path = dir_s1d3,
2517 			.access = LANDLOCK_ACCESS_FS_REFER,
2518 		},
2519 		{
2520 			.path = dir_s2d2,
2521 			.access = LANDLOCK_ACCESS_FS_REFER,
2522 		},
2523 		{
2524 			.path = dir_s2d3,
2525 			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2526 		},
2527 		{},
2528 	};
2529 
2530 	enforce_fs(_metadata,
2531 		   LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER,
2532 		   layer1);
2533 
2534 	ASSERT_EQ(0, unlink(file1_s1d1));
2535 	ASSERT_EQ(0, unlink(file1_s1d2));
2536 	ASSERT_EQ(0, unlink(file1_s1d3));
2537 
2538 	/* Denies linking because of missing MAKE_REG. */
2539 	ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
2540 	ASSERT_EQ(EACCES, errno);
2541 	/* Denies linking because of missing source and destination REFER. */
2542 	ASSERT_EQ(-1, link(file1_s2d1, file1_s1d2));
2543 	ASSERT_EQ(EXDEV, errno);
2544 	/* Denies linking because of missing source REFER. */
2545 	ASSERT_EQ(-1, link(file1_s2d1, file1_s1d3));
2546 	ASSERT_EQ(EXDEV, errno);
2547 
2548 	/* Denies linking because of missing MAKE_REG. */
2549 	ASSERT_EQ(-1, link(file1_s2d2, file1_s1d1));
2550 	ASSERT_EQ(EACCES, errno);
2551 	/* Denies linking because of missing destination REFER. */
2552 	ASSERT_EQ(-1, link(file1_s2d2, file1_s1d2));
2553 	ASSERT_EQ(EXDEV, errno);
2554 
2555 	/* Allows linking because of REFER and MAKE_REG. */
2556 	ASSERT_EQ(0, link(file1_s2d2, file1_s1d3));
2557 	ASSERT_EQ(0, unlink(file1_s2d2));
2558 	/* Reverse linking denied because of missing MAKE_REG. */
2559 	ASSERT_EQ(-1, link(file1_s1d3, file1_s2d2));
2560 	ASSERT_EQ(EACCES, errno);
2561 	ASSERT_EQ(0, unlink(file1_s2d3));
2562 	/* Checks reverse linking. */
2563 	ASSERT_EQ(0, link(file1_s1d3, file1_s2d3));
2564 	ASSERT_EQ(0, unlink(file1_s1d3));
2565 
2566 	/*
2567 	 * This is OK for a file link, but it should not be allowed for a
2568 	 * directory rename (because of the superset of access rights.
2569 	 */
2570 	ASSERT_EQ(0, link(file1_s2d3, file1_s1d3));
2571 	ASSERT_EQ(0, unlink(file1_s1d3));
2572 
2573 	ASSERT_EQ(-1, link(file2_s1d2, file1_s1d3));
2574 	ASSERT_EQ(EXDEV, errno);
2575 	ASSERT_EQ(-1, link(file2_s1d3, file1_s1d2));
2576 	ASSERT_EQ(EXDEV, errno);
2577 
2578 	ASSERT_EQ(0, link(file2_s1d2, file1_s1d2));
2579 	ASSERT_EQ(0, link(file2_s1d3, file1_s1d3));
2580 }
2581 
2582 TEST_F_FORK(layout1, reparent_rename)
2583 {
2584 	/* Same rules as for reparent_link. */
2585 	const struct rule layer1[] = {
2586 		{
2587 			.path = dir_s1d2,
2588 			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2589 		},
2590 		{
2591 			.path = dir_s1d3,
2592 			.access = LANDLOCK_ACCESS_FS_REFER,
2593 		},
2594 		{
2595 			.path = dir_s2d2,
2596 			.access = LANDLOCK_ACCESS_FS_REFER,
2597 		},
2598 		{
2599 			.path = dir_s2d3,
2600 			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2601 		},
2602 		{},
2603 	};
2604 
2605 	enforce_fs(_metadata,
2606 		   LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER,
2607 		   layer1);
2608 
2609 	ASSERT_EQ(0, unlink(file1_s1d2));
2610 	ASSERT_EQ(0, unlink(file1_s1d3));
2611 
2612 	/* Denies renaming because of missing MAKE_REG. */
2613 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file1_s1d1,
2614 				RENAME_EXCHANGE));
2615 	ASSERT_EQ(EACCES, errno);
2616 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file2_s1d1,
2617 				RENAME_EXCHANGE));
2618 	ASSERT_EQ(EACCES, errno);
2619 	ASSERT_EQ(0, unlink(file1_s1d1));
2620 	ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
2621 	ASSERT_EQ(EACCES, errno);
2622 	/* Even denies same file exchange. */
2623 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file2_s1d1,
2624 				RENAME_EXCHANGE));
2625 	ASSERT_EQ(EACCES, errno);
2626 
2627 	/* Denies renaming because of missing source and destination REFER. */
2628 	ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d2));
2629 	ASSERT_EQ(EXDEV, errno);
2630 	/*
2631 	 * Denies renaming because of missing MAKE_REG, source and destination
2632 	 * REFER.
2633 	 */
2634 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file2_s1d1,
2635 				RENAME_EXCHANGE));
2636 	ASSERT_EQ(EACCES, errno);
2637 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file1_s2d1,
2638 				RENAME_EXCHANGE));
2639 	ASSERT_EQ(EACCES, errno);
2640 
2641 	/* Denies renaming because of missing source REFER. */
2642 	ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
2643 	ASSERT_EQ(EXDEV, errno);
2644 	/* Denies renaming because of missing MAKE_REG. */
2645 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file2_s1d3,
2646 				RENAME_EXCHANGE));
2647 	ASSERT_EQ(EACCES, errno);
2648 
2649 	/* Denies renaming because of missing MAKE_REG. */
2650 	ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d1));
2651 	ASSERT_EQ(EACCES, errno);
2652 	/* Denies renaming because of missing destination REFER*/
2653 	ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d2));
2654 	ASSERT_EQ(EXDEV, errno);
2655 
2656 	/* Denies exchange because of one missing MAKE_REG. */
2657 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, file2_s1d3,
2658 				RENAME_EXCHANGE));
2659 	ASSERT_EQ(EACCES, errno);
2660 	/* Allows renaming because of REFER and MAKE_REG. */
2661 	ASSERT_EQ(0, rename(file1_s2d2, file1_s1d3));
2662 
2663 	/* Reverse renaming denied because of missing MAKE_REG. */
2664 	ASSERT_EQ(-1, rename(file1_s1d3, file1_s2d2));
2665 	ASSERT_EQ(EACCES, errno);
2666 	ASSERT_EQ(0, unlink(file1_s2d3));
2667 	ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2668 
2669 	/* Tests reverse renaming. */
2670 	ASSERT_EQ(0, rename(file1_s2d3, file1_s1d3));
2671 	ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s1d3,
2672 			       RENAME_EXCHANGE));
2673 	ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2674 
2675 	/*
2676 	 * This is OK for a file rename, but it should not be allowed for a
2677 	 * directory rename (because of the superset of access rights).
2678 	 */
2679 	ASSERT_EQ(0, rename(file1_s2d3, file1_s1d3));
2680 	ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2681 
2682 	/*
2683 	 * Tests superset restrictions applied to directories.  Not only the
2684 	 * dir_s2d3's parent (dir_s2d2) should be taken into account but also
2685 	 * access rights tied to dir_s2d3. dir_s2d2 is missing one access right
2686 	 * compared to dir_s1d3/file1_s1d3 (MAKE_REG) but it is provided
2687 	 * directly by the moved dir_s2d3.
2688 	 */
2689 	ASSERT_EQ(0, rename(dir_s2d3, file1_s1d3));
2690 	ASSERT_EQ(0, rename(file1_s1d3, dir_s2d3));
2691 	/*
2692 	 * The first rename is allowed but not the exchange because dir_s1d3's
2693 	 * parent (dir_s1d2) doesn't have REFER.
2694 	 */
2695 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, dir_s1d3,
2696 				RENAME_EXCHANGE));
2697 	ASSERT_EQ(EXDEV, errno);
2698 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, file1_s2d3,
2699 				RENAME_EXCHANGE));
2700 	ASSERT_EQ(EXDEV, errno);
2701 	ASSERT_EQ(-1, rename(file1_s2d3, dir_s1d3));
2702 	ASSERT_EQ(EXDEV, errno);
2703 
2704 	ASSERT_EQ(-1, rename(file2_s1d2, file1_s1d3));
2705 	ASSERT_EQ(EXDEV, errno);
2706 	ASSERT_EQ(-1, rename(file2_s1d3, file1_s1d2));
2707 	ASSERT_EQ(EXDEV, errno);
2708 
2709 	/* Renaming in the same directory is always allowed. */
2710 	ASSERT_EQ(0, rename(file2_s1d2, file1_s1d2));
2711 	ASSERT_EQ(0, rename(file2_s1d3, file1_s1d3));
2712 
2713 	ASSERT_EQ(0, unlink(file1_s1d2));
2714 	/* Denies because of missing source MAKE_REG and destination REFER. */
2715 	ASSERT_EQ(-1, rename(dir_s2d3, file1_s1d2));
2716 	ASSERT_EQ(EXDEV, errno);
2717 
2718 	ASSERT_EQ(0, unlink(file1_s1d3));
2719 	/* Denies because of missing source MAKE_REG and REFER. */
2720 	ASSERT_EQ(-1, rename(dir_s2d2, file1_s1d3));
2721 	ASSERT_EQ(EXDEV, errno);
2722 }
2723 
2724 static void
2725 reparent_exdev_layers_enforce1(struct __test_metadata *const _metadata)
2726 {
2727 	const struct rule layer1[] = {
2728 		{
2729 			.path = dir_s1d2,
2730 			.access = LANDLOCK_ACCESS_FS_REFER,
2731 		},
2732 		{
2733 			/* Interesting for the layer2 tests. */
2734 			.path = dir_s1d3,
2735 			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2736 		},
2737 		{
2738 			.path = dir_s2d2,
2739 			.access = LANDLOCK_ACCESS_FS_REFER,
2740 		},
2741 		{
2742 			.path = dir_s2d3,
2743 			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2744 		},
2745 		{},
2746 	};
2747 	enforce_fs(_metadata,
2748 		   LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER,
2749 		   layer1);
2750 }
2751 
2752 static void
2753 reparent_exdev_layers_enforce2(struct __test_metadata *const _metadata)
2754 {
2755 	const struct rule layer2[] = {
2756 		{
2757 			.path = dir_s2d3,
2758 			.access = LANDLOCK_ACCESS_FS_MAKE_DIR,
2759 		},
2760 		{},
2761 	};
2762 	/*
2763 	 * Same checks as before but with a second layer and a new MAKE_DIR
2764 	 * rule (and no explicit handling of REFER).
2765 	 */
2766 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_MAKE_DIR, layer2);
2767 }
2768 
2769 TEST_F_FORK(layout1, reparent_exdev_layers_rename1)
2770 {
2771 	ASSERT_EQ(0, unlink(file1_s2d2));
2772 	ASSERT_EQ(0, unlink(file1_s2d3));
2773 
2774 	reparent_exdev_layers_enforce1(_metadata);
2775 
2776 	/*
2777 	 * Moving the dir_s1d3 directory below dir_s2d2 is allowed by Landlock
2778 	 * because it doesn't inherit new access rights.
2779 	 */
2780 	ASSERT_EQ(0, rename(dir_s1d3, file1_s2d2));
2781 	ASSERT_EQ(0, rename(file1_s2d2, dir_s1d3));
2782 
2783 	/*
2784 	 * Moving the dir_s1d3 directory below dir_s2d3 is allowed, even if it
2785 	 * gets a new inherited access rights (MAKE_REG), because MAKE_REG is
2786 	 * already allowed for dir_s1d3.
2787 	 */
2788 	ASSERT_EQ(0, rename(dir_s1d3, file1_s2d3));
2789 	ASSERT_EQ(0, rename(file1_s2d3, dir_s1d3));
2790 
2791 	/*
2792 	 * However, moving the file1_s1d3 file below dir_s2d3 is allowed
2793 	 * because it cannot inherit MAKE_REG right (which is dedicated to
2794 	 * directories).
2795 	 */
2796 	ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2797 
2798 	reparent_exdev_layers_enforce2(_metadata);
2799 
2800 	/*
2801 	 * Moving the dir_s1d3 directory below dir_s2d2 is now denied because
2802 	 * MAKE_DIR is not tied to dir_s2d2.
2803 	 */
2804 	ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d2));
2805 	ASSERT_EQ(EACCES, errno);
2806 
2807 	/*
2808 	 * Moving the dir_s1d3 directory below dir_s2d3 is forbidden because it
2809 	 * would grants MAKE_REG and MAKE_DIR rights to it.
2810 	 */
2811 	ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d3));
2812 	ASSERT_EQ(EXDEV, errno);
2813 
2814 	/*
2815 	 * Moving the file2_s1d3 file below dir_s2d3 is denied because the
2816 	 * second layer does not handle REFER, which is always denied by
2817 	 * default.
2818 	 */
2819 	ASSERT_EQ(-1, rename(file2_s1d3, file1_s2d3));
2820 	ASSERT_EQ(EXDEV, errno);
2821 }
2822 
2823 TEST_F_FORK(layout1, reparent_exdev_layers_rename2)
2824 {
2825 	reparent_exdev_layers_enforce1(_metadata);
2826 
2827 	/* Checks EACCES predominance over EXDEV. */
2828 	ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d2));
2829 	ASSERT_EQ(EACCES, errno);
2830 	ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d2));
2831 	ASSERT_EQ(EACCES, errno);
2832 	ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d3));
2833 	ASSERT_EQ(EXDEV, errno);
2834 	/* Modify layout! */
2835 	ASSERT_EQ(0, rename(file1_s1d2, file1_s2d3));
2836 
2837 	/* Without REFER source. */
2838 	ASSERT_EQ(-1, rename(dir_s1d1, file1_s2d2));
2839 	ASSERT_EQ(EXDEV, errno);
2840 	ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d2));
2841 	ASSERT_EQ(EXDEV, errno);
2842 
2843 	reparent_exdev_layers_enforce2(_metadata);
2844 
2845 	/* Checks EACCES predominance over EXDEV. */
2846 	ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d2));
2847 	ASSERT_EQ(EACCES, errno);
2848 	/* Checks with actual file2_s1d2. */
2849 	ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d2));
2850 	ASSERT_EQ(EACCES, errno);
2851 	ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d3));
2852 	ASSERT_EQ(EXDEV, errno);
2853 	/*
2854 	 * Modifying the layout is now denied because the second layer does not
2855 	 * handle REFER, which is always denied by default.
2856 	 */
2857 	ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d3));
2858 	ASSERT_EQ(EXDEV, errno);
2859 
2860 	/* Without REFER source, EACCES wins over EXDEV. */
2861 	ASSERT_EQ(-1, rename(dir_s1d1, file1_s2d2));
2862 	ASSERT_EQ(EACCES, errno);
2863 	ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d2));
2864 	ASSERT_EQ(EACCES, errno);
2865 }
2866 
2867 TEST_F_FORK(layout1, reparent_exdev_layers_exchange1)
2868 {
2869 	const char *const dir_file1_s1d2 = file1_s1d2, *const dir_file2_s2d3 =
2870 							       file2_s2d3;
2871 
2872 	ASSERT_EQ(0, unlink(file1_s1d2));
2873 	ASSERT_EQ(0, mkdir(file1_s1d2, 0700));
2874 	ASSERT_EQ(0, unlink(file2_s2d3));
2875 	ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
2876 
2877 	reparent_exdev_layers_enforce1(_metadata);
2878 
2879 	/* Error predominance with file exchange: returns EXDEV and EACCES. */
2880 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file1_s2d3,
2881 				RENAME_EXCHANGE));
2882 	ASSERT_EQ(EACCES, errno);
2883 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d1,
2884 				RENAME_EXCHANGE));
2885 	ASSERT_EQ(EACCES, errno);
2886 
2887 	/*
2888 	 * Checks with directories which creation could be allowed, but denied
2889 	 * because of access rights that would be inherited.
2890 	 */
2891 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD,
2892 				dir_file2_s2d3, RENAME_EXCHANGE));
2893 	ASSERT_EQ(EXDEV, errno);
2894 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD,
2895 				dir_file1_s1d2, RENAME_EXCHANGE));
2896 	ASSERT_EQ(EXDEV, errno);
2897 
2898 	/* Checks with same access rights. */
2899 	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, dir_s2d3,
2900 			       RENAME_EXCHANGE));
2901 	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
2902 			       RENAME_EXCHANGE));
2903 
2904 	/* Checks with different (child-only) access rights. */
2905 	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_file1_s1d2,
2906 			       RENAME_EXCHANGE));
2907 	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD, dir_s2d3,
2908 			       RENAME_EXCHANGE));
2909 
2910 	/*
2911 	 * Checks that exchange between file and directory are consistent.
2912 	 *
2913 	 * Moving a file (file1_s2d2) to a directory which only grants more
2914 	 * directory-related access rights is allowed, and at the same time
2915 	 * moving a directory (dir_file2_s2d3) to another directory which
2916 	 * grants less access rights is allowed too.
2917 	 *
2918 	 * See layout1.reparent_exdev_layers_exchange3 for inverted arguments.
2919 	 */
2920 	ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
2921 			       RENAME_EXCHANGE));
2922 	/*
2923 	 * However, moving back the directory is denied because it would get
2924 	 * more access rights than the current state and because file creation
2925 	 * is forbidden (in dir_s2d2).
2926 	 */
2927 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
2928 				RENAME_EXCHANGE));
2929 	ASSERT_EQ(EACCES, errno);
2930 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
2931 				RENAME_EXCHANGE));
2932 	ASSERT_EQ(EACCES, errno);
2933 
2934 	reparent_exdev_layers_enforce2(_metadata);
2935 
2936 	/* Error predominance with file exchange: returns EXDEV and EACCES. */
2937 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file1_s2d3,
2938 				RENAME_EXCHANGE));
2939 	ASSERT_EQ(EACCES, errno);
2940 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d1,
2941 				RENAME_EXCHANGE));
2942 	ASSERT_EQ(EACCES, errno);
2943 
2944 	/* Checks with directories which creation is now denied. */
2945 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD,
2946 				dir_file2_s2d3, RENAME_EXCHANGE));
2947 	ASSERT_EQ(EACCES, errno);
2948 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD,
2949 				dir_file1_s1d2, RENAME_EXCHANGE));
2950 	ASSERT_EQ(EACCES, errno);
2951 
2952 	/* Checks with different (child-only) access rights. */
2953 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, dir_s2d3,
2954 				RENAME_EXCHANGE));
2955 	/* Denied because of MAKE_DIR. */
2956 	ASSERT_EQ(EACCES, errno);
2957 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
2958 				RENAME_EXCHANGE));
2959 	ASSERT_EQ(EACCES, errno);
2960 
2961 	/* Checks with different (child-only) access rights. */
2962 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_file1_s1d2,
2963 				RENAME_EXCHANGE));
2964 	/* Denied because of MAKE_DIR. */
2965 	ASSERT_EQ(EACCES, errno);
2966 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD, dir_s2d3,
2967 				RENAME_EXCHANGE));
2968 	ASSERT_EQ(EACCES, errno);
2969 
2970 	/* See layout1.reparent_exdev_layers_exchange2 for complement. */
2971 }
2972 
2973 TEST_F_FORK(layout1, reparent_exdev_layers_exchange2)
2974 {
2975 	const char *const dir_file2_s2d3 = file2_s2d3;
2976 
2977 	ASSERT_EQ(0, unlink(file2_s2d3));
2978 	ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
2979 
2980 	reparent_exdev_layers_enforce1(_metadata);
2981 	reparent_exdev_layers_enforce2(_metadata);
2982 
2983 	/* Checks that exchange between file and directory are consistent. */
2984 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
2985 				RENAME_EXCHANGE));
2986 	ASSERT_EQ(EACCES, errno);
2987 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
2988 				RENAME_EXCHANGE));
2989 	ASSERT_EQ(EACCES, errno);
2990 }
2991 
2992 TEST_F_FORK(layout1, reparent_exdev_layers_exchange3)
2993 {
2994 	const char *const dir_file2_s2d3 = file2_s2d3;
2995 
2996 	ASSERT_EQ(0, unlink(file2_s2d3));
2997 	ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
2998 
2999 	reparent_exdev_layers_enforce1(_metadata);
3000 
3001 	/*
3002 	 * Checks that exchange between file and directory are consistent,
3003 	 * including with inverted arguments (see
3004 	 * layout1.reparent_exdev_layers_exchange1).
3005 	 */
3006 	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
3007 			       RENAME_EXCHANGE));
3008 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
3009 				RENAME_EXCHANGE));
3010 	ASSERT_EQ(EACCES, errno);
3011 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
3012 				RENAME_EXCHANGE));
3013 	ASSERT_EQ(EACCES, errno);
3014 }
3015 
3016 TEST_F_FORK(layout1, reparent_remove)
3017 {
3018 	const struct rule layer1[] = {
3019 		{
3020 			.path = dir_s1d1,
3021 			.access = LANDLOCK_ACCESS_FS_REFER |
3022 				  LANDLOCK_ACCESS_FS_REMOVE_DIR,
3023 		},
3024 		{
3025 			.path = dir_s1d2,
3026 			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
3027 		},
3028 		{
3029 			.path = dir_s2d1,
3030 			.access = LANDLOCK_ACCESS_FS_REFER |
3031 				  LANDLOCK_ACCESS_FS_REMOVE_FILE,
3032 		},
3033 		{},
3034 	};
3035 
3036 	enforce_fs(_metadata,
3037 		   LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_REMOVE_DIR |
3038 			   LANDLOCK_ACCESS_FS_REMOVE_FILE,
3039 		   layer1);
3040 
3041 	/* Access denied because of wrong/swapped remove file/dir. */
3042 	ASSERT_EQ(-1, rename(file1_s1d1, dir_s2d2));
3043 	ASSERT_EQ(EACCES, errno);
3044 	ASSERT_EQ(-1, rename(dir_s2d2, file1_s1d1));
3045 	ASSERT_EQ(EACCES, errno);
3046 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s2d2,
3047 				RENAME_EXCHANGE));
3048 	ASSERT_EQ(EACCES, errno);
3049 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s2d3,
3050 				RENAME_EXCHANGE));
3051 	ASSERT_EQ(EACCES, errno);
3052 
3053 	/* Access allowed thanks to the matching rights. */
3054 	ASSERT_EQ(-1, rename(file1_s2d1, dir_s1d2));
3055 	ASSERT_EQ(EISDIR, errno);
3056 	ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d1));
3057 	ASSERT_EQ(ENOTDIR, errno);
3058 	ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d1));
3059 	ASSERT_EQ(ENOTDIR, errno);
3060 	ASSERT_EQ(0, unlink(file1_s2d1));
3061 	ASSERT_EQ(0, unlink(file1_s1d3));
3062 	ASSERT_EQ(0, unlink(file2_s1d3));
3063 	ASSERT_EQ(0, rename(dir_s1d3, file1_s2d1));
3064 
3065 	/* Effectively removes a file and a directory by exchanging them. */
3066 	ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
3067 	ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
3068 			       RENAME_EXCHANGE));
3069 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
3070 				RENAME_EXCHANGE));
3071 	ASSERT_EQ(EACCES, errno);
3072 }
3073 
3074 TEST_F_FORK(layout1, reparent_dom_superset)
3075 {
3076 	const struct rule layer1[] = {
3077 		{
3078 			.path = dir_s1d2,
3079 			.access = LANDLOCK_ACCESS_FS_REFER,
3080 		},
3081 		{
3082 			.path = file1_s1d2,
3083 			.access = LANDLOCK_ACCESS_FS_EXECUTE,
3084 		},
3085 		{
3086 			.path = dir_s1d3,
3087 			.access = LANDLOCK_ACCESS_FS_MAKE_SOCK |
3088 				  LANDLOCK_ACCESS_FS_EXECUTE,
3089 		},
3090 		{
3091 			.path = dir_s2d2,
3092 			.access = LANDLOCK_ACCESS_FS_REFER |
3093 				  LANDLOCK_ACCESS_FS_EXECUTE |
3094 				  LANDLOCK_ACCESS_FS_MAKE_SOCK,
3095 		},
3096 		{
3097 			.path = dir_s2d3,
3098 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
3099 				  LANDLOCK_ACCESS_FS_MAKE_FIFO,
3100 		},
3101 		{},
3102 	};
3103 
3104 	enforce_fs(_metadata,
3105 		   LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_EXECUTE |
3106 			   LANDLOCK_ACCESS_FS_MAKE_SOCK |
3107 			   LANDLOCK_ACCESS_FS_READ_FILE |
3108 			   LANDLOCK_ACCESS_FS_MAKE_FIFO,
3109 		   layer1);
3110 
3111 	ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d1));
3112 	ASSERT_EQ(EXDEV, errno);
3113 	/*
3114 	 * Moving file1_s1d2 beneath dir_s2d3 would grant it the READ_FILE
3115 	 * access right.
3116 	 */
3117 	ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d3));
3118 	ASSERT_EQ(EXDEV, errno);
3119 	/*
3120 	 * Moving file1_s1d2 should be allowed even if dir_s2d2 grants a
3121 	 * superset of access rights compared to dir_s1d2, because file1_s1d2
3122 	 * already has these access rights anyway.
3123 	 */
3124 	ASSERT_EQ(0, rename(file1_s1d2, file1_s2d2));
3125 	ASSERT_EQ(0, rename(file1_s2d2, file1_s1d2));
3126 
3127 	ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d1));
3128 	ASSERT_EQ(EXDEV, errno);
3129 	/*
3130 	 * Moving dir_s1d3 beneath dir_s2d3 would grant it the MAKE_FIFO access
3131 	 * right.
3132 	 */
3133 	ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d3));
3134 	ASSERT_EQ(EXDEV, errno);
3135 	/*
3136 	 * Moving dir_s1d3 should be allowed even if dir_s2d2 grants a superset
3137 	 * of access rights compared to dir_s1d2, because dir_s1d3 already has
3138 	 * these access rights anyway.
3139 	 */
3140 	ASSERT_EQ(0, rename(dir_s1d3, file1_s2d2));
3141 	ASSERT_EQ(0, rename(file1_s2d2, dir_s1d3));
3142 
3143 	/*
3144 	 * Moving file1_s2d3 beneath dir_s1d2 is allowed, but moving it back
3145 	 * will be denied because the new inherited access rights from dir_s1d2
3146 	 * will be less than the destination (original) dir_s2d3.  This is a
3147 	 * sinkhole scenario where we cannot move back files or directories.
3148 	 */
3149 	ASSERT_EQ(0, rename(file1_s2d3, file2_s1d2));
3150 	ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d3));
3151 	ASSERT_EQ(EXDEV, errno);
3152 	ASSERT_EQ(0, unlink(file2_s1d2));
3153 	ASSERT_EQ(0, unlink(file2_s2d3));
3154 	/*
3155 	 * Checks similar directory one-way move: dir_s2d3 loses EXECUTE and
3156 	 * MAKE_SOCK which were inherited from dir_s1d3.
3157 	 */
3158 	ASSERT_EQ(0, rename(dir_s2d3, file2_s1d2));
3159 	ASSERT_EQ(-1, rename(file2_s1d2, dir_s2d3));
3160 	ASSERT_EQ(EXDEV, errno);
3161 }
3162 
3163 TEST_F_FORK(layout1, remove_dir)
3164 {
3165 	const struct rule rules[] = {
3166 		{
3167 			.path = dir_s1d2,
3168 			.access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
3169 		},
3170 		{},
3171 	};
3172 
3173 	ASSERT_EQ(0, unlink(file1_s1d1));
3174 	ASSERT_EQ(0, unlink(file1_s1d2));
3175 	ASSERT_EQ(0, unlink(file1_s1d3));
3176 	ASSERT_EQ(0, unlink(file2_s1d3));
3177 
3178 	enforce_fs(_metadata, rules[0].access, rules);
3179 
3180 	ASSERT_EQ(0, rmdir(dir_s1d3));
3181 	ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
3182 	ASSERT_EQ(0, unlinkat(AT_FDCWD, dir_s1d3, AT_REMOVEDIR));
3183 
3184 	/* dir_s1d2 itself cannot be removed. */
3185 	ASSERT_EQ(-1, rmdir(dir_s1d2));
3186 	ASSERT_EQ(EACCES, errno);
3187 	ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d2, AT_REMOVEDIR));
3188 	ASSERT_EQ(EACCES, errno);
3189 	ASSERT_EQ(-1, rmdir(dir_s1d1));
3190 	ASSERT_EQ(EACCES, errno);
3191 	ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d1, AT_REMOVEDIR));
3192 	ASSERT_EQ(EACCES, errno);
3193 }
3194 
3195 TEST_F_FORK(layout1, remove_file)
3196 {
3197 	const struct rule rules[] = {
3198 		{
3199 			.path = dir_s1d2,
3200 			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
3201 		},
3202 		{},
3203 	};
3204 
3205 	enforce_fs(_metadata, rules[0].access, rules);
3206 
3207 	ASSERT_EQ(-1, unlink(file1_s1d1));
3208 	ASSERT_EQ(EACCES, errno);
3209 	ASSERT_EQ(-1, unlinkat(AT_FDCWD, file1_s1d1, 0));
3210 	ASSERT_EQ(EACCES, errno);
3211 	ASSERT_EQ(0, unlink(file1_s1d2));
3212 	ASSERT_EQ(0, unlinkat(AT_FDCWD, file1_s1d3, 0));
3213 }
3214 
3215 static void test_make_file(struct __test_metadata *const _metadata,
3216 			   const __u64 access, const mode_t mode,
3217 			   const dev_t dev)
3218 {
3219 	const struct rule rules[] = {
3220 		{
3221 			.path = dir_s1d2,
3222 			.access = access,
3223 		},
3224 		{},
3225 	};
3226 
3227 	ASSERT_EQ(0, unlink(file1_s1d1));
3228 	ASSERT_EQ(0, unlink(file2_s1d1));
3229 	ASSERT_EQ(0, mknod(file2_s1d1, mode | 0400, dev))
3230 	{
3231 		TH_LOG("Failed to make file \"%s\": %s", file2_s1d1,
3232 		       strerror(errno));
3233 	};
3234 
3235 	ASSERT_EQ(0, unlink(file1_s1d2));
3236 	ASSERT_EQ(0, unlink(file2_s1d2));
3237 
3238 	ASSERT_EQ(0, unlink(file1_s1d3));
3239 	ASSERT_EQ(0, unlink(file2_s1d3));
3240 
3241 	enforce_fs(_metadata, access, rules);
3242 
3243 	ASSERT_EQ(-1, mknod(file1_s1d1, mode | 0400, dev));
3244 	ASSERT_EQ(EACCES, errno);
3245 	ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
3246 	ASSERT_EQ(EACCES, errno);
3247 	ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
3248 	ASSERT_EQ(EACCES, errno);
3249 
3250 	ASSERT_EQ(0, mknod(file1_s1d2, mode | 0400, dev))
3251 	{
3252 		TH_LOG("Failed to make file \"%s\": %s", file1_s1d2,
3253 		       strerror(errno));
3254 	};
3255 	ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
3256 	ASSERT_EQ(0, unlink(file2_s1d2));
3257 	ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
3258 
3259 	ASSERT_EQ(0, mknod(file1_s1d3, mode | 0400, dev));
3260 	ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
3261 	ASSERT_EQ(0, unlink(file2_s1d3));
3262 	ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
3263 }
3264 
3265 TEST_F_FORK(layout1, make_char)
3266 {
3267 	/* Creates a /dev/null device. */
3268 	set_cap(_metadata, CAP_MKNOD);
3269 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_CHAR, S_IFCHR,
3270 		       makedev(1, 3));
3271 }
3272 
3273 TEST_F_FORK(layout1, make_block)
3274 {
3275 	/* Creates a /dev/loop0 device. */
3276 	set_cap(_metadata, CAP_MKNOD);
3277 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_BLOCK, S_IFBLK,
3278 		       makedev(7, 0));
3279 }
3280 
3281 TEST_F_FORK(layout1, make_reg_1)
3282 {
3283 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, S_IFREG, 0);
3284 }
3285 
3286 TEST_F_FORK(layout1, make_reg_2)
3287 {
3288 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, 0, 0);
3289 }
3290 
3291 TEST_F_FORK(layout1, make_sock)
3292 {
3293 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_SOCK, S_IFSOCK, 0);
3294 }
3295 
3296 TEST_F_FORK(layout1, make_fifo)
3297 {
3298 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_FIFO, S_IFIFO, 0);
3299 }
3300 
3301 TEST_F_FORK(layout1, make_sym)
3302 {
3303 	const struct rule rules[] = {
3304 		{
3305 			.path = dir_s1d2,
3306 			.access = LANDLOCK_ACCESS_FS_MAKE_SYM,
3307 		},
3308 		{},
3309 	};
3310 
3311 	ASSERT_EQ(0, unlink(file1_s1d1));
3312 	ASSERT_EQ(0, unlink(file2_s1d1));
3313 	ASSERT_EQ(0, symlink("none", file2_s1d1));
3314 
3315 	ASSERT_EQ(0, unlink(file1_s1d2));
3316 	ASSERT_EQ(0, unlink(file2_s1d2));
3317 
3318 	ASSERT_EQ(0, unlink(file1_s1d3));
3319 	ASSERT_EQ(0, unlink(file2_s1d3));
3320 
3321 	enforce_fs(_metadata, rules[0].access, rules);
3322 
3323 	ASSERT_EQ(-1, symlink("none", file1_s1d1));
3324 	ASSERT_EQ(EACCES, errno);
3325 	ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
3326 	ASSERT_EQ(EACCES, errno);
3327 	ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
3328 	ASSERT_EQ(EACCES, errno);
3329 
3330 	ASSERT_EQ(0, symlink("none", file1_s1d2));
3331 	ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
3332 	ASSERT_EQ(0, unlink(file2_s1d2));
3333 	ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
3334 
3335 	ASSERT_EQ(0, symlink("none", file1_s1d3));
3336 	ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
3337 	ASSERT_EQ(0, unlink(file2_s1d3));
3338 	ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
3339 }
3340 
3341 TEST_F_FORK(layout1, make_dir)
3342 {
3343 	const struct rule rules[] = {
3344 		{
3345 			.path = dir_s1d2,
3346 			.access = LANDLOCK_ACCESS_FS_MAKE_DIR,
3347 		},
3348 		{},
3349 	};
3350 
3351 	ASSERT_EQ(0, unlink(file1_s1d1));
3352 	ASSERT_EQ(0, unlink(file1_s1d2));
3353 	ASSERT_EQ(0, unlink(file1_s1d3));
3354 
3355 	enforce_fs(_metadata, rules[0].access, rules);
3356 
3357 	/* Uses file_* as directory names. */
3358 	ASSERT_EQ(-1, mkdir(file1_s1d1, 0700));
3359 	ASSERT_EQ(EACCES, errno);
3360 	ASSERT_EQ(0, mkdir(file1_s1d2, 0700));
3361 	ASSERT_EQ(0, mkdir(file1_s1d3, 0700));
3362 }
3363 
3364 static int open_proc_fd(struct __test_metadata *const _metadata, const int fd,
3365 			const int open_flags)
3366 {
3367 	static const char path_template[] = "/proc/self/fd/%d";
3368 	char procfd_path[sizeof(path_template) + 10];
3369 	const int procfd_path_size =
3370 		snprintf(procfd_path, sizeof(procfd_path), path_template, fd);
3371 
3372 	ASSERT_LT(procfd_path_size, sizeof(procfd_path));
3373 	return open(procfd_path, open_flags);
3374 }
3375 
3376 TEST_F_FORK(layout1, proc_unlinked_file)
3377 {
3378 	const struct rule rules[] = {
3379 		{
3380 			.path = file1_s1d2,
3381 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
3382 		},
3383 		{},
3384 	};
3385 	int reg_fd, proc_fd;
3386 
3387 	enforce_fs(_metadata,
3388 		   LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE,
3389 		   rules);
3390 
3391 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
3392 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
3393 	reg_fd = open(file1_s1d2, O_RDONLY | O_CLOEXEC);
3394 	ASSERT_LE(0, reg_fd);
3395 	ASSERT_EQ(0, unlink(file1_s1d2));
3396 
3397 	proc_fd = open_proc_fd(_metadata, reg_fd, O_RDONLY | O_CLOEXEC);
3398 	ASSERT_LE(0, proc_fd);
3399 	ASSERT_EQ(0, close(proc_fd));
3400 
3401 	proc_fd = open_proc_fd(_metadata, reg_fd, O_RDWR | O_CLOEXEC);
3402 	ASSERT_EQ(-1, proc_fd)
3403 	{
3404 		TH_LOG("Successfully opened /proc/self/fd/%d: %s", reg_fd,
3405 		       strerror(errno));
3406 	}
3407 	ASSERT_EQ(EACCES, errno);
3408 
3409 	ASSERT_EQ(0, close(reg_fd));
3410 }
3411 
3412 TEST_F_FORK(layout1, proc_pipe)
3413 {
3414 	int proc_fd;
3415 	int pipe_fds[2];
3416 	char buf = '\0';
3417 	const struct rule rules[] = {
3418 		{
3419 			.path = dir_s1d2,
3420 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
3421 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
3422 		},
3423 		{},
3424 	};
3425 
3426 	/* Limits read and write access to files tied to the filesystem. */
3427 	enforce_fs(_metadata, rules[0].access, rules);
3428 
3429 	/* Checks enforcement for normal files. */
3430 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
3431 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
3432 
3433 	/* Checks access to pipes through FD. */
3434 	ASSERT_EQ(0, pipe2(pipe_fds, O_CLOEXEC));
3435 	ASSERT_EQ(1, write(pipe_fds[1], ".", 1))
3436 	{
3437 		TH_LOG("Failed to write in pipe: %s", strerror(errno));
3438 	}
3439 	ASSERT_EQ(1, read(pipe_fds[0], &buf, 1));
3440 	ASSERT_EQ('.', buf);
3441 
3442 	/* Checks write access to pipe through /proc/self/fd . */
3443 	proc_fd = open_proc_fd(_metadata, pipe_fds[1], O_WRONLY | O_CLOEXEC);
3444 	ASSERT_LE(0, proc_fd);
3445 	ASSERT_EQ(1, write(proc_fd, ".", 1))
3446 	{
3447 		TH_LOG("Failed to write through /proc/self/fd/%d: %s",
3448 		       pipe_fds[1], strerror(errno));
3449 	}
3450 	ASSERT_EQ(0, close(proc_fd));
3451 
3452 	/* Checks read access to pipe through /proc/self/fd . */
3453 	proc_fd = open_proc_fd(_metadata, pipe_fds[0], O_RDONLY | O_CLOEXEC);
3454 	ASSERT_LE(0, proc_fd);
3455 	buf = '\0';
3456 	ASSERT_EQ(1, read(proc_fd, &buf, 1))
3457 	{
3458 		TH_LOG("Failed to read through /proc/self/fd/%d: %s",
3459 		       pipe_fds[1], strerror(errno));
3460 	}
3461 	ASSERT_EQ(0, close(proc_fd));
3462 
3463 	ASSERT_EQ(0, close(pipe_fds[0]));
3464 	ASSERT_EQ(0, close(pipe_fds[1]));
3465 }
3466 
3467 /* Invokes truncate(2) and returns its errno or 0. */
3468 static int test_truncate(const char *const path)
3469 {
3470 	if (truncate(path, 10) < 0)
3471 		return errno;
3472 	return 0;
3473 }
3474 
3475 /*
3476  * Invokes creat(2) and returns its errno or 0.
3477  * Closes the opened file descriptor on success.
3478  */
3479 static int test_creat(const char *const path)
3480 {
3481 	int fd = creat(path, 0600);
3482 
3483 	if (fd < 0)
3484 		return errno;
3485 
3486 	/*
3487 	 * Mixing error codes from close(2) and creat(2) should not lead to any
3488 	 * (access type) confusion for this test.
3489 	 */
3490 	if (close(fd) < 0)
3491 		return errno;
3492 	return 0;
3493 }
3494 
3495 /*
3496  * Exercises file truncation when it's not restricted,
3497  * as it was the case before LANDLOCK_ACCESS_FS_TRUNCATE existed.
3498  */
3499 TEST_F_FORK(layout1, truncate_unhandled)
3500 {
3501 	const char *const file_r = file1_s1d1;
3502 	const char *const file_w = file2_s1d1;
3503 	const char *const file_none = file1_s1d2;
3504 	const struct rule rules[] = {
3505 		{
3506 			.path = file_r,
3507 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
3508 		},
3509 		{
3510 			.path = file_w,
3511 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3512 		},
3513 		/* Implicitly: No rights for file_none. */
3514 		{},
3515 	};
3516 
3517 	/* Enables Landlock. */
3518 	enforce_fs(_metadata,
3519 		   LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE,
3520 		   rules);
3521 
3522 	/*
3523 	 * Checks read right: truncate and open with O_TRUNC work, unless the
3524 	 * file is attempted to be opened for writing.
3525 	 */
3526 	EXPECT_EQ(0, test_truncate(file_r));
3527 	EXPECT_EQ(0, test_open(file_r, O_RDONLY | O_TRUNC));
3528 	EXPECT_EQ(EACCES, test_open(file_r, O_WRONLY | O_TRUNC));
3529 	EXPECT_EQ(EACCES, test_creat(file_r));
3530 
3531 	/*
3532 	 * Checks write right: truncate and open with O_TRUNC work, unless the
3533 	 * file is attempted to be opened for reading.
3534 	 */
3535 	EXPECT_EQ(0, test_truncate(file_w));
3536 	EXPECT_EQ(EACCES, test_open(file_w, O_RDONLY | O_TRUNC));
3537 	EXPECT_EQ(0, test_open(file_w, O_WRONLY | O_TRUNC));
3538 	EXPECT_EQ(0, test_creat(file_w));
3539 
3540 	/*
3541 	 * Checks "no rights" case: truncate works but all open attempts fail,
3542 	 * including creat.
3543 	 */
3544 	EXPECT_EQ(0, test_truncate(file_none));
3545 	EXPECT_EQ(EACCES, test_open(file_none, O_RDONLY | O_TRUNC));
3546 	EXPECT_EQ(EACCES, test_open(file_none, O_WRONLY | O_TRUNC));
3547 	EXPECT_EQ(EACCES, test_creat(file_none));
3548 }
3549 
3550 TEST_F_FORK(layout1, truncate)
3551 {
3552 	const char *const file_rwt = file1_s1d1;
3553 	const char *const file_rw = file2_s1d1;
3554 	const char *const file_rt = file1_s1d2;
3555 	const char *const file_t = file2_s1d2;
3556 	const char *const file_none = file1_s1d3;
3557 	const char *const dir_t = dir_s2d1;
3558 	const char *const file_in_dir_t = file1_s2d1;
3559 	const char *const dir_w = dir_s3d1;
3560 	const char *const file_in_dir_w = file1_s3d1;
3561 	const struct rule rules[] = {
3562 		{
3563 			.path = file_rwt,
3564 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
3565 				  LANDLOCK_ACCESS_FS_WRITE_FILE |
3566 				  LANDLOCK_ACCESS_FS_TRUNCATE,
3567 		},
3568 		{
3569 			.path = file_rw,
3570 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
3571 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
3572 		},
3573 		{
3574 			.path = file_rt,
3575 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
3576 				  LANDLOCK_ACCESS_FS_TRUNCATE,
3577 		},
3578 		{
3579 			.path = file_t,
3580 			.access = LANDLOCK_ACCESS_FS_TRUNCATE,
3581 		},
3582 		/* Implicitly: No access rights for file_none. */
3583 		{
3584 			.path = dir_t,
3585 			.access = LANDLOCK_ACCESS_FS_TRUNCATE,
3586 		},
3587 		{
3588 			.path = dir_w,
3589 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3590 		},
3591 		{},
3592 	};
3593 
3594 	/* Enables Landlock. */
3595 	enforce_fs(_metadata,
3596 		   LANDLOCK_ACCESS_FS_READ_FILE |
3597 			   LANDLOCK_ACCESS_FS_WRITE_FILE |
3598 			   LANDLOCK_ACCESS_FS_TRUNCATE,
3599 		   rules);
3600 
3601 	/* Checks read, write and truncate rights: truncation works. */
3602 	EXPECT_EQ(0, test_truncate(file_rwt));
3603 	EXPECT_EQ(0, test_open(file_rwt, O_RDONLY | O_TRUNC));
3604 	EXPECT_EQ(0, test_open(file_rwt, O_WRONLY | O_TRUNC));
3605 
3606 	/* Checks read and write rights: no truncate variant works. */
3607 	EXPECT_EQ(EACCES, test_truncate(file_rw));
3608 	EXPECT_EQ(EACCES, test_open(file_rw, O_RDONLY | O_TRUNC));
3609 	EXPECT_EQ(EACCES, test_open(file_rw, O_WRONLY | O_TRUNC));
3610 
3611 	/*
3612 	 * Checks read and truncate rights: truncation works.
3613 	 *
3614 	 * Note: Files can get truncated using open() even with O_RDONLY.
3615 	 */
3616 	EXPECT_EQ(0, test_truncate(file_rt));
3617 	EXPECT_EQ(0, test_open(file_rt, O_RDONLY | O_TRUNC));
3618 	EXPECT_EQ(EACCES, test_open(file_rt, O_WRONLY | O_TRUNC));
3619 
3620 	/* Checks truncate right: truncate works, but can't open file. */
3621 	EXPECT_EQ(0, test_truncate(file_t));
3622 	EXPECT_EQ(EACCES, test_open(file_t, O_RDONLY | O_TRUNC));
3623 	EXPECT_EQ(EACCES, test_open(file_t, O_WRONLY | O_TRUNC));
3624 
3625 	/* Checks "no rights" case: No form of truncation works. */
3626 	EXPECT_EQ(EACCES, test_truncate(file_none));
3627 	EXPECT_EQ(EACCES, test_open(file_none, O_RDONLY | O_TRUNC));
3628 	EXPECT_EQ(EACCES, test_open(file_none, O_WRONLY | O_TRUNC));
3629 
3630 	/*
3631 	 * Checks truncate right on directory: truncate works on contained
3632 	 * files.
3633 	 */
3634 	EXPECT_EQ(0, test_truncate(file_in_dir_t));
3635 	EXPECT_EQ(EACCES, test_open(file_in_dir_t, O_RDONLY | O_TRUNC));
3636 	EXPECT_EQ(EACCES, test_open(file_in_dir_t, O_WRONLY | O_TRUNC));
3637 
3638 	/*
3639 	 * Checks creat in dir_w: This requires the truncate right when
3640 	 * overwriting an existing file, but does not require it when the file
3641 	 * is new.
3642 	 */
3643 	EXPECT_EQ(EACCES, test_creat(file_in_dir_w));
3644 
3645 	ASSERT_EQ(0, unlink(file_in_dir_w));
3646 	EXPECT_EQ(0, test_creat(file_in_dir_w));
3647 }
3648 
3649 /* Invokes ftruncate(2) and returns its errno or 0. */
3650 static int test_ftruncate(int fd)
3651 {
3652 	if (ftruncate(fd, 10) < 0)
3653 		return errno;
3654 	return 0;
3655 }
3656 
3657 TEST_F_FORK(layout1, ftruncate)
3658 {
3659 	/*
3660 	 * This test opens a new file descriptor at different stages of
3661 	 * Landlock restriction:
3662 	 *
3663 	 * without restriction:                    ftruncate works
3664 	 * something else but truncate restricted: ftruncate works
3665 	 * truncate restricted and permitted:      ftruncate works
3666 	 * truncate restricted and not permitted:  ftruncate fails
3667 	 *
3668 	 * Whether this works or not is expected to depend on the time when the
3669 	 * FD was opened, not to depend on the time when ftruncate() was
3670 	 * called.
3671 	 */
3672 	const char *const path = file1_s1d1;
3673 	const __u64 handled1 = LANDLOCK_ACCESS_FS_READ_FILE |
3674 			       LANDLOCK_ACCESS_FS_WRITE_FILE;
3675 	const struct rule layer1[] = {
3676 		{
3677 			.path = path,
3678 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3679 		},
3680 		{},
3681 	};
3682 	const __u64 handled2 = LANDLOCK_ACCESS_FS_TRUNCATE;
3683 	const struct rule layer2[] = {
3684 		{
3685 			.path = path,
3686 			.access = LANDLOCK_ACCESS_FS_TRUNCATE,
3687 		},
3688 		{},
3689 	};
3690 	const __u64 handled3 = LANDLOCK_ACCESS_FS_TRUNCATE |
3691 			       LANDLOCK_ACCESS_FS_WRITE_FILE;
3692 	const struct rule layer3[] = {
3693 		{
3694 			.path = path,
3695 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3696 		},
3697 		{},
3698 	};
3699 	int fd_layer0, fd_layer1, fd_layer2, fd_layer3;
3700 
3701 	fd_layer0 = open(path, O_WRONLY);
3702 	EXPECT_EQ(0, test_ftruncate(fd_layer0));
3703 
3704 	enforce_fs(_metadata, handled1, layer1);
3705 
3706 	fd_layer1 = open(path, O_WRONLY);
3707 	EXPECT_EQ(0, test_ftruncate(fd_layer0));
3708 	EXPECT_EQ(0, test_ftruncate(fd_layer1));
3709 
3710 	enforce_fs(_metadata, handled2, layer2);
3711 
3712 	fd_layer2 = open(path, O_WRONLY);
3713 	EXPECT_EQ(0, test_ftruncate(fd_layer0));
3714 	EXPECT_EQ(0, test_ftruncate(fd_layer1));
3715 	EXPECT_EQ(0, test_ftruncate(fd_layer2));
3716 
3717 	enforce_fs(_metadata, handled3, layer3);
3718 
3719 	fd_layer3 = open(path, O_WRONLY);
3720 	EXPECT_EQ(0, test_ftruncate(fd_layer0));
3721 	EXPECT_EQ(0, test_ftruncate(fd_layer1));
3722 	EXPECT_EQ(0, test_ftruncate(fd_layer2));
3723 	EXPECT_EQ(EACCES, test_ftruncate(fd_layer3));
3724 
3725 	ASSERT_EQ(0, close(fd_layer0));
3726 	ASSERT_EQ(0, close(fd_layer1));
3727 	ASSERT_EQ(0, close(fd_layer2));
3728 	ASSERT_EQ(0, close(fd_layer3));
3729 }
3730 
3731 /* clang-format off */
3732 FIXTURE(ftruncate) {};
3733 /* clang-format on */
3734 
3735 FIXTURE_SETUP(ftruncate)
3736 {
3737 	prepare_layout(_metadata);
3738 	create_file(_metadata, file1_s1d1);
3739 }
3740 
3741 FIXTURE_TEARDOWN_PARENT(ftruncate)
3742 {
3743 	EXPECT_EQ(0, remove_path(file1_s1d1));
3744 	cleanup_layout(_metadata);
3745 }
3746 
3747 FIXTURE_VARIANT(ftruncate)
3748 {
3749 	const __u64 handled;
3750 	const __u64 allowed;
3751 	const int expected_open_result;
3752 	const int expected_ftruncate_result;
3753 };
3754 
3755 /* clang-format off */
3756 FIXTURE_VARIANT_ADD(ftruncate, w_w) {
3757 	/* clang-format on */
3758 	.handled = LANDLOCK_ACCESS_FS_WRITE_FILE,
3759 	.allowed = LANDLOCK_ACCESS_FS_WRITE_FILE,
3760 	.expected_open_result = 0,
3761 	.expected_ftruncate_result = 0,
3762 };
3763 
3764 /* clang-format off */
3765 FIXTURE_VARIANT_ADD(ftruncate, t_t) {
3766 	/* clang-format on */
3767 	.handled = LANDLOCK_ACCESS_FS_TRUNCATE,
3768 	.allowed = LANDLOCK_ACCESS_FS_TRUNCATE,
3769 	.expected_open_result = 0,
3770 	.expected_ftruncate_result = 0,
3771 };
3772 
3773 /* clang-format off */
3774 FIXTURE_VARIANT_ADD(ftruncate, wt_w) {
3775 	/* clang-format on */
3776 	.handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
3777 	.allowed = LANDLOCK_ACCESS_FS_WRITE_FILE,
3778 	.expected_open_result = 0,
3779 	.expected_ftruncate_result = EACCES,
3780 };
3781 
3782 /* clang-format off */
3783 FIXTURE_VARIANT_ADD(ftruncate, wt_wt) {
3784 	/* clang-format on */
3785 	.handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
3786 	.allowed = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
3787 	.expected_open_result = 0,
3788 	.expected_ftruncate_result = 0,
3789 };
3790 
3791 /* clang-format off */
3792 FIXTURE_VARIANT_ADD(ftruncate, wt_t) {
3793 	/* clang-format on */
3794 	.handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
3795 	.allowed = LANDLOCK_ACCESS_FS_TRUNCATE,
3796 	.expected_open_result = EACCES,
3797 };
3798 
3799 TEST_F_FORK(ftruncate, open_and_ftruncate)
3800 {
3801 	const char *const path = file1_s1d1;
3802 	const struct rule rules[] = {
3803 		{
3804 			.path = path,
3805 			.access = variant->allowed,
3806 		},
3807 		{},
3808 	};
3809 	int fd;
3810 
3811 	/* Enables Landlock. */
3812 	enforce_fs(_metadata, variant->handled, rules);
3813 
3814 	fd = open(path, O_WRONLY);
3815 	EXPECT_EQ(variant->expected_open_result, (fd < 0 ? errno : 0));
3816 	if (fd >= 0) {
3817 		EXPECT_EQ(variant->expected_ftruncate_result,
3818 			  test_ftruncate(fd));
3819 		ASSERT_EQ(0, close(fd));
3820 	}
3821 }
3822 
3823 TEST_F_FORK(ftruncate, open_and_ftruncate_in_different_processes)
3824 {
3825 	int child, fd, status;
3826 	int socket_fds[2];
3827 
3828 	ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0,
3829 				socket_fds));
3830 
3831 	child = fork();
3832 	ASSERT_LE(0, child);
3833 	if (child == 0) {
3834 		/*
3835 		 * Enables Landlock in the child process, open a file descriptor
3836 		 * where truncation is forbidden and send it to the
3837 		 * non-landlocked parent process.
3838 		 */
3839 		const char *const path = file1_s1d1;
3840 		const struct rule rules[] = {
3841 			{
3842 				.path = path,
3843 				.access = variant->allowed,
3844 			},
3845 			{},
3846 		};
3847 		int fd;
3848 
3849 		enforce_fs(_metadata, variant->handled, rules);
3850 
3851 		fd = open(path, O_WRONLY);
3852 		ASSERT_EQ(variant->expected_open_result, (fd < 0 ? errno : 0));
3853 
3854 		if (fd >= 0) {
3855 			ASSERT_EQ(0, send_fd(socket_fds[0], fd));
3856 			ASSERT_EQ(0, close(fd));
3857 		}
3858 
3859 		ASSERT_EQ(0, close(socket_fds[0]));
3860 
3861 		_exit(_metadata->exit_code);
3862 		return;
3863 	}
3864 
3865 	if (variant->expected_open_result == 0) {
3866 		fd = recv_fd(socket_fds[1]);
3867 		ASSERT_LE(0, fd);
3868 
3869 		EXPECT_EQ(variant->expected_ftruncate_result,
3870 			  test_ftruncate(fd));
3871 		ASSERT_EQ(0, close(fd));
3872 	}
3873 
3874 	ASSERT_EQ(child, waitpid(child, &status, 0));
3875 	ASSERT_EQ(1, WIFEXITED(status));
3876 	ASSERT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
3877 
3878 	ASSERT_EQ(0, close(socket_fds[0]));
3879 	ASSERT_EQ(0, close(socket_fds[1]));
3880 }
3881 
3882 /* Invokes the FS_IOC_GETFLAGS IOCTL and returns its errno or 0. */
3883 static int test_fs_ioc_getflags_ioctl(int fd)
3884 {
3885 	uint32_t flags;
3886 
3887 	if (ioctl(fd, FS_IOC_GETFLAGS, &flags) < 0)
3888 		return errno;
3889 	return 0;
3890 }
3891 
3892 TEST(memfd_ftruncate_and_ioctl)
3893 {
3894 	int fd, i;
3895 
3896 	/*
3897 	 * We exercise the same test both with and without Landlock enabled, to
3898 	 * ensure that it behaves the same in both cases.
3899 	 */
3900 	for (i = 0; i < 2; i++) {
3901 		/* Creates a new memfd. */
3902 		fd = memfd_create("name", MFD_CLOEXEC);
3903 		ASSERT_LE(0, fd);
3904 
3905 		/*
3906 		 * Checks that operations associated with the opened file
3907 		 * (ftruncate, ioctl) are permitted on file descriptors that are
3908 		 * created in ways other than open(2).
3909 		 */
3910 		EXPECT_EQ(0, test_ftruncate(fd));
3911 		EXPECT_EQ(0, test_fs_ioc_getflags_ioctl(fd));
3912 
3913 		ASSERT_EQ(0, close(fd));
3914 
3915 		/* Enables Landlock. */
3916 		enforce_fs(_metadata, ACCESS_ALL, NULL);
3917 	}
3918 }
3919 
3920 static int test_fionread_ioctl(int fd)
3921 {
3922 	size_t sz = 0;
3923 
3924 	if (ioctl(fd, FIONREAD, &sz) < 0 && errno == EACCES)
3925 		return errno;
3926 	return 0;
3927 }
3928 
3929 TEST_F_FORK(layout1, o_path_ftruncate_and_ioctl)
3930 {
3931 	int fd;
3932 
3933 	/*
3934 	 * Checks that for files opened with O_PATH, both ioctl(2) and
3935 	 * ftruncate(2) yield EBADF, as it is documented in open(2) for the
3936 	 * O_PATH flag.
3937 	 */
3938 	fd = open(dir_s1d1, O_PATH | O_CLOEXEC);
3939 	ASSERT_LE(0, fd);
3940 
3941 	EXPECT_EQ(EBADF, test_ftruncate(fd));
3942 	EXPECT_EQ(EBADF, test_fs_ioc_getflags_ioctl(fd));
3943 
3944 	ASSERT_EQ(0, close(fd));
3945 
3946 	/* Enables Landlock. */
3947 	enforce_fs(_metadata, ACCESS_ALL, NULL);
3948 
3949 	/*
3950 	 * Checks that after enabling Landlock,
3951 	 * - the file can still be opened with O_PATH
3952 	 * - both ioctl and truncate still yield EBADF (not EACCES).
3953 	 */
3954 	fd = open(dir_s1d1, O_PATH | O_CLOEXEC);
3955 	ASSERT_LE(0, fd);
3956 
3957 	EXPECT_EQ(EBADF, test_ftruncate(fd));
3958 	EXPECT_EQ(EBADF, test_fs_ioc_getflags_ioctl(fd));
3959 
3960 	ASSERT_EQ(0, close(fd));
3961 }
3962 
3963 /*
3964  * ioctl_error - generically call the given ioctl with a pointer to a
3965  * sufficiently large zeroed-out memory region.
3966  *
3967  * Returns the IOCTLs error, or 0.
3968  */
3969 static int ioctl_error(struct __test_metadata *const _metadata, int fd,
3970 		       unsigned int cmd)
3971 {
3972 	char buf[128]; /* sufficiently large */
3973 	int res, stdinbak_fd;
3974 
3975 	/*
3976 	 * Depending on the IOCTL command, parts of the zeroed-out buffer might
3977 	 * be interpreted as file descriptor numbers.  We do not want to
3978 	 * accidentally operate on file descriptor 0 (stdin), so we temporarily
3979 	 * move stdin to a different FD and close FD 0 for the IOCTL call.
3980 	 */
3981 	stdinbak_fd = dup(0);
3982 	ASSERT_LT(0, stdinbak_fd);
3983 	ASSERT_EQ(0, close(0));
3984 
3985 	/* Invokes the IOCTL with a zeroed-out buffer. */
3986 	bzero(&buf, sizeof(buf));
3987 	res = ioctl(fd, cmd, &buf);
3988 
3989 	/* Restores the old FD 0 and closes the backup FD. */
3990 	ASSERT_EQ(0, dup2(stdinbak_fd, 0));
3991 	ASSERT_EQ(0, close(stdinbak_fd));
3992 
3993 	if (res < 0)
3994 		return errno;
3995 
3996 	return 0;
3997 }
3998 
3999 /* Define some linux/falloc.h IOCTL commands which are not available in uapi headers. */
4000 struct space_resv {
4001 	__s16 l_type;
4002 	__s16 l_whence;
4003 	__s64 l_start;
4004 	__s64 l_len; /* len == 0 means until end of file */
4005 	__s32 l_sysid;
4006 	__u32 l_pid;
4007 	__s32 l_pad[4]; /* reserved area */
4008 };
4009 
4010 #define FS_IOC_RESVSP _IOW('X', 40, struct space_resv)
4011 #define FS_IOC_UNRESVSP _IOW('X', 41, struct space_resv)
4012 #define FS_IOC_RESVSP64 _IOW('X', 42, struct space_resv)
4013 #define FS_IOC_UNRESVSP64 _IOW('X', 43, struct space_resv)
4014 #define FS_IOC_ZERO_RANGE _IOW('X', 57, struct space_resv)
4015 
4016 /*
4017  * Tests a series of blanket-permitted and denied IOCTLs.
4018  */
4019 TEST_F_FORK(layout1, blanket_permitted_ioctls)
4020 {
4021 	int fd;
4022 
4023 	/* Enables Landlock. */
4024 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_IOCTL_DEV, NULL);
4025 
4026 	fd = open("/dev/null", O_RDWR | O_CLOEXEC);
4027 	ASSERT_LE(0, fd);
4028 
4029 	/*
4030 	 * Checks permitted commands.
4031 	 * These ones may return errors, but should not be blocked by Landlock.
4032 	 */
4033 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIOCLEX));
4034 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIONCLEX));
4035 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIONBIO));
4036 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIOASYNC));
4037 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIOQSIZE));
4038 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIFREEZE));
4039 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FITHAW));
4040 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FS_IOC_FIEMAP));
4041 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIGETBSZ));
4042 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FICLONE));
4043 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FICLONERANGE));
4044 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIDEDUPERANGE));
4045 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FS_IOC_GETFSUUID));
4046 	EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FS_IOC_GETFSSYSFSPATH));
4047 
4048 	/*
4049 	 * Checks blocked commands.
4050 	 * A call to a blocked IOCTL command always returns EACCES.
4051 	 */
4052 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FIONREAD));
4053 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_GETFLAGS));
4054 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_SETFLAGS));
4055 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_FSGETXATTR));
4056 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_FSSETXATTR));
4057 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FIBMAP));
4058 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_RESVSP));
4059 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_RESVSP64));
4060 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_UNRESVSP));
4061 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_UNRESVSP64));
4062 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_ZERO_RANGE));
4063 
4064 	/* Default case is also blocked. */
4065 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, 0xc00ffeee));
4066 
4067 	ASSERT_EQ(0, close(fd));
4068 }
4069 
4070 /*
4071  * Named pipes are not governed by the LANDLOCK_ACCESS_FS_IOCTL_DEV right,
4072  * because they are not character or block devices.
4073  */
4074 TEST_F_FORK(layout1, named_pipe_ioctl)
4075 {
4076 	pid_t child_pid;
4077 	int fd;
4078 	const char *const path = file1_s1d1;
4079 
4080 	ASSERT_EQ(0, unlink(path));
4081 	ASSERT_EQ(0, mkfifo(path, 0600));
4082 
4083 	/* Enables Landlock. */
4084 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_IOCTL_DEV, NULL);
4085 
4086 	/* The child process opens the pipe for writing. */
4087 	child_pid = fork();
4088 	ASSERT_NE(-1, child_pid);
4089 	if (child_pid == 0) {
4090 		fd = open(path, O_WRONLY);
4091 		close(fd);
4092 		exit(0);
4093 	}
4094 
4095 	fd = open(path, O_RDONLY);
4096 	ASSERT_LE(0, fd);
4097 
4098 	/* FIONREAD is implemented by pipefifo_fops. */
4099 	EXPECT_EQ(0, test_fionread_ioctl(fd));
4100 
4101 	ASSERT_EQ(0, close(fd));
4102 	ASSERT_EQ(0, unlink(path));
4103 
4104 	ASSERT_EQ(child_pid, waitpid(child_pid, NULL, 0));
4105 }
4106 
4107 /*
4108  * set_up_named_unix_server - Create a pathname unix socket
4109  *
4110  * If the socket type is not SOCK_DGRAM, also invoke listen(2).
4111  *
4112  * Return: The listening FD - it is the caller responsibility to close it.
4113  */
4114 static int set_up_named_unix_server(struct __test_metadata *const _metadata,
4115 				    int type, const char *const path)
4116 {
4117 	int fd;
4118 	struct sockaddr_un addr = {
4119 		.sun_family = AF_UNIX,
4120 	};
4121 
4122 	fd = socket(AF_UNIX, type, 0);
4123 	ASSERT_LE(0, fd);
4124 
4125 	ASSERT_LT(strlen(path), sizeof(addr.sun_path));
4126 	strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
4127 
4128 	ASSERT_EQ(0, bind(fd, (struct sockaddr *)&addr, sizeof(addr)));
4129 
4130 	if (type != SOCK_DGRAM)
4131 		ASSERT_EQ(0, listen(fd, 10 /* qlen */));
4132 	return fd;
4133 }
4134 
4135 /*
4136  * test_connect_named_unix - connect to the given named UNIX socket
4137  *
4138  * Return: The errno from connect(), or 0
4139  */
4140 static int test_connect_named_unix(struct __test_metadata *const _metadata,
4141 				   int fd, const char *const path)
4142 {
4143 	struct sockaddr_un addr = {
4144 		.sun_family = AF_UNIX,
4145 	};
4146 
4147 	ASSERT_LT(strlen(path), sizeof(addr.sun_path));
4148 	strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
4149 
4150 	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
4151 		return errno;
4152 	return 0;
4153 }
4154 
4155 /* For named UNIX domain sockets, no IOCTL restrictions apply. */
4156 TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)
4157 {
4158 	const char *const path = file1_s1d1;
4159 	int srv_fd, cli_fd;
4160 
4161 	/* Sets up a server */
4162 	ASSERT_EQ(0, unlink(path));
4163 	srv_fd = set_up_named_unix_server(_metadata, SOCK_STREAM, path);
4164 
4165 	/* Enables Landlock. */
4166 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_IOCTL_DEV, NULL);
4167 
4168 	/* Sets up a client connection to it */
4169 	cli_fd = socket(AF_UNIX, SOCK_STREAM, 0);
4170 	ASSERT_LE(0, cli_fd);
4171 
4172 	ASSERT_EQ(0, test_connect_named_unix(_metadata, cli_fd, path));
4173 
4174 	/* FIONREAD and other IOCTLs should not be forbidden. */
4175 	EXPECT_EQ(0, test_fionread_ioctl(cli_fd));
4176 
4177 	EXPECT_EQ(0, close(cli_fd));
4178 	EXPECT_EQ(0, close(srv_fd));
4179 }
4180 
4181 /* clang-format off */
4182 FIXTURE(ioctl) {};
4183 
4184 FIXTURE_SETUP(ioctl) {};
4185 
4186 FIXTURE_TEARDOWN(ioctl) {};
4187 /* clang-format on */
4188 
4189 FIXTURE_VARIANT(ioctl)
4190 {
4191 	const __u64 handled;
4192 	const __u64 allowed;
4193 	const mode_t open_mode;
4194 	/*
4195 	 * FIONREAD is used as a characteristic device-specific IOCTL command.
4196 	 * It is implemented in fs/ioctl.c for regular files,
4197 	 * but we do not blanket-permit it for devices.
4198 	 */
4199 	const int expected_fionread_result;
4200 };
4201 
4202 /* clang-format off */
4203 FIXTURE_VARIANT_ADD(ioctl, handled_i_allowed_none) {
4204 	/* clang-format on */
4205 	.handled = LANDLOCK_ACCESS_FS_IOCTL_DEV,
4206 	.allowed = 0,
4207 	.open_mode = O_RDWR,
4208 	.expected_fionread_result = EACCES,
4209 };
4210 
4211 /* clang-format off */
4212 FIXTURE_VARIANT_ADD(ioctl, handled_i_allowed_i) {
4213 	/* clang-format on */
4214 	.handled = LANDLOCK_ACCESS_FS_IOCTL_DEV,
4215 	.allowed = LANDLOCK_ACCESS_FS_IOCTL_DEV,
4216 	.open_mode = O_RDWR,
4217 	.expected_fionread_result = 0,
4218 };
4219 
4220 /* clang-format off */
4221 FIXTURE_VARIANT_ADD(ioctl, unhandled) {
4222 	/* clang-format on */
4223 	.handled = LANDLOCK_ACCESS_FS_EXECUTE,
4224 	.allowed = LANDLOCK_ACCESS_FS_EXECUTE,
4225 	.open_mode = O_RDWR,
4226 	.expected_fionread_result = 0,
4227 };
4228 
4229 TEST_F_FORK(ioctl, handle_dir_access_file)
4230 {
4231 	const int flag = 0;
4232 	const struct rule rules[] = {
4233 		{
4234 			.path = "/dev",
4235 			.access = variant->allowed,
4236 		},
4237 		{},
4238 	};
4239 	int fd;
4240 
4241 	/* Enables Landlock. */
4242 	enforce_fs(_metadata, variant->handled, rules);
4243 
4244 	fd = open("/dev/zero", variant->open_mode);
4245 	ASSERT_LE(0, fd);
4246 
4247 	/* Checks that IOCTL commands return the expected errors. */
4248 	EXPECT_EQ(variant->expected_fionread_result, test_fionread_ioctl(fd));
4249 
4250 	/* Checks that unrestrictable commands are unrestricted. */
4251 	EXPECT_EQ(0, ioctl(fd, FIOCLEX));
4252 	EXPECT_EQ(0, ioctl(fd, FIONCLEX));
4253 	EXPECT_EQ(0, ioctl(fd, FIONBIO, &flag));
4254 	EXPECT_EQ(0, ioctl(fd, FIOASYNC, &flag));
4255 	EXPECT_EQ(0, ioctl(fd, FIGETBSZ, &flag));
4256 
4257 	ASSERT_EQ(0, close(fd));
4258 }
4259 
4260 TEST_F_FORK(ioctl, handle_dir_access_dir)
4261 {
4262 	const int flag = 0;
4263 	const struct rule rules[] = {
4264 		{
4265 			.path = "/dev",
4266 			.access = variant->allowed,
4267 		},
4268 		{},
4269 	};
4270 	int dir_fd;
4271 
4272 	/* Enables Landlock. */
4273 	enforce_fs(_metadata, variant->handled, rules);
4274 
4275 	/*
4276 	 * Ignore variant->open_mode for this test, as we intend to open a
4277 	 * directory.  If the directory can not be opened, the variant is
4278 	 * infeasible to test with an opened directory.
4279 	 */
4280 	dir_fd = open("/dev", O_RDONLY);
4281 	if (dir_fd < 0)
4282 		return;
4283 
4284 	/*
4285 	 * Checks that IOCTL commands return the expected errors.
4286 	 * We do not use the expected values from the fixture here.
4287 	 *
4288 	 * When using IOCTL on a directory, no Landlock restrictions apply.
4289 	 */
4290 	EXPECT_EQ(0, test_fionread_ioctl(dir_fd));
4291 
4292 	/* Checks that unrestrictable commands are unrestricted. */
4293 	EXPECT_EQ(0, ioctl(dir_fd, FIOCLEX));
4294 	EXPECT_EQ(0, ioctl(dir_fd, FIONCLEX));
4295 	EXPECT_EQ(0, ioctl(dir_fd, FIONBIO, &flag));
4296 	EXPECT_EQ(0, ioctl(dir_fd, FIOASYNC, &flag));
4297 	EXPECT_EQ(0, ioctl(dir_fd, FIGETBSZ, &flag));
4298 
4299 	ASSERT_EQ(0, close(dir_fd));
4300 }
4301 
4302 TEST_F_FORK(ioctl, handle_file_access_file)
4303 {
4304 	const int flag = 0;
4305 	const struct rule rules[] = {
4306 		{
4307 			.path = "/dev/zero",
4308 			.access = variant->allowed,
4309 		},
4310 		{},
4311 	};
4312 	int fd;
4313 
4314 	/* Enables Landlock. */
4315 	enforce_fs(_metadata, variant->handled, rules);
4316 
4317 	fd = open("/dev/zero", variant->open_mode);
4318 	ASSERT_LE(0, fd)
4319 	{
4320 		TH_LOG("Failed to open /dev/zero: %s", strerror(errno));
4321 	}
4322 
4323 	/* Checks that IOCTL commands return the expected errors. */
4324 	EXPECT_EQ(variant->expected_fionread_result, test_fionread_ioctl(fd));
4325 
4326 	/* Checks that unrestrictable commands are unrestricted. */
4327 	EXPECT_EQ(0, ioctl(fd, FIOCLEX));
4328 	EXPECT_EQ(0, ioctl(fd, FIONCLEX));
4329 	EXPECT_EQ(0, ioctl(fd, FIONBIO, &flag));
4330 	EXPECT_EQ(0, ioctl(fd, FIOASYNC, &flag));
4331 	EXPECT_EQ(0, ioctl(fd, FIGETBSZ, &flag));
4332 
4333 	ASSERT_EQ(0, close(fd));
4334 }
4335 
4336 /*
4337  * test_sendto_named_unix - sendto to the given named UNIX socket
4338  *
4339  * sendto() is equivalent to sendmsg() in this respect.
4340  *
4341  * Return: The errno from sendto(), or 0
4342  */
4343 static int test_sendto_named_unix(struct __test_metadata *const _metadata,
4344 				  int fd, const char *const path)
4345 {
4346 	static const char buf[] = "dummy";
4347 	struct sockaddr_un addr = {
4348 		.sun_family = AF_UNIX,
4349 	};
4350 
4351 	ASSERT_LT(strlen(path), sizeof(addr.sun_path));
4352 	strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
4353 
4354 	if (sendto(fd, buf, sizeof(buf), 0, (struct sockaddr *)&addr,
4355 		   sizeof(addr)) == -1)
4356 		return errno;
4357 	return 0;
4358 }
4359 
4360 /* clang-format off */
4361 FIXTURE(scoped_domains) {};
4362 /* clang-format on */
4363 
4364 #include "scoped_base_variants.h"
4365 
4366 FIXTURE_SETUP(scoped_domains)
4367 {
4368 	drop_caps(_metadata);
4369 };
4370 
4371 FIXTURE_TEARDOWN(scoped_domains)
4372 {
4373 }
4374 
4375 /*
4376  * Flags for test_connect_to_parent and test_connect_to_child:
4377  *
4378  * USE_SENDTO: Use sendto() instead of connect() (for SOCK_DGRAM only)
4379  * ENFORCE_ALL: Enforce a Landlock domain even when the variant says
4380  *   we shouldn't.  We enforce a domain where the path is allow-listed,
4381  *   and expect the behavior to be the same as if none was used.
4382  */
4383 #define USE_SENDTO (1 << 0)
4384 #define ENFORCE_ALL (1 << 1)
4385 
4386 static void test_connect_to_parent(struct __test_metadata *const _metadata,
4387 				   const FIXTURE_VARIANT(scoped_domains) *
4388 					   variant,
4389 				   int sock_type, int flags)
4390 {
4391 	const char *const path = "sock";
4392 	const struct rule rules[] = {
4393 		{
4394 			.path = ".",
4395 			.access = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
4396 		},
4397 		{},
4398 	};
4399 	int cli_fd, srv_fd, res, status;
4400 	pid_t child_pid;
4401 	int readiness_pipe[2];
4402 	char buf[1];
4403 
4404 	if (variant->domain_both)
4405 		enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX, NULL);
4406 	else if (flags & ENFORCE_ALL)
4407 		enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX, rules);
4408 
4409 	unlink(path);
4410 	ASSERT_EQ(0, pipe2(readiness_pipe, O_CLOEXEC));
4411 
4412 	child_pid = fork();
4413 	ASSERT_LE(0, child_pid);
4414 
4415 	if (child_pid == 0) {
4416 		if (variant->domain_child)
4417 			enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
4418 				   NULL);
4419 		else if (flags & ENFORCE_ALL)
4420 			enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
4421 				   rules);
4422 
4423 		/* Wait for server to be available. */
4424 		EXPECT_EQ(0, close(readiness_pipe[1]));
4425 		EXPECT_EQ(1, read(readiness_pipe[0], &buf, 1));
4426 		EXPECT_EQ(0, close(readiness_pipe[0]));
4427 
4428 		/* Talk to server. */
4429 		cli_fd = socket(AF_UNIX, sock_type, 0);
4430 		ASSERT_LE(0, cli_fd);
4431 
4432 		if (flags & USE_SENDTO)
4433 			res = test_sendto_named_unix(_metadata, cli_fd, path);
4434 		else
4435 			res = test_connect_named_unix(_metadata, cli_fd, path);
4436 
4437 		EXPECT_EQ(variant->domain_child ? EACCES : 0, res);
4438 
4439 		/* Clean up. */
4440 		EXPECT_EQ(0, close(cli_fd));
4441 
4442 		_exit(_metadata->exit_code);
4443 		return;
4444 	}
4445 
4446 	if (variant->domain_parent)
4447 		enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX, NULL);
4448 	else if (flags & ENFORCE_ALL)
4449 		enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX, rules);
4450 
4451 	srv_fd = set_up_named_unix_server(_metadata, sock_type, path);
4452 
4453 	/* Tell the child that it can connect. */
4454 	EXPECT_EQ(0, close(readiness_pipe[0]));
4455 	EXPECT_EQ(sizeof(buf), write(readiness_pipe[1], buf, sizeof(buf)));
4456 	EXPECT_EQ(0, close(readiness_pipe[1]));
4457 
4458 	/* Wait for child. */
4459 	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
4460 	EXPECT_EQ(1, WIFEXITED(status));
4461 	EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
4462 
4463 	/* Clean up. */
4464 	EXPECT_EQ(0, close(srv_fd));
4465 	EXPECT_EQ(0, unlink(path));
4466 }
4467 
4468 static void test_connect_to_child(struct __test_metadata *const _metadata,
4469 				  const FIXTURE_VARIANT(scoped_domains) *
4470 					  variant,
4471 				  int sock_type, int flags)
4472 {
4473 	const char *const path = "sock";
4474 	const struct rule rules[] = {
4475 		{
4476 			.path = ".",
4477 			.access = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
4478 		},
4479 		{},
4480 	};
4481 	int readiness_pipe[2];
4482 	int shutdown_pipe[2];
4483 	int cli_fd, srv_fd, res, status;
4484 	pid_t child_pid;
4485 	char buf[1];
4486 
4487 	if (variant->domain_both)
4488 		enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX, NULL);
4489 	else if (flags & ENFORCE_ALL)
4490 		enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX, rules);
4491 
4492 	unlink(path);
4493 	ASSERT_EQ(0, pipe2(readiness_pipe, O_CLOEXEC));
4494 	ASSERT_EQ(0, pipe2(shutdown_pipe, O_CLOEXEC));
4495 
4496 	child_pid = fork();
4497 	ASSERT_LE(0, child_pid);
4498 
4499 	if (child_pid == 0) {
4500 		if (variant->domain_child)
4501 			enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
4502 				   NULL);
4503 		else if (flags & ENFORCE_ALL)
4504 			enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
4505 				   rules);
4506 
4507 		srv_fd = set_up_named_unix_server(_metadata, sock_type, path);
4508 
4509 		/* Tell the parent that it can connect. */
4510 		EXPECT_EQ(0, close(readiness_pipe[0]));
4511 		EXPECT_EQ(sizeof(buf),
4512 			  write(readiness_pipe[1], buf, sizeof(buf)));
4513 		EXPECT_EQ(0, close(readiness_pipe[1]));
4514 
4515 		/* Wait until it is time to shut down. */
4516 		EXPECT_EQ(0, close(shutdown_pipe[1]));
4517 		EXPECT_EQ(1, read(shutdown_pipe[0], &buf, 1));
4518 		EXPECT_EQ(0, close(shutdown_pipe[0]));
4519 
4520 		/* Cleanup */
4521 		EXPECT_EQ(0, close(srv_fd));
4522 		EXPECT_EQ(0, unlink(path));
4523 
4524 		_exit(_metadata->exit_code);
4525 		return;
4526 	}
4527 
4528 	if (variant->domain_parent)
4529 		enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX, NULL);
4530 	else if (flags & ENFORCE_ALL)
4531 		enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX, rules);
4532 
4533 	/* Wait for server to be available. */
4534 	EXPECT_EQ(0, close(readiness_pipe[1]));
4535 	EXPECT_EQ(1, read(readiness_pipe[0], &buf, 1));
4536 	EXPECT_EQ(0, close(readiness_pipe[0]));
4537 
4538 	/* Talk to server. */
4539 	cli_fd = socket(AF_UNIX, sock_type, 0);
4540 	ASSERT_LE(0, cli_fd);
4541 
4542 	if (flags & USE_SENDTO)
4543 		res = test_sendto_named_unix(_metadata, cli_fd, path);
4544 	else
4545 		res = test_connect_named_unix(_metadata, cli_fd, path);
4546 
4547 	EXPECT_EQ(variant->domain_parent ? EACCES : 0, res);
4548 
4549 	/* Clean up. */
4550 	EXPECT_EQ(0, close(cli_fd));
4551 
4552 	/* Tell the server to shut down. */
4553 	EXPECT_EQ(0, close(shutdown_pipe[0]));
4554 	EXPECT_EQ(sizeof(buf), write(shutdown_pipe[1], buf, sizeof(buf)));
4555 	EXPECT_EQ(0, close(shutdown_pipe[1]));
4556 
4557 	/* Wait for child. */
4558 	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
4559 	EXPECT_EQ(1, WIFEXITED(status));
4560 	EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
4561 }
4562 
4563 TEST_F(scoped_domains, unix_stream_connect_to_parent)
4564 {
4565 	test_connect_to_parent(_metadata, variant, SOCK_STREAM, 0);
4566 }
4567 
4568 TEST_F(scoped_domains, unix_dgram_connect_to_parent)
4569 {
4570 	test_connect_to_parent(_metadata, variant, SOCK_DGRAM, 0);
4571 }
4572 
4573 TEST_F(scoped_domains, unix_dgram_sendmsg_to_parent)
4574 {
4575 	test_connect_to_parent(_metadata, variant, SOCK_DGRAM, USE_SENDTO);
4576 }
4577 
4578 TEST_F(scoped_domains, unix_seqpacket_connect_to_parent)
4579 {
4580 	test_connect_to_parent(_metadata, variant, SOCK_SEQPACKET, 0);
4581 }
4582 
4583 TEST_F(scoped_domains, unix_stream_connect_to_parent_full)
4584 {
4585 	test_connect_to_parent(_metadata, variant, SOCK_STREAM, ENFORCE_ALL);
4586 }
4587 
4588 TEST_F(scoped_domains, unix_dgram_connect_to_parent_full)
4589 {
4590 	test_connect_to_parent(_metadata, variant, SOCK_DGRAM, ENFORCE_ALL);
4591 }
4592 
4593 TEST_F(scoped_domains, unix_dgram_sendmsg_to_parent_full)
4594 {
4595 	test_connect_to_parent(_metadata, variant, SOCK_DGRAM,
4596 			       USE_SENDTO | ENFORCE_ALL);
4597 }
4598 
4599 TEST_F(scoped_domains, unix_seqpacket_connect_to_parent_full)
4600 {
4601 	test_connect_to_parent(_metadata, variant, SOCK_SEQPACKET, ENFORCE_ALL);
4602 }
4603 
4604 TEST_F(scoped_domains, unix_stream_connect_to_child)
4605 {
4606 	test_connect_to_child(_metadata, variant, SOCK_STREAM, 0);
4607 }
4608 
4609 TEST_F(scoped_domains, unix_dgram_connect_to_child)
4610 {
4611 	test_connect_to_child(_metadata, variant, SOCK_DGRAM, 0);
4612 }
4613 
4614 TEST_F(scoped_domains, unix_dgram_sendmsg_to_child)
4615 {
4616 	test_connect_to_child(_metadata, variant, SOCK_DGRAM, USE_SENDTO);
4617 }
4618 
4619 TEST_F(scoped_domains, unix_seqpacket_connect_to_child)
4620 {
4621 	test_connect_to_child(_metadata, variant, SOCK_SEQPACKET, 0);
4622 }
4623 
4624 TEST_F(scoped_domains, unix_stream_connect_to_child_full)
4625 {
4626 	test_connect_to_child(_metadata, variant, SOCK_STREAM, ENFORCE_ALL);
4627 }
4628 
4629 TEST_F(scoped_domains, unix_dgram_connect_to_child_full)
4630 {
4631 	test_connect_to_child(_metadata, variant, SOCK_DGRAM, ENFORCE_ALL);
4632 }
4633 
4634 TEST_F(scoped_domains, unix_dgram_sendmsg_to_child_full)
4635 {
4636 	test_connect_to_child(_metadata, variant, SOCK_DGRAM,
4637 			      USE_SENDTO | ENFORCE_ALL);
4638 }
4639 
4640 TEST_F(scoped_domains, unix_seqpacket_connect_to_child_full)
4641 {
4642 	test_connect_to_child(_metadata, variant, SOCK_SEQPACKET, ENFORCE_ALL);
4643 }
4644 
4645 #undef USE_SENDTO
4646 #undef ENFORCE_ALL
4647 
4648 static void read_core_pattern(struct __test_metadata *const _metadata,
4649 			      char *buf, size_t buf_size)
4650 {
4651 	int fd;
4652 	ssize_t ret;
4653 
4654 	fd = open("/proc/sys/kernel/core_pattern", O_RDONLY | O_CLOEXEC);
4655 	ASSERT_LE(0, fd);
4656 
4657 	ret = read(fd, buf, buf_size - 1);
4658 	ASSERT_LE(0, ret);
4659 	EXPECT_EQ(0, close(fd));
4660 
4661 	buf[ret] = '\0';
4662 }
4663 
4664 static void set_core_pattern(struct __test_metadata *const _metadata,
4665 			     const char *pattern)
4666 {
4667 	int fd;
4668 	size_t len = strlen(pattern);
4669 
4670 	/*
4671 	 * Writing to /proc/sys/kernel/core_pattern requires EUID 0 because
4672 	 * sysctl_perm() checks that, ignoring capabilities like
4673 	 * CAP_SYS_ADMIN or CAP_DAC_OVERRIDE.
4674 	 *
4675 	 * Switching EUID clears the dumpable flag, which must be restored
4676 	 * afterwards to allow coredumps.
4677 	 */
4678 	set_cap(_metadata, CAP_SETUID);
4679 	ASSERT_EQ(0, seteuid(0));
4680 	clear_cap(_metadata, CAP_SETUID);
4681 
4682 	fd = open("/proc/sys/kernel/core_pattern", O_WRONLY | O_CLOEXEC);
4683 	ASSERT_LE(0, fd)
4684 	{
4685 		TH_LOG("Failed to open core_pattern for writing: %s",
4686 		       strerror(errno));
4687 	}
4688 
4689 	ASSERT_EQ(len, write(fd, pattern, len));
4690 	EXPECT_EQ(0, close(fd));
4691 
4692 	set_cap(_metadata, CAP_SETUID);
4693 	ASSERT_EQ(0, seteuid(getuid()));
4694 	clear_cap(_metadata, CAP_SETUID);
4695 
4696 	/* Restore dumpable flag cleared by seteuid(). */
4697 	ASSERT_EQ(0, prctl(PR_SET_DUMPABLE, 1, 0, 0, 0));
4698 }
4699 
4700 FIXTURE(coredump)
4701 {
4702 	char original_core_pattern[256];
4703 };
4704 
4705 FIXTURE_SETUP(coredump)
4706 {
4707 	disable_caps(_metadata);
4708 	read_core_pattern(_metadata, self->original_core_pattern,
4709 			  sizeof(self->original_core_pattern));
4710 }
4711 
4712 FIXTURE_TEARDOWN_PARENT(coredump)
4713 {
4714 	set_core_pattern(_metadata, self->original_core_pattern);
4715 }
4716 
4717 /*
4718  * Test that even when a process is restricted with
4719  * LANDLOCK_ACCESS_FS_RESOLVE_UNIX, the kernel can still initiate a connection
4720  * to the coredump socket on the processes' behalf.
4721  */
4722 TEST_F_FORK(coredump, socket_not_restricted)
4723 {
4724 	static const char core_pattern[] = "@/tmp/landlock_coredump_test.sock";
4725 	const char *const sock_path = core_pattern + 1;
4726 	int srv_fd, conn_fd, status;
4727 	pid_t child_pid;
4728 	struct ucred cred;
4729 	socklen_t cred_len = sizeof(cred);
4730 	char buf[4096];
4731 
4732 	/* Set up the coredump server socket. */
4733 	unlink(sock_path);
4734 	srv_fd = set_up_named_unix_server(_metadata, SOCK_STREAM, sock_path);
4735 
4736 	/* Point coredumps at our socket. */
4737 	set_core_pattern(_metadata, core_pattern);
4738 
4739 	/* Restrict LANDLOCK_ACCESS_FS_RESOLVE_UNIX. */
4740 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_RESOLVE_UNIX, NULL);
4741 
4742 	/* Fork a child that crashes. */
4743 	child_pid = fork();
4744 	ASSERT_LE(0, child_pid);
4745 	if (child_pid == 0) {
4746 		struct rlimit rl = {
4747 			.rlim_cur = RLIM_INFINITY,
4748 			.rlim_max = RLIM_INFINITY,
4749 		};
4750 
4751 		ASSERT_EQ(0, setrlimit(RLIMIT_CORE, &rl));
4752 
4753 		/* Crash on purpose. */
4754 		kill(getpid(), SIGSEGV);
4755 		_exit(1);
4756 	}
4757 
4758 	/*
4759 	 * Accept the coredump connection.  If Landlock incorrectly denies the
4760 	 * kernel's coredump connect, accept() will block forever, so the test
4761 	 * would time out.
4762 	 */
4763 	conn_fd = accept(srv_fd, NULL, NULL);
4764 	ASSERT_LE(0, conn_fd);
4765 
4766 	/* Check that the connection came from the crashing child. */
4767 	ASSERT_EQ(0, getsockopt(conn_fd, SOL_SOCKET, SO_PEERCRED, &cred,
4768 				&cred_len));
4769 	EXPECT_EQ(child_pid, cred.pid);
4770 
4771 	/* Drain the coredump data so the kernel can finish. */
4772 	while (read(conn_fd, buf, sizeof(buf)) > 0)
4773 		;
4774 
4775 	EXPECT_EQ(0, close(conn_fd));
4776 
4777 	/* Wait for the child and verify it coredumped. */
4778 	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
4779 	ASSERT_TRUE(WIFSIGNALED(status));
4780 	ASSERT_TRUE(WCOREDUMP(status));
4781 
4782 	EXPECT_EQ(0, close(srv_fd));
4783 	EXPECT_EQ(0, unlink(sock_path));
4784 }
4785 
4786 /* clang-format off */
4787 FIXTURE(layout1_bind) {};
4788 /* clang-format on */
4789 
4790 static const char bind_dir_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3";
4791 static const char bind_file1_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3/f1";
4792 
4793 /* Move targets for disconnected path tests. */
4794 static const char dir_s4d1[] = TMP_DIR "/s4d1";
4795 static const char file1_s4d1[] = TMP_DIR "/s4d1/f1";
4796 static const char file2_s4d1[] = TMP_DIR "/s4d1/f2";
4797 static const char dir_s4d2[] = TMP_DIR "/s4d1/s4d2";
4798 static const char file1_s4d2[] = TMP_DIR "/s4d1/s4d2/f1";
4799 static const char file1_name[] = "f1";
4800 static const char file2_name[] = "f2";
4801 
4802 FIXTURE_SETUP(layout1_bind)
4803 {
4804 	prepare_layout(_metadata);
4805 
4806 	create_layout1(_metadata);
4807 
4808 	set_cap(_metadata, CAP_SYS_ADMIN);
4809 	ASSERT_EQ(0, mount(dir_s1d2, dir_s2d2, NULL, MS_BIND, NULL));
4810 	clear_cap(_metadata, CAP_SYS_ADMIN);
4811 }
4812 
4813 FIXTURE_TEARDOWN_PARENT(layout1_bind)
4814 {
4815 	/* umount(dir_s2d2)) is handled by namespace lifetime. */
4816 
4817 	remove_path(file1_s4d1);
4818 	remove_path(file2_s4d1);
4819 
4820 	remove_layout1(_metadata);
4821 
4822 	cleanup_layout(_metadata);
4823 }
4824 
4825 /*
4826  * layout1_bind hierarchy:
4827  *
4828  * tmp
4829  * ├── s1d1
4830  * │   ├── f1
4831  * │   ├── f2
4832  * │   └── s1d2
4833  * │       ├── f1
4834  * │       ├── f2
4835  * │       └── s1d3 [disconnected by path_disconnected]
4836  * │           ├── f1
4837  * │           └── f2
4838  * ├── s2d1
4839  * │   ├── f1
4840  * │   └── s2d2 [bind mount from s1d2]
4841  * │       ├── f1
4842  * │       ├── f2
4843  * │       └── s1d3
4844  * │           ├── f1
4845  * │           └── f2
4846  * ├── s3d1
4847  * │   └── s3d2
4848  * │       └── s3d3
4849  * └── s4d1 [renamed from s1d3 by path_disconnected]
4850  *     ├── f1
4851  *     ├── f2
4852  *     └── s4d2
4853  *         └── f1
4854  */
4855 
4856 TEST_F_FORK(layout1_bind, no_restriction)
4857 {
4858 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
4859 	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
4860 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
4861 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
4862 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
4863 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
4864 
4865 	ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
4866 	ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
4867 	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
4868 	ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
4869 	ASSERT_EQ(ENOENT, test_open(dir_s2d3, O_RDONLY));
4870 	ASSERT_EQ(ENOENT, test_open(file1_s2d3, O_RDONLY));
4871 
4872 	ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY));
4873 	ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
4874 
4875 	ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
4876 }
4877 
4878 TEST_F_FORK(layout1_bind, same_content_same_file)
4879 {
4880 	/*
4881 	 * Sets access right on parent directories of both source and
4882 	 * destination mount points.
4883 	 */
4884 	const struct rule layer1_parent[] = {
4885 		{
4886 			.path = dir_s1d1,
4887 			.access = ACCESS_RO,
4888 		},
4889 		{
4890 			.path = dir_s2d1,
4891 			.access = ACCESS_RW,
4892 		},
4893 		{},
4894 	};
4895 	/*
4896 	 * Sets access rights on the same bind-mounted directories.  The result
4897 	 * should be ACCESS_RW for both directories, but not both hierarchies
4898 	 * because of the first layer.
4899 	 */
4900 	const struct rule layer2_mount_point[] = {
4901 		{
4902 			.path = dir_s1d2,
4903 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4904 		},
4905 		{
4906 			.path = dir_s2d2,
4907 			.access = ACCESS_RW,
4908 		},
4909 		{},
4910 	};
4911 	/* Only allow read-access to the s1d3 hierarchies. */
4912 	const struct rule layer3_source[] = {
4913 		{
4914 			.path = dir_s1d3,
4915 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4916 		},
4917 		{},
4918 	};
4919 	/* Removes all access rights. */
4920 	const struct rule layer4_destination[] = {
4921 		{
4922 			.path = bind_file1_s1d3,
4923 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
4924 		},
4925 		{},
4926 	};
4927 
4928 	/* Sets rules for the parent directories. */
4929 	enforce_fs(_metadata, ACCESS_RW, layer1_parent);
4930 
4931 	/* Checks source hierarchy. */
4932 	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
4933 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
4934 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
4935 
4936 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
4937 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
4938 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
4939 
4940 	/* Checks destination hierarchy. */
4941 	ASSERT_EQ(0, test_open(file1_s2d1, O_RDWR));
4942 	ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
4943 
4944 	ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
4945 	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
4946 
4947 	/* Sets rules for the mount points. */
4948 	enforce_fs(_metadata, ACCESS_RW, layer2_mount_point);
4949 
4950 	/* Checks source hierarchy. */
4951 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
4952 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
4953 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
4954 
4955 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
4956 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
4957 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
4958 
4959 	/* Checks destination hierarchy. */
4960 	ASSERT_EQ(EACCES, test_open(file1_s2d1, O_RDONLY));
4961 	ASSERT_EQ(EACCES, test_open(file1_s2d1, O_WRONLY));
4962 	ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
4963 
4964 	ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
4965 	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
4966 	ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
4967 
4968 	/* Sets a (shared) rule only on the source. */
4969 	enforce_fs(_metadata, ACCESS_RW, layer3_source);
4970 
4971 	/* Checks source hierarchy. */
4972 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDONLY));
4973 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
4974 	ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
4975 
4976 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
4977 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
4978 	ASSERT_EQ(EACCES, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
4979 
4980 	/* Checks destination hierarchy. */
4981 	ASSERT_EQ(EACCES, test_open(file1_s2d2, O_RDONLY));
4982 	ASSERT_EQ(EACCES, test_open(file1_s2d2, O_WRONLY));
4983 	ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
4984 
4985 	ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
4986 	ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
4987 	ASSERT_EQ(EACCES, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
4988 
4989 	/* Sets a (shared) rule only on the destination. */
4990 	enforce_fs(_metadata, ACCESS_RW, layer4_destination);
4991 
4992 	/* Checks source hierarchy. */
4993 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
4994 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
4995 
4996 	/* Checks destination hierarchy. */
4997 	ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_RDONLY));
4998 	ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
4999 }
5000 
5001 TEST_F_FORK(layout1_bind, reparent_cross_mount)
5002 {
5003 	const struct rule layer1[] = {
5004 		{
5005 			/* dir_s2d1 is beneath the dir_s2d2 mount point. */
5006 			.path = dir_s2d1,
5007 			.access = LANDLOCK_ACCESS_FS_REFER,
5008 		},
5009 		{
5010 			.path = bind_dir_s1d3,
5011 			.access = LANDLOCK_ACCESS_FS_EXECUTE,
5012 		},
5013 		{},
5014 	};
5015 
5016 	enforce_fs(_metadata,
5017 		   LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_EXECUTE,
5018 		   layer1);
5019 
5020 	/* Checks basic denied move. */
5021 	ASSERT_EQ(-1, rename(file1_s1d1, file1_s1d2));
5022 	ASSERT_EQ(EXDEV, errno);
5023 
5024 	/* Checks real cross-mount move (Landlock is not involved). */
5025 	ASSERT_EQ(-1, rename(file1_s2d1, file1_s2d2));
5026 	ASSERT_EQ(EXDEV, errno);
5027 
5028 	/* Checks move that will give more accesses. */
5029 	ASSERT_EQ(-1, rename(file1_s2d2, bind_file1_s1d3));
5030 	ASSERT_EQ(EXDEV, errno);
5031 
5032 	/* Checks legitimate downgrade move. */
5033 	ASSERT_EQ(0, rename(bind_file1_s1d3, file1_s2d2));
5034 }
5035 
5036 /*
5037  * Make sure access to file through a disconnected path works as expected.
5038  * This test moves s1d3 to s4d1.
5039  */
5040 TEST_F_FORK(layout1_bind, path_disconnected)
5041 {
5042 	const struct rule layer1_allow_all[] = {
5043 		{
5044 			.path = TMP_DIR,
5045 			.access = ACCESS_ALL,
5046 		},
5047 		{},
5048 	};
5049 	const struct rule layer2_allow_just_f1[] = {
5050 		{
5051 			.path = file1_s1d3,
5052 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
5053 		},
5054 		{},
5055 	};
5056 	const struct rule layer3_only_s1d2[] = {
5057 		{
5058 			.path = dir_s1d2,
5059 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
5060 		},
5061 		{},
5062 	};
5063 
5064 	/* Landlock should not deny access just because it is disconnected. */
5065 	int ruleset_fd_l1 =
5066 		create_ruleset(_metadata, ACCESS_ALL, layer1_allow_all);
5067 
5068 	/* Creates the new ruleset now before we move the dir containing the file. */
5069 	int ruleset_fd_l2 =
5070 		create_ruleset(_metadata, ACCESS_RW, layer2_allow_just_f1);
5071 	int ruleset_fd_l3 =
5072 		create_ruleset(_metadata, ACCESS_RW, layer3_only_s1d2);
5073 	int bind_s1d3_fd;
5074 
5075 	enforce_ruleset(_metadata, ruleset_fd_l1);
5076 	EXPECT_EQ(0, close(ruleset_fd_l1));
5077 
5078 	bind_s1d3_fd = open(bind_dir_s1d3, O_PATH | O_CLOEXEC);
5079 	ASSERT_LE(0, bind_s1d3_fd);
5080 
5081 	/* Tests access is possible before we move. */
5082 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file1_name, O_RDONLY));
5083 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file2_name, O_RDONLY));
5084 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, "..", O_RDONLY | O_DIRECTORY));
5085 
5086 	/* Makes it disconnected. */
5087 	ASSERT_EQ(0, rename(dir_s1d3, dir_s4d1))
5088 	{
5089 		TH_LOG("Failed to rename %s to %s: %s", dir_s1d3, dir_s4d1,
5090 		       strerror(errno));
5091 	}
5092 
5093 	/* Tests that access is still possible. */
5094 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file1_name, O_RDONLY));
5095 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file2_name, O_RDONLY));
5096 
5097 	/*
5098 	 * Tests that ".." is not possible (not because of Landlock, but just
5099 	 * because it's disconnected).
5100 	 */
5101 	EXPECT_EQ(ENOENT,
5102 		  test_open_rel(bind_s1d3_fd, "..", O_RDONLY | O_DIRECTORY));
5103 
5104 	/* This should still work with a narrower rule. */
5105 	enforce_ruleset(_metadata, ruleset_fd_l2);
5106 	EXPECT_EQ(0, close(ruleset_fd_l2));
5107 
5108 	EXPECT_EQ(0, test_open(file1_s4d1, O_RDONLY));
5109 	/*
5110 	 * Accessing a file through a disconnected file descriptor can still be
5111 	 * allowed by a rule tied to this file, even if it is no longer visible in
5112 	 * its mount point.
5113 	 */
5114 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file1_name, O_RDONLY));
5115 	EXPECT_EQ(EACCES, test_open_rel(bind_s1d3_fd, file2_name, O_RDONLY));
5116 
5117 	enforce_ruleset(_metadata, ruleset_fd_l3);
5118 	EXPECT_EQ(0, close(ruleset_fd_l3));
5119 
5120 	EXPECT_EQ(EACCES, test_open(file1_s4d1, O_RDONLY));
5121 	/*
5122 	 * Accessing a file through a disconnected file descriptor can still be
5123 	 * allowed by a rule tied to the original mount point, even if it is no
5124 	 * longer visible in its mount point.
5125 	 */
5126 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file1_name, O_RDONLY));
5127 	EXPECT_EQ(EACCES, test_open_rel(bind_s1d3_fd, file2_name, O_RDONLY));
5128 }
5129 
5130 /*
5131  * Test that renameat with disconnected paths works under Landlock.  This test
5132  * moves s1d3 to s4d2, so that we can have a rule allowing refers on the move
5133  * target's immediate parent.
5134  */
5135 TEST_F_FORK(layout1_bind, path_disconnected_rename)
5136 {
5137 	const struct rule layer1[] = {
5138 		{
5139 			.path = dir_s1d2,
5140 			.access = LANDLOCK_ACCESS_FS_REFER |
5141 				  LANDLOCK_ACCESS_FS_MAKE_DIR |
5142 				  LANDLOCK_ACCESS_FS_REMOVE_DIR |
5143 				  LANDLOCK_ACCESS_FS_MAKE_REG |
5144 				  LANDLOCK_ACCESS_FS_REMOVE_FILE |
5145 				  LANDLOCK_ACCESS_FS_READ_FILE,
5146 		},
5147 		{
5148 			.path = dir_s4d1,
5149 			.access = LANDLOCK_ACCESS_FS_REFER |
5150 				  LANDLOCK_ACCESS_FS_MAKE_DIR |
5151 				  LANDLOCK_ACCESS_FS_REMOVE_DIR |
5152 				  LANDLOCK_ACCESS_FS_MAKE_REG |
5153 				  LANDLOCK_ACCESS_FS_REMOVE_FILE |
5154 				  LANDLOCK_ACCESS_FS_READ_FILE,
5155 		},
5156 		{}
5157 	};
5158 
5159 	/* This layer only handles LANDLOCK_ACCESS_FS_READ_FILE. */
5160 	const struct rule layer2_only_s1d2[] = {
5161 		{
5162 			.path = dir_s1d2,
5163 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
5164 		},
5165 		{},
5166 	};
5167 	int ruleset_fd_l1, ruleset_fd_l2;
5168 	pid_t child_pid;
5169 	int bind_s1d3_fd, status;
5170 
5171 	ASSERT_EQ(0, mkdir(dir_s4d1, 0755))
5172 	{
5173 		TH_LOG("Failed to create %s: %s", dir_s4d1, strerror(errno));
5174 	}
5175 	ruleset_fd_l1 = create_ruleset(_metadata, ACCESS_ALL, layer1);
5176 	ruleset_fd_l2 = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
5177 				       layer2_only_s1d2);
5178 
5179 	enforce_ruleset(_metadata, ruleset_fd_l1);
5180 	EXPECT_EQ(0, close(ruleset_fd_l1));
5181 
5182 	bind_s1d3_fd = open(bind_dir_s1d3, O_PATH | O_CLOEXEC);
5183 	ASSERT_LE(0, bind_s1d3_fd);
5184 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file1_name, O_RDONLY));
5185 
5186 	/* Tests ENOENT priority over EACCES for disconnected directory. */
5187 	EXPECT_EQ(EACCES, test_open_rel(bind_s1d3_fd, "..", O_DIRECTORY));
5188 	ASSERT_EQ(0, rename(dir_s1d3, dir_s4d2))
5189 	{
5190 		TH_LOG("Failed to rename %s to %s: %s", dir_s1d3, dir_s4d2,
5191 		       strerror(errno));
5192 	}
5193 	EXPECT_EQ(ENOENT, test_open_rel(bind_s1d3_fd, "..", O_DIRECTORY));
5194 
5195 	/*
5196 	 * The file is no longer under s1d2 but we should still be able to access it
5197 	 * with layer 2 because its mount point is evaluated as the first valid
5198 	 * directory because it was initially a parent.  Do a fork to test this so
5199 	 * we don't prevent ourselves from renaming it back later.
5200 	 */
5201 	child_pid = fork();
5202 	ASSERT_LE(0, child_pid);
5203 	if (child_pid == 0) {
5204 		enforce_ruleset(_metadata, ruleset_fd_l2);
5205 		EXPECT_EQ(0, close(ruleset_fd_l2));
5206 		EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file1_name, O_RDONLY));
5207 		EXPECT_EQ(EACCES, test_open(file1_s4d2, O_RDONLY));
5208 
5209 		/*
5210 		 * Tests that access widening checks indeed prevents us from renaming it
5211 		 * back.
5212 		 */
5213 		EXPECT_EQ(-1, rename(dir_s4d2, dir_s1d3));
5214 		EXPECT_EQ(EXDEV, errno);
5215 
5216 		/*
5217 		 * Including through the now disconnected fd (but it should return
5218 		 * EXDEV).
5219 		 */
5220 		EXPECT_EQ(-1, renameat(bind_s1d3_fd, file1_name, AT_FDCWD,
5221 				       file1_s2d2));
5222 		EXPECT_EQ(EXDEV, errno);
5223 		_exit(_metadata->exit_code);
5224 		return;
5225 	}
5226 
5227 	EXPECT_EQ(child_pid, waitpid(child_pid, &status, 0));
5228 	EXPECT_EQ(1, WIFEXITED(status));
5229 	EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
5230 
5231 	ASSERT_EQ(0, rename(dir_s4d2, dir_s1d3))
5232 	{
5233 		TH_LOG("Failed to rename %s back to %s: %s", dir_s4d1, dir_s1d3,
5234 		       strerror(errno));
5235 	}
5236 
5237 	/* Now checks that we can access it under l2. */
5238 	child_pid = fork();
5239 	ASSERT_LE(0, child_pid);
5240 	if (child_pid == 0) {
5241 		enforce_ruleset(_metadata, ruleset_fd_l2);
5242 		EXPECT_EQ(0, close(ruleset_fd_l2));
5243 		EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file1_name, O_RDONLY));
5244 		EXPECT_EQ(0, test_open(file1_s1d3, O_RDONLY));
5245 		_exit(_metadata->exit_code);
5246 		return;
5247 	}
5248 
5249 	EXPECT_EQ(child_pid, waitpid(child_pid, &status, 0));
5250 	EXPECT_EQ(1, WIFEXITED(status));
5251 	EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
5252 
5253 	/*
5254 	 * Also test that we can rename via a disconnected path.  We move the
5255 	 * dir back to the disconnected place first, then we rename file1 to
5256 	 * file2 through our dir fd.
5257 	 */
5258 	ASSERT_EQ(0, rename(dir_s1d3, dir_s4d2))
5259 	{
5260 		TH_LOG("Failed to rename %s to %s: %s", dir_s1d3, dir_s4d2,
5261 		       strerror(errno));
5262 	}
5263 	ASSERT_EQ(0,
5264 		  renameat(bind_s1d3_fd, file1_name, bind_s1d3_fd, file2_name))
5265 	{
5266 		TH_LOG("Failed to rename %s to %s within disconnected %s: %s",
5267 		       file1_name, file2_name, bind_dir_s1d3, strerror(errno));
5268 	}
5269 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file2_name, O_RDONLY));
5270 	ASSERT_EQ(0, renameat(bind_s1d3_fd, file2_name, AT_FDCWD, file1_s2d2))
5271 	{
5272 		TH_LOG("Failed to rename %s to %s through disconnected %s: %s",
5273 		       file2_name, file1_s2d2, bind_dir_s1d3, strerror(errno));
5274 	}
5275 	EXPECT_EQ(0, test_open(file1_s2d2, O_RDONLY));
5276 	EXPECT_EQ(0, test_open(file1_s1d2, O_RDONLY));
5277 
5278 	/* Move it back using the disconnected path as the target. */
5279 	ASSERT_EQ(0, renameat(AT_FDCWD, file1_s2d2, bind_s1d3_fd, file1_name))
5280 	{
5281 		TH_LOG("Failed to rename %s to %s through disconnected %s: %s",
5282 		       file1_s1d2, file1_name, bind_dir_s1d3, strerror(errno));
5283 	}
5284 
5285 	/* Now make it connected again. */
5286 	ASSERT_EQ(0, rename(dir_s4d2, dir_s1d3))
5287 	{
5288 		TH_LOG("Failed to rename %s back to %s: %s", dir_s4d2, dir_s1d3,
5289 		       strerror(errno));
5290 	}
5291 
5292 	/* Checks again that we can access it under l2. */
5293 	enforce_ruleset(_metadata, ruleset_fd_l2);
5294 	EXPECT_EQ(0, close(ruleset_fd_l2));
5295 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file1_name, O_RDONLY));
5296 	EXPECT_EQ(0, test_open(file1_s1d3, O_RDONLY));
5297 }
5298 
5299 /*
5300  * Test that linkat(2) with disconnected paths works under Landlock. This
5301  * test moves s1d3 to s4d1.
5302  */
5303 TEST_F_FORK(layout1_bind, path_disconnected_link)
5304 {
5305 	/* Ruleset to be applied after renaming s1d3 to s4d1. */
5306 	const struct rule layer1[] = {
5307 		{
5308 			.path = dir_s4d1,
5309 			.access = LANDLOCK_ACCESS_FS_REFER |
5310 				  LANDLOCK_ACCESS_FS_READ_FILE |
5311 				  LANDLOCK_ACCESS_FS_MAKE_REG |
5312 				  LANDLOCK_ACCESS_FS_REMOVE_FILE,
5313 		},
5314 		{
5315 			.path = dir_s2d2,
5316 			.access = LANDLOCK_ACCESS_FS_REFER |
5317 				  LANDLOCK_ACCESS_FS_READ_FILE |
5318 				  LANDLOCK_ACCESS_FS_MAKE_REG |
5319 				  LANDLOCK_ACCESS_FS_REMOVE_FILE,
5320 		},
5321 		{}
5322 	};
5323 	int bind_s1d3_fd;
5324 
5325 	/* Removes unneeded files created by layout1, otherwise it will EEXIST. */
5326 	ASSERT_EQ(0, unlink(file1_s1d2));
5327 	ASSERT_EQ(0, unlink(file2_s1d3));
5328 
5329 	bind_s1d3_fd = open(bind_dir_s1d3, O_PATH | O_CLOEXEC);
5330 	ASSERT_LE(0, bind_s1d3_fd);
5331 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file1_name, O_RDONLY));
5332 
5333 	/* Disconnects bind_s1d3_fd. */
5334 	ASSERT_EQ(0, rename(dir_s1d3, dir_s4d1))
5335 	{
5336 		TH_LOG("Failed to rename %s to %s: %s", dir_s1d3, dir_s4d1,
5337 		       strerror(errno));
5338 	}
5339 
5340 	/* Need this later to test different parent link. */
5341 	ASSERT_EQ(0, mkdir(dir_s4d2, 0755))
5342 	{
5343 		TH_LOG("Failed to create %s: %s", dir_s4d2, strerror(errno));
5344 	}
5345 
5346 	enforce_fs(_metadata, ACCESS_ALL, layer1);
5347 
5348 	/* From disconnected to connected. */
5349 	ASSERT_EQ(0, linkat(bind_s1d3_fd, file1_name, AT_FDCWD, file1_s2d2, 0))
5350 	{
5351 		TH_LOG("Failed to link %s to %s via disconnected %s: %s",
5352 		       file1_name, file1_s2d2, bind_dir_s1d3, strerror(errno));
5353 	}
5354 
5355 	/* Tests that we can access via the new link... */
5356 	EXPECT_EQ(0, test_open(file1_s2d2, O_RDONLY))
5357 	{
5358 		TH_LOG("Failed to open newly linked %s: %s", file1_s2d2,
5359 		       strerror(errno));
5360 	}
5361 
5362 	/* ...as well as the old one. */
5363 	EXPECT_EQ(0, test_open(file1_s4d1, O_RDONLY))
5364 	{
5365 		TH_LOG("Failed to open original %s: %s", file1_s4d1,
5366 		       strerror(errno));
5367 	}
5368 
5369 	/* From connected to disconnected. */
5370 	ASSERT_EQ(0, unlink(file1_s4d1));
5371 	ASSERT_EQ(0, linkat(AT_FDCWD, file1_s2d2, bind_s1d3_fd, file2_name, 0))
5372 	{
5373 		TH_LOG("Failed to link %s to %s via disconnected %s: %s",
5374 		       file1_s2d2, file2_name, bind_dir_s1d3, strerror(errno));
5375 	}
5376 	EXPECT_EQ(0, test_open(file2_s4d1, O_RDONLY));
5377 	ASSERT_EQ(0, unlink(file1_s2d2));
5378 
5379 	/* From disconnected to disconnected (same parent). */
5380 	ASSERT_EQ(0,
5381 		  linkat(bind_s1d3_fd, file2_name, bind_s1d3_fd, file1_name, 0))
5382 	{
5383 		TH_LOG("Failed to link %s to %s within disconnected %s: %s",
5384 		       file2_name, file1_name, bind_dir_s1d3, strerror(errno));
5385 	}
5386 	EXPECT_EQ(0, test_open(file1_s4d1, O_RDONLY))
5387 	{
5388 		TH_LOG("Failed to open newly linked %s: %s", file1_s4d1,
5389 		       strerror(errno));
5390 	}
5391 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file1_name, O_RDONLY))
5392 	{
5393 		TH_LOG("Failed to open %s through newly created link under disconnected path: %s",
5394 		       file1_name, strerror(errno));
5395 	}
5396 	ASSERT_EQ(0, unlink(file2_s4d1));
5397 
5398 	/* From disconnected to disconnected (different parent). */
5399 	ASSERT_EQ(0,
5400 		  linkat(bind_s1d3_fd, file1_name, bind_s1d3_fd, "s4d2/f1", 0))
5401 	{
5402 		TH_LOG("Failed to link %s to %s within disconnected %s: %s",
5403 		       file1_name, "s4d2/f1", bind_dir_s1d3, strerror(errno));
5404 	}
5405 	EXPECT_EQ(0, test_open(file1_s4d2, O_RDONLY))
5406 	{
5407 		TH_LOG("Failed to open %s after link: %s", file1_s4d2,
5408 		       strerror(errno));
5409 	}
5410 	EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, "s4d2/f1", O_RDONLY))
5411 	{
5412 		TH_LOG("Failed to open %s through disconnected path after link: %s",
5413 		       "s4d2/f1", strerror(errno));
5414 	}
5415 }
5416 
5417 /*
5418  * layout4_disconnected_leafs with bind mount and renames:
5419  *
5420  * tmp
5421  * ├── s1d1
5422  * │   └── s1d2 [source of the bind mount]
5423  * │       ├── s1d31
5424  * │       │   └── s1d41 [now renamed beneath s3d1]
5425  * │       │       ├── f1
5426  * │       │       └── f2
5427  * │       └── s1d32
5428  * │           └── s1d42 [now renamed beneath s4d1]
5429  * │               ├── f3
5430  * │               └── f4
5431  * ├── s2d1
5432  * │   └── s2d2 [bind mount of s1d2]
5433  * │       ├── s1d31
5434  * │       │   └── s1d41 [opened FD, now renamed beneath s3d1]
5435  * │       │       ├── f1
5436  * │       │       └── f2
5437  * │       └── s1d32
5438  * │           └── s1d42 [opened FD, now renamed beneath s4d1]
5439  * │               ├── f3
5440  * │               └── f4
5441  * ├── s3d1
5442  * │   └── s1d41 [renamed here]
5443  * │       ├── f1
5444  * │       └── f2
5445  * └── s4d1
5446  *     └── s1d42 [renamed here]
5447  *         ├── f3
5448  *         └── f4
5449  */
5450 /* clang-format off */
5451 FIXTURE(layout4_disconnected_leafs) {
5452 	int s2d2_fd;
5453 };
5454 /* clang-format on */
5455 
5456 FIXTURE_SETUP(layout4_disconnected_leafs)
5457 {
5458 	prepare_layout(_metadata);
5459 
5460 	create_file(_metadata, TMP_DIR "/s1d1/s1d2/s1d31/s1d41/f1");
5461 	create_file(_metadata, TMP_DIR "/s1d1/s1d2/s1d31/s1d41/f2");
5462 	create_file(_metadata, TMP_DIR "/s1d1/s1d2/s1d32/s1d42/f3");
5463 	create_file(_metadata, TMP_DIR "/s1d1/s1d2/s1d32/s1d42/f4");
5464 	create_directory(_metadata, TMP_DIR "/s2d1/s2d2");
5465 	create_directory(_metadata, TMP_DIR "/s3d1");
5466 	create_directory(_metadata, TMP_DIR "/s4d1");
5467 
5468 	self->s2d2_fd =
5469 		open(TMP_DIR "/s2d1/s2d2", O_DIRECTORY | O_PATH | O_CLOEXEC);
5470 	ASSERT_LE(0, self->s2d2_fd);
5471 
5472 	set_cap(_metadata, CAP_SYS_ADMIN);
5473 	ASSERT_EQ(0, mount(TMP_DIR "/s1d1/s1d2", TMP_DIR "/s2d1/s2d2", NULL,
5474 			   MS_BIND, NULL));
5475 	clear_cap(_metadata, CAP_SYS_ADMIN);
5476 }
5477 
5478 FIXTURE_TEARDOWN_PARENT(layout4_disconnected_leafs)
5479 {
5480 	/* umount(TMP_DIR "/s2d1") is handled by namespace lifetime. */
5481 
5482 	/* Removes files after renames. */
5483 	remove_path(TMP_DIR "/s3d1/s1d41/f1");
5484 	remove_path(TMP_DIR "/s3d1/s1d41/f2");
5485 	remove_path(TMP_DIR "/s4d1/s1d42/f1");
5486 	remove_path(TMP_DIR "/s4d1/s1d42/f3");
5487 	remove_path(TMP_DIR "/s4d1/s1d42/f4");
5488 	remove_path(TMP_DIR "/s4d1/s1d42/f5");
5489 
5490 	cleanup_layout(_metadata);
5491 }
5492 
5493 FIXTURE_VARIANT(layout4_disconnected_leafs)
5494 {
5495 	/*
5496 	 * Parent of the bind mount source.  It should always be ignored when
5497 	 * testing against files under the s1d41 or s1d42 disconnected directories.
5498 	 */
5499 	const __u64 allowed_s1d1;
5500 	/*
5501 	 * Source of bind mount (to s2d2).  It should always be enforced when
5502 	 * testing against files under the s1d41 or s1d42 disconnected directories.
5503 	 */
5504 	const __u64 allowed_s1d2;
5505 	/*
5506 	 * Original parent of s1d41.  It should always be ignored when testing
5507 	 * against files under the s1d41 disconnected directory.
5508 	 */
5509 	const __u64 allowed_s1d31;
5510 	/*
5511 	 * Original parent of s1d42.  It should always be ignored when testing
5512 	 * against files under the s1d42 disconnected directory.
5513 	 */
5514 	const __u64 allowed_s1d32;
5515 	/*
5516 	 * Opened and disconnected source directory.  It should always be enforced
5517 	 * when testing against files under the s1d41 disconnected directory.
5518 	 */
5519 	const __u64 allowed_s1d41;
5520 	/*
5521 	 * Opened and disconnected source directory.  It should always be enforced
5522 	 * when testing against files under the s1d42 disconnected directory.
5523 	 */
5524 	const __u64 allowed_s1d42;
5525 	/*
5526 	 * File in the s1d41 disconnected directory.  It should always be enforced
5527 	 * when testing against itself under the s1d41 disconnected directory.
5528 	 */
5529 	const __u64 allowed_f1;
5530 	/*
5531 	 * File in the s1d41 disconnected directory.  It should always be enforced
5532 	 * when testing against itself under the s1d41 disconnected directory.
5533 	 */
5534 	const __u64 allowed_f2;
5535 	/*
5536 	 * File in the s1d42 disconnected directory.  It should always be enforced
5537 	 * when testing against itself under the s1d42 disconnected directory.
5538 	 */
5539 	const __u64 allowed_f3;
5540 	/*
5541 	 * Parent of the bind mount destination.  It should always be enforced when
5542 	 * testing against files under the s1d41 or s1d42 disconnected directories.
5543 	 */
5544 	const __u64 allowed_s2d1;
5545 	/*
5546 	 * Directory covered by the bind mount.  It should always be ignored when
5547 	 * testing against files under the s1d41 or s1d42 disconnected directories.
5548 	 */
5549 	const __u64 allowed_s2d2;
5550 	/*
5551 	 * New parent of the renamed s1d41.  It should always be ignored when
5552 	 * testing against files under the s1d41 disconnected directory.
5553 	 */
5554 	const __u64 allowed_s3d1;
5555 	/*
5556 	 * New parent of the renamed s1d42.  It should always be ignored when
5557 	 * testing against files under the s1d42 disconnected directory.
5558 	 */
5559 	const __u64 allowed_s4d1;
5560 
5561 	/* Expected result of the call to open([fd:s1d41]/f1, O_RDONLY). */
5562 	const int expected_read_result;
5563 	/* Expected result of the call to renameat([fd:s1d41]/f1, [fd:s1d42]/f1). */
5564 	const int expected_rename_result;
5565 	/*
5566 	 * Expected result of the call to renameat([fd:s1d41]/f2, [fd:s1d42]/f3,
5567 	 * RENAME_EXCHANGE).
5568 	 */
5569 	const int expected_exchange_result;
5570 	/* Expected result of the call to renameat([fd:s1d42]/f4, [fd:s1d42]/f5). */
5571 	const int expected_same_dir_rename_result;
5572 };
5573 
5574 /* clang-format off */
5575 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d1_mount_src_parent) {
5576 	/* clang-format on */
5577 	.allowed_s1d1 = LANDLOCK_ACCESS_FS_REFER |
5578 			LANDLOCK_ACCESS_FS_READ_FILE |
5579 			LANDLOCK_ACCESS_FS_EXECUTE |
5580 			LANDLOCK_ACCESS_FS_MAKE_REG,
5581 	.expected_read_result = EACCES,
5582 	.expected_same_dir_rename_result = EACCES,
5583 	.expected_rename_result = EACCES,
5584 	.expected_exchange_result = EACCES,
5585 };
5586 
5587 /* clang-format off */
5588 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d2_mount_src_refer) {
5589 	/* clang-format on */
5590 	.allowed_s1d2 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE,
5591 	.expected_read_result = 0,
5592 	.expected_same_dir_rename_result = EACCES,
5593 	.expected_rename_result = EACCES,
5594 	.expected_exchange_result = EACCES,
5595 };
5596 
5597 /* clang-format off */
5598 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d2_mount_src_create) {
5599 	/* clang-format on */
5600 	.allowed_s1d2 = LANDLOCK_ACCESS_FS_READ_FILE |
5601 			LANDLOCK_ACCESS_FS_MAKE_REG,
5602 	.expected_read_result = 0,
5603 	.expected_same_dir_rename_result = 0,
5604 	.expected_rename_result = EXDEV,
5605 	.expected_exchange_result = EXDEV,
5606 };
5607 
5608 /* clang-format off */
5609 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d2_mount_src_rename) {
5610 	/* clang-format on */
5611 	.allowed_s1d2 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
5612 	.expected_read_result = EACCES,
5613 	.expected_same_dir_rename_result = 0,
5614 	.expected_rename_result = 0,
5615 	.expected_exchange_result = 0,
5616 };
5617 
5618 /* clang-format off */
5619 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d31_s1d32_old_parent) {
5620 	/* clang-format on */
5621 	.allowed_s1d31 = LANDLOCK_ACCESS_FS_REFER |
5622 			 LANDLOCK_ACCESS_FS_READ_FILE |
5623 			 LANDLOCK_ACCESS_FS_EXECUTE |
5624 			 LANDLOCK_ACCESS_FS_MAKE_REG,
5625 	.allowed_s1d32 = LANDLOCK_ACCESS_FS_REFER |
5626 			 LANDLOCK_ACCESS_FS_READ_FILE |
5627 			 LANDLOCK_ACCESS_FS_EXECUTE |
5628 			 LANDLOCK_ACCESS_FS_MAKE_REG,
5629 	.expected_read_result = EACCES,
5630 	.expected_same_dir_rename_result = EACCES,
5631 	.expected_rename_result = EACCES,
5632 	.expected_exchange_result = EACCES,
5633 };
5634 
5635 /* clang-format off */
5636 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d41_s1d42_disconnected_refer) {
5637 	/* clang-format on */
5638 	.allowed_s1d41 = LANDLOCK_ACCESS_FS_REFER |
5639 			 LANDLOCK_ACCESS_FS_READ_FILE,
5640 	.allowed_s1d42 = LANDLOCK_ACCESS_FS_REFER |
5641 			 LANDLOCK_ACCESS_FS_READ_FILE,
5642 	.expected_read_result = 0,
5643 	.expected_same_dir_rename_result = EACCES,
5644 	.expected_rename_result = EACCES,
5645 	.expected_exchange_result = EACCES,
5646 };
5647 
5648 /* clang-format off */
5649 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d41_s1d42_disconnected_create) {
5650 	/* clang-format on */
5651 	.allowed_s1d41 = LANDLOCK_ACCESS_FS_READ_FILE |
5652 			 LANDLOCK_ACCESS_FS_MAKE_REG,
5653 	.allowed_s1d42 = LANDLOCK_ACCESS_FS_READ_FILE |
5654 			 LANDLOCK_ACCESS_FS_MAKE_REG,
5655 	.expected_read_result = 0,
5656 	.expected_same_dir_rename_result = 0,
5657 	.expected_rename_result = EXDEV,
5658 	.expected_exchange_result = EXDEV,
5659 };
5660 
5661 /* clang-format off */
5662 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d41_s1d42_disconnected_rename_even) {
5663 	/* clang-format on */
5664 	.allowed_s1d41 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
5665 	.allowed_s1d42 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
5666 	.expected_read_result = EACCES,
5667 	.expected_same_dir_rename_result = 0,
5668 	.expected_rename_result = 0,
5669 	.expected_exchange_result = 0,
5670 };
5671 
5672 /* The destination directory has more access right. */
5673 /* clang-format off */
5674 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d41_s1d42_disconnected_rename_more) {
5675 	/* clang-format on */
5676 	.allowed_s1d41 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
5677 	.allowed_s1d42 = LANDLOCK_ACCESS_FS_REFER |
5678 			 LANDLOCK_ACCESS_FS_MAKE_REG |
5679 			 LANDLOCK_ACCESS_FS_EXECUTE,
5680 	.expected_read_result = EACCES,
5681 	.expected_same_dir_rename_result = 0,
5682 	/* Access denied. */
5683 	.expected_rename_result = EXDEV,
5684 	.expected_exchange_result = EXDEV,
5685 };
5686 
5687 /* The destination directory has less access right. */
5688 /* clang-format off */
5689 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d41_s1d42_disconnected_rename_less) {
5690 	/* clang-format on */
5691 	.allowed_s1d41 = LANDLOCK_ACCESS_FS_REFER |
5692 			 LANDLOCK_ACCESS_FS_MAKE_REG |
5693 			 LANDLOCK_ACCESS_FS_EXECUTE,
5694 	.allowed_s1d42 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
5695 	.expected_read_result = EACCES,
5696 	.expected_same_dir_rename_result = 0,
5697 	/* Access allowed. */
5698 	.expected_rename_result = 0,
5699 	.expected_exchange_result = EXDEV,
5700 };
5701 
5702 /* clang-format off */
5703 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s2d1_mount_dst_parent_create) {
5704 	/* clang-format on */
5705 	.allowed_s2d1 = LANDLOCK_ACCESS_FS_READ_FILE |
5706 			LANDLOCK_ACCESS_FS_MAKE_REG,
5707 	.expected_read_result = 0,
5708 	.expected_same_dir_rename_result = 0,
5709 	.expected_rename_result = EXDEV,
5710 	.expected_exchange_result = EXDEV,
5711 };
5712 
5713 /* clang-format off */
5714 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s2d1_mount_dst_parent_refer) {
5715 	/* clang-format on */
5716 	.allowed_s2d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE,
5717 	.expected_read_result = 0,
5718 	.expected_same_dir_rename_result = EACCES,
5719 	.expected_rename_result = EACCES,
5720 	.expected_exchange_result = EACCES,
5721 };
5722 
5723 /* clang-format off */
5724 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s2d1_mount_dst_parent_mini) {
5725 	/* clang-format on */
5726 	.allowed_s2d1 = LANDLOCK_ACCESS_FS_REFER |
5727 			LANDLOCK_ACCESS_FS_READ_FILE |
5728 			LANDLOCK_ACCESS_FS_MAKE_REG,
5729 	.expected_read_result = 0,
5730 	.expected_same_dir_rename_result = 0,
5731 	.expected_rename_result = 0,
5732 	.expected_exchange_result = 0,
5733 };
5734 
5735 /* clang-format off */
5736 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s2d2_covered_by_mount) {
5737 	/* clang-format on */
5738 	.allowed_s2d2 = LANDLOCK_ACCESS_FS_REFER |
5739 			LANDLOCK_ACCESS_FS_READ_FILE |
5740 			LANDLOCK_ACCESS_FS_EXECUTE |
5741 			LANDLOCK_ACCESS_FS_MAKE_REG,
5742 	.expected_read_result = EACCES,
5743 	.expected_same_dir_rename_result = EACCES,
5744 	.expected_rename_result = EACCES,
5745 	.expected_exchange_result = EACCES,
5746 };
5747 
5748 /* Tests collect_domain_accesses(). */
5749 /* clang-format off */
5750 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s3d1_s4d1_new_parent_refer) {
5751 	/* clang-format on */
5752 	.allowed_s3d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE,
5753 	.allowed_s4d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE,
5754 	.expected_read_result = 0,
5755 	.expected_same_dir_rename_result = EACCES,
5756 	.expected_rename_result = EACCES,
5757 	.expected_exchange_result = EACCES,
5758 };
5759 
5760 /* clang-format off */
5761 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s3d1_s4d1_new_parent_create) {
5762 	/* clang-format on */
5763 	.allowed_s3d1 = LANDLOCK_ACCESS_FS_READ_FILE |
5764 			LANDLOCK_ACCESS_FS_MAKE_REG,
5765 	.allowed_s4d1 = LANDLOCK_ACCESS_FS_READ_FILE |
5766 			LANDLOCK_ACCESS_FS_MAKE_REG,
5767 	.expected_read_result = 0,
5768 	.expected_same_dir_rename_result = 0,
5769 	.expected_rename_result = EXDEV,
5770 	.expected_exchange_result = EXDEV,
5771 };
5772 
5773 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs,
5774 		    s3d1_s4d1_disconnected_rename_even){
5775 	/* clang-format on */
5776 	.allowed_s3d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
5777 	.allowed_s4d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
5778 	.expected_read_result = EACCES,
5779 	.expected_same_dir_rename_result = 0,
5780 	.expected_rename_result = 0,
5781 	.expected_exchange_result = 0,
5782 };
5783 
5784 /* The destination directory has more access right. */
5785 /* clang-format off */
5786 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s3d1_s4d1_disconnected_rename_more) {
5787 	/* clang-format on */
5788 	.allowed_s3d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
5789 	.allowed_s4d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG |
5790 			LANDLOCK_ACCESS_FS_EXECUTE,
5791 	.expected_read_result = EACCES,
5792 	.expected_same_dir_rename_result = 0,
5793 	/* Access denied. */
5794 	.expected_rename_result = EXDEV,
5795 	.expected_exchange_result = EXDEV,
5796 };
5797 
5798 /* The destination directory has less access right. */
5799 /* clang-format off */
5800 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s3d1_s4d1_disconnected_rename_less) {
5801 	/* clang-format on */
5802 	.allowed_s3d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG |
5803 			LANDLOCK_ACCESS_FS_EXECUTE,
5804 	.allowed_s4d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
5805 	.expected_read_result = EACCES,
5806 	.expected_same_dir_rename_result = 0,
5807 	/* Access allowed. */
5808 	.expected_rename_result = 0,
5809 	.expected_exchange_result = EXDEV,
5810 };
5811 
5812 /* clang-format off */
5813 FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, f1_f2_f3) {
5814 	/* clang-format on */
5815 	.allowed_f1 = LANDLOCK_ACCESS_FS_READ_FILE,
5816 	.allowed_f2 = LANDLOCK_ACCESS_FS_READ_FILE,
5817 	.allowed_f3 = LANDLOCK_ACCESS_FS_READ_FILE,
5818 	.expected_read_result = 0,
5819 	.expected_same_dir_rename_result = EACCES,
5820 	.expected_rename_result = EACCES,
5821 	.expected_exchange_result = EACCES,
5822 };
5823 
5824 TEST_F_FORK(layout4_disconnected_leafs, read_rename_exchange)
5825 {
5826 	const __u64 handled_access =
5827 		LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE |
5828 		LANDLOCK_ACCESS_FS_EXECUTE | LANDLOCK_ACCESS_FS_MAKE_REG;
5829 	const struct rule rules[] = {
5830 		{
5831 			.path = TMP_DIR "/s1d1",
5832 			.access = variant->allowed_s1d1,
5833 		},
5834 		{
5835 			.path = TMP_DIR "/s1d1/s1d2",
5836 			.access = variant->allowed_s1d2,
5837 		},
5838 		{
5839 			.path = TMP_DIR "/s1d1/s1d2/s1d31",
5840 			.access = variant->allowed_s1d31,
5841 		},
5842 		{
5843 			.path = TMP_DIR "/s1d1/s1d2/s1d32",
5844 			.access = variant->allowed_s1d32,
5845 		},
5846 		{
5847 			.path = TMP_DIR "/s1d1/s1d2/s1d31/s1d41",
5848 			.access = variant->allowed_s1d41,
5849 		},
5850 		{
5851 			.path = TMP_DIR "/s1d1/s1d2/s1d32/s1d42",
5852 			.access = variant->allowed_s1d42,
5853 		},
5854 		{
5855 			.path = TMP_DIR "/s1d1/s1d2/s1d31/s1d41/f1",
5856 			.access = variant->allowed_f1,
5857 		},
5858 		{
5859 			.path = TMP_DIR "/s1d1/s1d2/s1d31/s1d41/f2",
5860 			.access = variant->allowed_f2,
5861 		},
5862 		{
5863 			.path = TMP_DIR "/s1d1/s1d2/s1d32/s1d42/f3",
5864 			.access = variant->allowed_f3,
5865 		},
5866 		{
5867 			.path = TMP_DIR "/s2d1",
5868 			.access = variant->allowed_s2d1,
5869 		},
5870 		/* s2d2_fd */
5871 		{
5872 			.path = TMP_DIR "/s3d1",
5873 			.access = variant->allowed_s3d1,
5874 		},
5875 		{
5876 			.path = TMP_DIR "/s4d1",
5877 			.access = variant->allowed_s4d1,
5878 		},
5879 		{},
5880 	};
5881 	int ruleset_fd, s1d41_bind_fd, s1d42_bind_fd;
5882 
5883 	ruleset_fd = create_ruleset(_metadata, handled_access, rules);
5884 
5885 	/* Adds rule for the covered directory. */
5886 	if (variant->allowed_s2d2) {
5887 		ASSERT_EQ(0, landlock_add_rule(
5888 				     ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
5889 				     &(struct landlock_path_beneath_attr){
5890 					     .parent_fd = self->s2d2_fd,
5891 					     .allowed_access =
5892 						     variant->allowed_s2d2,
5893 				     },
5894 				     0));
5895 	}
5896 	EXPECT_EQ(0, close(self->s2d2_fd));
5897 
5898 	s1d41_bind_fd = open(TMP_DIR "/s2d1/s2d2/s1d31/s1d41",
5899 			     O_DIRECTORY | O_PATH | O_CLOEXEC);
5900 	ASSERT_LE(0, s1d41_bind_fd);
5901 	s1d42_bind_fd = open(TMP_DIR "/s2d1/s2d2/s1d32/s1d42",
5902 			     O_DIRECTORY | O_PATH | O_CLOEXEC);
5903 	ASSERT_LE(0, s1d42_bind_fd);
5904 
5905 	/* Disconnects and checks source and destination directories. */
5906 	EXPECT_EQ(0, test_open_rel(s1d41_bind_fd, "..", O_DIRECTORY));
5907 	EXPECT_EQ(0, test_open_rel(s1d42_bind_fd, "..", O_DIRECTORY));
5908 	/* Renames to make it accessible through s3d1/s1d41 */
5909 	ASSERT_EQ(0, test_renameat(AT_FDCWD, TMP_DIR "/s1d1/s1d2/s1d31/s1d41",
5910 				   AT_FDCWD, TMP_DIR "/s3d1/s1d41"));
5911 	/* Renames to make it accessible through s4d1/s1d42 */
5912 	ASSERT_EQ(0, test_renameat(AT_FDCWD, TMP_DIR "/s1d1/s1d2/s1d32/s1d42",
5913 				   AT_FDCWD, TMP_DIR "/s4d1/s1d42"));
5914 	EXPECT_EQ(ENOENT, test_open_rel(s1d41_bind_fd, "..", O_DIRECTORY));
5915 	EXPECT_EQ(ENOENT, test_open_rel(s1d42_bind_fd, "..", O_DIRECTORY));
5916 
5917 	enforce_ruleset(_metadata, ruleset_fd);
5918 	EXPECT_EQ(0, close(ruleset_fd));
5919 
5920 	EXPECT_EQ(variant->expected_read_result,
5921 		  test_open_rel(s1d41_bind_fd, "f1", O_RDONLY));
5922 
5923 	EXPECT_EQ(variant->expected_rename_result,
5924 		  test_renameat(s1d41_bind_fd, "f1", s1d42_bind_fd, "f1"));
5925 	EXPECT_EQ(variant->expected_exchange_result,
5926 		  test_exchangeat(s1d41_bind_fd, "f2", s1d42_bind_fd, "f3"));
5927 
5928 	EXPECT_EQ(variant->expected_same_dir_rename_result,
5929 		  test_renameat(s1d42_bind_fd, "f4", s1d42_bind_fd, "f5"));
5930 }
5931 
5932 /*
5933  * layout5_disconnected_branch before rename:
5934  *
5935  * tmp
5936  * ├── s1d1
5937  * │   └── s1d2 [source of the first bind mount]
5938  * │       └── s1d3
5939  * │           ├── s1d41
5940  * │           │   ├── f1
5941  * │           │   └── f2
5942  * │           └── s1d42
5943  * │               ├── f3
5944  * │               └── f4
5945  * ├── s2d1
5946  * │   └── s2d2 [source of the second bind mount]
5947  * │       └── s2d3
5948  * │           └── s2d4 [first s1d2 bind mount]
5949  * │               └── s1d3
5950  * │                   ├── s1d41
5951  * │                   │   ├── f1
5952  * │                   │   └── f2
5953  * │                   └── s1d42
5954  * │                       ├── f3
5955  * │                       └── f4
5956  * ├── s3d1
5957  * │   └── s3d2 [second s2d2 bind mount]
5958  * │       └── s2d3
5959  * │           └── s2d4 [first s1d2 bind mount]
5960  * │               └── s1d3
5961  * │                   ├── s1d41
5962  * │                   │   ├── f1
5963  * │                   │   └── f2
5964  * │                   └── s1d42
5965  * │                       ├── f3
5966  * │                       └── f4
5967  * └── s4d1
5968  *
5969  * After rename:
5970  *
5971  * tmp
5972  * ├── s1d1
5973  * │   └── s1d2 [source of the first bind mount]
5974  * │       └── s1d3
5975  * │           ├── s1d41
5976  * │           │   ├── f1
5977  * │           │   └── f2
5978  * │           └── s1d42
5979  * │               ├── f3
5980  * │               └── f4
5981  * ├── s2d1
5982  * │   └── s2d2 [source of the second bind mount]
5983  * ├── s3d1
5984  * │   └── s3d2 [second s2d2 bind mount]
5985  * └── s4d1
5986  *     └── s2d3 [renamed here]
5987  *         └── s2d4 [first s1d2 bind mount]
5988  *             └── s1d3
5989  *                 ├── s1d41
5990  *                 │   ├── f1
5991  *                 │   └── f2
5992  *                 └── s1d42
5993  *                     ├── f3
5994  *                     └── f4
5995  *
5996  * Decision path for access from the s3d1/s3d2/s2d3/s2d4/s1d3 file descriptor:
5997  *   1. first bind mount:   s1d3 -> s1d2
5998  *   2. second bind mount:    s2d3
5999  *   3. tmp mount:              s4d1 -> tmp [disconnected branch]
6000  *   4. second bind mount:        s2d2
6001  *   5. tmp mount:                  s3d1 -> tmp
6002  *   6. parent mounts:                [...] -> /
6003  *
6004  * The s4d1 directory is evaluated even if it is not in the s2d2 mount.
6005  */
6006 
6007 /* clang-format off */
6008 FIXTURE(layout5_disconnected_branch) {
6009 	int s2d4_fd, s3d2_fd;
6010 };
6011 /* clang-format on */
6012 
6013 FIXTURE_SETUP(layout5_disconnected_branch)
6014 {
6015 	prepare_layout(_metadata);
6016 
6017 	create_file(_metadata, TMP_DIR "/s1d1/s1d2/s1d3/s1d41/f1");
6018 	create_file(_metadata, TMP_DIR "/s1d1/s1d2/s1d3/s1d41/f2");
6019 	create_file(_metadata, TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f3");
6020 	create_file(_metadata, TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f4");
6021 	create_directory(_metadata, TMP_DIR "/s2d1/s2d2/s2d3/s2d4");
6022 	create_directory(_metadata, TMP_DIR "/s3d1/s3d2");
6023 	create_directory(_metadata, TMP_DIR "/s4d1");
6024 
6025 	self->s2d4_fd = open(TMP_DIR "/s2d1/s2d2/s2d3/s2d4",
6026 			     O_DIRECTORY | O_PATH | O_CLOEXEC);
6027 	ASSERT_LE(0, self->s2d4_fd);
6028 
6029 	self->s3d2_fd =
6030 		open(TMP_DIR "/s3d1/s3d2", O_DIRECTORY | O_PATH | O_CLOEXEC);
6031 	ASSERT_LE(0, self->s3d2_fd);
6032 
6033 	set_cap(_metadata, CAP_SYS_ADMIN);
6034 	ASSERT_EQ(0, mount(TMP_DIR "/s1d1/s1d2", TMP_DIR "/s2d1/s2d2/s2d3/s2d4",
6035 			   NULL, MS_BIND, NULL));
6036 	ASSERT_EQ(0, mount(TMP_DIR "/s2d1/s2d2", TMP_DIR "/s3d1/s3d2", NULL,
6037 			   MS_BIND | MS_REC, NULL));
6038 	clear_cap(_metadata, CAP_SYS_ADMIN);
6039 }
6040 
6041 FIXTURE_TEARDOWN_PARENT(layout5_disconnected_branch)
6042 {
6043 	/* Bind mounts are handled by namespace lifetime. */
6044 
6045 	/* Removes files after renames. */
6046 	remove_path(TMP_DIR "/s1d1/s1d2/s1d3/s1d41/f1");
6047 	remove_path(TMP_DIR "/s1d1/s1d2/s1d3/s1d41/f2");
6048 	remove_path(TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f1");
6049 	remove_path(TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f3");
6050 	remove_path(TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f4");
6051 	remove_path(TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f5");
6052 
6053 	cleanup_layout(_metadata);
6054 }
6055 
6056 FIXTURE_VARIANT(layout5_disconnected_branch)
6057 {
6058 	/*
6059 	 * Parent of all files.  It should always be enforced when testing against
6060 	 * files under the s1d41 or s1d42 disconnected directories.
6061 	 */
6062 	const __u64 allowed_base;
6063 	/*
6064 	 * Parent of the first bind mount source.  It should always be ignored when
6065 	 * testing against files under the s1d41 or s1d42 disconnected directories.
6066 	 */
6067 	const __u64 allowed_s1d1;
6068 	const __u64 allowed_s1d2;
6069 	const __u64 allowed_s1d3;
6070 	const __u64 allowed_s2d1;
6071 	const __u64 allowed_s2d2;
6072 	const __u64 allowed_s2d3;
6073 	const __u64 allowed_s2d4;
6074 	const __u64 allowed_s3d1;
6075 	const __u64 allowed_s3d2;
6076 	const __u64 allowed_s4d1;
6077 
6078 	/* Expected result of the call to open([fd:s1d3]/s1d41/f1, O_RDONLY). */
6079 	const int expected_read_result;
6080 	/*
6081 	 * Expected result of the call to renameat([fd:s1d3]/s1d41/f1,
6082 	 * [fd:s1d3]/s1d42/f1).
6083 	 */
6084 	const int expected_rename_result;
6085 	/*
6086 	 * Expected result of the call to renameat([fd:s1d3]/s1d41/f2,
6087 	 * [fd:s1d3]/s1d42/f3,  RENAME_EXCHANGE).
6088 	 */
6089 	const int expected_exchange_result;
6090 	/*
6091 	 * Expected result of the call to renameat([fd:s1d3]/s1d42/f4,
6092 	 * [fd:s1d3]/s1d42/f5).
6093 	 */
6094 	const int expected_same_dir_rename_result;
6095 };
6096 
6097 /* clang-format off */
6098 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d1_mount1_src_parent) {
6099 	/* clang-format on */
6100 	.allowed_s1d1 = LANDLOCK_ACCESS_FS_REFER |
6101 			LANDLOCK_ACCESS_FS_READ_FILE |
6102 			LANDLOCK_ACCESS_FS_EXECUTE |
6103 			LANDLOCK_ACCESS_FS_MAKE_REG,
6104 	.expected_read_result = EACCES,
6105 	.expected_same_dir_rename_result = EACCES,
6106 	.expected_rename_result = EACCES,
6107 	.expected_exchange_result = EACCES,
6108 };
6109 
6110 /* clang-format off */
6111 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d2_mount1_src_refer) {
6112 	/* clang-format on */
6113 	.allowed_s1d2 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE,
6114 	.expected_read_result = 0,
6115 	.expected_same_dir_rename_result = EACCES,
6116 	.expected_rename_result = EACCES,
6117 	.expected_exchange_result = EACCES,
6118 };
6119 
6120 /* clang-format off */
6121 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d2_mount1_src_create) {
6122 	/* clang-format on */
6123 	.allowed_s1d2 = LANDLOCK_ACCESS_FS_READ_FILE |
6124 			LANDLOCK_ACCESS_FS_MAKE_REG,
6125 	.expected_read_result = 0,
6126 	.expected_same_dir_rename_result = 0,
6127 	.expected_rename_result = EXDEV,
6128 	.expected_exchange_result = EXDEV,
6129 };
6130 
6131 /* clang-format off */
6132 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d2_mount1_src_rename) {
6133 	/* clang-format on */
6134 	.allowed_s1d2 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
6135 	.expected_read_result = EACCES,
6136 	.expected_same_dir_rename_result = 0,
6137 	.expected_rename_result = 0,
6138 	.expected_exchange_result = 0,
6139 };
6140 
6141 /* clang-format off */
6142 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d3_fd_refer) {
6143 	/* clang-format on */
6144 	.allowed_s1d3 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE,
6145 	.expected_read_result = 0,
6146 	.expected_same_dir_rename_result = EACCES,
6147 	.expected_rename_result = EACCES,
6148 	.expected_exchange_result = EACCES,
6149 };
6150 
6151 /* clang-format off */
6152 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d3_fd_create) {
6153 	/* clang-format on */
6154 	.allowed_s1d3 = LANDLOCK_ACCESS_FS_READ_FILE |
6155 			LANDLOCK_ACCESS_FS_MAKE_REG,
6156 	.expected_read_result = 0,
6157 	.expected_same_dir_rename_result = 0,
6158 	.expected_rename_result = EXDEV,
6159 	.expected_exchange_result = EXDEV,
6160 };
6161 
6162 /* clang-format off */
6163 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d3_fd_rename) {
6164 	/* clang-format on */
6165 	.allowed_s1d3 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
6166 	.expected_read_result = EACCES,
6167 	.expected_same_dir_rename_result = 0,
6168 	.expected_rename_result = 0,
6169 	.expected_exchange_result = 0,
6170 };
6171 
6172 /* clang-format off */
6173 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d3_fd_full) {
6174 	/* clang-format on */
6175 	.allowed_s1d3 = LANDLOCK_ACCESS_FS_REFER |
6176 			LANDLOCK_ACCESS_FS_READ_FILE |
6177 			LANDLOCK_ACCESS_FS_EXECUTE |
6178 			LANDLOCK_ACCESS_FS_MAKE_REG,
6179 	.expected_read_result = 0,
6180 	.expected_same_dir_rename_result = 0,
6181 	.expected_rename_result = 0,
6182 	.expected_exchange_result = 0,
6183 };
6184 
6185 /* clang-format off */
6186 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d1_mount2_src_parent) {
6187 	/* clang-format on */
6188 	.allowed_s2d1 = LANDLOCK_ACCESS_FS_REFER |
6189 			LANDLOCK_ACCESS_FS_READ_FILE |
6190 			LANDLOCK_ACCESS_FS_EXECUTE |
6191 			LANDLOCK_ACCESS_FS_MAKE_REG,
6192 	.expected_read_result = EACCES,
6193 	.expected_same_dir_rename_result = EACCES,
6194 	.expected_rename_result = EACCES,
6195 	.expected_exchange_result = EACCES,
6196 };
6197 
6198 /* clang-format off */
6199 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d2_mount2_src_refer) {
6200 	/* clang-format on */
6201 	.allowed_s2d2 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE,
6202 	.expected_read_result = 0,
6203 	.expected_same_dir_rename_result = EACCES,
6204 	.expected_rename_result = EACCES,
6205 	.expected_exchange_result = EACCES,
6206 };
6207 
6208 /* clang-format off */
6209 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d2_mount2_src_create) {
6210 	/* clang-format on */
6211 	.allowed_s2d2 = LANDLOCK_ACCESS_FS_READ_FILE |
6212 			LANDLOCK_ACCESS_FS_MAKE_REG,
6213 	.expected_read_result = 0,
6214 	.expected_same_dir_rename_result = 0,
6215 	.expected_rename_result = EXDEV,
6216 	.expected_exchange_result = EXDEV,
6217 };
6218 
6219 /* clang-format off */
6220 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d2_mount2_src_rename) {
6221 	/* clang-format on */
6222 	.allowed_s2d2 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
6223 	.expected_read_result = EACCES,
6224 	.expected_same_dir_rename_result = 0,
6225 	.expected_rename_result = 0,
6226 	.expected_exchange_result = 0,
6227 };
6228 
6229 /* clang-format off */
6230 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d3_mount1_dst_parent_refer) {
6231 	/* clang-format on */
6232 	.allowed_s2d3 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE,
6233 	.expected_read_result = 0,
6234 	.expected_same_dir_rename_result = EACCES,
6235 	.expected_rename_result = EACCES,
6236 	.expected_exchange_result = EACCES,
6237 };
6238 
6239 /* clang-format off */
6240 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d3_mount1_dst_parent_create) {
6241 	/* clang-format on */
6242 	.allowed_s2d3 = LANDLOCK_ACCESS_FS_READ_FILE |
6243 			LANDLOCK_ACCESS_FS_MAKE_REG,
6244 	.expected_read_result = 0,
6245 	.expected_same_dir_rename_result = 0,
6246 	.expected_rename_result = EXDEV,
6247 	.expected_exchange_result = EXDEV,
6248 };
6249 
6250 /* clang-format off */
6251 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d3_mount1_dst_parent_rename) {
6252 	/* clang-format on */
6253 	.allowed_s2d3 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
6254 	.expected_read_result = EACCES,
6255 	.expected_same_dir_rename_result = 0,
6256 	.expected_rename_result = 0,
6257 	.expected_exchange_result = 0,
6258 };
6259 
6260 /* clang-format off */
6261 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d4_mount1_dst) {
6262 	/* clang-format on */
6263 	.allowed_s2d4 = LANDLOCK_ACCESS_FS_REFER |
6264 			LANDLOCK_ACCESS_FS_READ_FILE |
6265 			LANDLOCK_ACCESS_FS_EXECUTE |
6266 			LANDLOCK_ACCESS_FS_MAKE_REG,
6267 	.expected_read_result = EACCES,
6268 	.expected_same_dir_rename_result = EACCES,
6269 	.expected_rename_result = EACCES,
6270 	.expected_exchange_result = EACCES,
6271 };
6272 
6273 /* clang-format off */
6274 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s3d1_mount2_dst_parent_refer) {
6275 	/* clang-format on */
6276 	.allowed_s3d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE,
6277 	.expected_read_result = 0,
6278 	.expected_same_dir_rename_result = EACCES,
6279 	.expected_rename_result = EACCES,
6280 	.expected_exchange_result = EACCES,
6281 };
6282 
6283 /* clang-format off */
6284 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s3d1_mount2_dst_parent_create) {
6285 	/* clang-format on */
6286 	.allowed_s3d1 = LANDLOCK_ACCESS_FS_READ_FILE |
6287 			LANDLOCK_ACCESS_FS_MAKE_REG,
6288 	.expected_read_result = 0,
6289 	.expected_same_dir_rename_result = 0,
6290 	.expected_rename_result = EXDEV,
6291 	.expected_exchange_result = EXDEV,
6292 };
6293 
6294 /* clang-format off */
6295 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s3d1_mount2_dst_parent_rename) {
6296 	/* clang-format on */
6297 	.allowed_s3d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
6298 	.expected_read_result = EACCES,
6299 	.expected_same_dir_rename_result = 0,
6300 	.expected_rename_result = 0,
6301 	.expected_exchange_result = 0,
6302 };
6303 
6304 /* clang-format off */
6305 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s3d2_mount1_dst) {
6306 	/* clang-format on */
6307 	.allowed_s3d2 = LANDLOCK_ACCESS_FS_REFER |
6308 			LANDLOCK_ACCESS_FS_READ_FILE |
6309 			LANDLOCK_ACCESS_FS_EXECUTE |
6310 			LANDLOCK_ACCESS_FS_MAKE_REG,
6311 	.expected_read_result = EACCES,
6312 	.expected_same_dir_rename_result = EACCES,
6313 	.expected_rename_result = EACCES,
6314 	.expected_exchange_result = EACCES,
6315 };
6316 
6317 /* clang-format off */
6318 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s4d1_rename_parent_refer) {
6319 	/* clang-format on */
6320 	.allowed_s4d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE,
6321 	.expected_read_result = 0,
6322 	.expected_same_dir_rename_result = EACCES,
6323 	.expected_rename_result = EACCES,
6324 	.expected_exchange_result = EACCES,
6325 };
6326 
6327 /* clang-format off */
6328 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s4d1_rename_parent_create) {
6329 	/* clang-format on */
6330 	.allowed_s4d1 = LANDLOCK_ACCESS_FS_READ_FILE |
6331 			LANDLOCK_ACCESS_FS_MAKE_REG,
6332 	.expected_read_result = 0,
6333 	.expected_same_dir_rename_result = 0,
6334 	.expected_rename_result = EXDEV,
6335 	.expected_exchange_result = EXDEV,
6336 };
6337 
6338 /* clang-format off */
6339 FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s4d1_rename_parent_rename) {
6340 	/* clang-format on */
6341 	.allowed_s4d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG,
6342 	.expected_read_result = EACCES,
6343 	.expected_same_dir_rename_result = 0,
6344 	.expected_rename_result = 0,
6345 	.expected_exchange_result = 0,
6346 };
6347 
6348 TEST_F_FORK(layout5_disconnected_branch, read_rename_exchange)
6349 {
6350 	const __u64 handled_access =
6351 		LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE |
6352 		LANDLOCK_ACCESS_FS_EXECUTE | LANDLOCK_ACCESS_FS_MAKE_REG;
6353 	const struct rule rules[] = {
6354 		{
6355 			.path = TMP_DIR "/s1d1",
6356 			.access = variant->allowed_s1d1,
6357 		},
6358 		{
6359 			.path = TMP_DIR "/s1d1/s1d2",
6360 			.access = variant->allowed_s1d2,
6361 		},
6362 		{
6363 			.path = TMP_DIR "/s1d1/s1d2/s1d3",
6364 			.access = variant->allowed_s1d3,
6365 		},
6366 		{
6367 			.path = TMP_DIR "/s2d1",
6368 			.access = variant->allowed_s2d1,
6369 		},
6370 		{
6371 			.path = TMP_DIR "/s2d1/s2d2",
6372 			.access = variant->allowed_s2d2,
6373 		},
6374 		{
6375 			.path = TMP_DIR "/s2d1/s2d2/s2d3",
6376 			.access = variant->allowed_s2d3,
6377 		},
6378 		/* s2d4_fd */
6379 		{
6380 			.path = TMP_DIR "/s3d1",
6381 			.access = variant->allowed_s3d1,
6382 		},
6383 		/* s3d2_fd */
6384 		{
6385 			.path = TMP_DIR "/s4d1",
6386 			.access = variant->allowed_s4d1,
6387 		},
6388 		{},
6389 	};
6390 	int ruleset_fd, s1d3_bind_fd;
6391 
6392 	ruleset_fd = create_ruleset(_metadata, handled_access, rules);
6393 	ASSERT_LE(0, ruleset_fd);
6394 
6395 	/* Adds rules for the covered directories. */
6396 	if (variant->allowed_s2d4) {
6397 		ASSERT_EQ(0, landlock_add_rule(
6398 				     ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
6399 				     &(struct landlock_path_beneath_attr){
6400 					     .parent_fd = self->s2d4_fd,
6401 					     .allowed_access =
6402 						     variant->allowed_s2d4,
6403 				     },
6404 				     0));
6405 	}
6406 	EXPECT_EQ(0, close(self->s2d4_fd));
6407 
6408 	if (variant->allowed_s3d2) {
6409 		ASSERT_EQ(0, landlock_add_rule(
6410 				     ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
6411 				     &(struct landlock_path_beneath_attr){
6412 					     .parent_fd = self->s3d2_fd,
6413 					     .allowed_access =
6414 						     variant->allowed_s3d2,
6415 				     },
6416 				     0));
6417 	}
6418 	EXPECT_EQ(0, close(self->s3d2_fd));
6419 
6420 	s1d3_bind_fd = open(TMP_DIR "/s3d1/s3d2/s2d3/s2d4/s1d3",
6421 			    O_DIRECTORY | O_PATH | O_CLOEXEC);
6422 	ASSERT_LE(0, s1d3_bind_fd);
6423 
6424 	/* Disconnects and checks source and destination directories. */
6425 	EXPECT_EQ(0, test_open_rel(s1d3_bind_fd, "..", O_DIRECTORY));
6426 	EXPECT_EQ(0, test_open_rel(s1d3_bind_fd, "../..", O_DIRECTORY));
6427 	/* Renames to make it accessible through s3d1/s1d41 */
6428 	ASSERT_EQ(0, test_renameat(AT_FDCWD, TMP_DIR "/s2d1/s2d2/s2d3",
6429 				   AT_FDCWD, TMP_DIR "/s4d1/s2d3"));
6430 	EXPECT_EQ(0, test_open_rel(s1d3_bind_fd, "..", O_DIRECTORY));
6431 	EXPECT_EQ(ENOENT, test_open_rel(s1d3_bind_fd, "../..", O_DIRECTORY));
6432 
6433 	enforce_ruleset(_metadata, ruleset_fd);
6434 	EXPECT_EQ(0, close(ruleset_fd));
6435 
6436 	EXPECT_EQ(variant->expected_read_result,
6437 		  test_open_rel(s1d3_bind_fd, "s1d41/f1", O_RDONLY));
6438 
6439 	EXPECT_EQ(variant->expected_rename_result,
6440 		  test_renameat(s1d3_bind_fd, "s1d41/f1", s1d3_bind_fd,
6441 				"s1d42/f1"));
6442 	EXPECT_EQ(variant->expected_exchange_result,
6443 		  test_exchangeat(s1d3_bind_fd, "s1d41/f2", s1d3_bind_fd,
6444 				  "s1d42/f3"));
6445 
6446 	EXPECT_EQ(variant->expected_same_dir_rename_result,
6447 		  test_renameat(s1d3_bind_fd, "s1d42/f4", s1d3_bind_fd,
6448 				"s1d42/f5"));
6449 }
6450 
6451 #define LOWER_BASE TMP_DIR "/lower"
6452 #define LOWER_DATA LOWER_BASE "/data"
6453 static const char lower_fl1[] = LOWER_DATA "/fl1";
6454 static const char lower_dl1[] = LOWER_DATA "/dl1";
6455 static const char lower_dl1_fl2[] = LOWER_DATA "/dl1/fl2";
6456 static const char lower_fo1[] = LOWER_DATA "/fo1";
6457 static const char lower_do1[] = LOWER_DATA "/do1";
6458 static const char lower_do1_fo2[] = LOWER_DATA "/do1/fo2";
6459 static const char lower_do1_fl3[] = LOWER_DATA "/do1/fl3";
6460 
6461 static const char (*lower_base_files[])[] = {
6462 	&lower_fl1,
6463 	&lower_fo1,
6464 	NULL,
6465 };
6466 static const char (*lower_base_directories[])[] = {
6467 	&lower_dl1,
6468 	&lower_do1,
6469 	NULL,
6470 };
6471 static const char (*lower_sub_files[])[] = {
6472 	&lower_dl1_fl2,
6473 	&lower_do1_fo2,
6474 	&lower_do1_fl3,
6475 	NULL,
6476 };
6477 
6478 #define UPPER_BASE TMP_DIR "/upper"
6479 #define UPPER_DATA UPPER_BASE "/data"
6480 #define UPPER_WORK UPPER_BASE "/work"
6481 static const char upper_fu1[] = UPPER_DATA "/fu1";
6482 static const char upper_du1[] = UPPER_DATA "/du1";
6483 static const char upper_du1_fu2[] = UPPER_DATA "/du1/fu2";
6484 static const char upper_fo1[] = UPPER_DATA "/fo1";
6485 static const char upper_do1[] = UPPER_DATA "/do1";
6486 static const char upper_do1_fo2[] = UPPER_DATA "/do1/fo2";
6487 static const char upper_do1_fu3[] = UPPER_DATA "/do1/fu3";
6488 
6489 static const char (*upper_base_files[])[] = {
6490 	&upper_fu1,
6491 	&upper_fo1,
6492 	NULL,
6493 };
6494 static const char (*upper_base_directories[])[] = {
6495 	&upper_du1,
6496 	&upper_do1,
6497 	NULL,
6498 };
6499 static const char (*upper_sub_files[])[] = {
6500 	&upper_du1_fu2,
6501 	&upper_do1_fo2,
6502 	&upper_do1_fu3,
6503 	NULL,
6504 };
6505 
6506 #define MERGE_BASE TMP_DIR "/merge"
6507 #define MERGE_DATA MERGE_BASE "/data"
6508 static const char merge_fl1[] = MERGE_DATA "/fl1";
6509 static const char merge_dl1[] = MERGE_DATA "/dl1";
6510 static const char merge_dl1_fl2[] = MERGE_DATA "/dl1/fl2";
6511 static const char merge_fu1[] = MERGE_DATA "/fu1";
6512 static const char merge_du1[] = MERGE_DATA "/du1";
6513 static const char merge_du1_fu2[] = MERGE_DATA "/du1/fu2";
6514 static const char merge_fo1[] = MERGE_DATA "/fo1";
6515 static const char merge_do1[] = MERGE_DATA "/do1";
6516 static const char merge_do1_fo2[] = MERGE_DATA "/do1/fo2";
6517 static const char merge_do1_fl3[] = MERGE_DATA "/do1/fl3";
6518 static const char merge_do1_fu3[] = MERGE_DATA "/do1/fu3";
6519 
6520 static const char (*merge_base_files[])[] = {
6521 	&merge_fl1,
6522 	&merge_fu1,
6523 	&merge_fo1,
6524 	NULL,
6525 };
6526 static const char (*merge_base_directories[])[] = {
6527 	&merge_dl1,
6528 	&merge_du1,
6529 	&merge_do1,
6530 	NULL,
6531 };
6532 static const char (*merge_sub_files[])[] = {
6533 	&merge_dl1_fl2, &merge_du1_fu2, &merge_do1_fo2,
6534 	&merge_do1_fl3, &merge_do1_fu3, NULL,
6535 };
6536 
6537 /*
6538  * layout2_overlay hierarchy:
6539  *
6540  * tmp
6541  * ├── lower
6542  * │   └── data
6543  * │       ├── dl1
6544  * │       │   └── fl2
6545  * │       ├── do1
6546  * │       │   ├── fl3
6547  * │       │   └── fo2
6548  * │       ├── fl1
6549  * │       └── fo1
6550  * ├── merge
6551  * │   └── data
6552  * │       ├── dl1
6553  * │       │   └── fl2
6554  * │       ├── do1
6555  * │       │   ├── fl3
6556  * │       │   ├── fo2
6557  * │       │   └── fu3
6558  * │       ├── du1
6559  * │       │   └── fu2
6560  * │       ├── fl1
6561  * │       ├── fo1
6562  * │       └── fu1
6563  * └── upper
6564  *     ├── data
6565  *     │   ├── do1
6566  *     │   │   ├── fo2
6567  *     │   │   └── fu3
6568  *     │   ├── du1
6569  *     │   │   └── fu2
6570  *     │   ├── fo1
6571  *     │   └── fu1
6572  *     └── work
6573  *         └── work
6574  */
6575 
6576 FIXTURE(layout2_overlay)
6577 {
6578 	bool skip_test;
6579 };
6580 
6581 FIXTURE_SETUP(layout2_overlay)
6582 {
6583 	if (!supports_filesystem("overlay")) {
6584 		self->skip_test = true;
6585 		SKIP(return, "overlayfs is not supported (setup)");
6586 	}
6587 
6588 	prepare_layout(_metadata);
6589 
6590 	create_directory(_metadata, LOWER_BASE);
6591 	set_cap(_metadata, CAP_SYS_ADMIN);
6592 	/* Creates tmpfs mount points to get deterministic overlayfs. */
6593 	ASSERT_EQ(0, mount_opt(&mnt_tmp, LOWER_BASE));
6594 	clear_cap(_metadata, CAP_SYS_ADMIN);
6595 	create_file(_metadata, lower_fl1);
6596 	create_file(_metadata, lower_dl1_fl2);
6597 	create_file(_metadata, lower_fo1);
6598 	create_file(_metadata, lower_do1_fo2);
6599 	create_file(_metadata, lower_do1_fl3);
6600 
6601 	create_directory(_metadata, UPPER_BASE);
6602 	set_cap(_metadata, CAP_SYS_ADMIN);
6603 	ASSERT_EQ(0, mount_opt(&mnt_tmp, UPPER_BASE));
6604 	clear_cap(_metadata, CAP_SYS_ADMIN);
6605 	create_file(_metadata, upper_fu1);
6606 	create_file(_metadata, upper_du1_fu2);
6607 	create_file(_metadata, upper_fo1);
6608 	create_file(_metadata, upper_do1_fo2);
6609 	create_file(_metadata, upper_do1_fu3);
6610 	ASSERT_EQ(0, mkdir(UPPER_WORK, 0700));
6611 
6612 	create_directory(_metadata, MERGE_DATA);
6613 	set_cap(_metadata, CAP_SYS_ADMIN);
6614 	set_cap(_metadata, CAP_DAC_OVERRIDE);
6615 	ASSERT_EQ(0, mount("overlay", MERGE_DATA, "overlay", 0,
6616 			   "lowerdir=" LOWER_DATA ",upperdir=" UPPER_DATA
6617 			   ",workdir=" UPPER_WORK));
6618 	clear_cap(_metadata, CAP_DAC_OVERRIDE);
6619 	clear_cap(_metadata, CAP_SYS_ADMIN);
6620 }
6621 
6622 FIXTURE_TEARDOWN_PARENT(layout2_overlay)
6623 {
6624 	if (self->skip_test)
6625 		SKIP(return, "overlayfs is not supported (teardown)");
6626 
6627 	EXPECT_EQ(0, remove_path(lower_do1_fl3));
6628 	EXPECT_EQ(0, remove_path(lower_dl1_fl2));
6629 	EXPECT_EQ(0, remove_path(lower_fl1));
6630 	EXPECT_EQ(0, remove_path(lower_do1_fo2));
6631 	EXPECT_EQ(0, remove_path(lower_fo1));
6632 
6633 	/* umount(LOWER_BASE)) is handled by namespace lifetime. */
6634 	EXPECT_EQ(0, remove_path(LOWER_BASE));
6635 
6636 	EXPECT_EQ(0, remove_path(upper_do1_fu3));
6637 	EXPECT_EQ(0, remove_path(upper_du1_fu2));
6638 	EXPECT_EQ(0, remove_path(upper_fu1));
6639 	EXPECT_EQ(0, remove_path(upper_do1_fo2));
6640 	EXPECT_EQ(0, remove_path(upper_fo1));
6641 	EXPECT_EQ(0, remove_path(UPPER_WORK "/work"));
6642 
6643 	/* umount(UPPER_BASE)) is handled by namespace lifetime. */
6644 	EXPECT_EQ(0, remove_path(UPPER_BASE));
6645 
6646 	/* umount(MERGE_DATA)) is handled by namespace lifetime. */
6647 	EXPECT_EQ(0, remove_path(MERGE_DATA));
6648 
6649 	cleanup_layout(_metadata);
6650 }
6651 
6652 TEST_F_FORK(layout2_overlay, no_restriction)
6653 {
6654 	if (self->skip_test)
6655 		SKIP(return, "overlayfs is not supported (test)");
6656 
6657 	ASSERT_EQ(0, test_open(lower_fl1, O_RDONLY));
6658 	ASSERT_EQ(0, test_open(lower_dl1, O_RDONLY));
6659 	ASSERT_EQ(0, test_open(lower_dl1_fl2, O_RDONLY));
6660 	ASSERT_EQ(0, test_open(lower_fo1, O_RDONLY));
6661 	ASSERT_EQ(0, test_open(lower_do1, O_RDONLY));
6662 	ASSERT_EQ(0, test_open(lower_do1_fo2, O_RDONLY));
6663 	ASSERT_EQ(0, test_open(lower_do1_fl3, O_RDONLY));
6664 
6665 	ASSERT_EQ(0, test_open(upper_fu1, O_RDONLY));
6666 	ASSERT_EQ(0, test_open(upper_du1, O_RDONLY));
6667 	ASSERT_EQ(0, test_open(upper_du1_fu2, O_RDONLY));
6668 	ASSERT_EQ(0, test_open(upper_fo1, O_RDONLY));
6669 	ASSERT_EQ(0, test_open(upper_do1, O_RDONLY));
6670 	ASSERT_EQ(0, test_open(upper_do1_fo2, O_RDONLY));
6671 	ASSERT_EQ(0, test_open(upper_do1_fu3, O_RDONLY));
6672 
6673 	ASSERT_EQ(0, test_open(merge_fl1, O_RDONLY));
6674 	ASSERT_EQ(0, test_open(merge_dl1, O_RDONLY));
6675 	ASSERT_EQ(0, test_open(merge_dl1_fl2, O_RDONLY));
6676 	ASSERT_EQ(0, test_open(merge_fu1, O_RDONLY));
6677 	ASSERT_EQ(0, test_open(merge_du1, O_RDONLY));
6678 	ASSERT_EQ(0, test_open(merge_du1_fu2, O_RDONLY));
6679 	ASSERT_EQ(0, test_open(merge_fo1, O_RDONLY));
6680 	ASSERT_EQ(0, test_open(merge_do1, O_RDONLY));
6681 	ASSERT_EQ(0, test_open(merge_do1_fo2, O_RDONLY));
6682 	ASSERT_EQ(0, test_open(merge_do1_fl3, O_RDONLY));
6683 	ASSERT_EQ(0, test_open(merge_do1_fu3, O_RDONLY));
6684 }
6685 
6686 #define for_each_path(path_list, path_entry, i)               \
6687 	for (i = 0, path_entry = *path_list[i]; path_list[i]; \
6688 	     path_entry = *path_list[++i])
6689 
6690 TEST_F_FORK(layout2_overlay, same_content_different_file)
6691 {
6692 	/* Sets access right on parent directories of both layers. */
6693 	const struct rule layer1_base[] = {
6694 		{
6695 			.path = LOWER_BASE,
6696 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6697 		},
6698 		{
6699 			.path = UPPER_BASE,
6700 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6701 		},
6702 		{
6703 			.path = MERGE_BASE,
6704 			.access = ACCESS_RW,
6705 		},
6706 		{},
6707 	};
6708 	const struct rule layer2_data[] = {
6709 		{
6710 			.path = LOWER_DATA,
6711 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6712 		},
6713 		{
6714 			.path = UPPER_DATA,
6715 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6716 		},
6717 		{
6718 			.path = MERGE_DATA,
6719 			.access = ACCESS_RW,
6720 		},
6721 		{},
6722 	};
6723 	/* Sets access right on directories inside both layers. */
6724 	const struct rule layer3_subdirs[] = {
6725 		{
6726 			.path = lower_dl1,
6727 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6728 		},
6729 		{
6730 			.path = lower_do1,
6731 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6732 		},
6733 		{
6734 			.path = upper_du1,
6735 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6736 		},
6737 		{
6738 			.path = upper_do1,
6739 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6740 		},
6741 		{
6742 			.path = merge_dl1,
6743 			.access = ACCESS_RW,
6744 		},
6745 		{
6746 			.path = merge_du1,
6747 			.access = ACCESS_RW,
6748 		},
6749 		{
6750 			.path = merge_do1,
6751 			.access = ACCESS_RW,
6752 		},
6753 		{},
6754 	};
6755 	/* Tighten access rights to the files. */
6756 	const struct rule layer4_files[] = {
6757 		{
6758 			.path = lower_dl1_fl2,
6759 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6760 		},
6761 		{
6762 			.path = lower_do1_fo2,
6763 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6764 		},
6765 		{
6766 			.path = lower_do1_fl3,
6767 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6768 		},
6769 		{
6770 			.path = upper_du1_fu2,
6771 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6772 		},
6773 		{
6774 			.path = upper_do1_fo2,
6775 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6776 		},
6777 		{
6778 			.path = upper_do1_fu3,
6779 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
6780 		},
6781 		{
6782 			.path = merge_dl1_fl2,
6783 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
6784 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
6785 		},
6786 		{
6787 			.path = merge_du1_fu2,
6788 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
6789 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
6790 		},
6791 		{
6792 			.path = merge_do1_fo2,
6793 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
6794 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
6795 		},
6796 		{
6797 			.path = merge_do1_fl3,
6798 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
6799 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
6800 		},
6801 		{
6802 			.path = merge_do1_fu3,
6803 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
6804 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
6805 		},
6806 		{},
6807 	};
6808 	const struct rule layer5_merge_only[] = {
6809 		{
6810 			.path = MERGE_DATA,
6811 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
6812 				  LANDLOCK_ACCESS_FS_WRITE_FILE,
6813 		},
6814 		{},
6815 	};
6816 	size_t i;
6817 	const char *path_entry;
6818 
6819 	if (self->skip_test)
6820 		SKIP(return, "overlayfs is not supported (test)");
6821 
6822 	/* Sets rules on base directories (i.e. outside overlay scope). */
6823 	enforce_fs(_metadata, ACCESS_RW, layer1_base);
6824 
6825 	/* Checks lower layer. */
6826 	for_each_path(lower_base_files, path_entry, i) {
6827 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
6828 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
6829 	}
6830 	for_each_path(lower_base_directories, path_entry, i) {
6831 		ASSERT_EQ(EACCES,
6832 			  test_open(path_entry, O_RDONLY | O_DIRECTORY));
6833 	}
6834 	for_each_path(lower_sub_files, path_entry, i) {
6835 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
6836 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
6837 	}
6838 	/* Checks upper layer. */
6839 	for_each_path(upper_base_files, path_entry, i) {
6840 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
6841 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
6842 	}
6843 	for_each_path(upper_base_directories, path_entry, i) {
6844 		ASSERT_EQ(EACCES,
6845 			  test_open(path_entry, O_RDONLY | O_DIRECTORY));
6846 	}
6847 	for_each_path(upper_sub_files, path_entry, i) {
6848 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
6849 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
6850 	}
6851 	/*
6852 	 * Checks that access rights are independent from the lower and upper
6853 	 * layers: write access to upper files viewed through the merge point
6854 	 * is still allowed, and write access to lower file viewed (and copied)
6855 	 * through the merge point is still allowed.
6856 	 */
6857 	for_each_path(merge_base_files, path_entry, i) {
6858 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
6859 	}
6860 	for_each_path(merge_base_directories, path_entry, i) {
6861 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
6862 	}
6863 	for_each_path(merge_sub_files, path_entry, i) {
6864 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
6865 	}
6866 
6867 	/* Sets rules on data directories (i.e. inside overlay scope). */
6868 	enforce_fs(_metadata, ACCESS_RW, layer2_data);
6869 
6870 	/* Checks merge. */
6871 	for_each_path(merge_base_files, path_entry, i) {
6872 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
6873 	}
6874 	for_each_path(merge_base_directories, path_entry, i) {
6875 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
6876 	}
6877 	for_each_path(merge_sub_files, path_entry, i) {
6878 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
6879 	}
6880 
6881 	/* Same checks with tighter rules. */
6882 	enforce_fs(_metadata, ACCESS_RW, layer3_subdirs);
6883 
6884 	/* Checks changes for lower layer. */
6885 	for_each_path(lower_base_files, path_entry, i) {
6886 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
6887 	}
6888 	/* Checks changes for upper layer. */
6889 	for_each_path(upper_base_files, path_entry, i) {
6890 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
6891 	}
6892 	/* Checks all merge accesses. */
6893 	for_each_path(merge_base_files, path_entry, i) {
6894 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
6895 	}
6896 	for_each_path(merge_base_directories, path_entry, i) {
6897 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
6898 	}
6899 	for_each_path(merge_sub_files, path_entry, i) {
6900 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
6901 	}
6902 
6903 	/* Sets rules directly on overlayed files. */
6904 	enforce_fs(_metadata, ACCESS_RW, layer4_files);
6905 
6906 	/* Checks unchanged accesses on lower layer. */
6907 	for_each_path(lower_sub_files, path_entry, i) {
6908 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
6909 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
6910 	}
6911 	/* Checks unchanged accesses on upper layer. */
6912 	for_each_path(upper_sub_files, path_entry, i) {
6913 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
6914 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
6915 	}
6916 	/* Checks all merge accesses. */
6917 	for_each_path(merge_base_files, path_entry, i) {
6918 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
6919 	}
6920 	for_each_path(merge_base_directories, path_entry, i) {
6921 		ASSERT_EQ(EACCES,
6922 			  test_open(path_entry, O_RDONLY | O_DIRECTORY));
6923 	}
6924 	for_each_path(merge_sub_files, path_entry, i) {
6925 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
6926 	}
6927 
6928 	/* Only allowes access to the merge hierarchy. */
6929 	enforce_fs(_metadata, ACCESS_RW, layer5_merge_only);
6930 
6931 	/* Checks new accesses on lower layer. */
6932 	for_each_path(lower_sub_files, path_entry, i) {
6933 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
6934 	}
6935 	/* Checks new accesses on upper layer. */
6936 	for_each_path(upper_sub_files, path_entry, i) {
6937 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
6938 	}
6939 	/* Checks all merge accesses. */
6940 	for_each_path(merge_base_files, path_entry, i) {
6941 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
6942 	}
6943 	for_each_path(merge_base_directories, path_entry, i) {
6944 		ASSERT_EQ(EACCES,
6945 			  test_open(path_entry, O_RDONLY | O_DIRECTORY));
6946 	}
6947 	for_each_path(merge_sub_files, path_entry, i) {
6948 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
6949 	}
6950 }
6951 
6952 FIXTURE(layout3_fs)
6953 {
6954 	bool has_created_dir;
6955 	bool has_created_file;
6956 	bool skip_test;
6957 };
6958 
6959 FIXTURE_VARIANT(layout3_fs)
6960 {
6961 	const struct mnt_opt mnt;
6962 	const char *const file_path;
6963 	unsigned int cwd_fs_magic;
6964 };
6965 
6966 /* clang-format off */
6967 FIXTURE_VARIANT_ADD(layout3_fs, tmpfs) {
6968 	/* clang-format on */
6969 	.mnt = {
6970 		.type = "tmpfs",
6971 		.data = MNT_TMP_DATA,
6972 	},
6973 	.file_path = file1_s1d1,
6974 };
6975 
6976 FIXTURE_VARIANT_ADD(layout3_fs, ramfs) {
6977 	.mnt = {
6978 		.type = "ramfs",
6979 		.data = "mode=700",
6980 	},
6981 	.file_path = TMP_DIR "/dir/file",
6982 };
6983 
6984 FIXTURE_VARIANT_ADD(layout3_fs, cgroup2) {
6985 	.mnt = {
6986 		.type = "cgroup2",
6987 	},
6988 	.file_path = TMP_DIR "/test/cgroup.procs",
6989 };
6990 
6991 FIXTURE_VARIANT_ADD(layout3_fs, proc) {
6992 	.mnt = {
6993 		.type = "proc",
6994 	},
6995 	.file_path = TMP_DIR "/self/status",
6996 };
6997 
6998 FIXTURE_VARIANT_ADD(layout3_fs, sysfs) {
6999 	.mnt = {
7000 		.type = "sysfs",
7001 	},
7002 	.file_path = TMP_DIR "/kernel/notes",
7003 };
7004 
7005 FIXTURE_VARIANT_ADD(layout3_fs, hostfs) {
7006 	.mnt = {
7007 		.source = TMP_DIR,
7008 		.flags = MS_BIND,
7009 	},
7010 	.file_path = TMP_DIR "/dir/file",
7011 	.cwd_fs_magic = HOSTFS_SUPER_MAGIC,
7012 };
7013 
7014 static char *dirname_alloc(const char *path)
7015 {
7016 	char *dup;
7017 
7018 	if (!path)
7019 		return NULL;
7020 
7021 	dup = strdup(path);
7022 	if (!dup)
7023 		return NULL;
7024 
7025 	return dirname(dup);
7026 }
7027 
7028 FIXTURE_SETUP(layout3_fs)
7029 {
7030 	struct stat statbuf;
7031 	char *dir_path = dirname_alloc(variant->file_path);
7032 
7033 	if (!supports_filesystem(variant->mnt.type) ||
7034 	    !cwd_matches_fs(variant->cwd_fs_magic)) {
7035 		self->skip_test = true;
7036 		SKIP(return, "this filesystem is not supported (setup)");
7037 	}
7038 
7039 	prepare_layout_opt(_metadata, &variant->mnt);
7040 
7041 	/* Creates directory when required. */
7042 	if (stat(dir_path, &statbuf)) {
7043 		set_cap(_metadata, CAP_DAC_OVERRIDE);
7044 		EXPECT_EQ(0, mkdir(dir_path, 0700))
7045 		{
7046 			TH_LOG("Failed to create directory \"%s\": %s",
7047 			       dir_path, strerror(errno));
7048 		}
7049 		self->has_created_dir = true;
7050 		clear_cap(_metadata, CAP_DAC_OVERRIDE);
7051 	}
7052 
7053 	/* Creates file when required. */
7054 	if (stat(variant->file_path, &statbuf)) {
7055 		int fd;
7056 
7057 		set_cap(_metadata, CAP_DAC_OVERRIDE);
7058 		fd = creat(variant->file_path, 0600);
7059 		EXPECT_LE(0, fd)
7060 		{
7061 			TH_LOG("Failed to create file \"%s\": %s",
7062 			       variant->file_path, strerror(errno));
7063 		}
7064 		EXPECT_EQ(0, close(fd));
7065 		self->has_created_file = true;
7066 		clear_cap(_metadata, CAP_DAC_OVERRIDE);
7067 	}
7068 
7069 	free(dir_path);
7070 }
7071 
7072 FIXTURE_TEARDOWN_PARENT(layout3_fs)
7073 {
7074 	if (self->skip_test)
7075 		SKIP(return, "this filesystem is not supported (teardown)");
7076 
7077 	if (self->has_created_file) {
7078 		set_cap(_metadata, CAP_DAC_OVERRIDE);
7079 		/*
7080 		 * Don't check for error because the file might already
7081 		 * have been removed (cf. release_inode test).
7082 		 */
7083 		unlink(variant->file_path);
7084 		clear_cap(_metadata, CAP_DAC_OVERRIDE);
7085 	}
7086 
7087 	if (self->has_created_dir) {
7088 		char *dir_path = dirname_alloc(variant->file_path);
7089 
7090 		set_cap(_metadata, CAP_DAC_OVERRIDE);
7091 		/*
7092 		 * Don't check for error because the directory might already
7093 		 * have been removed (cf. release_inode test).
7094 		 */
7095 		rmdir(dir_path);
7096 		clear_cap(_metadata, CAP_DAC_OVERRIDE);
7097 		free(dir_path);
7098 	}
7099 
7100 	cleanup_layout(_metadata);
7101 }
7102 
7103 static void layer3_fs_tag_inode(struct __test_metadata *const _metadata,
7104 				FIXTURE_DATA(layout3_fs) * self,
7105 				const FIXTURE_VARIANT(layout3_fs) * variant,
7106 				const char *const rule_path)
7107 {
7108 	const struct rule layer1_allow_read_file[] = {
7109 		{
7110 			.path = rule_path,
7111 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
7112 		},
7113 		{},
7114 	};
7115 	const char *const dev_null_path = "/dev/null";
7116 
7117 	if (self->skip_test)
7118 		SKIP(return, "this filesystem is not supported (test)");
7119 
7120 	/* Checks without Landlock. */
7121 	EXPECT_EQ(0, test_open(dev_null_path, O_RDONLY | O_CLOEXEC));
7122 	EXPECT_EQ(0, test_open(variant->file_path, O_RDONLY | O_CLOEXEC));
7123 
7124 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
7125 		   layer1_allow_read_file);
7126 
7127 	EXPECT_EQ(EACCES, test_open(dev_null_path, O_RDONLY | O_CLOEXEC));
7128 	EXPECT_EQ(0, test_open(variant->file_path, O_RDONLY | O_CLOEXEC));
7129 
7130 	/* Forbids directory reading. */
7131 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_READ_FILE, NULL);
7132 
7133 	/* Checks with Landlock and forbidden access. */
7134 	EXPECT_EQ(EACCES, test_open(dev_null_path, O_RDONLY | O_CLOEXEC));
7135 	EXPECT_EQ(EACCES, test_open(variant->file_path, O_RDONLY | O_CLOEXEC));
7136 }
7137 
7138 /* Matrix of tests to check file hierarchy evaluation. */
7139 
7140 TEST_F_FORK(layout3_fs, tag_inode_dir_parent)
7141 {
7142 	/* The current directory must not be the root for this test. */
7143 	layer3_fs_tag_inode(_metadata, self, variant, ".");
7144 }
7145 
7146 TEST_F_FORK(layout3_fs, tag_inode_dir_mnt)
7147 {
7148 	layer3_fs_tag_inode(_metadata, self, variant, TMP_DIR);
7149 }
7150 
7151 TEST_F_FORK(layout3_fs, tag_inode_dir_child)
7152 {
7153 	char *dir_path = dirname_alloc(variant->file_path);
7154 
7155 	layer3_fs_tag_inode(_metadata, self, variant, dir_path);
7156 	free(dir_path);
7157 }
7158 
7159 TEST_F_FORK(layout3_fs, tag_inode_file)
7160 {
7161 	layer3_fs_tag_inode(_metadata, self, variant, variant->file_path);
7162 }
7163 
7164 /* Light version of layout1.release_inodes */
7165 TEST_F_FORK(layout3_fs, release_inodes)
7166 {
7167 	const struct rule layer1[] = {
7168 		{
7169 			.path = TMP_DIR,
7170 			.access = LANDLOCK_ACCESS_FS_READ_DIR,
7171 		},
7172 		{},
7173 	};
7174 	int ruleset_fd;
7175 
7176 	if (self->skip_test)
7177 		SKIP(return, "this filesystem is not supported (test)");
7178 
7179 	/* Clean up for the teardown to not fail. */
7180 	if (self->has_created_file)
7181 		EXPECT_EQ(0, remove_path(variant->file_path));
7182 
7183 	if (self->has_created_dir) {
7184 		char *dir_path = dirname_alloc(variant->file_path);
7185 
7186 		/* Don't check for error because of cgroup specificities. */
7187 		remove_path(dir_path);
7188 		free(dir_path);
7189 	}
7190 
7191 	ruleset_fd =
7192 		create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_DIR, layer1);
7193 
7194 	/* Unmount the filesystem while it is being used by a ruleset. */
7195 	set_cap(_metadata, CAP_SYS_ADMIN);
7196 	ASSERT_EQ(0, umount(TMP_DIR));
7197 	clear_cap(_metadata, CAP_SYS_ADMIN);
7198 
7199 	/* Replaces with a new mount point to simplify FIXTURE_TEARDOWN. */
7200 	set_cap(_metadata, CAP_SYS_ADMIN);
7201 	ASSERT_EQ(0, mount_opt(&mnt_tmp, TMP_DIR));
7202 	clear_cap(_metadata, CAP_SYS_ADMIN);
7203 
7204 	enforce_ruleset(_metadata, ruleset_fd);
7205 	ASSERT_EQ(0, close(ruleset_fd));
7206 
7207 	/* Checks that access to the new mount point is denied. */
7208 	ASSERT_EQ(EACCES, test_open(TMP_DIR, O_RDONLY));
7209 }
7210 
7211 static int matches_log_fs_extra(struct __test_metadata *const _metadata,
7212 				int audit_fd, const char *const blockers,
7213 				const char *const path, const char *const extra)
7214 {
7215 	static const char log_template[] = REGEX_LANDLOCK_PREFIX
7216 		" blockers=fs\\.%s path=\"%s\" dev=\"[^\"]\\+\" ino=[0-9]\\+$";
7217 	char *absolute_path = NULL;
7218 	size_t log_match_remaining = sizeof(log_template) + strlen(blockers) +
7219 				     PATH_MAX * 2 +
7220 				     (extra ? strlen(extra) : 0) + 1;
7221 	char log_match[log_match_remaining];
7222 	char *log_match_cursor = log_match;
7223 	size_t chunk_len;
7224 
7225 	chunk_len = snprintf(log_match_cursor, log_match_remaining,
7226 			     REGEX_LANDLOCK_PREFIX " blockers=%s path=\"",
7227 			     blockers);
7228 	if (chunk_len < 0 || chunk_len >= log_match_remaining)
7229 		return -E2BIG;
7230 
7231 	/*
7232 	 * It is assumed that absolute_path does not contain control
7233 	 * characters nor spaces, see audit_string_contains_control().
7234 	 */
7235 	absolute_path = realpath(path, NULL);
7236 	if (!absolute_path)
7237 		return -errno;
7238 
7239 	log_match_remaining -= chunk_len;
7240 	log_match_cursor += chunk_len;
7241 	log_match_cursor = regex_escape(absolute_path, log_match_cursor,
7242 					log_match_remaining);
7243 	free(absolute_path);
7244 	if (log_match_cursor < 0)
7245 		return (long long)log_match_cursor;
7246 
7247 	log_match_remaining -= log_match_cursor - log_match;
7248 	chunk_len = snprintf(log_match_cursor, log_match_remaining,
7249 			     "\" dev=\"[^\"]\\+\" ino=[0-9]\\+%s$",
7250 			     extra ?: "");
7251 	if (chunk_len < 0 || chunk_len >= log_match_remaining)
7252 		return -E2BIG;
7253 
7254 	return audit_match_record(audit_fd, AUDIT_LANDLOCK_ACCESS, log_match,
7255 				  NULL);
7256 }
7257 
7258 static int matches_log_fs(struct __test_metadata *const _metadata, int audit_fd,
7259 			  const char *const blockers, const char *const path)
7260 {
7261 	return matches_log_fs_extra(_metadata, audit_fd, blockers, path, NULL);
7262 }
7263 
7264 FIXTURE(audit_layout1)
7265 {
7266 	struct audit_filter audit_filter;
7267 	int audit_fd;
7268 };
7269 
7270 FIXTURE_SETUP(audit_layout1)
7271 {
7272 	prepare_layout(_metadata);
7273 
7274 	create_layout1(_metadata);
7275 
7276 	set_cap(_metadata, CAP_AUDIT_CONTROL);
7277 	self->audit_fd = audit_init_with_exe_filter(&self->audit_filter);
7278 	EXPECT_LE(0, self->audit_fd);
7279 	disable_caps(_metadata);
7280 }
7281 
7282 FIXTURE_TEARDOWN_PARENT(audit_layout1)
7283 {
7284 	remove_layout1(_metadata);
7285 
7286 	cleanup_layout(_metadata);
7287 
7288 	EXPECT_EQ(0, audit_cleanup(-1, NULL));
7289 }
7290 
7291 TEST_F(audit_layout1, execute_make)
7292 {
7293 	struct audit_records records;
7294 
7295 	copy_file(_metadata, bin_true, file1_s1d1);
7296 	test_execute(_metadata, 0, file1_s1d1);
7297 	test_check_exec(_metadata, 0, file1_s1d1);
7298 
7299 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_EXECUTE, NULL);
7300 
7301 	test_execute(_metadata, EACCES, file1_s1d1);
7302 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.execute",
7303 				    file1_s1d1));
7304 	test_check_exec(_metadata, EACCES, file1_s1d1);
7305 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.execute",
7306 				    file1_s1d1));
7307 
7308 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7309 	EXPECT_EQ(0, records.access);
7310 	EXPECT_EQ(0, records.domain);
7311 }
7312 
7313 /*
7314  * Using a set of handled/denied access rights make it possible to check that
7315  * only the blocked ones are logged.
7316  */
7317 
7318 TEST_F(audit_layout1, execute_read)
7319 {
7320 	struct audit_records records;
7321 
7322 	copy_file(_metadata, bin_true, file1_s1d1);
7323 	test_execute(_metadata, 0, file1_s1d1);
7324 	test_check_exec(_metadata, 0, file1_s1d1);
7325 
7326 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7327 
7328 	/*
7329 	 * The only difference with the previous audit_layout1.execute_read test is
7330 	 * the extra ",fs\\.read_file" blocked by the executable file.
7331 	 */
7332 	test_execute(_metadata, EACCES, file1_s1d1);
7333 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7334 				    "fs\\.execute,fs\\.read_file", file1_s1d1));
7335 	test_check_exec(_metadata, EACCES, file1_s1d1);
7336 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7337 				    "fs\\.execute,fs\\.read_file", file1_s1d1));
7338 
7339 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7340 	EXPECT_EQ(0, records.access);
7341 	EXPECT_EQ(0, records.domain);
7342 }
7343 
7344 TEST_F(audit_layout1, write_file)
7345 {
7346 	struct audit_records records;
7347 
7348 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7349 
7350 	EXPECT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
7351 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7352 				    "fs\\.write_file", file1_s1d1));
7353 
7354 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7355 	EXPECT_EQ(0, records.access);
7356 	EXPECT_EQ(1, records.domain);
7357 }
7358 
7359 TEST_F(audit_layout1, read_file)
7360 {
7361 	struct audit_records records;
7362 
7363 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7364 
7365 	EXPECT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
7366 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.read_file",
7367 				    file1_s1d1));
7368 
7369 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7370 	EXPECT_EQ(0, records.access);
7371 	EXPECT_EQ(1, records.domain);
7372 }
7373 
7374 TEST_F(audit_layout1, read_dir)
7375 {
7376 	struct audit_records records;
7377 
7378 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7379 
7380 	EXPECT_EQ(EACCES, test_open(dir_s1d1, O_DIRECTORY));
7381 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.read_dir",
7382 				    dir_s1d1));
7383 
7384 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7385 	EXPECT_EQ(0, records.access);
7386 	EXPECT_EQ(1, records.domain);
7387 }
7388 
7389 TEST_F(audit_layout1, remove_dir)
7390 {
7391 	struct audit_records records;
7392 
7393 	EXPECT_EQ(0, unlink(file1_s1d3));
7394 	EXPECT_EQ(0, unlink(file2_s1d3));
7395 
7396 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7397 
7398 	EXPECT_EQ(-1, rmdir(dir_s1d3));
7399 	EXPECT_EQ(EACCES, errno);
7400 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7401 				    "fs\\.remove_dir", dir_s1d2));
7402 
7403 	EXPECT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d3, AT_REMOVEDIR));
7404 	EXPECT_EQ(EACCES, errno);
7405 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7406 				    "fs\\.remove_dir", dir_s1d2));
7407 
7408 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7409 	EXPECT_EQ(0, records.access);
7410 	EXPECT_EQ(0, records.domain);
7411 }
7412 
7413 TEST_F(audit_layout1, remove_file)
7414 {
7415 	struct audit_records records;
7416 
7417 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7418 
7419 	EXPECT_EQ(-1, unlink(file1_s1d3));
7420 	EXPECT_EQ(EACCES, errno);
7421 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7422 				    "fs\\.remove_file", dir_s1d3));
7423 
7424 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7425 	EXPECT_EQ(0, records.access);
7426 	EXPECT_EQ(1, records.domain);
7427 }
7428 
7429 TEST_F(audit_layout1, make_char)
7430 {
7431 	struct audit_records records;
7432 
7433 	EXPECT_EQ(0, unlink(file1_s1d3));
7434 
7435 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7436 
7437 	EXPECT_EQ(-1, mknod(file1_s1d3, S_IFCHR | 0644, 0));
7438 	EXPECT_EQ(EACCES, errno);
7439 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.make_char",
7440 				    dir_s1d3));
7441 
7442 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7443 	EXPECT_EQ(0, records.access);
7444 	EXPECT_EQ(1, records.domain);
7445 }
7446 
7447 TEST_F(audit_layout1, make_dir)
7448 {
7449 	struct audit_records records;
7450 
7451 	EXPECT_EQ(0, unlink(file1_s1d3));
7452 
7453 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7454 
7455 	EXPECT_EQ(-1, mkdir(file1_s1d3, 0755));
7456 	EXPECT_EQ(EACCES, errno);
7457 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.make_dir",
7458 				    dir_s1d3));
7459 
7460 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7461 	EXPECT_EQ(0, records.access);
7462 	EXPECT_EQ(1, records.domain);
7463 }
7464 
7465 TEST_F(audit_layout1, make_reg)
7466 {
7467 	struct audit_records records;
7468 
7469 	EXPECT_EQ(0, unlink(file1_s1d3));
7470 
7471 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7472 
7473 	EXPECT_EQ(-1, mknod(file1_s1d3, S_IFREG | 0644, 0));
7474 	EXPECT_EQ(EACCES, errno);
7475 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.make_reg",
7476 				    dir_s1d3));
7477 
7478 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7479 	EXPECT_EQ(0, records.access);
7480 	EXPECT_EQ(1, records.domain);
7481 }
7482 
7483 TEST_F(audit_layout1, make_sock)
7484 {
7485 	struct audit_records records;
7486 
7487 	EXPECT_EQ(0, unlink(file1_s1d3));
7488 
7489 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7490 
7491 	EXPECT_EQ(-1, mknod(file1_s1d3, S_IFSOCK | 0644, 0));
7492 	EXPECT_EQ(EACCES, errno);
7493 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.make_sock",
7494 				    dir_s1d3));
7495 
7496 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7497 	EXPECT_EQ(0, records.access);
7498 	EXPECT_EQ(1, records.domain);
7499 }
7500 
7501 TEST_F(audit_layout1, make_fifo)
7502 {
7503 	struct audit_records records;
7504 
7505 	EXPECT_EQ(0, unlink(file1_s1d3));
7506 
7507 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7508 
7509 	EXPECT_EQ(-1, mknod(file1_s1d3, S_IFIFO | 0644, 0));
7510 	EXPECT_EQ(EACCES, errno);
7511 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.make_fifo",
7512 				    dir_s1d3));
7513 
7514 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7515 	EXPECT_EQ(0, records.access);
7516 	EXPECT_EQ(1, records.domain);
7517 }
7518 
7519 TEST_F(audit_layout1, make_block)
7520 {
7521 	struct audit_records records;
7522 
7523 	EXPECT_EQ(0, unlink(file1_s1d3));
7524 
7525 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7526 
7527 	EXPECT_EQ(-1, mknod(file1_s1d3, S_IFBLK | 0644, 0));
7528 	EXPECT_EQ(EACCES, errno);
7529 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7530 				    "fs\\.make_block", dir_s1d3));
7531 
7532 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7533 	EXPECT_EQ(0, records.access);
7534 	EXPECT_EQ(1, records.domain);
7535 }
7536 
7537 TEST_F(audit_layout1, make_sym)
7538 {
7539 	struct audit_records records;
7540 
7541 	EXPECT_EQ(0, unlink(file1_s1d3));
7542 
7543 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7544 
7545 	EXPECT_EQ(-1, symlink("target", file1_s1d3));
7546 	EXPECT_EQ(EACCES, errno);
7547 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.make_sym",
7548 				    dir_s1d3));
7549 
7550 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7551 	EXPECT_EQ(0, records.access);
7552 	EXPECT_EQ(1, records.domain);
7553 }
7554 
7555 TEST_F(audit_layout1, refer_handled)
7556 {
7557 	struct audit_records records;
7558 
7559 	EXPECT_EQ(0, unlink(file1_s1d3));
7560 
7561 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_REFER, NULL);
7562 
7563 	EXPECT_EQ(-1, link(file1_s1d1, file1_s1d3));
7564 	EXPECT_EQ(EXDEV, errno);
7565 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.refer",
7566 				    dir_s1d1));
7567 	EXPECT_EQ(0,
7568 		  matches_log_domain_allocated(self->audit_fd, getpid(), NULL));
7569 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.refer",
7570 				    dir_s1d3));
7571 
7572 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7573 	EXPECT_EQ(0, records.access);
7574 	EXPECT_EQ(0, records.domain);
7575 }
7576 
7577 TEST_F(audit_layout1, refer_make)
7578 {
7579 	struct audit_records records;
7580 
7581 	EXPECT_EQ(0, unlink(file1_s1d3));
7582 
7583 	enforce_fs(_metadata,
7584 		   LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER,
7585 		   NULL);
7586 
7587 	EXPECT_EQ(-1, link(file1_s1d1, file1_s1d3));
7588 	EXPECT_EQ(EACCES, errno);
7589 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.refer",
7590 				    dir_s1d1));
7591 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7592 				    "fs\\.make_reg,fs\\.refer", dir_s1d3));
7593 
7594 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7595 	EXPECT_EQ(0, records.access);
7596 	EXPECT_EQ(0, records.domain);
7597 }
7598 
7599 TEST_F(audit_layout1, refer_rename)
7600 {
7601 	struct audit_records records;
7602 
7603 	EXPECT_EQ(0, unlink(file1_s1d3));
7604 
7605 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7606 
7607 	EXPECT_EQ(EACCES, test_rename(file1_s1d2, file1_s2d3));
7608 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7609 				    "fs\\.remove_file,fs\\.refer", dir_s1d2));
7610 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7611 				    "fs\\.remove_file,fs\\.make_reg,fs\\.refer",
7612 				    dir_s2d3));
7613 
7614 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7615 	EXPECT_EQ(0, records.access);
7616 	EXPECT_EQ(0, records.domain);
7617 }
7618 
7619 TEST_F(audit_layout1, refer_exchange)
7620 {
7621 	struct audit_records records;
7622 
7623 	EXPECT_EQ(0, unlink(file1_s1d3));
7624 
7625 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7626 
7627 	/*
7628 	 * The only difference with the previous audit_layout1.refer_rename test is
7629 	 * the extra ",fs\\.make_reg" blocked by the source directory.
7630 	 */
7631 	EXPECT_EQ(EACCES, test_exchange(file1_s1d2, file1_s2d3));
7632 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7633 				    "fs\\.remove_file,fs\\.make_reg,fs\\.refer",
7634 				    dir_s1d2));
7635 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7636 				    "fs\\.remove_file,fs\\.make_reg,fs\\.refer",
7637 				    dir_s2d3));
7638 
7639 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7640 	EXPECT_EQ(0, records.access);
7641 	EXPECT_EQ(0, records.domain);
7642 }
7643 
7644 /*
7645  * This test checks that the audit record is correctly generated when the
7646  * operation is only partially denied.  This is the case for rename(2) when the
7647  * source file is allowed to be referenced but the destination directory is not.
7648  *
7649  * This is also a regression test for commit d617f0d72d80 ("landlock: Optimize
7650  * file path walks and prepare for audit support") and commit 058518c20920
7651  * ("landlock: Align partial refer access checks with final ones").
7652  */
7653 TEST_F(audit_layout1, refer_rename_half)
7654 {
7655 	struct audit_records records;
7656 	const struct rule layer1[] = {
7657 		{
7658 			.path = dir_s2d2,
7659 			.access = LANDLOCK_ACCESS_FS_REFER,
7660 		},
7661 		{},
7662 	};
7663 
7664 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_REFER, layer1);
7665 
7666 	ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d3));
7667 	ASSERT_EQ(EXDEV, errno);
7668 
7669 	/* Only half of the request is denied. */
7670 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.refer",
7671 				    dir_s1d1));
7672 
7673 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7674 	EXPECT_EQ(0, records.access);
7675 	EXPECT_EQ(1, records.domain);
7676 }
7677 
7678 TEST_F(audit_layout1, truncate)
7679 {
7680 	struct audit_records records;
7681 
7682 	enforce_fs(_metadata, ACCESS_ALL, NULL);
7683 
7684 	EXPECT_EQ(-1, truncate(file1_s1d3, 0));
7685 	EXPECT_EQ(EACCES, errno);
7686 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd, "fs\\.truncate",
7687 				    file1_s1d3));
7688 
7689 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7690 	EXPECT_EQ(0, records.access);
7691 	EXPECT_EQ(1, records.domain);
7692 }
7693 
7694 TEST_F(audit_layout1, ioctl_dev)
7695 {
7696 	struct audit_records records;
7697 	int fd;
7698 
7699 	enforce_fs(_metadata, ACCESS_ALL & ~LANDLOCK_ACCESS_FS_READ_FILE, NULL);
7700 
7701 	fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
7702 	ASSERT_LE(0, fd);
7703 	EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FIONREAD));
7704 	EXPECT_EQ(0, matches_log_fs_extra(_metadata, self->audit_fd,
7705 					  "fs\\.ioctl_dev", "/dev/null",
7706 					  " ioctlcmd=0x541b"));
7707 
7708 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7709 	EXPECT_EQ(0, records.access);
7710 	EXPECT_EQ(1, records.domain);
7711 }
7712 
7713 TEST_F(audit_layout1, resolve_unix)
7714 {
7715 	struct audit_records records;
7716 	const char *const path = "sock";
7717 	int srv_fd, cli_fd, status;
7718 	pid_t child_pid;
7719 
7720 	srv_fd = set_up_named_unix_server(_metadata, SOCK_STREAM, path);
7721 
7722 	child_pid = fork();
7723 	ASSERT_LE(0, child_pid);
7724 	if (!child_pid) {
7725 		enforce_fs(_metadata, ACCESS_ALL, NULL);
7726 
7727 		cli_fd = socket(AF_UNIX, SOCK_STREAM, 0);
7728 		ASSERT_LE(0, cli_fd);
7729 		EXPECT_EQ(EACCES,
7730 			  test_connect_named_unix(_metadata, cli_fd, path));
7731 
7732 		EXPECT_EQ(0, close(cli_fd));
7733 		_exit(_metadata->exit_code);
7734 	}
7735 
7736 	ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
7737 	EXPECT_EQ(1, WIFEXITED(status));
7738 	EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
7739 
7740 	EXPECT_EQ(0, matches_log_fs_extra(_metadata, self->audit_fd,
7741 					  "fs\\.resolve_unix", path, NULL));
7742 
7743 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7744 	EXPECT_EQ(0, records.access);
7745 	EXPECT_EQ(1, records.domain);
7746 
7747 	EXPECT_EQ(0, close(srv_fd));
7748 }
7749 
7750 TEST_F(audit_layout1, mount)
7751 {
7752 	struct audit_records records;
7753 
7754 	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_EXECUTE, NULL);
7755 
7756 	set_cap(_metadata, CAP_SYS_ADMIN);
7757 	EXPECT_EQ(-1, mount(NULL, dir_s3d2, NULL, MS_RDONLY, NULL));
7758 	EXPECT_EQ(EPERM, errno);
7759 	clear_cap(_metadata, CAP_SYS_ADMIN);
7760 	EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
7761 				    "fs\\.change_topology", dir_s3d2));
7762 	EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
7763 	EXPECT_EQ(0, records.access);
7764 	EXPECT_EQ(1, records.domain);
7765 }
7766 
7767 TEST_HARNESS_MAIN
7768