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