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