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