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-2021 Microsoft Corporation
8  */
9 
10 #define _GNU_SOURCE
11 #include <fcntl.h>
12 #include <linux/landlock.h>
13 #include <sched.h>
14 #include <string.h>
15 #include <sys/capability.h>
16 #include <sys/mount.h>
17 #include <sys/prctl.h>
18 #include <sys/sendfile.h>
19 #include <sys/stat.h>
20 #include <sys/sysmacros.h>
21 #include <unistd.h>
22 
23 #include "common.h"
24 
25 #define TMP_DIR		"tmp"
26 #define BINARY_PATH	"./true"
27 
28 /* Paths (sibling number and depth) */
29 static const char dir_s1d1[] = TMP_DIR "/s1d1";
30 static const char file1_s1d1[] = TMP_DIR "/s1d1/f1";
31 static const char file2_s1d1[] = TMP_DIR "/s1d1/f2";
32 static const char dir_s1d2[] = TMP_DIR "/s1d1/s1d2";
33 static const char file1_s1d2[] = TMP_DIR "/s1d1/s1d2/f1";
34 static const char file2_s1d2[] = TMP_DIR "/s1d1/s1d2/f2";
35 static const char dir_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3";
36 static const char file1_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f1";
37 static const char file2_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f2";
38 
39 static const char dir_s2d1[] = TMP_DIR "/s2d1";
40 static const char file1_s2d1[] = TMP_DIR "/s2d1/f1";
41 static const char dir_s2d2[] = TMP_DIR "/s2d1/s2d2";
42 static const char file1_s2d2[] = TMP_DIR "/s2d1/s2d2/f1";
43 static const char dir_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3";
44 static const char file1_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f1";
45 static const char file2_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f2";
46 
47 static const char dir_s3d1[] = TMP_DIR "/s3d1";
48 /* dir_s3d2 is a mount point. */
49 static const char dir_s3d2[] = TMP_DIR "/s3d1/s3d2";
50 static const char dir_s3d3[] = TMP_DIR "/s3d1/s3d2/s3d3";
51 
52 /*
53  * layout1 hierarchy:
54  *
55  * tmp
56  * ├── s1d1
57  * │   ├── f1
58  * │   ├── f2
59  * │   └── s1d2
60  * │       ├── f1
61  * │       ├── f2
62  * │       └── s1d3
63  * │           ├── f1
64  * │           └── f2
65  * ├── s2d1
66  * │   ├── f1
67  * │   └── s2d2
68  * │       ├── f1
69  * │       └── s2d3
70  * │           ├── f1
71  * │           └── f2
72  * └── s3d1
73  *     └── s3d2
74  *         └── s3d3
75  */
76 
mkdir_parents(struct __test_metadata * const _metadata,const char * const path)77 static void mkdir_parents(struct __test_metadata *const _metadata,
78 		const char *const path)
79 {
80 	char *walker;
81 	const char *parent;
82 	int i, err;
83 
84 	ASSERT_NE(path[0], '\0');
85 	walker = strdup(path);
86 	ASSERT_NE(NULL, walker);
87 	parent = walker;
88 	for (i = 1; walker[i]; i++) {
89 		if (walker[i] != '/')
90 			continue;
91 		walker[i] = '\0';
92 		err = mkdir(parent, 0700);
93 		ASSERT_FALSE(err && errno != EEXIST) {
94 			TH_LOG("Failed to create directory \"%s\": %s",
95 					parent, strerror(errno));
96 		}
97 		walker[i] = '/';
98 	}
99 	free(walker);
100 }
101 
create_directory(struct __test_metadata * const _metadata,const char * const path)102 static void create_directory(struct __test_metadata *const _metadata,
103 		const char *const path)
104 {
105 	mkdir_parents(_metadata, path);
106 	ASSERT_EQ(0, mkdir(path, 0700)) {
107 		TH_LOG("Failed to create directory \"%s\": %s", path,
108 				strerror(errno));
109 	}
110 }
111 
create_file(struct __test_metadata * const _metadata,const char * const path)112 static void create_file(struct __test_metadata *const _metadata,
113 		const char *const path)
114 {
115 	mkdir_parents(_metadata, path);
116 	ASSERT_EQ(0, mknod(path, S_IFREG | 0700, 0)) {
117 		TH_LOG("Failed to create file \"%s\": %s", path,
118 				strerror(errno));
119 	}
120 }
121 
remove_path(const char * const path)122 static int remove_path(const char *const path)
123 {
124 	char *walker;
125 	int i, ret, err = 0;
126 
127 	walker = strdup(path);
128 	if (!walker) {
129 		err = ENOMEM;
130 		goto out;
131 	}
132 	if (unlink(path) && rmdir(path)) {
133 		if (errno != ENOENT)
134 			err = errno;
135 		goto out;
136 	}
137 	for (i = strlen(walker); i > 0; i--) {
138 		if (walker[i] != '/')
139 			continue;
140 		walker[i] = '\0';
141 		ret = rmdir(walker);
142 		if (ret) {
143 			if (errno != ENOTEMPTY && errno != EBUSY)
144 				err = errno;
145 			goto out;
146 		}
147 		if (strcmp(walker, TMP_DIR) == 0)
148 			goto out;
149 	}
150 
151 out:
152 	free(walker);
153 	return err;
154 }
155 
prepare_layout(struct __test_metadata * const _metadata)156 static void prepare_layout(struct __test_metadata *const _metadata)
157 {
158 	disable_caps(_metadata);
159 	umask(0077);
160 	create_directory(_metadata, TMP_DIR);
161 
162 	/*
163 	 * Do not pollute the rest of the system: creates a private mount point
164 	 * for tests relying on pivot_root(2) and move_mount(2).
165 	 */
166 	set_cap(_metadata, CAP_SYS_ADMIN);
167 	ASSERT_EQ(0, unshare(CLONE_NEWNS));
168 	ASSERT_EQ(0, mount("tmp", TMP_DIR, "tmpfs", 0, "size=4m,mode=700"));
169 	ASSERT_EQ(0, mount(NULL, TMP_DIR, NULL, MS_PRIVATE | MS_REC, NULL));
170 	clear_cap(_metadata, CAP_SYS_ADMIN);
171 }
172 
cleanup_layout(struct __test_metadata * const _metadata)173 static void cleanup_layout(struct __test_metadata *const _metadata)
174 {
175 	set_cap(_metadata, CAP_SYS_ADMIN);
176 	EXPECT_EQ(0, umount(TMP_DIR));
177 	clear_cap(_metadata, CAP_SYS_ADMIN);
178 	EXPECT_EQ(0, remove_path(TMP_DIR));
179 }
180 
create_layout1(struct __test_metadata * const _metadata)181 static void create_layout1(struct __test_metadata *const _metadata)
182 {
183 	create_file(_metadata, file1_s1d1);
184 	create_file(_metadata, file1_s1d2);
185 	create_file(_metadata, file1_s1d3);
186 	create_file(_metadata, file2_s1d1);
187 	create_file(_metadata, file2_s1d2);
188 	create_file(_metadata, file2_s1d3);
189 
190 	create_file(_metadata, file1_s2d1);
191 	create_file(_metadata, file1_s2d2);
192 	create_file(_metadata, file1_s2d3);
193 	create_file(_metadata, file2_s2d3);
194 
195 	create_directory(_metadata, dir_s3d2);
196 	set_cap(_metadata, CAP_SYS_ADMIN);
197 	ASSERT_EQ(0, mount("tmp", dir_s3d2, "tmpfs", 0, "size=4m,mode=700"));
198 	clear_cap(_metadata, CAP_SYS_ADMIN);
199 
200 	ASSERT_EQ(0, mkdir(dir_s3d3, 0700));
201 }
202 
remove_layout1(struct __test_metadata * const _metadata)203 static void remove_layout1(struct __test_metadata *const _metadata)
204 {
205 	EXPECT_EQ(0, remove_path(file2_s1d3));
206 	EXPECT_EQ(0, remove_path(file2_s1d2));
207 	EXPECT_EQ(0, remove_path(file2_s1d1));
208 	EXPECT_EQ(0, remove_path(file1_s1d3));
209 	EXPECT_EQ(0, remove_path(file1_s1d2));
210 	EXPECT_EQ(0, remove_path(file1_s1d1));
211 
212 	EXPECT_EQ(0, remove_path(file2_s2d3));
213 	EXPECT_EQ(0, remove_path(file1_s2d3));
214 	EXPECT_EQ(0, remove_path(file1_s2d2));
215 	EXPECT_EQ(0, remove_path(file1_s2d1));
216 
217 	EXPECT_EQ(0, remove_path(dir_s3d3));
218 	set_cap(_metadata, CAP_SYS_ADMIN);
219 	umount(dir_s3d2);
220 	clear_cap(_metadata, CAP_SYS_ADMIN);
221 	EXPECT_EQ(0, remove_path(dir_s3d2));
222 }
223 
FIXTURE(layout1)224 FIXTURE(layout1) {
225 };
226 
FIXTURE_SETUP(layout1)227 FIXTURE_SETUP(layout1)
228 {
229 	prepare_layout(_metadata);
230 
231 	create_layout1(_metadata);
232 }
233 
FIXTURE_TEARDOWN(layout1)234 FIXTURE_TEARDOWN(layout1)
235 {
236 	remove_layout1(_metadata);
237 
238 	cleanup_layout(_metadata);
239 }
240 
241 /*
242  * This helper enables to use the ASSERT_* macros and print the line number
243  * pointing to the test caller.
244  */
test_open_rel(const int dirfd,const char * const path,const int flags)245 static int test_open_rel(const int dirfd, const char *const path, const int flags)
246 {
247 	int fd;
248 
249 	/* Works with file and directories. */
250 	fd = openat(dirfd, path, flags | O_CLOEXEC);
251 	if (fd < 0)
252 		return errno;
253 	/*
254 	 * Mixing error codes from close(2) and open(2) should not lead to any
255 	 * (access type) confusion for this test.
256 	 */
257 	if (close(fd) != 0)
258 		return errno;
259 	return 0;
260 }
261 
test_open(const char * const path,const int flags)262 static int test_open(const char *const path, const int flags)
263 {
264 	return test_open_rel(AT_FDCWD, path, flags);
265 }
266 
TEST_F_FORK(layout1,no_restriction)267 TEST_F_FORK(layout1, no_restriction)
268 {
269 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
270 	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
271 	ASSERT_EQ(0, test_open(file2_s1d1, O_RDONLY));
272 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
273 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
274 	ASSERT_EQ(0, test_open(file2_s1d2, O_RDONLY));
275 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
276 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
277 
278 	ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
279 	ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
280 	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
281 	ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
282 	ASSERT_EQ(0, test_open(dir_s2d3, O_RDONLY));
283 	ASSERT_EQ(0, test_open(file1_s2d3, O_RDONLY));
284 
285 	ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
286 	ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
287 	ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
288 }
289 
TEST_F_FORK(layout1,inval)290 TEST_F_FORK(layout1, inval)
291 {
292 	struct landlock_path_beneath_attr path_beneath = {
293 		.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
294 			LANDLOCK_ACCESS_FS_WRITE_FILE,
295 		.parent_fd = -1,
296 	};
297 	struct landlock_ruleset_attr ruleset_attr = {
298 		.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |
299 			LANDLOCK_ACCESS_FS_WRITE_FILE,
300 	};
301 	int ruleset_fd;
302 
303 	path_beneath.parent_fd = open(dir_s1d2, O_PATH | O_DIRECTORY |
304 			O_CLOEXEC);
305 	ASSERT_LE(0, path_beneath.parent_fd);
306 
307 	ruleset_fd = open(dir_s1d1, O_PATH | O_DIRECTORY | O_CLOEXEC);
308 	ASSERT_LE(0, ruleset_fd);
309 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
310 				&path_beneath, 0));
311 	/* Returns EBADF because ruleset_fd is not a landlock-ruleset FD. */
312 	ASSERT_EQ(EBADF, errno);
313 	ASSERT_EQ(0, close(ruleset_fd));
314 
315 	ruleset_fd = open(dir_s1d1, O_DIRECTORY | O_CLOEXEC);
316 	ASSERT_LE(0, ruleset_fd);
317 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
318 				&path_beneath, 0));
319 	/* Returns EBADFD because ruleset_fd is not a valid ruleset. */
320 	ASSERT_EQ(EBADFD, errno);
321 	ASSERT_EQ(0, close(ruleset_fd));
322 
323 	/* Gets a real ruleset. */
324 	ruleset_fd = landlock_create_ruleset(&ruleset_attr,
325 			sizeof(ruleset_attr), 0);
326 	ASSERT_LE(0, ruleset_fd);
327 	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
328 				&path_beneath, 0));
329 	ASSERT_EQ(0, close(path_beneath.parent_fd));
330 
331 	/* Tests without O_PATH. */
332 	path_beneath.parent_fd = open(dir_s1d2, O_DIRECTORY | O_CLOEXEC);
333 	ASSERT_LE(0, path_beneath.parent_fd);
334 	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
335 				&path_beneath, 0));
336 	ASSERT_EQ(0, close(path_beneath.parent_fd));
337 
338 	/* Tests with a ruleset FD. */
339 	path_beneath.parent_fd = ruleset_fd;
340 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
341 				&path_beneath, 0));
342 	ASSERT_EQ(EBADFD, errno);
343 
344 	/* Checks unhandled allowed_access. */
345 	path_beneath.parent_fd = open(dir_s1d2, O_PATH | O_DIRECTORY |
346 			O_CLOEXEC);
347 	ASSERT_LE(0, path_beneath.parent_fd);
348 
349 	/* Test with legitimate values. */
350 	path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_EXECUTE;
351 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
352 				&path_beneath, 0));
353 	ASSERT_EQ(EINVAL, errno);
354 	path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_EXECUTE;
355 
356 	/* Test with unknown (64-bits) value. */
357 	path_beneath.allowed_access |= (1ULL << 60);
358 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
359 				&path_beneath, 0));
360 	ASSERT_EQ(EINVAL, errno);
361 	path_beneath.allowed_access &= ~(1ULL << 60);
362 
363 	/* Test with no access. */
364 	path_beneath.allowed_access = 0;
365 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
366 				&path_beneath, 0));
367 	ASSERT_EQ(ENOMSG, errno);
368 	path_beneath.allowed_access &= ~(1ULL << 60);
369 
370 	ASSERT_EQ(0, close(path_beneath.parent_fd));
371 
372 	/* Enforces the ruleset. */
373 	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
374 	ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
375 
376 	ASSERT_EQ(0, close(ruleset_fd));
377 }
378 
379 #define ACCESS_FILE ( \
380 	LANDLOCK_ACCESS_FS_EXECUTE | \
381 	LANDLOCK_ACCESS_FS_WRITE_FILE | \
382 	LANDLOCK_ACCESS_FS_READ_FILE)
383 
384 #define ACCESS_LAST LANDLOCK_ACCESS_FS_MAKE_SYM
385 
386 #define ACCESS_ALL ( \
387 	ACCESS_FILE | \
388 	LANDLOCK_ACCESS_FS_READ_DIR | \
389 	LANDLOCK_ACCESS_FS_REMOVE_DIR | \
390 	LANDLOCK_ACCESS_FS_REMOVE_FILE | \
391 	LANDLOCK_ACCESS_FS_MAKE_CHAR | \
392 	LANDLOCK_ACCESS_FS_MAKE_DIR | \
393 	LANDLOCK_ACCESS_FS_MAKE_REG | \
394 	LANDLOCK_ACCESS_FS_MAKE_SOCK | \
395 	LANDLOCK_ACCESS_FS_MAKE_FIFO | \
396 	LANDLOCK_ACCESS_FS_MAKE_BLOCK | \
397 	ACCESS_LAST)
398 
TEST_F_FORK(layout1,file_access_rights)399 TEST_F_FORK(layout1, file_access_rights)
400 {
401 	__u64 access;
402 	int err;
403 	struct landlock_path_beneath_attr path_beneath = {};
404 	struct landlock_ruleset_attr ruleset_attr = {
405 		.handled_access_fs = ACCESS_ALL,
406 	};
407 	const int ruleset_fd = landlock_create_ruleset(&ruleset_attr,
408 			sizeof(ruleset_attr), 0);
409 
410 	ASSERT_LE(0, ruleset_fd);
411 
412 	/* Tests access rights for files. */
413 	path_beneath.parent_fd = open(file1_s1d2, O_PATH | O_CLOEXEC);
414 	ASSERT_LE(0, path_beneath.parent_fd);
415 	for (access = 1; access <= ACCESS_LAST; access <<= 1) {
416 		path_beneath.allowed_access = access;
417 		err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
418 				&path_beneath, 0);
419 		if ((access | ACCESS_FILE) == ACCESS_FILE) {
420 			ASSERT_EQ(0, err);
421 		} else {
422 			ASSERT_EQ(-1, err);
423 			ASSERT_EQ(EINVAL, errno);
424 		}
425 	}
426 	ASSERT_EQ(0, close(path_beneath.parent_fd));
427 }
428 
add_path_beneath(struct __test_metadata * const _metadata,const int ruleset_fd,const __u64 allowed_access,const char * const path)429 static void add_path_beneath(struct __test_metadata *const _metadata,
430 		const int ruleset_fd, const __u64 allowed_access,
431 		const char *const path)
432 {
433 	struct landlock_path_beneath_attr path_beneath = {
434 		.allowed_access = allowed_access,
435 	};
436 
437 	path_beneath.parent_fd = open(path, O_PATH | O_CLOEXEC);
438 	ASSERT_LE(0, path_beneath.parent_fd) {
439 		TH_LOG("Failed to open directory \"%s\": %s", path,
440 				strerror(errno));
441 	}
442 	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
443 				&path_beneath, 0)) {
444 		TH_LOG("Failed to update the ruleset with \"%s\": %s", path,
445 				strerror(errno));
446 	}
447 	ASSERT_EQ(0, close(path_beneath.parent_fd));
448 }
449 
450 struct rule {
451 	const char *path;
452 	__u64 access;
453 };
454 
455 #define ACCESS_RO ( \
456 	LANDLOCK_ACCESS_FS_READ_FILE | \
457 	LANDLOCK_ACCESS_FS_READ_DIR)
458 
459 #define ACCESS_RW ( \
460 	ACCESS_RO | \
461 	LANDLOCK_ACCESS_FS_WRITE_FILE)
462 
create_ruleset(struct __test_metadata * const _metadata,const __u64 handled_access_fs,const struct rule rules[])463 static int create_ruleset(struct __test_metadata *const _metadata,
464 		const __u64 handled_access_fs, const struct rule rules[])
465 {
466 	int ruleset_fd, i;
467 	struct landlock_ruleset_attr ruleset_attr = {
468 		.handled_access_fs = handled_access_fs,
469 	};
470 
471 	ASSERT_NE(NULL, rules) {
472 		TH_LOG("No rule list");
473 	}
474 	ASSERT_NE(NULL, rules[0].path) {
475 		TH_LOG("Empty rule list");
476 	}
477 
478 	ruleset_fd = landlock_create_ruleset(&ruleset_attr,
479 			sizeof(ruleset_attr), 0);
480 	ASSERT_LE(0, ruleset_fd) {
481 		TH_LOG("Failed to create a ruleset: %s", strerror(errno));
482 	}
483 
484 	for (i = 0; rules[i].path; i++) {
485 		add_path_beneath(_metadata, ruleset_fd, rules[i].access,
486 				rules[i].path);
487 	}
488 	return ruleset_fd;
489 }
490 
enforce_ruleset(struct __test_metadata * const _metadata,const int ruleset_fd)491 static void enforce_ruleset(struct __test_metadata *const _metadata,
492 		const int ruleset_fd)
493 {
494 	ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
495 	ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0)) {
496 		TH_LOG("Failed to enforce ruleset: %s", strerror(errno));
497 	}
498 }
499 
TEST_F_FORK(layout1,proc_nsfs)500 TEST_F_FORK(layout1, proc_nsfs)
501 {
502 	const struct rule rules[] = {
503 		{
504 			.path = "/dev/null",
505 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
506 				LANDLOCK_ACCESS_FS_WRITE_FILE,
507 		},
508 		{}
509 	};
510 	struct landlock_path_beneath_attr path_beneath;
511 	const int ruleset_fd = create_ruleset(_metadata, rules[0].access |
512 			LANDLOCK_ACCESS_FS_READ_DIR, rules);
513 
514 	ASSERT_LE(0, ruleset_fd);
515 	ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
516 
517 	enforce_ruleset(_metadata, ruleset_fd);
518 
519 	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
520 	ASSERT_EQ(EACCES, test_open("/dev", O_RDONLY));
521 	ASSERT_EQ(0, test_open("/dev/null", O_RDONLY));
522 	ASSERT_EQ(EACCES, test_open("/dev/full", O_RDONLY));
523 
524 	ASSERT_EQ(EACCES, test_open("/proc", O_RDONLY));
525 	ASSERT_EQ(EACCES, test_open("/proc/self", O_RDONLY));
526 	ASSERT_EQ(EACCES, test_open("/proc/self/ns", O_RDONLY));
527 	/*
528 	 * Because nsfs is an internal filesystem, /proc/self/ns/mnt is a
529 	 * disconnected path.  Such path cannot be identified and must then be
530 	 * allowed.
531 	 */
532 	ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
533 
534 	/*
535 	 * Checks that it is not possible to add nsfs-like filesystem
536 	 * references to a ruleset.
537 	 */
538 	path_beneath.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
539 		LANDLOCK_ACCESS_FS_WRITE_FILE,
540 	path_beneath.parent_fd = open("/proc/self/ns/mnt", O_PATH | O_CLOEXEC);
541 	ASSERT_LE(0, path_beneath.parent_fd);
542 	ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
543 				&path_beneath, 0));
544 	ASSERT_EQ(EBADFD, errno);
545 	ASSERT_EQ(0, close(path_beneath.parent_fd));
546 }
547 
TEST_F_FORK(layout1,unpriv)548 TEST_F_FORK(layout1, unpriv) {
549 	const struct rule rules[] = {
550 		{
551 			.path = dir_s1d2,
552 			.access = ACCESS_RO,
553 		},
554 		{}
555 	};
556 	int ruleset_fd;
557 
558 	drop_caps(_metadata);
559 
560 	ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
561 	ASSERT_LE(0, ruleset_fd);
562 	ASSERT_EQ(-1, landlock_restrict_self(ruleset_fd, 0));
563 	ASSERT_EQ(EPERM, errno);
564 
565 	/* enforce_ruleset() calls prctl(no_new_privs). */
566 	enforce_ruleset(_metadata, ruleset_fd);
567 	ASSERT_EQ(0, close(ruleset_fd));
568 }
569 
TEST_F_FORK(layout1,effective_access)570 TEST_F_FORK(layout1, effective_access)
571 {
572 	const struct rule rules[] = {
573 		{
574 			.path = dir_s1d2,
575 			.access = ACCESS_RO,
576 		},
577 		{
578 			.path = file1_s2d2,
579 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
580 				LANDLOCK_ACCESS_FS_WRITE_FILE,
581 		},
582 		{}
583 	};
584 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
585 	char buf;
586 	int reg_fd;
587 
588 	ASSERT_LE(0, ruleset_fd);
589 	enforce_ruleset(_metadata, ruleset_fd);
590 	ASSERT_EQ(0, close(ruleset_fd));
591 
592 	/* Tests on a directory. */
593 	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
594 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
595 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
596 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
597 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
598 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
599 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
600 
601 	/* Tests on a file. */
602 	ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY));
603 	ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
604 
605 	/* Checks effective read and write actions. */
606 	reg_fd = open(file1_s2d2, O_RDWR | O_CLOEXEC);
607 	ASSERT_LE(0, reg_fd);
608 	ASSERT_EQ(1, write(reg_fd, ".", 1));
609 	ASSERT_LE(0, lseek(reg_fd, 0, SEEK_SET));
610 	ASSERT_EQ(1, read(reg_fd, &buf, 1));
611 	ASSERT_EQ('.', buf);
612 	ASSERT_EQ(0, close(reg_fd));
613 
614 	/* Just in case, double-checks effective actions. */
615 	reg_fd = open(file1_s2d2, O_RDONLY | O_CLOEXEC);
616 	ASSERT_LE(0, reg_fd);
617 	ASSERT_EQ(-1, write(reg_fd, &buf, 1));
618 	ASSERT_EQ(EBADF, errno);
619 	ASSERT_EQ(0, close(reg_fd));
620 }
621 
TEST_F_FORK(layout1,unhandled_access)622 TEST_F_FORK(layout1, unhandled_access)
623 {
624 	const struct rule rules[] = {
625 		{
626 			.path = dir_s1d2,
627 			.access = ACCESS_RO,
628 		},
629 		{}
630 	};
631 	/* Here, we only handle read accesses, not write accesses. */
632 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
633 
634 	ASSERT_LE(0, ruleset_fd);
635 	enforce_ruleset(_metadata, ruleset_fd);
636 	ASSERT_EQ(0, close(ruleset_fd));
637 
638 	/*
639 	 * Because the policy does not handle LANDLOCK_ACCESS_FS_WRITE_FILE,
640 	 * opening for write-only should be allowed, but not read-write.
641 	 */
642 	ASSERT_EQ(0, test_open(file1_s1d1, O_WRONLY));
643 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
644 
645 	ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
646 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
647 }
648 
TEST_F_FORK(layout1,ruleset_overlap)649 TEST_F_FORK(layout1, ruleset_overlap)
650 {
651 	const struct rule rules[] = {
652 		/* These rules should be ORed among them. */
653 		{
654 			.path = dir_s1d2,
655 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
656 				LANDLOCK_ACCESS_FS_WRITE_FILE,
657 		},
658 		{
659 			.path = dir_s1d2,
660 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
661 				LANDLOCK_ACCESS_FS_READ_DIR,
662 		},
663 		{}
664 	};
665 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
666 
667 	ASSERT_LE(0, ruleset_fd);
668 	enforce_ruleset(_metadata, ruleset_fd);
669 	ASSERT_EQ(0, close(ruleset_fd));
670 
671 	/* Checks s1d1 hierarchy. */
672 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
673 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
674 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
675 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
676 
677 	/* Checks s1d2 hierarchy. */
678 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
679 	ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
680 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
681 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
682 
683 	/* Checks s1d3 hierarchy. */
684 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
685 	ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
686 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
687 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
688 }
689 
TEST_F_FORK(layout1,non_overlapping_accesses)690 TEST_F_FORK(layout1, non_overlapping_accesses)
691 {
692 	const struct rule layer1[] = {
693 		{
694 			.path = dir_s1d2,
695 			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
696 		},
697 		{}
698 	};
699 	const struct rule layer2[] = {
700 		{
701 			.path = dir_s1d3,
702 			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
703 		},
704 		{}
705 	};
706 	int ruleset_fd;
707 
708 	ASSERT_EQ(0, unlink(file1_s1d1));
709 	ASSERT_EQ(0, unlink(file1_s1d2));
710 
711 	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG,
712 			layer1);
713 	ASSERT_LE(0, ruleset_fd);
714 	enforce_ruleset(_metadata, ruleset_fd);
715 	ASSERT_EQ(0, close(ruleset_fd));
716 
717 	ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
718 	ASSERT_EQ(EACCES, errno);
719 	ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
720 	ASSERT_EQ(0, unlink(file1_s1d2));
721 
722 	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_REMOVE_FILE,
723 			layer2);
724 	ASSERT_LE(0, ruleset_fd);
725 	enforce_ruleset(_metadata, ruleset_fd);
726 	ASSERT_EQ(0, close(ruleset_fd));
727 
728 	/* Unchanged accesses for file creation. */
729 	ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
730 	ASSERT_EQ(EACCES, errno);
731 	ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
732 
733 	/* Checks file removing. */
734 	ASSERT_EQ(-1, unlink(file1_s1d2));
735 	ASSERT_EQ(EACCES, errno);
736 	ASSERT_EQ(0, unlink(file1_s1d3));
737 }
738 
TEST_F_FORK(layout1,interleaved_masked_accesses)739 TEST_F_FORK(layout1, interleaved_masked_accesses)
740 {
741 	/*
742 	 * Checks overly restrictive rules:
743 	 * layer 1: allows R   s1d1/s1d2/s1d3/file1
744 	 * layer 2: allows RW  s1d1/s1d2/s1d3
745 	 *          allows  W  s1d1/s1d2
746 	 *          denies R   s1d1/s1d2
747 	 * layer 3: allows R   s1d1
748 	 * layer 4: allows R   s1d1/s1d2
749 	 *          denies  W  s1d1/s1d2
750 	 * layer 5: allows R   s1d1/s1d2
751 	 * layer 6: allows   X ----
752 	 * layer 7: allows  W  s1d1/s1d2
753 	 *          denies R   s1d1/s1d2
754 	 */
755 	const struct rule layer1_read[] = {
756 		/* Allows read access to file1_s1d3 with the first layer. */
757 		{
758 			.path = file1_s1d3,
759 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
760 		},
761 		{}
762 	};
763 	/* First rule with write restrictions. */
764 	const struct rule layer2_read_write[] = {
765 		/* Start by granting read-write access via its parent directory... */
766 		{
767 			.path = dir_s1d3,
768 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
769 				LANDLOCK_ACCESS_FS_WRITE_FILE,
770 		},
771 		/* ...but also denies read access via its grandparent directory. */
772 		{
773 			.path = dir_s1d2,
774 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
775 		},
776 		{}
777 	};
778 	const struct rule layer3_read[] = {
779 		/* Allows read access via its great-grandparent directory. */
780 		{
781 			.path = dir_s1d1,
782 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
783 		},
784 		{}
785 	};
786 	const struct rule layer4_read_write[] = {
787 		/*
788 		 * Try to confuse the deny access by denying write (but not
789 		 * read) access via its grandparent directory.
790 		 */
791 		{
792 			.path = dir_s1d2,
793 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
794 		},
795 		{}
796 	};
797 	const struct rule layer5_read[] = {
798 		/*
799 		 * Try to override layer2's deny read access by explicitly
800 		 * allowing read access via file1_s1d3's grandparent.
801 		 */
802 		{
803 			.path = dir_s1d2,
804 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
805 		},
806 		{}
807 	};
808 	const struct rule layer6_execute[] = {
809 		/*
810 		 * Restricts an unrelated file hierarchy with a new access
811 		 * (non-overlapping) type.
812 		 */
813 		{
814 			.path = dir_s2d1,
815 			.access = LANDLOCK_ACCESS_FS_EXECUTE,
816 		},
817 		{}
818 	};
819 	const struct rule layer7_read_write[] = {
820 		/*
821 		 * Finally, denies read access to file1_s1d3 via its
822 		 * grandparent.
823 		 */
824 		{
825 			.path = dir_s1d2,
826 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
827 		},
828 		{}
829 	};
830 	int ruleset_fd;
831 
832 	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
833 			layer1_read);
834 	ASSERT_LE(0, ruleset_fd);
835 	enforce_ruleset(_metadata, ruleset_fd);
836 	ASSERT_EQ(0, close(ruleset_fd));
837 
838 	/* Checks that read access is granted for file1_s1d3 with layer 1. */
839 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
840 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
841 	ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
842 
843 	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE |
844 			LANDLOCK_ACCESS_FS_WRITE_FILE, layer2_read_write);
845 	ASSERT_LE(0, ruleset_fd);
846 	enforce_ruleset(_metadata, ruleset_fd);
847 	ASSERT_EQ(0, close(ruleset_fd));
848 
849 	/* Checks that previous access rights are unchanged with layer 2. */
850 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
851 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
852 	ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
853 
854 	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
855 			layer3_read);
856 	ASSERT_LE(0, ruleset_fd);
857 	enforce_ruleset(_metadata, ruleset_fd);
858 	ASSERT_EQ(0, close(ruleset_fd));
859 
860 	/* Checks that previous access rights are unchanged with layer 3. */
861 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
862 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
863 	ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
864 
865 	/* This time, denies write access for the file hierarchy. */
866 	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE |
867 			LANDLOCK_ACCESS_FS_WRITE_FILE, layer4_read_write);
868 	ASSERT_LE(0, ruleset_fd);
869 	enforce_ruleset(_metadata, ruleset_fd);
870 	ASSERT_EQ(0, close(ruleset_fd));
871 
872 	/*
873 	 * Checks that the only change with layer 4 is that write access is
874 	 * denied.
875 	 */
876 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
877 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
878 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
879 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
880 
881 	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
882 			layer5_read);
883 	ASSERT_LE(0, ruleset_fd);
884 	enforce_ruleset(_metadata, ruleset_fd);
885 	ASSERT_EQ(0, close(ruleset_fd));
886 
887 	/* Checks that previous access rights are unchanged with layer 5. */
888 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
889 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
890 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
891 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
892 
893 	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_EXECUTE,
894 			layer6_execute);
895 	ASSERT_LE(0, ruleset_fd);
896 	enforce_ruleset(_metadata, ruleset_fd);
897 	ASSERT_EQ(0, close(ruleset_fd));
898 
899 	/* Checks that previous access rights are unchanged with layer 6. */
900 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
901 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
902 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
903 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
904 
905 	ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE |
906 			LANDLOCK_ACCESS_FS_WRITE_FILE, layer7_read_write);
907 	ASSERT_LE(0, ruleset_fd);
908 	enforce_ruleset(_metadata, ruleset_fd);
909 	ASSERT_EQ(0, close(ruleset_fd));
910 
911 	/* Checks read access is now denied with layer 7. */
912 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
913 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
914 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
915 	ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
916 }
917 
TEST_F_FORK(layout1,inherit_subset)918 TEST_F_FORK(layout1, inherit_subset)
919 {
920 	const struct rule rules[] = {
921 		{
922 			.path = dir_s1d2,
923 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
924 				LANDLOCK_ACCESS_FS_READ_DIR,
925 		},
926 		{}
927 	};
928 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
929 
930 	ASSERT_LE(0, ruleset_fd);
931 	enforce_ruleset(_metadata, ruleset_fd);
932 
933 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
934 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
935 
936 	/* Write access is forbidden. */
937 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
938 	/* Readdir access is allowed. */
939 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
940 
941 	/* Write access is forbidden. */
942 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
943 	/* Readdir access is allowed. */
944 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
945 
946 	/*
947 	 * Tests shared rule extension: the following rules should not grant
948 	 * any new access, only remove some.  Once enforced, these rules are
949 	 * ANDed with the previous ones.
950 	 */
951 	add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
952 			dir_s1d2);
953 	/*
954 	 * According to ruleset_fd, dir_s1d2 should now have the
955 	 * LANDLOCK_ACCESS_FS_READ_FILE and LANDLOCK_ACCESS_FS_WRITE_FILE
956 	 * access rights (even if this directory is opened a second time).
957 	 * However, when enforcing this updated ruleset, the ruleset tied to
958 	 * the current process (i.e. its domain) will still only have the
959 	 * dir_s1d2 with LANDLOCK_ACCESS_FS_READ_FILE and
960 	 * LANDLOCK_ACCESS_FS_READ_DIR accesses, but
961 	 * LANDLOCK_ACCESS_FS_WRITE_FILE must not be allowed because it would
962 	 * be a privilege escalation.
963 	 */
964 	enforce_ruleset(_metadata, ruleset_fd);
965 
966 	/* Same tests and results as above. */
967 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
968 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
969 
970 	/* It is still forbidden to write in file1_s1d2. */
971 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
972 	/* Readdir access is still allowed. */
973 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
974 
975 	/* It is still forbidden to write in file1_s1d3. */
976 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
977 	/* Readdir access is still allowed. */
978 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
979 
980 	/*
981 	 * Try to get more privileges by adding new access rights to the parent
982 	 * directory: dir_s1d1.
983 	 */
984 	add_path_beneath(_metadata, ruleset_fd, ACCESS_RW, dir_s1d1);
985 	enforce_ruleset(_metadata, ruleset_fd);
986 
987 	/* Same tests and results as above. */
988 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
989 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
990 
991 	/* It is still forbidden to write in file1_s1d2. */
992 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
993 	/* Readdir access is still allowed. */
994 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
995 
996 	/* It is still forbidden to write in file1_s1d3. */
997 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
998 	/* Readdir access is still allowed. */
999 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1000 
1001 	/*
1002 	 * Now, dir_s1d3 get a new rule tied to it, only allowing
1003 	 * LANDLOCK_ACCESS_FS_WRITE_FILE.  The (kernel internal) difference is
1004 	 * that there was no rule tied to it before.
1005 	 */
1006 	add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
1007 			dir_s1d3);
1008 	enforce_ruleset(_metadata, ruleset_fd);
1009 	ASSERT_EQ(0, close(ruleset_fd));
1010 
1011 	/*
1012 	 * Same tests and results as above, except for open(dir_s1d3) which is
1013 	 * now denied because the new rule mask the rule previously inherited
1014 	 * from dir_s1d2.
1015 	 */
1016 
1017 	/* Same tests and results as above. */
1018 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1019 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1020 
1021 	/* It is still forbidden to write in file1_s1d2. */
1022 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1023 	/* Readdir access is still allowed. */
1024 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1025 
1026 	/* It is still forbidden to write in file1_s1d3. */
1027 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1028 	/*
1029 	 * Readdir of dir_s1d3 is still allowed because of the OR policy inside
1030 	 * the same layer.
1031 	 */
1032 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1033 }
1034 
TEST_F_FORK(layout1,inherit_superset)1035 TEST_F_FORK(layout1, inherit_superset)
1036 {
1037 	const struct rule rules[] = {
1038 		{
1039 			.path = dir_s1d3,
1040 			.access = ACCESS_RO,
1041 		},
1042 		{}
1043 	};
1044 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1045 
1046 	ASSERT_LE(0, ruleset_fd);
1047 	enforce_ruleset(_metadata, ruleset_fd);
1048 
1049 	/* Readdir access is denied for dir_s1d2. */
1050 	ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1051 	/* Readdir access is allowed for dir_s1d3. */
1052 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1053 	/* File access is allowed for file1_s1d3. */
1054 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1055 
1056 	/* Now dir_s1d2, parent of dir_s1d3, gets a new rule tied to it. */
1057 	add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_READ_FILE |
1058 			LANDLOCK_ACCESS_FS_READ_DIR, dir_s1d2);
1059 	enforce_ruleset(_metadata, ruleset_fd);
1060 	ASSERT_EQ(0, close(ruleset_fd));
1061 
1062 	/* Readdir access is still denied for dir_s1d2. */
1063 	ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1064 	/* Readdir access is still allowed for dir_s1d3. */
1065 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1066 	/* File access is still allowed for file1_s1d3. */
1067 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1068 }
1069 
TEST_F_FORK(layout1,max_layers)1070 TEST_F_FORK(layout1, max_layers)
1071 {
1072 	int i, err;
1073 	const struct rule rules[] = {
1074 		{
1075 			.path = dir_s1d2,
1076 			.access = ACCESS_RO,
1077 		},
1078 		{}
1079 	};
1080 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1081 
1082 	ASSERT_LE(0, ruleset_fd);
1083 	for (i = 0; i < 64; i++)
1084 		enforce_ruleset(_metadata, ruleset_fd);
1085 
1086 	for (i = 0; i < 2; i++) {
1087 		err = landlock_restrict_self(ruleset_fd, 0);
1088 		ASSERT_EQ(-1, err);
1089 		ASSERT_EQ(E2BIG, errno);
1090 	}
1091 	ASSERT_EQ(0, close(ruleset_fd));
1092 }
1093 
TEST_F_FORK(layout1,empty_or_same_ruleset)1094 TEST_F_FORK(layout1, empty_or_same_ruleset)
1095 {
1096 	struct landlock_ruleset_attr ruleset_attr = {};
1097 	int ruleset_fd;
1098 
1099 	/* Tests empty handled_access_fs. */
1100 	ruleset_fd = landlock_create_ruleset(&ruleset_attr,
1101 			sizeof(ruleset_attr), 0);
1102 	ASSERT_LE(-1, ruleset_fd);
1103 	ASSERT_EQ(ENOMSG, errno);
1104 
1105 	/* Enforces policy which deny read access to all files. */
1106 	ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE;
1107 	ruleset_fd = landlock_create_ruleset(&ruleset_attr,
1108 			sizeof(ruleset_attr), 0);
1109 	ASSERT_LE(0, ruleset_fd);
1110 	enforce_ruleset(_metadata, ruleset_fd);
1111 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1112 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1113 
1114 	/* Nests a policy which deny read access to all directories. */
1115 	ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR;
1116 	ruleset_fd = landlock_create_ruleset(&ruleset_attr,
1117 			sizeof(ruleset_attr), 0);
1118 	ASSERT_LE(0, ruleset_fd);
1119 	enforce_ruleset(_metadata, ruleset_fd);
1120 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1121 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1122 
1123 	/* Enforces a second time with the same ruleset. */
1124 	enforce_ruleset(_metadata, ruleset_fd);
1125 	ASSERT_EQ(0, close(ruleset_fd));
1126 }
1127 
TEST_F_FORK(layout1,rule_on_mountpoint)1128 TEST_F_FORK(layout1, rule_on_mountpoint)
1129 {
1130 	const struct rule rules[] = {
1131 		{
1132 			.path = dir_s1d1,
1133 			.access = ACCESS_RO,
1134 		},
1135 		{
1136 			/* dir_s3d2 is a mount point. */
1137 			.path = dir_s3d2,
1138 			.access = ACCESS_RO,
1139 		},
1140 		{}
1141 	};
1142 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1143 
1144 	ASSERT_LE(0, ruleset_fd);
1145 	enforce_ruleset(_metadata, ruleset_fd);
1146 	ASSERT_EQ(0, close(ruleset_fd));
1147 
1148 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1149 
1150 	ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
1151 
1152 	ASSERT_EQ(EACCES, test_open(dir_s3d1, O_RDONLY));
1153 	ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
1154 	ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
1155 }
1156 
TEST_F_FORK(layout1,rule_over_mountpoint)1157 TEST_F_FORK(layout1, rule_over_mountpoint)
1158 {
1159 	const struct rule rules[] = {
1160 		{
1161 			.path = dir_s1d1,
1162 			.access = ACCESS_RO,
1163 		},
1164 		{
1165 			/* dir_s3d2 is a mount point. */
1166 			.path = dir_s3d1,
1167 			.access = ACCESS_RO,
1168 		},
1169 		{}
1170 	};
1171 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1172 
1173 	ASSERT_LE(0, ruleset_fd);
1174 	enforce_ruleset(_metadata, ruleset_fd);
1175 	ASSERT_EQ(0, close(ruleset_fd));
1176 
1177 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1178 
1179 	ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
1180 
1181 	ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
1182 	ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
1183 	ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
1184 }
1185 
1186 /*
1187  * This test verifies that we can apply a landlock rule on the root directory
1188  * (which might require special handling).
1189  */
TEST_F_FORK(layout1,rule_over_root_allow_then_deny)1190 TEST_F_FORK(layout1, rule_over_root_allow_then_deny)
1191 {
1192 	struct rule rules[] = {
1193 		{
1194 			.path = "/",
1195 			.access = ACCESS_RO,
1196 		},
1197 		{}
1198 	};
1199 	int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1200 
1201 	ASSERT_LE(0, ruleset_fd);
1202 	enforce_ruleset(_metadata, ruleset_fd);
1203 	ASSERT_EQ(0, close(ruleset_fd));
1204 
1205 	/* Checks allowed access. */
1206 	ASSERT_EQ(0, test_open("/", O_RDONLY));
1207 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1208 
1209 	rules[0].access = LANDLOCK_ACCESS_FS_READ_FILE;
1210 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1211 	ASSERT_LE(0, ruleset_fd);
1212 	enforce_ruleset(_metadata, ruleset_fd);
1213 	ASSERT_EQ(0, close(ruleset_fd));
1214 
1215 	/* Checks denied access (on a directory). */
1216 	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1217 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1218 }
1219 
TEST_F_FORK(layout1,rule_over_root_deny)1220 TEST_F_FORK(layout1, rule_over_root_deny)
1221 {
1222 	const struct rule rules[] = {
1223 		{
1224 			.path = "/",
1225 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1226 		},
1227 		{}
1228 	};
1229 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1230 
1231 	ASSERT_LE(0, ruleset_fd);
1232 	enforce_ruleset(_metadata, ruleset_fd);
1233 	ASSERT_EQ(0, close(ruleset_fd));
1234 
1235 	/* Checks denied access (on a directory). */
1236 	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1237 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1238 }
1239 
TEST_F_FORK(layout1,rule_inside_mount_ns)1240 TEST_F_FORK(layout1, rule_inside_mount_ns)
1241 {
1242 	const struct rule rules[] = {
1243 		{
1244 			.path = "s3d3",
1245 			.access = ACCESS_RO,
1246 		},
1247 		{}
1248 	};
1249 	int ruleset_fd;
1250 
1251 	set_cap(_metadata, CAP_SYS_ADMIN);
1252 	ASSERT_EQ(0, syscall(SYS_pivot_root, dir_s3d2, dir_s3d3)) {
1253 		TH_LOG("Failed to pivot root: %s", strerror(errno));
1254 	};
1255 	ASSERT_EQ(0, chdir("/"));
1256 	clear_cap(_metadata, CAP_SYS_ADMIN);
1257 
1258 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1259 	ASSERT_LE(0, ruleset_fd);
1260 	enforce_ruleset(_metadata, ruleset_fd);
1261 	ASSERT_EQ(0, close(ruleset_fd));
1262 
1263 	ASSERT_EQ(0, test_open("s3d3", O_RDONLY));
1264 	ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1265 }
1266 
TEST_F_FORK(layout1,mount_and_pivot)1267 TEST_F_FORK(layout1, mount_and_pivot)
1268 {
1269 	const struct rule rules[] = {
1270 		{
1271 			.path = dir_s3d2,
1272 			.access = ACCESS_RO,
1273 		},
1274 		{}
1275 	};
1276 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1277 
1278 	ASSERT_LE(0, ruleset_fd);
1279 	enforce_ruleset(_metadata, ruleset_fd);
1280 	ASSERT_EQ(0, close(ruleset_fd));
1281 
1282 	set_cap(_metadata, CAP_SYS_ADMIN);
1283 	ASSERT_EQ(-1, mount(NULL, dir_s3d2, NULL, MS_RDONLY, NULL));
1284 	ASSERT_EQ(EPERM, errno);
1285 	ASSERT_EQ(-1, syscall(SYS_pivot_root, dir_s3d2, dir_s3d3));
1286 	ASSERT_EQ(EPERM, errno);
1287 	clear_cap(_metadata, CAP_SYS_ADMIN);
1288 }
1289 
TEST_F_FORK(layout1,move_mount)1290 TEST_F_FORK(layout1, move_mount)
1291 {
1292 	const struct rule rules[] = {
1293 		{
1294 			.path = dir_s3d2,
1295 			.access = ACCESS_RO,
1296 		},
1297 		{}
1298 	};
1299 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1300 
1301 	ASSERT_LE(0, ruleset_fd);
1302 
1303 	set_cap(_metadata, CAP_SYS_ADMIN);
1304 	ASSERT_EQ(0, syscall(SYS_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1305 				dir_s1d2, 0)) {
1306 		TH_LOG("Failed to move mount: %s", strerror(errno));
1307 	}
1308 
1309 	ASSERT_EQ(0, syscall(SYS_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD,
1310 				dir_s3d2, 0));
1311 	clear_cap(_metadata, CAP_SYS_ADMIN);
1312 
1313 	enforce_ruleset(_metadata, ruleset_fd);
1314 	ASSERT_EQ(0, close(ruleset_fd));
1315 
1316 	set_cap(_metadata, CAP_SYS_ADMIN);
1317 	ASSERT_EQ(-1, syscall(SYS_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1318 				dir_s1d2, 0));
1319 	ASSERT_EQ(EPERM, errno);
1320 	clear_cap(_metadata, CAP_SYS_ADMIN);
1321 }
1322 
TEST_F_FORK(layout1,release_inodes)1323 TEST_F_FORK(layout1, release_inodes)
1324 {
1325 	const struct rule rules[] = {
1326 		{
1327 			.path = dir_s1d1,
1328 			.access = ACCESS_RO,
1329 		},
1330 		{
1331 			.path = dir_s3d2,
1332 			.access = ACCESS_RO,
1333 		},
1334 		{
1335 			.path = dir_s3d3,
1336 			.access = ACCESS_RO,
1337 		},
1338 		{}
1339 	};
1340 	const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1341 
1342 	ASSERT_LE(0, ruleset_fd);
1343 	/* Unmount a file hierarchy while it is being used by a ruleset. */
1344 	set_cap(_metadata, CAP_SYS_ADMIN);
1345 	ASSERT_EQ(0, umount(dir_s3d2));
1346 	clear_cap(_metadata, CAP_SYS_ADMIN);
1347 
1348 	enforce_ruleset(_metadata, ruleset_fd);
1349 	ASSERT_EQ(0, close(ruleset_fd));
1350 
1351 	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
1352 	ASSERT_EQ(EACCES, test_open(dir_s3d2, O_RDONLY));
1353 	/* This dir_s3d3 would not be allowed and does not exist anyway. */
1354 	ASSERT_EQ(ENOENT, test_open(dir_s3d3, O_RDONLY));
1355 }
1356 
1357 enum relative_access {
1358 	REL_OPEN,
1359 	REL_CHDIR,
1360 	REL_CHROOT_ONLY,
1361 	REL_CHROOT_CHDIR,
1362 };
1363 
test_relative_path(struct __test_metadata * const _metadata,const enum relative_access rel)1364 static void test_relative_path(struct __test_metadata *const _metadata,
1365 		const enum relative_access rel)
1366 {
1367 	/*
1368 	 * Common layer to check that chroot doesn't ignore it (i.e. a chroot
1369 	 * is not a disconnected root directory).
1370 	 */
1371 	const struct rule layer1_base[] = {
1372 		{
1373 			.path = TMP_DIR,
1374 			.access = ACCESS_RO,
1375 		},
1376 		{}
1377 	};
1378 	const struct rule layer2_subs[] = {
1379 		{
1380 			.path = dir_s1d2,
1381 			.access = ACCESS_RO,
1382 		},
1383 		{
1384 			.path = dir_s2d2,
1385 			.access = ACCESS_RO,
1386 		},
1387 		{}
1388 	};
1389 	int dirfd, ruleset_fd;
1390 
1391 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_base);
1392 	ASSERT_LE(0, ruleset_fd);
1393 	enforce_ruleset(_metadata, ruleset_fd);
1394 	ASSERT_EQ(0, close(ruleset_fd));
1395 
1396 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_subs);
1397 
1398 	ASSERT_LE(0, ruleset_fd);
1399 	switch (rel) {
1400 	case REL_OPEN:
1401 	case REL_CHDIR:
1402 		break;
1403 	case REL_CHROOT_ONLY:
1404 		ASSERT_EQ(0, chdir(dir_s2d2));
1405 		break;
1406 	case REL_CHROOT_CHDIR:
1407 		ASSERT_EQ(0, chdir(dir_s1d2));
1408 		break;
1409 	default:
1410 		ASSERT_TRUE(false);
1411 		return;
1412 	}
1413 
1414 	set_cap(_metadata, CAP_SYS_CHROOT);
1415 	enforce_ruleset(_metadata, ruleset_fd);
1416 
1417 	switch (rel) {
1418 	case REL_OPEN:
1419 		dirfd = open(dir_s1d2, O_DIRECTORY);
1420 		ASSERT_LE(0, dirfd);
1421 		break;
1422 	case REL_CHDIR:
1423 		ASSERT_EQ(0, chdir(dir_s1d2));
1424 		dirfd = AT_FDCWD;
1425 		break;
1426 	case REL_CHROOT_ONLY:
1427 		/* Do chroot into dir_s1d2 (relative to dir_s2d2). */
1428 		ASSERT_EQ(0, chroot("../../s1d1/s1d2")) {
1429 			TH_LOG("Failed to chroot: %s", strerror(errno));
1430 		}
1431 		dirfd = AT_FDCWD;
1432 		break;
1433 	case REL_CHROOT_CHDIR:
1434 		/* Do chroot into dir_s1d2. */
1435 		ASSERT_EQ(0, chroot(".")) {
1436 			TH_LOG("Failed to chroot: %s", strerror(errno));
1437 		}
1438 		dirfd = AT_FDCWD;
1439 		break;
1440 	}
1441 
1442 	ASSERT_EQ((rel == REL_CHROOT_CHDIR) ? 0 : EACCES,
1443 			test_open_rel(dirfd, "..", O_RDONLY));
1444 	ASSERT_EQ(0, test_open_rel(dirfd, ".", O_RDONLY));
1445 
1446 	if (rel == REL_CHROOT_ONLY) {
1447 		/* The current directory is dir_s2d2. */
1448 		ASSERT_EQ(0, test_open_rel(dirfd, "./s2d3", O_RDONLY));
1449 	} else {
1450 		/* The current directory is dir_s1d2. */
1451 		ASSERT_EQ(0, test_open_rel(dirfd, "./s1d3", O_RDONLY));
1452 	}
1453 
1454 	if (rel == REL_CHROOT_ONLY || rel == REL_CHROOT_CHDIR) {
1455 		/* Checks the root dir_s1d2. */
1456 		ASSERT_EQ(0, test_open_rel(dirfd, "/..", O_RDONLY));
1457 		ASSERT_EQ(0, test_open_rel(dirfd, "/", O_RDONLY));
1458 		ASSERT_EQ(0, test_open_rel(dirfd, "/f1", O_RDONLY));
1459 		ASSERT_EQ(0, test_open_rel(dirfd, "/s1d3", O_RDONLY));
1460 	}
1461 
1462 	if (rel != REL_CHROOT_CHDIR) {
1463 		ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s1d1", O_RDONLY));
1464 		ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2", O_RDONLY));
1465 		ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2/s1d3", O_RDONLY));
1466 
1467 		ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s2d1", O_RDONLY));
1468 		ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2", O_RDONLY));
1469 		ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2/s2d3", O_RDONLY));
1470 	}
1471 
1472 	if (rel == REL_OPEN)
1473 		ASSERT_EQ(0, close(dirfd));
1474 	ASSERT_EQ(0, close(ruleset_fd));
1475 }
1476 
TEST_F_FORK(layout1,relative_open)1477 TEST_F_FORK(layout1, relative_open)
1478 {
1479 	test_relative_path(_metadata, REL_OPEN);
1480 }
1481 
TEST_F_FORK(layout1,relative_chdir)1482 TEST_F_FORK(layout1, relative_chdir)
1483 {
1484 	test_relative_path(_metadata, REL_CHDIR);
1485 }
1486 
TEST_F_FORK(layout1,relative_chroot_only)1487 TEST_F_FORK(layout1, relative_chroot_only)
1488 {
1489 	test_relative_path(_metadata, REL_CHROOT_ONLY);
1490 }
1491 
TEST_F_FORK(layout1,relative_chroot_chdir)1492 TEST_F_FORK(layout1, relative_chroot_chdir)
1493 {
1494 	test_relative_path(_metadata, REL_CHROOT_CHDIR);
1495 }
1496 
copy_binary(struct __test_metadata * const _metadata,const char * const dst_path)1497 static void copy_binary(struct __test_metadata *const _metadata,
1498 		const char *const dst_path)
1499 {
1500 	int dst_fd, src_fd;
1501 	struct stat statbuf;
1502 
1503 	dst_fd = open(dst_path, O_WRONLY | O_TRUNC | O_CLOEXEC);
1504 	ASSERT_LE(0, dst_fd) {
1505 		TH_LOG("Failed to open \"%s\": %s", dst_path,
1506 				strerror(errno));
1507 	}
1508 	src_fd = open(BINARY_PATH, O_RDONLY | O_CLOEXEC);
1509 	ASSERT_LE(0, src_fd) {
1510 		TH_LOG("Failed to open \"" BINARY_PATH "\": %s",
1511 				strerror(errno));
1512 	}
1513 	ASSERT_EQ(0, fstat(src_fd, &statbuf));
1514 	ASSERT_EQ(statbuf.st_size, sendfile(dst_fd, src_fd, 0,
1515 				statbuf.st_size));
1516 	ASSERT_EQ(0, close(src_fd));
1517 	ASSERT_EQ(0, close(dst_fd));
1518 }
1519 
test_execute(struct __test_metadata * const _metadata,const int err,const char * const path)1520 static void test_execute(struct __test_metadata *const _metadata,
1521 		const int err, const char *const path)
1522 {
1523 	int status;
1524 	char *const argv[] = {(char *)path, NULL};
1525 	const pid_t child = fork();
1526 
1527 	ASSERT_LE(0, child);
1528 	if (child == 0) {
1529 		ASSERT_EQ(err ? -1 : 0, execve(path, argv, NULL)) {
1530 			TH_LOG("Failed to execute \"%s\": %s", path,
1531 					strerror(errno));
1532 		};
1533 		ASSERT_EQ(err, errno);
1534 		_exit(_metadata->passed ? 2 : 1);
1535 		return;
1536 	}
1537 	ASSERT_EQ(child, waitpid(child, &status, 0));
1538 	ASSERT_EQ(1, WIFEXITED(status));
1539 	ASSERT_EQ(err ? 2 : 0, WEXITSTATUS(status)) {
1540 		TH_LOG("Unexpected return code for \"%s\": %s", path,
1541 				strerror(errno));
1542 	};
1543 }
1544 
TEST_F_FORK(layout1,execute)1545 TEST_F_FORK(layout1, execute)
1546 {
1547 	const struct rule rules[] = {
1548 		{
1549 			.path = dir_s1d2,
1550 			.access = LANDLOCK_ACCESS_FS_EXECUTE,
1551 		},
1552 		{}
1553 	};
1554 	const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
1555 			rules);
1556 
1557 	ASSERT_LE(0, ruleset_fd);
1558 	copy_binary(_metadata, file1_s1d1);
1559 	copy_binary(_metadata, file1_s1d2);
1560 	copy_binary(_metadata, file1_s1d3);
1561 
1562 	enforce_ruleset(_metadata, ruleset_fd);
1563 	ASSERT_EQ(0, close(ruleset_fd));
1564 
1565 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1566 	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
1567 	test_execute(_metadata, EACCES, file1_s1d1);
1568 
1569 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
1570 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
1571 	test_execute(_metadata, 0, file1_s1d2);
1572 
1573 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
1574 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1575 	test_execute(_metadata, 0, file1_s1d3);
1576 }
1577 
TEST_F_FORK(layout1,link)1578 TEST_F_FORK(layout1, link)
1579 {
1580 	const struct rule rules[] = {
1581 		{
1582 			.path = dir_s1d2,
1583 			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
1584 		},
1585 		{}
1586 	};
1587 	const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
1588 			rules);
1589 
1590 	ASSERT_LE(0, ruleset_fd);
1591 
1592 	ASSERT_EQ(0, unlink(file1_s1d1));
1593 	ASSERT_EQ(0, unlink(file1_s1d2));
1594 	ASSERT_EQ(0, unlink(file1_s1d3));
1595 
1596 	enforce_ruleset(_metadata, ruleset_fd);
1597 	ASSERT_EQ(0, close(ruleset_fd));
1598 
1599 	ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
1600 	ASSERT_EQ(EACCES, errno);
1601 	/* Denies linking because of reparenting. */
1602 	ASSERT_EQ(-1, link(file1_s2d1, file1_s1d2));
1603 	ASSERT_EQ(EXDEV, errno);
1604 	ASSERT_EQ(-1, link(file2_s1d2, file1_s1d3));
1605 	ASSERT_EQ(EXDEV, errno);
1606 
1607 	ASSERT_EQ(0, link(file2_s1d2, file1_s1d2));
1608 	ASSERT_EQ(0, link(file2_s1d3, file1_s1d3));
1609 }
1610 
TEST_F_FORK(layout1,rename_file)1611 TEST_F_FORK(layout1, rename_file)
1612 {
1613 	const struct rule rules[] = {
1614 		{
1615 			.path = dir_s1d3,
1616 			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1617 		},
1618 		{
1619 			.path = dir_s2d2,
1620 			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1621 		},
1622 		{}
1623 	};
1624 	const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
1625 			rules);
1626 
1627 	ASSERT_LE(0, ruleset_fd);
1628 
1629 	ASSERT_EQ(0, unlink(file1_s1d1));
1630 	ASSERT_EQ(0, unlink(file1_s1d2));
1631 
1632 	enforce_ruleset(_metadata, ruleset_fd);
1633 	ASSERT_EQ(0, close(ruleset_fd));
1634 
1635 	/*
1636 	 * Tries to replace a file, from a directory that allows file removal,
1637 	 * but to a different directory (which also allows file removal).
1638 	 */
1639 	ASSERT_EQ(-1, rename(file1_s2d3, file1_s1d3));
1640 	ASSERT_EQ(EXDEV, errno);
1641 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d3,
1642 				RENAME_EXCHANGE));
1643 	ASSERT_EQ(EXDEV, errno);
1644 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, dir_s1d3,
1645 				RENAME_EXCHANGE));
1646 	ASSERT_EQ(EXDEV, errno);
1647 
1648 	/*
1649 	 * Tries to replace a file, from a directory that denies file removal,
1650 	 * to a different directory (which allows file removal).
1651 	 */
1652 	ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
1653 	ASSERT_EQ(EXDEV, errno);
1654 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file1_s1d3,
1655 				RENAME_EXCHANGE));
1656 	ASSERT_EQ(EXDEV, errno);
1657 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s1d3,
1658 				RENAME_EXCHANGE));
1659 	ASSERT_EQ(EXDEV, errno);
1660 
1661 	/* Exchanges files and directories that partially allow removal. */
1662 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s2d1,
1663 				RENAME_EXCHANGE));
1664 	ASSERT_EQ(EACCES, errno);
1665 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, dir_s2d2,
1666 				RENAME_EXCHANGE));
1667 	ASSERT_EQ(EACCES, errno);
1668 
1669 	/* Renames files with different parents. */
1670 	ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d2));
1671 	ASSERT_EQ(EXDEV, errno);
1672 	ASSERT_EQ(0, unlink(file1_s1d3));
1673 	ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
1674 	ASSERT_EQ(EXDEV, errno);
1675 
1676 	/* Exchanges and renames files with same parent. */
1677 	ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s2d3,
1678 				RENAME_EXCHANGE));
1679 	ASSERT_EQ(0, rename(file2_s2d3, file1_s2d3));
1680 
1681 	/* Exchanges files and directories with same parent, twice. */
1682 	ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
1683 				RENAME_EXCHANGE));
1684 	ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
1685 				RENAME_EXCHANGE));
1686 }
1687 
TEST_F_FORK(layout1,rename_dir)1688 TEST_F_FORK(layout1, rename_dir)
1689 {
1690 	const struct rule rules[] = {
1691 		{
1692 			.path = dir_s1d2,
1693 			.access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
1694 		},
1695 		{
1696 			.path = dir_s2d1,
1697 			.access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
1698 		},
1699 		{}
1700 	};
1701 	const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
1702 			rules);
1703 
1704 	ASSERT_LE(0, ruleset_fd);
1705 
1706 	/* Empties dir_s1d3 to allow renaming. */
1707 	ASSERT_EQ(0, unlink(file1_s1d3));
1708 	ASSERT_EQ(0, unlink(file2_s1d3));
1709 
1710 	enforce_ruleset(_metadata, ruleset_fd);
1711 	ASSERT_EQ(0, close(ruleset_fd));
1712 
1713 	/* Exchanges and renames directory to a different parent. */
1714 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
1715 				RENAME_EXCHANGE));
1716 	ASSERT_EQ(EXDEV, errno);
1717 	ASSERT_EQ(-1, rename(dir_s2d3, dir_s1d3));
1718 	ASSERT_EQ(EXDEV, errno);
1719 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
1720 				RENAME_EXCHANGE));
1721 	ASSERT_EQ(EXDEV, errno);
1722 
1723 	/*
1724 	 * Exchanges directory to the same parent, which doesn't allow
1725 	 * directory removal.
1726 	 */
1727 	ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d1, AT_FDCWD, dir_s2d1,
1728 				RENAME_EXCHANGE));
1729 	ASSERT_EQ(EACCES, errno);
1730 	ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s1d2,
1731 				RENAME_EXCHANGE));
1732 	ASSERT_EQ(EACCES, errno);
1733 
1734 	/*
1735 	 * Exchanges and renames directory to the same parent, which allows
1736 	 * directory removal.
1737 	 */
1738 	ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, file1_s1d2,
1739 				RENAME_EXCHANGE));
1740 	ASSERT_EQ(0, unlink(dir_s1d3));
1741 	ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
1742 	ASSERT_EQ(0, rename(file1_s1d2, dir_s1d3));
1743 	ASSERT_EQ(0, rmdir(dir_s1d3));
1744 }
1745 
TEST_F_FORK(layout1,remove_dir)1746 TEST_F_FORK(layout1, remove_dir)
1747 {
1748 	const struct rule rules[] = {
1749 		{
1750 			.path = dir_s1d2,
1751 			.access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
1752 		},
1753 		{}
1754 	};
1755 	const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
1756 			rules);
1757 
1758 	ASSERT_LE(0, ruleset_fd);
1759 
1760 	ASSERT_EQ(0, unlink(file1_s1d1));
1761 	ASSERT_EQ(0, unlink(file1_s1d2));
1762 	ASSERT_EQ(0, unlink(file1_s1d3));
1763 	ASSERT_EQ(0, unlink(file2_s1d3));
1764 
1765 	enforce_ruleset(_metadata, ruleset_fd);
1766 	ASSERT_EQ(0, close(ruleset_fd));
1767 
1768 	ASSERT_EQ(0, rmdir(dir_s1d3));
1769 	ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
1770 	ASSERT_EQ(0, unlinkat(AT_FDCWD, dir_s1d3, AT_REMOVEDIR));
1771 
1772 	/* dir_s1d2 itself cannot be removed. */
1773 	ASSERT_EQ(-1, rmdir(dir_s1d2));
1774 	ASSERT_EQ(EACCES, errno);
1775 	ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d2, AT_REMOVEDIR));
1776 	ASSERT_EQ(EACCES, errno);
1777 	ASSERT_EQ(-1, rmdir(dir_s1d1));
1778 	ASSERT_EQ(EACCES, errno);
1779 	ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d1, AT_REMOVEDIR));
1780 	ASSERT_EQ(EACCES, errno);
1781 }
1782 
TEST_F_FORK(layout1,remove_file)1783 TEST_F_FORK(layout1, remove_file)
1784 {
1785 	const struct rule rules[] = {
1786 		{
1787 			.path = dir_s1d2,
1788 			.access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1789 		},
1790 		{}
1791 	};
1792 	const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
1793 			rules);
1794 
1795 	ASSERT_LE(0, ruleset_fd);
1796 	enforce_ruleset(_metadata, ruleset_fd);
1797 	ASSERT_EQ(0, close(ruleset_fd));
1798 
1799 	ASSERT_EQ(-1, unlink(file1_s1d1));
1800 	ASSERT_EQ(EACCES, errno);
1801 	ASSERT_EQ(-1, unlinkat(AT_FDCWD, file1_s1d1, 0));
1802 	ASSERT_EQ(EACCES, errno);
1803 	ASSERT_EQ(0, unlink(file1_s1d2));
1804 	ASSERT_EQ(0, unlinkat(AT_FDCWD, file1_s1d3, 0));
1805 }
1806 
test_make_file(struct __test_metadata * const _metadata,const __u64 access,const mode_t mode,const dev_t dev)1807 static void test_make_file(struct __test_metadata *const _metadata,
1808 		const __u64 access, const mode_t mode, const dev_t dev)
1809 {
1810 	const struct rule rules[] = {
1811 		{
1812 			.path = dir_s1d2,
1813 			.access = access,
1814 		},
1815 		{}
1816 	};
1817 	const int ruleset_fd = create_ruleset(_metadata, access, rules);
1818 
1819 	ASSERT_LE(0, ruleset_fd);
1820 
1821 	ASSERT_EQ(0, unlink(file1_s1d1));
1822 	ASSERT_EQ(0, unlink(file2_s1d1));
1823 	ASSERT_EQ(0, mknod(file2_s1d1, mode | 0400, dev)) {
1824 		TH_LOG("Failed to make file \"%s\": %s",
1825 				file2_s1d1, strerror(errno));
1826 	};
1827 
1828 	ASSERT_EQ(0, unlink(file1_s1d2));
1829 	ASSERT_EQ(0, unlink(file2_s1d2));
1830 
1831 	ASSERT_EQ(0, unlink(file1_s1d3));
1832 	ASSERT_EQ(0, unlink(file2_s1d3));
1833 
1834 	enforce_ruleset(_metadata, ruleset_fd);
1835 	ASSERT_EQ(0, close(ruleset_fd));
1836 
1837 	ASSERT_EQ(-1, mknod(file1_s1d1, mode | 0400, dev));
1838 	ASSERT_EQ(EACCES, errno);
1839 	ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
1840 	ASSERT_EQ(EACCES, errno);
1841 	ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
1842 	ASSERT_EQ(EACCES, errno);
1843 
1844 	ASSERT_EQ(0, mknod(file1_s1d2, mode | 0400, dev)) {
1845 		TH_LOG("Failed to make file \"%s\": %s",
1846 				file1_s1d2, strerror(errno));
1847 	};
1848 	ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
1849 	ASSERT_EQ(0, unlink(file2_s1d2));
1850 	ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
1851 
1852 	ASSERT_EQ(0, mknod(file1_s1d3, mode | 0400, dev));
1853 	ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
1854 	ASSERT_EQ(0, unlink(file2_s1d3));
1855 	ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
1856 }
1857 
TEST_F_FORK(layout1,make_char)1858 TEST_F_FORK(layout1, make_char)
1859 {
1860 	/* Creates a /dev/null device. */
1861 	set_cap(_metadata, CAP_MKNOD);
1862 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_CHAR, S_IFCHR,
1863 			makedev(1, 3));
1864 }
1865 
TEST_F_FORK(layout1,make_block)1866 TEST_F_FORK(layout1, make_block)
1867 {
1868 	/* Creates a /dev/loop0 device. */
1869 	set_cap(_metadata, CAP_MKNOD);
1870 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_BLOCK, S_IFBLK,
1871 			makedev(7, 0));
1872 }
1873 
TEST_F_FORK(layout1,make_reg_1)1874 TEST_F_FORK(layout1, make_reg_1)
1875 {
1876 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, S_IFREG, 0);
1877 }
1878 
TEST_F_FORK(layout1,make_reg_2)1879 TEST_F_FORK(layout1, make_reg_2)
1880 {
1881 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, 0, 0);
1882 }
1883 
TEST_F_FORK(layout1,make_sock)1884 TEST_F_FORK(layout1, make_sock)
1885 {
1886 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_SOCK, S_IFSOCK, 0);
1887 }
1888 
TEST_F_FORK(layout1,make_fifo)1889 TEST_F_FORK(layout1, make_fifo)
1890 {
1891 	test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_FIFO, S_IFIFO, 0);
1892 }
1893 
TEST_F_FORK(layout1,make_sym)1894 TEST_F_FORK(layout1, make_sym)
1895 {
1896 	const struct rule rules[] = {
1897 		{
1898 			.path = dir_s1d2,
1899 			.access = LANDLOCK_ACCESS_FS_MAKE_SYM,
1900 		},
1901 		{}
1902 	};
1903 	const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
1904 			rules);
1905 
1906 	ASSERT_LE(0, ruleset_fd);
1907 
1908 	ASSERT_EQ(0, unlink(file1_s1d1));
1909 	ASSERT_EQ(0, unlink(file2_s1d1));
1910 	ASSERT_EQ(0, symlink("none", file2_s1d1));
1911 
1912 	ASSERT_EQ(0, unlink(file1_s1d2));
1913 	ASSERT_EQ(0, unlink(file2_s1d2));
1914 
1915 	ASSERT_EQ(0, unlink(file1_s1d3));
1916 	ASSERT_EQ(0, unlink(file2_s1d3));
1917 
1918 	enforce_ruleset(_metadata, ruleset_fd);
1919 	ASSERT_EQ(0, close(ruleset_fd));
1920 
1921 	ASSERT_EQ(-1, symlink("none", file1_s1d1));
1922 	ASSERT_EQ(EACCES, errno);
1923 	ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
1924 	ASSERT_EQ(EACCES, errno);
1925 	ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
1926 	ASSERT_EQ(EACCES, errno);
1927 
1928 	ASSERT_EQ(0, symlink("none", file1_s1d2));
1929 	ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
1930 	ASSERT_EQ(0, unlink(file2_s1d2));
1931 	ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
1932 
1933 	ASSERT_EQ(0, symlink("none", file1_s1d3));
1934 	ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
1935 	ASSERT_EQ(0, unlink(file2_s1d3));
1936 	ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
1937 }
1938 
TEST_F_FORK(layout1,make_dir)1939 TEST_F_FORK(layout1, make_dir)
1940 {
1941 	const struct rule rules[] = {
1942 		{
1943 			.path = dir_s1d2,
1944 			.access = LANDLOCK_ACCESS_FS_MAKE_DIR,
1945 		},
1946 		{}
1947 	};
1948 	const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
1949 			rules);
1950 
1951 	ASSERT_LE(0, ruleset_fd);
1952 
1953 	ASSERT_EQ(0, unlink(file1_s1d1));
1954 	ASSERT_EQ(0, unlink(file1_s1d2));
1955 	ASSERT_EQ(0, unlink(file1_s1d3));
1956 
1957 	enforce_ruleset(_metadata, ruleset_fd);
1958 	ASSERT_EQ(0, close(ruleset_fd));
1959 
1960 	/* Uses file_* as directory names. */
1961 	ASSERT_EQ(-1, mkdir(file1_s1d1, 0700));
1962 	ASSERT_EQ(EACCES, errno);
1963 	ASSERT_EQ(0, mkdir(file1_s1d2, 0700));
1964 	ASSERT_EQ(0, mkdir(file1_s1d3, 0700));
1965 }
1966 
open_proc_fd(struct __test_metadata * const _metadata,const int fd,const int open_flags)1967 static int open_proc_fd(struct __test_metadata *const _metadata, const int fd,
1968 		const int open_flags)
1969 {
1970 	static const char path_template[] = "/proc/self/fd/%d";
1971 	char procfd_path[sizeof(path_template) + 10];
1972 	const int procfd_path_size = snprintf(procfd_path, sizeof(procfd_path),
1973 			path_template, fd);
1974 
1975 	ASSERT_LT(procfd_path_size, sizeof(procfd_path));
1976 	return open(procfd_path, open_flags);
1977 }
1978 
TEST_F_FORK(layout1,proc_unlinked_file)1979 TEST_F_FORK(layout1, proc_unlinked_file)
1980 {
1981 	const struct rule rules[] = {
1982 		{
1983 			.path = file1_s1d2,
1984 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
1985 		},
1986 		{}
1987 	};
1988 	int reg_fd, proc_fd;
1989 	const int ruleset_fd = create_ruleset(_metadata,
1990 			LANDLOCK_ACCESS_FS_READ_FILE |
1991 			LANDLOCK_ACCESS_FS_WRITE_FILE, rules);
1992 
1993 	ASSERT_LE(0, ruleset_fd);
1994 	enforce_ruleset(_metadata, ruleset_fd);
1995 	ASSERT_EQ(0, close(ruleset_fd));
1996 
1997 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
1998 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
1999 	reg_fd = open(file1_s1d2, O_RDONLY | O_CLOEXEC);
2000 	ASSERT_LE(0, reg_fd);
2001 	ASSERT_EQ(0, unlink(file1_s1d2));
2002 
2003 	proc_fd = open_proc_fd(_metadata, reg_fd, O_RDONLY | O_CLOEXEC);
2004 	ASSERT_LE(0, proc_fd);
2005 	ASSERT_EQ(0, close(proc_fd));
2006 
2007 	proc_fd = open_proc_fd(_metadata, reg_fd, O_RDWR | O_CLOEXEC);
2008 	ASSERT_EQ(-1, proc_fd) {
2009 		TH_LOG("Successfully opened /proc/self/fd/%d: %s",
2010 				reg_fd, strerror(errno));
2011 	}
2012 	ASSERT_EQ(EACCES, errno);
2013 
2014 	ASSERT_EQ(0, close(reg_fd));
2015 }
2016 
TEST_F_FORK(layout1,proc_pipe)2017 TEST_F_FORK(layout1, proc_pipe)
2018 {
2019 	int proc_fd;
2020 	int pipe_fds[2];
2021 	char buf = '\0';
2022 	const struct rule rules[] = {
2023 		{
2024 			.path = dir_s1d2,
2025 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
2026 				LANDLOCK_ACCESS_FS_WRITE_FILE,
2027 		},
2028 		{}
2029 	};
2030 	/* Limits read and write access to files tied to the filesystem. */
2031 	const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
2032 			rules);
2033 
2034 	ASSERT_LE(0, ruleset_fd);
2035 	enforce_ruleset(_metadata, ruleset_fd);
2036 	ASSERT_EQ(0, close(ruleset_fd));
2037 
2038 	/* Checks enforcement for normal files. */
2039 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
2040 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
2041 
2042 	/* Checks access to pipes through FD. */
2043 	ASSERT_EQ(0, pipe2(pipe_fds, O_CLOEXEC));
2044 	ASSERT_EQ(1, write(pipe_fds[1], ".", 1)) {
2045 		TH_LOG("Failed to write in pipe: %s", strerror(errno));
2046 	}
2047 	ASSERT_EQ(1, read(pipe_fds[0], &buf, 1));
2048 	ASSERT_EQ('.', buf);
2049 
2050 	/* Checks write access to pipe through /proc/self/fd . */
2051 	proc_fd = open_proc_fd(_metadata, pipe_fds[1], O_WRONLY | O_CLOEXEC);
2052 	ASSERT_LE(0, proc_fd);
2053 	ASSERT_EQ(1, write(proc_fd, ".", 1)) {
2054 		TH_LOG("Failed to write through /proc/self/fd/%d: %s",
2055 				pipe_fds[1], strerror(errno));
2056 	}
2057 	ASSERT_EQ(0, close(proc_fd));
2058 
2059 	/* Checks read access to pipe through /proc/self/fd . */
2060 	proc_fd = open_proc_fd(_metadata, pipe_fds[0], O_RDONLY | O_CLOEXEC);
2061 	ASSERT_LE(0, proc_fd);
2062 	buf = '\0';
2063 	ASSERT_EQ(1, read(proc_fd, &buf, 1)) {
2064 		TH_LOG("Failed to read through /proc/self/fd/%d: %s",
2065 				pipe_fds[1], strerror(errno));
2066 	}
2067 	ASSERT_EQ(0, close(proc_fd));
2068 
2069 	ASSERT_EQ(0, close(pipe_fds[0]));
2070 	ASSERT_EQ(0, close(pipe_fds[1]));
2071 }
2072 
FIXTURE(layout1_bind)2073 FIXTURE(layout1_bind) {
2074 };
2075 
FIXTURE_SETUP(layout1_bind)2076 FIXTURE_SETUP(layout1_bind)
2077 {
2078 	prepare_layout(_metadata);
2079 
2080 	create_layout1(_metadata);
2081 
2082 	set_cap(_metadata, CAP_SYS_ADMIN);
2083 	ASSERT_EQ(0, mount(dir_s1d2, dir_s2d2, NULL, MS_BIND, NULL));
2084 	clear_cap(_metadata, CAP_SYS_ADMIN);
2085 }
2086 
FIXTURE_TEARDOWN(layout1_bind)2087 FIXTURE_TEARDOWN(layout1_bind)
2088 {
2089 	set_cap(_metadata, CAP_SYS_ADMIN);
2090 	EXPECT_EQ(0, umount(dir_s2d2));
2091 	clear_cap(_metadata, CAP_SYS_ADMIN);
2092 
2093 	remove_layout1(_metadata);
2094 
2095 	cleanup_layout(_metadata);
2096 }
2097 
2098 static const char bind_dir_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3";
2099 static const char bind_file1_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3/f1";
2100 
2101 /*
2102  * layout1_bind hierarchy:
2103  *
2104  * tmp
2105  * ├── s1d1
2106  * │   ├── f1
2107  * │   ├── f2
2108  * │   └── s1d2
2109  * │       ├── f1
2110  * │       ├── f2
2111  * │       └── s1d3
2112  * │           ├── f1
2113  * │           └── f2
2114  * ├── s2d1
2115  * │   ├── f1
2116  * │   └── s2d2
2117  * │       ├── f1
2118  * │       ├── f2
2119  * │       └── s1d3
2120  * │           ├── f1
2121  * │           └── f2
2122  * └── s3d1
2123  *     └── s3d2
2124  *         └── s3d3
2125  */
2126 
TEST_F_FORK(layout1_bind,no_restriction)2127 TEST_F_FORK(layout1_bind, no_restriction)
2128 {
2129 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
2130 	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
2131 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
2132 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
2133 	ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
2134 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
2135 
2136 	ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
2137 	ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
2138 	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
2139 	ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
2140 	ASSERT_EQ(ENOENT, test_open(dir_s2d3, O_RDONLY));
2141 	ASSERT_EQ(ENOENT, test_open(file1_s2d3, O_RDONLY));
2142 
2143 	ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY));
2144 	ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
2145 
2146 	ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
2147 }
2148 
TEST_F_FORK(layout1_bind,same_content_same_file)2149 TEST_F_FORK(layout1_bind, same_content_same_file)
2150 {
2151 	/*
2152 	 * Sets access right on parent directories of both source and
2153 	 * destination mount points.
2154 	 */
2155 	const struct rule layer1_parent[] = {
2156 		{
2157 			.path = dir_s1d1,
2158 			.access = ACCESS_RO,
2159 		},
2160 		{
2161 			.path = dir_s2d1,
2162 			.access = ACCESS_RW,
2163 		},
2164 		{}
2165 	};
2166 	/*
2167 	 * Sets access rights on the same bind-mounted directories.  The result
2168 	 * should be ACCESS_RW for both directories, but not both hierarchies
2169 	 * because of the first layer.
2170 	 */
2171 	const struct rule layer2_mount_point[] = {
2172 		{
2173 			.path = dir_s1d2,
2174 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2175 		},
2176 		{
2177 			.path = dir_s2d2,
2178 			.access = ACCESS_RW,
2179 		},
2180 		{}
2181 	};
2182 	/* Only allow read-access to the s1d3 hierarchies. */
2183 	const struct rule layer3_source[] = {
2184 		{
2185 			.path = dir_s1d3,
2186 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2187 		},
2188 		{}
2189 	};
2190 	/* Removes all access rights. */
2191 	const struct rule layer4_destination[] = {
2192 		{
2193 			.path = bind_file1_s1d3,
2194 			.access = LANDLOCK_ACCESS_FS_WRITE_FILE,
2195 		},
2196 		{}
2197 	};
2198 	int ruleset_fd;
2199 
2200 	/* Sets rules for the parent directories. */
2201 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_parent);
2202 	ASSERT_LE(0, ruleset_fd);
2203 	enforce_ruleset(_metadata, ruleset_fd);
2204 	ASSERT_EQ(0, close(ruleset_fd));
2205 
2206 	/* Checks source hierarchy. */
2207 	ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
2208 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
2209 	ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
2210 
2211 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
2212 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
2213 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
2214 
2215 	/* Checks destination hierarchy. */
2216 	ASSERT_EQ(0, test_open(file1_s2d1, O_RDWR));
2217 	ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
2218 
2219 	ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
2220 	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
2221 
2222 	/* Sets rules for the mount points. */
2223 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_mount_point);
2224 	ASSERT_LE(0, ruleset_fd);
2225 	enforce_ruleset(_metadata, ruleset_fd);
2226 	ASSERT_EQ(0, close(ruleset_fd));
2227 
2228 	/* Checks source hierarchy. */
2229 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
2230 	ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
2231 	ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
2232 
2233 	ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
2234 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
2235 	ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
2236 
2237 	/* Checks destination hierarchy. */
2238 	ASSERT_EQ(EACCES, test_open(file1_s2d1, O_RDONLY));
2239 	ASSERT_EQ(EACCES, test_open(file1_s2d1, O_WRONLY));
2240 	ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
2241 
2242 	ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
2243 	ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
2244 	ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
2245 
2246 	/* Sets a (shared) rule only on the source. */
2247 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3_source);
2248 	ASSERT_LE(0, ruleset_fd);
2249 	enforce_ruleset(_metadata, ruleset_fd);
2250 	ASSERT_EQ(0, close(ruleset_fd));
2251 
2252 	/* Checks source hierarchy. */
2253 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDONLY));
2254 	ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
2255 	ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
2256 
2257 	ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
2258 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
2259 	ASSERT_EQ(EACCES, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
2260 
2261 	/* Checks destination hierarchy. */
2262 	ASSERT_EQ(EACCES, test_open(file1_s2d2, O_RDONLY));
2263 	ASSERT_EQ(EACCES, test_open(file1_s2d2, O_WRONLY));
2264 	ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
2265 
2266 	ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
2267 	ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
2268 	ASSERT_EQ(EACCES, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
2269 
2270 	/* Sets a (shared) rule only on the destination. */
2271 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer4_destination);
2272 	ASSERT_LE(0, ruleset_fd);
2273 	enforce_ruleset(_metadata, ruleset_fd);
2274 	ASSERT_EQ(0, close(ruleset_fd));
2275 
2276 	/* Checks source hierarchy. */
2277 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
2278 	ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
2279 
2280 	/* Checks destination hierarchy. */
2281 	ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_RDONLY));
2282 	ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
2283 }
2284 
2285 #define LOWER_BASE	TMP_DIR "/lower"
2286 #define LOWER_DATA	LOWER_BASE "/data"
2287 static const char lower_fl1[] = LOWER_DATA "/fl1";
2288 static const char lower_dl1[] = LOWER_DATA "/dl1";
2289 static const char lower_dl1_fl2[] = LOWER_DATA "/dl1/fl2";
2290 static const char lower_fo1[] = LOWER_DATA "/fo1";
2291 static const char lower_do1[] = LOWER_DATA "/do1";
2292 static const char lower_do1_fo2[] = LOWER_DATA "/do1/fo2";
2293 static const char lower_do1_fl3[] = LOWER_DATA "/do1/fl3";
2294 
2295 static const char (*lower_base_files[])[] = {
2296 	&lower_fl1,
2297 	&lower_fo1,
2298 	NULL
2299 };
2300 static const char (*lower_base_directories[])[] = {
2301 	&lower_dl1,
2302 	&lower_do1,
2303 	NULL
2304 };
2305 static const char (*lower_sub_files[])[] = {
2306 	&lower_dl1_fl2,
2307 	&lower_do1_fo2,
2308 	&lower_do1_fl3,
2309 	NULL
2310 };
2311 
2312 #define UPPER_BASE	TMP_DIR "/upper"
2313 #define UPPER_DATA	UPPER_BASE "/data"
2314 #define UPPER_WORK	UPPER_BASE "/work"
2315 static const char upper_fu1[] = UPPER_DATA "/fu1";
2316 static const char upper_du1[] = UPPER_DATA "/du1";
2317 static const char upper_du1_fu2[] = UPPER_DATA "/du1/fu2";
2318 static const char upper_fo1[] = UPPER_DATA "/fo1";
2319 static const char upper_do1[] = UPPER_DATA "/do1";
2320 static const char upper_do1_fo2[] = UPPER_DATA "/do1/fo2";
2321 static const char upper_do1_fu3[] = UPPER_DATA "/do1/fu3";
2322 
2323 static const char (*upper_base_files[])[] = {
2324 	&upper_fu1,
2325 	&upper_fo1,
2326 	NULL
2327 };
2328 static const char (*upper_base_directories[])[] = {
2329 	&upper_du1,
2330 	&upper_do1,
2331 	NULL
2332 };
2333 static const char (*upper_sub_files[])[] = {
2334 	&upper_du1_fu2,
2335 	&upper_do1_fo2,
2336 	&upper_do1_fu3,
2337 	NULL
2338 };
2339 
2340 #define MERGE_BASE	TMP_DIR "/merge"
2341 #define MERGE_DATA	MERGE_BASE "/data"
2342 static const char merge_fl1[] = MERGE_DATA "/fl1";
2343 static const char merge_dl1[] = MERGE_DATA "/dl1";
2344 static const char merge_dl1_fl2[] = MERGE_DATA "/dl1/fl2";
2345 static const char merge_fu1[] = MERGE_DATA "/fu1";
2346 static const char merge_du1[] = MERGE_DATA "/du1";
2347 static const char merge_du1_fu2[] = MERGE_DATA "/du1/fu2";
2348 static const char merge_fo1[] = MERGE_DATA "/fo1";
2349 static const char merge_do1[] = MERGE_DATA "/do1";
2350 static const char merge_do1_fo2[] = MERGE_DATA "/do1/fo2";
2351 static const char merge_do1_fl3[] = MERGE_DATA "/do1/fl3";
2352 static const char merge_do1_fu3[] = MERGE_DATA "/do1/fu3";
2353 
2354 static const char (*merge_base_files[])[] = {
2355 	&merge_fl1,
2356 	&merge_fu1,
2357 	&merge_fo1,
2358 	NULL
2359 };
2360 static const char (*merge_base_directories[])[] = {
2361 	&merge_dl1,
2362 	&merge_du1,
2363 	&merge_do1,
2364 	NULL
2365 };
2366 static const char (*merge_sub_files[])[] = {
2367 	&merge_dl1_fl2,
2368 	&merge_du1_fu2,
2369 	&merge_do1_fo2,
2370 	&merge_do1_fl3,
2371 	&merge_do1_fu3,
2372 	NULL
2373 };
2374 
2375 /*
2376  * layout2_overlay hierarchy:
2377  *
2378  * tmp
2379  * ├── lower
2380  * │   └── data
2381  * │       ├── dl1
2382  * │       │   └── fl2
2383  * │       ├── do1
2384  * │       │   ├── fl3
2385  * │       │   └── fo2
2386  * │       ├── fl1
2387  * │       └── fo1
2388  * ├── merge
2389  * │   └── data
2390  * │       ├── dl1
2391  * │       │   └── fl2
2392  * │       ├── do1
2393  * │       │   ├── fl3
2394  * │       │   ├── fo2
2395  * │       │   └── fu3
2396  * │       ├── du1
2397  * │       │   └── fu2
2398  * │       ├── fl1
2399  * │       ├── fo1
2400  * │       └── fu1
2401  * └── upper
2402  *     ├── data
2403  *     │   ├── do1
2404  *     │   │   ├── fo2
2405  *     │   │   └── fu3
2406  *     │   ├── du1
2407  *     │   │   └── fu2
2408  *     │   ├── fo1
2409  *     │   └── fu1
2410  *     └── work
2411  *         └── work
2412  */
2413 
FIXTURE(layout2_overlay)2414 FIXTURE(layout2_overlay) {
2415 };
2416 
FIXTURE_SETUP(layout2_overlay)2417 FIXTURE_SETUP(layout2_overlay)
2418 {
2419 	prepare_layout(_metadata);
2420 
2421 	create_directory(_metadata, LOWER_BASE);
2422 	set_cap(_metadata, CAP_SYS_ADMIN);
2423 	/* Creates tmpfs mount points to get deterministic overlayfs. */
2424 	ASSERT_EQ(0, mount("tmp", LOWER_BASE, "tmpfs", 0, "size=4m,mode=700"));
2425 	clear_cap(_metadata, CAP_SYS_ADMIN);
2426 	create_file(_metadata, lower_fl1);
2427 	create_file(_metadata, lower_dl1_fl2);
2428 	create_file(_metadata, lower_fo1);
2429 	create_file(_metadata, lower_do1_fo2);
2430 	create_file(_metadata, lower_do1_fl3);
2431 
2432 	create_directory(_metadata, UPPER_BASE);
2433 	set_cap(_metadata, CAP_SYS_ADMIN);
2434 	ASSERT_EQ(0, mount("tmp", UPPER_BASE, "tmpfs", 0, "size=4m,mode=700"));
2435 	clear_cap(_metadata, CAP_SYS_ADMIN);
2436 	create_file(_metadata, upper_fu1);
2437 	create_file(_metadata, upper_du1_fu2);
2438 	create_file(_metadata, upper_fo1);
2439 	create_file(_metadata, upper_do1_fo2);
2440 	create_file(_metadata, upper_do1_fu3);
2441 	ASSERT_EQ(0, mkdir(UPPER_WORK, 0700));
2442 
2443 	create_directory(_metadata, MERGE_DATA);
2444 	set_cap(_metadata, CAP_SYS_ADMIN);
2445 	set_cap(_metadata, CAP_DAC_OVERRIDE);
2446 	ASSERT_EQ(0, mount("overlay", MERGE_DATA, "overlay", 0,
2447 				"lowerdir=" LOWER_DATA
2448 				",upperdir=" UPPER_DATA
2449 				",workdir=" UPPER_WORK));
2450 	clear_cap(_metadata, CAP_DAC_OVERRIDE);
2451 	clear_cap(_metadata, CAP_SYS_ADMIN);
2452 }
2453 
FIXTURE_TEARDOWN(layout2_overlay)2454 FIXTURE_TEARDOWN(layout2_overlay)
2455 {
2456 	EXPECT_EQ(0, remove_path(lower_do1_fl3));
2457 	EXPECT_EQ(0, remove_path(lower_dl1_fl2));
2458 	EXPECT_EQ(0, remove_path(lower_fl1));
2459 	EXPECT_EQ(0, remove_path(lower_do1_fo2));
2460 	EXPECT_EQ(0, remove_path(lower_fo1));
2461 	set_cap(_metadata, CAP_SYS_ADMIN);
2462 	EXPECT_EQ(0, umount(LOWER_BASE));
2463 	clear_cap(_metadata, CAP_SYS_ADMIN);
2464 	EXPECT_EQ(0, remove_path(LOWER_BASE));
2465 
2466 	EXPECT_EQ(0, remove_path(upper_do1_fu3));
2467 	EXPECT_EQ(0, remove_path(upper_du1_fu2));
2468 	EXPECT_EQ(0, remove_path(upper_fu1));
2469 	EXPECT_EQ(0, remove_path(upper_do1_fo2));
2470 	EXPECT_EQ(0, remove_path(upper_fo1));
2471 	EXPECT_EQ(0, remove_path(UPPER_WORK "/work"));
2472 	set_cap(_metadata, CAP_SYS_ADMIN);
2473 	EXPECT_EQ(0, umount(UPPER_BASE));
2474 	clear_cap(_metadata, CAP_SYS_ADMIN);
2475 	EXPECT_EQ(0, remove_path(UPPER_BASE));
2476 
2477 	set_cap(_metadata, CAP_SYS_ADMIN);
2478 	EXPECT_EQ(0, umount(MERGE_DATA));
2479 	clear_cap(_metadata, CAP_SYS_ADMIN);
2480 	EXPECT_EQ(0, remove_path(MERGE_DATA));
2481 
2482 	cleanup_layout(_metadata);
2483 }
2484 
TEST_F_FORK(layout2_overlay,no_restriction)2485 TEST_F_FORK(layout2_overlay, no_restriction)
2486 {
2487 	ASSERT_EQ(0, test_open(lower_fl1, O_RDONLY));
2488 	ASSERT_EQ(0, test_open(lower_dl1, O_RDONLY));
2489 	ASSERT_EQ(0, test_open(lower_dl1_fl2, O_RDONLY));
2490 	ASSERT_EQ(0, test_open(lower_fo1, O_RDONLY));
2491 	ASSERT_EQ(0, test_open(lower_do1, O_RDONLY));
2492 	ASSERT_EQ(0, test_open(lower_do1_fo2, O_RDONLY));
2493 	ASSERT_EQ(0, test_open(lower_do1_fl3, O_RDONLY));
2494 
2495 	ASSERT_EQ(0, test_open(upper_fu1, O_RDONLY));
2496 	ASSERT_EQ(0, test_open(upper_du1, O_RDONLY));
2497 	ASSERT_EQ(0, test_open(upper_du1_fu2, O_RDONLY));
2498 	ASSERT_EQ(0, test_open(upper_fo1, O_RDONLY));
2499 	ASSERT_EQ(0, test_open(upper_do1, O_RDONLY));
2500 	ASSERT_EQ(0, test_open(upper_do1_fo2, O_RDONLY));
2501 	ASSERT_EQ(0, test_open(upper_do1_fu3, O_RDONLY));
2502 
2503 	ASSERT_EQ(0, test_open(merge_fl1, O_RDONLY));
2504 	ASSERT_EQ(0, test_open(merge_dl1, O_RDONLY));
2505 	ASSERT_EQ(0, test_open(merge_dl1_fl2, O_RDONLY));
2506 	ASSERT_EQ(0, test_open(merge_fu1, O_RDONLY));
2507 	ASSERT_EQ(0, test_open(merge_du1, O_RDONLY));
2508 	ASSERT_EQ(0, test_open(merge_du1_fu2, O_RDONLY));
2509 	ASSERT_EQ(0, test_open(merge_fo1, O_RDONLY));
2510 	ASSERT_EQ(0, test_open(merge_do1, O_RDONLY));
2511 	ASSERT_EQ(0, test_open(merge_do1_fo2, O_RDONLY));
2512 	ASSERT_EQ(0, test_open(merge_do1_fl3, O_RDONLY));
2513 	ASSERT_EQ(0, test_open(merge_do1_fu3, O_RDONLY));
2514 }
2515 
2516 #define for_each_path(path_list, path_entry, i)			\
2517 	for (i = 0, path_entry = *path_list[i]; path_list[i];	\
2518 			path_entry = *path_list[++i])
2519 
TEST_F_FORK(layout2_overlay,same_content_different_file)2520 TEST_F_FORK(layout2_overlay, same_content_different_file)
2521 {
2522 	/* Sets access right on parent directories of both layers. */
2523 	const struct rule layer1_base[] = {
2524 		{
2525 			.path = LOWER_BASE,
2526 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2527 		},
2528 		{
2529 			.path = UPPER_BASE,
2530 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2531 		},
2532 		{
2533 			.path = MERGE_BASE,
2534 			.access = ACCESS_RW,
2535 		},
2536 		{}
2537 	};
2538 	const struct rule layer2_data[] = {
2539 		{
2540 			.path = LOWER_DATA,
2541 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2542 		},
2543 		{
2544 			.path = UPPER_DATA,
2545 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2546 		},
2547 		{
2548 			.path = MERGE_DATA,
2549 			.access = ACCESS_RW,
2550 		},
2551 		{}
2552 	};
2553 	/* Sets access right on directories inside both layers. */
2554 	const struct rule layer3_subdirs[] = {
2555 		{
2556 			.path = lower_dl1,
2557 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2558 		},
2559 		{
2560 			.path = lower_do1,
2561 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2562 		},
2563 		{
2564 			.path = upper_du1,
2565 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2566 		},
2567 		{
2568 			.path = upper_do1,
2569 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2570 		},
2571 		{
2572 			.path = merge_dl1,
2573 			.access = ACCESS_RW,
2574 		},
2575 		{
2576 			.path = merge_du1,
2577 			.access = ACCESS_RW,
2578 		},
2579 		{
2580 			.path = merge_do1,
2581 			.access = ACCESS_RW,
2582 		},
2583 		{}
2584 	};
2585 	/* Tighten access rights to the files. */
2586 	const struct rule layer4_files[] = {
2587 		{
2588 			.path = lower_dl1_fl2,
2589 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2590 		},
2591 		{
2592 			.path = lower_do1_fo2,
2593 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2594 		},
2595 		{
2596 			.path = lower_do1_fl3,
2597 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2598 		},
2599 		{
2600 			.path = upper_du1_fu2,
2601 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2602 		},
2603 		{
2604 			.path = upper_do1_fo2,
2605 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2606 		},
2607 		{
2608 			.path = upper_do1_fu3,
2609 			.access = LANDLOCK_ACCESS_FS_READ_FILE,
2610 		},
2611 		{
2612 			.path = merge_dl1_fl2,
2613 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
2614 				LANDLOCK_ACCESS_FS_WRITE_FILE,
2615 		},
2616 		{
2617 			.path = merge_du1_fu2,
2618 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
2619 				LANDLOCK_ACCESS_FS_WRITE_FILE,
2620 		},
2621 		{
2622 			.path = merge_do1_fo2,
2623 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
2624 				LANDLOCK_ACCESS_FS_WRITE_FILE,
2625 		},
2626 		{
2627 			.path = merge_do1_fl3,
2628 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
2629 				LANDLOCK_ACCESS_FS_WRITE_FILE,
2630 		},
2631 		{
2632 			.path = merge_do1_fu3,
2633 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
2634 				LANDLOCK_ACCESS_FS_WRITE_FILE,
2635 		},
2636 		{}
2637 	};
2638 	const struct rule layer5_merge_only[] = {
2639 		{
2640 			.path = MERGE_DATA,
2641 			.access = LANDLOCK_ACCESS_FS_READ_FILE |
2642 				LANDLOCK_ACCESS_FS_WRITE_FILE,
2643 		},
2644 		{}
2645 	};
2646 	int ruleset_fd;
2647 	size_t i;
2648 	const char *path_entry;
2649 
2650 	/* Sets rules on base directories (i.e. outside overlay scope). */
2651 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_base);
2652 	ASSERT_LE(0, ruleset_fd);
2653 	enforce_ruleset(_metadata, ruleset_fd);
2654 	ASSERT_EQ(0, close(ruleset_fd));
2655 
2656 	/* Checks lower layer. */
2657 	for_each_path(lower_base_files, path_entry, i) {
2658 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2659 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2660 	}
2661 	for_each_path(lower_base_directories, path_entry, i) {
2662 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY | O_DIRECTORY));
2663 	}
2664 	for_each_path(lower_sub_files, path_entry, i) {
2665 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2666 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2667 	}
2668 	/* Checks upper layer. */
2669 	for_each_path(upper_base_files, path_entry, i) {
2670 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2671 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2672 	}
2673 	for_each_path(upper_base_directories, path_entry, i) {
2674 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY | O_DIRECTORY));
2675 	}
2676 	for_each_path(upper_sub_files, path_entry, i) {
2677 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2678 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2679 	}
2680 	/*
2681 	 * Checks that access rights are independent from the lower and upper
2682 	 * layers: write access to upper files viewed through the merge point
2683 	 * is still allowed, and write access to lower file viewed (and copied)
2684 	 * through the merge point is still allowed.
2685 	 */
2686 	for_each_path(merge_base_files, path_entry, i) {
2687 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2688 	}
2689 	for_each_path(merge_base_directories, path_entry, i) {
2690 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
2691 	}
2692 	for_each_path(merge_sub_files, path_entry, i) {
2693 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2694 	}
2695 
2696 	/* Sets rules on data directories (i.e. inside overlay scope). */
2697 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_data);
2698 	ASSERT_LE(0, ruleset_fd);
2699 	enforce_ruleset(_metadata, ruleset_fd);
2700 	ASSERT_EQ(0, close(ruleset_fd));
2701 
2702 	/* Checks merge. */
2703 	for_each_path(merge_base_files, path_entry, i) {
2704 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2705 	}
2706 	for_each_path(merge_base_directories, path_entry, i) {
2707 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
2708 	}
2709 	for_each_path(merge_sub_files, path_entry, i) {
2710 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2711 	}
2712 
2713 	/* Same checks with tighter rules. */
2714 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3_subdirs);
2715 	ASSERT_LE(0, ruleset_fd);
2716 	enforce_ruleset(_metadata, ruleset_fd);
2717 	ASSERT_EQ(0, close(ruleset_fd));
2718 
2719 	/* Checks changes for lower layer. */
2720 	for_each_path(lower_base_files, path_entry, i) {
2721 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
2722 	}
2723 	/* Checks changes for upper layer. */
2724 	for_each_path(upper_base_files, path_entry, i) {
2725 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
2726 	}
2727 	/* Checks all merge accesses. */
2728 	for_each_path(merge_base_files, path_entry, i) {
2729 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
2730 	}
2731 	for_each_path(merge_base_directories, path_entry, i) {
2732 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
2733 	}
2734 	for_each_path(merge_sub_files, path_entry, i) {
2735 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2736 	}
2737 
2738 	/* Sets rules directly on overlayed files. */
2739 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer4_files);
2740 	ASSERT_LE(0, ruleset_fd);
2741 	enforce_ruleset(_metadata, ruleset_fd);
2742 	ASSERT_EQ(0, close(ruleset_fd));
2743 
2744 	/* Checks unchanged accesses on lower layer. */
2745 	for_each_path(lower_sub_files, path_entry, i) {
2746 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2747 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2748 	}
2749 	/* Checks unchanged accesses on upper layer. */
2750 	for_each_path(upper_sub_files, path_entry, i) {
2751 		ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2752 		ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2753 	}
2754 	/* Checks all merge accesses. */
2755 	for_each_path(merge_base_files, path_entry, i) {
2756 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
2757 	}
2758 	for_each_path(merge_base_directories, path_entry, i) {
2759 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY | O_DIRECTORY));
2760 	}
2761 	for_each_path(merge_sub_files, path_entry, i) {
2762 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2763 	}
2764 
2765 	/* Only allowes access to the merge hierarchy. */
2766 	ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer5_merge_only);
2767 	ASSERT_LE(0, ruleset_fd);
2768 	enforce_ruleset(_metadata, ruleset_fd);
2769 	ASSERT_EQ(0, close(ruleset_fd));
2770 
2771 	/* Checks new accesses on lower layer. */
2772 	for_each_path(lower_sub_files, path_entry, i) {
2773 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
2774 	}
2775 	/* Checks new accesses on upper layer. */
2776 	for_each_path(upper_sub_files, path_entry, i) {
2777 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
2778 	}
2779 	/* Checks all merge accesses. */
2780 	for_each_path(merge_base_files, path_entry, i) {
2781 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
2782 	}
2783 	for_each_path(merge_base_directories, path_entry, i) {
2784 		ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY | O_DIRECTORY));
2785 	}
2786 	for_each_path(merge_sub_files, path_entry, i) {
2787 		ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2788 	}
2789 }
2790 
2791 TEST_HARNESS_MAIN
2792