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