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