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