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 <fcntl.h>
12#include <linux/landlock.h>
13#include <linux/magic.h>
14#include <sched.h>
15#include <stdio.h>
16#include <string.h>
17#include <sys/capability.h>
18#include <sys/mount.h>
19#include <sys/prctl.h>
20#include <sys/sendfile.h>
21#include <sys/stat.h>
22#include <sys/sysmacros.h>
23#include <sys/vfs.h>
24#include <unistd.h>
25
26#include "common.h"
27
28#ifndef renameat2
29int renameat2(int olddirfd, const char *oldpath, int newdirfd,
30	      const char *newpath, unsigned int flags)
31{
32	return syscall(__NR_renameat2, olddirfd, oldpath, newdirfd, newpath,
33		       flags);
34}
35#endif
36
37#ifndef RENAME_EXCHANGE
38#define RENAME_EXCHANGE (1 << 1)
39#endif
40
41#define TMP_DIR "tmp"
42#define BINARY_PATH "./true"
43
44/* Paths (sibling number and depth) */
45static const char dir_s1d1[] = TMP_DIR "/s1d1";
46static const char file1_s1d1[] = TMP_DIR "/s1d1/f1";
47static const char file2_s1d1[] = TMP_DIR "/s1d1/f2";
48static const char dir_s1d2[] = TMP_DIR "/s1d1/s1d2";
49static const char file1_s1d2[] = TMP_DIR "/s1d1/s1d2/f1";
50static const char file2_s1d2[] = TMP_DIR "/s1d1/s1d2/f2";
51static const char dir_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3";
52static const char file1_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f1";
53static const char file2_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f2";
54
55static const char dir_s2d1[] = TMP_DIR "/s2d1";
56static const char file1_s2d1[] = TMP_DIR "/s2d1/f1";
57static const char dir_s2d2[] = TMP_DIR "/s2d1/s2d2";
58static const char file1_s2d2[] = TMP_DIR "/s2d1/s2d2/f1";
59static const char dir_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3";
60static const char file1_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f1";
61static const char file2_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f2";
62
63static const char dir_s3d1[] = TMP_DIR "/s3d1";
64static const char file1_s3d1[] = TMP_DIR "/s3d1/f1";
65/* dir_s3d2 is a mount point. */
66static const char dir_s3d2[] = TMP_DIR "/s3d1/s3d2";
67static const char dir_s3d3[] = TMP_DIR "/s3d1/s3d2/s3d3";
68
69/*
70 * layout1 hierarchy:
71 *
72 * tmp
73 * ├── s1d1
74 * │   ├── f1
75 * │   ├── f2
76 * │   └── s1d2
77 * │       ├── f1
78 * │       ├── f2
79 * │       └── s1d3
80 * │           ├── f1
81 * │           └── f2
82 * ├── s2d1
83 * │   ├── f1
84 * │   └── s2d2
85 * │       ├── f1
86 * │       └── s2d3
87 * │           ├── f1
88 * │           └── f2
89 * └── s3d1
90 *     ├── f1
91 *     └── s3d2
92 *         └── s3d3
93 */
94
95static bool fgrep(FILE *const inf, const char *const str)
96{
97	char line[32];
98	const int slen = strlen(str);
99
100	while (!feof(inf)) {
101		if (!fgets(line, sizeof(line), inf))
102			break;
103		if (strncmp(line, str, slen))
104			continue;
105
106		return true;
107	}
108
109	return false;
110}
111
112static bool supports_filesystem(const char *const filesystem)
113{
114	char str[32];
115	int len;
116	bool res = true;
117	FILE *const inf = fopen("/proc/filesystems", "r");
118
119	/*
120	 * Consider that the filesystem is supported if we cannot get the
121	 * supported ones.
122	 */
123	if (!inf)
124		return true;
125
126	/* filesystem can be null for bind mounts. */
127	if (!filesystem)
128		goto out;
129
130	len = snprintf(str, sizeof(str), "nodev\t%s\n", filesystem);
131	if (len >= sizeof(str))
132		/* Ignores too-long filesystem names. */
133		goto out;
134
135	res = fgrep(inf, str);
136
137out:
138	fclose(inf);
139	return res;
140}
141
142static bool cwd_matches_fs(unsigned int fs_magic)
143{
144	struct statfs statfs_buf;
145
146	if (!fs_magic)
147		return true;
148
149	if (statfs(".", &statfs_buf))
150		return true;
151
152	return statfs_buf.f_type == fs_magic;
153}
154
155static void mkdir_parents(struct __test_metadata *const _metadata,
156			  const char *const path)
157{
158	char *walker;
159	const char *parent;
160	int i, err;
161
162	ASSERT_NE(path[0], '\0');
163	walker = strdup(path);
164	ASSERT_NE(NULL, walker);
165	parent = walker;
166	for (i = 1; walker[i]; i++) {
167		if (walker[i] != '/')
168			continue;
169		walker[i] = '\0';
170		err = mkdir(parent, 0700);
171		ASSERT_FALSE(err && errno != EEXIST)
172		{
173			TH_LOG("Failed to create directory \"%s\": %s", parent,
174			       strerror(errno));
175		}
176		walker[i] = '/';
177	}
178	free(walker);
179}
180
181static void create_directory(struct __test_metadata *const _metadata,
182			     const char *const path)
183{
184	mkdir_parents(_metadata, path);
185	ASSERT_EQ(0, mkdir(path, 0700))
186	{
187		TH_LOG("Failed to create directory \"%s\": %s", path,
188		       strerror(errno));
189	}
190}
191
192static void create_file(struct __test_metadata *const _metadata,
193			const char *const path)
194{
195	mkdir_parents(_metadata, path);
196	ASSERT_EQ(0, mknod(path, S_IFREG | 0700, 0))
197	{
198		TH_LOG("Failed to create file \"%s\": %s", path,
199		       strerror(errno));
200	}
201}
202
203static int remove_path(const char *const path)
204{
205	char *walker;
206	int i, ret, err = 0;
207
208	walker = strdup(path);
209	if (!walker) {
210		err = ENOMEM;
211		goto out;
212	}
213	if (unlink(path) && rmdir(path)) {
214		if (errno != ENOENT && errno != ENOTDIR)
215			err = errno;
216		goto out;
217	}
218	for (i = strlen(walker); i > 0; i--) {
219		if (walker[i] != '/')
220			continue;
221		walker[i] = '\0';
222		ret = rmdir(walker);
223		if (ret) {
224			if (errno != ENOTEMPTY && errno != EBUSY)
225				err = errno;
226			goto out;
227		}
228		if (strcmp(walker, TMP_DIR) == 0)
229			goto out;
230	}
231
232out:
233	free(walker);
234	return err;
235}
236
237struct mnt_opt {
238	const char *const source;
239	const char *const type;
240	const unsigned long flags;
241	const char *const data;
242};
243
244#define MNT_TMP_DATA "size=4m,mode=700"
245
246static const struct mnt_opt mnt_tmp = {
247	.type = "tmpfs",
248	.data = MNT_TMP_DATA,
249};
250
251static int mount_opt(const struct mnt_opt *const mnt, const char *const target)
252{
253	return mount(mnt->source ?: mnt->type, target, mnt->type, mnt->flags,
254		     mnt->data);
255}
256
257static void prepare_layout_opt(struct __test_metadata *const _metadata,
258			       const struct mnt_opt *const mnt)
259{
260	disable_caps(_metadata);
261	umask(0077);
262	create_directory(_metadata, TMP_DIR);
263
264	/*
265	 * Do not pollute the rest of the system: creates a private mount point
266	 * for tests relying on pivot_root(2) and move_mount(2).
267	 */
268	set_cap(_metadata, CAP_SYS_ADMIN);
269	ASSERT_EQ(0, unshare(CLONE_NEWNS | CLONE_NEWCGROUP));
270	ASSERT_EQ(0, mount_opt(mnt, TMP_DIR))
271	{
272		TH_LOG("Failed to mount the %s filesystem: %s", mnt->type,
273		       strerror(errno));
274		/*
275		 * FIXTURE_TEARDOWN() is not called when FIXTURE_SETUP()
276		 * failed, so we need to explicitly do a minimal cleanup to
277		 * avoid cascading errors with other tests that don't depend on
278		 * the same filesystem.
279		 */
280		remove_path(TMP_DIR);
281	}
282	ASSERT_EQ(0, mount(NULL, TMP_DIR, NULL, MS_PRIVATE | MS_REC, NULL));
283	clear_cap(_metadata, CAP_SYS_ADMIN);
284}
285
286static void prepare_layout(struct __test_metadata *const _metadata)
287{
288	prepare_layout_opt(_metadata, &mnt_tmp);
289}
290
291static void cleanup_layout(struct __test_metadata *const _metadata)
292{
293	set_cap(_metadata, CAP_SYS_ADMIN);
294	EXPECT_EQ(0, umount(TMP_DIR));
295	clear_cap(_metadata, CAP_SYS_ADMIN);
296	EXPECT_EQ(0, remove_path(TMP_DIR));
297}
298
299/* clang-format off */
300FIXTURE(layout0) {};
301/* clang-format on */
302
303FIXTURE_SETUP(layout0)
304{
305	prepare_layout(_metadata);
306}
307
308FIXTURE_TEARDOWN(layout0)
309{
310	cleanup_layout(_metadata);
311}
312
313static void create_layout1(struct __test_metadata *const _metadata)
314{
315	create_file(_metadata, file1_s1d1);
316	create_file(_metadata, file1_s1d2);
317	create_file(_metadata, file1_s1d3);
318	create_file(_metadata, file2_s1d1);
319	create_file(_metadata, file2_s1d2);
320	create_file(_metadata, file2_s1d3);
321
322	create_file(_metadata, file1_s2d1);
323	create_file(_metadata, file1_s2d2);
324	create_file(_metadata, file1_s2d3);
325	create_file(_metadata, file2_s2d3);
326
327	create_file(_metadata, file1_s3d1);
328	create_directory(_metadata, dir_s3d2);
329	set_cap(_metadata, CAP_SYS_ADMIN);
330	ASSERT_EQ(0, mount_opt(&mnt_tmp, dir_s3d2));
331	clear_cap(_metadata, CAP_SYS_ADMIN);
332
333	ASSERT_EQ(0, mkdir(dir_s3d3, 0700));
334}
335
336static void remove_layout1(struct __test_metadata *const _metadata)
337{
338	EXPECT_EQ(0, remove_path(file2_s1d3));
339	EXPECT_EQ(0, remove_path(file2_s1d2));
340	EXPECT_EQ(0, remove_path(file2_s1d1));
341	EXPECT_EQ(0, remove_path(file1_s1d3));
342	EXPECT_EQ(0, remove_path(file1_s1d2));
343	EXPECT_EQ(0, remove_path(file1_s1d1));
344	EXPECT_EQ(0, remove_path(dir_s1d3));
345
346	EXPECT_EQ(0, remove_path(file2_s2d3));
347	EXPECT_EQ(0, remove_path(file1_s2d3));
348	EXPECT_EQ(0, remove_path(file1_s2d2));
349	EXPECT_EQ(0, remove_path(file1_s2d1));
350	EXPECT_EQ(0, remove_path(dir_s2d2));
351
352	EXPECT_EQ(0, remove_path(file1_s3d1));
353	EXPECT_EQ(0, remove_path(dir_s3d3));
354	set_cap(_metadata, CAP_SYS_ADMIN);
355	umount(dir_s3d2);
356	clear_cap(_metadata, CAP_SYS_ADMIN);
357	EXPECT_EQ(0, remove_path(dir_s3d2));
358}
359
360/* clang-format off */
361FIXTURE(layout1) {};
362/* clang-format on */
363
364FIXTURE_SETUP(layout1)
365{
366	prepare_layout(_metadata);
367
368	create_layout1(_metadata);
369}
370
371FIXTURE_TEARDOWN(layout1)
372{
373	remove_layout1(_metadata);
374
375	cleanup_layout(_metadata);
376}
377
378/*
379 * This helper enables to use the ASSERT_* macros and print the line number
380 * pointing to the test caller.
381 */
382static int test_open_rel(const int dirfd, const char *const path,
383			 const int flags)
384{
385	int fd;
386
387	/* Works with file and directories. */
388	fd = openat(dirfd, path, flags | O_CLOEXEC);
389	if (fd < 0)
390		return errno;
391	/*
392	 * Mixing error codes from close(2) and open(2) should not lead to any
393	 * (access type) confusion for this test.
394	 */
395	if (close(fd) != 0)
396		return errno;
397	return 0;
398}
399
400static int test_open(const char *const path, const int flags)
401{
402	return test_open_rel(AT_FDCWD, path, flags);
403}
404
405TEST_F_FORK(layout1, no_restriction)
406{
407	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
408	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
409	ASSERT_EQ(0, test_open(file2_s1d1, O_RDONLY));
410	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
411	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
412	ASSERT_EQ(0, test_open(file2_s1d2, O_RDONLY));
413	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
414	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
415
416	ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
417	ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
418	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
419	ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
420	ASSERT_EQ(0, test_open(dir_s2d3, O_RDONLY));
421	ASSERT_EQ(0, test_open(file1_s2d3, O_RDONLY));
422
423	ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
424	ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
425	ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
426}
427
428TEST_F_FORK(layout1, inval)
429{
430	struct landlock_path_beneath_attr path_beneath = {
431		.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
432				  LANDLOCK_ACCESS_FS_WRITE_FILE,
433		.parent_fd = -1,
434	};
435	struct landlock_ruleset_attr ruleset_attr = {
436		.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |
437				     LANDLOCK_ACCESS_FS_WRITE_FILE,
438	};
439	int ruleset_fd;
440
441	path_beneath.parent_fd =
442		open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
443	ASSERT_LE(0, path_beneath.parent_fd);
444
445	ruleset_fd = open(dir_s1d1, O_PATH | O_DIRECTORY | O_CLOEXEC);
446	ASSERT_LE(0, ruleset_fd);
447	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
448					&path_beneath, 0));
449	/* Returns EBADF because ruleset_fd is not a landlock-ruleset FD. */
450	ASSERT_EQ(EBADF, errno);
451	ASSERT_EQ(0, close(ruleset_fd));
452
453	ruleset_fd = open(dir_s1d1, O_DIRECTORY | O_CLOEXEC);
454	ASSERT_LE(0, ruleset_fd);
455	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
456					&path_beneath, 0));
457	/* Returns EBADFD because ruleset_fd is not a valid ruleset. */
458	ASSERT_EQ(EBADFD, errno);
459	ASSERT_EQ(0, close(ruleset_fd));
460
461	/* Gets a real ruleset. */
462	ruleset_fd =
463		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
464	ASSERT_LE(0, ruleset_fd);
465	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
466				       &path_beneath, 0));
467	ASSERT_EQ(0, close(path_beneath.parent_fd));
468
469	/* Tests without O_PATH. */
470	path_beneath.parent_fd = open(dir_s1d2, O_DIRECTORY | O_CLOEXEC);
471	ASSERT_LE(0, path_beneath.parent_fd);
472	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
473				       &path_beneath, 0));
474	ASSERT_EQ(0, close(path_beneath.parent_fd));
475
476	/* Tests with a ruleset FD. */
477	path_beneath.parent_fd = ruleset_fd;
478	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
479					&path_beneath, 0));
480	ASSERT_EQ(EBADFD, errno);
481
482	/* Checks unhandled allowed_access. */
483	path_beneath.parent_fd =
484		open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
485	ASSERT_LE(0, path_beneath.parent_fd);
486
487	/* Test with legitimate values. */
488	path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_EXECUTE;
489	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
490					&path_beneath, 0));
491	ASSERT_EQ(EINVAL, errno);
492	path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_EXECUTE;
493
494	/* Tests with denied-by-default access right. */
495	path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_REFER;
496	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
497					&path_beneath, 0));
498	ASSERT_EQ(EINVAL, errno);
499	path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_REFER;
500
501	/* Test with unknown (64-bits) value. */
502	path_beneath.allowed_access |= (1ULL << 60);
503	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
504					&path_beneath, 0));
505	ASSERT_EQ(EINVAL, errno);
506	path_beneath.allowed_access &= ~(1ULL << 60);
507
508	/* Test with no access. */
509	path_beneath.allowed_access = 0;
510	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
511					&path_beneath, 0));
512	ASSERT_EQ(ENOMSG, errno);
513	path_beneath.allowed_access &= ~(1ULL << 60);
514
515	ASSERT_EQ(0, close(path_beneath.parent_fd));
516
517	/* Enforces the ruleset. */
518	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
519	ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
520
521	ASSERT_EQ(0, close(ruleset_fd));
522}
523
524/* clang-format off */
525
526#define ACCESS_FILE ( \
527	LANDLOCK_ACCESS_FS_EXECUTE | \
528	LANDLOCK_ACCESS_FS_WRITE_FILE | \
529	LANDLOCK_ACCESS_FS_READ_FILE | \
530	LANDLOCK_ACCESS_FS_TRUNCATE)
531
532#define ACCESS_LAST LANDLOCK_ACCESS_FS_TRUNCATE
533
534#define ACCESS_ALL ( \
535	ACCESS_FILE | \
536	LANDLOCK_ACCESS_FS_READ_DIR | \
537	LANDLOCK_ACCESS_FS_REMOVE_DIR | \
538	LANDLOCK_ACCESS_FS_REMOVE_FILE | \
539	LANDLOCK_ACCESS_FS_MAKE_CHAR | \
540	LANDLOCK_ACCESS_FS_MAKE_DIR | \
541	LANDLOCK_ACCESS_FS_MAKE_REG | \
542	LANDLOCK_ACCESS_FS_MAKE_SOCK | \
543	LANDLOCK_ACCESS_FS_MAKE_FIFO | \
544	LANDLOCK_ACCESS_FS_MAKE_BLOCK | \
545	LANDLOCK_ACCESS_FS_MAKE_SYM | \
546	LANDLOCK_ACCESS_FS_REFER)
547
548/* clang-format on */
549
550TEST_F_FORK(layout1, file_and_dir_access_rights)
551{
552	__u64 access;
553	int err;
554	struct landlock_path_beneath_attr path_beneath_file = {},
555					  path_beneath_dir = {};
556	struct landlock_ruleset_attr ruleset_attr = {
557		.handled_access_fs = ACCESS_ALL,
558	};
559	const int ruleset_fd =
560		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
561
562	ASSERT_LE(0, ruleset_fd);
563
564	/* Tests access rights for files. */
565	path_beneath_file.parent_fd = open(file1_s1d2, O_PATH | O_CLOEXEC);
566	ASSERT_LE(0, path_beneath_file.parent_fd);
567
568	/* Tests access rights for directories. */
569	path_beneath_dir.parent_fd =
570		open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
571	ASSERT_LE(0, path_beneath_dir.parent_fd);
572
573	for (access = 1; access <= ACCESS_LAST; access <<= 1) {
574		path_beneath_dir.allowed_access = access;
575		ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
576					       LANDLOCK_RULE_PATH_BENEATH,
577					       &path_beneath_dir, 0));
578
579		path_beneath_file.allowed_access = access;
580		err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
581					&path_beneath_file, 0);
582		if (access & ACCESS_FILE) {
583			ASSERT_EQ(0, err);
584		} else {
585			ASSERT_EQ(-1, err);
586			ASSERT_EQ(EINVAL, errno);
587		}
588	}
589	ASSERT_EQ(0, close(path_beneath_file.parent_fd));
590	ASSERT_EQ(0, close(path_beneath_dir.parent_fd));
591	ASSERT_EQ(0, close(ruleset_fd));
592}
593
594TEST_F_FORK(layout0, unknown_access_rights)
595{
596	__u64 access_mask;
597
598	for (access_mask = 1ULL << 63; access_mask != ACCESS_LAST;
599	     access_mask >>= 1) {
600		struct landlock_ruleset_attr ruleset_attr = {
601			.handled_access_fs = access_mask,
602		};
603
604		ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
605						      sizeof(ruleset_attr), 0));
606		ASSERT_EQ(EINVAL, errno);
607	}
608}
609
610static void add_path_beneath(struct __test_metadata *const _metadata,
611			     const int ruleset_fd, const __u64 allowed_access,
612			     const char *const path)
613{
614	struct landlock_path_beneath_attr path_beneath = {
615		.allowed_access = allowed_access,
616	};
617
618	path_beneath.parent_fd = open(path, O_PATH | O_CLOEXEC);
619	ASSERT_LE(0, path_beneath.parent_fd)
620	{
621		TH_LOG("Failed to open directory \"%s\": %s", path,
622		       strerror(errno));
623	}
624	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
625				       &path_beneath, 0))
626	{
627		TH_LOG("Failed to update the ruleset with \"%s\": %s", path,
628		       strerror(errno));
629	}
630	ASSERT_EQ(0, close(path_beneath.parent_fd));
631}
632
633struct rule {
634	const char *path;
635	__u64 access;
636};
637
638/* clang-format off */
639
640#define ACCESS_RO ( \
641	LANDLOCK_ACCESS_FS_READ_FILE | \
642	LANDLOCK_ACCESS_FS_READ_DIR)
643
644#define ACCESS_RW ( \
645	ACCESS_RO | \
646	LANDLOCK_ACCESS_FS_WRITE_FILE)
647
648/* clang-format on */
649
650static int create_ruleset(struct __test_metadata *const _metadata,
651			  const __u64 handled_access_fs,
652			  const struct rule rules[])
653{
654	int ruleset_fd, i;
655	struct landlock_ruleset_attr ruleset_attr = {
656		.handled_access_fs = handled_access_fs,
657	};
658
659	ASSERT_NE(NULL, rules)
660	{
661		TH_LOG("No rule list");
662	}
663	ASSERT_NE(NULL, rules[0].path)
664	{
665		TH_LOG("Empty rule list");
666	}
667
668	ruleset_fd =
669		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
670	ASSERT_LE(0, ruleset_fd)
671	{
672		TH_LOG("Failed to create a ruleset: %s", strerror(errno));
673	}
674
675	for (i = 0; rules[i].path; i++) {
676		add_path_beneath(_metadata, ruleset_fd, rules[i].access,
677				 rules[i].path);
678	}
679	return ruleset_fd;
680}
681
682static void enforce_ruleset(struct __test_metadata *const _metadata,
683			    const int ruleset_fd)
684{
685	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
686	ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0))
687	{
688		TH_LOG("Failed to enforce ruleset: %s", strerror(errno));
689	}
690}
691
692TEST_F_FORK(layout0, proc_nsfs)
693{
694	const struct rule rules[] = {
695		{
696			.path = "/dev/null",
697			.access = LANDLOCK_ACCESS_FS_READ_FILE |
698				  LANDLOCK_ACCESS_FS_WRITE_FILE,
699		},
700		{},
701	};
702	struct landlock_path_beneath_attr path_beneath;
703	const int ruleset_fd = create_ruleset(
704		_metadata, rules[0].access | LANDLOCK_ACCESS_FS_READ_DIR,
705		rules);
706
707	ASSERT_LE(0, ruleset_fd);
708	ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
709
710	enforce_ruleset(_metadata, ruleset_fd);
711
712	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
713	ASSERT_EQ(EACCES, test_open("/dev", O_RDONLY));
714	ASSERT_EQ(0, test_open("/dev/null", O_RDONLY));
715	ASSERT_EQ(EACCES, test_open("/dev/full", O_RDONLY));
716
717	ASSERT_EQ(EACCES, test_open("/proc", O_RDONLY));
718	ASSERT_EQ(EACCES, test_open("/proc/self", O_RDONLY));
719	ASSERT_EQ(EACCES, test_open("/proc/self/ns", O_RDONLY));
720	/*
721	 * Because nsfs is an internal filesystem, /proc/self/ns/mnt is a
722	 * disconnected path.  Such path cannot be identified and must then be
723	 * allowed.
724	 */
725	ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
726
727	/*
728	 * Checks that it is not possible to add nsfs-like filesystem
729	 * references to a ruleset.
730	 */
731	path_beneath.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
732				      LANDLOCK_ACCESS_FS_WRITE_FILE,
733	path_beneath.parent_fd = open("/proc/self/ns/mnt", O_PATH | O_CLOEXEC);
734	ASSERT_LE(0, path_beneath.parent_fd);
735	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
736					&path_beneath, 0));
737	ASSERT_EQ(EBADFD, errno);
738	ASSERT_EQ(0, close(path_beneath.parent_fd));
739}
740
741TEST_F_FORK(layout0, unpriv)
742{
743	const struct rule rules[] = {
744		{
745			.path = TMP_DIR,
746			.access = ACCESS_RO,
747		},
748		{},
749	};
750	int ruleset_fd;
751
752	drop_caps(_metadata);
753
754	ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
755	ASSERT_LE(0, ruleset_fd);
756	ASSERT_EQ(-1, landlock_restrict_self(ruleset_fd, 0));
757	ASSERT_EQ(EPERM, errno);
758
759	/* enforce_ruleset() calls prctl(no_new_privs). */
760	enforce_ruleset(_metadata, ruleset_fd);
761	ASSERT_EQ(0, close(ruleset_fd));
762}
763
764TEST_F_FORK(layout1, effective_access)
765{
766	const struct rule rules[] = {
767		{
768			.path = dir_s1d2,
769			.access = ACCESS_RO,
770		},
771		{
772			.path = file1_s2d2,
773			.access = LANDLOCK_ACCESS_FS_READ_FILE |
774				  LANDLOCK_ACCESS_FS_WRITE_FILE,
775		},
776		{},
777	};
778	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
779	char buf;
780	int reg_fd;
781
782	ASSERT_LE(0, ruleset_fd);
783	enforce_ruleset(_metadata, ruleset_fd);
784	ASSERT_EQ(0, close(ruleset_fd));
785
786	/* Tests on a directory (with or without O_PATH). */
787	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
788	ASSERT_EQ(0, test_open("/", O_RDONLY | O_PATH));
789	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
790	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_PATH));
791	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
792	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY | O_PATH));
793
794	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
795	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
796	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
797	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
798
799	/* Tests on a file (with or without O_PATH). */
800	ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY));
801	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_PATH));
802
803	ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
804
805	/* Checks effective read and write actions. */
806	reg_fd = open(file1_s2d2, O_RDWR | O_CLOEXEC);
807	ASSERT_LE(0, reg_fd);
808	ASSERT_EQ(1, write(reg_fd, ".", 1));
809	ASSERT_LE(0, lseek(reg_fd, 0, SEEK_SET));
810	ASSERT_EQ(1, read(reg_fd, &buf, 1));
811	ASSERT_EQ('.', buf);
812	ASSERT_EQ(0, close(reg_fd));
813
814	/* Just in case, double-checks effective actions. */
815	reg_fd = open(file1_s2d2, O_RDONLY | O_CLOEXEC);
816	ASSERT_LE(0, reg_fd);
817	ASSERT_EQ(-1, write(reg_fd, &buf, 1));
818	ASSERT_EQ(EBADF, errno);
819	ASSERT_EQ(0, close(reg_fd));
820}
821
822TEST_F_FORK(layout1, unhandled_access)
823{
824	const struct rule rules[] = {
825		{
826			.path = dir_s1d2,
827			.access = ACCESS_RO,
828		},
829		{},
830	};
831	/* Here, we only handle read accesses, not write accesses. */
832	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
833
834	ASSERT_LE(0, ruleset_fd);
835	enforce_ruleset(_metadata, ruleset_fd);
836	ASSERT_EQ(0, close(ruleset_fd));
837
838	/*
839	 * Because the policy does not handle LANDLOCK_ACCESS_FS_WRITE_FILE,
840	 * opening for write-only should be allowed, but not read-write.
841	 */
842	ASSERT_EQ(0, test_open(file1_s1d1, O_WRONLY));
843	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
844
845	ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
846	ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
847}
848
849TEST_F_FORK(layout1, ruleset_overlap)
850{
851	const struct rule rules[] = {
852		/* These rules should be ORed among them. */
853		{
854			.path = dir_s1d2,
855			.access = LANDLOCK_ACCESS_FS_READ_FILE |
856				  LANDLOCK_ACCESS_FS_WRITE_FILE,
857		},
858		{
859			.path = dir_s1d2,
860			.access = LANDLOCK_ACCESS_FS_READ_FILE |
861				  LANDLOCK_ACCESS_FS_READ_DIR,
862		},
863		{},
864	};
865	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
866
867	ASSERT_LE(0, ruleset_fd);
868	enforce_ruleset(_metadata, ruleset_fd);
869	ASSERT_EQ(0, close(ruleset_fd));
870
871	/* Checks s1d1 hierarchy. */
872	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
873	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
874	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
875	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
876
877	/* Checks s1d2 hierarchy. */
878	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
879	ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
880	ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
881	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
882
883	/* Checks s1d3 hierarchy. */
884	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
885	ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
886	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
887	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
888}
889
890TEST_F_FORK(layout1, layer_rule_unions)
891{
892	const struct rule layer1[] = {
893		{
894			.path = dir_s1d2,
895			.access = LANDLOCK_ACCESS_FS_READ_FILE,
896		},
897		/* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
898		{
899			.path = dir_s1d3,
900			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
901		},
902		{},
903	};
904	const struct rule layer2[] = {
905		/* Doesn't change anything from layer1. */
906		{
907			.path = dir_s1d2,
908			.access = LANDLOCK_ACCESS_FS_READ_FILE |
909				  LANDLOCK_ACCESS_FS_WRITE_FILE,
910		},
911		{},
912	};
913	const struct rule layer3[] = {
914		/* Only allows write (but not read) to dir_s1d3. */
915		{
916			.path = dir_s1d2,
917			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
918		},
919		{},
920	};
921	int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1);
922
923	ASSERT_LE(0, ruleset_fd);
924	enforce_ruleset(_metadata, ruleset_fd);
925	ASSERT_EQ(0, close(ruleset_fd));
926
927	/* Checks s1d1 hierarchy with layer1. */
928	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
929	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
930	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
931	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
932
933	/* Checks s1d2 hierarchy with layer1. */
934	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
935	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
936	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
937	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
938
939	/* Checks s1d3 hierarchy with layer1. */
940	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
941	ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
942	/* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
943	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
944	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
945
946	/* Doesn't change anything from layer1. */
947	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2);
948	ASSERT_LE(0, ruleset_fd);
949	enforce_ruleset(_metadata, ruleset_fd);
950	ASSERT_EQ(0, close(ruleset_fd));
951
952	/* Checks s1d1 hierarchy with layer2. */
953	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
954	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
955	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
956	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
957
958	/* Checks s1d2 hierarchy with layer2. */
959	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
960	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
961	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
962	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
963
964	/* Checks s1d3 hierarchy with layer2. */
965	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
966	ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
967	/* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
968	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
969	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
970
971	/* Only allows write (but not read) to dir_s1d3. */
972	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3);
973	ASSERT_LE(0, ruleset_fd);
974	enforce_ruleset(_metadata, ruleset_fd);
975	ASSERT_EQ(0, close(ruleset_fd));
976
977	/* Checks s1d1 hierarchy with layer3. */
978	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
979	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
980	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
981	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
982
983	/* Checks s1d2 hierarchy with layer3. */
984	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDONLY));
985	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
986	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
987	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
988
989	/* Checks s1d3 hierarchy with layer3. */
990	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
991	ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
992	/* dir_s1d3 should now deny READ_FILE and WRITE_FILE (O_RDWR). */
993	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDWR));
994	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
995}
996
997TEST_F_FORK(layout1, non_overlapping_accesses)
998{
999	const struct rule layer1[] = {
1000		{
1001			.path = dir_s1d2,
1002			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
1003		},
1004		{},
1005	};
1006	const struct rule layer2[] = {
1007		{
1008			.path = dir_s1d3,
1009			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1010		},
1011		{},
1012	};
1013	int ruleset_fd;
1014
1015	ASSERT_EQ(0, unlink(file1_s1d1));
1016	ASSERT_EQ(0, unlink(file1_s1d2));
1017
1018	ruleset_fd =
1019		create_ruleset(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, layer1);
1020	ASSERT_LE(0, ruleset_fd);
1021	enforce_ruleset(_metadata, ruleset_fd);
1022	ASSERT_EQ(0, close(ruleset_fd));
1023
1024	ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
1025	ASSERT_EQ(EACCES, errno);
1026	ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
1027	ASSERT_EQ(0, unlink(file1_s1d2));
1028
1029	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_REMOVE_FILE,
1030				    layer2);
1031	ASSERT_LE(0, ruleset_fd);
1032	enforce_ruleset(_metadata, ruleset_fd);
1033	ASSERT_EQ(0, close(ruleset_fd));
1034
1035	/* Unchanged accesses for file creation. */
1036	ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
1037	ASSERT_EQ(EACCES, errno);
1038	ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
1039
1040	/* Checks file removing. */
1041	ASSERT_EQ(-1, unlink(file1_s1d2));
1042	ASSERT_EQ(EACCES, errno);
1043	ASSERT_EQ(0, unlink(file1_s1d3));
1044}
1045
1046TEST_F_FORK(layout1, interleaved_masked_accesses)
1047{
1048	/*
1049	 * Checks overly restrictive rules:
1050	 * layer 1: allows R   s1d1/s1d2/s1d3/file1
1051	 * layer 2: allows RW  s1d1/s1d2/s1d3
1052	 *          allows  W  s1d1/s1d2
1053	 *          denies R   s1d1/s1d2
1054	 * layer 3: allows R   s1d1
1055	 * layer 4: allows R   s1d1/s1d2
1056	 *          denies  W  s1d1/s1d2
1057	 * layer 5: allows R   s1d1/s1d2
1058	 * layer 6: allows   X ----
1059	 * layer 7: allows  W  s1d1/s1d2
1060	 *          denies R   s1d1/s1d2
1061	 */
1062	const struct rule layer1_read[] = {
1063		/* Allows read access to file1_s1d3 with the first layer. */
1064		{
1065			.path = file1_s1d3,
1066			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1067		},
1068		{},
1069	};
1070	/* First rule with write restrictions. */
1071	const struct rule layer2_read_write[] = {
1072		/* Start by granting read-write access via its parent directory... */
1073		{
1074			.path = dir_s1d3,
1075			.access = LANDLOCK_ACCESS_FS_READ_FILE |
1076				  LANDLOCK_ACCESS_FS_WRITE_FILE,
1077		},
1078		/* ...but also denies read access via its grandparent directory. */
1079		{
1080			.path = dir_s1d2,
1081			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
1082		},
1083		{},
1084	};
1085	const struct rule layer3_read[] = {
1086		/* Allows read access via its great-grandparent directory. */
1087		{
1088			.path = dir_s1d1,
1089			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1090		},
1091		{},
1092	};
1093	const struct rule layer4_read_write[] = {
1094		/*
1095		 * Try to confuse the deny access by denying write (but not
1096		 * read) access via its grandparent directory.
1097		 */
1098		{
1099			.path = dir_s1d2,
1100			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1101		},
1102		{},
1103	};
1104	const struct rule layer5_read[] = {
1105		/*
1106		 * Try to override layer2's deny read access by explicitly
1107		 * allowing read access via file1_s1d3's grandparent.
1108		 */
1109		{
1110			.path = dir_s1d2,
1111			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1112		},
1113		{},
1114	};
1115	const struct rule layer6_execute[] = {
1116		/*
1117		 * Restricts an unrelated file hierarchy with a new access
1118		 * (non-overlapping) type.
1119		 */
1120		{
1121			.path = dir_s2d1,
1122			.access = LANDLOCK_ACCESS_FS_EXECUTE,
1123		},
1124		{},
1125	};
1126	const struct rule layer7_read_write[] = {
1127		/*
1128		 * Finally, denies read access to file1_s1d3 via its
1129		 * grandparent.
1130		 */
1131		{
1132			.path = dir_s1d2,
1133			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
1134		},
1135		{},
1136	};
1137	int ruleset_fd;
1138
1139	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
1140				    layer1_read);
1141	ASSERT_LE(0, ruleset_fd);
1142	enforce_ruleset(_metadata, ruleset_fd);
1143	ASSERT_EQ(0, close(ruleset_fd));
1144
1145	/* Checks that read access is granted for file1_s1d3 with layer 1. */
1146	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1147	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1148	ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
1149
1150	ruleset_fd = create_ruleset(_metadata,
1151				    LANDLOCK_ACCESS_FS_READ_FILE |
1152					    LANDLOCK_ACCESS_FS_WRITE_FILE,
1153				    layer2_read_write);
1154	ASSERT_LE(0, ruleset_fd);
1155	enforce_ruleset(_metadata, ruleset_fd);
1156	ASSERT_EQ(0, close(ruleset_fd));
1157
1158	/* Checks that previous access rights are unchanged with layer 2. */
1159	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1160	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1161	ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
1162
1163	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
1164				    layer3_read);
1165	ASSERT_LE(0, ruleset_fd);
1166	enforce_ruleset(_metadata, ruleset_fd);
1167	ASSERT_EQ(0, close(ruleset_fd));
1168
1169	/* Checks that previous access rights are unchanged with layer 3. */
1170	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1171	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1172	ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
1173
1174	/* This time, denies write access for the file hierarchy. */
1175	ruleset_fd = create_ruleset(_metadata,
1176				    LANDLOCK_ACCESS_FS_READ_FILE |
1177					    LANDLOCK_ACCESS_FS_WRITE_FILE,
1178				    layer4_read_write);
1179	ASSERT_LE(0, ruleset_fd);
1180	enforce_ruleset(_metadata, ruleset_fd);
1181	ASSERT_EQ(0, close(ruleset_fd));
1182
1183	/*
1184	 * Checks that the only change with layer 4 is that write access is
1185	 * denied.
1186	 */
1187	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1188	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1189	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1190	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1191
1192	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
1193				    layer5_read);
1194	ASSERT_LE(0, ruleset_fd);
1195	enforce_ruleset(_metadata, ruleset_fd);
1196	ASSERT_EQ(0, close(ruleset_fd));
1197
1198	/* Checks that previous access rights are unchanged with layer 5. */
1199	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1200	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1201	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1202	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1203
1204	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_EXECUTE,
1205				    layer6_execute);
1206	ASSERT_LE(0, ruleset_fd);
1207	enforce_ruleset(_metadata, ruleset_fd);
1208	ASSERT_EQ(0, close(ruleset_fd));
1209
1210	/* Checks that previous access rights are unchanged with layer 6. */
1211	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1212	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1213	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1214	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1215
1216	ruleset_fd = create_ruleset(_metadata,
1217				    LANDLOCK_ACCESS_FS_READ_FILE |
1218					    LANDLOCK_ACCESS_FS_WRITE_FILE,
1219				    layer7_read_write);
1220	ASSERT_LE(0, ruleset_fd);
1221	enforce_ruleset(_metadata, ruleset_fd);
1222	ASSERT_EQ(0, close(ruleset_fd));
1223
1224	/* Checks read access is now denied with layer 7. */
1225	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
1226	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1227	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1228	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1229}
1230
1231TEST_F_FORK(layout1, inherit_subset)
1232{
1233	const struct rule rules[] = {
1234		{
1235			.path = dir_s1d2,
1236			.access = LANDLOCK_ACCESS_FS_READ_FILE |
1237				  LANDLOCK_ACCESS_FS_READ_DIR,
1238		},
1239		{},
1240	};
1241	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1242
1243	ASSERT_LE(0, ruleset_fd);
1244	enforce_ruleset(_metadata, ruleset_fd);
1245
1246	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1247	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1248
1249	/* Write access is forbidden. */
1250	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1251	/* Readdir access is allowed. */
1252	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1253
1254	/* Write access is forbidden. */
1255	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1256	/* Readdir access is allowed. */
1257	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1258
1259	/*
1260	 * Tests shared rule extension: the following rules should not grant
1261	 * any new access, only remove some.  Once enforced, these rules are
1262	 * ANDed with the previous ones.
1263	 */
1264	add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
1265			 dir_s1d2);
1266	/*
1267	 * According to ruleset_fd, dir_s1d2 should now have the
1268	 * LANDLOCK_ACCESS_FS_READ_FILE and LANDLOCK_ACCESS_FS_WRITE_FILE
1269	 * access rights (even if this directory is opened a second time).
1270	 * However, when enforcing this updated ruleset, the ruleset tied to
1271	 * the current process (i.e. its domain) will still only have the
1272	 * dir_s1d2 with LANDLOCK_ACCESS_FS_READ_FILE and
1273	 * LANDLOCK_ACCESS_FS_READ_DIR accesses, but
1274	 * LANDLOCK_ACCESS_FS_WRITE_FILE must not be allowed because it would
1275	 * be a privilege escalation.
1276	 */
1277	enforce_ruleset(_metadata, ruleset_fd);
1278
1279	/* Same tests and results as above. */
1280	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1281	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1282
1283	/* It is still forbidden to write in file1_s1d2. */
1284	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1285	/* Readdir access is still allowed. */
1286	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1287
1288	/* It is still forbidden to write in file1_s1d3. */
1289	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1290	/* Readdir access is still allowed. */
1291	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1292
1293	/*
1294	 * Try to get more privileges by adding new access rights to the parent
1295	 * directory: dir_s1d1.
1296	 */
1297	add_path_beneath(_metadata, ruleset_fd, ACCESS_RW, dir_s1d1);
1298	enforce_ruleset(_metadata, ruleset_fd);
1299
1300	/* Same tests and results as above. */
1301	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1302	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1303
1304	/* It is still forbidden to write in file1_s1d2. */
1305	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1306	/* Readdir access is still allowed. */
1307	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1308
1309	/* It is still forbidden to write in file1_s1d3. */
1310	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1311	/* Readdir access is still allowed. */
1312	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1313
1314	/*
1315	 * Now, dir_s1d3 get a new rule tied to it, only allowing
1316	 * LANDLOCK_ACCESS_FS_WRITE_FILE.  The (kernel internal) difference is
1317	 * that there was no rule tied to it before.
1318	 */
1319	add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
1320			 dir_s1d3);
1321	enforce_ruleset(_metadata, ruleset_fd);
1322	ASSERT_EQ(0, close(ruleset_fd));
1323
1324	/*
1325	 * Same tests and results as above, except for open(dir_s1d3) which is
1326	 * now denied because the new rule mask the rule previously inherited
1327	 * from dir_s1d2.
1328	 */
1329
1330	/* Same tests and results as above. */
1331	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1332	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1333
1334	/* It is still forbidden to write in file1_s1d2. */
1335	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1336	/* Readdir access is still allowed. */
1337	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1338
1339	/* It is still forbidden to write in file1_s1d3. */
1340	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1341	/*
1342	 * Readdir of dir_s1d3 is still allowed because of the OR policy inside
1343	 * the same layer.
1344	 */
1345	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1346}
1347
1348TEST_F_FORK(layout1, inherit_superset)
1349{
1350	const struct rule rules[] = {
1351		{
1352			.path = dir_s1d3,
1353			.access = ACCESS_RO,
1354		},
1355		{},
1356	};
1357	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1358
1359	ASSERT_LE(0, ruleset_fd);
1360	enforce_ruleset(_metadata, ruleset_fd);
1361
1362	/* Readdir access is denied for dir_s1d2. */
1363	ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1364	/* Readdir access is allowed for dir_s1d3. */
1365	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1366	/* File access is allowed for file1_s1d3. */
1367	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1368
1369	/* Now dir_s1d2, parent of dir_s1d3, gets a new rule tied to it. */
1370	add_path_beneath(_metadata, ruleset_fd,
1371			 LANDLOCK_ACCESS_FS_READ_FILE |
1372				 LANDLOCK_ACCESS_FS_READ_DIR,
1373			 dir_s1d2);
1374	enforce_ruleset(_metadata, ruleset_fd);
1375	ASSERT_EQ(0, close(ruleset_fd));
1376
1377	/* Readdir access is still denied for dir_s1d2. */
1378	ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1379	/* Readdir access is still allowed for dir_s1d3. */
1380	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1381	/* File access is still allowed for file1_s1d3. */
1382	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1383}
1384
1385TEST_F_FORK(layout0, max_layers)
1386{
1387	int i, err;
1388	const struct rule rules[] = {
1389		{
1390			.path = TMP_DIR,
1391			.access = ACCESS_RO,
1392		},
1393		{},
1394	};
1395	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1396
1397	ASSERT_LE(0, ruleset_fd);
1398	for (i = 0; i < 16; i++)
1399		enforce_ruleset(_metadata, ruleset_fd);
1400
1401	for (i = 0; i < 2; i++) {
1402		err = landlock_restrict_self(ruleset_fd, 0);
1403		ASSERT_EQ(-1, err);
1404		ASSERT_EQ(E2BIG, errno);
1405	}
1406	ASSERT_EQ(0, close(ruleset_fd));
1407}
1408
1409TEST_F_FORK(layout1, empty_or_same_ruleset)
1410{
1411	struct landlock_ruleset_attr ruleset_attr = {};
1412	int ruleset_fd;
1413
1414	/* Tests empty handled_access_fs. */
1415	ruleset_fd =
1416		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
1417	ASSERT_LE(-1, ruleset_fd);
1418	ASSERT_EQ(ENOMSG, errno);
1419
1420	/* Enforces policy which deny read access to all files. */
1421	ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE;
1422	ruleset_fd =
1423		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
1424	ASSERT_LE(0, ruleset_fd);
1425	enforce_ruleset(_metadata, ruleset_fd);
1426	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1427	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1428
1429	/* Nests a policy which deny read access to all directories. */
1430	ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR;
1431	ruleset_fd =
1432		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
1433	ASSERT_LE(0, ruleset_fd);
1434	enforce_ruleset(_metadata, ruleset_fd);
1435	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1436	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1437
1438	/* Enforces a second time with the same ruleset. */
1439	enforce_ruleset(_metadata, ruleset_fd);
1440	ASSERT_EQ(0, close(ruleset_fd));
1441}
1442
1443TEST_F_FORK(layout1, rule_on_mountpoint)
1444{
1445	const struct rule rules[] = {
1446		{
1447			.path = dir_s1d1,
1448			.access = ACCESS_RO,
1449		},
1450		{
1451			/* dir_s3d2 is a mount point. */
1452			.path = dir_s3d2,
1453			.access = ACCESS_RO,
1454		},
1455		{},
1456	};
1457	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1458
1459	ASSERT_LE(0, ruleset_fd);
1460	enforce_ruleset(_metadata, ruleset_fd);
1461	ASSERT_EQ(0, close(ruleset_fd));
1462
1463	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1464
1465	ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
1466
1467	ASSERT_EQ(EACCES, test_open(dir_s3d1, O_RDONLY));
1468	ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
1469	ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
1470}
1471
1472TEST_F_FORK(layout1, rule_over_mountpoint)
1473{
1474	const struct rule rules[] = {
1475		{
1476			.path = dir_s1d1,
1477			.access = ACCESS_RO,
1478		},
1479		{
1480			/* dir_s3d2 is a mount point. */
1481			.path = dir_s3d1,
1482			.access = ACCESS_RO,
1483		},
1484		{},
1485	};
1486	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1487
1488	ASSERT_LE(0, ruleset_fd);
1489	enforce_ruleset(_metadata, ruleset_fd);
1490	ASSERT_EQ(0, close(ruleset_fd));
1491
1492	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1493
1494	ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
1495
1496	ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
1497	ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
1498	ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
1499}
1500
1501/*
1502 * This test verifies that we can apply a landlock rule on the root directory
1503 * (which might require special handling).
1504 */
1505TEST_F_FORK(layout1, rule_over_root_allow_then_deny)
1506{
1507	struct rule rules[] = {
1508		{
1509			.path = "/",
1510			.access = ACCESS_RO,
1511		},
1512		{},
1513	};
1514	int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1515
1516	ASSERT_LE(0, ruleset_fd);
1517	enforce_ruleset(_metadata, ruleset_fd);
1518	ASSERT_EQ(0, close(ruleset_fd));
1519
1520	/* Checks allowed access. */
1521	ASSERT_EQ(0, test_open("/", O_RDONLY));
1522	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1523
1524	rules[0].access = LANDLOCK_ACCESS_FS_READ_FILE;
1525	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1526	ASSERT_LE(0, ruleset_fd);
1527	enforce_ruleset(_metadata, ruleset_fd);
1528	ASSERT_EQ(0, close(ruleset_fd));
1529
1530	/* Checks denied access (on a directory). */
1531	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1532	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1533}
1534
1535TEST_F_FORK(layout1, rule_over_root_deny)
1536{
1537	const struct rule rules[] = {
1538		{
1539			.path = "/",
1540			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1541		},
1542		{},
1543	};
1544	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1545
1546	ASSERT_LE(0, ruleset_fd);
1547	enforce_ruleset(_metadata, ruleset_fd);
1548	ASSERT_EQ(0, close(ruleset_fd));
1549
1550	/* Checks denied access (on a directory). */
1551	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1552	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1553}
1554
1555TEST_F_FORK(layout1, rule_inside_mount_ns)
1556{
1557	const struct rule rules[] = {
1558		{
1559			.path = "s3d3",
1560			.access = ACCESS_RO,
1561		},
1562		{},
1563	};
1564	int ruleset_fd;
1565
1566	set_cap(_metadata, CAP_SYS_ADMIN);
1567	ASSERT_EQ(0, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3))
1568	{
1569		TH_LOG("Failed to pivot root: %s", strerror(errno));
1570	};
1571	ASSERT_EQ(0, chdir("/"));
1572	clear_cap(_metadata, CAP_SYS_ADMIN);
1573
1574	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1575	ASSERT_LE(0, ruleset_fd);
1576	enforce_ruleset(_metadata, ruleset_fd);
1577	ASSERT_EQ(0, close(ruleset_fd));
1578
1579	ASSERT_EQ(0, test_open("s3d3", O_RDONLY));
1580	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1581}
1582
1583TEST_F_FORK(layout1, mount_and_pivot)
1584{
1585	const struct rule rules[] = {
1586		{
1587			.path = dir_s3d2,
1588			.access = ACCESS_RO,
1589		},
1590		{},
1591	};
1592	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1593
1594	ASSERT_LE(0, ruleset_fd);
1595	enforce_ruleset(_metadata, ruleset_fd);
1596	ASSERT_EQ(0, close(ruleset_fd));
1597
1598	set_cap(_metadata, CAP_SYS_ADMIN);
1599	ASSERT_EQ(-1, mount(NULL, dir_s3d2, NULL, MS_RDONLY, NULL));
1600	ASSERT_EQ(EPERM, errno);
1601	ASSERT_EQ(-1, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3));
1602	ASSERT_EQ(EPERM, errno);
1603	clear_cap(_metadata, CAP_SYS_ADMIN);
1604}
1605
1606TEST_F_FORK(layout1, move_mount)
1607{
1608	const struct rule rules[] = {
1609		{
1610			.path = dir_s3d2,
1611			.access = ACCESS_RO,
1612		},
1613		{},
1614	};
1615	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1616
1617	ASSERT_LE(0, ruleset_fd);
1618
1619	set_cap(_metadata, CAP_SYS_ADMIN);
1620	ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1621			     dir_s1d2, 0))
1622	{
1623		TH_LOG("Failed to move mount: %s", strerror(errno));
1624	}
1625
1626	ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD,
1627			     dir_s3d2, 0));
1628	clear_cap(_metadata, CAP_SYS_ADMIN);
1629
1630	enforce_ruleset(_metadata, ruleset_fd);
1631	ASSERT_EQ(0, close(ruleset_fd));
1632
1633	set_cap(_metadata, CAP_SYS_ADMIN);
1634	ASSERT_EQ(-1, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1635			      dir_s1d2, 0));
1636	ASSERT_EQ(EPERM, errno);
1637	clear_cap(_metadata, CAP_SYS_ADMIN);
1638}
1639
1640TEST_F_FORK(layout1, release_inodes)
1641{
1642	const struct rule rules[] = {
1643		{
1644			.path = dir_s1d1,
1645			.access = ACCESS_RO,
1646		},
1647		{
1648			.path = dir_s3d2,
1649			.access = ACCESS_RO,
1650		},
1651		{
1652			.path = dir_s3d3,
1653			.access = ACCESS_RO,
1654		},
1655		{},
1656	};
1657	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1658
1659	ASSERT_LE(0, ruleset_fd);
1660	/* Unmount a file hierarchy while it is being used by a ruleset. */
1661	set_cap(_metadata, CAP_SYS_ADMIN);
1662	ASSERT_EQ(0, umount(dir_s3d2));
1663	clear_cap(_metadata, CAP_SYS_ADMIN);
1664
1665	enforce_ruleset(_metadata, ruleset_fd);
1666	ASSERT_EQ(0, close(ruleset_fd));
1667
1668	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
1669	ASSERT_EQ(EACCES, test_open(dir_s3d2, O_RDONLY));
1670	/* This dir_s3d3 would not be allowed and does not exist anyway. */
1671	ASSERT_EQ(ENOENT, test_open(dir_s3d3, O_RDONLY));
1672}
1673
1674enum relative_access {
1675	REL_OPEN,
1676	REL_CHDIR,
1677	REL_CHROOT_ONLY,
1678	REL_CHROOT_CHDIR,
1679};
1680
1681static void test_relative_path(struct __test_metadata *const _metadata,
1682			       const enum relative_access rel)
1683{
1684	/*
1685	 * Common layer to check that chroot doesn't ignore it (i.e. a chroot
1686	 * is not a disconnected root directory).
1687	 */
1688	const struct rule layer1_base[] = {
1689		{
1690			.path = TMP_DIR,
1691			.access = ACCESS_RO,
1692		},
1693		{},
1694	};
1695	const struct rule layer2_subs[] = {
1696		{
1697			.path = dir_s1d2,
1698			.access = ACCESS_RO,
1699		},
1700		{
1701			.path = dir_s2d2,
1702			.access = ACCESS_RO,
1703		},
1704		{},
1705	};
1706	int dirfd, ruleset_fd;
1707
1708	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_base);
1709	ASSERT_LE(0, ruleset_fd);
1710	enforce_ruleset(_metadata, ruleset_fd);
1711	ASSERT_EQ(0, close(ruleset_fd));
1712
1713	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_subs);
1714
1715	ASSERT_LE(0, ruleset_fd);
1716	switch (rel) {
1717	case REL_OPEN:
1718	case REL_CHDIR:
1719		break;
1720	case REL_CHROOT_ONLY:
1721		ASSERT_EQ(0, chdir(dir_s2d2));
1722		break;
1723	case REL_CHROOT_CHDIR:
1724		ASSERT_EQ(0, chdir(dir_s1d2));
1725		break;
1726	default:
1727		ASSERT_TRUE(false);
1728		return;
1729	}
1730
1731	set_cap(_metadata, CAP_SYS_CHROOT);
1732	enforce_ruleset(_metadata, ruleset_fd);
1733
1734	switch (rel) {
1735	case REL_OPEN:
1736		dirfd = open(dir_s1d2, O_DIRECTORY);
1737		ASSERT_LE(0, dirfd);
1738		break;
1739	case REL_CHDIR:
1740		ASSERT_EQ(0, chdir(dir_s1d2));
1741		dirfd = AT_FDCWD;
1742		break;
1743	case REL_CHROOT_ONLY:
1744		/* Do chroot into dir_s1d2 (relative to dir_s2d2). */
1745		ASSERT_EQ(0, chroot("../../s1d1/s1d2"))
1746		{
1747			TH_LOG("Failed to chroot: %s", strerror(errno));
1748		}
1749		dirfd = AT_FDCWD;
1750		break;
1751	case REL_CHROOT_CHDIR:
1752		/* Do chroot into dir_s1d2. */
1753		ASSERT_EQ(0, chroot("."))
1754		{
1755			TH_LOG("Failed to chroot: %s", strerror(errno));
1756		}
1757		dirfd = AT_FDCWD;
1758		break;
1759	}
1760
1761	ASSERT_EQ((rel == REL_CHROOT_CHDIR) ? 0 : EACCES,
1762		  test_open_rel(dirfd, "..", O_RDONLY));
1763	ASSERT_EQ(0, test_open_rel(dirfd, ".", O_RDONLY));
1764
1765	if (rel == REL_CHROOT_ONLY) {
1766		/* The current directory is dir_s2d2. */
1767		ASSERT_EQ(0, test_open_rel(dirfd, "./s2d3", O_RDONLY));
1768	} else {
1769		/* The current directory is dir_s1d2. */
1770		ASSERT_EQ(0, test_open_rel(dirfd, "./s1d3", O_RDONLY));
1771	}
1772
1773	if (rel == REL_CHROOT_ONLY || rel == REL_CHROOT_CHDIR) {
1774		/* Checks the root dir_s1d2. */
1775		ASSERT_EQ(0, test_open_rel(dirfd, "/..", O_RDONLY));
1776		ASSERT_EQ(0, test_open_rel(dirfd, "/", O_RDONLY));
1777		ASSERT_EQ(0, test_open_rel(dirfd, "/f1", O_RDONLY));
1778		ASSERT_EQ(0, test_open_rel(dirfd, "/s1d3", O_RDONLY));
1779	}
1780
1781	if (rel != REL_CHROOT_CHDIR) {
1782		ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s1d1", O_RDONLY));
1783		ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2", O_RDONLY));
1784		ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2/s1d3",
1785					   O_RDONLY));
1786
1787		ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s2d1", O_RDONLY));
1788		ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2", O_RDONLY));
1789		ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2/s2d3",
1790					   O_RDONLY));
1791	}
1792
1793	if (rel == REL_OPEN)
1794		ASSERT_EQ(0, close(dirfd));
1795	ASSERT_EQ(0, close(ruleset_fd));
1796}
1797
1798TEST_F_FORK(layout1, relative_open)
1799{
1800	test_relative_path(_metadata, REL_OPEN);
1801}
1802
1803TEST_F_FORK(layout1, relative_chdir)
1804{
1805	test_relative_path(_metadata, REL_CHDIR);
1806}
1807
1808TEST_F_FORK(layout1, relative_chroot_only)
1809{
1810	test_relative_path(_metadata, REL_CHROOT_ONLY);
1811}
1812
1813TEST_F_FORK(layout1, relative_chroot_chdir)
1814{
1815	test_relative_path(_metadata, REL_CHROOT_CHDIR);
1816}
1817
1818static void copy_binary(struct __test_metadata *const _metadata,
1819			const char *const dst_path)
1820{
1821	int dst_fd, src_fd;
1822	struct stat statbuf;
1823
1824	dst_fd = open(dst_path, O_WRONLY | O_TRUNC | O_CLOEXEC);
1825	ASSERT_LE(0, dst_fd)
1826	{
1827		TH_LOG("Failed to open \"%s\": %s", dst_path, strerror(errno));
1828	}
1829	src_fd = open(BINARY_PATH, O_RDONLY | O_CLOEXEC);
1830	ASSERT_LE(0, src_fd)
1831	{
1832		TH_LOG("Failed to open \"" BINARY_PATH "\": %s",
1833		       strerror(errno));
1834	}
1835	ASSERT_EQ(0, fstat(src_fd, &statbuf));
1836	ASSERT_EQ(statbuf.st_size,
1837		  sendfile(dst_fd, src_fd, 0, statbuf.st_size));
1838	ASSERT_EQ(0, close(src_fd));
1839	ASSERT_EQ(0, close(dst_fd));
1840}
1841
1842static void test_execute(struct __test_metadata *const _metadata, const int err,
1843			 const char *const path)
1844{
1845	int status;
1846	char *const argv[] = { (char *)path, NULL };
1847	const pid_t child = fork();
1848
1849	ASSERT_LE(0, child);
1850	if (child == 0) {
1851		ASSERT_EQ(err ? -1 : 0, execve(path, argv, NULL))
1852		{
1853			TH_LOG("Failed to execute \"%s\": %s", path,
1854			       strerror(errno));
1855		};
1856		ASSERT_EQ(err, errno);
1857		_exit(_metadata->passed ? 2 : 1);
1858		return;
1859	}
1860	ASSERT_EQ(child, waitpid(child, &status, 0));
1861	ASSERT_EQ(1, WIFEXITED(status));
1862	ASSERT_EQ(err ? 2 : 0, WEXITSTATUS(status))
1863	{
1864		TH_LOG("Unexpected return code for \"%s\": %s", path,
1865		       strerror(errno));
1866	};
1867}
1868
1869TEST_F_FORK(layout1, execute)
1870{
1871	const struct rule rules[] = {
1872		{
1873			.path = dir_s1d2,
1874			.access = LANDLOCK_ACCESS_FS_EXECUTE,
1875		},
1876		{},
1877	};
1878	const int ruleset_fd =
1879		create_ruleset(_metadata, rules[0].access, rules);
1880
1881	ASSERT_LE(0, ruleset_fd);
1882	copy_binary(_metadata, file1_s1d1);
1883	copy_binary(_metadata, file1_s1d2);
1884	copy_binary(_metadata, file1_s1d3);
1885
1886	enforce_ruleset(_metadata, ruleset_fd);
1887	ASSERT_EQ(0, close(ruleset_fd));
1888
1889	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1890	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
1891	test_execute(_metadata, EACCES, file1_s1d1);
1892
1893	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
1894	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
1895	test_execute(_metadata, 0, file1_s1d2);
1896
1897	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
1898	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1899	test_execute(_metadata, 0, file1_s1d3);
1900}
1901
1902TEST_F_FORK(layout1, link)
1903{
1904	const struct rule layer1[] = {
1905		{
1906			.path = dir_s1d2,
1907			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
1908		},
1909		{},
1910	};
1911	const struct rule layer2[] = {
1912		{
1913			.path = dir_s1d3,
1914			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1915		},
1916		{},
1917	};
1918	int ruleset_fd = create_ruleset(_metadata, layer1[0].access, layer1);
1919
1920	ASSERT_LE(0, ruleset_fd);
1921
1922	ASSERT_EQ(0, unlink(file1_s1d1));
1923	ASSERT_EQ(0, unlink(file1_s1d2));
1924	ASSERT_EQ(0, unlink(file1_s1d3));
1925
1926	enforce_ruleset(_metadata, ruleset_fd);
1927	ASSERT_EQ(0, close(ruleset_fd));
1928
1929	ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
1930	ASSERT_EQ(EACCES, errno);
1931
1932	/* Denies linking because of reparenting. */
1933	ASSERT_EQ(-1, link(file1_s2d1, file1_s1d2));
1934	ASSERT_EQ(EXDEV, errno);
1935	ASSERT_EQ(-1, link(file2_s1d2, file1_s1d3));
1936	ASSERT_EQ(EXDEV, errno);
1937	ASSERT_EQ(-1, link(file2_s1d3, file1_s1d2));
1938	ASSERT_EQ(EXDEV, errno);
1939
1940	ASSERT_EQ(0, link(file2_s1d2, file1_s1d2));
1941	ASSERT_EQ(0, link(file2_s1d3, file1_s1d3));
1942
1943	/* Prepares for next unlinks. */
1944	ASSERT_EQ(0, unlink(file2_s1d2));
1945	ASSERT_EQ(0, unlink(file2_s1d3));
1946
1947	ruleset_fd = create_ruleset(_metadata, layer2[0].access, layer2);
1948	ASSERT_LE(0, ruleset_fd);
1949	enforce_ruleset(_metadata, ruleset_fd);
1950	ASSERT_EQ(0, close(ruleset_fd));
1951
1952	/* Checks that linkind doesn't require the ability to delete a file. */
1953	ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
1954	ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
1955}
1956
1957static int test_rename(const char *const oldpath, const char *const newpath)
1958{
1959	if (rename(oldpath, newpath))
1960		return errno;
1961	return 0;
1962}
1963
1964static int test_exchange(const char *const oldpath, const char *const newpath)
1965{
1966	if (renameat2(AT_FDCWD, oldpath, AT_FDCWD, newpath, RENAME_EXCHANGE))
1967		return errno;
1968	return 0;
1969}
1970
1971TEST_F_FORK(layout1, rename_file)
1972{
1973	const struct rule rules[] = {
1974		{
1975			.path = dir_s1d3,
1976			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1977		},
1978		{
1979			.path = dir_s2d2,
1980			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1981		},
1982		{},
1983	};
1984	const int ruleset_fd =
1985		create_ruleset(_metadata, rules[0].access, rules);
1986
1987	ASSERT_LE(0, ruleset_fd);
1988
1989	ASSERT_EQ(0, unlink(file1_s1d2));
1990
1991	enforce_ruleset(_metadata, ruleset_fd);
1992	ASSERT_EQ(0, close(ruleset_fd));
1993
1994	/*
1995	 * Tries to replace a file, from a directory that allows file removal,
1996	 * but to a different directory (which also allows file removal).
1997	 */
1998	ASSERT_EQ(-1, rename(file1_s2d3, file1_s1d3));
1999	ASSERT_EQ(EXDEV, errno);
2000	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d3,
2001				RENAME_EXCHANGE));
2002	ASSERT_EQ(EXDEV, errno);
2003	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, dir_s1d3,
2004				RENAME_EXCHANGE));
2005	ASSERT_EQ(EXDEV, errno);
2006
2007	/*
2008	 * Tries to replace a file, from a directory that denies file removal,
2009	 * to a different directory (which allows file removal).
2010	 */
2011	ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
2012	ASSERT_EQ(EACCES, errno);
2013	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file1_s1d3,
2014				RENAME_EXCHANGE));
2015	ASSERT_EQ(EACCES, errno);
2016	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s1d3,
2017				RENAME_EXCHANGE));
2018	ASSERT_EQ(EXDEV, errno);
2019
2020	/* Exchanges files and directories that partially allow removal. */
2021	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s2d1,
2022				RENAME_EXCHANGE));
2023	ASSERT_EQ(EACCES, errno);
2024	/* Checks that file1_s2d1 cannot be removed (instead of ENOTDIR). */
2025	ASSERT_EQ(-1, rename(dir_s2d2, file1_s2d1));
2026	ASSERT_EQ(EACCES, errno);
2027	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, dir_s2d2,
2028				RENAME_EXCHANGE));
2029	ASSERT_EQ(EACCES, errno);
2030	/* Checks that file1_s1d1 cannot be removed (instead of EISDIR). */
2031	ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
2032	ASSERT_EQ(EACCES, errno);
2033
2034	/* Renames files with different parents. */
2035	ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d2));
2036	ASSERT_EQ(EXDEV, errno);
2037	ASSERT_EQ(0, unlink(file1_s1d3));
2038	ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
2039	ASSERT_EQ(EACCES, errno);
2040
2041	/* Exchanges and renames files with same parent. */
2042	ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s2d3,
2043			       RENAME_EXCHANGE));
2044	ASSERT_EQ(0, rename(file2_s2d3, file1_s2d3));
2045
2046	/* Exchanges files and directories with same parent, twice. */
2047	ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
2048			       RENAME_EXCHANGE));
2049	ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
2050			       RENAME_EXCHANGE));
2051}
2052
2053TEST_F_FORK(layout1, rename_dir)
2054{
2055	const struct rule rules[] = {
2056		{
2057			.path = dir_s1d2,
2058			.access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
2059		},
2060		{
2061			.path = dir_s2d1,
2062			.access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
2063		},
2064		{},
2065	};
2066	const int ruleset_fd =
2067		create_ruleset(_metadata, rules[0].access, rules);
2068
2069	ASSERT_LE(0, ruleset_fd);
2070
2071	/* Empties dir_s1d3 to allow renaming. */
2072	ASSERT_EQ(0, unlink(file1_s1d3));
2073	ASSERT_EQ(0, unlink(file2_s1d3));
2074
2075	enforce_ruleset(_metadata, ruleset_fd);
2076	ASSERT_EQ(0, close(ruleset_fd));
2077
2078	/* Exchanges and renames directory to a different parent. */
2079	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
2080				RENAME_EXCHANGE));
2081	ASSERT_EQ(EXDEV, errno);
2082	ASSERT_EQ(-1, rename(dir_s2d3, dir_s1d3));
2083	ASSERT_EQ(EXDEV, errno);
2084	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
2085				RENAME_EXCHANGE));
2086	ASSERT_EQ(EXDEV, errno);
2087
2088	/*
2089	 * Exchanges directory to the same parent, which doesn't allow
2090	 * directory removal.
2091	 */
2092	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d1, AT_FDCWD, dir_s2d1,
2093				RENAME_EXCHANGE));
2094	ASSERT_EQ(EACCES, errno);
2095	/* Checks that dir_s1d2 cannot be removed (instead of ENOTDIR). */
2096	ASSERT_EQ(-1, rename(dir_s1d2, file1_s1d1));
2097	ASSERT_EQ(EACCES, errno);
2098	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s1d2,
2099				RENAME_EXCHANGE));
2100	ASSERT_EQ(EACCES, errno);
2101	/* Checks that dir_s1d2 cannot be removed (instead of EISDIR). */
2102	ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
2103	ASSERT_EQ(EACCES, errno);
2104
2105	/*
2106	 * Exchanges and renames directory to the same parent, which allows
2107	 * directory removal.
2108	 */
2109	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, file1_s1d2,
2110			       RENAME_EXCHANGE));
2111	ASSERT_EQ(0, unlink(dir_s1d3));
2112	ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
2113	ASSERT_EQ(0, rename(file1_s1d2, dir_s1d3));
2114	ASSERT_EQ(0, rmdir(dir_s1d3));
2115}
2116
2117TEST_F_FORK(layout1, reparent_refer)
2118{
2119	const struct rule layer1[] = {
2120		{
2121			.path = dir_s1d2,
2122			.access = LANDLOCK_ACCESS_FS_REFER,
2123		},
2124		{
2125			.path = dir_s2d2,
2126			.access = LANDLOCK_ACCESS_FS_REFER,
2127		},
2128		{},
2129	};
2130	int ruleset_fd =
2131		create_ruleset(_metadata, LANDLOCK_ACCESS_FS_REFER, layer1);
2132
2133	ASSERT_LE(0, ruleset_fd);
2134	enforce_ruleset(_metadata, ruleset_fd);
2135	ASSERT_EQ(0, close(ruleset_fd));
2136
2137	ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d1));
2138	ASSERT_EQ(EXDEV, errno);
2139	ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d2));
2140	ASSERT_EQ(EXDEV, errno);
2141	ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d3));
2142	ASSERT_EQ(EXDEV, errno);
2143
2144	ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d1));
2145	ASSERT_EQ(EXDEV, errno);
2146	ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d2));
2147	ASSERT_EQ(EXDEV, errno);
2148	/*
2149	 * Moving should only be allowed when the source and the destination
2150	 * parent directory have REFER.
2151	 */
2152	ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d3));
2153	ASSERT_EQ(ENOTEMPTY, errno);
2154	ASSERT_EQ(0, unlink(file1_s2d3));
2155	ASSERT_EQ(0, unlink(file2_s2d3));
2156	ASSERT_EQ(0, rename(dir_s1d3, dir_s2d3));
2157}
2158
2159/* Checks renames beneath dir_s1d1. */
2160static void refer_denied_by_default(struct __test_metadata *const _metadata,
2161				    const struct rule layer1[],
2162				    const int layer1_err,
2163				    const struct rule layer2[])
2164{
2165	int ruleset_fd;
2166
2167	ASSERT_EQ(0, unlink(file1_s1d2));
2168
2169	ruleset_fd = create_ruleset(_metadata, layer1[0].access, layer1);
2170	ASSERT_LE(0, ruleset_fd);
2171	enforce_ruleset(_metadata, ruleset_fd);
2172	ASSERT_EQ(0, close(ruleset_fd));
2173
2174	/*
2175	 * If the first layer handles LANDLOCK_ACCESS_FS_REFER (according to
2176	 * layer1_err), then it allows some different-parent renames and links.
2177	 */
2178	ASSERT_EQ(layer1_err, test_rename(file1_s1d1, file1_s1d2));
2179	if (layer1_err == 0)
2180		ASSERT_EQ(layer1_err, test_rename(file1_s1d2, file1_s1d1));
2181	ASSERT_EQ(layer1_err, test_exchange(file2_s1d1, file2_s1d2));
2182	ASSERT_EQ(layer1_err, test_exchange(file2_s1d2, file2_s1d1));
2183
2184	ruleset_fd = create_ruleset(_metadata, layer2[0].access, layer2);
2185	ASSERT_LE(0, ruleset_fd);
2186	enforce_ruleset(_metadata, ruleset_fd);
2187	ASSERT_EQ(0, close(ruleset_fd));
2188
2189	/*
2190	 * Now, either the first or the second layer does not handle
2191	 * LANDLOCK_ACCESS_FS_REFER, which means that any different-parent
2192	 * renames and links are denied, thus making the layer handling
2193	 * LANDLOCK_ACCESS_FS_REFER null and void.
2194	 */
2195	ASSERT_EQ(EXDEV, test_rename(file1_s1d1, file1_s1d2));
2196	ASSERT_EQ(EXDEV, test_exchange(file2_s1d1, file2_s1d2));
2197	ASSERT_EQ(EXDEV, test_exchange(file2_s1d2, file2_s1d1));
2198}
2199
2200const struct rule layer_dir_s1d1_refer[] = {
2201	{
2202		.path = dir_s1d1,
2203		.access = LANDLOCK_ACCESS_FS_REFER,
2204	},
2205	{},
2206};
2207
2208const struct rule layer_dir_s1d1_execute[] = {
2209	{
2210		/* Matches a parent directory. */
2211		.path = dir_s1d1,
2212		.access = LANDLOCK_ACCESS_FS_EXECUTE,
2213	},
2214	{},
2215};
2216
2217const struct rule layer_dir_s2d1_execute[] = {
2218	{
2219		/* Does not match a parent directory. */
2220		.path = dir_s2d1,
2221		.access = LANDLOCK_ACCESS_FS_EXECUTE,
2222	},
2223	{},
2224};
2225
2226/*
2227 * Tests precedence over renames: denied by default for different parent
2228 * directories, *with* a rule matching a parent directory, but not directly
2229 * denying access (with MAKE_REG nor REMOVE).
2230 */
2231TEST_F_FORK(layout1, refer_denied_by_default1)
2232{
2233	refer_denied_by_default(_metadata, layer_dir_s1d1_refer, 0,
2234				layer_dir_s1d1_execute);
2235}
2236
2237/*
2238 * Same test but this time turning around the ABI version order: the first
2239 * layer does not handle LANDLOCK_ACCESS_FS_REFER.
2240 */
2241TEST_F_FORK(layout1, refer_denied_by_default2)
2242{
2243	refer_denied_by_default(_metadata, layer_dir_s1d1_execute, EXDEV,
2244				layer_dir_s1d1_refer);
2245}
2246
2247/*
2248 * Tests precedence over renames: denied by default for different parent
2249 * directories, *without* a rule matching a parent directory, but not directly
2250 * denying access (with MAKE_REG nor REMOVE).
2251 */
2252TEST_F_FORK(layout1, refer_denied_by_default3)
2253{
2254	refer_denied_by_default(_metadata, layer_dir_s1d1_refer, 0,
2255				layer_dir_s2d1_execute);
2256}
2257
2258/*
2259 * Same test but this time turning around the ABI version order: the first
2260 * layer does not handle LANDLOCK_ACCESS_FS_REFER.
2261 */
2262TEST_F_FORK(layout1, refer_denied_by_default4)
2263{
2264	refer_denied_by_default(_metadata, layer_dir_s2d1_execute, EXDEV,
2265				layer_dir_s1d1_refer);
2266}
2267
2268TEST_F_FORK(layout1, reparent_link)
2269{
2270	const struct rule layer1[] = {
2271		{
2272			.path = dir_s1d2,
2273			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2274		},
2275		{
2276			.path = dir_s1d3,
2277			.access = LANDLOCK_ACCESS_FS_REFER,
2278		},
2279		{
2280			.path = dir_s2d2,
2281			.access = LANDLOCK_ACCESS_FS_REFER,
2282		},
2283		{
2284			.path = dir_s2d3,
2285			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2286		},
2287		{},
2288	};
2289	const int ruleset_fd = create_ruleset(
2290		_metadata,
2291		LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER, layer1);
2292
2293	ASSERT_LE(0, ruleset_fd);
2294	enforce_ruleset(_metadata, ruleset_fd);
2295	ASSERT_EQ(0, close(ruleset_fd));
2296
2297	ASSERT_EQ(0, unlink(file1_s1d1));
2298	ASSERT_EQ(0, unlink(file1_s1d2));
2299	ASSERT_EQ(0, unlink(file1_s1d3));
2300
2301	/* Denies linking because of missing MAKE_REG. */
2302	ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
2303	ASSERT_EQ(EACCES, errno);
2304	/* Denies linking because of missing source and destination REFER. */
2305	ASSERT_EQ(-1, link(file1_s2d1, file1_s1d2));
2306	ASSERT_EQ(EXDEV, errno);
2307	/* Denies linking because of missing source REFER. */
2308	ASSERT_EQ(-1, link(file1_s2d1, file1_s1d3));
2309	ASSERT_EQ(EXDEV, errno);
2310
2311	/* Denies linking because of missing MAKE_REG. */
2312	ASSERT_EQ(-1, link(file1_s2d2, file1_s1d1));
2313	ASSERT_EQ(EACCES, errno);
2314	/* Denies linking because of missing destination REFER. */
2315	ASSERT_EQ(-1, link(file1_s2d2, file1_s1d2));
2316	ASSERT_EQ(EXDEV, errno);
2317
2318	/* Allows linking because of REFER and MAKE_REG. */
2319	ASSERT_EQ(0, link(file1_s2d2, file1_s1d3));
2320	ASSERT_EQ(0, unlink(file1_s2d2));
2321	/* Reverse linking denied because of missing MAKE_REG. */
2322	ASSERT_EQ(-1, link(file1_s1d3, file1_s2d2));
2323	ASSERT_EQ(EACCES, errno);
2324	ASSERT_EQ(0, unlink(file1_s2d3));
2325	/* Checks reverse linking. */
2326	ASSERT_EQ(0, link(file1_s1d3, file1_s2d3));
2327	ASSERT_EQ(0, unlink(file1_s1d3));
2328
2329	/*
2330	 * This is OK for a file link, but it should not be allowed for a
2331	 * directory rename (because of the superset of access rights.
2332	 */
2333	ASSERT_EQ(0, link(file1_s2d3, file1_s1d3));
2334	ASSERT_EQ(0, unlink(file1_s1d3));
2335
2336	ASSERT_EQ(-1, link(file2_s1d2, file1_s1d3));
2337	ASSERT_EQ(EXDEV, errno);
2338	ASSERT_EQ(-1, link(file2_s1d3, file1_s1d2));
2339	ASSERT_EQ(EXDEV, errno);
2340
2341	ASSERT_EQ(0, link(file2_s1d2, file1_s1d2));
2342	ASSERT_EQ(0, link(file2_s1d3, file1_s1d3));
2343}
2344
2345TEST_F_FORK(layout1, reparent_rename)
2346{
2347	/* Same rules as for reparent_link. */
2348	const struct rule layer1[] = {
2349		{
2350			.path = dir_s1d2,
2351			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2352		},
2353		{
2354			.path = dir_s1d3,
2355			.access = LANDLOCK_ACCESS_FS_REFER,
2356		},
2357		{
2358			.path = dir_s2d2,
2359			.access = LANDLOCK_ACCESS_FS_REFER,
2360		},
2361		{
2362			.path = dir_s2d3,
2363			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2364		},
2365		{},
2366	};
2367	const int ruleset_fd = create_ruleset(
2368		_metadata,
2369		LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER, layer1);
2370
2371	ASSERT_LE(0, ruleset_fd);
2372	enforce_ruleset(_metadata, ruleset_fd);
2373	ASSERT_EQ(0, close(ruleset_fd));
2374
2375	ASSERT_EQ(0, unlink(file1_s1d2));
2376	ASSERT_EQ(0, unlink(file1_s1d3));
2377
2378	/* Denies renaming because of missing MAKE_REG. */
2379	ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file1_s1d1,
2380				RENAME_EXCHANGE));
2381	ASSERT_EQ(EACCES, errno);
2382	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file2_s1d1,
2383				RENAME_EXCHANGE));
2384	ASSERT_EQ(EACCES, errno);
2385	ASSERT_EQ(0, unlink(file1_s1d1));
2386	ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
2387	ASSERT_EQ(EACCES, errno);
2388	/* Even denies same file exchange. */
2389	ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file2_s1d1,
2390				RENAME_EXCHANGE));
2391	ASSERT_EQ(EACCES, errno);
2392
2393	/* Denies renaming because of missing source and destination REFER. */
2394	ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d2));
2395	ASSERT_EQ(EXDEV, errno);
2396	/*
2397	 * Denies renaming because of missing MAKE_REG, source and destination
2398	 * REFER.
2399	 */
2400	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file2_s1d1,
2401				RENAME_EXCHANGE));
2402	ASSERT_EQ(EACCES, errno);
2403	ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file1_s2d1,
2404				RENAME_EXCHANGE));
2405	ASSERT_EQ(EACCES, errno);
2406
2407	/* Denies renaming because of missing source REFER. */
2408	ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
2409	ASSERT_EQ(EXDEV, errno);
2410	/* Denies renaming because of missing MAKE_REG. */
2411	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file2_s1d3,
2412				RENAME_EXCHANGE));
2413	ASSERT_EQ(EACCES, errno);
2414
2415	/* Denies renaming because of missing MAKE_REG. */
2416	ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d1));
2417	ASSERT_EQ(EACCES, errno);
2418	/* Denies renaming because of missing destination REFER*/
2419	ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d2));
2420	ASSERT_EQ(EXDEV, errno);
2421
2422	/* Denies exchange because of one missing MAKE_REG. */
2423	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, file2_s1d3,
2424				RENAME_EXCHANGE));
2425	ASSERT_EQ(EACCES, errno);
2426	/* Allows renaming because of REFER and MAKE_REG. */
2427	ASSERT_EQ(0, rename(file1_s2d2, file1_s1d3));
2428
2429	/* Reverse renaming denied because of missing MAKE_REG. */
2430	ASSERT_EQ(-1, rename(file1_s1d3, file1_s2d2));
2431	ASSERT_EQ(EACCES, errno);
2432	ASSERT_EQ(0, unlink(file1_s2d3));
2433	ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2434
2435	/* Tests reverse renaming. */
2436	ASSERT_EQ(0, rename(file1_s2d3, file1_s1d3));
2437	ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s1d3,
2438			       RENAME_EXCHANGE));
2439	ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2440
2441	/*
2442	 * This is OK for a file rename, but it should not be allowed for a
2443	 * directory rename (because of the superset of access rights).
2444	 */
2445	ASSERT_EQ(0, rename(file1_s2d3, file1_s1d3));
2446	ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2447
2448	/*
2449	 * Tests superset restrictions applied to directories.  Not only the
2450	 * dir_s2d3's parent (dir_s2d2) should be taken into account but also
2451	 * access rights tied to dir_s2d3. dir_s2d2 is missing one access right
2452	 * compared to dir_s1d3/file1_s1d3 (MAKE_REG) but it is provided
2453	 * directly by the moved dir_s2d3.
2454	 */
2455	ASSERT_EQ(0, rename(dir_s2d3, file1_s1d3));
2456	ASSERT_EQ(0, rename(file1_s1d3, dir_s2d3));
2457	/*
2458	 * The first rename is allowed but not the exchange because dir_s1d3's
2459	 * parent (dir_s1d2) doesn't have REFER.
2460	 */
2461	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, dir_s1d3,
2462				RENAME_EXCHANGE));
2463	ASSERT_EQ(EXDEV, errno);
2464	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, file1_s2d3,
2465				RENAME_EXCHANGE));
2466	ASSERT_EQ(EXDEV, errno);
2467	ASSERT_EQ(-1, rename(file1_s2d3, dir_s1d3));
2468	ASSERT_EQ(EXDEV, errno);
2469
2470	ASSERT_EQ(-1, rename(file2_s1d2, file1_s1d3));
2471	ASSERT_EQ(EXDEV, errno);
2472	ASSERT_EQ(-1, rename(file2_s1d3, file1_s1d2));
2473	ASSERT_EQ(EXDEV, errno);
2474
2475	/* Renaming in the same directory is always allowed. */
2476	ASSERT_EQ(0, rename(file2_s1d2, file1_s1d2));
2477	ASSERT_EQ(0, rename(file2_s1d3, file1_s1d3));
2478
2479	ASSERT_EQ(0, unlink(file1_s1d2));
2480	/* Denies because of missing source MAKE_REG and destination REFER. */
2481	ASSERT_EQ(-1, rename(dir_s2d3, file1_s1d2));
2482	ASSERT_EQ(EXDEV, errno);
2483
2484	ASSERT_EQ(0, unlink(file1_s1d3));
2485	/* Denies because of missing source MAKE_REG and REFER. */
2486	ASSERT_EQ(-1, rename(dir_s2d2, file1_s1d3));
2487	ASSERT_EQ(EXDEV, errno);
2488}
2489
2490static void
2491reparent_exdev_layers_enforce1(struct __test_metadata *const _metadata)
2492{
2493	const struct rule layer1[] = {
2494		{
2495			.path = dir_s1d2,
2496			.access = LANDLOCK_ACCESS_FS_REFER,
2497		},
2498		{
2499			/* Interesting for the layer2 tests. */
2500			.path = dir_s1d3,
2501			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2502		},
2503		{
2504			.path = dir_s2d2,
2505			.access = LANDLOCK_ACCESS_FS_REFER,
2506		},
2507		{
2508			.path = dir_s2d3,
2509			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
2510		},
2511		{},
2512	};
2513	const int ruleset_fd = create_ruleset(
2514		_metadata,
2515		LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER, layer1);
2516
2517	ASSERT_LE(0, ruleset_fd);
2518	enforce_ruleset(_metadata, ruleset_fd);
2519	ASSERT_EQ(0, close(ruleset_fd));
2520}
2521
2522static void
2523reparent_exdev_layers_enforce2(struct __test_metadata *const _metadata)
2524{
2525	const struct rule layer2[] = {
2526		{
2527			.path = dir_s2d3,
2528			.access = LANDLOCK_ACCESS_FS_MAKE_DIR,
2529		},
2530		{},
2531	};
2532	/*
2533	 * Same checks as before but with a second layer and a new MAKE_DIR
2534	 * rule (and no explicit handling of REFER).
2535	 */
2536	const int ruleset_fd =
2537		create_ruleset(_metadata, LANDLOCK_ACCESS_FS_MAKE_DIR, layer2);
2538
2539	ASSERT_LE(0, ruleset_fd);
2540	enforce_ruleset(_metadata, ruleset_fd);
2541	ASSERT_EQ(0, close(ruleset_fd));
2542}
2543
2544TEST_F_FORK(layout1, reparent_exdev_layers_rename1)
2545{
2546	ASSERT_EQ(0, unlink(file1_s2d2));
2547	ASSERT_EQ(0, unlink(file1_s2d3));
2548
2549	reparent_exdev_layers_enforce1(_metadata);
2550
2551	/*
2552	 * Moving the dir_s1d3 directory below dir_s2d2 is allowed by Landlock
2553	 * because it doesn't inherit new access rights.
2554	 */
2555	ASSERT_EQ(0, rename(dir_s1d3, file1_s2d2));
2556	ASSERT_EQ(0, rename(file1_s2d2, dir_s1d3));
2557
2558	/*
2559	 * Moving the dir_s1d3 directory below dir_s2d3 is allowed, even if it
2560	 * gets a new inherited access rights (MAKE_REG), because MAKE_REG is
2561	 * already allowed for dir_s1d3.
2562	 */
2563	ASSERT_EQ(0, rename(dir_s1d3, file1_s2d3));
2564	ASSERT_EQ(0, rename(file1_s2d3, dir_s1d3));
2565
2566	/*
2567	 * However, moving the file1_s1d3 file below dir_s2d3 is allowed
2568	 * because it cannot inherit MAKE_REG right (which is dedicated to
2569	 * directories).
2570	 */
2571	ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2572
2573	reparent_exdev_layers_enforce2(_metadata);
2574
2575	/*
2576	 * Moving the dir_s1d3 directory below dir_s2d2 is now denied because
2577	 * MAKE_DIR is not tied to dir_s2d2.
2578	 */
2579	ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d2));
2580	ASSERT_EQ(EACCES, errno);
2581
2582	/*
2583	 * Moving the dir_s1d3 directory below dir_s2d3 is forbidden because it
2584	 * would grants MAKE_REG and MAKE_DIR rights to it.
2585	 */
2586	ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d3));
2587	ASSERT_EQ(EXDEV, errno);
2588
2589	/*
2590	 * Moving the file2_s1d3 file below dir_s2d3 is denied because the
2591	 * second layer does not handle REFER, which is always denied by
2592	 * default.
2593	 */
2594	ASSERT_EQ(-1, rename(file2_s1d3, file1_s2d3));
2595	ASSERT_EQ(EXDEV, errno);
2596}
2597
2598TEST_F_FORK(layout1, reparent_exdev_layers_rename2)
2599{
2600	reparent_exdev_layers_enforce1(_metadata);
2601
2602	/* Checks EACCES predominance over EXDEV. */
2603	ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d2));
2604	ASSERT_EQ(EACCES, errno);
2605	ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d2));
2606	ASSERT_EQ(EACCES, errno);
2607	ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d3));
2608	ASSERT_EQ(EXDEV, errno);
2609	/* Modify layout! */
2610	ASSERT_EQ(0, rename(file1_s1d2, file1_s2d3));
2611
2612	/* Without REFER source. */
2613	ASSERT_EQ(-1, rename(dir_s1d1, file1_s2d2));
2614	ASSERT_EQ(EXDEV, errno);
2615	ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d2));
2616	ASSERT_EQ(EXDEV, errno);
2617
2618	reparent_exdev_layers_enforce2(_metadata);
2619
2620	/* Checks EACCES predominance over EXDEV. */
2621	ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d2));
2622	ASSERT_EQ(EACCES, errno);
2623	/* Checks with actual file2_s1d2. */
2624	ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d2));
2625	ASSERT_EQ(EACCES, errno);
2626	ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d3));
2627	ASSERT_EQ(EXDEV, errno);
2628	/*
2629	 * Modifying the layout is now denied because the second layer does not
2630	 * handle REFER, which is always denied by default.
2631	 */
2632	ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d3));
2633	ASSERT_EQ(EXDEV, errno);
2634
2635	/* Without REFER source, EACCES wins over EXDEV. */
2636	ASSERT_EQ(-1, rename(dir_s1d1, file1_s2d2));
2637	ASSERT_EQ(EACCES, errno);
2638	ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d2));
2639	ASSERT_EQ(EACCES, errno);
2640}
2641
2642TEST_F_FORK(layout1, reparent_exdev_layers_exchange1)
2643{
2644	const char *const dir_file1_s1d2 = file1_s1d2, *const dir_file2_s2d3 =
2645							       file2_s2d3;
2646
2647	ASSERT_EQ(0, unlink(file1_s1d2));
2648	ASSERT_EQ(0, mkdir(file1_s1d2, 0700));
2649	ASSERT_EQ(0, unlink(file2_s2d3));
2650	ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
2651
2652	reparent_exdev_layers_enforce1(_metadata);
2653
2654	/* Error predominance with file exchange: returns EXDEV and EACCES. */
2655	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file1_s2d3,
2656				RENAME_EXCHANGE));
2657	ASSERT_EQ(EACCES, errno);
2658	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d1,
2659				RENAME_EXCHANGE));
2660	ASSERT_EQ(EACCES, errno);
2661
2662	/*
2663	 * Checks with directories which creation could be allowed, but denied
2664	 * because of access rights that would be inherited.
2665	 */
2666	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD,
2667				dir_file2_s2d3, RENAME_EXCHANGE));
2668	ASSERT_EQ(EXDEV, errno);
2669	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD,
2670				dir_file1_s1d2, RENAME_EXCHANGE));
2671	ASSERT_EQ(EXDEV, errno);
2672
2673	/* Checks with same access rights. */
2674	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, dir_s2d3,
2675			       RENAME_EXCHANGE));
2676	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
2677			       RENAME_EXCHANGE));
2678
2679	/* Checks with different (child-only) access rights. */
2680	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_file1_s1d2,
2681			       RENAME_EXCHANGE));
2682	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD, dir_s2d3,
2683			       RENAME_EXCHANGE));
2684
2685	/*
2686	 * Checks that exchange between file and directory are consistent.
2687	 *
2688	 * Moving a file (file1_s2d2) to a directory which only grants more
2689	 * directory-related access rights is allowed, and at the same time
2690	 * moving a directory (dir_file2_s2d3) to another directory which
2691	 * grants less access rights is allowed too.
2692	 *
2693	 * See layout1.reparent_exdev_layers_exchange3 for inverted arguments.
2694	 */
2695	ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
2696			       RENAME_EXCHANGE));
2697	/*
2698	 * However, moving back the directory is denied because it would get
2699	 * more access rights than the current state and because file creation
2700	 * is forbidden (in dir_s2d2).
2701	 */
2702	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
2703				RENAME_EXCHANGE));
2704	ASSERT_EQ(EACCES, errno);
2705	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
2706				RENAME_EXCHANGE));
2707	ASSERT_EQ(EACCES, errno);
2708
2709	reparent_exdev_layers_enforce2(_metadata);
2710
2711	/* Error predominance with file exchange: returns EXDEV and EACCES. */
2712	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file1_s2d3,
2713				RENAME_EXCHANGE));
2714	ASSERT_EQ(EACCES, errno);
2715	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d1,
2716				RENAME_EXCHANGE));
2717	ASSERT_EQ(EACCES, errno);
2718
2719	/* Checks with directories which creation is now denied. */
2720	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD,
2721				dir_file2_s2d3, RENAME_EXCHANGE));
2722	ASSERT_EQ(EACCES, errno);
2723	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD,
2724				dir_file1_s1d2, RENAME_EXCHANGE));
2725	ASSERT_EQ(EACCES, errno);
2726
2727	/* Checks with different (child-only) access rights. */
2728	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, dir_s2d3,
2729				RENAME_EXCHANGE));
2730	/* Denied because of MAKE_DIR. */
2731	ASSERT_EQ(EACCES, errno);
2732	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
2733				RENAME_EXCHANGE));
2734	ASSERT_EQ(EACCES, errno);
2735
2736	/* Checks with different (child-only) access rights. */
2737	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_file1_s1d2,
2738				RENAME_EXCHANGE));
2739	/* Denied because of MAKE_DIR. */
2740	ASSERT_EQ(EACCES, errno);
2741	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD, dir_s2d3,
2742				RENAME_EXCHANGE));
2743	ASSERT_EQ(EACCES, errno);
2744
2745	/* See layout1.reparent_exdev_layers_exchange2 for complement. */
2746}
2747
2748TEST_F_FORK(layout1, reparent_exdev_layers_exchange2)
2749{
2750	const char *const dir_file2_s2d3 = file2_s2d3;
2751
2752	ASSERT_EQ(0, unlink(file2_s2d3));
2753	ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
2754
2755	reparent_exdev_layers_enforce1(_metadata);
2756	reparent_exdev_layers_enforce2(_metadata);
2757
2758	/* Checks that exchange between file and directory are consistent. */
2759	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
2760				RENAME_EXCHANGE));
2761	ASSERT_EQ(EACCES, errno);
2762	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
2763				RENAME_EXCHANGE));
2764	ASSERT_EQ(EACCES, errno);
2765}
2766
2767TEST_F_FORK(layout1, reparent_exdev_layers_exchange3)
2768{
2769	const char *const dir_file2_s2d3 = file2_s2d3;
2770
2771	ASSERT_EQ(0, unlink(file2_s2d3));
2772	ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
2773
2774	reparent_exdev_layers_enforce1(_metadata);
2775
2776	/*
2777	 * Checks that exchange between file and directory are consistent,
2778	 * including with inverted arguments (see
2779	 * layout1.reparent_exdev_layers_exchange1).
2780	 */
2781	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
2782			       RENAME_EXCHANGE));
2783	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
2784				RENAME_EXCHANGE));
2785	ASSERT_EQ(EACCES, errno);
2786	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
2787				RENAME_EXCHANGE));
2788	ASSERT_EQ(EACCES, errno);
2789}
2790
2791TEST_F_FORK(layout1, reparent_remove)
2792{
2793	const struct rule layer1[] = {
2794		{
2795			.path = dir_s1d1,
2796			.access = LANDLOCK_ACCESS_FS_REFER |
2797				  LANDLOCK_ACCESS_FS_REMOVE_DIR,
2798		},
2799		{
2800			.path = dir_s1d2,
2801			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
2802		},
2803		{
2804			.path = dir_s2d1,
2805			.access = LANDLOCK_ACCESS_FS_REFER |
2806				  LANDLOCK_ACCESS_FS_REMOVE_FILE,
2807		},
2808		{},
2809	};
2810	const int ruleset_fd = create_ruleset(
2811		_metadata,
2812		LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_REMOVE_DIR |
2813			LANDLOCK_ACCESS_FS_REMOVE_FILE,
2814		layer1);
2815
2816	ASSERT_LE(0, ruleset_fd);
2817	enforce_ruleset(_metadata, ruleset_fd);
2818	ASSERT_EQ(0, close(ruleset_fd));
2819
2820	/* Access denied because of wrong/swapped remove file/dir. */
2821	ASSERT_EQ(-1, rename(file1_s1d1, dir_s2d2));
2822	ASSERT_EQ(EACCES, errno);
2823	ASSERT_EQ(-1, rename(dir_s2d2, file1_s1d1));
2824	ASSERT_EQ(EACCES, errno);
2825	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s2d2,
2826				RENAME_EXCHANGE));
2827	ASSERT_EQ(EACCES, errno);
2828	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s2d3,
2829				RENAME_EXCHANGE));
2830	ASSERT_EQ(EACCES, errno);
2831
2832	/* Access allowed thanks to the matching rights. */
2833	ASSERT_EQ(-1, rename(file1_s2d1, dir_s1d2));
2834	ASSERT_EQ(EISDIR, errno);
2835	ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d1));
2836	ASSERT_EQ(ENOTDIR, errno);
2837	ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d1));
2838	ASSERT_EQ(ENOTDIR, errno);
2839	ASSERT_EQ(0, unlink(file1_s2d1));
2840	ASSERT_EQ(0, unlink(file1_s1d3));
2841	ASSERT_EQ(0, unlink(file2_s1d3));
2842	ASSERT_EQ(0, rename(dir_s1d3, file1_s2d1));
2843
2844	/* Effectively removes a file and a directory by exchanging them. */
2845	ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
2846	ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
2847			       RENAME_EXCHANGE));
2848	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
2849				RENAME_EXCHANGE));
2850	ASSERT_EQ(EACCES, errno);
2851}
2852
2853TEST_F_FORK(layout1, reparent_dom_superset)
2854{
2855	const struct rule layer1[] = {
2856		{
2857			.path = dir_s1d2,
2858			.access = LANDLOCK_ACCESS_FS_REFER,
2859		},
2860		{
2861			.path = file1_s1d2,
2862			.access = LANDLOCK_ACCESS_FS_EXECUTE,
2863		},
2864		{
2865			.path = dir_s1d3,
2866			.access = LANDLOCK_ACCESS_FS_MAKE_SOCK |
2867				  LANDLOCK_ACCESS_FS_EXECUTE,
2868		},
2869		{
2870			.path = dir_s2d2,
2871			.access = LANDLOCK_ACCESS_FS_REFER |
2872				  LANDLOCK_ACCESS_FS_EXECUTE |
2873				  LANDLOCK_ACCESS_FS_MAKE_SOCK,
2874		},
2875		{
2876			.path = dir_s2d3,
2877			.access = LANDLOCK_ACCESS_FS_READ_FILE |
2878				  LANDLOCK_ACCESS_FS_MAKE_FIFO,
2879		},
2880		{},
2881	};
2882	int ruleset_fd = create_ruleset(_metadata,
2883					LANDLOCK_ACCESS_FS_REFER |
2884						LANDLOCK_ACCESS_FS_EXECUTE |
2885						LANDLOCK_ACCESS_FS_MAKE_SOCK |
2886						LANDLOCK_ACCESS_FS_READ_FILE |
2887						LANDLOCK_ACCESS_FS_MAKE_FIFO,
2888					layer1);
2889
2890	ASSERT_LE(0, ruleset_fd);
2891	enforce_ruleset(_metadata, ruleset_fd);
2892	ASSERT_EQ(0, close(ruleset_fd));
2893
2894	ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d1));
2895	ASSERT_EQ(EXDEV, errno);
2896	/*
2897	 * Moving file1_s1d2 beneath dir_s2d3 would grant it the READ_FILE
2898	 * access right.
2899	 */
2900	ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d3));
2901	ASSERT_EQ(EXDEV, errno);
2902	/*
2903	 * Moving file1_s1d2 should be allowed even if dir_s2d2 grants a
2904	 * superset of access rights compared to dir_s1d2, because file1_s1d2
2905	 * already has these access rights anyway.
2906	 */
2907	ASSERT_EQ(0, rename(file1_s1d2, file1_s2d2));
2908	ASSERT_EQ(0, rename(file1_s2d2, file1_s1d2));
2909
2910	ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d1));
2911	ASSERT_EQ(EXDEV, errno);
2912	/*
2913	 * Moving dir_s1d3 beneath dir_s2d3 would grant it the MAKE_FIFO access
2914	 * right.
2915	 */
2916	ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d3));
2917	ASSERT_EQ(EXDEV, errno);
2918	/*
2919	 * Moving dir_s1d3 should be allowed even if dir_s2d2 grants a superset
2920	 * of access rights compared to dir_s1d2, because dir_s1d3 already has
2921	 * these access rights anyway.
2922	 */
2923	ASSERT_EQ(0, rename(dir_s1d3, file1_s2d2));
2924	ASSERT_EQ(0, rename(file1_s2d2, dir_s1d3));
2925
2926	/*
2927	 * Moving file1_s2d3 beneath dir_s1d2 is allowed, but moving it back
2928	 * will be denied because the new inherited access rights from dir_s1d2
2929	 * will be less than the destination (original) dir_s2d3.  This is a
2930	 * sinkhole scenario where we cannot move back files or directories.
2931	 */
2932	ASSERT_EQ(0, rename(file1_s2d3, file2_s1d2));
2933	ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d3));
2934	ASSERT_EQ(EXDEV, errno);
2935	ASSERT_EQ(0, unlink(file2_s1d2));
2936	ASSERT_EQ(0, unlink(file2_s2d3));
2937	/*
2938	 * Checks similar directory one-way move: dir_s2d3 loses EXECUTE and
2939	 * MAKE_SOCK which were inherited from dir_s1d3.
2940	 */
2941	ASSERT_EQ(0, rename(dir_s2d3, file2_s1d2));
2942	ASSERT_EQ(-1, rename(file2_s1d2, dir_s2d3));
2943	ASSERT_EQ(EXDEV, errno);
2944}
2945
2946TEST_F_FORK(layout1, remove_dir)
2947{
2948	const struct rule rules[] = {
2949		{
2950			.path = dir_s1d2,
2951			.access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
2952		},
2953		{},
2954	};
2955	const int ruleset_fd =
2956		create_ruleset(_metadata, rules[0].access, rules);
2957
2958	ASSERT_LE(0, ruleset_fd);
2959
2960	ASSERT_EQ(0, unlink(file1_s1d1));
2961	ASSERT_EQ(0, unlink(file1_s1d2));
2962	ASSERT_EQ(0, unlink(file1_s1d3));
2963	ASSERT_EQ(0, unlink(file2_s1d3));
2964
2965	enforce_ruleset(_metadata, ruleset_fd);
2966	ASSERT_EQ(0, close(ruleset_fd));
2967
2968	ASSERT_EQ(0, rmdir(dir_s1d3));
2969	ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
2970	ASSERT_EQ(0, unlinkat(AT_FDCWD, dir_s1d3, AT_REMOVEDIR));
2971
2972	/* dir_s1d2 itself cannot be removed. */
2973	ASSERT_EQ(-1, rmdir(dir_s1d2));
2974	ASSERT_EQ(EACCES, errno);
2975	ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d2, AT_REMOVEDIR));
2976	ASSERT_EQ(EACCES, errno);
2977	ASSERT_EQ(-1, rmdir(dir_s1d1));
2978	ASSERT_EQ(EACCES, errno);
2979	ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d1, AT_REMOVEDIR));
2980	ASSERT_EQ(EACCES, errno);
2981}
2982
2983TEST_F_FORK(layout1, remove_file)
2984{
2985	const struct rule rules[] = {
2986		{
2987			.path = dir_s1d2,
2988			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
2989		},
2990		{},
2991	};
2992	const int ruleset_fd =
2993		create_ruleset(_metadata, rules[0].access, rules);
2994
2995	ASSERT_LE(0, ruleset_fd);
2996	enforce_ruleset(_metadata, ruleset_fd);
2997	ASSERT_EQ(0, close(ruleset_fd));
2998
2999	ASSERT_EQ(-1, unlink(file1_s1d1));
3000	ASSERT_EQ(EACCES, errno);
3001	ASSERT_EQ(-1, unlinkat(AT_FDCWD, file1_s1d1, 0));
3002	ASSERT_EQ(EACCES, errno);
3003	ASSERT_EQ(0, unlink(file1_s1d2));
3004	ASSERT_EQ(0, unlinkat(AT_FDCWD, file1_s1d3, 0));
3005}
3006
3007static void test_make_file(struct __test_metadata *const _metadata,
3008			   const __u64 access, const mode_t mode,
3009			   const dev_t dev)
3010{
3011	const struct rule rules[] = {
3012		{
3013			.path = dir_s1d2,
3014			.access = access,
3015		},
3016		{},
3017	};
3018	const int ruleset_fd = create_ruleset(_metadata, access, rules);
3019
3020	ASSERT_LE(0, ruleset_fd);
3021
3022	ASSERT_EQ(0, unlink(file1_s1d1));
3023	ASSERT_EQ(0, unlink(file2_s1d1));
3024	ASSERT_EQ(0, mknod(file2_s1d1, mode | 0400, dev))
3025	{
3026		TH_LOG("Failed to make file \"%s\": %s", file2_s1d1,
3027		       strerror(errno));
3028	};
3029
3030	ASSERT_EQ(0, unlink(file1_s1d2));
3031	ASSERT_EQ(0, unlink(file2_s1d2));
3032
3033	ASSERT_EQ(0, unlink(file1_s1d3));
3034	ASSERT_EQ(0, unlink(file2_s1d3));
3035
3036	enforce_ruleset(_metadata, ruleset_fd);
3037	ASSERT_EQ(0, close(ruleset_fd));
3038
3039	ASSERT_EQ(-1, mknod(file1_s1d1, mode | 0400, dev));
3040	ASSERT_EQ(EACCES, errno);
3041	ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
3042	ASSERT_EQ(EACCES, errno);
3043	ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
3044	ASSERT_EQ(EACCES, errno);
3045
3046	ASSERT_EQ(0, mknod(file1_s1d2, mode | 0400, dev))
3047	{
3048		TH_LOG("Failed to make file \"%s\": %s", file1_s1d2,
3049		       strerror(errno));
3050	};
3051	ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
3052	ASSERT_EQ(0, unlink(file2_s1d2));
3053	ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
3054
3055	ASSERT_EQ(0, mknod(file1_s1d3, mode | 0400, dev));
3056	ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
3057	ASSERT_EQ(0, unlink(file2_s1d3));
3058	ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
3059}
3060
3061TEST_F_FORK(layout1, make_char)
3062{
3063	/* Creates a /dev/null device. */
3064	set_cap(_metadata, CAP_MKNOD);
3065	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_CHAR, S_IFCHR,
3066		       makedev(1, 3));
3067}
3068
3069TEST_F_FORK(layout1, make_block)
3070{
3071	/* Creates a /dev/loop0 device. */
3072	set_cap(_metadata, CAP_MKNOD);
3073	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_BLOCK, S_IFBLK,
3074		       makedev(7, 0));
3075}
3076
3077TEST_F_FORK(layout1, make_reg_1)
3078{
3079	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, S_IFREG, 0);
3080}
3081
3082TEST_F_FORK(layout1, make_reg_2)
3083{
3084	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, 0, 0);
3085}
3086
3087TEST_F_FORK(layout1, make_sock)
3088{
3089	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_SOCK, S_IFSOCK, 0);
3090}
3091
3092TEST_F_FORK(layout1, make_fifo)
3093{
3094	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_FIFO, S_IFIFO, 0);
3095}
3096
3097TEST_F_FORK(layout1, make_sym)
3098{
3099	const struct rule rules[] = {
3100		{
3101			.path = dir_s1d2,
3102			.access = LANDLOCK_ACCESS_FS_MAKE_SYM,
3103		},
3104		{},
3105	};
3106	const int ruleset_fd =
3107		create_ruleset(_metadata, rules[0].access, rules);
3108
3109	ASSERT_LE(0, ruleset_fd);
3110
3111	ASSERT_EQ(0, unlink(file1_s1d1));
3112	ASSERT_EQ(0, unlink(file2_s1d1));
3113	ASSERT_EQ(0, symlink("none", file2_s1d1));
3114
3115	ASSERT_EQ(0, unlink(file1_s1d2));
3116	ASSERT_EQ(0, unlink(file2_s1d2));
3117
3118	ASSERT_EQ(0, unlink(file1_s1d3));
3119	ASSERT_EQ(0, unlink(file2_s1d3));
3120
3121	enforce_ruleset(_metadata, ruleset_fd);
3122	ASSERT_EQ(0, close(ruleset_fd));
3123
3124	ASSERT_EQ(-1, symlink("none", file1_s1d1));
3125	ASSERT_EQ(EACCES, errno);
3126	ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
3127	ASSERT_EQ(EACCES, errno);
3128	ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
3129	ASSERT_EQ(EACCES, errno);
3130
3131	ASSERT_EQ(0, symlink("none", file1_s1d2));
3132	ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
3133	ASSERT_EQ(0, unlink(file2_s1d2));
3134	ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
3135
3136	ASSERT_EQ(0, symlink("none", file1_s1d3));
3137	ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
3138	ASSERT_EQ(0, unlink(file2_s1d3));
3139	ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
3140}
3141
3142TEST_F_FORK(layout1, make_dir)
3143{
3144	const struct rule rules[] = {
3145		{
3146			.path = dir_s1d2,
3147			.access = LANDLOCK_ACCESS_FS_MAKE_DIR,
3148		},
3149		{},
3150	};
3151	const int ruleset_fd =
3152		create_ruleset(_metadata, rules[0].access, rules);
3153
3154	ASSERT_LE(0, ruleset_fd);
3155
3156	ASSERT_EQ(0, unlink(file1_s1d1));
3157	ASSERT_EQ(0, unlink(file1_s1d2));
3158	ASSERT_EQ(0, unlink(file1_s1d3));
3159
3160	enforce_ruleset(_metadata, ruleset_fd);
3161	ASSERT_EQ(0, close(ruleset_fd));
3162
3163	/* Uses file_* as directory names. */
3164	ASSERT_EQ(-1, mkdir(file1_s1d1, 0700));
3165	ASSERT_EQ(EACCES, errno);
3166	ASSERT_EQ(0, mkdir(file1_s1d2, 0700));
3167	ASSERT_EQ(0, mkdir(file1_s1d3, 0700));
3168}
3169
3170static int open_proc_fd(struct __test_metadata *const _metadata, const int fd,
3171			const int open_flags)
3172{
3173	static const char path_template[] = "/proc/self/fd/%d";
3174	char procfd_path[sizeof(path_template) + 10];
3175	const int procfd_path_size =
3176		snprintf(procfd_path, sizeof(procfd_path), path_template, fd);
3177
3178	ASSERT_LT(procfd_path_size, sizeof(procfd_path));
3179	return open(procfd_path, open_flags);
3180}
3181
3182TEST_F_FORK(layout1, proc_unlinked_file)
3183{
3184	const struct rule rules[] = {
3185		{
3186			.path = file1_s1d2,
3187			.access = LANDLOCK_ACCESS_FS_READ_FILE,
3188		},
3189		{},
3190	};
3191	int reg_fd, proc_fd;
3192	const int ruleset_fd = create_ruleset(
3193		_metadata,
3194		LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE,
3195		rules);
3196
3197	ASSERT_LE(0, ruleset_fd);
3198	enforce_ruleset(_metadata, ruleset_fd);
3199	ASSERT_EQ(0, close(ruleset_fd));
3200
3201	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
3202	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
3203	reg_fd = open(file1_s1d2, O_RDONLY | O_CLOEXEC);
3204	ASSERT_LE(0, reg_fd);
3205	ASSERT_EQ(0, unlink(file1_s1d2));
3206
3207	proc_fd = open_proc_fd(_metadata, reg_fd, O_RDONLY | O_CLOEXEC);
3208	ASSERT_LE(0, proc_fd);
3209	ASSERT_EQ(0, close(proc_fd));
3210
3211	proc_fd = open_proc_fd(_metadata, reg_fd, O_RDWR | O_CLOEXEC);
3212	ASSERT_EQ(-1, proc_fd)
3213	{
3214		TH_LOG("Successfully opened /proc/self/fd/%d: %s", reg_fd,
3215		       strerror(errno));
3216	}
3217	ASSERT_EQ(EACCES, errno);
3218
3219	ASSERT_EQ(0, close(reg_fd));
3220}
3221
3222TEST_F_FORK(layout1, proc_pipe)
3223{
3224	int proc_fd;
3225	int pipe_fds[2];
3226	char buf = '\0';
3227	const struct rule rules[] = {
3228		{
3229			.path = dir_s1d2,
3230			.access = LANDLOCK_ACCESS_FS_READ_FILE |
3231				  LANDLOCK_ACCESS_FS_WRITE_FILE,
3232		},
3233		{},
3234	};
3235	/* Limits read and write access to files tied to the filesystem. */
3236	const int ruleset_fd =
3237		create_ruleset(_metadata, rules[0].access, rules);
3238
3239	ASSERT_LE(0, ruleset_fd);
3240	enforce_ruleset(_metadata, ruleset_fd);
3241	ASSERT_EQ(0, close(ruleset_fd));
3242
3243	/* Checks enforcement for normal files. */
3244	ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
3245	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
3246
3247	/* Checks access to pipes through FD. */
3248	ASSERT_EQ(0, pipe2(pipe_fds, O_CLOEXEC));
3249	ASSERT_EQ(1, write(pipe_fds[1], ".", 1))
3250	{
3251		TH_LOG("Failed to write in pipe: %s", strerror(errno));
3252	}
3253	ASSERT_EQ(1, read(pipe_fds[0], &buf, 1));
3254	ASSERT_EQ('.', buf);
3255
3256	/* Checks write access to pipe through /proc/self/fd . */
3257	proc_fd = open_proc_fd(_metadata, pipe_fds[1], O_WRONLY | O_CLOEXEC);
3258	ASSERT_LE(0, proc_fd);
3259	ASSERT_EQ(1, write(proc_fd, ".", 1))
3260	{
3261		TH_LOG("Failed to write through /proc/self/fd/%d: %s",
3262		       pipe_fds[1], strerror(errno));
3263	}
3264	ASSERT_EQ(0, close(proc_fd));
3265
3266	/* Checks read access to pipe through /proc/self/fd . */
3267	proc_fd = open_proc_fd(_metadata, pipe_fds[0], O_RDONLY | O_CLOEXEC);
3268	ASSERT_LE(0, proc_fd);
3269	buf = '\0';
3270	ASSERT_EQ(1, read(proc_fd, &buf, 1))
3271	{
3272		TH_LOG("Failed to read through /proc/self/fd/%d: %s",
3273		       pipe_fds[1], strerror(errno));
3274	}
3275	ASSERT_EQ(0, close(proc_fd));
3276
3277	ASSERT_EQ(0, close(pipe_fds[0]));
3278	ASSERT_EQ(0, close(pipe_fds[1]));
3279}
3280
3281/* Invokes truncate(2) and returns its errno or 0. */
3282static int test_truncate(const char *const path)
3283{
3284	if (truncate(path, 10) < 0)
3285		return errno;
3286	return 0;
3287}
3288
3289/*
3290 * Invokes creat(2) and returns its errno or 0.
3291 * Closes the opened file descriptor on success.
3292 */
3293static int test_creat(const char *const path)
3294{
3295	int fd = creat(path, 0600);
3296
3297	if (fd < 0)
3298		return errno;
3299
3300	/*
3301	 * Mixing error codes from close(2) and creat(2) should not lead to any
3302	 * (access type) confusion for this test.
3303	 */
3304	if (close(fd) < 0)
3305		return errno;
3306	return 0;
3307}
3308
3309/*
3310 * Exercises file truncation when it's not restricted,
3311 * as it was the case before LANDLOCK_ACCESS_FS_TRUNCATE existed.
3312 */
3313TEST_F_FORK(layout1, truncate_unhandled)
3314{
3315	const char *const file_r = file1_s1d1;
3316	const char *const file_w = file2_s1d1;
3317	const char *const file_none = file1_s1d2;
3318	const struct rule rules[] = {
3319		{
3320			.path = file_r,
3321			.access = LANDLOCK_ACCESS_FS_READ_FILE,
3322		},
3323		{
3324			.path = file_w,
3325			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3326		},
3327		/* Implicitly: No rights for file_none. */
3328		{},
3329	};
3330
3331	const __u64 handled = LANDLOCK_ACCESS_FS_READ_FILE |
3332			      LANDLOCK_ACCESS_FS_WRITE_FILE;
3333	int ruleset_fd;
3334
3335	/* Enable Landlock. */
3336	ruleset_fd = create_ruleset(_metadata, handled, rules);
3337
3338	ASSERT_LE(0, ruleset_fd);
3339	enforce_ruleset(_metadata, ruleset_fd);
3340	ASSERT_EQ(0, close(ruleset_fd));
3341
3342	/*
3343	 * Checks read right: truncate and open with O_TRUNC work, unless the
3344	 * file is attempted to be opened for writing.
3345	 */
3346	EXPECT_EQ(0, test_truncate(file_r));
3347	EXPECT_EQ(0, test_open(file_r, O_RDONLY | O_TRUNC));
3348	EXPECT_EQ(EACCES, test_open(file_r, O_WRONLY | O_TRUNC));
3349	EXPECT_EQ(EACCES, test_creat(file_r));
3350
3351	/*
3352	 * Checks write right: truncate and open with O_TRUNC work, unless the
3353	 * file is attempted to be opened for reading.
3354	 */
3355	EXPECT_EQ(0, test_truncate(file_w));
3356	EXPECT_EQ(EACCES, test_open(file_w, O_RDONLY | O_TRUNC));
3357	EXPECT_EQ(0, test_open(file_w, O_WRONLY | O_TRUNC));
3358	EXPECT_EQ(0, test_creat(file_w));
3359
3360	/*
3361	 * Checks "no rights" case: truncate works but all open attempts fail,
3362	 * including creat.
3363	 */
3364	EXPECT_EQ(0, test_truncate(file_none));
3365	EXPECT_EQ(EACCES, test_open(file_none, O_RDONLY | O_TRUNC));
3366	EXPECT_EQ(EACCES, test_open(file_none, O_WRONLY | O_TRUNC));
3367	EXPECT_EQ(EACCES, test_creat(file_none));
3368}
3369
3370TEST_F_FORK(layout1, truncate)
3371{
3372	const char *const file_rwt = file1_s1d1;
3373	const char *const file_rw = file2_s1d1;
3374	const char *const file_rt = file1_s1d2;
3375	const char *const file_t = file2_s1d2;
3376	const char *const file_none = file1_s1d3;
3377	const char *const dir_t = dir_s2d1;
3378	const char *const file_in_dir_t = file1_s2d1;
3379	const char *const dir_w = dir_s3d1;
3380	const char *const file_in_dir_w = file1_s3d1;
3381	const struct rule rules[] = {
3382		{
3383			.path = file_rwt,
3384			.access = LANDLOCK_ACCESS_FS_READ_FILE |
3385				  LANDLOCK_ACCESS_FS_WRITE_FILE |
3386				  LANDLOCK_ACCESS_FS_TRUNCATE,
3387		},
3388		{
3389			.path = file_rw,
3390			.access = LANDLOCK_ACCESS_FS_READ_FILE |
3391				  LANDLOCK_ACCESS_FS_WRITE_FILE,
3392		},
3393		{
3394			.path = file_rt,
3395			.access = LANDLOCK_ACCESS_FS_READ_FILE |
3396				  LANDLOCK_ACCESS_FS_TRUNCATE,
3397		},
3398		{
3399			.path = file_t,
3400			.access = LANDLOCK_ACCESS_FS_TRUNCATE,
3401		},
3402		/* Implicitly: No access rights for file_none. */
3403		{
3404			.path = dir_t,
3405			.access = LANDLOCK_ACCESS_FS_TRUNCATE,
3406		},
3407		{
3408			.path = dir_w,
3409			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3410		},
3411		{},
3412	};
3413	const __u64 handled = LANDLOCK_ACCESS_FS_READ_FILE |
3414			      LANDLOCK_ACCESS_FS_WRITE_FILE |
3415			      LANDLOCK_ACCESS_FS_TRUNCATE;
3416	int ruleset_fd;
3417
3418	/* Enable Landlock. */
3419	ruleset_fd = create_ruleset(_metadata, handled, rules);
3420
3421	ASSERT_LE(0, ruleset_fd);
3422	enforce_ruleset(_metadata, ruleset_fd);
3423	ASSERT_EQ(0, close(ruleset_fd));
3424
3425	/* Checks read, write and truncate rights: truncation works. */
3426	EXPECT_EQ(0, test_truncate(file_rwt));
3427	EXPECT_EQ(0, test_open(file_rwt, O_RDONLY | O_TRUNC));
3428	EXPECT_EQ(0, test_open(file_rwt, O_WRONLY | O_TRUNC));
3429
3430	/* Checks read and write rights: no truncate variant works. */
3431	EXPECT_EQ(EACCES, test_truncate(file_rw));
3432	EXPECT_EQ(EACCES, test_open(file_rw, O_RDONLY | O_TRUNC));
3433	EXPECT_EQ(EACCES, test_open(file_rw, O_WRONLY | O_TRUNC));
3434
3435	/*
3436	 * Checks read and truncate rights: truncation works.
3437	 *
3438	 * Note: Files can get truncated using open() even with O_RDONLY.
3439	 */
3440	EXPECT_EQ(0, test_truncate(file_rt));
3441	EXPECT_EQ(0, test_open(file_rt, O_RDONLY | O_TRUNC));
3442	EXPECT_EQ(EACCES, test_open(file_rt, O_WRONLY | O_TRUNC));
3443
3444	/* Checks truncate right: truncate works, but can't open file. */
3445	EXPECT_EQ(0, test_truncate(file_t));
3446	EXPECT_EQ(EACCES, test_open(file_t, O_RDONLY | O_TRUNC));
3447	EXPECT_EQ(EACCES, test_open(file_t, O_WRONLY | O_TRUNC));
3448
3449	/* Checks "no rights" case: No form of truncation works. */
3450	EXPECT_EQ(EACCES, test_truncate(file_none));
3451	EXPECT_EQ(EACCES, test_open(file_none, O_RDONLY | O_TRUNC));
3452	EXPECT_EQ(EACCES, test_open(file_none, O_WRONLY | O_TRUNC));
3453
3454	/*
3455	 * Checks truncate right on directory: truncate works on contained
3456	 * files.
3457	 */
3458	EXPECT_EQ(0, test_truncate(file_in_dir_t));
3459	EXPECT_EQ(EACCES, test_open(file_in_dir_t, O_RDONLY | O_TRUNC));
3460	EXPECT_EQ(EACCES, test_open(file_in_dir_t, O_WRONLY | O_TRUNC));
3461
3462	/*
3463	 * Checks creat in dir_w: This requires the truncate right when
3464	 * overwriting an existing file, but does not require it when the file
3465	 * is new.
3466	 */
3467	EXPECT_EQ(EACCES, test_creat(file_in_dir_w));
3468
3469	ASSERT_EQ(0, unlink(file_in_dir_w));
3470	EXPECT_EQ(0, test_creat(file_in_dir_w));
3471}
3472
3473/* Invokes ftruncate(2) and returns its errno or 0. */
3474static int test_ftruncate(int fd)
3475{
3476	if (ftruncate(fd, 10) < 0)
3477		return errno;
3478	return 0;
3479}
3480
3481TEST_F_FORK(layout1, ftruncate)
3482{
3483	/*
3484	 * This test opens a new file descriptor at different stages of
3485	 * Landlock restriction:
3486	 *
3487	 * without restriction:                    ftruncate works
3488	 * something else but truncate restricted: ftruncate works
3489	 * truncate restricted and permitted:      ftruncate works
3490	 * truncate restricted and not permitted:  ftruncate fails
3491	 *
3492	 * Whether this works or not is expected to depend on the time when the
3493	 * FD was opened, not to depend on the time when ftruncate() was
3494	 * called.
3495	 */
3496	const char *const path = file1_s1d1;
3497	const __u64 handled1 = LANDLOCK_ACCESS_FS_READ_FILE |
3498			       LANDLOCK_ACCESS_FS_WRITE_FILE;
3499	const struct rule layer1[] = {
3500		{
3501			.path = path,
3502			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3503		},
3504		{},
3505	};
3506	const __u64 handled2 = LANDLOCK_ACCESS_FS_TRUNCATE;
3507	const struct rule layer2[] = {
3508		{
3509			.path = path,
3510			.access = LANDLOCK_ACCESS_FS_TRUNCATE,
3511		},
3512		{},
3513	};
3514	const __u64 handled3 = LANDLOCK_ACCESS_FS_TRUNCATE |
3515			       LANDLOCK_ACCESS_FS_WRITE_FILE;
3516	const struct rule layer3[] = {
3517		{
3518			.path = path,
3519			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3520		},
3521		{},
3522	};
3523	int fd_layer0, fd_layer1, fd_layer2, fd_layer3, ruleset_fd;
3524
3525	fd_layer0 = open(path, O_WRONLY);
3526	EXPECT_EQ(0, test_ftruncate(fd_layer0));
3527
3528	ruleset_fd = create_ruleset(_metadata, handled1, layer1);
3529	ASSERT_LE(0, ruleset_fd);
3530	enforce_ruleset(_metadata, ruleset_fd);
3531	ASSERT_EQ(0, close(ruleset_fd));
3532
3533	fd_layer1 = open(path, O_WRONLY);
3534	EXPECT_EQ(0, test_ftruncate(fd_layer0));
3535	EXPECT_EQ(0, test_ftruncate(fd_layer1));
3536
3537	ruleset_fd = create_ruleset(_metadata, handled2, layer2);
3538	ASSERT_LE(0, ruleset_fd);
3539	enforce_ruleset(_metadata, ruleset_fd);
3540	ASSERT_EQ(0, close(ruleset_fd));
3541
3542	fd_layer2 = open(path, O_WRONLY);
3543	EXPECT_EQ(0, test_ftruncate(fd_layer0));
3544	EXPECT_EQ(0, test_ftruncate(fd_layer1));
3545	EXPECT_EQ(0, test_ftruncate(fd_layer2));
3546
3547	ruleset_fd = create_ruleset(_metadata, handled3, layer3);
3548	ASSERT_LE(0, ruleset_fd);
3549	enforce_ruleset(_metadata, ruleset_fd);
3550	ASSERT_EQ(0, close(ruleset_fd));
3551
3552	fd_layer3 = open(path, O_WRONLY);
3553	EXPECT_EQ(0, test_ftruncate(fd_layer0));
3554	EXPECT_EQ(0, test_ftruncate(fd_layer1));
3555	EXPECT_EQ(0, test_ftruncate(fd_layer2));
3556	EXPECT_EQ(EACCES, test_ftruncate(fd_layer3));
3557
3558	ASSERT_EQ(0, close(fd_layer0));
3559	ASSERT_EQ(0, close(fd_layer1));
3560	ASSERT_EQ(0, close(fd_layer2));
3561	ASSERT_EQ(0, close(fd_layer3));
3562}
3563
3564/* clang-format off */
3565FIXTURE(ftruncate) {};
3566/* clang-format on */
3567
3568FIXTURE_SETUP(ftruncate)
3569{
3570	prepare_layout(_metadata);
3571	create_file(_metadata, file1_s1d1);
3572}
3573
3574FIXTURE_TEARDOWN(ftruncate)
3575{
3576	EXPECT_EQ(0, remove_path(file1_s1d1));
3577	cleanup_layout(_metadata);
3578}
3579
3580FIXTURE_VARIANT(ftruncate)
3581{
3582	const __u64 handled;
3583	const __u64 permitted;
3584	const int expected_open_result;
3585	const int expected_ftruncate_result;
3586};
3587
3588/* clang-format off */
3589FIXTURE_VARIANT_ADD(ftruncate, w_w) {
3590	/* clang-format on */
3591	.handled = LANDLOCK_ACCESS_FS_WRITE_FILE,
3592	.permitted = LANDLOCK_ACCESS_FS_WRITE_FILE,
3593	.expected_open_result = 0,
3594	.expected_ftruncate_result = 0,
3595};
3596
3597/* clang-format off */
3598FIXTURE_VARIANT_ADD(ftruncate, t_t) {
3599	/* clang-format on */
3600	.handled = LANDLOCK_ACCESS_FS_TRUNCATE,
3601	.permitted = LANDLOCK_ACCESS_FS_TRUNCATE,
3602	.expected_open_result = 0,
3603	.expected_ftruncate_result = 0,
3604};
3605
3606/* clang-format off */
3607FIXTURE_VARIANT_ADD(ftruncate, wt_w) {
3608	/* clang-format on */
3609	.handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
3610	.permitted = LANDLOCK_ACCESS_FS_WRITE_FILE,
3611	.expected_open_result = 0,
3612	.expected_ftruncate_result = EACCES,
3613};
3614
3615/* clang-format off */
3616FIXTURE_VARIANT_ADD(ftruncate, wt_wt) {
3617	/* clang-format on */
3618	.handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
3619	.permitted = LANDLOCK_ACCESS_FS_WRITE_FILE |
3620		     LANDLOCK_ACCESS_FS_TRUNCATE,
3621	.expected_open_result = 0,
3622	.expected_ftruncate_result = 0,
3623};
3624
3625/* clang-format off */
3626FIXTURE_VARIANT_ADD(ftruncate, wt_t) {
3627	/* clang-format on */
3628	.handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
3629	.permitted = LANDLOCK_ACCESS_FS_TRUNCATE,
3630	.expected_open_result = EACCES,
3631};
3632
3633TEST_F_FORK(ftruncate, open_and_ftruncate)
3634{
3635	const char *const path = file1_s1d1;
3636	const struct rule rules[] = {
3637		{
3638			.path = path,
3639			.access = variant->permitted,
3640		},
3641		{},
3642	};
3643	int fd, ruleset_fd;
3644
3645	/* Enable Landlock. */
3646	ruleset_fd = create_ruleset(_metadata, variant->handled, rules);
3647	ASSERT_LE(0, ruleset_fd);
3648	enforce_ruleset(_metadata, ruleset_fd);
3649	ASSERT_EQ(0, close(ruleset_fd));
3650
3651	fd = open(path, O_WRONLY);
3652	EXPECT_EQ(variant->expected_open_result, (fd < 0 ? errno : 0));
3653	if (fd >= 0) {
3654		EXPECT_EQ(variant->expected_ftruncate_result,
3655			  test_ftruncate(fd));
3656		ASSERT_EQ(0, close(fd));
3657	}
3658}
3659
3660TEST_F_FORK(ftruncate, open_and_ftruncate_in_different_processes)
3661{
3662	int child, fd, status;
3663	int socket_fds[2];
3664
3665	ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0,
3666				socket_fds));
3667
3668	child = fork();
3669	ASSERT_LE(0, child);
3670	if (child == 0) {
3671		/*
3672		 * Enables Landlock in the child process, open a file descriptor
3673		 * where truncation is forbidden and send it to the
3674		 * non-landlocked parent process.
3675		 */
3676		const char *const path = file1_s1d1;
3677		const struct rule rules[] = {
3678			{
3679				.path = path,
3680				.access = variant->permitted,
3681			},
3682			{},
3683		};
3684		int fd, ruleset_fd;
3685
3686		ruleset_fd = create_ruleset(_metadata, variant->handled, rules);
3687		ASSERT_LE(0, ruleset_fd);
3688		enforce_ruleset(_metadata, ruleset_fd);
3689		ASSERT_EQ(0, close(ruleset_fd));
3690
3691		fd = open(path, O_WRONLY);
3692		ASSERT_EQ(variant->expected_open_result, (fd < 0 ? errno : 0));
3693
3694		if (fd >= 0) {
3695			ASSERT_EQ(0, send_fd(socket_fds[0], fd));
3696			ASSERT_EQ(0, close(fd));
3697		}
3698
3699		ASSERT_EQ(0, close(socket_fds[0]));
3700
3701		_exit(_metadata->passed ? EXIT_SUCCESS : EXIT_FAILURE);
3702		return;
3703	}
3704
3705	if (variant->expected_open_result == 0) {
3706		fd = recv_fd(socket_fds[1]);
3707		ASSERT_LE(0, fd);
3708
3709		EXPECT_EQ(variant->expected_ftruncate_result,
3710			  test_ftruncate(fd));
3711		ASSERT_EQ(0, close(fd));
3712	}
3713
3714	ASSERT_EQ(child, waitpid(child, &status, 0));
3715	ASSERT_EQ(1, WIFEXITED(status));
3716	ASSERT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
3717
3718	ASSERT_EQ(0, close(socket_fds[0]));
3719	ASSERT_EQ(0, close(socket_fds[1]));
3720}
3721
3722TEST(memfd_ftruncate)
3723{
3724	int fd;
3725
3726	fd = memfd_create("name", MFD_CLOEXEC);
3727	ASSERT_LE(0, fd);
3728
3729	/*
3730	 * Checks that ftruncate is permitted on file descriptors that are
3731	 * created in ways other than open(2).
3732	 */
3733	EXPECT_EQ(0, test_ftruncate(fd));
3734
3735	ASSERT_EQ(0, close(fd));
3736}
3737
3738/* clang-format off */
3739FIXTURE(layout1_bind) {};
3740/* clang-format on */
3741
3742FIXTURE_SETUP(layout1_bind)
3743{
3744	prepare_layout(_metadata);
3745
3746	create_layout1(_metadata);
3747
3748	set_cap(_metadata, CAP_SYS_ADMIN);
3749	ASSERT_EQ(0, mount(dir_s1d2, dir_s2d2, NULL, MS_BIND, NULL));
3750	clear_cap(_metadata, CAP_SYS_ADMIN);
3751}
3752
3753FIXTURE_TEARDOWN(layout1_bind)
3754{
3755	set_cap(_metadata, CAP_SYS_ADMIN);
3756	EXPECT_EQ(0, umount(dir_s2d2));
3757	clear_cap(_metadata, CAP_SYS_ADMIN);
3758
3759	remove_layout1(_metadata);
3760
3761	cleanup_layout(_metadata);
3762}
3763
3764static const char bind_dir_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3";
3765static const char bind_file1_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3/f1";
3766
3767/*
3768 * layout1_bind hierarchy:
3769 *
3770 * tmp
3771 * ├── s1d1
3772 * │   ├── f1
3773 * │   ├── f2
3774 * │   └── s1d2
3775 * │       ├── f1
3776 * │       ├── f2
3777 * │       └── s1d3
3778 * │           ├── f1
3779 * │           └── f2
3780 * ├── s2d1
3781 * │   ├── f1
3782 * │   └── s2d2
3783 * │       ├── f1
3784 * │       ├── f2
3785 * │       └── s1d3
3786 * │           ├── f1
3787 * │           └── f2
3788 * └── s3d1
3789 *     └── s3d2
3790 *         └── s3d3
3791 */
3792
3793TEST_F_FORK(layout1_bind, no_restriction)
3794{
3795	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
3796	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
3797	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
3798	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
3799	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
3800	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
3801
3802	ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
3803	ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
3804	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
3805	ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
3806	ASSERT_EQ(ENOENT, test_open(dir_s2d3, O_RDONLY));
3807	ASSERT_EQ(ENOENT, test_open(file1_s2d3, O_RDONLY));
3808
3809	ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY));
3810	ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
3811
3812	ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
3813}
3814
3815TEST_F_FORK(layout1_bind, same_content_same_file)
3816{
3817	/*
3818	 * Sets access right on parent directories of both source and
3819	 * destination mount points.
3820	 */
3821	const struct rule layer1_parent[] = {
3822		{
3823			.path = dir_s1d1,
3824			.access = ACCESS_RO,
3825		},
3826		{
3827			.path = dir_s2d1,
3828			.access = ACCESS_RW,
3829		},
3830		{},
3831	};
3832	/*
3833	 * Sets access rights on the same bind-mounted directories.  The result
3834	 * should be ACCESS_RW for both directories, but not both hierarchies
3835	 * because of the first layer.
3836	 */
3837	const struct rule layer2_mount_point[] = {
3838		{
3839			.path = dir_s1d2,
3840			.access = LANDLOCK_ACCESS_FS_READ_FILE,
3841		},
3842		{
3843			.path = dir_s2d2,
3844			.access = ACCESS_RW,
3845		},
3846		{},
3847	};
3848	/* Only allow read-access to the s1d3 hierarchies. */
3849	const struct rule layer3_source[] = {
3850		{
3851			.path = dir_s1d3,
3852			.access = LANDLOCK_ACCESS_FS_READ_FILE,
3853		},
3854		{},
3855	};
3856	/* Removes all access rights. */
3857	const struct rule layer4_destination[] = {
3858		{
3859			.path = bind_file1_s1d3,
3860			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3861		},
3862		{},
3863	};
3864	int ruleset_fd;
3865
3866	/* Sets rules for the parent directories. */
3867	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_parent);
3868	ASSERT_LE(0, ruleset_fd);
3869	enforce_ruleset(_metadata, ruleset_fd);
3870	ASSERT_EQ(0, close(ruleset_fd));
3871
3872	/* Checks source hierarchy. */
3873	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
3874	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
3875	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
3876
3877	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
3878	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
3879	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
3880
3881	/* Checks destination hierarchy. */
3882	ASSERT_EQ(0, test_open(file1_s2d1, O_RDWR));
3883	ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
3884
3885	ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
3886	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
3887
3888	/* Sets rules for the mount points. */
3889	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_mount_point);
3890	ASSERT_LE(0, ruleset_fd);
3891	enforce_ruleset(_metadata, ruleset_fd);
3892	ASSERT_EQ(0, close(ruleset_fd));
3893
3894	/* Checks source hierarchy. */
3895	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
3896	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
3897	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
3898
3899	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
3900	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
3901	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
3902
3903	/* Checks destination hierarchy. */
3904	ASSERT_EQ(EACCES, test_open(file1_s2d1, O_RDONLY));
3905	ASSERT_EQ(EACCES, test_open(file1_s2d1, O_WRONLY));
3906	ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
3907
3908	ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
3909	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
3910	ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
3911
3912	/* Sets a (shared) rule only on the source. */
3913	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3_source);
3914	ASSERT_LE(0, ruleset_fd);
3915	enforce_ruleset(_metadata, ruleset_fd);
3916	ASSERT_EQ(0, close(ruleset_fd));
3917
3918	/* Checks source hierarchy. */
3919	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDONLY));
3920	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
3921	ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
3922
3923	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
3924	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
3925	ASSERT_EQ(EACCES, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
3926
3927	/* Checks destination hierarchy. */
3928	ASSERT_EQ(EACCES, test_open(file1_s2d2, O_RDONLY));
3929	ASSERT_EQ(EACCES, test_open(file1_s2d2, O_WRONLY));
3930	ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
3931
3932	ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
3933	ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
3934	ASSERT_EQ(EACCES, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
3935
3936	/* Sets a (shared) rule only on the destination. */
3937	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer4_destination);
3938	ASSERT_LE(0, ruleset_fd);
3939	enforce_ruleset(_metadata, ruleset_fd);
3940	ASSERT_EQ(0, close(ruleset_fd));
3941
3942	/* Checks source hierarchy. */
3943	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
3944	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
3945
3946	/* Checks destination hierarchy. */
3947	ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_RDONLY));
3948	ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
3949}
3950
3951TEST_F_FORK(layout1_bind, reparent_cross_mount)
3952{
3953	const struct rule layer1[] = {
3954		{
3955			/* dir_s2d1 is beneath the dir_s2d2 mount point. */
3956			.path = dir_s2d1,
3957			.access = LANDLOCK_ACCESS_FS_REFER,
3958		},
3959		{
3960			.path = bind_dir_s1d3,
3961			.access = LANDLOCK_ACCESS_FS_EXECUTE,
3962		},
3963		{},
3964	};
3965	int ruleset_fd = create_ruleset(
3966		_metadata,
3967		LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_EXECUTE, layer1);
3968
3969	ASSERT_LE(0, ruleset_fd);
3970	enforce_ruleset(_metadata, ruleset_fd);
3971	ASSERT_EQ(0, close(ruleset_fd));
3972
3973	/* Checks basic denied move. */
3974	ASSERT_EQ(-1, rename(file1_s1d1, file1_s1d2));
3975	ASSERT_EQ(EXDEV, errno);
3976
3977	/* Checks real cross-mount move (Landlock is not involved). */
3978	ASSERT_EQ(-1, rename(file1_s2d1, file1_s2d2));
3979	ASSERT_EQ(EXDEV, errno);
3980
3981	/* Checks move that will give more accesses. */
3982	ASSERT_EQ(-1, rename(file1_s2d2, bind_file1_s1d3));
3983	ASSERT_EQ(EXDEV, errno);
3984
3985	/* Checks legitimate downgrade move. */
3986	ASSERT_EQ(0, rename(bind_file1_s1d3, file1_s2d2));
3987}
3988
3989#define LOWER_BASE TMP_DIR "/lower"
3990#define LOWER_DATA LOWER_BASE "/data"
3991static const char lower_fl1[] = LOWER_DATA "/fl1";
3992static const char lower_dl1[] = LOWER_DATA "/dl1";
3993static const char lower_dl1_fl2[] = LOWER_DATA "/dl1/fl2";
3994static const char lower_fo1[] = LOWER_DATA "/fo1";
3995static const char lower_do1[] = LOWER_DATA "/do1";
3996static const char lower_do1_fo2[] = LOWER_DATA "/do1/fo2";
3997static const char lower_do1_fl3[] = LOWER_DATA "/do1/fl3";
3998
3999static const char (*lower_base_files[])[] = {
4000	&lower_fl1,
4001	&lower_fo1,
4002	NULL,
4003};
4004static const char (*lower_base_directories[])[] = {
4005	&lower_dl1,
4006	&lower_do1,
4007	NULL,
4008};
4009static const char (*lower_sub_files[])[] = {
4010	&lower_dl1_fl2,
4011	&lower_do1_fo2,
4012	&lower_do1_fl3,
4013	NULL,
4014};
4015
4016#define UPPER_BASE TMP_DIR "/upper"
4017#define UPPER_DATA UPPER_BASE "/data"
4018#define UPPER_WORK UPPER_BASE "/work"
4019static const char upper_fu1[] = UPPER_DATA "/fu1";
4020static const char upper_du1[] = UPPER_DATA "/du1";
4021static const char upper_du1_fu2[] = UPPER_DATA "/du1/fu2";
4022static const char upper_fo1[] = UPPER_DATA "/fo1";
4023static const char upper_do1[] = UPPER_DATA "/do1";
4024static const char upper_do1_fo2[] = UPPER_DATA "/do1/fo2";
4025static const char upper_do1_fu3[] = UPPER_DATA "/do1/fu3";
4026
4027static const char (*upper_base_files[])[] = {
4028	&upper_fu1,
4029	&upper_fo1,
4030	NULL,
4031};
4032static const char (*upper_base_directories[])[] = {
4033	&upper_du1,
4034	&upper_do1,
4035	NULL,
4036};
4037static const char (*upper_sub_files[])[] = {
4038	&upper_du1_fu2,
4039	&upper_do1_fo2,
4040	&upper_do1_fu3,
4041	NULL,
4042};
4043
4044#define MERGE_BASE TMP_DIR "/merge"
4045#define MERGE_DATA MERGE_BASE "/data"
4046static const char merge_fl1[] = MERGE_DATA "/fl1";
4047static const char merge_dl1[] = MERGE_DATA "/dl1";
4048static const char merge_dl1_fl2[] = MERGE_DATA "/dl1/fl2";
4049static const char merge_fu1[] = MERGE_DATA "/fu1";
4050static const char merge_du1[] = MERGE_DATA "/du1";
4051static const char merge_du1_fu2[] = MERGE_DATA "/du1/fu2";
4052static const char merge_fo1[] = MERGE_DATA "/fo1";
4053static const char merge_do1[] = MERGE_DATA "/do1";
4054static const char merge_do1_fo2[] = MERGE_DATA "/do1/fo2";
4055static const char merge_do1_fl3[] = MERGE_DATA "/do1/fl3";
4056static const char merge_do1_fu3[] = MERGE_DATA "/do1/fu3";
4057
4058static const char (*merge_base_files[])[] = {
4059	&merge_fl1,
4060	&merge_fu1,
4061	&merge_fo1,
4062	NULL,
4063};
4064static const char (*merge_base_directories[])[] = {
4065	&merge_dl1,
4066	&merge_du1,
4067	&merge_do1,
4068	NULL,
4069};
4070static const char (*merge_sub_files[])[] = {
4071	&merge_dl1_fl2, &merge_du1_fu2, &merge_do1_fo2,
4072	&merge_do1_fl3, &merge_do1_fu3, NULL,
4073};
4074
4075/*
4076 * layout2_overlay hierarchy:
4077 *
4078 * tmp
4079 * ├── lower
4080 * │   └── data
4081 * │       ├── dl1
4082 * │       │   └── fl2
4083 * │       ├── do1
4084 * │       │   ├── fl3
4085 * │       │   └── fo2
4086 * │       ├── fl1
4087 * │       └── fo1
4088 * ├── merge
4089 * │   └── data
4090 * │       ├── dl1
4091 * │       │   └── fl2
4092 * │       ├── do1
4093 * │       │   ├── fl3
4094 * │       │   ├── fo2
4095 * │       │   └── fu3
4096 * │       ├── du1
4097 * │       │   └── fu2
4098 * │       ├── fl1
4099 * │       ├── fo1
4100 * │       └── fu1
4101 * └── upper
4102 *     ├── data
4103 *     │   ├── do1
4104 *     │   │   ├── fo2
4105 *     │   │   └── fu3
4106 *     │   ├── du1
4107 *     │   │   └── fu2
4108 *     │   ├── fo1
4109 *     │   └── fu1
4110 *     └── work
4111 *         └── work
4112 */
4113
4114FIXTURE(layout2_overlay)
4115{
4116	bool skip_test;
4117};
4118
4119FIXTURE_SETUP(layout2_overlay)
4120{
4121	if (!supports_filesystem("overlay")) {
4122		self->skip_test = true;
4123		SKIP(return, "overlayfs is not supported (setup)");
4124	}
4125
4126	prepare_layout(_metadata);
4127
4128	create_directory(_metadata, LOWER_BASE);
4129	set_cap(_metadata, CAP_SYS_ADMIN);
4130	/* Creates tmpfs mount points to get deterministic overlayfs. */
4131	ASSERT_EQ(0, mount_opt(&mnt_tmp, LOWER_BASE));
4132	clear_cap(_metadata, CAP_SYS_ADMIN);
4133	create_file(_metadata, lower_fl1);
4134	create_file(_metadata, lower_dl1_fl2);
4135	create_file(_metadata, lower_fo1);
4136	create_file(_metadata, lower_do1_fo2);
4137	create_file(_metadata, lower_do1_fl3);
4138
4139	create_directory(_metadata, UPPER_BASE);
4140	set_cap(_metadata, CAP_SYS_ADMIN);
4141	ASSERT_EQ(0, mount_opt(&mnt_tmp, UPPER_BASE));
4142	clear_cap(_metadata, CAP_SYS_ADMIN);
4143	create_file(_metadata, upper_fu1);
4144	create_file(_metadata, upper_du1_fu2);
4145	create_file(_metadata, upper_fo1);
4146	create_file(_metadata, upper_do1_fo2);
4147	create_file(_metadata, upper_do1_fu3);
4148	ASSERT_EQ(0, mkdir(UPPER_WORK, 0700));
4149
4150	create_directory(_metadata, MERGE_DATA);
4151	set_cap(_metadata, CAP_SYS_ADMIN);
4152	set_cap(_metadata, CAP_DAC_OVERRIDE);
4153	ASSERT_EQ(0, mount("overlay", MERGE_DATA, "overlay", 0,
4154			   "lowerdir=" LOWER_DATA ",upperdir=" UPPER_DATA
4155			   ",workdir=" UPPER_WORK));
4156	clear_cap(_metadata, CAP_DAC_OVERRIDE);
4157	clear_cap(_metadata, CAP_SYS_ADMIN);
4158}
4159
4160FIXTURE_TEARDOWN(layout2_overlay)
4161{
4162	if (self->skip_test)
4163		SKIP(return, "overlayfs is not supported (teardown)");
4164
4165	EXPECT_EQ(0, remove_path(lower_do1_fl3));
4166	EXPECT_EQ(0, remove_path(lower_dl1_fl2));
4167	EXPECT_EQ(0, remove_path(lower_fl1));
4168	EXPECT_EQ(0, remove_path(lower_do1_fo2));
4169	EXPECT_EQ(0, remove_path(lower_fo1));
4170	set_cap(_metadata, CAP_SYS_ADMIN);
4171	EXPECT_EQ(0, umount(LOWER_BASE));
4172	clear_cap(_metadata, CAP_SYS_ADMIN);
4173	EXPECT_EQ(0, remove_path(LOWER_BASE));
4174
4175	EXPECT_EQ(0, remove_path(upper_do1_fu3));
4176	EXPECT_EQ(0, remove_path(upper_du1_fu2));
4177	EXPECT_EQ(0, remove_path(upper_fu1));
4178	EXPECT_EQ(0, remove_path(upper_do1_fo2));
4179	EXPECT_EQ(0, remove_path(upper_fo1));
4180	EXPECT_EQ(0, remove_path(UPPER_WORK "/work"));
4181	set_cap(_metadata, CAP_SYS_ADMIN);
4182	EXPECT_EQ(0, umount(UPPER_BASE));
4183	clear_cap(_metadata, CAP_SYS_ADMIN);
4184	EXPECT_EQ(0, remove_path(UPPER_BASE));
4185
4186	set_cap(_metadata, CAP_SYS_ADMIN);
4187	EXPECT_EQ(0, umount(MERGE_DATA));
4188	clear_cap(_metadata, CAP_SYS_ADMIN);
4189	EXPECT_EQ(0, remove_path(MERGE_DATA));
4190
4191	cleanup_layout(_metadata);
4192}
4193
4194TEST_F_FORK(layout2_overlay, no_restriction)
4195{
4196	if (self->skip_test)
4197		SKIP(return, "overlayfs is not supported (test)");
4198
4199	ASSERT_EQ(0, test_open(lower_fl1, O_RDONLY));
4200	ASSERT_EQ(0, test_open(lower_dl1, O_RDONLY));
4201	ASSERT_EQ(0, test_open(lower_dl1_fl2, O_RDONLY));
4202	ASSERT_EQ(0, test_open(lower_fo1, O_RDONLY));
4203	ASSERT_EQ(0, test_open(lower_do1, O_RDONLY));
4204	ASSERT_EQ(0, test_open(lower_do1_fo2, O_RDONLY));
4205	ASSERT_EQ(0, test_open(lower_do1_fl3, O_RDONLY));
4206
4207	ASSERT_EQ(0, test_open(upper_fu1, O_RDONLY));
4208	ASSERT_EQ(0, test_open(upper_du1, O_RDONLY));
4209	ASSERT_EQ(0, test_open(upper_du1_fu2, O_RDONLY));
4210	ASSERT_EQ(0, test_open(upper_fo1, O_RDONLY));
4211	ASSERT_EQ(0, test_open(upper_do1, O_RDONLY));
4212	ASSERT_EQ(0, test_open(upper_do1_fo2, O_RDONLY));
4213	ASSERT_EQ(0, test_open(upper_do1_fu3, O_RDONLY));
4214
4215	ASSERT_EQ(0, test_open(merge_fl1, O_RDONLY));
4216	ASSERT_EQ(0, test_open(merge_dl1, O_RDONLY));
4217	ASSERT_EQ(0, test_open(merge_dl1_fl2, O_RDONLY));
4218	ASSERT_EQ(0, test_open(merge_fu1, O_RDONLY));
4219	ASSERT_EQ(0, test_open(merge_du1, O_RDONLY));
4220	ASSERT_EQ(0, test_open(merge_du1_fu2, O_RDONLY));
4221	ASSERT_EQ(0, test_open(merge_fo1, O_RDONLY));
4222	ASSERT_EQ(0, test_open(merge_do1, O_RDONLY));
4223	ASSERT_EQ(0, test_open(merge_do1_fo2, O_RDONLY));
4224	ASSERT_EQ(0, test_open(merge_do1_fl3, O_RDONLY));
4225	ASSERT_EQ(0, test_open(merge_do1_fu3, O_RDONLY));
4226}
4227
4228#define for_each_path(path_list, path_entry, i)               \
4229	for (i = 0, path_entry = *path_list[i]; path_list[i]; \
4230	     path_entry = *path_list[++i])
4231
4232TEST_F_FORK(layout2_overlay, same_content_different_file)
4233{
4234	/* Sets access right on parent directories of both layers. */
4235	const struct rule layer1_base[] = {
4236		{
4237			.path = LOWER_BASE,
4238			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4239		},
4240		{
4241			.path = UPPER_BASE,
4242			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4243		},
4244		{
4245			.path = MERGE_BASE,
4246			.access = ACCESS_RW,
4247		},
4248		{},
4249	};
4250	const struct rule layer2_data[] = {
4251		{
4252			.path = LOWER_DATA,
4253			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4254		},
4255		{
4256			.path = UPPER_DATA,
4257			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4258		},
4259		{
4260			.path = MERGE_DATA,
4261			.access = ACCESS_RW,
4262		},
4263		{},
4264	};
4265	/* Sets access right on directories inside both layers. */
4266	const struct rule layer3_subdirs[] = {
4267		{
4268			.path = lower_dl1,
4269			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4270		},
4271		{
4272			.path = lower_do1,
4273			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4274		},
4275		{
4276			.path = upper_du1,
4277			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4278		},
4279		{
4280			.path = upper_do1,
4281			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4282		},
4283		{
4284			.path = merge_dl1,
4285			.access = ACCESS_RW,
4286		},
4287		{
4288			.path = merge_du1,
4289			.access = ACCESS_RW,
4290		},
4291		{
4292			.path = merge_do1,
4293			.access = ACCESS_RW,
4294		},
4295		{},
4296	};
4297	/* Tighten access rights to the files. */
4298	const struct rule layer4_files[] = {
4299		{
4300			.path = lower_dl1_fl2,
4301			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4302		},
4303		{
4304			.path = lower_do1_fo2,
4305			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4306		},
4307		{
4308			.path = lower_do1_fl3,
4309			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4310		},
4311		{
4312			.path = upper_du1_fu2,
4313			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4314		},
4315		{
4316			.path = upper_do1_fo2,
4317			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4318		},
4319		{
4320			.path = upper_do1_fu3,
4321			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4322		},
4323		{
4324			.path = merge_dl1_fl2,
4325			.access = LANDLOCK_ACCESS_FS_READ_FILE |
4326				  LANDLOCK_ACCESS_FS_WRITE_FILE,
4327		},
4328		{
4329			.path = merge_du1_fu2,
4330			.access = LANDLOCK_ACCESS_FS_READ_FILE |
4331				  LANDLOCK_ACCESS_FS_WRITE_FILE,
4332		},
4333		{
4334			.path = merge_do1_fo2,
4335			.access = LANDLOCK_ACCESS_FS_READ_FILE |
4336				  LANDLOCK_ACCESS_FS_WRITE_FILE,
4337		},
4338		{
4339			.path = merge_do1_fl3,
4340			.access = LANDLOCK_ACCESS_FS_READ_FILE |
4341				  LANDLOCK_ACCESS_FS_WRITE_FILE,
4342		},
4343		{
4344			.path = merge_do1_fu3,
4345			.access = LANDLOCK_ACCESS_FS_READ_FILE |
4346				  LANDLOCK_ACCESS_FS_WRITE_FILE,
4347		},
4348		{},
4349	};
4350	const struct rule layer5_merge_only[] = {
4351		{
4352			.path = MERGE_DATA,
4353			.access = LANDLOCK_ACCESS_FS_READ_FILE |
4354				  LANDLOCK_ACCESS_FS_WRITE_FILE,
4355		},
4356		{},
4357	};
4358	int ruleset_fd;
4359	size_t i;
4360	const char *path_entry;
4361
4362	if (self->skip_test)
4363		SKIP(return, "overlayfs is not supported (test)");
4364
4365	/* Sets rules on base directories (i.e. outside overlay scope). */
4366	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_base);
4367	ASSERT_LE(0, ruleset_fd);
4368	enforce_ruleset(_metadata, ruleset_fd);
4369	ASSERT_EQ(0, close(ruleset_fd));
4370
4371	/* Checks lower layer. */
4372	for_each_path(lower_base_files, path_entry, i) {
4373		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
4374		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
4375	}
4376	for_each_path(lower_base_directories, path_entry, i) {
4377		ASSERT_EQ(EACCES,
4378			  test_open(path_entry, O_RDONLY | O_DIRECTORY));
4379	}
4380	for_each_path(lower_sub_files, path_entry, i) {
4381		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
4382		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
4383	}
4384	/* Checks upper layer. */
4385	for_each_path(upper_base_files, path_entry, i) {
4386		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
4387		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
4388	}
4389	for_each_path(upper_base_directories, path_entry, i) {
4390		ASSERT_EQ(EACCES,
4391			  test_open(path_entry, O_RDONLY | O_DIRECTORY));
4392	}
4393	for_each_path(upper_sub_files, path_entry, i) {
4394		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
4395		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
4396	}
4397	/*
4398	 * Checks that access rights are independent from the lower and upper
4399	 * layers: write access to upper files viewed through the merge point
4400	 * is still allowed, and write access to lower file viewed (and copied)
4401	 * through the merge point is still allowed.
4402	 */
4403	for_each_path(merge_base_files, path_entry, i) {
4404		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
4405	}
4406	for_each_path(merge_base_directories, path_entry, i) {
4407		ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
4408	}
4409	for_each_path(merge_sub_files, path_entry, i) {
4410		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
4411	}
4412
4413	/* Sets rules on data directories (i.e. inside overlay scope). */
4414	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_data);
4415	ASSERT_LE(0, ruleset_fd);
4416	enforce_ruleset(_metadata, ruleset_fd);
4417	ASSERT_EQ(0, close(ruleset_fd));
4418
4419	/* Checks merge. */
4420	for_each_path(merge_base_files, path_entry, i) {
4421		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
4422	}
4423	for_each_path(merge_base_directories, path_entry, i) {
4424		ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
4425	}
4426	for_each_path(merge_sub_files, path_entry, i) {
4427		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
4428	}
4429
4430	/* Same checks with tighter rules. */
4431	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3_subdirs);
4432	ASSERT_LE(0, ruleset_fd);
4433	enforce_ruleset(_metadata, ruleset_fd);
4434	ASSERT_EQ(0, close(ruleset_fd));
4435
4436	/* Checks changes for lower layer. */
4437	for_each_path(lower_base_files, path_entry, i) {
4438		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
4439	}
4440	/* Checks changes for upper layer. */
4441	for_each_path(upper_base_files, path_entry, i) {
4442		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
4443	}
4444	/* Checks all merge accesses. */
4445	for_each_path(merge_base_files, path_entry, i) {
4446		ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
4447	}
4448	for_each_path(merge_base_directories, path_entry, i) {
4449		ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
4450	}
4451	for_each_path(merge_sub_files, path_entry, i) {
4452		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
4453	}
4454
4455	/* Sets rules directly on overlayed files. */
4456	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer4_files);
4457	ASSERT_LE(0, ruleset_fd);
4458	enforce_ruleset(_metadata, ruleset_fd);
4459	ASSERT_EQ(0, close(ruleset_fd));
4460
4461	/* Checks unchanged accesses on lower layer. */
4462	for_each_path(lower_sub_files, path_entry, i) {
4463		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
4464		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
4465	}
4466	/* Checks unchanged accesses on upper layer. */
4467	for_each_path(upper_sub_files, path_entry, i) {
4468		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
4469		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
4470	}
4471	/* Checks all merge accesses. */
4472	for_each_path(merge_base_files, path_entry, i) {
4473		ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
4474	}
4475	for_each_path(merge_base_directories, path_entry, i) {
4476		ASSERT_EQ(EACCES,
4477			  test_open(path_entry, O_RDONLY | O_DIRECTORY));
4478	}
4479	for_each_path(merge_sub_files, path_entry, i) {
4480		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
4481	}
4482
4483	/* Only allowes access to the merge hierarchy. */
4484	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer5_merge_only);
4485	ASSERT_LE(0, ruleset_fd);
4486	enforce_ruleset(_metadata, ruleset_fd);
4487	ASSERT_EQ(0, close(ruleset_fd));
4488
4489	/* Checks new accesses on lower layer. */
4490	for_each_path(lower_sub_files, path_entry, i) {
4491		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
4492	}
4493	/* Checks new accesses on upper layer. */
4494	for_each_path(upper_sub_files, path_entry, i) {
4495		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
4496	}
4497	/* Checks all merge accesses. */
4498	for_each_path(merge_base_files, path_entry, i) {
4499		ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
4500	}
4501	for_each_path(merge_base_directories, path_entry, i) {
4502		ASSERT_EQ(EACCES,
4503			  test_open(path_entry, O_RDONLY | O_DIRECTORY));
4504	}
4505	for_each_path(merge_sub_files, path_entry, i) {
4506		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
4507	}
4508}
4509
4510FIXTURE(layout3_fs)
4511{
4512	bool has_created_dir;
4513	bool has_created_file;
4514	char *dir_path;
4515	bool skip_test;
4516};
4517
4518FIXTURE_VARIANT(layout3_fs)
4519{
4520	const struct mnt_opt mnt;
4521	const char *const file_path;
4522	unsigned int cwd_fs_magic;
4523};
4524
4525/* clang-format off */
4526FIXTURE_VARIANT_ADD(layout3_fs, tmpfs) {
4527	/* clang-format on */
4528	.mnt = {
4529		.type = "tmpfs",
4530		.data = MNT_TMP_DATA,
4531	},
4532	.file_path = file1_s1d1,
4533};
4534
4535FIXTURE_VARIANT_ADD(layout3_fs, ramfs) {
4536	.mnt = {
4537		.type = "ramfs",
4538		.data = "mode=700",
4539	},
4540	.file_path = TMP_DIR "/dir/file",
4541};
4542
4543FIXTURE_VARIANT_ADD(layout3_fs, cgroup2) {
4544	.mnt = {
4545		.type = "cgroup2",
4546	},
4547	.file_path = TMP_DIR "/test/cgroup.procs",
4548};
4549
4550FIXTURE_VARIANT_ADD(layout3_fs, proc) {
4551	.mnt = {
4552		.type = "proc",
4553	},
4554	.file_path = TMP_DIR "/self/status",
4555};
4556
4557FIXTURE_VARIANT_ADD(layout3_fs, sysfs) {
4558	.mnt = {
4559		.type = "sysfs",
4560	},
4561	.file_path = TMP_DIR "/kernel/notes",
4562};
4563
4564FIXTURE_VARIANT_ADD(layout3_fs, hostfs) {
4565	.mnt = {
4566		.source = TMP_DIR,
4567		.flags = MS_BIND,
4568	},
4569	.file_path = TMP_DIR "/dir/file",
4570	.cwd_fs_magic = HOSTFS_SUPER_MAGIC,
4571};
4572
4573FIXTURE_SETUP(layout3_fs)
4574{
4575	struct stat statbuf;
4576	const char *slash;
4577	size_t dir_len;
4578
4579	if (!supports_filesystem(variant->mnt.type) ||
4580	    !cwd_matches_fs(variant->cwd_fs_magic)) {
4581		self->skip_test = true;
4582		SKIP(return, "this filesystem is not supported (setup)");
4583	}
4584
4585	slash = strrchr(variant->file_path, '/');
4586	ASSERT_NE(slash, NULL);
4587	dir_len = (size_t)slash - (size_t)variant->file_path;
4588	ASSERT_LT(0, dir_len);
4589	self->dir_path = malloc(dir_len + 1);
4590	self->dir_path[dir_len] = '\0';
4591	strncpy(self->dir_path, variant->file_path, dir_len);
4592
4593	prepare_layout_opt(_metadata, &variant->mnt);
4594
4595	/* Creates directory when required. */
4596	if (stat(self->dir_path, &statbuf)) {
4597		set_cap(_metadata, CAP_DAC_OVERRIDE);
4598		EXPECT_EQ(0, mkdir(self->dir_path, 0700))
4599		{
4600			TH_LOG("Failed to create directory \"%s\": %s",
4601			       self->dir_path, strerror(errno));
4602			free(self->dir_path);
4603			self->dir_path = NULL;
4604		}
4605		self->has_created_dir = true;
4606		clear_cap(_metadata, CAP_DAC_OVERRIDE);
4607	}
4608
4609	/* Creates file when required. */
4610	if (stat(variant->file_path, &statbuf)) {
4611		int fd;
4612
4613		set_cap(_metadata, CAP_DAC_OVERRIDE);
4614		fd = creat(variant->file_path, 0600);
4615		EXPECT_LE(0, fd)
4616		{
4617			TH_LOG("Failed to create file \"%s\": %s",
4618			       variant->file_path, strerror(errno));
4619		}
4620		EXPECT_EQ(0, close(fd));
4621		self->has_created_file = true;
4622		clear_cap(_metadata, CAP_DAC_OVERRIDE);
4623	}
4624}
4625
4626FIXTURE_TEARDOWN(layout3_fs)
4627{
4628	if (self->skip_test)
4629		SKIP(return, "this filesystem is not supported (teardown)");
4630
4631	if (self->has_created_file) {
4632		set_cap(_metadata, CAP_DAC_OVERRIDE);
4633		/*
4634		 * Don't check for error because the file might already
4635		 * have been removed (cf. release_inode test).
4636		 */
4637		unlink(variant->file_path);
4638		clear_cap(_metadata, CAP_DAC_OVERRIDE);
4639	}
4640
4641	if (self->has_created_dir) {
4642		set_cap(_metadata, CAP_DAC_OVERRIDE);
4643		/*
4644		 * Don't check for error because the directory might already
4645		 * have been removed (cf. release_inode test).
4646		 */
4647		rmdir(self->dir_path);
4648		clear_cap(_metadata, CAP_DAC_OVERRIDE);
4649	}
4650	free(self->dir_path);
4651	self->dir_path = NULL;
4652
4653	cleanup_layout(_metadata);
4654}
4655
4656static void layer3_fs_tag_inode(struct __test_metadata *const _metadata,
4657				FIXTURE_DATA(layout3_fs) * self,
4658				const FIXTURE_VARIANT(layout3_fs) * variant,
4659				const char *const rule_path)
4660{
4661	const struct rule layer1_allow_read_file[] = {
4662		{
4663			.path = rule_path,
4664			.access = LANDLOCK_ACCESS_FS_READ_FILE,
4665		},
4666		{},
4667	};
4668	const struct landlock_ruleset_attr layer2_deny_everything_attr = {
4669		.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
4670	};
4671	const char *const dev_null_path = "/dev/null";
4672	int ruleset_fd;
4673
4674	if (self->skip_test)
4675		SKIP(return, "this filesystem is not supported (test)");
4676
4677	/* Checks without Landlock. */
4678	EXPECT_EQ(0, test_open(dev_null_path, O_RDONLY | O_CLOEXEC));
4679	EXPECT_EQ(0, test_open(variant->file_path, O_RDONLY | O_CLOEXEC));
4680
4681	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
4682				    layer1_allow_read_file);
4683	EXPECT_LE(0, ruleset_fd);
4684	enforce_ruleset(_metadata, ruleset_fd);
4685	EXPECT_EQ(0, close(ruleset_fd));
4686
4687	EXPECT_EQ(EACCES, test_open(dev_null_path, O_RDONLY | O_CLOEXEC));
4688	EXPECT_EQ(0, test_open(variant->file_path, O_RDONLY | O_CLOEXEC));
4689
4690	/* Forbids directory reading. */
4691	ruleset_fd =
4692		landlock_create_ruleset(&layer2_deny_everything_attr,
4693					sizeof(layer2_deny_everything_attr), 0);
4694	EXPECT_LE(0, ruleset_fd);
4695	enforce_ruleset(_metadata, ruleset_fd);
4696	EXPECT_EQ(0, close(ruleset_fd));
4697
4698	/* Checks with Landlock and forbidden access. */
4699	EXPECT_EQ(EACCES, test_open(dev_null_path, O_RDONLY | O_CLOEXEC));
4700	EXPECT_EQ(EACCES, test_open(variant->file_path, O_RDONLY | O_CLOEXEC));
4701}
4702
4703/* Matrix of tests to check file hierarchy evaluation. */
4704
4705TEST_F_FORK(layout3_fs, tag_inode_dir_parent)
4706{
4707	/* The current directory must not be the root for this test. */
4708	layer3_fs_tag_inode(_metadata, self, variant, ".");
4709}
4710
4711TEST_F_FORK(layout3_fs, tag_inode_dir_mnt)
4712{
4713	layer3_fs_tag_inode(_metadata, self, variant, TMP_DIR);
4714}
4715
4716TEST_F_FORK(layout3_fs, tag_inode_dir_child)
4717{
4718	layer3_fs_tag_inode(_metadata, self, variant, self->dir_path);
4719}
4720
4721TEST_F_FORK(layout3_fs, tag_inode_file)
4722{
4723	layer3_fs_tag_inode(_metadata, self, variant, variant->file_path);
4724}
4725
4726/* Light version of layout1.release_inodes */
4727TEST_F_FORK(layout3_fs, release_inodes)
4728{
4729	const struct rule layer1[] = {
4730		{
4731			.path = TMP_DIR,
4732			.access = LANDLOCK_ACCESS_FS_READ_DIR,
4733		},
4734		{},
4735	};
4736	int ruleset_fd;
4737
4738	if (self->skip_test)
4739		SKIP(return, "this filesystem is not supported (test)");
4740
4741	/* Clean up for the teardown to not fail. */
4742	if (self->has_created_file)
4743		EXPECT_EQ(0, remove_path(variant->file_path));
4744
4745	if (self->has_created_dir)
4746		/* Don't check for error because of cgroup specificities. */
4747		remove_path(self->dir_path);
4748
4749	ruleset_fd =
4750		create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_DIR, layer1);
4751	ASSERT_LE(0, ruleset_fd);
4752
4753	/* Unmount the filesystem while it is being used by a ruleset. */
4754	set_cap(_metadata, CAP_SYS_ADMIN);
4755	ASSERT_EQ(0, umount(TMP_DIR));
4756	clear_cap(_metadata, CAP_SYS_ADMIN);
4757
4758	/* Replaces with a new mount point to simplify FIXTURE_TEARDOWN. */
4759	set_cap(_metadata, CAP_SYS_ADMIN);
4760	ASSERT_EQ(0, mount_opt(&mnt_tmp, TMP_DIR));
4761	clear_cap(_metadata, CAP_SYS_ADMIN);
4762
4763	enforce_ruleset(_metadata, ruleset_fd);
4764	ASSERT_EQ(0, close(ruleset_fd));
4765
4766	/* Checks that access to the new mount point is denied. */
4767	ASSERT_EQ(EACCES, test_open(TMP_DIR, O_RDONLY));
4768}
4769
4770TEST_HARNESS_MAIN
4771