1 // SPDX-License-Identifier: GPL-2.0
3 * Landlock tests - Filesystem
5 * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
6 * Copyright © 2020 ANSSI
7 * Copyright © 2020-2021 Microsoft Corporation
12 #include <linux/landlock.h>
15 #include <sys/capability.h>
16 #include <sys/mount.h>
17 #include <sys/prctl.h>
18 #include <sys/sendfile.h>
20 #include <sys/sysmacros.h>
26 int renameat2(int olddirfd, const char *oldpath, int newdirfd,
27 const char *newpath, unsigned int flags)
29 return syscall(__NR_renameat2, olddirfd, oldpath, newdirfd, newpath,
34 #ifndef RENAME_EXCHANGE
35 #define RENAME_EXCHANGE (1 << 1)
39 #define BINARY_PATH "./true"
41 /* Paths (sibling number and depth) */
42 static const char dir_s1d1[] = TMP_DIR "/s1d1";
43 static const char file1_s1d1[] = TMP_DIR "/s1d1/f1";
44 static const char file2_s1d1[] = TMP_DIR "/s1d1/f2";
45 static const char dir_s1d2[] = TMP_DIR "/s1d1/s1d2";
46 static const char file1_s1d2[] = TMP_DIR "/s1d1/s1d2/f1";
47 static const char file2_s1d2[] = TMP_DIR "/s1d1/s1d2/f2";
48 static const char dir_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3";
49 static const char file1_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f1";
50 static const char file2_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f2";
52 static const char dir_s2d1[] = TMP_DIR "/s2d1";
53 static const char file1_s2d1[] = TMP_DIR "/s2d1/f1";
54 static const char dir_s2d2[] = TMP_DIR "/s2d1/s2d2";
55 static const char file1_s2d2[] = TMP_DIR "/s2d1/s2d2/f1";
56 static const char dir_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3";
57 static const char file1_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f1";
58 static const char file2_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f2";
60 static const char dir_s3d1[] = TMP_DIR "/s3d1";
61 /* dir_s3d2 is a mount point. */
62 static const char dir_s3d2[] = TMP_DIR "/s3d1/s3d2";
63 static const char dir_s3d3[] = TMP_DIR "/s3d1/s3d2/s3d3";
90 static void mkdir_parents(struct __test_metadata *const _metadata,
91 const char *const path)
97 ASSERT_NE(path[0], '\0');
98 walker = strdup(path);
99 ASSERT_NE(NULL, walker);
101 for (i = 1; walker[i]; i++) {
102 if (walker[i] != '/')
105 err = mkdir(parent, 0700);
106 ASSERT_FALSE(err && errno != EEXIST)
108 TH_LOG("Failed to create directory \"%s\": %s", parent,
116 static void create_directory(struct __test_metadata *const _metadata,
117 const char *const path)
119 mkdir_parents(_metadata, path);
120 ASSERT_EQ(0, mkdir(path, 0700))
122 TH_LOG("Failed to create directory \"%s\": %s", path,
127 static void create_file(struct __test_metadata *const _metadata,
128 const char *const path)
130 mkdir_parents(_metadata, path);
131 ASSERT_EQ(0, mknod(path, S_IFREG | 0700, 0))
133 TH_LOG("Failed to create file \"%s\": %s", path,
138 static int remove_path(const char *const path)
143 walker = strdup(path);
148 if (unlink(path) && rmdir(path)) {
153 for (i = strlen(walker); i > 0; i--) {
154 if (walker[i] != '/')
159 if (errno != ENOTEMPTY && errno != EBUSY)
163 if (strcmp(walker, TMP_DIR) == 0)
172 static void prepare_layout(struct __test_metadata *const _metadata)
174 disable_caps(_metadata);
176 create_directory(_metadata, TMP_DIR);
179 * Do not pollute the rest of the system: creates a private mount point
180 * for tests relying on pivot_root(2) and move_mount(2).
182 set_cap(_metadata, CAP_SYS_ADMIN);
183 ASSERT_EQ(0, unshare(CLONE_NEWNS));
184 ASSERT_EQ(0, mount("tmp", TMP_DIR, "tmpfs", 0, "size=4m,mode=700"));
185 ASSERT_EQ(0, mount(NULL, TMP_DIR, NULL, MS_PRIVATE | MS_REC, NULL));
186 clear_cap(_metadata, CAP_SYS_ADMIN);
189 static void cleanup_layout(struct __test_metadata *const _metadata)
191 set_cap(_metadata, CAP_SYS_ADMIN);
192 EXPECT_EQ(0, umount(TMP_DIR));
193 clear_cap(_metadata, CAP_SYS_ADMIN);
194 EXPECT_EQ(0, remove_path(TMP_DIR));
197 static void create_layout1(struct __test_metadata *const _metadata)
199 create_file(_metadata, file1_s1d1);
200 create_file(_metadata, file1_s1d2);
201 create_file(_metadata, file1_s1d3);
202 create_file(_metadata, file2_s1d1);
203 create_file(_metadata, file2_s1d2);
204 create_file(_metadata, file2_s1d3);
206 create_file(_metadata, file1_s2d1);
207 create_file(_metadata, file1_s2d2);
208 create_file(_metadata, file1_s2d3);
209 create_file(_metadata, file2_s2d3);
211 create_directory(_metadata, dir_s3d2);
212 set_cap(_metadata, CAP_SYS_ADMIN);
213 ASSERT_EQ(0, mount("tmp", dir_s3d2, "tmpfs", 0, "size=4m,mode=700"));
214 clear_cap(_metadata, CAP_SYS_ADMIN);
216 ASSERT_EQ(0, mkdir(dir_s3d3, 0700));
219 static void remove_layout1(struct __test_metadata *const _metadata)
221 EXPECT_EQ(0, remove_path(file2_s1d3));
222 EXPECT_EQ(0, remove_path(file2_s1d2));
223 EXPECT_EQ(0, remove_path(file2_s1d1));
224 EXPECT_EQ(0, remove_path(file1_s1d3));
225 EXPECT_EQ(0, remove_path(file1_s1d2));
226 EXPECT_EQ(0, remove_path(file1_s1d1));
228 EXPECT_EQ(0, remove_path(file2_s2d3));
229 EXPECT_EQ(0, remove_path(file1_s2d3));
230 EXPECT_EQ(0, remove_path(file1_s2d2));
231 EXPECT_EQ(0, remove_path(file1_s2d1));
233 EXPECT_EQ(0, remove_path(dir_s3d3));
234 set_cap(_metadata, CAP_SYS_ADMIN);
236 clear_cap(_metadata, CAP_SYS_ADMIN);
237 EXPECT_EQ(0, remove_path(dir_s3d2));
240 /* clang-format off */
242 /* clang-format on */
244 FIXTURE_SETUP(layout1)
246 prepare_layout(_metadata);
248 create_layout1(_metadata);
251 FIXTURE_TEARDOWN(layout1)
253 remove_layout1(_metadata);
255 cleanup_layout(_metadata);
259 * This helper enables to use the ASSERT_* macros and print the line number
260 * pointing to the test caller.
262 static int test_open_rel(const int dirfd, const char *const path,
267 /* Works with file and directories. */
268 fd = openat(dirfd, path, flags | O_CLOEXEC);
272 * Mixing error codes from close(2) and open(2) should not lead to any
273 * (access type) confusion for this test.
280 static int test_open(const char *const path, const int flags)
282 return test_open_rel(AT_FDCWD, path, flags);
285 TEST_F_FORK(layout1, no_restriction)
287 ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
288 ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
289 ASSERT_EQ(0, test_open(file2_s1d1, O_RDONLY));
290 ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
291 ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
292 ASSERT_EQ(0, test_open(file2_s1d2, O_RDONLY));
293 ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
294 ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
296 ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
297 ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
298 ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
299 ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
300 ASSERT_EQ(0, test_open(dir_s2d3, O_RDONLY));
301 ASSERT_EQ(0, test_open(file1_s2d3, O_RDONLY));
303 ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
304 ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
305 ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
308 TEST_F_FORK(layout1, inval)
310 struct landlock_path_beneath_attr path_beneath = {
311 .allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
312 LANDLOCK_ACCESS_FS_WRITE_FILE,
315 struct landlock_ruleset_attr ruleset_attr = {
316 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |
317 LANDLOCK_ACCESS_FS_WRITE_FILE,
321 path_beneath.parent_fd =
322 open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
323 ASSERT_LE(0, path_beneath.parent_fd);
325 ruleset_fd = open(dir_s1d1, O_PATH | O_DIRECTORY | O_CLOEXEC);
326 ASSERT_LE(0, ruleset_fd);
327 ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
329 /* Returns EBADF because ruleset_fd is not a landlock-ruleset FD. */
330 ASSERT_EQ(EBADF, errno);
331 ASSERT_EQ(0, close(ruleset_fd));
333 ruleset_fd = open(dir_s1d1, O_DIRECTORY | O_CLOEXEC);
334 ASSERT_LE(0, ruleset_fd);
335 ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
337 /* Returns EBADFD because ruleset_fd is not a valid ruleset. */
338 ASSERT_EQ(EBADFD, errno);
339 ASSERT_EQ(0, close(ruleset_fd));
341 /* Gets a real ruleset. */
343 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
344 ASSERT_LE(0, ruleset_fd);
345 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
347 ASSERT_EQ(0, close(path_beneath.parent_fd));
349 /* Tests without O_PATH. */
350 path_beneath.parent_fd = open(dir_s1d2, O_DIRECTORY | O_CLOEXEC);
351 ASSERT_LE(0, path_beneath.parent_fd);
352 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
354 ASSERT_EQ(0, close(path_beneath.parent_fd));
356 /* Tests with a ruleset FD. */
357 path_beneath.parent_fd = ruleset_fd;
358 ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
360 ASSERT_EQ(EBADFD, errno);
362 /* Checks unhandled allowed_access. */
363 path_beneath.parent_fd =
364 open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
365 ASSERT_LE(0, path_beneath.parent_fd);
367 /* Test with legitimate values. */
368 path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_EXECUTE;
369 ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
371 ASSERT_EQ(EINVAL, errno);
372 path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_EXECUTE;
374 /* Test with unknown (64-bits) value. */
375 path_beneath.allowed_access |= (1ULL << 60);
376 ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
378 ASSERT_EQ(EINVAL, errno);
379 path_beneath.allowed_access &= ~(1ULL << 60);
381 /* Test with no access. */
382 path_beneath.allowed_access = 0;
383 ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
385 ASSERT_EQ(ENOMSG, errno);
386 path_beneath.allowed_access &= ~(1ULL << 60);
388 ASSERT_EQ(0, close(path_beneath.parent_fd));
390 /* Enforces the ruleset. */
391 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
392 ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
394 ASSERT_EQ(0, close(ruleset_fd));
397 /* clang-format off */
399 #define ACCESS_FILE ( \
400 LANDLOCK_ACCESS_FS_EXECUTE | \
401 LANDLOCK_ACCESS_FS_WRITE_FILE | \
402 LANDLOCK_ACCESS_FS_READ_FILE)
404 #define ACCESS_LAST LANDLOCK_ACCESS_FS_MAKE_SYM
406 #define ACCESS_ALL ( \
408 LANDLOCK_ACCESS_FS_READ_DIR | \
409 LANDLOCK_ACCESS_FS_REMOVE_DIR | \
410 LANDLOCK_ACCESS_FS_REMOVE_FILE | \
411 LANDLOCK_ACCESS_FS_MAKE_CHAR | \
412 LANDLOCK_ACCESS_FS_MAKE_DIR | \
413 LANDLOCK_ACCESS_FS_MAKE_REG | \
414 LANDLOCK_ACCESS_FS_MAKE_SOCK | \
415 LANDLOCK_ACCESS_FS_MAKE_FIFO | \
416 LANDLOCK_ACCESS_FS_MAKE_BLOCK | \
419 /* clang-format on */
421 TEST_F_FORK(layout1, file_and_dir_access_rights)
425 struct landlock_path_beneath_attr path_beneath_file = {},
426 path_beneath_dir = {};
427 struct landlock_ruleset_attr ruleset_attr = {
428 .handled_access_fs = ACCESS_ALL,
430 const int ruleset_fd =
431 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
433 ASSERT_LE(0, ruleset_fd);
435 /* Tests access rights for files. */
436 path_beneath_file.parent_fd = open(file1_s1d2, O_PATH | O_CLOEXEC);
437 ASSERT_LE(0, path_beneath_file.parent_fd);
439 /* Tests access rights for directories. */
440 path_beneath_dir.parent_fd =
441 open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
442 ASSERT_LE(0, path_beneath_dir.parent_fd);
444 for (access = 1; access <= ACCESS_LAST; access <<= 1) {
445 path_beneath_dir.allowed_access = access;
446 ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
447 LANDLOCK_RULE_PATH_BENEATH,
448 &path_beneath_dir, 0));
450 path_beneath_file.allowed_access = access;
451 err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
452 &path_beneath_file, 0);
453 if (access & ACCESS_FILE) {
457 ASSERT_EQ(EINVAL, errno);
460 ASSERT_EQ(0, close(path_beneath_file.parent_fd));
461 ASSERT_EQ(0, close(path_beneath_dir.parent_fd));
462 ASSERT_EQ(0, close(ruleset_fd));
465 TEST_F_FORK(layout1, unknown_access_rights)
469 for (access_mask = 1ULL << 63; access_mask != ACCESS_LAST;
471 struct landlock_ruleset_attr ruleset_attr = {
472 .handled_access_fs = access_mask,
475 ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
476 sizeof(ruleset_attr), 0));
477 ASSERT_EQ(EINVAL, errno);
481 static void add_path_beneath(struct __test_metadata *const _metadata,
482 const int ruleset_fd, const __u64 allowed_access,
483 const char *const path)
485 struct landlock_path_beneath_attr path_beneath = {
486 .allowed_access = allowed_access,
489 path_beneath.parent_fd = open(path, O_PATH | O_CLOEXEC);
490 ASSERT_LE(0, path_beneath.parent_fd)
492 TH_LOG("Failed to open directory \"%s\": %s", path,
495 ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
498 TH_LOG("Failed to update the ruleset with \"%s\": %s", path,
501 ASSERT_EQ(0, close(path_beneath.parent_fd));
509 /* clang-format off */
511 #define ACCESS_RO ( \
512 LANDLOCK_ACCESS_FS_READ_FILE | \
513 LANDLOCK_ACCESS_FS_READ_DIR)
515 #define ACCESS_RW ( \
517 LANDLOCK_ACCESS_FS_WRITE_FILE)
519 /* clang-format on */
521 static int create_ruleset(struct __test_metadata *const _metadata,
522 const __u64 handled_access_fs,
523 const struct rule rules[])
526 struct landlock_ruleset_attr ruleset_attr = {
527 .handled_access_fs = handled_access_fs,
530 ASSERT_NE(NULL, rules)
532 TH_LOG("No rule list");
534 ASSERT_NE(NULL, rules[0].path)
536 TH_LOG("Empty rule list");
540 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
541 ASSERT_LE(0, ruleset_fd)
543 TH_LOG("Failed to create a ruleset: %s", strerror(errno));
546 for (i = 0; rules[i].path; i++) {
547 add_path_beneath(_metadata, ruleset_fd, rules[i].access,
553 static void enforce_ruleset(struct __test_metadata *const _metadata,
554 const int ruleset_fd)
556 ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
557 ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0))
559 TH_LOG("Failed to enforce ruleset: %s", strerror(errno));
563 TEST_F_FORK(layout1, proc_nsfs)
565 const struct rule rules[] = {
568 .access = LANDLOCK_ACCESS_FS_READ_FILE |
569 LANDLOCK_ACCESS_FS_WRITE_FILE,
573 struct landlock_path_beneath_attr path_beneath;
574 const int ruleset_fd = create_ruleset(
575 _metadata, rules[0].access | LANDLOCK_ACCESS_FS_READ_DIR,
578 ASSERT_LE(0, ruleset_fd);
579 ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
581 enforce_ruleset(_metadata, ruleset_fd);
583 ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
584 ASSERT_EQ(EACCES, test_open("/dev", O_RDONLY));
585 ASSERT_EQ(0, test_open("/dev/null", O_RDONLY));
586 ASSERT_EQ(EACCES, test_open("/dev/full", O_RDONLY));
588 ASSERT_EQ(EACCES, test_open("/proc", O_RDONLY));
589 ASSERT_EQ(EACCES, test_open("/proc/self", O_RDONLY));
590 ASSERT_EQ(EACCES, test_open("/proc/self/ns", O_RDONLY));
592 * Because nsfs is an internal filesystem, /proc/self/ns/mnt is a
593 * disconnected path. Such path cannot be identified and must then be
596 ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
599 * Checks that it is not possible to add nsfs-like filesystem
600 * references to a ruleset.
602 path_beneath.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
603 LANDLOCK_ACCESS_FS_WRITE_FILE,
604 path_beneath.parent_fd = open("/proc/self/ns/mnt", O_PATH | O_CLOEXEC);
605 ASSERT_LE(0, path_beneath.parent_fd);
606 ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
608 ASSERT_EQ(EBADFD, errno);
609 ASSERT_EQ(0, close(path_beneath.parent_fd));
612 TEST_F_FORK(layout1, unpriv)
614 const struct rule rules[] = {
623 drop_caps(_metadata);
625 ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
626 ASSERT_LE(0, ruleset_fd);
627 ASSERT_EQ(-1, landlock_restrict_self(ruleset_fd, 0));
628 ASSERT_EQ(EPERM, errno);
630 /* enforce_ruleset() calls prctl(no_new_privs). */
631 enforce_ruleset(_metadata, ruleset_fd);
632 ASSERT_EQ(0, close(ruleset_fd));
635 TEST_F_FORK(layout1, effective_access)
637 const struct rule rules[] = {
644 .access = LANDLOCK_ACCESS_FS_READ_FILE |
645 LANDLOCK_ACCESS_FS_WRITE_FILE,
649 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
653 ASSERT_LE(0, ruleset_fd);
654 enforce_ruleset(_metadata, ruleset_fd);
655 ASSERT_EQ(0, close(ruleset_fd));
657 /* Tests on a directory (with or without O_PATH). */
658 ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
659 ASSERT_EQ(0, test_open("/", O_RDONLY | O_PATH));
660 ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
661 ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_PATH));
662 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
663 ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY | O_PATH));
665 ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
666 ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
667 ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
668 ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
670 /* Tests on a file (with or without O_PATH). */
671 ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY));
672 ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_PATH));
674 ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
676 /* Checks effective read and write actions. */
677 reg_fd = open(file1_s2d2, O_RDWR | O_CLOEXEC);
678 ASSERT_LE(0, reg_fd);
679 ASSERT_EQ(1, write(reg_fd, ".", 1));
680 ASSERT_LE(0, lseek(reg_fd, 0, SEEK_SET));
681 ASSERT_EQ(1, read(reg_fd, &buf, 1));
683 ASSERT_EQ(0, close(reg_fd));
685 /* Just in case, double-checks effective actions. */
686 reg_fd = open(file1_s2d2, O_RDONLY | O_CLOEXEC);
687 ASSERT_LE(0, reg_fd);
688 ASSERT_EQ(-1, write(reg_fd, &buf, 1));
689 ASSERT_EQ(EBADF, errno);
690 ASSERT_EQ(0, close(reg_fd));
693 TEST_F_FORK(layout1, unhandled_access)
695 const struct rule rules[] = {
702 /* Here, we only handle read accesses, not write accesses. */
703 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
705 ASSERT_LE(0, ruleset_fd);
706 enforce_ruleset(_metadata, ruleset_fd);
707 ASSERT_EQ(0, close(ruleset_fd));
710 * Because the policy does not handle LANDLOCK_ACCESS_FS_WRITE_FILE,
711 * opening for write-only should be allowed, but not read-write.
713 ASSERT_EQ(0, test_open(file1_s1d1, O_WRONLY));
714 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
716 ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
717 ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
720 TEST_F_FORK(layout1, ruleset_overlap)
722 const struct rule rules[] = {
723 /* These rules should be ORed among them. */
726 .access = LANDLOCK_ACCESS_FS_READ_FILE |
727 LANDLOCK_ACCESS_FS_WRITE_FILE,
731 .access = LANDLOCK_ACCESS_FS_READ_FILE |
732 LANDLOCK_ACCESS_FS_READ_DIR,
736 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
738 ASSERT_LE(0, ruleset_fd);
739 enforce_ruleset(_metadata, ruleset_fd);
740 ASSERT_EQ(0, close(ruleset_fd));
742 /* Checks s1d1 hierarchy. */
743 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
744 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
745 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
746 ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
748 /* Checks s1d2 hierarchy. */
749 ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
750 ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
751 ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
752 ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
754 /* Checks s1d3 hierarchy. */
755 ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
756 ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
757 ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
758 ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
761 TEST_F_FORK(layout1, non_overlapping_accesses)
763 const struct rule layer1[] = {
766 .access = LANDLOCK_ACCESS_FS_MAKE_REG,
770 const struct rule layer2[] = {
773 .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
779 ASSERT_EQ(0, unlink(file1_s1d1));
780 ASSERT_EQ(0, unlink(file1_s1d2));
783 create_ruleset(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, layer1);
784 ASSERT_LE(0, ruleset_fd);
785 enforce_ruleset(_metadata, ruleset_fd);
786 ASSERT_EQ(0, close(ruleset_fd));
788 ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
789 ASSERT_EQ(EACCES, errno);
790 ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
791 ASSERT_EQ(0, unlink(file1_s1d2));
793 ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_REMOVE_FILE,
795 ASSERT_LE(0, ruleset_fd);
796 enforce_ruleset(_metadata, ruleset_fd);
797 ASSERT_EQ(0, close(ruleset_fd));
799 /* Unchanged accesses for file creation. */
800 ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
801 ASSERT_EQ(EACCES, errno);
802 ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
804 /* Checks file removing. */
805 ASSERT_EQ(-1, unlink(file1_s1d2));
806 ASSERT_EQ(EACCES, errno);
807 ASSERT_EQ(0, unlink(file1_s1d3));
810 TEST_F_FORK(layout1, interleaved_masked_accesses)
813 * Checks overly restrictive rules:
814 * layer 1: allows R s1d1/s1d2/s1d3/file1
815 * layer 2: allows RW s1d1/s1d2/s1d3
818 * layer 3: allows R s1d1
819 * layer 4: allows R s1d1/s1d2
821 * layer 5: allows R s1d1/s1d2
822 * layer 6: allows X ----
823 * layer 7: allows W s1d1/s1d2
826 const struct rule layer1_read[] = {
827 /* Allows read access to file1_s1d3 with the first layer. */
830 .access = LANDLOCK_ACCESS_FS_READ_FILE,
834 /* First rule with write restrictions. */
835 const struct rule layer2_read_write[] = {
836 /* Start by granting read-write access via its parent directory... */
839 .access = LANDLOCK_ACCESS_FS_READ_FILE |
840 LANDLOCK_ACCESS_FS_WRITE_FILE,
842 /* ...but also denies read access via its grandparent directory. */
845 .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
849 const struct rule layer3_read[] = {
850 /* Allows read access via its great-grandparent directory. */
853 .access = LANDLOCK_ACCESS_FS_READ_FILE,
857 const struct rule layer4_read_write[] = {
859 * Try to confuse the deny access by denying write (but not
860 * read) access via its grandparent directory.
864 .access = LANDLOCK_ACCESS_FS_READ_FILE,
868 const struct rule layer5_read[] = {
870 * Try to override layer2's deny read access by explicitly
871 * allowing read access via file1_s1d3's grandparent.
875 .access = LANDLOCK_ACCESS_FS_READ_FILE,
879 const struct rule layer6_execute[] = {
881 * Restricts an unrelated file hierarchy with a new access
882 * (non-overlapping) type.
886 .access = LANDLOCK_ACCESS_FS_EXECUTE,
890 const struct rule layer7_read_write[] = {
892 * Finally, denies read access to file1_s1d3 via its
897 .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
903 ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
905 ASSERT_LE(0, ruleset_fd);
906 enforce_ruleset(_metadata, ruleset_fd);
907 ASSERT_EQ(0, close(ruleset_fd));
909 /* Checks that read access is granted for file1_s1d3 with layer 1. */
910 ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
911 ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
912 ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
914 ruleset_fd = create_ruleset(_metadata,
915 LANDLOCK_ACCESS_FS_READ_FILE |
916 LANDLOCK_ACCESS_FS_WRITE_FILE,
918 ASSERT_LE(0, ruleset_fd);
919 enforce_ruleset(_metadata, ruleset_fd);
920 ASSERT_EQ(0, close(ruleset_fd));
922 /* Checks that previous access rights are unchanged with layer 2. */
923 ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
924 ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
925 ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
927 ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
929 ASSERT_LE(0, ruleset_fd);
930 enforce_ruleset(_metadata, ruleset_fd);
931 ASSERT_EQ(0, close(ruleset_fd));
933 /* Checks that previous access rights are unchanged with layer 3. */
934 ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
935 ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
936 ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
938 /* This time, denies write access for the file hierarchy. */
939 ruleset_fd = create_ruleset(_metadata,
940 LANDLOCK_ACCESS_FS_READ_FILE |
941 LANDLOCK_ACCESS_FS_WRITE_FILE,
943 ASSERT_LE(0, ruleset_fd);
944 enforce_ruleset(_metadata, ruleset_fd);
945 ASSERT_EQ(0, close(ruleset_fd));
948 * Checks that the only change with layer 4 is that write access is
951 ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
952 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
953 ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
954 ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
956 ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
958 ASSERT_LE(0, ruleset_fd);
959 enforce_ruleset(_metadata, ruleset_fd);
960 ASSERT_EQ(0, close(ruleset_fd));
962 /* Checks that previous access rights are unchanged with layer 5. */
963 ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
964 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
965 ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
966 ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
968 ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_EXECUTE,
970 ASSERT_LE(0, ruleset_fd);
971 enforce_ruleset(_metadata, ruleset_fd);
972 ASSERT_EQ(0, close(ruleset_fd));
974 /* Checks that previous access rights are unchanged with layer 6. */
975 ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
976 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
977 ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
978 ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
980 ruleset_fd = create_ruleset(_metadata,
981 LANDLOCK_ACCESS_FS_READ_FILE |
982 LANDLOCK_ACCESS_FS_WRITE_FILE,
984 ASSERT_LE(0, ruleset_fd);
985 enforce_ruleset(_metadata, ruleset_fd);
986 ASSERT_EQ(0, close(ruleset_fd));
988 /* Checks read access is now denied with layer 7. */
989 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
990 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
991 ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
992 ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
995 TEST_F_FORK(layout1, inherit_subset)
997 const struct rule rules[] = {
1000 .access = LANDLOCK_ACCESS_FS_READ_FILE |
1001 LANDLOCK_ACCESS_FS_READ_DIR,
1005 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1007 ASSERT_LE(0, ruleset_fd);
1008 enforce_ruleset(_metadata, ruleset_fd);
1010 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1011 ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1013 /* Write access is forbidden. */
1014 ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1015 /* Readdir access is allowed. */
1016 ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1018 /* Write access is forbidden. */
1019 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1020 /* Readdir access is allowed. */
1021 ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1024 * Tests shared rule extension: the following rules should not grant
1025 * any new access, only remove some. Once enforced, these rules are
1026 * ANDed with the previous ones.
1028 add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
1031 * According to ruleset_fd, dir_s1d2 should now have the
1032 * LANDLOCK_ACCESS_FS_READ_FILE and LANDLOCK_ACCESS_FS_WRITE_FILE
1033 * access rights (even if this directory is opened a second time).
1034 * However, when enforcing this updated ruleset, the ruleset tied to
1035 * the current process (i.e. its domain) will still only have the
1036 * dir_s1d2 with LANDLOCK_ACCESS_FS_READ_FILE and
1037 * LANDLOCK_ACCESS_FS_READ_DIR accesses, but
1038 * LANDLOCK_ACCESS_FS_WRITE_FILE must not be allowed because it would
1039 * be a privilege escalation.
1041 enforce_ruleset(_metadata, ruleset_fd);
1043 /* Same tests and results as above. */
1044 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1045 ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1047 /* It is still forbidden to write in file1_s1d2. */
1048 ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1049 /* Readdir access is still allowed. */
1050 ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1052 /* It is still forbidden to write in file1_s1d3. */
1053 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1054 /* Readdir access is still allowed. */
1055 ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1058 * Try to get more privileges by adding new access rights to the parent
1059 * directory: dir_s1d1.
1061 add_path_beneath(_metadata, ruleset_fd, ACCESS_RW, dir_s1d1);
1062 enforce_ruleset(_metadata, ruleset_fd);
1064 /* Same tests and results as above. */
1065 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1066 ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1068 /* It is still forbidden to write in file1_s1d2. */
1069 ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1070 /* Readdir access is still allowed. */
1071 ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1073 /* It is still forbidden to write in file1_s1d3. */
1074 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1075 /* Readdir access is still allowed. */
1076 ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1079 * Now, dir_s1d3 get a new rule tied to it, only allowing
1080 * LANDLOCK_ACCESS_FS_WRITE_FILE. The (kernel internal) difference is
1081 * that there was no rule tied to it before.
1083 add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
1085 enforce_ruleset(_metadata, ruleset_fd);
1086 ASSERT_EQ(0, close(ruleset_fd));
1089 * Same tests and results as above, except for open(dir_s1d3) which is
1090 * now denied because the new rule mask the rule previously inherited
1094 /* Same tests and results as above. */
1095 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1096 ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1098 /* It is still forbidden to write in file1_s1d2. */
1099 ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1100 /* Readdir access is still allowed. */
1101 ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1103 /* It is still forbidden to write in file1_s1d3. */
1104 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1106 * Readdir of dir_s1d3 is still allowed because of the OR policy inside
1109 ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1112 TEST_F_FORK(layout1, inherit_superset)
1114 const struct rule rules[] = {
1117 .access = ACCESS_RO,
1121 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1123 ASSERT_LE(0, ruleset_fd);
1124 enforce_ruleset(_metadata, ruleset_fd);
1126 /* Readdir access is denied for dir_s1d2. */
1127 ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1128 /* Readdir access is allowed for dir_s1d3. */
1129 ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1130 /* File access is allowed for file1_s1d3. */
1131 ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1133 /* Now dir_s1d2, parent of dir_s1d3, gets a new rule tied to it. */
1134 add_path_beneath(_metadata, ruleset_fd,
1135 LANDLOCK_ACCESS_FS_READ_FILE |
1136 LANDLOCK_ACCESS_FS_READ_DIR,
1138 enforce_ruleset(_metadata, ruleset_fd);
1139 ASSERT_EQ(0, close(ruleset_fd));
1141 /* Readdir access is still denied for dir_s1d2. */
1142 ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1143 /* Readdir access is still allowed for dir_s1d3. */
1144 ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1145 /* File access is still allowed for file1_s1d3. */
1146 ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1149 TEST_F_FORK(layout1, max_layers)
1152 const struct rule rules[] = {
1155 .access = ACCESS_RO,
1159 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1161 ASSERT_LE(0, ruleset_fd);
1162 for (i = 0; i < 16; i++)
1163 enforce_ruleset(_metadata, ruleset_fd);
1165 for (i = 0; i < 2; i++) {
1166 err = landlock_restrict_self(ruleset_fd, 0);
1168 ASSERT_EQ(E2BIG, errno);
1170 ASSERT_EQ(0, close(ruleset_fd));
1173 TEST_F_FORK(layout1, empty_or_same_ruleset)
1175 struct landlock_ruleset_attr ruleset_attr = {};
1178 /* Tests empty handled_access_fs. */
1180 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
1181 ASSERT_LE(-1, ruleset_fd);
1182 ASSERT_EQ(ENOMSG, errno);
1184 /* Enforces policy which deny read access to all files. */
1185 ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE;
1187 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
1188 ASSERT_LE(0, ruleset_fd);
1189 enforce_ruleset(_metadata, ruleset_fd);
1190 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1191 ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1193 /* Nests a policy which deny read access to all directories. */
1194 ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR;
1196 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
1197 ASSERT_LE(0, ruleset_fd);
1198 enforce_ruleset(_metadata, ruleset_fd);
1199 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1200 ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1202 /* Enforces a second time with the same ruleset. */
1203 enforce_ruleset(_metadata, ruleset_fd);
1204 ASSERT_EQ(0, close(ruleset_fd));
1207 TEST_F_FORK(layout1, rule_on_mountpoint)
1209 const struct rule rules[] = {
1212 .access = ACCESS_RO,
1215 /* dir_s3d2 is a mount point. */
1217 .access = ACCESS_RO,
1221 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1223 ASSERT_LE(0, ruleset_fd);
1224 enforce_ruleset(_metadata, ruleset_fd);
1225 ASSERT_EQ(0, close(ruleset_fd));
1227 ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1229 ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
1231 ASSERT_EQ(EACCES, test_open(dir_s3d1, O_RDONLY));
1232 ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
1233 ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
1236 TEST_F_FORK(layout1, rule_over_mountpoint)
1238 const struct rule rules[] = {
1241 .access = ACCESS_RO,
1244 /* dir_s3d2 is a mount point. */
1246 .access = ACCESS_RO,
1250 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1252 ASSERT_LE(0, ruleset_fd);
1253 enforce_ruleset(_metadata, ruleset_fd);
1254 ASSERT_EQ(0, close(ruleset_fd));
1256 ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1258 ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
1260 ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
1261 ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
1262 ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
1266 * This test verifies that we can apply a landlock rule on the root directory
1267 * (which might require special handling).
1269 TEST_F_FORK(layout1, rule_over_root_allow_then_deny)
1271 struct rule rules[] = {
1274 .access = ACCESS_RO,
1278 int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1280 ASSERT_LE(0, ruleset_fd);
1281 enforce_ruleset(_metadata, ruleset_fd);
1282 ASSERT_EQ(0, close(ruleset_fd));
1284 /* Checks allowed access. */
1285 ASSERT_EQ(0, test_open("/", O_RDONLY));
1286 ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1288 rules[0].access = LANDLOCK_ACCESS_FS_READ_FILE;
1289 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1290 ASSERT_LE(0, ruleset_fd);
1291 enforce_ruleset(_metadata, ruleset_fd);
1292 ASSERT_EQ(0, close(ruleset_fd));
1294 /* Checks denied access (on a directory). */
1295 ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1296 ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1299 TEST_F_FORK(layout1, rule_over_root_deny)
1301 const struct rule rules[] = {
1304 .access = LANDLOCK_ACCESS_FS_READ_FILE,
1308 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1310 ASSERT_LE(0, ruleset_fd);
1311 enforce_ruleset(_metadata, ruleset_fd);
1312 ASSERT_EQ(0, close(ruleset_fd));
1314 /* Checks denied access (on a directory). */
1315 ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1316 ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1319 TEST_F_FORK(layout1, rule_inside_mount_ns)
1321 const struct rule rules[] = {
1324 .access = ACCESS_RO,
1330 set_cap(_metadata, CAP_SYS_ADMIN);
1331 ASSERT_EQ(0, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3))
1333 TH_LOG("Failed to pivot root: %s", strerror(errno));
1335 ASSERT_EQ(0, chdir("/"));
1336 clear_cap(_metadata, CAP_SYS_ADMIN);
1338 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1339 ASSERT_LE(0, ruleset_fd);
1340 enforce_ruleset(_metadata, ruleset_fd);
1341 ASSERT_EQ(0, close(ruleset_fd));
1343 ASSERT_EQ(0, test_open("s3d3", O_RDONLY));
1344 ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1347 TEST_F_FORK(layout1, mount_and_pivot)
1349 const struct rule rules[] = {
1352 .access = ACCESS_RO,
1356 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1358 ASSERT_LE(0, ruleset_fd);
1359 enforce_ruleset(_metadata, ruleset_fd);
1360 ASSERT_EQ(0, close(ruleset_fd));
1362 set_cap(_metadata, CAP_SYS_ADMIN);
1363 ASSERT_EQ(-1, mount(NULL, dir_s3d2, NULL, MS_RDONLY, NULL));
1364 ASSERT_EQ(EPERM, errno);
1365 ASSERT_EQ(-1, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3));
1366 ASSERT_EQ(EPERM, errno);
1367 clear_cap(_metadata, CAP_SYS_ADMIN);
1370 TEST_F_FORK(layout1, move_mount)
1372 const struct rule rules[] = {
1375 .access = ACCESS_RO,
1379 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1381 ASSERT_LE(0, ruleset_fd);
1383 set_cap(_metadata, CAP_SYS_ADMIN);
1384 ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1387 TH_LOG("Failed to move mount: %s", strerror(errno));
1390 ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD,
1392 clear_cap(_metadata, CAP_SYS_ADMIN);
1394 enforce_ruleset(_metadata, ruleset_fd);
1395 ASSERT_EQ(0, close(ruleset_fd));
1397 set_cap(_metadata, CAP_SYS_ADMIN);
1398 ASSERT_EQ(-1, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1400 ASSERT_EQ(EPERM, errno);
1401 clear_cap(_metadata, CAP_SYS_ADMIN);
1404 TEST_F_FORK(layout1, release_inodes)
1406 const struct rule rules[] = {
1409 .access = ACCESS_RO,
1413 .access = ACCESS_RO,
1417 .access = ACCESS_RO,
1421 const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1423 ASSERT_LE(0, ruleset_fd);
1424 /* Unmount a file hierarchy while it is being used by a ruleset. */
1425 set_cap(_metadata, CAP_SYS_ADMIN);
1426 ASSERT_EQ(0, umount(dir_s3d2));
1427 clear_cap(_metadata, CAP_SYS_ADMIN);
1429 enforce_ruleset(_metadata, ruleset_fd);
1430 ASSERT_EQ(0, close(ruleset_fd));
1432 ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
1433 ASSERT_EQ(EACCES, test_open(dir_s3d2, O_RDONLY));
1434 /* This dir_s3d3 would not be allowed and does not exist anyway. */
1435 ASSERT_EQ(ENOENT, test_open(dir_s3d3, O_RDONLY));
1438 enum relative_access {
1445 static void test_relative_path(struct __test_metadata *const _metadata,
1446 const enum relative_access rel)
1449 * Common layer to check that chroot doesn't ignore it (i.e. a chroot
1450 * is not a disconnected root directory).
1452 const struct rule layer1_base[] = {
1455 .access = ACCESS_RO,
1459 const struct rule layer2_subs[] = {
1462 .access = ACCESS_RO,
1466 .access = ACCESS_RO,
1470 int dirfd, ruleset_fd;
1472 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_base);
1473 ASSERT_LE(0, ruleset_fd);
1474 enforce_ruleset(_metadata, ruleset_fd);
1475 ASSERT_EQ(0, close(ruleset_fd));
1477 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_subs);
1479 ASSERT_LE(0, ruleset_fd);
1484 case REL_CHROOT_ONLY:
1485 ASSERT_EQ(0, chdir(dir_s2d2));
1487 case REL_CHROOT_CHDIR:
1488 ASSERT_EQ(0, chdir(dir_s1d2));
1495 set_cap(_metadata, CAP_SYS_CHROOT);
1496 enforce_ruleset(_metadata, ruleset_fd);
1500 dirfd = open(dir_s1d2, O_DIRECTORY);
1501 ASSERT_LE(0, dirfd);
1504 ASSERT_EQ(0, chdir(dir_s1d2));
1507 case REL_CHROOT_ONLY:
1508 /* Do chroot into dir_s1d2 (relative to dir_s2d2). */
1509 ASSERT_EQ(0, chroot("../../s1d1/s1d2"))
1511 TH_LOG("Failed to chroot: %s", strerror(errno));
1515 case REL_CHROOT_CHDIR:
1516 /* Do chroot into dir_s1d2. */
1517 ASSERT_EQ(0, chroot("."))
1519 TH_LOG("Failed to chroot: %s", strerror(errno));
1525 ASSERT_EQ((rel == REL_CHROOT_CHDIR) ? 0 : EACCES,
1526 test_open_rel(dirfd, "..", O_RDONLY));
1527 ASSERT_EQ(0, test_open_rel(dirfd, ".", O_RDONLY));
1529 if (rel == REL_CHROOT_ONLY) {
1530 /* The current directory is dir_s2d2. */
1531 ASSERT_EQ(0, test_open_rel(dirfd, "./s2d3", O_RDONLY));
1533 /* The current directory is dir_s1d2. */
1534 ASSERT_EQ(0, test_open_rel(dirfd, "./s1d3", O_RDONLY));
1537 if (rel == REL_CHROOT_ONLY || rel == REL_CHROOT_CHDIR) {
1538 /* Checks the root dir_s1d2. */
1539 ASSERT_EQ(0, test_open_rel(dirfd, "/..", O_RDONLY));
1540 ASSERT_EQ(0, test_open_rel(dirfd, "/", O_RDONLY));
1541 ASSERT_EQ(0, test_open_rel(dirfd, "/f1", O_RDONLY));
1542 ASSERT_EQ(0, test_open_rel(dirfd, "/s1d3", O_RDONLY));
1545 if (rel != REL_CHROOT_CHDIR) {
1546 ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s1d1", O_RDONLY));
1547 ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2", O_RDONLY));
1548 ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2/s1d3",
1551 ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s2d1", O_RDONLY));
1552 ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2", O_RDONLY));
1553 ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2/s2d3",
1557 if (rel == REL_OPEN)
1558 ASSERT_EQ(0, close(dirfd));
1559 ASSERT_EQ(0, close(ruleset_fd));
1562 TEST_F_FORK(layout1, relative_open)
1564 test_relative_path(_metadata, REL_OPEN);
1567 TEST_F_FORK(layout1, relative_chdir)
1569 test_relative_path(_metadata, REL_CHDIR);
1572 TEST_F_FORK(layout1, relative_chroot_only)
1574 test_relative_path(_metadata, REL_CHROOT_ONLY);
1577 TEST_F_FORK(layout1, relative_chroot_chdir)
1579 test_relative_path(_metadata, REL_CHROOT_CHDIR);
1582 static void copy_binary(struct __test_metadata *const _metadata,
1583 const char *const dst_path)
1586 struct stat statbuf;
1588 dst_fd = open(dst_path, O_WRONLY | O_TRUNC | O_CLOEXEC);
1589 ASSERT_LE(0, dst_fd)
1591 TH_LOG("Failed to open \"%s\": %s", dst_path, strerror(errno));
1593 src_fd = open(BINARY_PATH, O_RDONLY | O_CLOEXEC);
1594 ASSERT_LE(0, src_fd)
1596 TH_LOG("Failed to open \"" BINARY_PATH "\": %s",
1599 ASSERT_EQ(0, fstat(src_fd, &statbuf));
1600 ASSERT_EQ(statbuf.st_size,
1601 sendfile(dst_fd, src_fd, 0, statbuf.st_size));
1602 ASSERT_EQ(0, close(src_fd));
1603 ASSERT_EQ(0, close(dst_fd));
1606 static void test_execute(struct __test_metadata *const _metadata, const int err,
1607 const char *const path)
1610 char *const argv[] = { (char *)path, NULL };
1611 const pid_t child = fork();
1613 ASSERT_LE(0, child);
1615 ASSERT_EQ(err ? -1 : 0, execve(path, argv, NULL))
1617 TH_LOG("Failed to execute \"%s\": %s", path,
1620 ASSERT_EQ(err, errno);
1621 _exit(_metadata->passed ? 2 : 1);
1624 ASSERT_EQ(child, waitpid(child, &status, 0));
1625 ASSERT_EQ(1, WIFEXITED(status));
1626 ASSERT_EQ(err ? 2 : 0, WEXITSTATUS(status))
1628 TH_LOG("Unexpected return code for \"%s\": %s", path,
1633 TEST_F_FORK(layout1, execute)
1635 const struct rule rules[] = {
1638 .access = LANDLOCK_ACCESS_FS_EXECUTE,
1642 const int ruleset_fd =
1643 create_ruleset(_metadata, rules[0].access, rules);
1645 ASSERT_LE(0, ruleset_fd);
1646 copy_binary(_metadata, file1_s1d1);
1647 copy_binary(_metadata, file1_s1d2);
1648 copy_binary(_metadata, file1_s1d3);
1650 enforce_ruleset(_metadata, ruleset_fd);
1651 ASSERT_EQ(0, close(ruleset_fd));
1653 ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1654 ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
1655 test_execute(_metadata, EACCES, file1_s1d1);
1657 ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
1658 ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
1659 test_execute(_metadata, 0, file1_s1d2);
1661 ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
1662 ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1663 test_execute(_metadata, 0, file1_s1d3);
1666 TEST_F_FORK(layout1, link)
1668 const struct rule layer1[] = {
1671 .access = LANDLOCK_ACCESS_FS_MAKE_REG,
1675 const struct rule layer2[] = {
1678 .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1682 int ruleset_fd = create_ruleset(_metadata, layer1[0].access, layer1);
1684 ASSERT_LE(0, ruleset_fd);
1686 ASSERT_EQ(0, unlink(file1_s1d1));
1687 ASSERT_EQ(0, unlink(file1_s1d2));
1688 ASSERT_EQ(0, unlink(file1_s1d3));
1690 enforce_ruleset(_metadata, ruleset_fd);
1691 ASSERT_EQ(0, close(ruleset_fd));
1693 ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
1694 ASSERT_EQ(EACCES, errno);
1696 /* Denies linking because of reparenting. */
1697 ASSERT_EQ(-1, link(file1_s2d1, file1_s1d2));
1698 ASSERT_EQ(EXDEV, errno);
1699 ASSERT_EQ(-1, link(file2_s1d2, file1_s1d3));
1700 ASSERT_EQ(EXDEV, errno);
1701 ASSERT_EQ(-1, link(file2_s1d3, file1_s1d2));
1702 ASSERT_EQ(EXDEV, errno);
1704 ASSERT_EQ(0, link(file2_s1d2, file1_s1d2));
1705 ASSERT_EQ(0, link(file2_s1d3, file1_s1d3));
1707 /* Prepares for next unlinks. */
1708 ASSERT_EQ(0, unlink(file2_s1d2));
1709 ASSERT_EQ(0, unlink(file2_s1d3));
1711 ruleset_fd = create_ruleset(_metadata, layer2[0].access, layer2);
1712 ASSERT_LE(0, ruleset_fd);
1713 enforce_ruleset(_metadata, ruleset_fd);
1714 ASSERT_EQ(0, close(ruleset_fd));
1716 /* Checks that linkind doesn't require the ability to delete a file. */
1717 ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
1718 ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
1721 TEST_F_FORK(layout1, rename_file)
1723 const struct rule rules[] = {
1726 .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1730 .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1734 const int ruleset_fd =
1735 create_ruleset(_metadata, rules[0].access, rules);
1737 ASSERT_LE(0, ruleset_fd);
1739 ASSERT_EQ(0, unlink(file1_s1d2));
1741 enforce_ruleset(_metadata, ruleset_fd);
1742 ASSERT_EQ(0, close(ruleset_fd));
1745 * Tries to replace a file, from a directory that allows file removal,
1746 * but to a different directory (which also allows file removal).
1748 ASSERT_EQ(-1, rename(file1_s2d3, file1_s1d3));
1749 ASSERT_EQ(EXDEV, errno);
1750 ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d3,
1752 ASSERT_EQ(EXDEV, errno);
1753 ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, dir_s1d3,
1755 ASSERT_EQ(EXDEV, errno);
1758 * Tries to replace a file, from a directory that denies file removal,
1759 * to a different directory (which allows file removal).
1761 ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
1762 ASSERT_EQ(EXDEV, errno);
1763 ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file1_s1d3,
1765 ASSERT_EQ(EXDEV, errno);
1766 ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s1d3,
1768 ASSERT_EQ(EXDEV, errno);
1770 /* Exchanges files and directories that partially allow removal. */
1771 ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s2d1,
1773 ASSERT_EQ(EACCES, errno);
1774 /* Checks that file1_s2d1 cannot be removed (instead of ENOTDIR). */
1775 ASSERT_EQ(-1, rename(dir_s2d2, file1_s2d1));
1776 ASSERT_EQ(EACCES, errno);
1777 ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, dir_s2d2,
1779 ASSERT_EQ(EACCES, errno);
1780 /* Checks that file1_s1d1 cannot be removed (instead of EISDIR). */
1781 ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
1782 ASSERT_EQ(EACCES, errno);
1784 /* Renames files with different parents. */
1785 ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d2));
1786 ASSERT_EQ(EXDEV, errno);
1787 ASSERT_EQ(0, unlink(file1_s1d3));
1788 ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
1789 ASSERT_EQ(EXDEV, errno);
1791 /* Exchanges and renames files with same parent. */
1792 ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s2d3,
1794 ASSERT_EQ(0, rename(file2_s2d3, file1_s2d3));
1796 /* Exchanges files and directories with same parent, twice. */
1797 ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
1799 ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
1803 TEST_F_FORK(layout1, rename_dir)
1805 const struct rule rules[] = {
1808 .access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
1812 .access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
1816 const int ruleset_fd =
1817 create_ruleset(_metadata, rules[0].access, rules);
1819 ASSERT_LE(0, ruleset_fd);
1821 /* Empties dir_s1d3 to allow renaming. */
1822 ASSERT_EQ(0, unlink(file1_s1d3));
1823 ASSERT_EQ(0, unlink(file2_s1d3));
1825 enforce_ruleset(_metadata, ruleset_fd);
1826 ASSERT_EQ(0, close(ruleset_fd));
1828 /* Exchanges and renames directory to a different parent. */
1829 ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
1831 ASSERT_EQ(EXDEV, errno);
1832 ASSERT_EQ(-1, rename(dir_s2d3, dir_s1d3));
1833 ASSERT_EQ(EXDEV, errno);
1834 ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
1836 ASSERT_EQ(EXDEV, errno);
1839 * Exchanges directory to the same parent, which doesn't allow
1840 * directory removal.
1842 ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d1, AT_FDCWD, dir_s2d1,
1844 ASSERT_EQ(EACCES, errno);
1845 /* Checks that dir_s1d2 cannot be removed (instead of ENOTDIR). */
1846 ASSERT_EQ(-1, rename(dir_s1d2, file1_s1d1));
1847 ASSERT_EQ(EACCES, errno);
1848 ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s1d2,
1850 ASSERT_EQ(EACCES, errno);
1851 /* Checks that dir_s1d2 cannot be removed (instead of EISDIR). */
1852 ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
1853 ASSERT_EQ(EACCES, errno);
1856 * Exchanges and renames directory to the same parent, which allows
1857 * directory removal.
1859 ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, file1_s1d2,
1861 ASSERT_EQ(0, unlink(dir_s1d3));
1862 ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
1863 ASSERT_EQ(0, rename(file1_s1d2, dir_s1d3));
1864 ASSERT_EQ(0, rmdir(dir_s1d3));
1867 TEST_F_FORK(layout1, remove_dir)
1869 const struct rule rules[] = {
1872 .access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
1876 const int ruleset_fd =
1877 create_ruleset(_metadata, rules[0].access, rules);
1879 ASSERT_LE(0, ruleset_fd);
1881 ASSERT_EQ(0, unlink(file1_s1d1));
1882 ASSERT_EQ(0, unlink(file1_s1d2));
1883 ASSERT_EQ(0, unlink(file1_s1d3));
1884 ASSERT_EQ(0, unlink(file2_s1d3));
1886 enforce_ruleset(_metadata, ruleset_fd);
1887 ASSERT_EQ(0, close(ruleset_fd));
1889 ASSERT_EQ(0, rmdir(dir_s1d3));
1890 ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
1891 ASSERT_EQ(0, unlinkat(AT_FDCWD, dir_s1d3, AT_REMOVEDIR));
1893 /* dir_s1d2 itself cannot be removed. */
1894 ASSERT_EQ(-1, rmdir(dir_s1d2));
1895 ASSERT_EQ(EACCES, errno);
1896 ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d2, AT_REMOVEDIR));
1897 ASSERT_EQ(EACCES, errno);
1898 ASSERT_EQ(-1, rmdir(dir_s1d1));
1899 ASSERT_EQ(EACCES, errno);
1900 ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d1, AT_REMOVEDIR));
1901 ASSERT_EQ(EACCES, errno);
1904 TEST_F_FORK(layout1, remove_file)
1906 const struct rule rules[] = {
1909 .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1913 const int ruleset_fd =
1914 create_ruleset(_metadata, rules[0].access, rules);
1916 ASSERT_LE(0, ruleset_fd);
1917 enforce_ruleset(_metadata, ruleset_fd);
1918 ASSERT_EQ(0, close(ruleset_fd));
1920 ASSERT_EQ(-1, unlink(file1_s1d1));
1921 ASSERT_EQ(EACCES, errno);
1922 ASSERT_EQ(-1, unlinkat(AT_FDCWD, file1_s1d1, 0));
1923 ASSERT_EQ(EACCES, errno);
1924 ASSERT_EQ(0, unlink(file1_s1d2));
1925 ASSERT_EQ(0, unlinkat(AT_FDCWD, file1_s1d3, 0));
1928 static void test_make_file(struct __test_metadata *const _metadata,
1929 const __u64 access, const mode_t mode,
1932 const struct rule rules[] = {
1939 const int ruleset_fd = create_ruleset(_metadata, access, rules);
1941 ASSERT_LE(0, ruleset_fd);
1943 ASSERT_EQ(0, unlink(file1_s1d1));
1944 ASSERT_EQ(0, unlink(file2_s1d1));
1945 ASSERT_EQ(0, mknod(file2_s1d1, mode | 0400, dev))
1947 TH_LOG("Failed to make file \"%s\": %s", file2_s1d1,
1951 ASSERT_EQ(0, unlink(file1_s1d2));
1952 ASSERT_EQ(0, unlink(file2_s1d2));
1954 ASSERT_EQ(0, unlink(file1_s1d3));
1955 ASSERT_EQ(0, unlink(file2_s1d3));
1957 enforce_ruleset(_metadata, ruleset_fd);
1958 ASSERT_EQ(0, close(ruleset_fd));
1960 ASSERT_EQ(-1, mknod(file1_s1d1, mode | 0400, dev));
1961 ASSERT_EQ(EACCES, errno);
1962 ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
1963 ASSERT_EQ(EACCES, errno);
1964 ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
1965 ASSERT_EQ(EACCES, errno);
1967 ASSERT_EQ(0, mknod(file1_s1d2, mode | 0400, dev))
1969 TH_LOG("Failed to make file \"%s\": %s", file1_s1d2,
1972 ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
1973 ASSERT_EQ(0, unlink(file2_s1d2));
1974 ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
1976 ASSERT_EQ(0, mknod(file1_s1d3, mode | 0400, dev));
1977 ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
1978 ASSERT_EQ(0, unlink(file2_s1d3));
1979 ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
1982 TEST_F_FORK(layout1, make_char)
1984 /* Creates a /dev/null device. */
1985 set_cap(_metadata, CAP_MKNOD);
1986 test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_CHAR, S_IFCHR,
1990 TEST_F_FORK(layout1, make_block)
1992 /* Creates a /dev/loop0 device. */
1993 set_cap(_metadata, CAP_MKNOD);
1994 test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_BLOCK, S_IFBLK,
1998 TEST_F_FORK(layout1, make_reg_1)
2000 test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, S_IFREG, 0);
2003 TEST_F_FORK(layout1, make_reg_2)
2005 test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, 0, 0);
2008 TEST_F_FORK(layout1, make_sock)
2010 test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_SOCK, S_IFSOCK, 0);
2013 TEST_F_FORK(layout1, make_fifo)
2015 test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_FIFO, S_IFIFO, 0);
2018 TEST_F_FORK(layout1, make_sym)
2020 const struct rule rules[] = {
2023 .access = LANDLOCK_ACCESS_FS_MAKE_SYM,
2027 const int ruleset_fd =
2028 create_ruleset(_metadata, rules[0].access, rules);
2030 ASSERT_LE(0, ruleset_fd);
2032 ASSERT_EQ(0, unlink(file1_s1d1));
2033 ASSERT_EQ(0, unlink(file2_s1d1));
2034 ASSERT_EQ(0, symlink("none", file2_s1d1));
2036 ASSERT_EQ(0, unlink(file1_s1d2));
2037 ASSERT_EQ(0, unlink(file2_s1d2));
2039 ASSERT_EQ(0, unlink(file1_s1d3));
2040 ASSERT_EQ(0, unlink(file2_s1d3));
2042 enforce_ruleset(_metadata, ruleset_fd);
2043 ASSERT_EQ(0, close(ruleset_fd));
2045 ASSERT_EQ(-1, symlink("none", file1_s1d1));
2046 ASSERT_EQ(EACCES, errno);
2047 ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
2048 ASSERT_EQ(EACCES, errno);
2049 ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
2050 ASSERT_EQ(EACCES, errno);
2052 ASSERT_EQ(0, symlink("none", file1_s1d2));
2053 ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
2054 ASSERT_EQ(0, unlink(file2_s1d2));
2055 ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
2057 ASSERT_EQ(0, symlink("none", file1_s1d3));
2058 ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
2059 ASSERT_EQ(0, unlink(file2_s1d3));
2060 ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
2063 TEST_F_FORK(layout1, make_dir)
2065 const struct rule rules[] = {
2068 .access = LANDLOCK_ACCESS_FS_MAKE_DIR,
2072 const int ruleset_fd =
2073 create_ruleset(_metadata, rules[0].access, rules);
2075 ASSERT_LE(0, ruleset_fd);
2077 ASSERT_EQ(0, unlink(file1_s1d1));
2078 ASSERT_EQ(0, unlink(file1_s1d2));
2079 ASSERT_EQ(0, unlink(file1_s1d3));
2081 enforce_ruleset(_metadata, ruleset_fd);
2082 ASSERT_EQ(0, close(ruleset_fd));
2084 /* Uses file_* as directory names. */
2085 ASSERT_EQ(-1, mkdir(file1_s1d1, 0700));
2086 ASSERT_EQ(EACCES, errno);
2087 ASSERT_EQ(0, mkdir(file1_s1d2, 0700));
2088 ASSERT_EQ(0, mkdir(file1_s1d3, 0700));
2091 static int open_proc_fd(struct __test_metadata *const _metadata, const int fd,
2092 const int open_flags)
2094 static const char path_template[] = "/proc/self/fd/%d";
2095 char procfd_path[sizeof(path_template) + 10];
2096 const int procfd_path_size =
2097 snprintf(procfd_path, sizeof(procfd_path), path_template, fd);
2099 ASSERT_LT(procfd_path_size, sizeof(procfd_path));
2100 return open(procfd_path, open_flags);
2103 TEST_F_FORK(layout1, proc_unlinked_file)
2105 const struct rule rules[] = {
2108 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2112 int reg_fd, proc_fd;
2113 const int ruleset_fd = create_ruleset(
2115 LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE,
2118 ASSERT_LE(0, ruleset_fd);
2119 enforce_ruleset(_metadata, ruleset_fd);
2120 ASSERT_EQ(0, close(ruleset_fd));
2122 ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
2123 ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
2124 reg_fd = open(file1_s1d2, O_RDONLY | O_CLOEXEC);
2125 ASSERT_LE(0, reg_fd);
2126 ASSERT_EQ(0, unlink(file1_s1d2));
2128 proc_fd = open_proc_fd(_metadata, reg_fd, O_RDONLY | O_CLOEXEC);
2129 ASSERT_LE(0, proc_fd);
2130 ASSERT_EQ(0, close(proc_fd));
2132 proc_fd = open_proc_fd(_metadata, reg_fd, O_RDWR | O_CLOEXEC);
2133 ASSERT_EQ(-1, proc_fd)
2135 TH_LOG("Successfully opened /proc/self/fd/%d: %s", reg_fd,
2138 ASSERT_EQ(EACCES, errno);
2140 ASSERT_EQ(0, close(reg_fd));
2143 TEST_F_FORK(layout1, proc_pipe)
2148 const struct rule rules[] = {
2151 .access = LANDLOCK_ACCESS_FS_READ_FILE |
2152 LANDLOCK_ACCESS_FS_WRITE_FILE,
2156 /* Limits read and write access to files tied to the filesystem. */
2157 const int ruleset_fd =
2158 create_ruleset(_metadata, rules[0].access, rules);
2160 ASSERT_LE(0, ruleset_fd);
2161 enforce_ruleset(_metadata, ruleset_fd);
2162 ASSERT_EQ(0, close(ruleset_fd));
2164 /* Checks enforcement for normal files. */
2165 ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
2166 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
2168 /* Checks access to pipes through FD. */
2169 ASSERT_EQ(0, pipe2(pipe_fds, O_CLOEXEC));
2170 ASSERT_EQ(1, write(pipe_fds[1], ".", 1))
2172 TH_LOG("Failed to write in pipe: %s", strerror(errno));
2174 ASSERT_EQ(1, read(pipe_fds[0], &buf, 1));
2175 ASSERT_EQ('.', buf);
2177 /* Checks write access to pipe through /proc/self/fd . */
2178 proc_fd = open_proc_fd(_metadata, pipe_fds[1], O_WRONLY | O_CLOEXEC);
2179 ASSERT_LE(0, proc_fd);
2180 ASSERT_EQ(1, write(proc_fd, ".", 1))
2182 TH_LOG("Failed to write through /proc/self/fd/%d: %s",
2183 pipe_fds[1], strerror(errno));
2185 ASSERT_EQ(0, close(proc_fd));
2187 /* Checks read access to pipe through /proc/self/fd . */
2188 proc_fd = open_proc_fd(_metadata, pipe_fds[0], O_RDONLY | O_CLOEXEC);
2189 ASSERT_LE(0, proc_fd);
2191 ASSERT_EQ(1, read(proc_fd, &buf, 1))
2193 TH_LOG("Failed to read through /proc/self/fd/%d: %s",
2194 pipe_fds[1], strerror(errno));
2196 ASSERT_EQ(0, close(proc_fd));
2198 ASSERT_EQ(0, close(pipe_fds[0]));
2199 ASSERT_EQ(0, close(pipe_fds[1]));
2202 /* clang-format off */
2203 FIXTURE(layout1_bind) {};
2204 /* clang-format on */
2206 FIXTURE_SETUP(layout1_bind)
2208 prepare_layout(_metadata);
2210 create_layout1(_metadata);
2212 set_cap(_metadata, CAP_SYS_ADMIN);
2213 ASSERT_EQ(0, mount(dir_s1d2, dir_s2d2, NULL, MS_BIND, NULL));
2214 clear_cap(_metadata, CAP_SYS_ADMIN);
2217 FIXTURE_TEARDOWN(layout1_bind)
2219 set_cap(_metadata, CAP_SYS_ADMIN);
2220 EXPECT_EQ(0, umount(dir_s2d2));
2221 clear_cap(_metadata, CAP_SYS_ADMIN);
2223 remove_layout1(_metadata);
2225 cleanup_layout(_metadata);
2228 static const char bind_dir_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3";
2229 static const char bind_file1_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3/f1";
2232 * layout1_bind hierarchy:
2257 TEST_F_FORK(layout1_bind, no_restriction)
2259 ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
2260 ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
2261 ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
2262 ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
2263 ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
2264 ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
2266 ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
2267 ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
2268 ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
2269 ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
2270 ASSERT_EQ(ENOENT, test_open(dir_s2d3, O_RDONLY));
2271 ASSERT_EQ(ENOENT, test_open(file1_s2d3, O_RDONLY));
2273 ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY));
2274 ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
2276 ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
2279 TEST_F_FORK(layout1_bind, same_content_same_file)
2282 * Sets access right on parent directories of both source and
2283 * destination mount points.
2285 const struct rule layer1_parent[] = {
2288 .access = ACCESS_RO,
2292 .access = ACCESS_RW,
2297 * Sets access rights on the same bind-mounted directories. The result
2298 * should be ACCESS_RW for both directories, but not both hierarchies
2299 * because of the first layer.
2301 const struct rule layer2_mount_point[] = {
2304 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2308 .access = ACCESS_RW,
2312 /* Only allow read-access to the s1d3 hierarchies. */
2313 const struct rule layer3_source[] = {
2316 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2320 /* Removes all access rights. */
2321 const struct rule layer4_destination[] = {
2323 .path = bind_file1_s1d3,
2324 .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
2330 /* Sets rules for the parent directories. */
2331 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_parent);
2332 ASSERT_LE(0, ruleset_fd);
2333 enforce_ruleset(_metadata, ruleset_fd);
2334 ASSERT_EQ(0, close(ruleset_fd));
2336 /* Checks source hierarchy. */
2337 ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
2338 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
2339 ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
2341 ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
2342 ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
2343 ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
2345 /* Checks destination hierarchy. */
2346 ASSERT_EQ(0, test_open(file1_s2d1, O_RDWR));
2347 ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
2349 ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
2350 ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
2352 /* Sets rules for the mount points. */
2353 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_mount_point);
2354 ASSERT_LE(0, ruleset_fd);
2355 enforce_ruleset(_metadata, ruleset_fd);
2356 ASSERT_EQ(0, close(ruleset_fd));
2358 /* Checks source hierarchy. */
2359 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
2360 ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
2361 ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
2363 ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
2364 ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
2365 ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
2367 /* Checks destination hierarchy. */
2368 ASSERT_EQ(EACCES, test_open(file1_s2d1, O_RDONLY));
2369 ASSERT_EQ(EACCES, test_open(file1_s2d1, O_WRONLY));
2370 ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
2372 ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
2373 ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
2374 ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
2376 /* Sets a (shared) rule only on the source. */
2377 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3_source);
2378 ASSERT_LE(0, ruleset_fd);
2379 enforce_ruleset(_metadata, ruleset_fd);
2380 ASSERT_EQ(0, close(ruleset_fd));
2382 /* Checks source hierarchy. */
2383 ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDONLY));
2384 ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
2385 ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
2387 ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
2388 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
2389 ASSERT_EQ(EACCES, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
2391 /* Checks destination hierarchy. */
2392 ASSERT_EQ(EACCES, test_open(file1_s2d2, O_RDONLY));
2393 ASSERT_EQ(EACCES, test_open(file1_s2d2, O_WRONLY));
2394 ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
2396 ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
2397 ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
2398 ASSERT_EQ(EACCES, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
2400 /* Sets a (shared) rule only on the destination. */
2401 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer4_destination);
2402 ASSERT_LE(0, ruleset_fd);
2403 enforce_ruleset(_metadata, ruleset_fd);
2404 ASSERT_EQ(0, close(ruleset_fd));
2406 /* Checks source hierarchy. */
2407 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
2408 ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
2410 /* Checks destination hierarchy. */
2411 ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_RDONLY));
2412 ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
2415 #define LOWER_BASE TMP_DIR "/lower"
2416 #define LOWER_DATA LOWER_BASE "/data"
2417 static const char lower_fl1[] = LOWER_DATA "/fl1";
2418 static const char lower_dl1[] = LOWER_DATA "/dl1";
2419 static const char lower_dl1_fl2[] = LOWER_DATA "/dl1/fl2";
2420 static const char lower_fo1[] = LOWER_DATA "/fo1";
2421 static const char lower_do1[] = LOWER_DATA "/do1";
2422 static const char lower_do1_fo2[] = LOWER_DATA "/do1/fo2";
2423 static const char lower_do1_fl3[] = LOWER_DATA "/do1/fl3";
2425 static const char (*lower_base_files[])[] = {
2430 static const char (*lower_base_directories[])[] = {
2435 static const char (*lower_sub_files[])[] = {
2442 #define UPPER_BASE TMP_DIR "/upper"
2443 #define UPPER_DATA UPPER_BASE "/data"
2444 #define UPPER_WORK UPPER_BASE "/work"
2445 static const char upper_fu1[] = UPPER_DATA "/fu1";
2446 static const char upper_du1[] = UPPER_DATA "/du1";
2447 static const char upper_du1_fu2[] = UPPER_DATA "/du1/fu2";
2448 static const char upper_fo1[] = UPPER_DATA "/fo1";
2449 static const char upper_do1[] = UPPER_DATA "/do1";
2450 static const char upper_do1_fo2[] = UPPER_DATA "/do1/fo2";
2451 static const char upper_do1_fu3[] = UPPER_DATA "/do1/fu3";
2453 static const char (*upper_base_files[])[] = {
2458 static const char (*upper_base_directories[])[] = {
2463 static const char (*upper_sub_files[])[] = {
2470 #define MERGE_BASE TMP_DIR "/merge"
2471 #define MERGE_DATA MERGE_BASE "/data"
2472 static const char merge_fl1[] = MERGE_DATA "/fl1";
2473 static const char merge_dl1[] = MERGE_DATA "/dl1";
2474 static const char merge_dl1_fl2[] = MERGE_DATA "/dl1/fl2";
2475 static const char merge_fu1[] = MERGE_DATA "/fu1";
2476 static const char merge_du1[] = MERGE_DATA "/du1";
2477 static const char merge_du1_fu2[] = MERGE_DATA "/du1/fu2";
2478 static const char merge_fo1[] = MERGE_DATA "/fo1";
2479 static const char merge_do1[] = MERGE_DATA "/do1";
2480 static const char merge_do1_fo2[] = MERGE_DATA "/do1/fo2";
2481 static const char merge_do1_fl3[] = MERGE_DATA "/do1/fl3";
2482 static const char merge_do1_fu3[] = MERGE_DATA "/do1/fu3";
2484 static const char (*merge_base_files[])[] = {
2490 static const char (*merge_base_directories[])[] = {
2496 static const char (*merge_sub_files[])[] = {
2497 &merge_dl1_fl2, &merge_du1_fu2, &merge_do1_fo2,
2498 &merge_do1_fl3, &merge_do1_fu3, NULL,
2502 * layout2_overlay hierarchy:
2540 /* clang-format off */
2541 FIXTURE(layout2_overlay) {};
2542 /* clang-format on */
2544 FIXTURE_SETUP(layout2_overlay)
2546 prepare_layout(_metadata);
2548 create_directory(_metadata, LOWER_BASE);
2549 set_cap(_metadata, CAP_SYS_ADMIN);
2550 /* Creates tmpfs mount points to get deterministic overlayfs. */
2551 ASSERT_EQ(0, mount("tmp", LOWER_BASE, "tmpfs", 0, "size=4m,mode=700"));
2552 clear_cap(_metadata, CAP_SYS_ADMIN);
2553 create_file(_metadata, lower_fl1);
2554 create_file(_metadata, lower_dl1_fl2);
2555 create_file(_metadata, lower_fo1);
2556 create_file(_metadata, lower_do1_fo2);
2557 create_file(_metadata, lower_do1_fl3);
2559 create_directory(_metadata, UPPER_BASE);
2560 set_cap(_metadata, CAP_SYS_ADMIN);
2561 ASSERT_EQ(0, mount("tmp", UPPER_BASE, "tmpfs", 0, "size=4m,mode=700"));
2562 clear_cap(_metadata, CAP_SYS_ADMIN);
2563 create_file(_metadata, upper_fu1);
2564 create_file(_metadata, upper_du1_fu2);
2565 create_file(_metadata, upper_fo1);
2566 create_file(_metadata, upper_do1_fo2);
2567 create_file(_metadata, upper_do1_fu3);
2568 ASSERT_EQ(0, mkdir(UPPER_WORK, 0700));
2570 create_directory(_metadata, MERGE_DATA);
2571 set_cap(_metadata, CAP_SYS_ADMIN);
2572 set_cap(_metadata, CAP_DAC_OVERRIDE);
2573 ASSERT_EQ(0, mount("overlay", MERGE_DATA, "overlay", 0,
2574 "lowerdir=" LOWER_DATA ",upperdir=" UPPER_DATA
2575 ",workdir=" UPPER_WORK));
2576 clear_cap(_metadata, CAP_DAC_OVERRIDE);
2577 clear_cap(_metadata, CAP_SYS_ADMIN);
2580 FIXTURE_TEARDOWN(layout2_overlay)
2582 EXPECT_EQ(0, remove_path(lower_do1_fl3));
2583 EXPECT_EQ(0, remove_path(lower_dl1_fl2));
2584 EXPECT_EQ(0, remove_path(lower_fl1));
2585 EXPECT_EQ(0, remove_path(lower_do1_fo2));
2586 EXPECT_EQ(0, remove_path(lower_fo1));
2587 set_cap(_metadata, CAP_SYS_ADMIN);
2588 EXPECT_EQ(0, umount(LOWER_BASE));
2589 clear_cap(_metadata, CAP_SYS_ADMIN);
2590 EXPECT_EQ(0, remove_path(LOWER_BASE));
2592 EXPECT_EQ(0, remove_path(upper_do1_fu3));
2593 EXPECT_EQ(0, remove_path(upper_du1_fu2));
2594 EXPECT_EQ(0, remove_path(upper_fu1));
2595 EXPECT_EQ(0, remove_path(upper_do1_fo2));
2596 EXPECT_EQ(0, remove_path(upper_fo1));
2597 EXPECT_EQ(0, remove_path(UPPER_WORK "/work"));
2598 set_cap(_metadata, CAP_SYS_ADMIN);
2599 EXPECT_EQ(0, umount(UPPER_BASE));
2600 clear_cap(_metadata, CAP_SYS_ADMIN);
2601 EXPECT_EQ(0, remove_path(UPPER_BASE));
2603 set_cap(_metadata, CAP_SYS_ADMIN);
2604 EXPECT_EQ(0, umount(MERGE_DATA));
2605 clear_cap(_metadata, CAP_SYS_ADMIN);
2606 EXPECT_EQ(0, remove_path(MERGE_DATA));
2608 cleanup_layout(_metadata);
2611 TEST_F_FORK(layout2_overlay, no_restriction)
2613 ASSERT_EQ(0, test_open(lower_fl1, O_RDONLY));
2614 ASSERT_EQ(0, test_open(lower_dl1, O_RDONLY));
2615 ASSERT_EQ(0, test_open(lower_dl1_fl2, O_RDONLY));
2616 ASSERT_EQ(0, test_open(lower_fo1, O_RDONLY));
2617 ASSERT_EQ(0, test_open(lower_do1, O_RDONLY));
2618 ASSERT_EQ(0, test_open(lower_do1_fo2, O_RDONLY));
2619 ASSERT_EQ(0, test_open(lower_do1_fl3, O_RDONLY));
2621 ASSERT_EQ(0, test_open(upper_fu1, O_RDONLY));
2622 ASSERT_EQ(0, test_open(upper_du1, O_RDONLY));
2623 ASSERT_EQ(0, test_open(upper_du1_fu2, O_RDONLY));
2624 ASSERT_EQ(0, test_open(upper_fo1, O_RDONLY));
2625 ASSERT_EQ(0, test_open(upper_do1, O_RDONLY));
2626 ASSERT_EQ(0, test_open(upper_do1_fo2, O_RDONLY));
2627 ASSERT_EQ(0, test_open(upper_do1_fu3, O_RDONLY));
2629 ASSERT_EQ(0, test_open(merge_fl1, O_RDONLY));
2630 ASSERT_EQ(0, test_open(merge_dl1, O_RDONLY));
2631 ASSERT_EQ(0, test_open(merge_dl1_fl2, O_RDONLY));
2632 ASSERT_EQ(0, test_open(merge_fu1, O_RDONLY));
2633 ASSERT_EQ(0, test_open(merge_du1, O_RDONLY));
2634 ASSERT_EQ(0, test_open(merge_du1_fu2, O_RDONLY));
2635 ASSERT_EQ(0, test_open(merge_fo1, O_RDONLY));
2636 ASSERT_EQ(0, test_open(merge_do1, O_RDONLY));
2637 ASSERT_EQ(0, test_open(merge_do1_fo2, O_RDONLY));
2638 ASSERT_EQ(0, test_open(merge_do1_fl3, O_RDONLY));
2639 ASSERT_EQ(0, test_open(merge_do1_fu3, O_RDONLY));
2642 #define for_each_path(path_list, path_entry, i) \
2643 for (i = 0, path_entry = *path_list[i]; path_list[i]; \
2644 path_entry = *path_list[++i])
2646 TEST_F_FORK(layout2_overlay, same_content_different_file)
2648 /* Sets access right on parent directories of both layers. */
2649 const struct rule layer1_base[] = {
2652 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2656 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2660 .access = ACCESS_RW,
2664 const struct rule layer2_data[] = {
2667 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2671 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2675 .access = ACCESS_RW,
2679 /* Sets access right on directories inside both layers. */
2680 const struct rule layer3_subdirs[] = {
2683 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2687 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2691 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2695 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2699 .access = ACCESS_RW,
2703 .access = ACCESS_RW,
2707 .access = ACCESS_RW,
2711 /* Tighten access rights to the files. */
2712 const struct rule layer4_files[] = {
2714 .path = lower_dl1_fl2,
2715 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2718 .path = lower_do1_fo2,
2719 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2722 .path = lower_do1_fl3,
2723 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2726 .path = upper_du1_fu2,
2727 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2730 .path = upper_do1_fo2,
2731 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2734 .path = upper_do1_fu3,
2735 .access = LANDLOCK_ACCESS_FS_READ_FILE,
2738 .path = merge_dl1_fl2,
2739 .access = LANDLOCK_ACCESS_FS_READ_FILE |
2740 LANDLOCK_ACCESS_FS_WRITE_FILE,
2743 .path = merge_du1_fu2,
2744 .access = LANDLOCK_ACCESS_FS_READ_FILE |
2745 LANDLOCK_ACCESS_FS_WRITE_FILE,
2748 .path = merge_do1_fo2,
2749 .access = LANDLOCK_ACCESS_FS_READ_FILE |
2750 LANDLOCK_ACCESS_FS_WRITE_FILE,
2753 .path = merge_do1_fl3,
2754 .access = LANDLOCK_ACCESS_FS_READ_FILE |
2755 LANDLOCK_ACCESS_FS_WRITE_FILE,
2758 .path = merge_do1_fu3,
2759 .access = LANDLOCK_ACCESS_FS_READ_FILE |
2760 LANDLOCK_ACCESS_FS_WRITE_FILE,
2764 const struct rule layer5_merge_only[] = {
2767 .access = LANDLOCK_ACCESS_FS_READ_FILE |
2768 LANDLOCK_ACCESS_FS_WRITE_FILE,
2774 const char *path_entry;
2776 /* Sets rules on base directories (i.e. outside overlay scope). */
2777 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_base);
2778 ASSERT_LE(0, ruleset_fd);
2779 enforce_ruleset(_metadata, ruleset_fd);
2780 ASSERT_EQ(0, close(ruleset_fd));
2782 /* Checks lower layer. */
2783 for_each_path(lower_base_files, path_entry, i) {
2784 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2785 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2787 for_each_path(lower_base_directories, path_entry, i) {
2789 test_open(path_entry, O_RDONLY | O_DIRECTORY));
2791 for_each_path(lower_sub_files, path_entry, i) {
2792 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2793 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2795 /* Checks upper layer. */
2796 for_each_path(upper_base_files, path_entry, i) {
2797 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2798 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2800 for_each_path(upper_base_directories, path_entry, i) {
2802 test_open(path_entry, O_RDONLY | O_DIRECTORY));
2804 for_each_path(upper_sub_files, path_entry, i) {
2805 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2806 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2809 * Checks that access rights are independent from the lower and upper
2810 * layers: write access to upper files viewed through the merge point
2811 * is still allowed, and write access to lower file viewed (and copied)
2812 * through the merge point is still allowed.
2814 for_each_path(merge_base_files, path_entry, i) {
2815 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2817 for_each_path(merge_base_directories, path_entry, i) {
2818 ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
2820 for_each_path(merge_sub_files, path_entry, i) {
2821 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2824 /* Sets rules on data directories (i.e. inside overlay scope). */
2825 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_data);
2826 ASSERT_LE(0, ruleset_fd);
2827 enforce_ruleset(_metadata, ruleset_fd);
2828 ASSERT_EQ(0, close(ruleset_fd));
2831 for_each_path(merge_base_files, path_entry, i) {
2832 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2834 for_each_path(merge_base_directories, path_entry, i) {
2835 ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
2837 for_each_path(merge_sub_files, path_entry, i) {
2838 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2841 /* Same checks with tighter rules. */
2842 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3_subdirs);
2843 ASSERT_LE(0, ruleset_fd);
2844 enforce_ruleset(_metadata, ruleset_fd);
2845 ASSERT_EQ(0, close(ruleset_fd));
2847 /* Checks changes for lower layer. */
2848 for_each_path(lower_base_files, path_entry, i) {
2849 ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
2851 /* Checks changes for upper layer. */
2852 for_each_path(upper_base_files, path_entry, i) {
2853 ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
2855 /* Checks all merge accesses. */
2856 for_each_path(merge_base_files, path_entry, i) {
2857 ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
2859 for_each_path(merge_base_directories, path_entry, i) {
2860 ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
2862 for_each_path(merge_sub_files, path_entry, i) {
2863 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2866 /* Sets rules directly on overlayed files. */
2867 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer4_files);
2868 ASSERT_LE(0, ruleset_fd);
2869 enforce_ruleset(_metadata, ruleset_fd);
2870 ASSERT_EQ(0, close(ruleset_fd));
2872 /* Checks unchanged accesses on lower layer. */
2873 for_each_path(lower_sub_files, path_entry, i) {
2874 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2875 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2877 /* Checks unchanged accesses on upper layer. */
2878 for_each_path(upper_sub_files, path_entry, i) {
2879 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
2880 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
2882 /* Checks all merge accesses. */
2883 for_each_path(merge_base_files, path_entry, i) {
2884 ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
2886 for_each_path(merge_base_directories, path_entry, i) {
2888 test_open(path_entry, O_RDONLY | O_DIRECTORY));
2890 for_each_path(merge_sub_files, path_entry, i) {
2891 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
2894 /* Only allowes access to the merge hierarchy. */
2895 ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer5_merge_only);
2896 ASSERT_LE(0, ruleset_fd);
2897 enforce_ruleset(_metadata, ruleset_fd);
2898 ASSERT_EQ(0, close(ruleset_fd));
2900 /* Checks new accesses on lower layer. */
2901 for_each_path(lower_sub_files, path_entry, i) {
2902 ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
2904 /* Checks new accesses on upper layer. */
2905 for_each_path(upper_sub_files, path_entry, i) {
2906 ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
2908 /* Checks all merge accesses. */
2909 for_each_path(merge_base_files, path_entry, i) {
2910 ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
2912 for_each_path(merge_base_directories, path_entry, i) {
2914 test_open(path_entry, O_RDONLY | O_DIRECTORY));
2916 for_each_path(merge_sub_files, path_entry, i) {
2917 ASSERT_EQ(0, test_open(path_entry, O_RDWR));