~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/landlock/fs_test.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Landlock tests - Filesystem
  4  *
  5  * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
  6  * Copyright © 2020 ANSSI
  7  * Copyright © 2020-2022 Microsoft Corporation
  8  */
  9 
 10 #define _GNU_SOURCE
 11 #include <asm/termbits.h>
 12 #include <fcntl.h>
 13 #include <libgen.h>
 14 #include <linux/fiemap.h>
 15 #include <linux/landlock.h>
 16 #include <linux/magic.h>
 17 #include <sched.h>
 18 #include <stddef.h>
 19 #include <stdio.h>
 20 #include <string.h>
 21 #include <sys/capability.h>
 22 #include <sys/ioctl.h>
 23 #include <sys/mount.h>
 24 #include <sys/prctl.h>
 25 #include <sys/sendfile.h>
 26 #include <sys/socket.h>
 27 #include <sys/stat.h>
 28 #include <sys/sysmacros.h>
 29 #include <sys/un.h>
 30 #include <sys/vfs.h>
 31 #include <unistd.h>
 32 
 33 /*
 34  * Intentionally included last to work around header conflict.
 35  * See https://sourceware.org/glibc/wiki/Synchronizing_Headers.
 36  */
 37 #include <linux/fs.h>
 38 #include <linux/mount.h>
 39 
 40 #include "common.h"
 41 
 42 #ifndef renameat2
 43 int renameat2(int olddirfd, const char *oldpath, int newdirfd,
 44               const char *newpath, unsigned int flags)
 45 {
 46         return syscall(__NR_renameat2, olddirfd, oldpath, newdirfd, newpath,
 47                        flags);
 48 }
 49 #endif
 50 
 51 #ifndef open_tree
 52 int open_tree(int dfd, const char *filename, unsigned int flags)
 53 {
 54         return syscall(__NR_open_tree, dfd, filename, flags);
 55 }
 56 #endif
 57 
 58 #ifndef RENAME_EXCHANGE
 59 #define RENAME_EXCHANGE (1 << 1)
 60 #endif
 61 
 62 #define TMP_DIR "tmp"
 63 #define BINARY_PATH "./true"
 64 
 65 /* Paths (sibling number and depth) */
 66 static const char dir_s1d1[] = TMP_DIR "/s1d1";
 67 static const char file1_s1d1[] = TMP_DIR "/s1d1/f1";
 68 static const char file2_s1d1[] = TMP_DIR "/s1d1/f2";
 69 static const char dir_s1d2[] = TMP_DIR "/s1d1/s1d2";
 70 static const char file1_s1d2[] = TMP_DIR "/s1d1/s1d2/f1";
 71 static const char file2_s1d2[] = TMP_DIR "/s1d1/s1d2/f2";
 72 static const char dir_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3";
 73 static const char file1_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f1";
 74 static const char file2_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f2";
 75 
 76 static const char dir_s2d1[] = TMP_DIR "/s2d1";
 77 static const char file1_s2d1[] = TMP_DIR "/s2d1/f1";
 78 static const char dir_s2d2[] = TMP_DIR "/s2d1/s2d2";
 79 static const char file1_s2d2[] = TMP_DIR "/s2d1/s2d2/f1";
 80 static const char dir_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3";
 81 static const char file1_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f1";
 82 static const char file2_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f2";
 83 
 84 static const char dir_s3d1[] = TMP_DIR "/s3d1";
 85 static const char file1_s3d1[] = TMP_DIR "/s3d1/f1";
 86 /* dir_s3d2 is a mount point. */
 87 static const char dir_s3d2[] = TMP_DIR "/s3d1/s3d2";
 88 static const char dir_s3d3[] = TMP_DIR "/s3d1/s3d2/s3d3";
 89 
 90 /*
 91  * layout1 hierarchy:
 92  *
 93  * tmp
 94  * ├── s1d1
 95  * │   ├── f1
 96  * │   ├── f2
 97  * │   └── s1d2
 98  * │       ├── f1
 99  * │       ├── f2
100  * │       └── s1d3
101  * │           ├── f1
102  * │           └── f2
103  * ├── s2d1
104  * │   ├── f1
105  * │   └── s2d2
106  * │       ├── f1
107  * │       └── s2d3
108  * │           ├── f1
109  * │           └── f2
110  * └── s3d1
111  *     ├── f1
112  *     └── s3d2
113  *         └── s3d3
114  */
115 
116 static bool fgrep(FILE *const inf, const char *const str)
117 {
118         char line[32];
119         const int slen = strlen(str);
120 
121         while (!feof(inf)) {
122                 if (!fgets(line, sizeof(line), inf))
123                         break;
124                 if (strncmp(line, str, slen))
125                         continue;
126 
127                 return true;
128         }
129 
130         return false;
131 }
132 
133 static bool supports_filesystem(const char *const filesystem)
134 {
135         char str[32];
136         int len;
137         bool res = true;
138         FILE *const inf = fopen("/proc/filesystems", "r");
139 
140         /*
141          * Consider that the filesystem is supported if we cannot get the
142          * supported ones.
143          */
144         if (!inf)
145                 return true;
146 
147         /* filesystem can be null for bind mounts. */
148         if (!filesystem)
149                 goto out;
150 
151         len = snprintf(str, sizeof(str), "nodev\t%s\n", filesystem);
152         if (len >= sizeof(str))
153                 /* Ignores too-long filesystem names. */
154                 goto out;
155 
156         res = fgrep(inf, str);
157 
158 out:
159         fclose(inf);
160         return res;
161 }
162 
163 static bool cwd_matches_fs(unsigned int fs_magic)
164 {
165         struct statfs statfs_buf;
166 
167         if (!fs_magic)
168                 return true;
169 
170         if (statfs(".", &statfs_buf))
171                 return true;
172 
173         return statfs_buf.f_type == fs_magic;
174 }
175 
176 static void mkdir_parents(struct __test_metadata *const _metadata,
177                           const char *const path)
178 {
179         char *walker;
180         const char *parent;
181         int i, err;
182 
183         ASSERT_NE(path[0], '\0');
184         walker = strdup(path);
185         ASSERT_NE(NULL, walker);
186         parent = walker;
187         for (i = 1; walker[i]; i++) {
188                 if (walker[i] != '/')
189                         continue;
190                 walker[i] = '\0';
191                 err = mkdir(parent, 0700);
192                 ASSERT_FALSE(err && errno != EEXIST)
193                 {
194                         TH_LOG("Failed to create directory \"%s\": %s", parent,
195                                strerror(errno));
196                 }
197                 walker[i] = '/';
198         }
199         free(walker);
200 }
201 
202 static void create_directory(struct __test_metadata *const _metadata,
203                              const char *const path)
204 {
205         mkdir_parents(_metadata, path);
206         ASSERT_EQ(0, mkdir(path, 0700))
207         {
208                 TH_LOG("Failed to create directory \"%s\": %s", path,
209                        strerror(errno));
210         }
211 }
212 
213 static void create_file(struct __test_metadata *const _metadata,
214                         const char *const path)
215 {
216         mkdir_parents(_metadata, path);
217         ASSERT_EQ(0, mknod(path, S_IFREG | 0700, 0))
218         {
219                 TH_LOG("Failed to create file \"%s\": %s", path,
220                        strerror(errno));
221         }
222 }
223 
224 static int remove_path(const char *const path)
225 {
226         char *walker;
227         int i, ret, err = 0;
228 
229         walker = strdup(path);
230         if (!walker) {
231                 err = ENOMEM;
232                 goto out;
233         }
234         if (unlink(path) && rmdir(path)) {
235                 if (errno != ENOENT && errno != ENOTDIR)
236                         err = errno;
237                 goto out;
238         }
239         for (i = strlen(walker); i > 0; i--) {
240                 if (walker[i] != '/')
241                         continue;
242                 walker[i] = '\0';
243                 ret = rmdir(walker);
244                 if (ret) {
245                         if (errno != ENOTEMPTY && errno != EBUSY)
246                                 err = errno;
247                         goto out;
248                 }
249                 if (strcmp(walker, TMP_DIR) == 0)
250                         goto out;
251         }
252 
253 out:
254         free(walker);
255         return err;
256 }
257 
258 struct mnt_opt {
259         const char *const source;
260         const char *const type;
261         const unsigned long flags;
262         const char *const data;
263 };
264 
265 #define MNT_TMP_DATA "size=4m,mode=700"
266 
267 static const struct mnt_opt mnt_tmp = {
268         .type = "tmpfs",
269         .data = MNT_TMP_DATA,
270 };
271 
272 static int mount_opt(const struct mnt_opt *const mnt, const char *const target)
273 {
274         return mount(mnt->source ?: mnt->type, target, mnt->type, mnt->flags,
275                      mnt->data);
276 }
277 
278 static void prepare_layout_opt(struct __test_metadata *const _metadata,
279                                const struct mnt_opt *const mnt)
280 {
281         disable_caps(_metadata);
282         umask(0077);
283         create_directory(_metadata, TMP_DIR);
284 
285         /*
286          * Do not pollute the rest of the system: creates a private mount point
287          * for tests relying on pivot_root(2) and move_mount(2).
288          */
289         set_cap(_metadata, CAP_SYS_ADMIN);
290         ASSERT_EQ(0, unshare(CLONE_NEWNS | CLONE_NEWCGROUP));
291         ASSERT_EQ(0, mount_opt(mnt, TMP_DIR))
292         {
293                 TH_LOG("Failed to mount the %s filesystem: %s", mnt->type,
294                        strerror(errno));
295                 /*
296                  * FIXTURE_TEARDOWN() is not called when FIXTURE_SETUP()
297                  * failed, so we need to explicitly do a minimal cleanup to
298                  * avoid cascading errors with other tests that don't depend on
299                  * the same filesystem.
300                  */
301                 remove_path(TMP_DIR);
302         }
303         ASSERT_EQ(0, mount(NULL, TMP_DIR, NULL, MS_PRIVATE | MS_REC, NULL));
304         clear_cap(_metadata, CAP_SYS_ADMIN);
305 }
306 
307 static void prepare_layout(struct __test_metadata *const _metadata)
308 {
309         prepare_layout_opt(_metadata, &mnt_tmp);
310 }
311 
312 static void cleanup_layout(struct __test_metadata *const _metadata)
313 {
314         set_cap(_metadata, CAP_SYS_ADMIN);
315         if (umount(TMP_DIR)) {
316                 /*
317                  * According to the test environment, the mount point of the
318                  * current directory may be shared or not, which changes the
319                  * visibility of the nested TMP_DIR mount point for the test's
320                  * parent process doing this cleanup.
321                  */
322                 ASSERT_EQ(EINVAL, errno);
323         }
324         clear_cap(_metadata, CAP_SYS_ADMIN);
325         EXPECT_EQ(0, remove_path(TMP_DIR));
326 }
327 
328 /* clang-format off */
329 FIXTURE(layout0) {};
330 /* clang-format on */
331 
332 FIXTURE_SETUP(layout0)
333 {
334         prepare_layout(_metadata);
335 }
336 
337 FIXTURE_TEARDOWN_PARENT(layout0)
338 {
339         cleanup_layout(_metadata);
340 }
341 
342 static void create_layout1(struct __test_metadata *const _metadata)
343 {
344         create_file(_metadata, file1_s1d1);
345         create_file(_metadata, file1_s1d2);
346         create_file(_metadata, file1_s1d3);
347         create_file(_metadata, file2_s1d1);
348         create_file(_metadata, file2_s1d2);
349         create_file(_metadata, file2_s1d3);
350 
351         create_file(_metadata, file1_s2d1);
352         create_file(_metadata, file1_s2d2);
353         create_file(_metadata, file1_s2d3);
354         create_file(_metadata, file2_s2d3);
355 
356         create_file(_metadata, file1_s3d1);
357         create_directory(_metadata, dir_s3d2);
358         set_cap(_metadata, CAP_SYS_ADMIN);
359         ASSERT_EQ(0, mount_opt(&mnt_tmp, dir_s3d2));
360         clear_cap(_metadata, CAP_SYS_ADMIN);
361 
362         ASSERT_EQ(0, mkdir(dir_s3d3, 0700));
363 }
364 
365 static void remove_layout1(struct __test_metadata *const _metadata)
366 {
367         EXPECT_EQ(0, remove_path(file2_s1d3));
368         EXPECT_EQ(0, remove_path(file2_s1d2));
369         EXPECT_EQ(0, remove_path(file2_s1d1));
370         EXPECT_EQ(0, remove_path(file1_s1d3));
371         EXPECT_EQ(0, remove_path(file1_s1d2));
372         EXPECT_EQ(0, remove_path(file1_s1d1));
373         EXPECT_EQ(0, remove_path(dir_s1d3));
374 
375         EXPECT_EQ(0, remove_path(file2_s2d3));
376         EXPECT_EQ(0, remove_path(file1_s2d3));
377         EXPECT_EQ(0, remove_path(file1_s2d2));
378         EXPECT_EQ(0, remove_path(file1_s2d1));
379         EXPECT_EQ(0, remove_path(dir_s2d2));
380 
381         EXPECT_EQ(0, remove_path(file1_s3d1));
382         EXPECT_EQ(0, remove_path(dir_s3d3));
383         set_cap(_metadata, CAP_SYS_ADMIN);
384         umount(dir_s3d2);
385         clear_cap(_metadata, CAP_SYS_ADMIN);
386         EXPECT_EQ(0, remove_path(dir_s3d2));
387 }
388 
389 /* clang-format off */
390 FIXTURE(layout1) {};
391 /* clang-format on */
392 
393 FIXTURE_SETUP(layout1)
394 {
395         prepare_layout(_metadata);
396 
397         create_layout1(_metadata);
398 }
399 
400 FIXTURE_TEARDOWN_PARENT(layout1)
401 {
402         remove_layout1(_metadata);
403 
404         cleanup_layout(_metadata);
405 }
406 
407 /*
408  * This helper enables to use the ASSERT_* macros and print the line number
409  * pointing to the test caller.
410  */
411 static int test_open_rel(const int dirfd, const char *const path,
412                          const int flags)
413 {
414         int fd;
415 
416         /* Works with file and directories. */
417         fd = openat(dirfd, path, flags | O_CLOEXEC);
418         if (fd < 0)
419                 return errno;
420         /*
421          * Mixing error codes from close(2) and open(2) should not lead to any
422          * (access type) confusion for this test.
423          */
424         if (close(fd) != 0)
425                 return errno;
426         return 0;
427 }
428 
429 static int test_open(const char *const path, const int flags)
430 {
431         return test_open_rel(AT_FDCWD, path, flags);
432 }
433 
434 TEST_F_FORK(layout1, no_restriction)
435 {
436         ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
437         ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
438         ASSERT_EQ(0, test_open(file2_s1d1, O_RDONLY));
439         ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
440         ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
441         ASSERT_EQ(0, test_open(file2_s1d2, O_RDONLY));
442         ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
443         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
444 
445         ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
446         ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
447         ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
448         ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
449         ASSERT_EQ(0, test_open(dir_s2d3, O_RDONLY));
450         ASSERT_EQ(0, test_open(file1_s2d3, O_RDONLY));
451 
452         ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
453         ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
454         ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
455 }
456 
457 TEST_F_FORK(layout1, inval)
458 {
459         struct landlock_path_beneath_attr path_beneath = {
460                 .allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
461                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
462                 .parent_fd = -1,
463         };
464         struct landlock_ruleset_attr ruleset_attr = {
465                 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |
466                                      LANDLOCK_ACCESS_FS_WRITE_FILE,
467         };
468         int ruleset_fd;
469 
470         path_beneath.parent_fd =
471                 open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
472         ASSERT_LE(0, path_beneath.parent_fd);
473 
474         ruleset_fd = open(dir_s1d1, O_PATH | O_DIRECTORY | O_CLOEXEC);
475         ASSERT_LE(0, ruleset_fd);
476         ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
477                                         &path_beneath, 0));
478         /* Returns EBADF because ruleset_fd is not a landlock-ruleset FD. */
479         ASSERT_EQ(EBADF, errno);
480         ASSERT_EQ(0, close(ruleset_fd));
481 
482         ruleset_fd = open(dir_s1d1, O_DIRECTORY | O_CLOEXEC);
483         ASSERT_LE(0, ruleset_fd);
484         ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
485                                         &path_beneath, 0));
486         /* Returns EBADFD because ruleset_fd is not a valid ruleset. */
487         ASSERT_EQ(EBADFD, errno);
488         ASSERT_EQ(0, close(ruleset_fd));
489 
490         /* Gets a real ruleset. */
491         ruleset_fd =
492                 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
493         ASSERT_LE(0, ruleset_fd);
494         ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
495                                        &path_beneath, 0));
496         ASSERT_EQ(0, close(path_beneath.parent_fd));
497 
498         /* Tests without O_PATH. */
499         path_beneath.parent_fd = open(dir_s1d2, O_DIRECTORY | O_CLOEXEC);
500         ASSERT_LE(0, path_beneath.parent_fd);
501         ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
502                                        &path_beneath, 0));
503         ASSERT_EQ(0, close(path_beneath.parent_fd));
504 
505         /* Tests with a ruleset FD. */
506         path_beneath.parent_fd = ruleset_fd;
507         ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
508                                         &path_beneath, 0));
509         ASSERT_EQ(EBADFD, errno);
510 
511         /* Checks unhandled allowed_access. */
512         path_beneath.parent_fd =
513                 open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
514         ASSERT_LE(0, path_beneath.parent_fd);
515 
516         /* Test with legitimate values. */
517         path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_EXECUTE;
518         ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
519                                         &path_beneath, 0));
520         ASSERT_EQ(EINVAL, errno);
521         path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_EXECUTE;
522 
523         /* Tests with denied-by-default access right. */
524         path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_REFER;
525         ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
526                                         &path_beneath, 0));
527         ASSERT_EQ(EINVAL, errno);
528         path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_REFER;
529 
530         /* Test with unknown (64-bits) value. */
531         path_beneath.allowed_access |= (1ULL << 60);
532         ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
533                                         &path_beneath, 0));
534         ASSERT_EQ(EINVAL, errno);
535         path_beneath.allowed_access &= ~(1ULL << 60);
536 
537         /* Test with no access. */
538         path_beneath.allowed_access = 0;
539         ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
540                                         &path_beneath, 0));
541         ASSERT_EQ(ENOMSG, errno);
542         path_beneath.allowed_access &= ~(1ULL << 60);
543 
544         ASSERT_EQ(0, close(path_beneath.parent_fd));
545 
546         /* Enforces the ruleset. */
547         ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
548         ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
549 
550         ASSERT_EQ(0, close(ruleset_fd));
551 }
552 
553 /* clang-format off */
554 
555 #define ACCESS_FILE ( \
556         LANDLOCK_ACCESS_FS_EXECUTE | \
557         LANDLOCK_ACCESS_FS_WRITE_FILE | \
558         LANDLOCK_ACCESS_FS_READ_FILE | \
559         LANDLOCK_ACCESS_FS_TRUNCATE | \
560         LANDLOCK_ACCESS_FS_IOCTL_DEV)
561 
562 #define ACCESS_LAST LANDLOCK_ACCESS_FS_IOCTL_DEV
563 
564 #define ACCESS_ALL ( \
565         ACCESS_FILE | \
566         LANDLOCK_ACCESS_FS_READ_DIR | \
567         LANDLOCK_ACCESS_FS_REMOVE_DIR | \
568         LANDLOCK_ACCESS_FS_REMOVE_FILE | \
569         LANDLOCK_ACCESS_FS_MAKE_CHAR | \
570         LANDLOCK_ACCESS_FS_MAKE_DIR | \
571         LANDLOCK_ACCESS_FS_MAKE_REG | \
572         LANDLOCK_ACCESS_FS_MAKE_SOCK | \
573         LANDLOCK_ACCESS_FS_MAKE_FIFO | \
574         LANDLOCK_ACCESS_FS_MAKE_BLOCK | \
575         LANDLOCK_ACCESS_FS_MAKE_SYM | \
576         LANDLOCK_ACCESS_FS_REFER)
577 
578 /* clang-format on */
579 
580 TEST_F_FORK(layout1, file_and_dir_access_rights)
581 {
582         __u64 access;
583         int err;
584         struct landlock_path_beneath_attr path_beneath_file = {},
585                                           path_beneath_dir = {};
586         struct landlock_ruleset_attr ruleset_attr = {
587                 .handled_access_fs = ACCESS_ALL,
588         };
589         const int ruleset_fd =
590                 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
591 
592         ASSERT_LE(0, ruleset_fd);
593 
594         /* Tests access rights for files. */
595         path_beneath_file.parent_fd = open(file1_s1d2, O_PATH | O_CLOEXEC);
596         ASSERT_LE(0, path_beneath_file.parent_fd);
597 
598         /* Tests access rights for directories. */
599         path_beneath_dir.parent_fd =
600                 open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
601         ASSERT_LE(0, path_beneath_dir.parent_fd);
602 
603         for (access = 1; access <= ACCESS_LAST; access <<= 1) {
604                 path_beneath_dir.allowed_access = access;
605                 ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
606                                                LANDLOCK_RULE_PATH_BENEATH,
607                                                &path_beneath_dir, 0));
608 
609                 path_beneath_file.allowed_access = access;
610                 err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
611                                         &path_beneath_file, 0);
612                 if (access & ACCESS_FILE) {
613                         ASSERT_EQ(0, err);
614                 } else {
615                         ASSERT_EQ(-1, err);
616                         ASSERT_EQ(EINVAL, errno);
617                 }
618         }
619         ASSERT_EQ(0, close(path_beneath_file.parent_fd));
620         ASSERT_EQ(0, close(path_beneath_dir.parent_fd));
621         ASSERT_EQ(0, close(ruleset_fd));
622 }
623 
624 TEST_F_FORK(layout0, ruleset_with_unknown_access)
625 {
626         __u64 access_mask;
627 
628         for (access_mask = 1ULL << 63; access_mask != ACCESS_LAST;
629              access_mask >>= 1) {
630                 struct landlock_ruleset_attr ruleset_attr = {
631                         .handled_access_fs = access_mask,
632                 };
633 
634                 ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
635                                                       sizeof(ruleset_attr), 0));
636                 ASSERT_EQ(EINVAL, errno);
637         }
638 }
639 
640 TEST_F_FORK(layout0, rule_with_unknown_access)
641 {
642         __u64 access;
643         struct landlock_path_beneath_attr path_beneath = {};
644         const struct landlock_ruleset_attr ruleset_attr = {
645                 .handled_access_fs = ACCESS_ALL,
646         };
647         const int ruleset_fd =
648                 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
649 
650         ASSERT_LE(0, ruleset_fd);
651 
652         path_beneath.parent_fd =
653                 open(TMP_DIR, O_PATH | O_DIRECTORY | O_CLOEXEC);
654         ASSERT_LE(0, path_beneath.parent_fd);
655 
656         for (access = 1ULL << 63; access != ACCESS_LAST; access >>= 1) {
657                 path_beneath.allowed_access = access;
658                 EXPECT_EQ(-1, landlock_add_rule(ruleset_fd,
659                                                 LANDLOCK_RULE_PATH_BENEATH,
660                                                 &path_beneath, 0));
661                 EXPECT_EQ(EINVAL, errno);
662         }
663         ASSERT_EQ(0, close(path_beneath.parent_fd));
664         ASSERT_EQ(0, close(ruleset_fd));
665 }
666 
667 TEST_F_FORK(layout1, rule_with_unhandled_access)
668 {
669         struct landlock_ruleset_attr ruleset_attr = {
670                 .handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
671         };
672         struct landlock_path_beneath_attr path_beneath = {};
673         int ruleset_fd;
674         __u64 access;
675 
676         ruleset_fd =
677                 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
678         ASSERT_LE(0, ruleset_fd);
679 
680         path_beneath.parent_fd = open(file1_s1d2, O_PATH | O_CLOEXEC);
681         ASSERT_LE(0, path_beneath.parent_fd);
682 
683         for (access = 1; access > 0; access <<= 1) {
684                 int err;
685 
686                 path_beneath.allowed_access = access;
687                 err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
688                                         &path_beneath, 0);
689                 if (access == ruleset_attr.handled_access_fs) {
690                         EXPECT_EQ(0, err);
691                 } else {
692                         EXPECT_EQ(-1, err);
693                         EXPECT_EQ(EINVAL, errno);
694                 }
695         }
696 
697         EXPECT_EQ(0, close(path_beneath.parent_fd));
698         EXPECT_EQ(0, close(ruleset_fd));
699 }
700 
701 static void add_path_beneath(struct __test_metadata *const _metadata,
702                              const int ruleset_fd, const __u64 allowed_access,
703                              const char *const path)
704 {
705         struct landlock_path_beneath_attr path_beneath = {
706                 .allowed_access = allowed_access,
707         };
708 
709         path_beneath.parent_fd = open(path, O_PATH | O_CLOEXEC);
710         ASSERT_LE(0, path_beneath.parent_fd)
711         {
712                 TH_LOG("Failed to open directory \"%s\": %s", path,
713                        strerror(errno));
714         }
715         ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
716                                        &path_beneath, 0))
717         {
718                 TH_LOG("Failed to update the ruleset with \"%s\": %s", path,
719                        strerror(errno));
720         }
721         ASSERT_EQ(0, close(path_beneath.parent_fd));
722 }
723 
724 struct rule {
725         const char *path;
726         __u64 access;
727 };
728 
729 /* clang-format off */
730 
731 #define ACCESS_RO ( \
732         LANDLOCK_ACCESS_FS_READ_FILE | \
733         LANDLOCK_ACCESS_FS_READ_DIR)
734 
735 #define ACCESS_RW ( \
736         ACCESS_RO | \
737         LANDLOCK_ACCESS_FS_WRITE_FILE)
738 
739 /* clang-format on */
740 
741 static int create_ruleset(struct __test_metadata *const _metadata,
742                           const __u64 handled_access_fs,
743                           const struct rule rules[])
744 {
745         int ruleset_fd, i;
746         struct landlock_ruleset_attr ruleset_attr = {
747                 .handled_access_fs = handled_access_fs,
748         };
749 
750         ASSERT_NE(NULL, rules)
751         {
752                 TH_LOG("No rule list");
753         }
754         ASSERT_NE(NULL, rules[0].path)
755         {
756                 TH_LOG("Empty rule list");
757         }
758 
759         ruleset_fd =
760                 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
761         ASSERT_LE(0, ruleset_fd)
762         {
763                 TH_LOG("Failed to create a ruleset: %s", strerror(errno));
764         }
765 
766         for (i = 0; rules[i].path; i++) {
767                 if (!rules[i].access)
768                         continue;
769 
770                 add_path_beneath(_metadata, ruleset_fd, rules[i].access,
771                                  rules[i].path);
772         }
773         return ruleset_fd;
774 }
775 
776 TEST_F_FORK(layout0, proc_nsfs)
777 {
778         const struct rule rules[] = {
779                 {
780                         .path = "/dev/null",
781                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
782                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
783                 },
784                 {},
785         };
786         struct landlock_path_beneath_attr path_beneath;
787         const int ruleset_fd = create_ruleset(
788                 _metadata, rules[0].access | LANDLOCK_ACCESS_FS_READ_DIR,
789                 rules);
790 
791         ASSERT_LE(0, ruleset_fd);
792         ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
793 
794         enforce_ruleset(_metadata, ruleset_fd);
795 
796         ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
797         ASSERT_EQ(EACCES, test_open("/dev", O_RDONLY));
798         ASSERT_EQ(0, test_open("/dev/null", O_RDONLY));
799         ASSERT_EQ(EACCES, test_open("/dev/full", O_RDONLY));
800 
801         ASSERT_EQ(EACCES, test_open("/proc", O_RDONLY));
802         ASSERT_EQ(EACCES, test_open("/proc/self", O_RDONLY));
803         ASSERT_EQ(EACCES, test_open("/proc/self/ns", O_RDONLY));
804         /*
805          * Because nsfs is an internal filesystem, /proc/self/ns/mnt is a
806          * disconnected path.  Such path cannot be identified and must then be
807          * allowed.
808          */
809         ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
810 
811         /*
812          * Checks that it is not possible to add nsfs-like filesystem
813          * references to a ruleset.
814          */
815         path_beneath.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
816                                       LANDLOCK_ACCESS_FS_WRITE_FILE,
817         path_beneath.parent_fd = open("/proc/self/ns/mnt", O_PATH | O_CLOEXEC);
818         ASSERT_LE(0, path_beneath.parent_fd);
819         ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
820                                         &path_beneath, 0));
821         ASSERT_EQ(EBADFD, errno);
822         ASSERT_EQ(0, close(path_beneath.parent_fd));
823 }
824 
825 TEST_F_FORK(layout0, unpriv)
826 {
827         const struct rule rules[] = {
828                 {
829                         .path = TMP_DIR,
830                         .access = ACCESS_RO,
831                 },
832                 {},
833         };
834         int ruleset_fd;
835 
836         drop_caps(_metadata);
837 
838         ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
839         ASSERT_LE(0, ruleset_fd);
840         ASSERT_EQ(-1, landlock_restrict_self(ruleset_fd, 0));
841         ASSERT_EQ(EPERM, errno);
842 
843         /* enforce_ruleset() calls prctl(no_new_privs). */
844         enforce_ruleset(_metadata, ruleset_fd);
845         ASSERT_EQ(0, close(ruleset_fd));
846 }
847 
848 TEST_F_FORK(layout1, effective_access)
849 {
850         const struct rule rules[] = {
851                 {
852                         .path = dir_s1d2,
853                         .access = ACCESS_RO,
854                 },
855                 {
856                         .path = file1_s2d2,
857                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
858                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
859                 },
860                 {},
861         };
862         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
863         char buf;
864         int reg_fd;
865 
866         ASSERT_LE(0, ruleset_fd);
867         enforce_ruleset(_metadata, ruleset_fd);
868         ASSERT_EQ(0, close(ruleset_fd));
869 
870         /* Tests on a directory (with or without O_PATH). */
871         ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
872         ASSERT_EQ(0, test_open("/", O_RDONLY | O_PATH));
873         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
874         ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_PATH));
875         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
876         ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY | O_PATH));
877 
878         ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
879         ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
880         ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
881         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
882 
883         /* Tests on a file (with or without O_PATH). */
884         ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY));
885         ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_PATH));
886 
887         ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
888 
889         /* Checks effective read and write actions. */
890         reg_fd = open(file1_s2d2, O_RDWR | O_CLOEXEC);
891         ASSERT_LE(0, reg_fd);
892         ASSERT_EQ(1, write(reg_fd, ".", 1));
893         ASSERT_LE(0, lseek(reg_fd, 0, SEEK_SET));
894         ASSERT_EQ(1, read(reg_fd, &buf, 1));
895         ASSERT_EQ('.', buf);
896         ASSERT_EQ(0, close(reg_fd));
897 
898         /* Just in case, double-checks effective actions. */
899         reg_fd = open(file1_s2d2, O_RDONLY | O_CLOEXEC);
900         ASSERT_LE(0, reg_fd);
901         ASSERT_EQ(-1, write(reg_fd, &buf, 1));
902         ASSERT_EQ(EBADF, errno);
903         ASSERT_EQ(0, close(reg_fd));
904 }
905 
906 TEST_F_FORK(layout1, unhandled_access)
907 {
908         const struct rule rules[] = {
909                 {
910                         .path = dir_s1d2,
911                         .access = ACCESS_RO,
912                 },
913                 {},
914         };
915         /* Here, we only handle read accesses, not write accesses. */
916         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
917 
918         ASSERT_LE(0, ruleset_fd);
919         enforce_ruleset(_metadata, ruleset_fd);
920         ASSERT_EQ(0, close(ruleset_fd));
921 
922         /*
923          * Because the policy does not handle LANDLOCK_ACCESS_FS_WRITE_FILE,
924          * opening for write-only should be allowed, but not read-write.
925          */
926         ASSERT_EQ(0, test_open(file1_s1d1, O_WRONLY));
927         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
928 
929         ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
930         ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
931 }
932 
933 TEST_F_FORK(layout1, ruleset_overlap)
934 {
935         const struct rule rules[] = {
936                 /* These rules should be ORed among them. */
937                 {
938                         .path = dir_s1d2,
939                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
940                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
941                 },
942                 {
943                         .path = dir_s1d2,
944                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
945                                   LANDLOCK_ACCESS_FS_READ_DIR,
946                 },
947                 {},
948         };
949         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
950 
951         ASSERT_LE(0, ruleset_fd);
952         enforce_ruleset(_metadata, ruleset_fd);
953         ASSERT_EQ(0, close(ruleset_fd));
954 
955         /* Checks s1d1 hierarchy. */
956         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
957         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
958         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
959         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
960 
961         /* Checks s1d2 hierarchy. */
962         ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
963         ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
964         ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
965         ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
966 
967         /* Checks s1d3 hierarchy. */
968         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
969         ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
970         ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
971         ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
972 }
973 
974 TEST_F_FORK(layout1, layer_rule_unions)
975 {
976         const struct rule layer1[] = {
977                 {
978                         .path = dir_s1d2,
979                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
980                 },
981                 /* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
982                 {
983                         .path = dir_s1d3,
984                         .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
985                 },
986                 {},
987         };
988         const struct rule layer2[] = {
989                 /* Doesn't change anything from layer1. */
990                 {
991                         .path = dir_s1d2,
992                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
993                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
994                 },
995                 {},
996         };
997         const struct rule layer3[] = {
998                 /* Only allows write (but not read) to dir_s1d3. */
999                 {
1000                         .path = dir_s1d2,
1001                         .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
1002                 },
1003                 {},
1004         };
1005         int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1);
1006 
1007         ASSERT_LE(0, ruleset_fd);
1008         enforce_ruleset(_metadata, ruleset_fd);
1009         ASSERT_EQ(0, close(ruleset_fd));
1010 
1011         /* Checks s1d1 hierarchy with layer1. */
1012         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1013         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1014         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
1015         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1016 
1017         /* Checks s1d2 hierarchy with layer1. */
1018         ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
1019         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1020         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
1021         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1022 
1023         /* Checks s1d3 hierarchy with layer1. */
1024         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1025         ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
1026         /* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
1027         ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1028         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1029 
1030         /* Doesn't change anything from layer1. */
1031         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2);
1032         ASSERT_LE(0, ruleset_fd);
1033         enforce_ruleset(_metadata, ruleset_fd);
1034         ASSERT_EQ(0, close(ruleset_fd));
1035 
1036         /* Checks s1d1 hierarchy with layer2. */
1037         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1038         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1039         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
1040         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1041 
1042         /* Checks s1d2 hierarchy with layer2. */
1043         ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
1044         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1045         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
1046         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1047 
1048         /* Checks s1d3 hierarchy with layer2. */
1049         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1050         ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
1051         /* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
1052         ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1053         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1054 
1055         /* Only allows write (but not read) to dir_s1d3. */
1056         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3);
1057         ASSERT_LE(0, ruleset_fd);
1058         enforce_ruleset(_metadata, ruleset_fd);
1059         ASSERT_EQ(0, close(ruleset_fd));
1060 
1061         /* Checks s1d1 hierarchy with layer3. */
1062         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1063         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1064         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
1065         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1066 
1067         /* Checks s1d2 hierarchy with layer3. */
1068         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDONLY));
1069         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1070         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
1071         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1072 
1073         /* Checks s1d3 hierarchy with layer3. */
1074         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
1075         ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
1076         /* dir_s1d3 should now deny READ_FILE and WRITE_FILE (O_RDWR). */
1077         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDWR));
1078         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1079 }
1080 
1081 TEST_F_FORK(layout1, non_overlapping_accesses)
1082 {
1083         const struct rule layer1[] = {
1084                 {
1085                         .path = dir_s1d2,
1086                         .access = LANDLOCK_ACCESS_FS_MAKE_REG,
1087                 },
1088                 {},
1089         };
1090         const struct rule layer2[] = {
1091                 {
1092                         .path = dir_s1d3,
1093                         .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
1094                 },
1095                 {},
1096         };
1097         int ruleset_fd;
1098 
1099         ASSERT_EQ(0, unlink(file1_s1d1));
1100         ASSERT_EQ(0, unlink(file1_s1d2));
1101 
1102         ruleset_fd =
1103                 create_ruleset(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, layer1);
1104         ASSERT_LE(0, ruleset_fd);
1105         enforce_ruleset(_metadata, ruleset_fd);
1106         ASSERT_EQ(0, close(ruleset_fd));
1107 
1108         ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
1109         ASSERT_EQ(EACCES, errno);
1110         ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
1111         ASSERT_EQ(0, unlink(file1_s1d2));
1112 
1113         ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_REMOVE_FILE,
1114                                     layer2);
1115         ASSERT_LE(0, ruleset_fd);
1116         enforce_ruleset(_metadata, ruleset_fd);
1117         ASSERT_EQ(0, close(ruleset_fd));
1118 
1119         /* Unchanged accesses for file creation. */
1120         ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
1121         ASSERT_EQ(EACCES, errno);
1122         ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
1123 
1124         /* Checks file removing. */
1125         ASSERT_EQ(-1, unlink(file1_s1d2));
1126         ASSERT_EQ(EACCES, errno);
1127         ASSERT_EQ(0, unlink(file1_s1d3));
1128 }
1129 
1130 TEST_F_FORK(layout1, interleaved_masked_accesses)
1131 {
1132         /*
1133          * Checks overly restrictive rules:
1134          * layer 1: allows R   s1d1/s1d2/s1d3/file1
1135          * layer 2: allows RW  s1d1/s1d2/s1d3
1136          *          allows  W  s1d1/s1d2
1137          *          denies R   s1d1/s1d2
1138          * layer 3: allows R   s1d1
1139          * layer 4: allows R   s1d1/s1d2
1140          *          denies  W  s1d1/s1d2
1141          * layer 5: allows R   s1d1/s1d2
1142          * layer 6: allows   X ----
1143          * layer 7: allows  W  s1d1/s1d2
1144          *          denies R   s1d1/s1d2
1145          */
1146         const struct rule layer1_read[] = {
1147                 /* Allows read access to file1_s1d3 with the first layer. */
1148                 {
1149                         .path = file1_s1d3,
1150                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
1151                 },
1152                 {},
1153         };
1154         /* First rule with write restrictions. */
1155         const struct rule layer2_read_write[] = {
1156                 /* Start by granting read-write access via its parent directory... */
1157                 {
1158                         .path = dir_s1d3,
1159                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
1160                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
1161                 },
1162                 /* ...but also denies read access via its grandparent directory. */
1163                 {
1164                         .path = dir_s1d2,
1165                         .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
1166                 },
1167                 {},
1168         };
1169         const struct rule layer3_read[] = {
1170                 /* Allows read access via its great-grandparent directory. */
1171                 {
1172                         .path = dir_s1d1,
1173                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
1174                 },
1175                 {},
1176         };
1177         const struct rule layer4_read_write[] = {
1178                 /*
1179                  * Try to confuse the deny access by denying write (but not
1180                  * read) access via its grandparent directory.
1181                  */
1182                 {
1183                         .path = dir_s1d2,
1184                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
1185                 },
1186                 {},
1187         };
1188         const struct rule layer5_read[] = {
1189                 /*
1190                  * Try to override layer2's deny read access by explicitly
1191                  * allowing read access via file1_s1d3's grandparent.
1192                  */
1193                 {
1194                         .path = dir_s1d2,
1195                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
1196                 },
1197                 {},
1198         };
1199         const struct rule layer6_execute[] = {
1200                 /*
1201                  * Restricts an unrelated file hierarchy with a new access
1202                  * (non-overlapping) type.
1203                  */
1204                 {
1205                         .path = dir_s2d1,
1206                         .access = LANDLOCK_ACCESS_FS_EXECUTE,
1207                 },
1208                 {},
1209         };
1210         const struct rule layer7_read_write[] = {
1211                 /*
1212                  * Finally, denies read access to file1_s1d3 via its
1213                  * grandparent.
1214                  */
1215                 {
1216                         .path = dir_s1d2,
1217                         .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
1218                 },
1219                 {},
1220         };
1221         int ruleset_fd;
1222 
1223         ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
1224                                     layer1_read);
1225         ASSERT_LE(0, ruleset_fd);
1226         enforce_ruleset(_metadata, ruleset_fd);
1227         ASSERT_EQ(0, close(ruleset_fd));
1228 
1229         /* Checks that read access is granted for file1_s1d3 with layer 1. */
1230         ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1231         ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1232         ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
1233 
1234         ruleset_fd = create_ruleset(_metadata,
1235                                     LANDLOCK_ACCESS_FS_READ_FILE |
1236                                             LANDLOCK_ACCESS_FS_WRITE_FILE,
1237                                     layer2_read_write);
1238         ASSERT_LE(0, ruleset_fd);
1239         enforce_ruleset(_metadata, ruleset_fd);
1240         ASSERT_EQ(0, close(ruleset_fd));
1241 
1242         /* Checks that previous access rights are unchanged with layer 2. */
1243         ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1244         ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1245         ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
1246 
1247         ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
1248                                     layer3_read);
1249         ASSERT_LE(0, ruleset_fd);
1250         enforce_ruleset(_metadata, ruleset_fd);
1251         ASSERT_EQ(0, close(ruleset_fd));
1252 
1253         /* Checks that previous access rights are unchanged with layer 3. */
1254         ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
1255         ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1256         ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
1257 
1258         /* This time, denies write access for the file hierarchy. */
1259         ruleset_fd = create_ruleset(_metadata,
1260                                     LANDLOCK_ACCESS_FS_READ_FILE |
1261                                             LANDLOCK_ACCESS_FS_WRITE_FILE,
1262                                     layer4_read_write);
1263         ASSERT_LE(0, ruleset_fd);
1264         enforce_ruleset(_metadata, ruleset_fd);
1265         ASSERT_EQ(0, close(ruleset_fd));
1266 
1267         /*
1268          * Checks that the only change with layer 4 is that write access is
1269          * denied.
1270          */
1271         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1272         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1273         ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1274         ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1275 
1276         ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
1277                                     layer5_read);
1278         ASSERT_LE(0, ruleset_fd);
1279         enforce_ruleset(_metadata, ruleset_fd);
1280         ASSERT_EQ(0, close(ruleset_fd));
1281 
1282         /* Checks that previous access rights are unchanged with layer 5. */
1283         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1284         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1285         ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1286         ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1287 
1288         ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_EXECUTE,
1289                                     layer6_execute);
1290         ASSERT_LE(0, ruleset_fd);
1291         enforce_ruleset(_metadata, ruleset_fd);
1292         ASSERT_EQ(0, close(ruleset_fd));
1293 
1294         /* Checks that previous access rights are unchanged with layer 6. */
1295         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1296         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1297         ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1298         ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1299 
1300         ruleset_fd = create_ruleset(_metadata,
1301                                     LANDLOCK_ACCESS_FS_READ_FILE |
1302                                             LANDLOCK_ACCESS_FS_WRITE_FILE,
1303                                     layer7_read_write);
1304         ASSERT_LE(0, ruleset_fd);
1305         enforce_ruleset(_metadata, ruleset_fd);
1306         ASSERT_EQ(0, close(ruleset_fd));
1307 
1308         /* Checks read access is now denied with layer 7. */
1309         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
1310         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1311         ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
1312         ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
1313 }
1314 
1315 TEST_F_FORK(layout1, inherit_subset)
1316 {
1317         const struct rule rules[] = {
1318                 {
1319                         .path = dir_s1d2,
1320                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
1321                                   LANDLOCK_ACCESS_FS_READ_DIR,
1322                 },
1323                 {},
1324         };
1325         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1326 
1327         ASSERT_LE(0, ruleset_fd);
1328         enforce_ruleset(_metadata, ruleset_fd);
1329 
1330         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1331         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1332 
1333         /* Write access is forbidden. */
1334         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1335         /* Readdir access is allowed. */
1336         ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1337 
1338         /* Write access is forbidden. */
1339         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1340         /* Readdir access is allowed. */
1341         ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1342 
1343         /*
1344          * Tests shared rule extension: the following rules should not grant
1345          * any new access, only remove some.  Once enforced, these rules are
1346          * ANDed with the previous ones.
1347          */
1348         add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
1349                          dir_s1d2);
1350         /*
1351          * According to ruleset_fd, dir_s1d2 should now have the
1352          * LANDLOCK_ACCESS_FS_READ_FILE and LANDLOCK_ACCESS_FS_WRITE_FILE
1353          * access rights (even if this directory is opened a second time).
1354          * However, when enforcing this updated ruleset, the ruleset tied to
1355          * the current process (i.e. its domain) will still only have the
1356          * dir_s1d2 with LANDLOCK_ACCESS_FS_READ_FILE and
1357          * LANDLOCK_ACCESS_FS_READ_DIR accesses, but
1358          * LANDLOCK_ACCESS_FS_WRITE_FILE must not be allowed because it would
1359          * be a privilege escalation.
1360          */
1361         enforce_ruleset(_metadata, ruleset_fd);
1362 
1363         /* Same tests and results as above. */
1364         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1365         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1366 
1367         /* It is still forbidden to write in file1_s1d2. */
1368         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1369         /* Readdir access is still allowed. */
1370         ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1371 
1372         /* It is still forbidden to write in file1_s1d3. */
1373         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1374         /* Readdir access is still allowed. */
1375         ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1376 
1377         /*
1378          * Try to get more privileges by adding new access rights to the parent
1379          * directory: dir_s1d1.
1380          */
1381         add_path_beneath(_metadata, ruleset_fd, ACCESS_RW, dir_s1d1);
1382         enforce_ruleset(_metadata, ruleset_fd);
1383 
1384         /* Same tests and results as above. */
1385         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1386         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1387 
1388         /* It is still forbidden to write in file1_s1d2. */
1389         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1390         /* Readdir access is still allowed. */
1391         ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1392 
1393         /* It is still forbidden to write in file1_s1d3. */
1394         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1395         /* Readdir access is still allowed. */
1396         ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1397 
1398         /*
1399          * Now, dir_s1d3 get a new rule tied to it, only allowing
1400          * LANDLOCK_ACCESS_FS_WRITE_FILE.  The (kernel internal) difference is
1401          * that there was no rule tied to it before.
1402          */
1403         add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
1404                          dir_s1d3);
1405         enforce_ruleset(_metadata, ruleset_fd);
1406         ASSERT_EQ(0, close(ruleset_fd));
1407 
1408         /*
1409          * Same tests and results as above, except for open(dir_s1d3) which is
1410          * now denied because the new rule mask the rule previously inherited
1411          * from dir_s1d2.
1412          */
1413 
1414         /* Same tests and results as above. */
1415         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
1416         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
1417 
1418         /* It is still forbidden to write in file1_s1d2. */
1419         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
1420         /* Readdir access is still allowed. */
1421         ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1422 
1423         /* It is still forbidden to write in file1_s1d3. */
1424         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
1425         /*
1426          * Readdir of dir_s1d3 is still allowed because of the OR policy inside
1427          * the same layer.
1428          */
1429         ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1430 }
1431 
1432 TEST_F_FORK(layout1, inherit_superset)
1433 {
1434         const struct rule rules[] = {
1435                 {
1436                         .path = dir_s1d3,
1437                         .access = ACCESS_RO,
1438                 },
1439                 {},
1440         };
1441         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1442 
1443         ASSERT_LE(0, ruleset_fd);
1444         enforce_ruleset(_metadata, ruleset_fd);
1445 
1446         /* Readdir access is denied for dir_s1d2. */
1447         ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1448         /* Readdir access is allowed for dir_s1d3. */
1449         ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1450         /* File access is allowed for file1_s1d3. */
1451         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1452 
1453         /* Now dir_s1d2, parent of dir_s1d3, gets a new rule tied to it. */
1454         add_path_beneath(_metadata, ruleset_fd,
1455                          LANDLOCK_ACCESS_FS_READ_FILE |
1456                                  LANDLOCK_ACCESS_FS_READ_DIR,
1457                          dir_s1d2);
1458         enforce_ruleset(_metadata, ruleset_fd);
1459         ASSERT_EQ(0, close(ruleset_fd));
1460 
1461         /* Readdir access is still denied for dir_s1d2. */
1462         ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
1463         /* Readdir access is still allowed for dir_s1d3. */
1464         ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
1465         /* File access is still allowed for file1_s1d3. */
1466         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
1467 }
1468 
1469 TEST_F_FORK(layout0, max_layers)
1470 {
1471         int i, err;
1472         const struct rule rules[] = {
1473                 {
1474                         .path = TMP_DIR,
1475                         .access = ACCESS_RO,
1476                 },
1477                 {},
1478         };
1479         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1480 
1481         ASSERT_LE(0, ruleset_fd);
1482         for (i = 0; i < 16; i++)
1483                 enforce_ruleset(_metadata, ruleset_fd);
1484 
1485         for (i = 0; i < 2; i++) {
1486                 err = landlock_restrict_self(ruleset_fd, 0);
1487                 ASSERT_EQ(-1, err);
1488                 ASSERT_EQ(E2BIG, errno);
1489         }
1490         ASSERT_EQ(0, close(ruleset_fd));
1491 }
1492 
1493 TEST_F_FORK(layout1, empty_or_same_ruleset)
1494 {
1495         struct landlock_ruleset_attr ruleset_attr = {};
1496         int ruleset_fd;
1497 
1498         /* Tests empty handled_access_fs. */
1499         ruleset_fd =
1500                 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
1501         ASSERT_LE(-1, ruleset_fd);
1502         ASSERT_EQ(ENOMSG, errno);
1503 
1504         /* Enforces policy which deny read access to all files. */
1505         ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE;
1506         ruleset_fd =
1507                 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
1508         ASSERT_LE(0, ruleset_fd);
1509         enforce_ruleset(_metadata, ruleset_fd);
1510         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1511         ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1512 
1513         /* Nests a policy which deny read access to all directories. */
1514         ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR;
1515         ruleset_fd =
1516                 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
1517         ASSERT_LE(0, ruleset_fd);
1518         enforce_ruleset(_metadata, ruleset_fd);
1519         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
1520         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1521 
1522         /* Enforces a second time with the same ruleset. */
1523         enforce_ruleset(_metadata, ruleset_fd);
1524         ASSERT_EQ(0, close(ruleset_fd));
1525 }
1526 
1527 TEST_F_FORK(layout1, rule_on_mountpoint)
1528 {
1529         const struct rule rules[] = {
1530                 {
1531                         .path = dir_s1d1,
1532                         .access = ACCESS_RO,
1533                 },
1534                 {
1535                         /* dir_s3d2 is a mount point. */
1536                         .path = dir_s3d2,
1537                         .access = ACCESS_RO,
1538                 },
1539                 {},
1540         };
1541         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1542 
1543         ASSERT_LE(0, ruleset_fd);
1544         enforce_ruleset(_metadata, ruleset_fd);
1545         ASSERT_EQ(0, close(ruleset_fd));
1546 
1547         ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1548 
1549         ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
1550 
1551         ASSERT_EQ(EACCES, test_open(dir_s3d1, O_RDONLY));
1552         ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
1553         ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
1554 }
1555 
1556 TEST_F_FORK(layout1, rule_over_mountpoint)
1557 {
1558         const struct rule rules[] = {
1559                 {
1560                         .path = dir_s1d1,
1561                         .access = ACCESS_RO,
1562                 },
1563                 {
1564                         /* dir_s3d2 is a mount point. */
1565                         .path = dir_s3d1,
1566                         .access = ACCESS_RO,
1567                 },
1568                 {},
1569         };
1570         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1571 
1572         ASSERT_LE(0, ruleset_fd);
1573         enforce_ruleset(_metadata, ruleset_fd);
1574         ASSERT_EQ(0, close(ruleset_fd));
1575 
1576         ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1577 
1578         ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
1579 
1580         ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
1581         ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
1582         ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
1583 }
1584 
1585 /*
1586  * This test verifies that we can apply a landlock rule on the root directory
1587  * (which might require special handling).
1588  */
1589 TEST_F_FORK(layout1, rule_over_root_allow_then_deny)
1590 {
1591         struct rule rules[] = {
1592                 {
1593                         .path = "/",
1594                         .access = ACCESS_RO,
1595                 },
1596                 {},
1597         };
1598         int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1599 
1600         ASSERT_LE(0, ruleset_fd);
1601         enforce_ruleset(_metadata, ruleset_fd);
1602         ASSERT_EQ(0, close(ruleset_fd));
1603 
1604         /* Checks allowed access. */
1605         ASSERT_EQ(0, test_open("/", O_RDONLY));
1606         ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
1607 
1608         rules[0].access = LANDLOCK_ACCESS_FS_READ_FILE;
1609         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1610         ASSERT_LE(0, ruleset_fd);
1611         enforce_ruleset(_metadata, ruleset_fd);
1612         ASSERT_EQ(0, close(ruleset_fd));
1613 
1614         /* Checks denied access (on a directory). */
1615         ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1616         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1617 }
1618 
1619 TEST_F_FORK(layout1, rule_over_root_deny)
1620 {
1621         const struct rule rules[] = {
1622                 {
1623                         .path = "/",
1624                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
1625                 },
1626                 {},
1627         };
1628         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1629 
1630         ASSERT_LE(0, ruleset_fd);
1631         enforce_ruleset(_metadata, ruleset_fd);
1632         ASSERT_EQ(0, close(ruleset_fd));
1633 
1634         /* Checks denied access (on a directory). */
1635         ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1636         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
1637 }
1638 
1639 TEST_F_FORK(layout1, rule_inside_mount_ns)
1640 {
1641         const struct rule rules[] = {
1642                 {
1643                         .path = "s3d3",
1644                         .access = ACCESS_RO,
1645                 },
1646                 {},
1647         };
1648         int ruleset_fd;
1649 
1650         set_cap(_metadata, CAP_SYS_ADMIN);
1651         ASSERT_EQ(0, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3))
1652         {
1653                 TH_LOG("Failed to pivot root: %s", strerror(errno));
1654         };
1655         ASSERT_EQ(0, chdir("/"));
1656         clear_cap(_metadata, CAP_SYS_ADMIN);
1657 
1658         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1659         ASSERT_LE(0, ruleset_fd);
1660         enforce_ruleset(_metadata, ruleset_fd);
1661         ASSERT_EQ(0, close(ruleset_fd));
1662 
1663         ASSERT_EQ(0, test_open("s3d3", O_RDONLY));
1664         ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
1665 }
1666 
1667 TEST_F_FORK(layout1, mount_and_pivot)
1668 {
1669         const struct rule rules[] = {
1670                 {
1671                         .path = dir_s3d2,
1672                         .access = ACCESS_RO,
1673                 },
1674                 {},
1675         };
1676         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1677 
1678         ASSERT_LE(0, ruleset_fd);
1679         enforce_ruleset(_metadata, ruleset_fd);
1680         ASSERT_EQ(0, close(ruleset_fd));
1681 
1682         set_cap(_metadata, CAP_SYS_ADMIN);
1683         ASSERT_EQ(-1, mount(NULL, dir_s3d2, NULL, MS_RDONLY, NULL));
1684         ASSERT_EQ(EPERM, errno);
1685         ASSERT_EQ(-1, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3));
1686         ASSERT_EQ(EPERM, errno);
1687         clear_cap(_metadata, CAP_SYS_ADMIN);
1688 }
1689 
1690 TEST_F_FORK(layout1, move_mount)
1691 {
1692         const struct rule rules[] = {
1693                 {
1694                         .path = dir_s3d2,
1695                         .access = ACCESS_RO,
1696                 },
1697                 {},
1698         };
1699         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1700 
1701         ASSERT_LE(0, ruleset_fd);
1702 
1703         set_cap(_metadata, CAP_SYS_ADMIN);
1704         ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1705                              dir_s1d2, 0))
1706         {
1707                 TH_LOG("Failed to move mount: %s", strerror(errno));
1708         }
1709 
1710         ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD,
1711                              dir_s3d2, 0));
1712         clear_cap(_metadata, CAP_SYS_ADMIN);
1713 
1714         enforce_ruleset(_metadata, ruleset_fd);
1715         ASSERT_EQ(0, close(ruleset_fd));
1716 
1717         set_cap(_metadata, CAP_SYS_ADMIN);
1718         ASSERT_EQ(-1, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1719                               dir_s1d2, 0));
1720         ASSERT_EQ(EPERM, errno);
1721         clear_cap(_metadata, CAP_SYS_ADMIN);
1722 }
1723 
1724 TEST_F_FORK(layout1, topology_changes_with_net_only)
1725 {
1726         const struct landlock_ruleset_attr ruleset_net = {
1727                 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP |
1728                                       LANDLOCK_ACCESS_NET_CONNECT_TCP,
1729         };
1730         int ruleset_fd;
1731 
1732         /* Add network restrictions. */
1733         ruleset_fd =
1734                 landlock_create_ruleset(&ruleset_net, sizeof(ruleset_net), 0);
1735         ASSERT_LE(0, ruleset_fd);
1736         enforce_ruleset(_metadata, ruleset_fd);
1737         ASSERT_EQ(0, close(ruleset_fd));
1738 
1739         /* Mount, remount, move_mount, umount, and pivot_root checks. */
1740         set_cap(_metadata, CAP_SYS_ADMIN);
1741         ASSERT_EQ(0, mount_opt(&mnt_tmp, dir_s1d2));
1742         ASSERT_EQ(0, mount(NULL, dir_s1d2, NULL, MS_PRIVATE | MS_REC, NULL));
1743         ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD,
1744                              dir_s2d2, 0));
1745         ASSERT_EQ(0, umount(dir_s2d2));
1746         ASSERT_EQ(0, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3));
1747         ASSERT_EQ(0, chdir("/"));
1748         clear_cap(_metadata, CAP_SYS_ADMIN);
1749 }
1750 
1751 TEST_F_FORK(layout1, topology_changes_with_net_and_fs)
1752 {
1753         const struct landlock_ruleset_attr ruleset_net_fs = {
1754                 .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP |
1755                                       LANDLOCK_ACCESS_NET_CONNECT_TCP,
1756                 .handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
1757         };
1758         int ruleset_fd;
1759 
1760         /* Add network and filesystem restrictions. */
1761         ruleset_fd = landlock_create_ruleset(&ruleset_net_fs,
1762                                              sizeof(ruleset_net_fs), 0);
1763         ASSERT_LE(0, ruleset_fd);
1764         enforce_ruleset(_metadata, ruleset_fd);
1765         ASSERT_EQ(0, close(ruleset_fd));
1766 
1767         /* Mount, remount, move_mount, umount, and pivot_root checks. */
1768         set_cap(_metadata, CAP_SYS_ADMIN);
1769         ASSERT_EQ(-1, mount_opt(&mnt_tmp, dir_s1d2));
1770         ASSERT_EQ(EPERM, errno);
1771         ASSERT_EQ(-1, mount(NULL, dir_s3d2, NULL, MS_PRIVATE | MS_REC, NULL));
1772         ASSERT_EQ(EPERM, errno);
1773         ASSERT_EQ(-1, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
1774                               dir_s2d2, 0));
1775         ASSERT_EQ(EPERM, errno);
1776         ASSERT_EQ(-1, umount(dir_s3d2));
1777         ASSERT_EQ(EPERM, errno);
1778         ASSERT_EQ(-1, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3));
1779         ASSERT_EQ(EPERM, errno);
1780         clear_cap(_metadata, CAP_SYS_ADMIN);
1781 }
1782 
1783 TEST_F_FORK(layout1, release_inodes)
1784 {
1785         const struct rule rules[] = {
1786                 {
1787                         .path = dir_s1d1,
1788                         .access = ACCESS_RO,
1789                 },
1790                 {
1791                         .path = dir_s3d2,
1792                         .access = ACCESS_RO,
1793                 },
1794                 {
1795                         .path = dir_s3d3,
1796                         .access = ACCESS_RO,
1797                 },
1798                 {},
1799         };
1800         const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
1801 
1802         ASSERT_LE(0, ruleset_fd);
1803         /* Unmount a file hierarchy while it is being used by a ruleset. */
1804         set_cap(_metadata, CAP_SYS_ADMIN);
1805         ASSERT_EQ(0, umount(dir_s3d2));
1806         clear_cap(_metadata, CAP_SYS_ADMIN);
1807 
1808         enforce_ruleset(_metadata, ruleset_fd);
1809         ASSERT_EQ(0, close(ruleset_fd));
1810 
1811         ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
1812         ASSERT_EQ(EACCES, test_open(dir_s3d2, O_RDONLY));
1813         /* This dir_s3d3 would not be allowed and does not exist anyway. */
1814         ASSERT_EQ(ENOENT, test_open(dir_s3d3, O_RDONLY));
1815 }
1816 
1817 enum relative_access {
1818         REL_OPEN,
1819         REL_CHDIR,
1820         REL_CHROOT_ONLY,
1821         REL_CHROOT_CHDIR,
1822 };
1823 
1824 static void test_relative_path(struct __test_metadata *const _metadata,
1825                                const enum relative_access rel)
1826 {
1827         /*
1828          * Common layer to check that chroot doesn't ignore it (i.e. a chroot
1829          * is not a disconnected root directory).
1830          */
1831         const struct rule layer1_base[] = {
1832                 {
1833                         .path = TMP_DIR,
1834                         .access = ACCESS_RO,
1835                 },
1836                 {},
1837         };
1838         const struct rule layer2_subs[] = {
1839                 {
1840                         .path = dir_s1d2,
1841                         .access = ACCESS_RO,
1842                 },
1843                 {
1844                         .path = dir_s2d2,
1845                         .access = ACCESS_RO,
1846                 },
1847                 {},
1848         };
1849         int dirfd, ruleset_fd;
1850 
1851         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_base);
1852         ASSERT_LE(0, ruleset_fd);
1853         enforce_ruleset(_metadata, ruleset_fd);
1854         ASSERT_EQ(0, close(ruleset_fd));
1855 
1856         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_subs);
1857 
1858         ASSERT_LE(0, ruleset_fd);
1859         switch (rel) {
1860         case REL_OPEN:
1861         case REL_CHDIR:
1862                 break;
1863         case REL_CHROOT_ONLY:
1864                 ASSERT_EQ(0, chdir(dir_s2d2));
1865                 break;
1866         case REL_CHROOT_CHDIR:
1867                 ASSERT_EQ(0, chdir(dir_s1d2));
1868                 break;
1869         default:
1870                 ASSERT_TRUE(false);
1871                 return;
1872         }
1873 
1874         set_cap(_metadata, CAP_SYS_CHROOT);
1875         enforce_ruleset(_metadata, ruleset_fd);
1876 
1877         switch (rel) {
1878         case REL_OPEN:
1879                 dirfd = open(dir_s1d2, O_DIRECTORY);
1880                 ASSERT_LE(0, dirfd);
1881                 break;
1882         case REL_CHDIR:
1883                 ASSERT_EQ(0, chdir(dir_s1d2));
1884                 dirfd = AT_FDCWD;
1885                 break;
1886         case REL_CHROOT_ONLY:
1887                 /* Do chroot into dir_s1d2 (relative to dir_s2d2). */
1888                 ASSERT_EQ(0, chroot("../../s1d1/s1d2"))
1889                 {
1890                         TH_LOG("Failed to chroot: %s", strerror(errno));
1891                 }
1892                 dirfd = AT_FDCWD;
1893                 break;
1894         case REL_CHROOT_CHDIR:
1895                 /* Do chroot into dir_s1d2. */
1896                 ASSERT_EQ(0, chroot("."))
1897                 {
1898                         TH_LOG("Failed to chroot: %s", strerror(errno));
1899                 }
1900                 dirfd = AT_FDCWD;
1901                 break;
1902         }
1903 
1904         ASSERT_EQ((rel == REL_CHROOT_CHDIR) ? 0 : EACCES,
1905                   test_open_rel(dirfd, "..", O_RDONLY));
1906         ASSERT_EQ(0, test_open_rel(dirfd, ".", O_RDONLY));
1907 
1908         if (rel == REL_CHROOT_ONLY) {
1909                 /* The current directory is dir_s2d2. */
1910                 ASSERT_EQ(0, test_open_rel(dirfd, "./s2d3", O_RDONLY));
1911         } else {
1912                 /* The current directory is dir_s1d2. */
1913                 ASSERT_EQ(0, test_open_rel(dirfd, "./s1d3", O_RDONLY));
1914         }
1915 
1916         if (rel == REL_CHROOT_ONLY || rel == REL_CHROOT_CHDIR) {
1917                 /* Checks the root dir_s1d2. */
1918                 ASSERT_EQ(0, test_open_rel(dirfd, "/..", O_RDONLY));
1919                 ASSERT_EQ(0, test_open_rel(dirfd, "/", O_RDONLY));
1920                 ASSERT_EQ(0, test_open_rel(dirfd, "/f1", O_RDONLY));
1921                 ASSERT_EQ(0, test_open_rel(dirfd, "/s1d3", O_RDONLY));
1922         }
1923 
1924         if (rel != REL_CHROOT_CHDIR) {
1925                 ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s1d1", O_RDONLY));
1926                 ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2", O_RDONLY));
1927                 ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2/s1d3",
1928                                            O_RDONLY));
1929 
1930                 ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s2d1", O_RDONLY));
1931                 ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2", O_RDONLY));
1932                 ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2/s2d3",
1933                                            O_RDONLY));
1934         }
1935 
1936         if (rel == REL_OPEN)
1937                 ASSERT_EQ(0, close(dirfd));
1938         ASSERT_EQ(0, close(ruleset_fd));
1939 }
1940 
1941 TEST_F_FORK(layout1, relative_open)
1942 {
1943         test_relative_path(_metadata, REL_OPEN);
1944 }
1945 
1946 TEST_F_FORK(layout1, relative_chdir)
1947 {
1948         test_relative_path(_metadata, REL_CHDIR);
1949 }
1950 
1951 TEST_F_FORK(layout1, relative_chroot_only)
1952 {
1953         test_relative_path(_metadata, REL_CHROOT_ONLY);
1954 }
1955 
1956 TEST_F_FORK(layout1, relative_chroot_chdir)
1957 {
1958         test_relative_path(_metadata, REL_CHROOT_CHDIR);
1959 }
1960 
1961 static void copy_binary(struct __test_metadata *const _metadata,
1962                         const char *const dst_path)
1963 {
1964         int dst_fd, src_fd;
1965         struct stat statbuf;
1966 
1967         dst_fd = open(dst_path, O_WRONLY | O_TRUNC | O_CLOEXEC);
1968         ASSERT_LE(0, dst_fd)
1969         {
1970                 TH_LOG("Failed to open \"%s\": %s", dst_path, strerror(errno));
1971         }
1972         src_fd = open(BINARY_PATH, O_RDONLY | O_CLOEXEC);
1973         ASSERT_LE(0, src_fd)
1974         {
1975                 TH_LOG("Failed to open \"" BINARY_PATH "\": %s",
1976                        strerror(errno));
1977         }
1978         ASSERT_EQ(0, fstat(src_fd, &statbuf));
1979         ASSERT_EQ(statbuf.st_size,
1980                   sendfile(dst_fd, src_fd, 0, statbuf.st_size));
1981         ASSERT_EQ(0, close(src_fd));
1982         ASSERT_EQ(0, close(dst_fd));
1983 }
1984 
1985 static void test_execute(struct __test_metadata *const _metadata, const int err,
1986                          const char *const path)
1987 {
1988         int status;
1989         char *const argv[] = { (char *)path, NULL };
1990         const pid_t child = fork();
1991 
1992         ASSERT_LE(0, child);
1993         if (child == 0) {
1994                 ASSERT_EQ(err ? -1 : 0, execve(path, argv, NULL))
1995                 {
1996                         TH_LOG("Failed to execute \"%s\": %s", path,
1997                                strerror(errno));
1998                 };
1999                 ASSERT_EQ(err, errno);
2000                 _exit(__test_passed(_metadata) ? 2 : 1);
2001                 return;
2002         }
2003         ASSERT_EQ(child, waitpid(child, &status, 0));
2004         ASSERT_EQ(1, WIFEXITED(status));
2005         ASSERT_EQ(err ? 2 : 0, WEXITSTATUS(status))
2006         {
2007                 TH_LOG("Unexpected return code for \"%s\": %s", path,
2008                        strerror(errno));
2009         };
2010 }
2011 
2012 TEST_F_FORK(layout1, execute)
2013 {
2014         const struct rule rules[] = {
2015                 {
2016                         .path = dir_s1d2,
2017                         .access = LANDLOCK_ACCESS_FS_EXECUTE,
2018                 },
2019                 {},
2020         };
2021         const int ruleset_fd =
2022                 create_ruleset(_metadata, rules[0].access, rules);
2023 
2024         ASSERT_LE(0, ruleset_fd);
2025         copy_binary(_metadata, file1_s1d1);
2026         copy_binary(_metadata, file1_s1d2);
2027         copy_binary(_metadata, file1_s1d3);
2028 
2029         enforce_ruleset(_metadata, ruleset_fd);
2030         ASSERT_EQ(0, close(ruleset_fd));
2031 
2032         ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
2033         ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
2034         test_execute(_metadata, EACCES, file1_s1d1);
2035 
2036         ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
2037         ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
2038         test_execute(_metadata, 0, file1_s1d2);
2039 
2040         ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
2041         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
2042         test_execute(_metadata, 0, file1_s1d3);
2043 }
2044 
2045 TEST_F_FORK(layout1, link)
2046 {
2047         const struct rule layer1[] = {
2048                 {
2049                         .path = dir_s1d2,
2050                         .access = LANDLOCK_ACCESS_FS_MAKE_REG,
2051                 },
2052                 {},
2053         };
2054         const struct rule layer2[] = {
2055                 {
2056                         .path = dir_s1d3,
2057                         .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
2058                 },
2059                 {},
2060         };
2061         int ruleset_fd = create_ruleset(_metadata, layer1[0].access, layer1);
2062 
2063         ASSERT_LE(0, ruleset_fd);
2064 
2065         ASSERT_EQ(0, unlink(file1_s1d1));
2066         ASSERT_EQ(0, unlink(file1_s1d2));
2067         ASSERT_EQ(0, unlink(file1_s1d3));
2068 
2069         enforce_ruleset(_metadata, ruleset_fd);
2070         ASSERT_EQ(0, close(ruleset_fd));
2071 
2072         ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
2073         ASSERT_EQ(EACCES, errno);
2074 
2075         /* Denies linking because of reparenting. */
2076         ASSERT_EQ(-1, link(file1_s2d1, file1_s1d2));
2077         ASSERT_EQ(EXDEV, errno);
2078         ASSERT_EQ(-1, link(file2_s1d2, file1_s1d3));
2079         ASSERT_EQ(EXDEV, errno);
2080         ASSERT_EQ(-1, link(file2_s1d3, file1_s1d2));
2081         ASSERT_EQ(EXDEV, errno);
2082 
2083         ASSERT_EQ(0, link(file2_s1d2, file1_s1d2));
2084         ASSERT_EQ(0, link(file2_s1d3, file1_s1d3));
2085 
2086         /* Prepares for next unlinks. */
2087         ASSERT_EQ(0, unlink(file2_s1d2));
2088         ASSERT_EQ(0, unlink(file2_s1d3));
2089 
2090         ruleset_fd = create_ruleset(_metadata, layer2[0].access, layer2);
2091         ASSERT_LE(0, ruleset_fd);
2092         enforce_ruleset(_metadata, ruleset_fd);
2093         ASSERT_EQ(0, close(ruleset_fd));
2094 
2095         /* Checks that linkind doesn't require the ability to delete a file. */
2096         ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
2097         ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
2098 }
2099 
2100 static int test_rename(const char *const oldpath, const char *const newpath)
2101 {
2102         if (rename(oldpath, newpath))
2103                 return errno;
2104         return 0;
2105 }
2106 
2107 static int test_exchange(const char *const oldpath, const char *const newpath)
2108 {
2109         if (renameat2(AT_FDCWD, oldpath, AT_FDCWD, newpath, RENAME_EXCHANGE))
2110                 return errno;
2111         return 0;
2112 }
2113 
2114 TEST_F_FORK(layout1, rename_file)
2115 {
2116         const struct rule rules[] = {
2117                 {
2118                         .path = dir_s1d3,
2119                         .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
2120                 },
2121                 {
2122                         .path = dir_s2d2,
2123                         .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
2124                 },
2125                 {},
2126         };
2127         const int ruleset_fd =
2128                 create_ruleset(_metadata, rules[0].access, rules);
2129 
2130         ASSERT_LE(0, ruleset_fd);
2131 
2132         ASSERT_EQ(0, unlink(file1_s1d2));
2133 
2134         enforce_ruleset(_metadata, ruleset_fd);
2135         ASSERT_EQ(0, close(ruleset_fd));
2136 
2137         /*
2138          * Tries to replace a file, from a directory that allows file removal,
2139          * but to a different directory (which also allows file removal).
2140          */
2141         ASSERT_EQ(-1, rename(file1_s2d3, file1_s1d3));
2142         ASSERT_EQ(EXDEV, errno);
2143         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d3,
2144                                 RENAME_EXCHANGE));
2145         ASSERT_EQ(EXDEV, errno);
2146         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, dir_s1d3,
2147                                 RENAME_EXCHANGE));
2148         ASSERT_EQ(EXDEV, errno);
2149 
2150         /*
2151          * Tries to replace a file, from a directory that denies file removal,
2152          * to a different directory (which allows file removal).
2153          */
2154         ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
2155         ASSERT_EQ(EACCES, errno);
2156         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file1_s1d3,
2157                                 RENAME_EXCHANGE));
2158         ASSERT_EQ(EACCES, errno);
2159         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s1d3,
2160                                 RENAME_EXCHANGE));
2161         ASSERT_EQ(EXDEV, errno);
2162 
2163         /* Exchanges files and directories that partially allow removal. */
2164         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s2d1,
2165                                 RENAME_EXCHANGE));
2166         ASSERT_EQ(EACCES, errno);
2167         /* Checks that file1_s2d1 cannot be removed (instead of ENOTDIR). */
2168         ASSERT_EQ(-1, rename(dir_s2d2, file1_s2d1));
2169         ASSERT_EQ(EACCES, errno);
2170         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, dir_s2d2,
2171                                 RENAME_EXCHANGE));
2172         ASSERT_EQ(EACCES, errno);
2173         /* Checks that file1_s1d1 cannot be removed (instead of EISDIR). */
2174         ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
2175         ASSERT_EQ(EACCES, errno);
2176 
2177         /* Renames files with different parents. */
2178         ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d2));
2179         ASSERT_EQ(EXDEV, errno);
2180         ASSERT_EQ(0, unlink(file1_s1d3));
2181         ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
2182         ASSERT_EQ(EACCES, errno);
2183 
2184         /* Exchanges and renames files with same parent. */
2185         ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s2d3,
2186                                RENAME_EXCHANGE));
2187         ASSERT_EQ(0, rename(file2_s2d3, file1_s2d3));
2188 
2189         /* Exchanges files and directories with same parent, twice. */
2190         ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
2191                                RENAME_EXCHANGE));
2192         ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
2193                                RENAME_EXCHANGE));
2194 }
2195 
2196 TEST_F_FORK(layout1, rename_dir)
2197 {
2198         const struct rule rules[] = {
2199                 {
2200                         .path = dir_s1d2,
2201                         .access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
2202                 },
2203                 {
2204                         .path = dir_s2d1,
2205                         .access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
2206                 },
2207                 {},
2208         };
2209         const int ruleset_fd =
2210                 create_ruleset(_metadata, rules[0].access, rules);
2211 
2212         ASSERT_LE(0, ruleset_fd);
2213 
2214         /* Empties dir_s1d3 to allow renaming. */
2215         ASSERT_EQ(0, unlink(file1_s1d3));
2216         ASSERT_EQ(0, unlink(file2_s1d3));
2217 
2218         enforce_ruleset(_metadata, ruleset_fd);
2219         ASSERT_EQ(0, close(ruleset_fd));
2220 
2221         /* Exchanges and renames directory to a different parent. */
2222         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
2223                                 RENAME_EXCHANGE));
2224         ASSERT_EQ(EXDEV, errno);
2225         ASSERT_EQ(-1, rename(dir_s2d3, dir_s1d3));
2226         ASSERT_EQ(EXDEV, errno);
2227         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
2228                                 RENAME_EXCHANGE));
2229         ASSERT_EQ(EXDEV, errno);
2230 
2231         /*
2232          * Exchanges directory to the same parent, which doesn't allow
2233          * directory removal.
2234          */
2235         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d1, AT_FDCWD, dir_s2d1,
2236                                 RENAME_EXCHANGE));
2237         ASSERT_EQ(EACCES, errno);
2238         /* Checks that dir_s1d2 cannot be removed (instead of ENOTDIR). */
2239         ASSERT_EQ(-1, rename(dir_s1d2, file1_s1d1));
2240         ASSERT_EQ(EACCES, errno);
2241         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s1d2,
2242                                 RENAME_EXCHANGE));
2243         ASSERT_EQ(EACCES, errno);
2244         /* Checks that dir_s1d2 cannot be removed (instead of EISDIR). */
2245         ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
2246         ASSERT_EQ(EACCES, errno);
2247 
2248         /*
2249          * Exchanges and renames directory to the same parent, which allows
2250          * directory removal.
2251          */
2252         ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, file1_s1d2,
2253                                RENAME_EXCHANGE));
2254         ASSERT_EQ(0, unlink(dir_s1d3));
2255         ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
2256         ASSERT_EQ(0, rename(file1_s1d2, dir_s1d3));
2257         ASSERT_EQ(0, rmdir(dir_s1d3));
2258 }
2259 
2260 TEST_F_FORK(layout1, reparent_refer)
2261 {
2262         const struct rule layer1[] = {
2263                 {
2264                         .path = dir_s1d2,
2265                         .access = LANDLOCK_ACCESS_FS_REFER,
2266                 },
2267                 {
2268                         .path = dir_s2d2,
2269                         .access = LANDLOCK_ACCESS_FS_REFER,
2270                 },
2271                 {},
2272         };
2273         int ruleset_fd =
2274                 create_ruleset(_metadata, LANDLOCK_ACCESS_FS_REFER, layer1);
2275 
2276         ASSERT_LE(0, ruleset_fd);
2277         enforce_ruleset(_metadata, ruleset_fd);
2278         ASSERT_EQ(0, close(ruleset_fd));
2279 
2280         ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d1));
2281         ASSERT_EQ(EXDEV, errno);
2282         ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d2));
2283         ASSERT_EQ(EXDEV, errno);
2284         ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d3));
2285         ASSERT_EQ(EXDEV, errno);
2286 
2287         ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d1));
2288         ASSERT_EQ(EXDEV, errno);
2289         ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d2));
2290         ASSERT_EQ(EXDEV, errno);
2291         /*
2292          * Moving should only be allowed when the source and the destination
2293          * parent directory have REFER.
2294          */
2295         ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d3));
2296         ASSERT_EQ(ENOTEMPTY, errno);
2297         ASSERT_EQ(0, unlink(file1_s2d3));
2298         ASSERT_EQ(0, unlink(file2_s2d3));
2299         ASSERT_EQ(0, rename(dir_s1d3, dir_s2d3));
2300 }
2301 
2302 /* Checks renames beneath dir_s1d1. */
2303 static void refer_denied_by_default(struct __test_metadata *const _metadata,
2304                                     const struct rule layer1[],
2305                                     const int layer1_err,
2306                                     const struct rule layer2[])
2307 {
2308         int ruleset_fd;
2309 
2310         ASSERT_EQ(0, unlink(file1_s1d2));
2311 
2312         ruleset_fd = create_ruleset(_metadata, layer1[0].access, layer1);
2313         ASSERT_LE(0, ruleset_fd);
2314         enforce_ruleset(_metadata, ruleset_fd);
2315         ASSERT_EQ(0, close(ruleset_fd));
2316 
2317         /*
2318          * If the first layer handles LANDLOCK_ACCESS_FS_REFER (according to
2319          * layer1_err), then it allows some different-parent renames and links.
2320          */
2321         ASSERT_EQ(layer1_err, test_rename(file1_s1d1, file1_s1d2));
2322         if (layer1_err == 0)
2323                 ASSERT_EQ(layer1_err, test_rename(file1_s1d2, file1_s1d1));
2324         ASSERT_EQ(layer1_err, test_exchange(file2_s1d1, file2_s1d2));
2325         ASSERT_EQ(layer1_err, test_exchange(file2_s1d2, file2_s1d1));
2326 
2327         ruleset_fd = create_ruleset(_metadata, layer2[0].access, layer2);
2328         ASSERT_LE(0, ruleset_fd);
2329         enforce_ruleset(_metadata, ruleset_fd);
2330         ASSERT_EQ(0, close(ruleset_fd));
2331 
2332         /*
2333          * Now, either the first or the second layer does not handle
2334          * LANDLOCK_ACCESS_FS_REFER, which means that any different-parent
2335          * renames and links are denied, thus making the layer handling
2336          * LANDLOCK_ACCESS_FS_REFER null and void.
2337          */
2338         ASSERT_EQ(EXDEV, test_rename(file1_s1d1, file1_s1d2));
2339         ASSERT_EQ(EXDEV, test_exchange(file2_s1d1, file2_s1d2));
2340         ASSERT_EQ(EXDEV, test_exchange(file2_s1d2, file2_s1d1));
2341 }
2342 
2343 const struct rule layer_dir_s1d1_refer[] = {
2344         {
2345                 .path = dir_s1d1,
2346                 .access = LANDLOCK_ACCESS_FS_REFER,
2347         },
2348         {},
2349 };
2350 
2351 const struct rule layer_dir_s1d1_execute[] = {
2352         {
2353                 /* Matches a parent directory. */
2354                 .path = dir_s1d1,
2355                 .access = LANDLOCK_ACCESS_FS_EXECUTE,
2356         },
2357         {},
2358 };
2359 
2360 const struct rule layer_dir_s2d1_execute[] = {
2361         {
2362                 /* Does not match a parent directory. */
2363                 .path = dir_s2d1,
2364                 .access = LANDLOCK_ACCESS_FS_EXECUTE,
2365         },
2366         {},
2367 };
2368 
2369 /*
2370  * Tests precedence over renames: denied by default for different parent
2371  * directories, *with* a rule matching a parent directory, but not directly
2372  * denying access (with MAKE_REG nor REMOVE).
2373  */
2374 TEST_F_FORK(layout1, refer_denied_by_default1)
2375 {
2376         refer_denied_by_default(_metadata, layer_dir_s1d1_refer, 0,
2377                                 layer_dir_s1d1_execute);
2378 }
2379 
2380 /*
2381  * Same test but this time turning around the ABI version order: the first
2382  * layer does not handle LANDLOCK_ACCESS_FS_REFER.
2383  */
2384 TEST_F_FORK(layout1, refer_denied_by_default2)
2385 {
2386         refer_denied_by_default(_metadata, layer_dir_s1d1_execute, EXDEV,
2387                                 layer_dir_s1d1_refer);
2388 }
2389 
2390 /*
2391  * Tests precedence over renames: denied by default for different parent
2392  * directories, *without* a rule matching a parent directory, but not directly
2393  * denying access (with MAKE_REG nor REMOVE).
2394  */
2395 TEST_F_FORK(layout1, refer_denied_by_default3)
2396 {
2397         refer_denied_by_default(_metadata, layer_dir_s1d1_refer, 0,
2398                                 layer_dir_s2d1_execute);
2399 }
2400 
2401 /*
2402  * Same test but this time turning around the ABI version order: the first
2403  * layer does not handle LANDLOCK_ACCESS_FS_REFER.
2404  */
2405 TEST_F_FORK(layout1, refer_denied_by_default4)
2406 {
2407         refer_denied_by_default(_metadata, layer_dir_s2d1_execute, EXDEV,
2408                                 layer_dir_s1d1_refer);
2409 }
2410 
2411 /*
2412  * Tests walking through a denied root mount.
2413  */
2414 TEST_F_FORK(layout1, refer_mount_root_deny)
2415 {
2416         const struct landlock_ruleset_attr ruleset_attr = {
2417                 .handled_access_fs = LANDLOCK_ACCESS_FS_MAKE_DIR,
2418         };
2419         int root_fd, ruleset_fd;
2420 
2421         /* Creates a mount object from a non-mount point. */
2422         set_cap(_metadata, CAP_SYS_ADMIN);
2423         root_fd =
2424                 open_tree(AT_FDCWD, dir_s1d1,
2425                           AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
2426         clear_cap(_metadata, CAP_SYS_ADMIN);
2427         ASSERT_LE(0, root_fd);
2428 
2429         ruleset_fd =
2430                 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
2431         ASSERT_LE(0, ruleset_fd);
2432 
2433         ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
2434         ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
2435         EXPECT_EQ(0, close(ruleset_fd));
2436 
2437         /* Link denied by Landlock: EACCES. */
2438         EXPECT_EQ(-1, linkat(root_fd, ".", root_fd, "does_not_exist", 0));
2439         EXPECT_EQ(EACCES, errno);
2440 
2441         /* renameat2() always returns EBUSY. */
2442         EXPECT_EQ(-1, renameat2(root_fd, ".", root_fd, "does_not_exist", 0));
2443         EXPECT_EQ(EBUSY, errno);
2444 
2445         EXPECT_EQ(0, close(root_fd));
2446 }
2447 
2448 TEST_F_FORK(layout1, reparent_link)
2449 {
2450         const struct rule layer1[] = {
2451                 {
2452                         .path = dir_s1d2,
2453                         .access = LANDLOCK_ACCESS_FS_MAKE_REG,
2454                 },
2455                 {
2456                         .path = dir_s1d3,
2457                         .access = LANDLOCK_ACCESS_FS_REFER,
2458                 },
2459                 {
2460                         .path = dir_s2d2,
2461                         .access = LANDLOCK_ACCESS_FS_REFER,
2462                 },
2463                 {
2464                         .path = dir_s2d3,
2465                         .access = LANDLOCK_ACCESS_FS_MAKE_REG,
2466                 },
2467                 {},
2468         };
2469         const int ruleset_fd = create_ruleset(
2470                 _metadata,
2471                 LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER, layer1);
2472 
2473         ASSERT_LE(0, ruleset_fd);
2474         enforce_ruleset(_metadata, ruleset_fd);
2475         ASSERT_EQ(0, close(ruleset_fd));
2476 
2477         ASSERT_EQ(0, unlink(file1_s1d1));
2478         ASSERT_EQ(0, unlink(file1_s1d2));
2479         ASSERT_EQ(0, unlink(file1_s1d3));
2480 
2481         /* Denies linking because of missing MAKE_REG. */
2482         ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
2483         ASSERT_EQ(EACCES, errno);
2484         /* Denies linking because of missing source and destination REFER. */
2485         ASSERT_EQ(-1, link(file1_s2d1, file1_s1d2));
2486         ASSERT_EQ(EXDEV, errno);
2487         /* Denies linking because of missing source REFER. */
2488         ASSERT_EQ(-1, link(file1_s2d1, file1_s1d3));
2489         ASSERT_EQ(EXDEV, errno);
2490 
2491         /* Denies linking because of missing MAKE_REG. */
2492         ASSERT_EQ(-1, link(file1_s2d2, file1_s1d1));
2493         ASSERT_EQ(EACCES, errno);
2494         /* Denies linking because of missing destination REFER. */
2495         ASSERT_EQ(-1, link(file1_s2d2, file1_s1d2));
2496         ASSERT_EQ(EXDEV, errno);
2497 
2498         /* Allows linking because of REFER and MAKE_REG. */
2499         ASSERT_EQ(0, link(file1_s2d2, file1_s1d3));
2500         ASSERT_EQ(0, unlink(file1_s2d2));
2501         /* Reverse linking denied because of missing MAKE_REG. */
2502         ASSERT_EQ(-1, link(file1_s1d3, file1_s2d2));
2503         ASSERT_EQ(EACCES, errno);
2504         ASSERT_EQ(0, unlink(file1_s2d3));
2505         /* Checks reverse linking. */
2506         ASSERT_EQ(0, link(file1_s1d3, file1_s2d3));
2507         ASSERT_EQ(0, unlink(file1_s1d3));
2508 
2509         /*
2510          * This is OK for a file link, but it should not be allowed for a
2511          * directory rename (because of the superset of access rights.
2512          */
2513         ASSERT_EQ(0, link(file1_s2d3, file1_s1d3));
2514         ASSERT_EQ(0, unlink(file1_s1d3));
2515 
2516         ASSERT_EQ(-1, link(file2_s1d2, file1_s1d3));
2517         ASSERT_EQ(EXDEV, errno);
2518         ASSERT_EQ(-1, link(file2_s1d3, file1_s1d2));
2519         ASSERT_EQ(EXDEV, errno);
2520 
2521         ASSERT_EQ(0, link(file2_s1d2, file1_s1d2));
2522         ASSERT_EQ(0, link(file2_s1d3, file1_s1d3));
2523 }
2524 
2525 TEST_F_FORK(layout1, reparent_rename)
2526 {
2527         /* Same rules as for reparent_link. */
2528         const struct rule layer1[] = {
2529                 {
2530                         .path = dir_s1d2,
2531                         .access = LANDLOCK_ACCESS_FS_MAKE_REG,
2532                 },
2533                 {
2534                         .path = dir_s1d3,
2535                         .access = LANDLOCK_ACCESS_FS_REFER,
2536                 },
2537                 {
2538                         .path = dir_s2d2,
2539                         .access = LANDLOCK_ACCESS_FS_REFER,
2540                 },
2541                 {
2542                         .path = dir_s2d3,
2543                         .access = LANDLOCK_ACCESS_FS_MAKE_REG,
2544                 },
2545                 {},
2546         };
2547         const int ruleset_fd = create_ruleset(
2548                 _metadata,
2549                 LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER, layer1);
2550 
2551         ASSERT_LE(0, ruleset_fd);
2552         enforce_ruleset(_metadata, ruleset_fd);
2553         ASSERT_EQ(0, close(ruleset_fd));
2554 
2555         ASSERT_EQ(0, unlink(file1_s1d2));
2556         ASSERT_EQ(0, unlink(file1_s1d3));
2557 
2558         /* Denies renaming because of missing MAKE_REG. */
2559         ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file1_s1d1,
2560                                 RENAME_EXCHANGE));
2561         ASSERT_EQ(EACCES, errno);
2562         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file2_s1d1,
2563                                 RENAME_EXCHANGE));
2564         ASSERT_EQ(EACCES, errno);
2565         ASSERT_EQ(0, unlink(file1_s1d1));
2566         ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
2567         ASSERT_EQ(EACCES, errno);
2568         /* Even denies same file exchange. */
2569         ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file2_s1d1,
2570                                 RENAME_EXCHANGE));
2571         ASSERT_EQ(EACCES, errno);
2572 
2573         /* Denies renaming because of missing source and destination REFER. */
2574         ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d2));
2575         ASSERT_EQ(EXDEV, errno);
2576         /*
2577          * Denies renaming because of missing MAKE_REG, source and destination
2578          * REFER.
2579          */
2580         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file2_s1d1,
2581                                 RENAME_EXCHANGE));
2582         ASSERT_EQ(EACCES, errno);
2583         ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file1_s2d1,
2584                                 RENAME_EXCHANGE));
2585         ASSERT_EQ(EACCES, errno);
2586 
2587         /* Denies renaming because of missing source REFER. */
2588         ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
2589         ASSERT_EQ(EXDEV, errno);
2590         /* Denies renaming because of missing MAKE_REG. */
2591         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file2_s1d3,
2592                                 RENAME_EXCHANGE));
2593         ASSERT_EQ(EACCES, errno);
2594 
2595         /* Denies renaming because of missing MAKE_REG. */
2596         ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d1));
2597         ASSERT_EQ(EACCES, errno);
2598         /* Denies renaming because of missing destination REFER*/
2599         ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d2));
2600         ASSERT_EQ(EXDEV, errno);
2601 
2602         /* Denies exchange because of one missing MAKE_REG. */
2603         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, file2_s1d3,
2604                                 RENAME_EXCHANGE));
2605         ASSERT_EQ(EACCES, errno);
2606         /* Allows renaming because of REFER and MAKE_REG. */
2607         ASSERT_EQ(0, rename(file1_s2d2, file1_s1d3));
2608 
2609         /* Reverse renaming denied because of missing MAKE_REG. */
2610         ASSERT_EQ(-1, rename(file1_s1d3, file1_s2d2));
2611         ASSERT_EQ(EACCES, errno);
2612         ASSERT_EQ(0, unlink(file1_s2d3));
2613         ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2614 
2615         /* Tests reverse renaming. */
2616         ASSERT_EQ(0, rename(file1_s2d3, file1_s1d3));
2617         ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s1d3,
2618                                RENAME_EXCHANGE));
2619         ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2620 
2621         /*
2622          * This is OK for a file rename, but it should not be allowed for a
2623          * directory rename (because of the superset of access rights).
2624          */
2625         ASSERT_EQ(0, rename(file1_s2d3, file1_s1d3));
2626         ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2627 
2628         /*
2629          * Tests superset restrictions applied to directories.  Not only the
2630          * dir_s2d3's parent (dir_s2d2) should be taken into account but also
2631          * access rights tied to dir_s2d3. dir_s2d2 is missing one access right
2632          * compared to dir_s1d3/file1_s1d3 (MAKE_REG) but it is provided
2633          * directly by the moved dir_s2d3.
2634          */
2635         ASSERT_EQ(0, rename(dir_s2d3, file1_s1d3));
2636         ASSERT_EQ(0, rename(file1_s1d3, dir_s2d3));
2637         /*
2638          * The first rename is allowed but not the exchange because dir_s1d3's
2639          * parent (dir_s1d2) doesn't have REFER.
2640          */
2641         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, dir_s1d3,
2642                                 RENAME_EXCHANGE));
2643         ASSERT_EQ(EXDEV, errno);
2644         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, file1_s2d3,
2645                                 RENAME_EXCHANGE));
2646         ASSERT_EQ(EXDEV, errno);
2647         ASSERT_EQ(-1, rename(file1_s2d3, dir_s1d3));
2648         ASSERT_EQ(EXDEV, errno);
2649 
2650         ASSERT_EQ(-1, rename(file2_s1d2, file1_s1d3));
2651         ASSERT_EQ(EXDEV, errno);
2652         ASSERT_EQ(-1, rename(file2_s1d3, file1_s1d2));
2653         ASSERT_EQ(EXDEV, errno);
2654 
2655         /* Renaming in the same directory is always allowed. */
2656         ASSERT_EQ(0, rename(file2_s1d2, file1_s1d2));
2657         ASSERT_EQ(0, rename(file2_s1d3, file1_s1d3));
2658 
2659         ASSERT_EQ(0, unlink(file1_s1d2));
2660         /* Denies because of missing source MAKE_REG and destination REFER. */
2661         ASSERT_EQ(-1, rename(dir_s2d3, file1_s1d2));
2662         ASSERT_EQ(EXDEV, errno);
2663 
2664         ASSERT_EQ(0, unlink(file1_s1d3));
2665         /* Denies because of missing source MAKE_REG and REFER. */
2666         ASSERT_EQ(-1, rename(dir_s2d2, file1_s1d3));
2667         ASSERT_EQ(EXDEV, errno);
2668 }
2669 
2670 static void
2671 reparent_exdev_layers_enforce1(struct __test_metadata *const _metadata)
2672 {
2673         const struct rule layer1[] = {
2674                 {
2675                         .path = dir_s1d2,
2676                         .access = LANDLOCK_ACCESS_FS_REFER,
2677                 },
2678                 {
2679                         /* Interesting for the layer2 tests. */
2680                         .path = dir_s1d3,
2681                         .access = LANDLOCK_ACCESS_FS_MAKE_REG,
2682                 },
2683                 {
2684                         .path = dir_s2d2,
2685                         .access = LANDLOCK_ACCESS_FS_REFER,
2686                 },
2687                 {
2688                         .path = dir_s2d3,
2689                         .access = LANDLOCK_ACCESS_FS_MAKE_REG,
2690                 },
2691                 {},
2692         };
2693         const int ruleset_fd = create_ruleset(
2694                 _metadata,
2695                 LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER, layer1);
2696 
2697         ASSERT_LE(0, ruleset_fd);
2698         enforce_ruleset(_metadata, ruleset_fd);
2699         ASSERT_EQ(0, close(ruleset_fd));
2700 }
2701 
2702 static void
2703 reparent_exdev_layers_enforce2(struct __test_metadata *const _metadata)
2704 {
2705         const struct rule layer2[] = {
2706                 {
2707                         .path = dir_s2d3,
2708                         .access = LANDLOCK_ACCESS_FS_MAKE_DIR,
2709                 },
2710                 {},
2711         };
2712         /*
2713          * Same checks as before but with a second layer and a new MAKE_DIR
2714          * rule (and no explicit handling of REFER).
2715          */
2716         const int ruleset_fd =
2717                 create_ruleset(_metadata, LANDLOCK_ACCESS_FS_MAKE_DIR, layer2);
2718 
2719         ASSERT_LE(0, ruleset_fd);
2720         enforce_ruleset(_metadata, ruleset_fd);
2721         ASSERT_EQ(0, close(ruleset_fd));
2722 }
2723 
2724 TEST_F_FORK(layout1, reparent_exdev_layers_rename1)
2725 {
2726         ASSERT_EQ(0, unlink(file1_s2d2));
2727         ASSERT_EQ(0, unlink(file1_s2d3));
2728 
2729         reparent_exdev_layers_enforce1(_metadata);
2730 
2731         /*
2732          * Moving the dir_s1d3 directory below dir_s2d2 is allowed by Landlock
2733          * because it doesn't inherit new access rights.
2734          */
2735         ASSERT_EQ(0, rename(dir_s1d3, file1_s2d2));
2736         ASSERT_EQ(0, rename(file1_s2d2, dir_s1d3));
2737 
2738         /*
2739          * Moving the dir_s1d3 directory below dir_s2d3 is allowed, even if it
2740          * gets a new inherited access rights (MAKE_REG), because MAKE_REG is
2741          * already allowed for dir_s1d3.
2742          */
2743         ASSERT_EQ(0, rename(dir_s1d3, file1_s2d3));
2744         ASSERT_EQ(0, rename(file1_s2d3, dir_s1d3));
2745 
2746         /*
2747          * However, moving the file1_s1d3 file below dir_s2d3 is allowed
2748          * because it cannot inherit MAKE_REG right (which is dedicated to
2749          * directories).
2750          */
2751         ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
2752 
2753         reparent_exdev_layers_enforce2(_metadata);
2754 
2755         /*
2756          * Moving the dir_s1d3 directory below dir_s2d2 is now denied because
2757          * MAKE_DIR is not tied to dir_s2d2.
2758          */
2759         ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d2));
2760         ASSERT_EQ(EACCES, errno);
2761 
2762         /*
2763          * Moving the dir_s1d3 directory below dir_s2d3 is forbidden because it
2764          * would grants MAKE_REG and MAKE_DIR rights to it.
2765          */
2766         ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d3));
2767         ASSERT_EQ(EXDEV, errno);
2768 
2769         /*
2770          * Moving the file2_s1d3 file below dir_s2d3 is denied because the
2771          * second layer does not handle REFER, which is always denied by
2772          * default.
2773          */
2774         ASSERT_EQ(-1, rename(file2_s1d3, file1_s2d3));
2775         ASSERT_EQ(EXDEV, errno);
2776 }
2777 
2778 TEST_F_FORK(layout1, reparent_exdev_layers_rename2)
2779 {
2780         reparent_exdev_layers_enforce1(_metadata);
2781 
2782         /* Checks EACCES predominance over EXDEV. */
2783         ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d2));
2784         ASSERT_EQ(EACCES, errno);
2785         ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d2));
2786         ASSERT_EQ(EACCES, errno);
2787         ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d3));
2788         ASSERT_EQ(EXDEV, errno);
2789         /* Modify layout! */
2790         ASSERT_EQ(0, rename(file1_s1d2, file1_s2d3));
2791 
2792         /* Without REFER source. */
2793         ASSERT_EQ(-1, rename(dir_s1d1, file1_s2d2));
2794         ASSERT_EQ(EXDEV, errno);
2795         ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d2));
2796         ASSERT_EQ(EXDEV, errno);
2797 
2798         reparent_exdev_layers_enforce2(_metadata);
2799 
2800         /* Checks EACCES predominance over EXDEV. */
2801         ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d2));
2802         ASSERT_EQ(EACCES, errno);
2803         /* Checks with actual file2_s1d2. */
2804         ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d2));
2805         ASSERT_EQ(EACCES, errno);
2806         ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d3));
2807         ASSERT_EQ(EXDEV, errno);
2808         /*
2809          * Modifying the layout is now denied because the second layer does not
2810          * handle REFER, which is always denied by default.
2811          */
2812         ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d3));
2813         ASSERT_EQ(EXDEV, errno);
2814 
2815         /* Without REFER source, EACCES wins over EXDEV. */
2816         ASSERT_EQ(-1, rename(dir_s1d1, file1_s2d2));
2817         ASSERT_EQ(EACCES, errno);
2818         ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d2));
2819         ASSERT_EQ(EACCES, errno);
2820 }
2821 
2822 TEST_F_FORK(layout1, reparent_exdev_layers_exchange1)
2823 {
2824         const char *const dir_file1_s1d2 = file1_s1d2, *const dir_file2_s2d3 =
2825                                                                file2_s2d3;
2826 
2827         ASSERT_EQ(0, unlink(file1_s1d2));
2828         ASSERT_EQ(0, mkdir(file1_s1d2, 0700));
2829         ASSERT_EQ(0, unlink(file2_s2d3));
2830         ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
2831 
2832         reparent_exdev_layers_enforce1(_metadata);
2833 
2834         /* Error predominance with file exchange: returns EXDEV and EACCES. */
2835         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file1_s2d3,
2836                                 RENAME_EXCHANGE));
2837         ASSERT_EQ(EACCES, errno);
2838         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d1,
2839                                 RENAME_EXCHANGE));
2840         ASSERT_EQ(EACCES, errno);
2841 
2842         /*
2843          * Checks with directories which creation could be allowed, but denied
2844          * because of access rights that would be inherited.
2845          */
2846         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD,
2847                                 dir_file2_s2d3, RENAME_EXCHANGE));
2848         ASSERT_EQ(EXDEV, errno);
2849         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD,
2850                                 dir_file1_s1d2, RENAME_EXCHANGE));
2851         ASSERT_EQ(EXDEV, errno);
2852 
2853         /* Checks with same access rights. */
2854         ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, dir_s2d3,
2855                                RENAME_EXCHANGE));
2856         ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
2857                                RENAME_EXCHANGE));
2858 
2859         /* Checks with different (child-only) access rights. */
2860         ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_file1_s1d2,
2861                                RENAME_EXCHANGE));
2862         ASSERT_EQ(0, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD, dir_s2d3,
2863                                RENAME_EXCHANGE));
2864 
2865         /*
2866          * Checks that exchange between file and directory are consistent.
2867          *
2868          * Moving a file (file1_s2d2) to a directory which only grants more
2869          * directory-related access rights is allowed, and at the same time
2870          * moving a directory (dir_file2_s2d3) to another directory which
2871          * grants less access rights is allowed too.
2872          *
2873          * See layout1.reparent_exdev_layers_exchange3 for inverted arguments.
2874          */
2875         ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
2876                                RENAME_EXCHANGE));
2877         /*
2878          * However, moving back the directory is denied because it would get
2879          * more access rights than the current state and because file creation
2880          * is forbidden (in dir_s2d2).
2881          */
2882         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
2883                                 RENAME_EXCHANGE));
2884         ASSERT_EQ(EACCES, errno);
2885         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
2886                                 RENAME_EXCHANGE));
2887         ASSERT_EQ(EACCES, errno);
2888 
2889         reparent_exdev_layers_enforce2(_metadata);
2890 
2891         /* Error predominance with file exchange: returns EXDEV and EACCES. */
2892         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file1_s2d3,
2893                                 RENAME_EXCHANGE));
2894         ASSERT_EQ(EACCES, errno);
2895         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d1,
2896                                 RENAME_EXCHANGE));
2897         ASSERT_EQ(EACCES, errno);
2898 
2899         /* Checks with directories which creation is now denied. */
2900         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD,
2901                                 dir_file2_s2d3, RENAME_EXCHANGE));
2902         ASSERT_EQ(EACCES, errno);
2903         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD,
2904                                 dir_file1_s1d2, RENAME_EXCHANGE));
2905         ASSERT_EQ(EACCES, errno);
2906 
2907         /* Checks with different (child-only) access rights. */
2908         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, dir_s2d3,
2909                                 RENAME_EXCHANGE));
2910         /* Denied because of MAKE_DIR. */
2911         ASSERT_EQ(EACCES, errno);
2912         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
2913                                 RENAME_EXCHANGE));
2914         ASSERT_EQ(EACCES, errno);
2915 
2916         /* Checks with different (child-only) access rights. */
2917         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_file1_s1d2,
2918                                 RENAME_EXCHANGE));
2919         /* Denied because of MAKE_DIR. */
2920         ASSERT_EQ(EACCES, errno);
2921         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD, dir_s2d3,
2922                                 RENAME_EXCHANGE));
2923         ASSERT_EQ(EACCES, errno);
2924 
2925         /* See layout1.reparent_exdev_layers_exchange2 for complement. */
2926 }
2927 
2928 TEST_F_FORK(layout1, reparent_exdev_layers_exchange2)
2929 {
2930         const char *const dir_file2_s2d3 = file2_s2d3;
2931 
2932         ASSERT_EQ(0, unlink(file2_s2d3));
2933         ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
2934 
2935         reparent_exdev_layers_enforce1(_metadata);
2936         reparent_exdev_layers_enforce2(_metadata);
2937 
2938         /* Checks that exchange between file and directory are consistent. */
2939         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
2940                                 RENAME_EXCHANGE));
2941         ASSERT_EQ(EACCES, errno);
2942         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
2943                                 RENAME_EXCHANGE));
2944         ASSERT_EQ(EACCES, errno);
2945 }
2946 
2947 TEST_F_FORK(layout1, reparent_exdev_layers_exchange3)
2948 {
2949         const char *const dir_file2_s2d3 = file2_s2d3;
2950 
2951         ASSERT_EQ(0, unlink(file2_s2d3));
2952         ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
2953 
2954         reparent_exdev_layers_enforce1(_metadata);
2955 
2956         /*
2957          * Checks that exchange between file and directory are consistent,
2958          * including with inverted arguments (see
2959          * layout1.reparent_exdev_layers_exchange1).
2960          */
2961         ASSERT_EQ(0, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
2962                                RENAME_EXCHANGE));
2963         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
2964                                 RENAME_EXCHANGE));
2965         ASSERT_EQ(EACCES, errno);
2966         ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
2967                                 RENAME_EXCHANGE));
2968         ASSERT_EQ(EACCES, errno);
2969 }
2970 
2971 TEST_F_FORK(layout1, reparent_remove)
2972 {
2973         const struct rule layer1[] = {
2974                 {
2975                         .path = dir_s1d1,
2976                         .access = LANDLOCK_ACCESS_FS_REFER |
2977                                   LANDLOCK_ACCESS_FS_REMOVE_DIR,
2978                 },
2979                 {
2980                         .path = dir_s1d2,
2981                         .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
2982                 },
2983                 {
2984                         .path = dir_s2d1,
2985                         .access = LANDLOCK_ACCESS_FS_REFER |
2986                                   LANDLOCK_ACCESS_FS_REMOVE_FILE,
2987                 },
2988                 {},
2989         };
2990         const int ruleset_fd = create_ruleset(
2991                 _metadata,
2992                 LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_REMOVE_DIR |
2993                         LANDLOCK_ACCESS_FS_REMOVE_FILE,
2994                 layer1);
2995 
2996         ASSERT_LE(0, ruleset_fd);
2997         enforce_ruleset(_metadata, ruleset_fd);
2998         ASSERT_EQ(0, close(ruleset_fd));
2999 
3000         /* Access denied because of wrong/swapped remove file/dir. */
3001         ASSERT_EQ(-1, rename(file1_s1d1, dir_s2d2));
3002         ASSERT_EQ(EACCES, errno);
3003         ASSERT_EQ(-1, rename(dir_s2d2, file1_s1d1));
3004         ASSERT_EQ(EACCES, errno);
3005         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s2d2,
3006                                 RENAME_EXCHANGE));
3007         ASSERT_EQ(EACCES, errno);
3008         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s2d3,
3009                                 RENAME_EXCHANGE));
3010         ASSERT_EQ(EACCES, errno);
3011 
3012         /* Access allowed thanks to the matching rights. */
3013         ASSERT_EQ(-1, rename(file1_s2d1, dir_s1d2));
3014         ASSERT_EQ(EISDIR, errno);
3015         ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d1));
3016         ASSERT_EQ(ENOTDIR, errno);
3017         ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d1));
3018         ASSERT_EQ(ENOTDIR, errno);
3019         ASSERT_EQ(0, unlink(file1_s2d1));
3020         ASSERT_EQ(0, unlink(file1_s1d3));
3021         ASSERT_EQ(0, unlink(file2_s1d3));
3022         ASSERT_EQ(0, rename(dir_s1d3, file1_s2d1));
3023 
3024         /* Effectively removes a file and a directory by exchanging them. */
3025         ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
3026         ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
3027                                RENAME_EXCHANGE));
3028         ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
3029                                 RENAME_EXCHANGE));
3030         ASSERT_EQ(EACCES, errno);
3031 }
3032 
3033 TEST_F_FORK(layout1, reparent_dom_superset)
3034 {
3035         const struct rule layer1[] = {
3036                 {
3037                         .path = dir_s1d2,
3038                         .access = LANDLOCK_ACCESS_FS_REFER,
3039                 },
3040                 {
3041                         .path = file1_s1d2,
3042                         .access = LANDLOCK_ACCESS_FS_EXECUTE,
3043                 },
3044                 {
3045                         .path = dir_s1d3,
3046                         .access = LANDLOCK_ACCESS_FS_MAKE_SOCK |
3047                                   LANDLOCK_ACCESS_FS_EXECUTE,
3048                 },
3049                 {
3050                         .path = dir_s2d2,
3051                         .access = LANDLOCK_ACCESS_FS_REFER |
3052                                   LANDLOCK_ACCESS_FS_EXECUTE |
3053                                   LANDLOCK_ACCESS_FS_MAKE_SOCK,
3054                 },
3055                 {
3056                         .path = dir_s2d3,
3057                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
3058                                   LANDLOCK_ACCESS_FS_MAKE_FIFO,
3059                 },
3060                 {},
3061         };
3062         int ruleset_fd = create_ruleset(_metadata,
3063                                         LANDLOCK_ACCESS_FS_REFER |
3064                                                 LANDLOCK_ACCESS_FS_EXECUTE |
3065                                                 LANDLOCK_ACCESS_FS_MAKE_SOCK |
3066                                                 LANDLOCK_ACCESS_FS_READ_FILE |
3067                                                 LANDLOCK_ACCESS_FS_MAKE_FIFO,
3068                                         layer1);
3069 
3070         ASSERT_LE(0, ruleset_fd);
3071         enforce_ruleset(_metadata, ruleset_fd);
3072         ASSERT_EQ(0, close(ruleset_fd));
3073 
3074         ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d1));
3075         ASSERT_EQ(EXDEV, errno);
3076         /*
3077          * Moving file1_s1d2 beneath dir_s2d3 would grant it the READ_FILE
3078          * access right.
3079          */
3080         ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d3));
3081         ASSERT_EQ(EXDEV, errno);
3082         /*
3083          * Moving file1_s1d2 should be allowed even if dir_s2d2 grants a
3084          * superset of access rights compared to dir_s1d2, because file1_s1d2
3085          * already has these access rights anyway.
3086          */
3087         ASSERT_EQ(0, rename(file1_s1d2, file1_s2d2));
3088         ASSERT_EQ(0, rename(file1_s2d2, file1_s1d2));
3089 
3090         ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d1));
3091         ASSERT_EQ(EXDEV, errno);
3092         /*
3093          * Moving dir_s1d3 beneath dir_s2d3 would grant it the MAKE_FIFO access
3094          * right.
3095          */
3096         ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d3));
3097         ASSERT_EQ(EXDEV, errno);
3098         /*
3099          * Moving dir_s1d3 should be allowed even if dir_s2d2 grants a superset
3100          * of access rights compared to dir_s1d2, because dir_s1d3 already has
3101          * these access rights anyway.
3102          */
3103         ASSERT_EQ(0, rename(dir_s1d3, file1_s2d2));
3104         ASSERT_EQ(0, rename(file1_s2d2, dir_s1d3));
3105 
3106         /*
3107          * Moving file1_s2d3 beneath dir_s1d2 is allowed, but moving it back
3108          * will be denied because the new inherited access rights from dir_s1d2
3109          * will be less than the destination (original) dir_s2d3.  This is a
3110          * sinkhole scenario where we cannot move back files or directories.
3111          */
3112         ASSERT_EQ(0, rename(file1_s2d3, file2_s1d2));
3113         ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d3));
3114         ASSERT_EQ(EXDEV, errno);
3115         ASSERT_EQ(0, unlink(file2_s1d2));
3116         ASSERT_EQ(0, unlink(file2_s2d3));
3117         /*
3118          * Checks similar directory one-way move: dir_s2d3 loses EXECUTE and
3119          * MAKE_SOCK which were inherited from dir_s1d3.
3120          */
3121         ASSERT_EQ(0, rename(dir_s2d3, file2_s1d2));
3122         ASSERT_EQ(-1, rename(file2_s1d2, dir_s2d3));
3123         ASSERT_EQ(EXDEV, errno);
3124 }
3125 
3126 TEST_F_FORK(layout1, remove_dir)
3127 {
3128         const struct rule rules[] = {
3129                 {
3130                         .path = dir_s1d2,
3131                         .access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
3132                 },
3133                 {},
3134         };
3135         const int ruleset_fd =
3136                 create_ruleset(_metadata, rules[0].access, rules);
3137 
3138         ASSERT_LE(0, ruleset_fd);
3139 
3140         ASSERT_EQ(0, unlink(file1_s1d1));
3141         ASSERT_EQ(0, unlink(file1_s1d2));
3142         ASSERT_EQ(0, unlink(file1_s1d3));
3143         ASSERT_EQ(0, unlink(file2_s1d3));
3144 
3145         enforce_ruleset(_metadata, ruleset_fd);
3146         ASSERT_EQ(0, close(ruleset_fd));
3147 
3148         ASSERT_EQ(0, rmdir(dir_s1d3));
3149         ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
3150         ASSERT_EQ(0, unlinkat(AT_FDCWD, dir_s1d3, AT_REMOVEDIR));
3151 
3152         /* dir_s1d2 itself cannot be removed. */
3153         ASSERT_EQ(-1, rmdir(dir_s1d2));
3154         ASSERT_EQ(EACCES, errno);
3155         ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d2, AT_REMOVEDIR));
3156         ASSERT_EQ(EACCES, errno);
3157         ASSERT_EQ(-1, rmdir(dir_s1d1));
3158         ASSERT_EQ(EACCES, errno);
3159         ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d1, AT_REMOVEDIR));
3160         ASSERT_EQ(EACCES, errno);
3161 }
3162 
3163 TEST_F_FORK(layout1, remove_file)
3164 {
3165         const struct rule rules[] = {
3166                 {
3167                         .path = dir_s1d2,
3168                         .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
3169                 },
3170                 {},
3171         };
3172         const int ruleset_fd =
3173                 create_ruleset(_metadata, rules[0].access, rules);
3174 
3175         ASSERT_LE(0, ruleset_fd);
3176         enforce_ruleset(_metadata, ruleset_fd);
3177         ASSERT_EQ(0, close(ruleset_fd));
3178 
3179         ASSERT_EQ(-1, unlink(file1_s1d1));
3180         ASSERT_EQ(EACCES, errno);
3181         ASSERT_EQ(-1, unlinkat(AT_FDCWD, file1_s1d1, 0));
3182         ASSERT_EQ(EACCES, errno);
3183         ASSERT_EQ(0, unlink(file1_s1d2));
3184         ASSERT_EQ(0, unlinkat(AT_FDCWD, file1_s1d3, 0));
3185 }
3186 
3187 static void test_make_file(struct __test_metadata *const _metadata,
3188                            const __u64 access, const mode_t mode,
3189                            const dev_t dev)
3190 {
3191         const struct rule rules[] = {
3192                 {
3193                         .path = dir_s1d2,
3194                         .access = access,
3195                 },
3196                 {},
3197         };
3198         const int ruleset_fd = create_ruleset(_metadata, access, rules);
3199 
3200         ASSERT_LE(0, ruleset_fd);
3201 
3202         ASSERT_EQ(0, unlink(file1_s1d1));
3203         ASSERT_EQ(0, unlink(file2_s1d1));
3204         ASSERT_EQ(0, mknod(file2_s1d1, mode | 0400, dev))
3205         {
3206                 TH_LOG("Failed to make file \"%s\": %s", file2_s1d1,
3207                        strerror(errno));
3208         };
3209 
3210         ASSERT_EQ(0, unlink(file1_s1d2));
3211         ASSERT_EQ(0, unlink(file2_s1d2));
3212 
3213         ASSERT_EQ(0, unlink(file1_s1d3));
3214         ASSERT_EQ(0, unlink(file2_s1d3));
3215 
3216         enforce_ruleset(_metadata, ruleset_fd);
3217         ASSERT_EQ(0, close(ruleset_fd));
3218 
3219         ASSERT_EQ(-1, mknod(file1_s1d1, mode | 0400, dev));
3220         ASSERT_EQ(EACCES, errno);
3221         ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
3222         ASSERT_EQ(EACCES, errno);
3223         ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
3224         ASSERT_EQ(EACCES, errno);
3225 
3226         ASSERT_EQ(0, mknod(file1_s1d2, mode | 0400, dev))
3227         {
3228                 TH_LOG("Failed to make file \"%s\": %s", file1_s1d2,
3229                        strerror(errno));
3230         };
3231         ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
3232         ASSERT_EQ(0, unlink(file2_s1d2));
3233         ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
3234 
3235         ASSERT_EQ(0, mknod(file1_s1d3, mode | 0400, dev));
3236         ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
3237         ASSERT_EQ(0, unlink(file2_s1d3));
3238         ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
3239 }
3240 
3241 TEST_F_FORK(layout1, make_char)
3242 {
3243         /* Creates a /dev/null device. */
3244         set_cap(_metadata, CAP_MKNOD);
3245         test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_CHAR, S_IFCHR,
3246                        makedev(1, 3));
3247 }
3248 
3249 TEST_F_FORK(layout1, make_block)
3250 {
3251         /* Creates a /dev/loop0 device. */
3252         set_cap(_metadata, CAP_MKNOD);
3253         test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_BLOCK, S_IFBLK,
3254                        makedev(7, 0));
3255 }
3256 
3257 TEST_F_FORK(layout1, make_reg_1)
3258 {
3259         test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, S_IFREG, 0);
3260 }
3261 
3262 TEST_F_FORK(layout1, make_reg_2)
3263 {
3264         test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, 0, 0);
3265 }
3266 
3267 TEST_F_FORK(layout1, make_sock)
3268 {
3269         test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_SOCK, S_IFSOCK, 0);
3270 }
3271 
3272 TEST_F_FORK(layout1, make_fifo)
3273 {
3274         test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_FIFO, S_IFIFO, 0);
3275 }
3276 
3277 TEST_F_FORK(layout1, make_sym)
3278 {
3279         const struct rule rules[] = {
3280                 {
3281                         .path = dir_s1d2,
3282                         .access = LANDLOCK_ACCESS_FS_MAKE_SYM,
3283                 },
3284                 {},
3285         };
3286         const int ruleset_fd =
3287                 create_ruleset(_metadata, rules[0].access, rules);
3288 
3289         ASSERT_LE(0, ruleset_fd);
3290 
3291         ASSERT_EQ(0, unlink(file1_s1d1));
3292         ASSERT_EQ(0, unlink(file2_s1d1));
3293         ASSERT_EQ(0, symlink("none", file2_s1d1));
3294 
3295         ASSERT_EQ(0, unlink(file1_s1d2));
3296         ASSERT_EQ(0, unlink(file2_s1d2));
3297 
3298         ASSERT_EQ(0, unlink(file1_s1d3));
3299         ASSERT_EQ(0, unlink(file2_s1d3));
3300 
3301         enforce_ruleset(_metadata, ruleset_fd);
3302         ASSERT_EQ(0, close(ruleset_fd));
3303 
3304         ASSERT_EQ(-1, symlink("none", file1_s1d1));
3305         ASSERT_EQ(EACCES, errno);
3306         ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
3307         ASSERT_EQ(EACCES, errno);
3308         ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
3309         ASSERT_EQ(EACCES, errno);
3310 
3311         ASSERT_EQ(0, symlink("none", file1_s1d2));
3312         ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
3313         ASSERT_EQ(0, unlink(file2_s1d2));
3314         ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
3315 
3316         ASSERT_EQ(0, symlink("none", file1_s1d3));
3317         ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
3318         ASSERT_EQ(0, unlink(file2_s1d3));
3319         ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
3320 }
3321 
3322 TEST_F_FORK(layout1, make_dir)
3323 {
3324         const struct rule rules[] = {
3325                 {
3326                         .path = dir_s1d2,
3327                         .access = LANDLOCK_ACCESS_FS_MAKE_DIR,
3328                 },
3329                 {},
3330         };
3331         const int ruleset_fd =
3332                 create_ruleset(_metadata, rules[0].access, rules);
3333 
3334         ASSERT_LE(0, ruleset_fd);
3335 
3336         ASSERT_EQ(0, unlink(file1_s1d1));
3337         ASSERT_EQ(0, unlink(file1_s1d2));
3338         ASSERT_EQ(0, unlink(file1_s1d3));
3339 
3340         enforce_ruleset(_metadata, ruleset_fd);
3341         ASSERT_EQ(0, close(ruleset_fd));
3342 
3343         /* Uses file_* as directory names. */
3344         ASSERT_EQ(-1, mkdir(file1_s1d1, 0700));
3345         ASSERT_EQ(EACCES, errno);
3346         ASSERT_EQ(0, mkdir(file1_s1d2, 0700));
3347         ASSERT_EQ(0, mkdir(file1_s1d3, 0700));
3348 }
3349 
3350 static int open_proc_fd(struct __test_metadata *const _metadata, const int fd,
3351                         const int open_flags)
3352 {
3353         static const char path_template[] = "/proc/self/fd/%d";
3354         char procfd_path[sizeof(path_template) + 10];
3355         const int procfd_path_size =
3356                 snprintf(procfd_path, sizeof(procfd_path), path_template, fd);
3357 
3358         ASSERT_LT(procfd_path_size, sizeof(procfd_path));
3359         return open(procfd_path, open_flags);
3360 }
3361 
3362 TEST_F_FORK(layout1, proc_unlinked_file)
3363 {
3364         const struct rule rules[] = {
3365                 {
3366                         .path = file1_s1d2,
3367                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
3368                 },
3369                 {},
3370         };
3371         int reg_fd, proc_fd;
3372         const int ruleset_fd = create_ruleset(
3373                 _metadata,
3374                 LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE,
3375                 rules);
3376 
3377         ASSERT_LE(0, ruleset_fd);
3378         enforce_ruleset(_metadata, ruleset_fd);
3379         ASSERT_EQ(0, close(ruleset_fd));
3380 
3381         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
3382         ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
3383         reg_fd = open(file1_s1d2, O_RDONLY | O_CLOEXEC);
3384         ASSERT_LE(0, reg_fd);
3385         ASSERT_EQ(0, unlink(file1_s1d2));
3386 
3387         proc_fd = open_proc_fd(_metadata, reg_fd, O_RDONLY | O_CLOEXEC);
3388         ASSERT_LE(0, proc_fd);
3389         ASSERT_EQ(0, close(proc_fd));
3390 
3391         proc_fd = open_proc_fd(_metadata, reg_fd, O_RDWR | O_CLOEXEC);
3392         ASSERT_EQ(-1, proc_fd)
3393         {
3394                 TH_LOG("Successfully opened /proc/self/fd/%d: %s", reg_fd,
3395                        strerror(errno));
3396         }
3397         ASSERT_EQ(EACCES, errno);
3398 
3399         ASSERT_EQ(0, close(reg_fd));
3400 }
3401 
3402 TEST_F_FORK(layout1, proc_pipe)
3403 {
3404         int proc_fd;
3405         int pipe_fds[2];
3406         char buf = '\0';
3407         const struct rule rules[] = {
3408                 {
3409                         .path = dir_s1d2,
3410                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
3411                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
3412                 },
3413                 {},
3414         };
3415         /* Limits read and write access to files tied to the filesystem. */
3416         const int ruleset_fd =
3417                 create_ruleset(_metadata, rules[0].access, rules);
3418 
3419         ASSERT_LE(0, ruleset_fd);
3420         enforce_ruleset(_metadata, ruleset_fd);
3421         ASSERT_EQ(0, close(ruleset_fd));
3422 
3423         /* Checks enforcement for normal files. */
3424         ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
3425         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
3426 
3427         /* Checks access to pipes through FD. */
3428         ASSERT_EQ(0, pipe2(pipe_fds, O_CLOEXEC));
3429         ASSERT_EQ(1, write(pipe_fds[1], ".", 1))
3430         {
3431                 TH_LOG("Failed to write in pipe: %s", strerror(errno));
3432         }
3433         ASSERT_EQ(1, read(pipe_fds[0], &buf, 1));
3434         ASSERT_EQ('.', buf);
3435 
3436         /* Checks write access to pipe through /proc/self/fd . */
3437         proc_fd = open_proc_fd(_metadata, pipe_fds[1], O_WRONLY | O_CLOEXEC);
3438         ASSERT_LE(0, proc_fd);
3439         ASSERT_EQ(1, write(proc_fd, ".", 1))
3440         {
3441                 TH_LOG("Failed to write through /proc/self/fd/%d: %s",
3442                        pipe_fds[1], strerror(errno));
3443         }
3444         ASSERT_EQ(0, close(proc_fd));
3445 
3446         /* Checks read access to pipe through /proc/self/fd . */
3447         proc_fd = open_proc_fd(_metadata, pipe_fds[0], O_RDONLY | O_CLOEXEC);
3448         ASSERT_LE(0, proc_fd);
3449         buf = '\0';
3450         ASSERT_EQ(1, read(proc_fd, &buf, 1))
3451         {
3452                 TH_LOG("Failed to read through /proc/self/fd/%d: %s",
3453                        pipe_fds[1], strerror(errno));
3454         }
3455         ASSERT_EQ(0, close(proc_fd));
3456 
3457         ASSERT_EQ(0, close(pipe_fds[0]));
3458         ASSERT_EQ(0, close(pipe_fds[1]));
3459 }
3460 
3461 /* Invokes truncate(2) and returns its errno or 0. */
3462 static int test_truncate(const char *const path)
3463 {
3464         if (truncate(path, 10) < 0)
3465                 return errno;
3466         return 0;
3467 }
3468 
3469 /*
3470  * Invokes creat(2) and returns its errno or 0.
3471  * Closes the opened file descriptor on success.
3472  */
3473 static int test_creat(const char *const path)
3474 {
3475         int fd = creat(path, 0600);
3476 
3477         if (fd < 0)
3478                 return errno;
3479 
3480         /*
3481          * Mixing error codes from close(2) and creat(2) should not lead to any
3482          * (access type) confusion for this test.
3483          */
3484         if (close(fd) < 0)
3485                 return errno;
3486         return 0;
3487 }
3488 
3489 /*
3490  * Exercises file truncation when it's not restricted,
3491  * as it was the case before LANDLOCK_ACCESS_FS_TRUNCATE existed.
3492  */
3493 TEST_F_FORK(layout1, truncate_unhandled)
3494 {
3495         const char *const file_r = file1_s1d1;
3496         const char *const file_w = file2_s1d1;
3497         const char *const file_none = file1_s1d2;
3498         const struct rule rules[] = {
3499                 {
3500                         .path = file_r,
3501                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
3502                 },
3503                 {
3504                         .path = file_w,
3505                         .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3506                 },
3507                 /* Implicitly: No rights for file_none. */
3508                 {},
3509         };
3510 
3511         const __u64 handled = LANDLOCK_ACCESS_FS_READ_FILE |
3512                               LANDLOCK_ACCESS_FS_WRITE_FILE;
3513         int ruleset_fd;
3514 
3515         /* Enables Landlock. */
3516         ruleset_fd = create_ruleset(_metadata, handled, rules);
3517 
3518         ASSERT_LE(0, ruleset_fd);
3519         enforce_ruleset(_metadata, ruleset_fd);
3520         ASSERT_EQ(0, close(ruleset_fd));
3521 
3522         /*
3523          * Checks read right: truncate and open with O_TRUNC work, unless the
3524          * file is attempted to be opened for writing.
3525          */
3526         EXPECT_EQ(0, test_truncate(file_r));
3527         EXPECT_EQ(0, test_open(file_r, O_RDONLY | O_TRUNC));
3528         EXPECT_EQ(EACCES, test_open(file_r, O_WRONLY | O_TRUNC));
3529         EXPECT_EQ(EACCES, test_creat(file_r));
3530 
3531         /*
3532          * Checks write right: truncate and open with O_TRUNC work, unless the
3533          * file is attempted to be opened for reading.
3534          */
3535         EXPECT_EQ(0, test_truncate(file_w));
3536         EXPECT_EQ(EACCES, test_open(file_w, O_RDONLY | O_TRUNC));
3537         EXPECT_EQ(0, test_open(file_w, O_WRONLY | O_TRUNC));
3538         EXPECT_EQ(0, test_creat(file_w));
3539 
3540         /*
3541          * Checks "no rights" case: truncate works but all open attempts fail,
3542          * including creat.
3543          */
3544         EXPECT_EQ(0, test_truncate(file_none));
3545         EXPECT_EQ(EACCES, test_open(file_none, O_RDONLY | O_TRUNC));
3546         EXPECT_EQ(EACCES, test_open(file_none, O_WRONLY | O_TRUNC));
3547         EXPECT_EQ(EACCES, test_creat(file_none));
3548 }
3549 
3550 TEST_F_FORK(layout1, truncate)
3551 {
3552         const char *const file_rwt = file1_s1d1;
3553         const char *const file_rw = file2_s1d1;
3554         const char *const file_rt = file1_s1d2;
3555         const char *const file_t = file2_s1d2;
3556         const char *const file_none = file1_s1d3;
3557         const char *const dir_t = dir_s2d1;
3558         const char *const file_in_dir_t = file1_s2d1;
3559         const char *const dir_w = dir_s3d1;
3560         const char *const file_in_dir_w = file1_s3d1;
3561         const struct rule rules[] = {
3562                 {
3563                         .path = file_rwt,
3564                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
3565                                   LANDLOCK_ACCESS_FS_WRITE_FILE |
3566                                   LANDLOCK_ACCESS_FS_TRUNCATE,
3567                 },
3568                 {
3569                         .path = file_rw,
3570                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
3571                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
3572                 },
3573                 {
3574                         .path = file_rt,
3575                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
3576                                   LANDLOCK_ACCESS_FS_TRUNCATE,
3577                 },
3578                 {
3579                         .path = file_t,
3580                         .access = LANDLOCK_ACCESS_FS_TRUNCATE,
3581                 },
3582                 /* Implicitly: No access rights for file_none. */
3583                 {
3584                         .path = dir_t,
3585                         .access = LANDLOCK_ACCESS_FS_TRUNCATE,
3586                 },
3587                 {
3588                         .path = dir_w,
3589                         .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3590                 },
3591                 {},
3592         };
3593         const __u64 handled = LANDLOCK_ACCESS_FS_READ_FILE |
3594                               LANDLOCK_ACCESS_FS_WRITE_FILE |
3595                               LANDLOCK_ACCESS_FS_TRUNCATE;
3596         int ruleset_fd;
3597 
3598         /* Enables Landlock. */
3599         ruleset_fd = create_ruleset(_metadata, handled, rules);
3600 
3601         ASSERT_LE(0, ruleset_fd);
3602         enforce_ruleset(_metadata, ruleset_fd);
3603         ASSERT_EQ(0, close(ruleset_fd));
3604 
3605         /* Checks read, write and truncate rights: truncation works. */
3606         EXPECT_EQ(0, test_truncate(file_rwt));
3607         EXPECT_EQ(0, test_open(file_rwt, O_RDONLY | O_TRUNC));
3608         EXPECT_EQ(0, test_open(file_rwt, O_WRONLY | O_TRUNC));
3609 
3610         /* Checks read and write rights: no truncate variant works. */
3611         EXPECT_EQ(EACCES, test_truncate(file_rw));
3612         EXPECT_EQ(EACCES, test_open(file_rw, O_RDONLY | O_TRUNC));
3613         EXPECT_EQ(EACCES, test_open(file_rw, O_WRONLY | O_TRUNC));
3614 
3615         /*
3616          * Checks read and truncate rights: truncation works.
3617          *
3618          * Note: Files can get truncated using open() even with O_RDONLY.
3619          */
3620         EXPECT_EQ(0, test_truncate(file_rt));
3621         EXPECT_EQ(0, test_open(file_rt, O_RDONLY | O_TRUNC));
3622         EXPECT_EQ(EACCES, test_open(file_rt, O_WRONLY | O_TRUNC));
3623 
3624         /* Checks truncate right: truncate works, but can't open file. */
3625         EXPECT_EQ(0, test_truncate(file_t));
3626         EXPECT_EQ(EACCES, test_open(file_t, O_RDONLY | O_TRUNC));
3627         EXPECT_EQ(EACCES, test_open(file_t, O_WRONLY | O_TRUNC));
3628 
3629         /* Checks "no rights" case: No form of truncation works. */
3630         EXPECT_EQ(EACCES, test_truncate(file_none));
3631         EXPECT_EQ(EACCES, test_open(file_none, O_RDONLY | O_TRUNC));
3632         EXPECT_EQ(EACCES, test_open(file_none, O_WRONLY | O_TRUNC));
3633 
3634         /*
3635          * Checks truncate right on directory: truncate works on contained
3636          * files.
3637          */
3638         EXPECT_EQ(0, test_truncate(file_in_dir_t));
3639         EXPECT_EQ(EACCES, test_open(file_in_dir_t, O_RDONLY | O_TRUNC));
3640         EXPECT_EQ(EACCES, test_open(file_in_dir_t, O_WRONLY | O_TRUNC));
3641 
3642         /*
3643          * Checks creat in dir_w: This requires the truncate right when
3644          * overwriting an existing file, but does not require it when the file
3645          * is new.
3646          */
3647         EXPECT_EQ(EACCES, test_creat(file_in_dir_w));
3648 
3649         ASSERT_EQ(0, unlink(file_in_dir_w));
3650         EXPECT_EQ(0, test_creat(file_in_dir_w));
3651 }
3652 
3653 /* Invokes ftruncate(2) and returns its errno or 0. */
3654 static int test_ftruncate(int fd)
3655 {
3656         if (ftruncate(fd, 10) < 0)
3657                 return errno;
3658         return 0;
3659 }
3660 
3661 TEST_F_FORK(layout1, ftruncate)
3662 {
3663         /*
3664          * This test opens a new file descriptor at different stages of
3665          * Landlock restriction:
3666          *
3667          * without restriction:                    ftruncate works
3668          * something else but truncate restricted: ftruncate works
3669          * truncate restricted and permitted:      ftruncate works
3670          * truncate restricted and not permitted:  ftruncate fails
3671          *
3672          * Whether this works or not is expected to depend on the time when the
3673          * FD was opened, not to depend on the time when ftruncate() was
3674          * called.
3675          */
3676         const char *const path = file1_s1d1;
3677         const __u64 handled1 = LANDLOCK_ACCESS_FS_READ_FILE |
3678                                LANDLOCK_ACCESS_FS_WRITE_FILE;
3679         const struct rule layer1[] = {
3680                 {
3681                         .path = path,
3682                         .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3683                 },
3684                 {},
3685         };
3686         const __u64 handled2 = LANDLOCK_ACCESS_FS_TRUNCATE;
3687         const struct rule layer2[] = {
3688                 {
3689                         .path = path,
3690                         .access = LANDLOCK_ACCESS_FS_TRUNCATE,
3691                 },
3692                 {},
3693         };
3694         const __u64 handled3 = LANDLOCK_ACCESS_FS_TRUNCATE |
3695                                LANDLOCK_ACCESS_FS_WRITE_FILE;
3696         const struct rule layer3[] = {
3697                 {
3698                         .path = path,
3699                         .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
3700                 },
3701                 {},
3702         };
3703         int fd_layer0, fd_layer1, fd_layer2, fd_layer3, ruleset_fd;
3704 
3705         fd_layer0 = open(path, O_WRONLY);
3706         EXPECT_EQ(0, test_ftruncate(fd_layer0));
3707 
3708         ruleset_fd = create_ruleset(_metadata, handled1, layer1);
3709         ASSERT_LE(0, ruleset_fd);
3710         enforce_ruleset(_metadata, ruleset_fd);
3711         ASSERT_EQ(0, close(ruleset_fd));
3712 
3713         fd_layer1 = open(path, O_WRONLY);
3714         EXPECT_EQ(0, test_ftruncate(fd_layer0));
3715         EXPECT_EQ(0, test_ftruncate(fd_layer1));
3716 
3717         ruleset_fd = create_ruleset(_metadata, handled2, layer2);
3718         ASSERT_LE(0, ruleset_fd);
3719         enforce_ruleset(_metadata, ruleset_fd);
3720         ASSERT_EQ(0, close(ruleset_fd));
3721 
3722         fd_layer2 = open(path, O_WRONLY);
3723         EXPECT_EQ(0, test_ftruncate(fd_layer0));
3724         EXPECT_EQ(0, test_ftruncate(fd_layer1));
3725         EXPECT_EQ(0, test_ftruncate(fd_layer2));
3726 
3727         ruleset_fd = create_ruleset(_metadata, handled3, layer3);
3728         ASSERT_LE(0, ruleset_fd);
3729         enforce_ruleset(_metadata, ruleset_fd);
3730         ASSERT_EQ(0, close(ruleset_fd));
3731 
3732         fd_layer3 = open(path, O_WRONLY);
3733         EXPECT_EQ(0, test_ftruncate(fd_layer0));
3734         EXPECT_EQ(0, test_ftruncate(fd_layer1));
3735         EXPECT_EQ(0, test_ftruncate(fd_layer2));
3736         EXPECT_EQ(EACCES, test_ftruncate(fd_layer3));
3737 
3738         ASSERT_EQ(0, close(fd_layer0));
3739         ASSERT_EQ(0, close(fd_layer1));
3740         ASSERT_EQ(0, close(fd_layer2));
3741         ASSERT_EQ(0, close(fd_layer3));
3742 }
3743 
3744 /* clang-format off */
3745 FIXTURE(ftruncate) {};
3746 /* clang-format on */
3747 
3748 FIXTURE_SETUP(ftruncate)
3749 {
3750         prepare_layout(_metadata);
3751         create_file(_metadata, file1_s1d1);
3752 }
3753 
3754 FIXTURE_TEARDOWN_PARENT(ftruncate)
3755 {
3756         EXPECT_EQ(0, remove_path(file1_s1d1));
3757         cleanup_layout(_metadata);
3758 }
3759 
3760 FIXTURE_VARIANT(ftruncate)
3761 {
3762         const __u64 handled;
3763         const __u64 allowed;
3764         const int expected_open_result;
3765         const int expected_ftruncate_result;
3766 };
3767 
3768 /* clang-format off */
3769 FIXTURE_VARIANT_ADD(ftruncate, w_w) {
3770         /* clang-format on */
3771         .handled = LANDLOCK_ACCESS_FS_WRITE_FILE,
3772         .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE,
3773         .expected_open_result = 0,
3774         .expected_ftruncate_result = 0,
3775 };
3776 
3777 /* clang-format off */
3778 FIXTURE_VARIANT_ADD(ftruncate, t_t) {
3779         /* clang-format on */
3780         .handled = LANDLOCK_ACCESS_FS_TRUNCATE,
3781         .allowed = LANDLOCK_ACCESS_FS_TRUNCATE,
3782         .expected_open_result = 0,
3783         .expected_ftruncate_result = 0,
3784 };
3785 
3786 /* clang-format off */
3787 FIXTURE_VARIANT_ADD(ftruncate, wt_w) {
3788         /* clang-format on */
3789         .handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
3790         .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE,
3791         .expected_open_result = 0,
3792         .expected_ftruncate_result = EACCES,
3793 };
3794 
3795 /* clang-format off */
3796 FIXTURE_VARIANT_ADD(ftruncate, wt_wt) {
3797         /* clang-format on */
3798         .handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
3799         .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
3800         .expected_open_result = 0,
3801         .expected_ftruncate_result = 0,
3802 };
3803 
3804 /* clang-format off */
3805 FIXTURE_VARIANT_ADD(ftruncate, wt_t) {
3806         /* clang-format on */
3807         .handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
3808         .allowed = LANDLOCK_ACCESS_FS_TRUNCATE,
3809         .expected_open_result = EACCES,
3810 };
3811 
3812 TEST_F_FORK(ftruncate, open_and_ftruncate)
3813 {
3814         const char *const path = file1_s1d1;
3815         const struct rule rules[] = {
3816                 {
3817                         .path = path,
3818                         .access = variant->allowed,
3819                 },
3820                 {},
3821         };
3822         int fd, ruleset_fd;
3823 
3824         /* Enables Landlock. */
3825         ruleset_fd = create_ruleset(_metadata, variant->handled, rules);
3826         ASSERT_LE(0, ruleset_fd);
3827         enforce_ruleset(_metadata, ruleset_fd);
3828         ASSERT_EQ(0, close(ruleset_fd));
3829 
3830         fd = open(path, O_WRONLY);
3831         EXPECT_EQ(variant->expected_open_result, (fd < 0 ? errno : 0));
3832         if (fd >= 0) {
3833                 EXPECT_EQ(variant->expected_ftruncate_result,
3834                           test_ftruncate(fd));
3835                 ASSERT_EQ(0, close(fd));
3836         }
3837 }
3838 
3839 TEST_F_FORK(ftruncate, open_and_ftruncate_in_different_processes)
3840 {
3841         int child, fd, status;
3842         int socket_fds[2];
3843 
3844         ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0,
3845                                 socket_fds));
3846 
3847         child = fork();
3848         ASSERT_LE(0, child);
3849         if (child == 0) {
3850                 /*
3851                  * Enables Landlock in the child process, open a file descriptor
3852                  * where truncation is forbidden and send it to the
3853                  * non-landlocked parent process.
3854                  */
3855                 const char *const path = file1_s1d1;
3856                 const struct rule rules[] = {
3857                         {
3858                                 .path = path,
3859                                 .access = variant->allowed,
3860                         },
3861                         {},
3862                 };
3863                 int fd, ruleset_fd;
3864 
3865                 ruleset_fd = create_ruleset(_metadata, variant->handled, rules);
3866                 ASSERT_LE(0, ruleset_fd);
3867                 enforce_ruleset(_metadata, ruleset_fd);
3868                 ASSERT_EQ(0, close(ruleset_fd));
3869 
3870                 fd = open(path, O_WRONLY);
3871                 ASSERT_EQ(variant->expected_open_result, (fd < 0 ? errno : 0));
3872 
3873                 if (fd >= 0) {
3874                         ASSERT_EQ(0, send_fd(socket_fds[0], fd));
3875                         ASSERT_EQ(0, close(fd));
3876                 }
3877 
3878                 ASSERT_EQ(0, close(socket_fds[0]));
3879 
3880                 _exit(_metadata->exit_code);
3881                 return;
3882         }
3883 
3884         if (variant->expected_open_result == 0) {
3885                 fd = recv_fd(socket_fds[1]);
3886                 ASSERT_LE(0, fd);
3887 
3888                 EXPECT_EQ(variant->expected_ftruncate_result,
3889                           test_ftruncate(fd));
3890                 ASSERT_EQ(0, close(fd));
3891         }
3892 
3893         ASSERT_EQ(child, waitpid(child, &status, 0));
3894         ASSERT_EQ(1, WIFEXITED(status));
3895         ASSERT_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
3896 
3897         ASSERT_EQ(0, close(socket_fds[0]));
3898         ASSERT_EQ(0, close(socket_fds[1]));
3899 }
3900 
3901 /* Invokes the FS_IOC_GETFLAGS IOCTL and returns its errno or 0. */
3902 static int test_fs_ioc_getflags_ioctl(int fd)
3903 {
3904         uint32_t flags;
3905 
3906         if (ioctl(fd, FS_IOC_GETFLAGS, &flags) < 0)
3907                 return errno;
3908         return 0;
3909 }
3910 
3911 TEST(memfd_ftruncate_and_ioctl)
3912 {
3913         const struct landlock_ruleset_attr attr = {
3914                 .handled_access_fs = ACCESS_ALL,
3915         };
3916         int ruleset_fd, fd, i;
3917 
3918         /*
3919          * We exercise the same test both with and without Landlock enabled, to
3920          * ensure that it behaves the same in both cases.
3921          */
3922         for (i = 0; i < 2; i++) {
3923                 /* Creates a new memfd. */
3924                 fd = memfd_create("name", MFD_CLOEXEC);
3925                 ASSERT_LE(0, fd);
3926 
3927                 /*
3928                  * Checks that operations associated with the opened file
3929                  * (ftruncate, ioctl) are permitted on file descriptors that are
3930                  * created in ways other than open(2).
3931                  */
3932                 EXPECT_EQ(0, test_ftruncate(fd));
3933                 EXPECT_EQ(0, test_fs_ioc_getflags_ioctl(fd));
3934 
3935                 ASSERT_EQ(0, close(fd));
3936 
3937                 /* Enables Landlock. */
3938                 ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0);
3939                 ASSERT_LE(0, ruleset_fd);
3940                 enforce_ruleset(_metadata, ruleset_fd);
3941                 ASSERT_EQ(0, close(ruleset_fd));
3942         }
3943 }
3944 
3945 static int test_fionread_ioctl(int fd)
3946 {
3947         size_t sz = 0;
3948 
3949         if (ioctl(fd, FIONREAD, &sz) < 0 && errno == EACCES)
3950                 return errno;
3951         return 0;
3952 }
3953 
3954 TEST_F_FORK(layout1, o_path_ftruncate_and_ioctl)
3955 {
3956         const struct landlock_ruleset_attr attr = {
3957                 .handled_access_fs = ACCESS_ALL,
3958         };
3959         int ruleset_fd, fd;
3960 
3961         /*
3962          * Checks that for files opened with O_PATH, both ioctl(2) and
3963          * ftruncate(2) yield EBADF, as it is documented in open(2) for the
3964          * O_PATH flag.
3965          */
3966         fd = open(dir_s1d1, O_PATH | O_CLOEXEC);
3967         ASSERT_LE(0, fd);
3968 
3969         EXPECT_EQ(EBADF, test_ftruncate(fd));
3970         EXPECT_EQ(EBADF, test_fs_ioc_getflags_ioctl(fd));
3971 
3972         ASSERT_EQ(0, close(fd));
3973 
3974         /* Enables Landlock. */
3975         ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0);
3976         ASSERT_LE(0, ruleset_fd);
3977         enforce_ruleset(_metadata, ruleset_fd);
3978         ASSERT_EQ(0, close(ruleset_fd));
3979 
3980         /*
3981          * Checks that after enabling Landlock,
3982          * - the file can still be opened with O_PATH
3983          * - both ioctl and truncate still yield EBADF (not EACCES).
3984          */
3985         fd = open(dir_s1d1, O_PATH | O_CLOEXEC);
3986         ASSERT_LE(0, fd);
3987 
3988         EXPECT_EQ(EBADF, test_ftruncate(fd));
3989         EXPECT_EQ(EBADF, test_fs_ioc_getflags_ioctl(fd));
3990 
3991         ASSERT_EQ(0, close(fd));
3992 }
3993 
3994 /*
3995  * ioctl_error - generically call the given ioctl with a pointer to a
3996  * sufficiently large zeroed-out memory region.
3997  *
3998  * Returns the IOCTLs error, or 0.
3999  */
4000 static int ioctl_error(struct __test_metadata *const _metadata, int fd,
4001                        unsigned int cmd)
4002 {
4003         char buf[128]; /* sufficiently large */
4004         int res, stdinbak_fd;
4005 
4006         /*
4007          * Depending on the IOCTL command, parts of the zeroed-out buffer might
4008          * be interpreted as file descriptor numbers.  We do not want to
4009          * accidentally operate on file descriptor 0 (stdin), so we temporarily
4010          * move stdin to a different FD and close FD 0 for the IOCTL call.
4011          */
4012         stdinbak_fd = dup(0);
4013         ASSERT_LT(0, stdinbak_fd);
4014         ASSERT_EQ(0, close(0));
4015 
4016         /* Invokes the IOCTL with a zeroed-out buffer. */
4017         bzero(&buf, sizeof(buf));
4018         res = ioctl(fd, cmd, &buf);
4019 
4020         /* Restores the old FD 0 and closes the backup FD. */
4021         ASSERT_EQ(0, dup2(stdinbak_fd, 0));
4022         ASSERT_EQ(0, close(stdinbak_fd));
4023 
4024         if (res < 0)
4025                 return errno;
4026 
4027         return 0;
4028 }
4029 
4030 /* Define some linux/falloc.h IOCTL commands which are not available in uapi headers. */
4031 struct space_resv {
4032         __s16 l_type;
4033         __s16 l_whence;
4034         __s64 l_start;
4035         __s64 l_len; /* len == 0 means until end of file */
4036         __s32 l_sysid;
4037         __u32 l_pid;
4038         __s32 l_pad[4]; /* reserved area */
4039 };
4040 
4041 #define FS_IOC_RESVSP _IOW('X', 40, struct space_resv)
4042 #define FS_IOC_UNRESVSP _IOW('X', 41, struct space_resv)
4043 #define FS_IOC_RESVSP64 _IOW('X', 42, struct space_resv)
4044 #define FS_IOC_UNRESVSP64 _IOW('X', 43, struct space_resv)
4045 #define FS_IOC_ZERO_RANGE _IOW('X', 57, struct space_resv)
4046 
4047 /*
4048  * Tests a series of blanket-permitted and denied IOCTLs.
4049  */
4050 TEST_F_FORK(layout1, blanket_permitted_ioctls)
4051 {
4052         const struct landlock_ruleset_attr attr = {
4053                 .handled_access_fs = LANDLOCK_ACCESS_FS_IOCTL_DEV,
4054         };
4055         int ruleset_fd, fd;
4056 
4057         /* Enables Landlock. */
4058         ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0);
4059         ASSERT_LE(0, ruleset_fd);
4060         enforce_ruleset(_metadata, ruleset_fd);
4061         ASSERT_EQ(0, close(ruleset_fd));
4062 
4063         fd = open("/dev/null", O_RDWR | O_CLOEXEC);
4064         ASSERT_LE(0, fd);
4065 
4066         /*
4067          * Checks permitted commands.
4068          * These ones may return errors, but should not be blocked by Landlock.
4069          */
4070         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIOCLEX));
4071         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIONCLEX));
4072         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIONBIO));
4073         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIOASYNC));
4074         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIOQSIZE));
4075         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIFREEZE));
4076         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FITHAW));
4077         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FS_IOC_FIEMAP));
4078         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIGETBSZ));
4079         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FICLONE));
4080         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FICLONERANGE));
4081         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FIDEDUPERANGE));
4082         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FS_IOC_GETFSUUID));
4083         EXPECT_NE(EACCES, ioctl_error(_metadata, fd, FS_IOC_GETFSSYSFSPATH));
4084 
4085         /*
4086          * Checks blocked commands.
4087          * A call to a blocked IOCTL command always returns EACCES.
4088          */
4089         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FIONREAD));
4090         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_GETFLAGS));
4091         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_SETFLAGS));
4092         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_FSGETXATTR));
4093         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_FSSETXATTR));
4094         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FIBMAP));
4095         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_RESVSP));
4096         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_RESVSP64));
4097         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_UNRESVSP));
4098         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_UNRESVSP64));
4099         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, FS_IOC_ZERO_RANGE));
4100 
4101         /* Default case is also blocked. */
4102         EXPECT_EQ(EACCES, ioctl_error(_metadata, fd, 0xc00ffeee));
4103 
4104         ASSERT_EQ(0, close(fd));
4105 }
4106 
4107 /*
4108  * Named pipes are not governed by the LANDLOCK_ACCESS_FS_IOCTL_DEV right,
4109  * because they are not character or block devices.
4110  */
4111 TEST_F_FORK(layout1, named_pipe_ioctl)
4112 {
4113         pid_t child_pid;
4114         int fd, ruleset_fd;
4115         const char *const path = file1_s1d1;
4116         const struct landlock_ruleset_attr attr = {
4117                 .handled_access_fs = LANDLOCK_ACCESS_FS_IOCTL_DEV,
4118         };
4119 
4120         ASSERT_EQ(0, unlink(path));
4121         ASSERT_EQ(0, mkfifo(path, 0600));
4122 
4123         /* Enables Landlock. */
4124         ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0);
4125         ASSERT_LE(0, ruleset_fd);
4126         enforce_ruleset(_metadata, ruleset_fd);
4127         ASSERT_EQ(0, close(ruleset_fd));
4128 
4129         /* The child process opens the pipe for writing. */
4130         child_pid = fork();
4131         ASSERT_NE(-1, child_pid);
4132         if (child_pid == 0) {
4133                 fd = open(path, O_WRONLY);
4134                 close(fd);
4135                 exit(0);
4136         }
4137 
4138         fd = open(path, O_RDONLY);
4139         ASSERT_LE(0, fd);
4140 
4141         /* FIONREAD is implemented by pipefifo_fops. */
4142         EXPECT_EQ(0, test_fionread_ioctl(fd));
4143 
4144         ASSERT_EQ(0, close(fd));
4145         ASSERT_EQ(0, unlink(path));
4146 
4147         ASSERT_EQ(child_pid, waitpid(child_pid, NULL, 0));
4148 }
4149 
4150 /* For named UNIX domain sockets, no IOCTL restrictions apply. */
4151 TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)
4152 {
4153         const char *const path = file1_s1d1;
4154         int srv_fd, cli_fd, ruleset_fd;
4155         socklen_t size;
4156         struct sockaddr_un srv_un, cli_un;
4157         const struct landlock_ruleset_attr attr = {
4158                 .handled_access_fs = LANDLOCK_ACCESS_FS_IOCTL_DEV,
4159         };
4160 
4161         /* Sets up a server */
4162         srv_un.sun_family = AF_UNIX;
4163         strncpy(srv_un.sun_path, path, sizeof(srv_un.sun_path));
4164 
4165         ASSERT_EQ(0, unlink(path));
4166         srv_fd = socket(AF_UNIX, SOCK_STREAM, 0);
4167         ASSERT_LE(0, srv_fd);
4168 
4169         size = offsetof(struct sockaddr_un, sun_path) + strlen(srv_un.sun_path);
4170         ASSERT_EQ(0, bind(srv_fd, (struct sockaddr *)&srv_un, size));
4171         ASSERT_EQ(0, listen(srv_fd, 10 /* qlen */));
4172 
4173         /* Enables Landlock. */
4174         ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0);
4175         ASSERT_LE(0, ruleset_fd);
4176         enforce_ruleset(_metadata, ruleset_fd);
4177         ASSERT_EQ(0, close(ruleset_fd));
4178 
4179         /* Sets up a client connection to it */
4180         cli_un.sun_family = AF_UNIX;
4181         cli_fd = socket(AF_UNIX, SOCK_STREAM, 0);
4182         ASSERT_LE(0, cli_fd);
4183 
4184         size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path);
4185         ASSERT_EQ(0, bind(cli_fd, (struct sockaddr *)&cli_un, size));
4186 
4187         bzero(&cli_un, sizeof(cli_un));
4188         cli_un.sun_family = AF_UNIX;
4189         strncpy(cli_un.sun_path, path, sizeof(cli_un.sun_path));
4190         size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path);
4191 
4192         ASSERT_EQ(0, connect(cli_fd, (struct sockaddr *)&cli_un, size));
4193 
4194         /* FIONREAD and other IOCTLs should not be forbidden. */
4195         EXPECT_EQ(0, test_fionread_ioctl(cli_fd));
4196 
4197         ASSERT_EQ(0, close(cli_fd));
4198 }
4199 
4200 /* clang-format off */
4201 FIXTURE(ioctl) {};
4202 
4203 FIXTURE_SETUP(ioctl) {};
4204 
4205 FIXTURE_TEARDOWN(ioctl) {};
4206 /* clang-format on */
4207 
4208 FIXTURE_VARIANT(ioctl)
4209 {
4210         const __u64 handled;
4211         const __u64 allowed;
4212         const mode_t open_mode;
4213         /*
4214          * FIONREAD is used as a characteristic device-specific IOCTL command.
4215          * It is implemented in fs/ioctl.c for regular files,
4216          * but we do not blanket-permit it for devices.
4217          */
4218         const int expected_fionread_result;
4219 };
4220 
4221 /* clang-format off */
4222 FIXTURE_VARIANT_ADD(ioctl, handled_i_allowed_none) {
4223         /* clang-format on */
4224         .handled = LANDLOCK_ACCESS_FS_IOCTL_DEV,
4225         .allowed = 0,
4226         .open_mode = O_RDWR,
4227         .expected_fionread_result = EACCES,
4228 };
4229 
4230 /* clang-format off */
4231 FIXTURE_VARIANT_ADD(ioctl, handled_i_allowed_i) {
4232         /* clang-format on */
4233         .handled = LANDLOCK_ACCESS_FS_IOCTL_DEV,
4234         .allowed = LANDLOCK_ACCESS_FS_IOCTL_DEV,
4235         .open_mode = O_RDWR,
4236         .expected_fionread_result = 0,
4237 };
4238 
4239 /* clang-format off */
4240 FIXTURE_VARIANT_ADD(ioctl, unhandled) {
4241         /* clang-format on */
4242         .handled = LANDLOCK_ACCESS_FS_EXECUTE,
4243         .allowed = LANDLOCK_ACCESS_FS_EXECUTE,
4244         .open_mode = O_RDWR,
4245         .expected_fionread_result = 0,
4246 };
4247 
4248 TEST_F_FORK(ioctl, handle_dir_access_file)
4249 {
4250         const int flag = 0;
4251         const struct rule rules[] = {
4252                 {
4253                         .path = "/dev",
4254                         .access = variant->allowed,
4255                 },
4256                 {},
4257         };
4258         int file_fd, ruleset_fd;
4259 
4260         /* Enables Landlock. */
4261         ruleset_fd = create_ruleset(_metadata, variant->handled, rules);
4262         ASSERT_LE(0, ruleset_fd);
4263         enforce_ruleset(_metadata, ruleset_fd);
4264         ASSERT_EQ(0, close(ruleset_fd));
4265 
4266         file_fd = open("/dev/zero", variant->open_mode);
4267         ASSERT_LE(0, file_fd);
4268 
4269         /* Checks that IOCTL commands return the expected errors. */
4270         EXPECT_EQ(variant->expected_fionread_result,
4271                   test_fionread_ioctl(file_fd));
4272 
4273         /* Checks that unrestrictable commands are unrestricted. */
4274         EXPECT_EQ(0, ioctl(file_fd, FIOCLEX));
4275         EXPECT_EQ(0, ioctl(file_fd, FIONCLEX));
4276         EXPECT_EQ(0, ioctl(file_fd, FIONBIO, &flag));
4277         EXPECT_EQ(0, ioctl(file_fd, FIOASYNC, &flag));
4278         EXPECT_EQ(0, ioctl(file_fd, FIGETBSZ, &flag));
4279 
4280         ASSERT_EQ(0, close(file_fd));
4281 }
4282 
4283 TEST_F_FORK(ioctl, handle_dir_access_dir)
4284 {
4285         const int flag = 0;
4286         const struct rule rules[] = {
4287                 {
4288                         .path = "/dev",
4289                         .access = variant->allowed,
4290                 },
4291                 {},
4292         };
4293         int dir_fd, ruleset_fd;
4294 
4295         /* Enables Landlock. */
4296         ruleset_fd = create_ruleset(_metadata, variant->handled, rules);
4297         ASSERT_LE(0, ruleset_fd);
4298         enforce_ruleset(_metadata, ruleset_fd);
4299         ASSERT_EQ(0, close(ruleset_fd));
4300 
4301         /*
4302          * Ignore variant->open_mode for this test, as we intend to open a
4303          * directory.  If the directory can not be opened, the variant is
4304          * infeasible to test with an opened directory.
4305          */
4306         dir_fd = open("/dev", O_RDONLY);
4307         if (dir_fd < 0)
4308                 return;
4309 
4310         /*
4311          * Checks that IOCTL commands return the expected errors.
4312          * We do not use the expected values from the fixture here.
4313          *
4314          * When using IOCTL on a directory, no Landlock restrictions apply.
4315          */
4316         EXPECT_EQ(0, test_fionread_ioctl(dir_fd));
4317 
4318         /* Checks that unrestrictable commands are unrestricted. */
4319         EXPECT_EQ(0, ioctl(dir_fd, FIOCLEX));
4320         EXPECT_EQ(0, ioctl(dir_fd, FIONCLEX));
4321         EXPECT_EQ(0, ioctl(dir_fd, FIONBIO, &flag));
4322         EXPECT_EQ(0, ioctl(dir_fd, FIOASYNC, &flag));
4323         EXPECT_EQ(0, ioctl(dir_fd, FIGETBSZ, &flag));
4324 
4325         ASSERT_EQ(0, close(dir_fd));
4326 }
4327 
4328 TEST_F_FORK(ioctl, handle_file_access_file)
4329 {
4330         const int flag = 0;
4331         const struct rule rules[] = {
4332                 {
4333                         .path = "/dev/zero",
4334                         .access = variant->allowed,
4335                 },
4336                 {},
4337         };
4338         int file_fd, ruleset_fd;
4339 
4340         /* Enables Landlock. */
4341         ruleset_fd = create_ruleset(_metadata, variant->handled, rules);
4342         ASSERT_LE(0, ruleset_fd);
4343         enforce_ruleset(_metadata, ruleset_fd);
4344         ASSERT_EQ(0, close(ruleset_fd));
4345 
4346         file_fd = open("/dev/zero", variant->open_mode);
4347         ASSERT_LE(0, file_fd)
4348         {
4349                 TH_LOG("Failed to open /dev/zero: %s", strerror(errno));
4350         }
4351 
4352         /* Checks that IOCTL commands return the expected errors. */
4353         EXPECT_EQ(variant->expected_fionread_result,
4354                   test_fionread_ioctl(file_fd));
4355 
4356         /* Checks that unrestrictable commands are unrestricted. */
4357         EXPECT_EQ(0, ioctl(file_fd, FIOCLEX));
4358         EXPECT_EQ(0, ioctl(file_fd, FIONCLEX));
4359         EXPECT_EQ(0, ioctl(file_fd, FIONBIO, &flag));
4360         EXPECT_EQ(0, ioctl(file_fd, FIOASYNC, &flag));
4361         EXPECT_EQ(0, ioctl(file_fd, FIGETBSZ, &flag));
4362 
4363         ASSERT_EQ(0, close(file_fd));
4364 }
4365 
4366 /* clang-format off */
4367 FIXTURE(layout1_bind) {};
4368 /* clang-format on */
4369 
4370 FIXTURE_SETUP(layout1_bind)
4371 {
4372         prepare_layout(_metadata);
4373 
4374         create_layout1(_metadata);
4375 
4376         set_cap(_metadata, CAP_SYS_ADMIN);
4377         ASSERT_EQ(0, mount(dir_s1d2, dir_s2d2, NULL, MS_BIND, NULL));
4378         clear_cap(_metadata, CAP_SYS_ADMIN);
4379 }
4380 
4381 FIXTURE_TEARDOWN_PARENT(layout1_bind)
4382 {
4383         /* umount(dir_s2d2)) is handled by namespace lifetime. */
4384 
4385         remove_layout1(_metadata);
4386 
4387         cleanup_layout(_metadata);
4388 }
4389 
4390 static const char bind_dir_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3";
4391 static const char bind_file1_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3/f1";
4392 
4393 /*
4394  * layout1_bind hierarchy:
4395  *
4396  * tmp
4397  * ├── s1d1
4398  * │   ├── f1
4399  * │   ├── f2
4400  * │   └── s1d2
4401  * │       ├── f1
4402  * │       ├── f2
4403  * │       └── s1d3
4404  * │           ├── f1
4405  * │           └── f2
4406  * ├── s2d1
4407  * │   ├── f1
4408  * │   └── s2d2
4409  * │       ├── f1
4410  * │       ├── f2
4411  * │       └── s1d3
4412  * │           ├── f1
4413  * │           └── f2
4414  * └── s3d1
4415  *     └── s3d2
4416  *         └── s3d3
4417  */
4418 
4419 TEST_F_FORK(layout1_bind, no_restriction)
4420 {
4421         ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
4422         ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
4423         ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
4424         ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
4425         ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
4426         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
4427 
4428         ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
4429         ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
4430         ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
4431         ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
4432         ASSERT_EQ(ENOENT, test_open(dir_s2d3, O_RDONLY));
4433         ASSERT_EQ(ENOENT, test_open(file1_s2d3, O_RDONLY));
4434 
4435         ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY));
4436         ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
4437 
4438         ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
4439 }
4440 
4441 TEST_F_FORK(layout1_bind, same_content_same_file)
4442 {
4443         /*
4444          * Sets access right on parent directories of both source and
4445          * destination mount points.
4446          */
4447         const struct rule layer1_parent[] = {
4448                 {
4449                         .path = dir_s1d1,
4450                         .access = ACCESS_RO,
4451                 },
4452                 {
4453                         .path = dir_s2d1,
4454                         .access = ACCESS_RW,
4455                 },
4456                 {},
4457         };
4458         /*
4459          * Sets access rights on the same bind-mounted directories.  The result
4460          * should be ACCESS_RW for both directories, but not both hierarchies
4461          * because of the first layer.
4462          */
4463         const struct rule layer2_mount_point[] = {
4464                 {
4465                         .path = dir_s1d2,
4466                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4467                 },
4468                 {
4469                         .path = dir_s2d2,
4470                         .access = ACCESS_RW,
4471                 },
4472                 {},
4473         };
4474         /* Only allow read-access to the s1d3 hierarchies. */
4475         const struct rule layer3_source[] = {
4476                 {
4477                         .path = dir_s1d3,
4478                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4479                 },
4480                 {},
4481         };
4482         /* Removes all access rights. */
4483         const struct rule layer4_destination[] = {
4484                 {
4485                         .path = bind_file1_s1d3,
4486                         .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
4487                 },
4488                 {},
4489         };
4490         int ruleset_fd;
4491 
4492         /* Sets rules for the parent directories. */
4493         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_parent);
4494         ASSERT_LE(0, ruleset_fd);
4495         enforce_ruleset(_metadata, ruleset_fd);
4496         ASSERT_EQ(0, close(ruleset_fd));
4497 
4498         /* Checks source hierarchy. */
4499         ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
4500         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
4501         ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
4502 
4503         ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
4504         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
4505         ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
4506 
4507         /* Checks destination hierarchy. */
4508         ASSERT_EQ(0, test_open(file1_s2d1, O_RDWR));
4509         ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
4510 
4511         ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
4512         ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
4513 
4514         /* Sets rules for the mount points. */
4515         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_mount_point);
4516         ASSERT_LE(0, ruleset_fd);
4517         enforce_ruleset(_metadata, ruleset_fd);
4518         ASSERT_EQ(0, close(ruleset_fd));
4519 
4520         /* Checks source hierarchy. */
4521         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
4522         ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
4523         ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
4524 
4525         ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
4526         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
4527         ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
4528 
4529         /* Checks destination hierarchy. */
4530         ASSERT_EQ(EACCES, test_open(file1_s2d1, O_RDONLY));
4531         ASSERT_EQ(EACCES, test_open(file1_s2d1, O_WRONLY));
4532         ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
4533 
4534         ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
4535         ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
4536         ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
4537 
4538         /* Sets a (shared) rule only on the source. */
4539         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3_source);
4540         ASSERT_LE(0, ruleset_fd);
4541         enforce_ruleset(_metadata, ruleset_fd);
4542         ASSERT_EQ(0, close(ruleset_fd));
4543 
4544         /* Checks source hierarchy. */
4545         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDONLY));
4546         ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
4547         ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
4548 
4549         ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
4550         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
4551         ASSERT_EQ(EACCES, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
4552 
4553         /* Checks destination hierarchy. */
4554         ASSERT_EQ(EACCES, test_open(file1_s2d2, O_RDONLY));
4555         ASSERT_EQ(EACCES, test_open(file1_s2d2, O_WRONLY));
4556         ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
4557 
4558         ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
4559         ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
4560         ASSERT_EQ(EACCES, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
4561 
4562         /* Sets a (shared) rule only on the destination. */
4563         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer4_destination);
4564         ASSERT_LE(0, ruleset_fd);
4565         enforce_ruleset(_metadata, ruleset_fd);
4566         ASSERT_EQ(0, close(ruleset_fd));
4567 
4568         /* Checks source hierarchy. */
4569         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
4570         ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
4571 
4572         /* Checks destination hierarchy. */
4573         ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_RDONLY));
4574         ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
4575 }
4576 
4577 TEST_F_FORK(layout1_bind, reparent_cross_mount)
4578 {
4579         const struct rule layer1[] = {
4580                 {
4581                         /* dir_s2d1 is beneath the dir_s2d2 mount point. */
4582                         .path = dir_s2d1,
4583                         .access = LANDLOCK_ACCESS_FS_REFER,
4584                 },
4585                 {
4586                         .path = bind_dir_s1d3,
4587                         .access = LANDLOCK_ACCESS_FS_EXECUTE,
4588                 },
4589                 {},
4590         };
4591         int ruleset_fd = create_ruleset(
4592                 _metadata,
4593                 LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_EXECUTE, layer1);
4594 
4595         ASSERT_LE(0, ruleset_fd);
4596         enforce_ruleset(_metadata, ruleset_fd);
4597         ASSERT_EQ(0, close(ruleset_fd));
4598 
4599         /* Checks basic denied move. */
4600         ASSERT_EQ(-1, rename(file1_s1d1, file1_s1d2));
4601         ASSERT_EQ(EXDEV, errno);
4602 
4603         /* Checks real cross-mount move (Landlock is not involved). */
4604         ASSERT_EQ(-1, rename(file1_s2d1, file1_s2d2));
4605         ASSERT_EQ(EXDEV, errno);
4606 
4607         /* Checks move that will give more accesses. */
4608         ASSERT_EQ(-1, rename(file1_s2d2, bind_file1_s1d3));
4609         ASSERT_EQ(EXDEV, errno);
4610 
4611         /* Checks legitimate downgrade move. */
4612         ASSERT_EQ(0, rename(bind_file1_s1d3, file1_s2d2));
4613 }
4614 
4615 #define LOWER_BASE TMP_DIR "/lower"
4616 #define LOWER_DATA LOWER_BASE "/data"
4617 static const char lower_fl1[] = LOWER_DATA "/fl1";
4618 static const char lower_dl1[] = LOWER_DATA "/dl1";
4619 static const char lower_dl1_fl2[] = LOWER_DATA "/dl1/fl2";
4620 static const char lower_fo1[] = LOWER_DATA "/fo1";
4621 static const char lower_do1[] = LOWER_DATA "/do1";
4622 static const char lower_do1_fo2[] = LOWER_DATA "/do1/fo2";
4623 static const char lower_do1_fl3[] = LOWER_DATA "/do1/fl3";
4624 
4625 static const char (*lower_base_files[])[] = {
4626         &lower_fl1,
4627         &lower_fo1,
4628         NULL,
4629 };
4630 static const char (*lower_base_directories[])[] = {
4631         &lower_dl1,
4632         &lower_do1,
4633         NULL,
4634 };
4635 static const char (*lower_sub_files[])[] = {
4636         &lower_dl1_fl2,
4637         &lower_do1_fo2,
4638         &lower_do1_fl3,
4639         NULL,
4640 };
4641 
4642 #define UPPER_BASE TMP_DIR "/upper"
4643 #define UPPER_DATA UPPER_BASE "/data"
4644 #define UPPER_WORK UPPER_BASE "/work"
4645 static const char upper_fu1[] = UPPER_DATA "/fu1";
4646 static const char upper_du1[] = UPPER_DATA "/du1";
4647 static const char upper_du1_fu2[] = UPPER_DATA "/du1/fu2";
4648 static const char upper_fo1[] = UPPER_DATA "/fo1";
4649 static const char upper_do1[] = UPPER_DATA "/do1";
4650 static const char upper_do1_fo2[] = UPPER_DATA "/do1/fo2";
4651 static const char upper_do1_fu3[] = UPPER_DATA "/do1/fu3";
4652 
4653 static const char (*upper_base_files[])[] = {
4654         &upper_fu1,
4655         &upper_fo1,
4656         NULL,
4657 };
4658 static const char (*upper_base_directories[])[] = {
4659         &upper_du1,
4660         &upper_do1,
4661         NULL,
4662 };
4663 static const char (*upper_sub_files[])[] = {
4664         &upper_du1_fu2,
4665         &upper_do1_fo2,
4666         &upper_do1_fu3,
4667         NULL,
4668 };
4669 
4670 #define MERGE_BASE TMP_DIR "/merge"
4671 #define MERGE_DATA MERGE_BASE "/data"
4672 static const char merge_fl1[] = MERGE_DATA "/fl1";
4673 static const char merge_dl1[] = MERGE_DATA "/dl1";
4674 static const char merge_dl1_fl2[] = MERGE_DATA "/dl1/fl2";
4675 static const char merge_fu1[] = MERGE_DATA "/fu1";
4676 static const char merge_du1[] = MERGE_DATA "/du1";
4677 static const char merge_du1_fu2[] = MERGE_DATA "/du1/fu2";
4678 static const char merge_fo1[] = MERGE_DATA "/fo1";
4679 static const char merge_do1[] = MERGE_DATA "/do1";
4680 static const char merge_do1_fo2[] = MERGE_DATA "/do1/fo2";
4681 static const char merge_do1_fl3[] = MERGE_DATA "/do1/fl3";
4682 static const char merge_do1_fu3[] = MERGE_DATA "/do1/fu3";
4683 
4684 static const char (*merge_base_files[])[] = {
4685         &merge_fl1,
4686         &merge_fu1,
4687         &merge_fo1,
4688         NULL,
4689 };
4690 static const char (*merge_base_directories[])[] = {
4691         &merge_dl1,
4692         &merge_du1,
4693         &merge_do1,
4694         NULL,
4695 };
4696 static const char (*merge_sub_files[])[] = {
4697         &merge_dl1_fl2, &merge_du1_fu2, &merge_do1_fo2,
4698         &merge_do1_fl3, &merge_do1_fu3, NULL,
4699 };
4700 
4701 /*
4702  * layout2_overlay hierarchy:
4703  *
4704  * tmp
4705  * ├── lower
4706  * │   └── data
4707  * │       ├── dl1
4708  * │       │   └── fl2
4709  * │       ├── do1
4710  * │       │   ├── fl3
4711  * │       │   └── fo2
4712  * │       ├── fl1
4713  * │       └── fo1
4714  * ├── merge
4715  * │   └── data
4716  * │       ├── dl1
4717  * │       │   └── fl2
4718  * │       ├── do1
4719  * │       │   ├── fl3
4720  * │       │   ├── fo2
4721  * │       │   └── fu3
4722  * │       ├── du1
4723  * │       │   └── fu2
4724  * │       ├── fl1
4725  * │       ├── fo1
4726  * │       └── fu1
4727  * └── upper
4728  *     ├── data
4729  *     │   ├── do1
4730  *     │   │   ├── fo2
4731  *     │   │   └── fu3
4732  *     │   ├── du1
4733  *     │   │   └── fu2
4734  *     │   ├── fo1
4735  *     │   └── fu1
4736  *     └── work
4737  *         └── work
4738  */
4739 
4740 FIXTURE(layout2_overlay)
4741 {
4742         bool skip_test;
4743 };
4744 
4745 FIXTURE_SETUP(layout2_overlay)
4746 {
4747         if (!supports_filesystem("overlay")) {
4748                 self->skip_test = true;
4749                 SKIP(return, "overlayfs is not supported (setup)");
4750         }
4751 
4752         prepare_layout(_metadata);
4753 
4754         create_directory(_metadata, LOWER_BASE);
4755         set_cap(_metadata, CAP_SYS_ADMIN);
4756         /* Creates tmpfs mount points to get deterministic overlayfs. */
4757         ASSERT_EQ(0, mount_opt(&mnt_tmp, LOWER_BASE));
4758         clear_cap(_metadata, CAP_SYS_ADMIN);
4759         create_file(_metadata, lower_fl1);
4760         create_file(_metadata, lower_dl1_fl2);
4761         create_file(_metadata, lower_fo1);
4762         create_file(_metadata, lower_do1_fo2);
4763         create_file(_metadata, lower_do1_fl3);
4764 
4765         create_directory(_metadata, UPPER_BASE);
4766         set_cap(_metadata, CAP_SYS_ADMIN);
4767         ASSERT_EQ(0, mount_opt(&mnt_tmp, UPPER_BASE));
4768         clear_cap(_metadata, CAP_SYS_ADMIN);
4769         create_file(_metadata, upper_fu1);
4770         create_file(_metadata, upper_du1_fu2);
4771         create_file(_metadata, upper_fo1);
4772         create_file(_metadata, upper_do1_fo2);
4773         create_file(_metadata, upper_do1_fu3);
4774         ASSERT_EQ(0, mkdir(UPPER_WORK, 0700));
4775 
4776         create_directory(_metadata, MERGE_DATA);
4777         set_cap(_metadata, CAP_SYS_ADMIN);
4778         set_cap(_metadata, CAP_DAC_OVERRIDE);
4779         ASSERT_EQ(0, mount("overlay", MERGE_DATA, "overlay", 0,
4780                            "lowerdir=" LOWER_DATA ",upperdir=" UPPER_DATA
4781                            ",workdir=" UPPER_WORK));
4782         clear_cap(_metadata, CAP_DAC_OVERRIDE);
4783         clear_cap(_metadata, CAP_SYS_ADMIN);
4784 }
4785 
4786 FIXTURE_TEARDOWN_PARENT(layout2_overlay)
4787 {
4788         if (self->skip_test)
4789                 SKIP(return, "overlayfs is not supported (teardown)");
4790 
4791         EXPECT_EQ(0, remove_path(lower_do1_fl3));
4792         EXPECT_EQ(0, remove_path(lower_dl1_fl2));
4793         EXPECT_EQ(0, remove_path(lower_fl1));
4794         EXPECT_EQ(0, remove_path(lower_do1_fo2));
4795         EXPECT_EQ(0, remove_path(lower_fo1));
4796 
4797         /* umount(LOWER_BASE)) is handled by namespace lifetime. */
4798         EXPECT_EQ(0, remove_path(LOWER_BASE));
4799 
4800         EXPECT_EQ(0, remove_path(upper_do1_fu3));
4801         EXPECT_EQ(0, remove_path(upper_du1_fu2));
4802         EXPECT_EQ(0, remove_path(upper_fu1));
4803         EXPECT_EQ(0, remove_path(upper_do1_fo2));
4804         EXPECT_EQ(0, remove_path(upper_fo1));
4805         EXPECT_EQ(0, remove_path(UPPER_WORK "/work"));
4806 
4807         /* umount(UPPER_BASE)) is handled by namespace lifetime. */
4808         EXPECT_EQ(0, remove_path(UPPER_BASE));
4809 
4810         /* umount(MERGE_DATA)) is handled by namespace lifetime. */
4811         EXPECT_EQ(0, remove_path(MERGE_DATA));
4812 
4813         cleanup_layout(_metadata);
4814 }
4815 
4816 TEST_F_FORK(layout2_overlay, no_restriction)
4817 {
4818         if (self->skip_test)
4819                 SKIP(return, "overlayfs is not supported (test)");
4820 
4821         ASSERT_EQ(0, test_open(lower_fl1, O_RDONLY));
4822         ASSERT_EQ(0, test_open(lower_dl1, O_RDONLY));
4823         ASSERT_EQ(0, test_open(lower_dl1_fl2, O_RDONLY));
4824         ASSERT_EQ(0, test_open(lower_fo1, O_RDONLY));
4825         ASSERT_EQ(0, test_open(lower_do1, O_RDONLY));
4826         ASSERT_EQ(0, test_open(lower_do1_fo2, O_RDONLY));
4827         ASSERT_EQ(0, test_open(lower_do1_fl3, O_RDONLY));
4828 
4829         ASSERT_EQ(0, test_open(upper_fu1, O_RDONLY));
4830         ASSERT_EQ(0, test_open(upper_du1, O_RDONLY));
4831         ASSERT_EQ(0, test_open(upper_du1_fu2, O_RDONLY));
4832         ASSERT_EQ(0, test_open(upper_fo1, O_RDONLY));
4833         ASSERT_EQ(0, test_open(upper_do1, O_RDONLY));
4834         ASSERT_EQ(0, test_open(upper_do1_fo2, O_RDONLY));
4835         ASSERT_EQ(0, test_open(upper_do1_fu3, O_RDONLY));
4836 
4837         ASSERT_EQ(0, test_open(merge_fl1, O_RDONLY));
4838         ASSERT_EQ(0, test_open(merge_dl1, O_RDONLY));
4839         ASSERT_EQ(0, test_open(merge_dl1_fl2, O_RDONLY));
4840         ASSERT_EQ(0, test_open(merge_fu1, O_RDONLY));
4841         ASSERT_EQ(0, test_open(merge_du1, O_RDONLY));
4842         ASSERT_EQ(0, test_open(merge_du1_fu2, O_RDONLY));
4843         ASSERT_EQ(0, test_open(merge_fo1, O_RDONLY));
4844         ASSERT_EQ(0, test_open(merge_do1, O_RDONLY));
4845         ASSERT_EQ(0, test_open(merge_do1_fo2, O_RDONLY));
4846         ASSERT_EQ(0, test_open(merge_do1_fl3, O_RDONLY));
4847         ASSERT_EQ(0, test_open(merge_do1_fu3, O_RDONLY));
4848 }
4849 
4850 #define for_each_path(path_list, path_entry, i)               \
4851         for (i = 0, path_entry = *path_list[i]; path_list[i]; \
4852              path_entry = *path_list[++i])
4853 
4854 TEST_F_FORK(layout2_overlay, same_content_different_file)
4855 {
4856         /* Sets access right on parent directories of both layers. */
4857         const struct rule layer1_base[] = {
4858                 {
4859                         .path = LOWER_BASE,
4860                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4861                 },
4862                 {
4863                         .path = UPPER_BASE,
4864                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4865                 },
4866                 {
4867                         .path = MERGE_BASE,
4868                         .access = ACCESS_RW,
4869                 },
4870                 {},
4871         };
4872         const struct rule layer2_data[] = {
4873                 {
4874                         .path = LOWER_DATA,
4875                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4876                 },
4877                 {
4878                         .path = UPPER_DATA,
4879                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4880                 },
4881                 {
4882                         .path = MERGE_DATA,
4883                         .access = ACCESS_RW,
4884                 },
4885                 {},
4886         };
4887         /* Sets access right on directories inside both layers. */
4888         const struct rule layer3_subdirs[] = {
4889                 {
4890                         .path = lower_dl1,
4891                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4892                 },
4893                 {
4894                         .path = lower_do1,
4895                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4896                 },
4897                 {
4898                         .path = upper_du1,
4899                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4900                 },
4901                 {
4902                         .path = upper_do1,
4903                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4904                 },
4905                 {
4906                         .path = merge_dl1,
4907                         .access = ACCESS_RW,
4908                 },
4909                 {
4910                         .path = merge_du1,
4911                         .access = ACCESS_RW,
4912                 },
4913                 {
4914                         .path = merge_do1,
4915                         .access = ACCESS_RW,
4916                 },
4917                 {},
4918         };
4919         /* Tighten access rights to the files. */
4920         const struct rule layer4_files[] = {
4921                 {
4922                         .path = lower_dl1_fl2,
4923                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4924                 },
4925                 {
4926                         .path = lower_do1_fo2,
4927                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4928                 },
4929                 {
4930                         .path = lower_do1_fl3,
4931                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4932                 },
4933                 {
4934                         .path = upper_du1_fu2,
4935                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4936                 },
4937                 {
4938                         .path = upper_do1_fo2,
4939                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4940                 },
4941                 {
4942                         .path = upper_do1_fu3,
4943                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
4944                 },
4945                 {
4946                         .path = merge_dl1_fl2,
4947                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
4948                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
4949                 },
4950                 {
4951                         .path = merge_du1_fu2,
4952                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
4953                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
4954                 },
4955                 {
4956                         .path = merge_do1_fo2,
4957                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
4958                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
4959                 },
4960                 {
4961                         .path = merge_do1_fl3,
4962                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
4963                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
4964                 },
4965                 {
4966                         .path = merge_do1_fu3,
4967                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
4968                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
4969                 },
4970                 {},
4971         };
4972         const struct rule layer5_merge_only[] = {
4973                 {
4974                         .path = MERGE_DATA,
4975                         .access = LANDLOCK_ACCESS_FS_READ_FILE |
4976                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
4977                 },
4978                 {},
4979         };
4980         int ruleset_fd;
4981         size_t i;
4982         const char *path_entry;
4983 
4984         if (self->skip_test)
4985                 SKIP(return, "overlayfs is not supported (test)");
4986 
4987         /* Sets rules on base directories (i.e. outside overlay scope). */
4988         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_base);
4989         ASSERT_LE(0, ruleset_fd);
4990         enforce_ruleset(_metadata, ruleset_fd);
4991         ASSERT_EQ(0, close(ruleset_fd));
4992 
4993         /* Checks lower layer. */
4994         for_each_path(lower_base_files, path_entry, i) {
4995                 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
4996                 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
4997         }
4998         for_each_path(lower_base_directories, path_entry, i) {
4999                 ASSERT_EQ(EACCES,
5000                           test_open(path_entry, O_RDONLY | O_DIRECTORY));
5001         }
5002         for_each_path(lower_sub_files, path_entry, i) {
5003                 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
5004                 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
5005         }
5006         /* Checks upper layer. */
5007         for_each_path(upper_base_files, path_entry, i) {
5008                 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
5009                 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
5010         }
5011         for_each_path(upper_base_directories, path_entry, i) {
5012                 ASSERT_EQ(EACCES,
5013                           test_open(path_entry, O_RDONLY | O_DIRECTORY));
5014         }
5015         for_each_path(upper_sub_files, path_entry, i) {
5016                 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
5017                 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
5018         }
5019         /*
5020          * Checks that access rights are independent from the lower and upper
5021          * layers: write access to upper files viewed through the merge point
5022          * is still allowed, and write access to lower file viewed (and copied)
5023          * through the merge point is still allowed.
5024          */
5025         for_each_path(merge_base_files, path_entry, i) {
5026                 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
5027         }
5028         for_each_path(merge_base_directories, path_entry, i) {
5029                 ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
5030         }
5031         for_each_path(merge_sub_files, path_entry, i) {
5032                 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
5033         }
5034 
5035         /* Sets rules on data directories (i.e. inside overlay scope). */
5036         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_data);
5037         ASSERT_LE(0, ruleset_fd);
5038         enforce_ruleset(_metadata, ruleset_fd);
5039         ASSERT_EQ(0, close(ruleset_fd));
5040 
5041         /* Checks merge. */
5042         for_each_path(merge_base_files, path_entry, i) {
5043                 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
5044         }
5045         for_each_path(merge_base_directories, path_entry, i) {
5046                 ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
5047         }
5048         for_each_path(merge_sub_files, path_entry, i) {
5049                 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
5050         }
5051 
5052         /* Same checks with tighter rules. */
5053         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3_subdirs);
5054         ASSERT_LE(0, ruleset_fd);
5055         enforce_ruleset(_metadata, ruleset_fd);
5056         ASSERT_EQ(0, close(ruleset_fd));
5057 
5058         /* Checks changes for lower layer. */
5059         for_each_path(lower_base_files, path_entry, i) {
5060                 ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
5061         }
5062         /* Checks changes for upper layer. */
5063         for_each_path(upper_base_files, path_entry, i) {
5064                 ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
5065         }
5066         /* Checks all merge accesses. */
5067         for_each_path(merge_base_files, path_entry, i) {
5068                 ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
5069         }
5070         for_each_path(merge_base_directories, path_entry, i) {
5071                 ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
5072         }
5073         for_each_path(merge_sub_files, path_entry, i) {
5074                 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
5075         }
5076 
5077         /* Sets rules directly on overlayed files. */
5078         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer4_files);
5079         ASSERT_LE(0, ruleset_fd);
5080         enforce_ruleset(_metadata, ruleset_fd);
5081         ASSERT_EQ(0, close(ruleset_fd));
5082 
5083         /* Checks unchanged accesses on lower layer. */
5084         for_each_path(lower_sub_files, path_entry, i) {
5085                 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
5086                 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
5087         }
5088         /* Checks unchanged accesses on upper layer. */
5089         for_each_path(upper_sub_files, path_entry, i) {
5090                 ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
5091                 ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
5092         }
5093         /* Checks all merge accesses. */
5094         for_each_path(merge_base_files, path_entry, i) {
5095                 ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
5096         }
5097         for_each_path(merge_base_directories, path_entry, i) {
5098                 ASSERT_EQ(EACCES,
5099                           test_open(path_entry, O_RDONLY | O_DIRECTORY));
5100         }
5101         for_each_path(merge_sub_files, path_entry, i) {
5102                 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
5103         }
5104 
5105         /* Only allowes access to the merge hierarchy. */
5106         ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer5_merge_only);
5107         ASSERT_LE(0, ruleset_fd);
5108         enforce_ruleset(_metadata, ruleset_fd);
5109         ASSERT_EQ(0, close(ruleset_fd));
5110 
5111         /* Checks new accesses on lower layer. */
5112         for_each_path(lower_sub_files, path_entry, i) {
5113                 ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
5114         }
5115         /* Checks new accesses on upper layer. */
5116         for_each_path(upper_sub_files, path_entry, i) {
5117                 ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
5118         }
5119         /* Checks all merge accesses. */
5120         for_each_path(merge_base_files, path_entry, i) {
5121                 ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
5122         }
5123         for_each_path(merge_base_directories, path_entry, i) {
5124                 ASSERT_EQ(EACCES,
5125                           test_open(path_entry, O_RDONLY | O_DIRECTORY));
5126         }
5127         for_each_path(merge_sub_files, path_entry, i) {
5128                 ASSERT_EQ(0, test_open(path_entry, O_RDWR));
5129         }
5130 }
5131 
5132 FIXTURE(layout3_fs)
5133 {
5134         bool has_created_dir;
5135         bool has_created_file;
5136         bool skip_test;
5137 };
5138 
5139 FIXTURE_VARIANT(layout3_fs)
5140 {
5141         const struct mnt_opt mnt;
5142         const char *const file_path;
5143         unsigned int cwd_fs_magic;
5144 };
5145 
5146 /* clang-format off */
5147 FIXTURE_VARIANT_ADD(layout3_fs, tmpfs) {
5148         /* clang-format on */
5149         .mnt = {
5150                 .type = "tmpfs",
5151                 .data = MNT_TMP_DATA,
5152         },
5153         .file_path = file1_s1d1,
5154 };
5155 
5156 FIXTURE_VARIANT_ADD(layout3_fs, ramfs) {
5157         .mnt = {
5158                 .type = "ramfs",
5159                 .data = "mode=700",
5160         },
5161         .file_path = TMP_DIR "/dir/file",
5162 };
5163 
5164 FIXTURE_VARIANT_ADD(layout3_fs, cgroup2) {
5165         .mnt = {
5166                 .type = "cgroup2",
5167         },
5168         .file_path = TMP_DIR "/test/cgroup.procs",
5169 };
5170 
5171 FIXTURE_VARIANT_ADD(layout3_fs, proc) {
5172         .mnt = {
5173                 .type = "proc",
5174         },
5175         .file_path = TMP_DIR "/self/status",
5176 };
5177 
5178 FIXTURE_VARIANT_ADD(layout3_fs, sysfs) {
5179         .mnt = {
5180                 .type = "sysfs",
5181         },
5182         .file_path = TMP_DIR "/kernel/notes",
5183 };
5184 
5185 FIXTURE_VARIANT_ADD(layout3_fs, hostfs) {
5186         .mnt = {
5187                 .source = TMP_DIR,
5188                 .flags = MS_BIND,
5189         },
5190         .file_path = TMP_DIR "/dir/file",
5191         .cwd_fs_magic = HOSTFS_SUPER_MAGIC,
5192 };
5193 
5194 static char *dirname_alloc(const char *path)
5195 {
5196         char *dup;
5197 
5198         if (!path)
5199                 return NULL;
5200 
5201         dup = strdup(path);
5202         if (!dup)
5203                 return NULL;
5204 
5205         return dirname(dup);
5206 }
5207 
5208 FIXTURE_SETUP(layout3_fs)
5209 {
5210         struct stat statbuf;
5211         char *dir_path = dirname_alloc(variant->file_path);
5212 
5213         if (!supports_filesystem(variant->mnt.type) ||
5214             !cwd_matches_fs(variant->cwd_fs_magic)) {
5215                 self->skip_test = true;
5216                 SKIP(return, "this filesystem is not supported (setup)");
5217         }
5218 
5219         prepare_layout_opt(_metadata, &variant->mnt);
5220 
5221         /* Creates directory when required. */
5222         if (stat(dir_path, &statbuf)) {
5223                 set_cap(_metadata, CAP_DAC_OVERRIDE);
5224                 EXPECT_EQ(0, mkdir(dir_path, 0700))
5225                 {
5226                         TH_LOG("Failed to create directory \"%s\": %s",
5227                                dir_path, strerror(errno));
5228                 }
5229                 self->has_created_dir = true;
5230                 clear_cap(_metadata, CAP_DAC_OVERRIDE);
5231         }
5232 
5233         /* Creates file when required. */
5234         if (stat(variant->file_path, &statbuf)) {
5235                 int fd;
5236 
5237                 set_cap(_metadata, CAP_DAC_OVERRIDE);
5238                 fd = creat(variant->file_path, 0600);
5239                 EXPECT_LE(0, fd)
5240                 {
5241                         TH_LOG("Failed to create file \"%s\": %s",
5242                                variant->file_path, strerror(errno));
5243                 }
5244                 EXPECT_EQ(0, close(fd));
5245                 self->has_created_file = true;
5246                 clear_cap(_metadata, CAP_DAC_OVERRIDE);
5247         }
5248 
5249         free(dir_path);
5250 }
5251 
5252 FIXTURE_TEARDOWN_PARENT(layout3_fs)
5253 {
5254         if (self->skip_test)
5255                 SKIP(return, "this filesystem is not supported (teardown)");
5256 
5257         if (self->has_created_file) {
5258                 set_cap(_metadata, CAP_DAC_OVERRIDE);
5259                 /*
5260                  * Don't check for error because the file might already
5261                  * have been removed (cf. release_inode test).
5262                  */
5263                 unlink(variant->file_path);
5264                 clear_cap(_metadata, CAP_DAC_OVERRIDE);
5265         }
5266 
5267         if (self->has_created_dir) {
5268                 char *dir_path = dirname_alloc(variant->file_path);
5269 
5270                 set_cap(_metadata, CAP_DAC_OVERRIDE);
5271                 /*
5272                  * Don't check for error because the directory might already
5273                  * have been removed (cf. release_inode test).
5274                  */
5275                 rmdir(dir_path);
5276                 clear_cap(_metadata, CAP_DAC_OVERRIDE);
5277                 free(dir_path);
5278         }
5279 
5280         cleanup_layout(_metadata);
5281 }
5282 
5283 static void layer3_fs_tag_inode(struct __test_metadata *const _metadata,
5284                                 FIXTURE_DATA(layout3_fs) * self,
5285                                 const FIXTURE_VARIANT(layout3_fs) * variant,
5286                                 const char *const rule_path)
5287 {
5288         const struct rule layer1_allow_read_file[] = {
5289                 {
5290                         .path = rule_path,
5291                         .access = LANDLOCK_ACCESS_FS_READ_FILE,
5292                 },
5293                 {},
5294         };
5295         const struct landlock_ruleset_attr layer2_deny_everything_attr = {
5296                 .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
5297         };
5298         const char *const dev_null_path = "/dev/null";
5299         int ruleset_fd;
5300 
5301         if (self->skip_test)
5302                 SKIP(return, "this filesystem is not supported (test)");
5303 
5304         /* Checks without Landlock. */
5305         EXPECT_EQ(0, test_open(dev_null_path, O_RDONLY | O_CLOEXEC));
5306         EXPECT_EQ(0, test_open(variant->file_path, O_RDONLY | O_CLOEXEC));
5307 
5308         ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
5309                                     layer1_allow_read_file);
5310         EXPECT_LE(0, ruleset_fd);
5311         enforce_ruleset(_metadata, ruleset_fd);
5312         EXPECT_EQ(0, close(ruleset_fd));
5313 
5314         EXPECT_EQ(EACCES, test_open(dev_null_path, O_RDONLY | O_CLOEXEC));
5315         EXPECT_EQ(0, test_open(variant->file_path, O_RDONLY | O_CLOEXEC));
5316 
5317         /* Forbids directory reading. */
5318         ruleset_fd =
5319                 landlock_create_ruleset(&layer2_deny_everything_attr,
5320                                         sizeof(layer2_deny_everything_attr), 0);
5321         EXPECT_LE(0, ruleset_fd);
5322         enforce_ruleset(_metadata, ruleset_fd);
5323         EXPECT_EQ(0, close(ruleset_fd));
5324 
5325         /* Checks with Landlock and forbidden access. */
5326         EXPECT_EQ(EACCES, test_open(dev_null_path, O_RDONLY | O_CLOEXEC));
5327         EXPECT_EQ(EACCES, test_open(variant->file_path, O_RDONLY | O_CLOEXEC));
5328 }
5329 
5330 /* Matrix of tests to check file hierarchy evaluation. */
5331 
5332 TEST_F_FORK(layout3_fs, tag_inode_dir_parent)
5333 {
5334         /* The current directory must not be the root for this test. */
5335         layer3_fs_tag_inode(_metadata, self, variant, ".");
5336 }
5337 
5338 TEST_F_FORK(layout3_fs, tag_inode_dir_mnt)
5339 {
5340         layer3_fs_tag_inode(_metadata, self, variant, TMP_DIR);
5341 }
5342 
5343 TEST_F_FORK(layout3_fs, tag_inode_dir_child)
5344 {
5345         char *dir_path = dirname_alloc(variant->file_path);
5346 
5347         layer3_fs_tag_inode(_metadata, self, variant, dir_path);
5348         free(dir_path);
5349 }
5350 
5351 TEST_F_FORK(layout3_fs, tag_inode_file)
5352 {
5353         layer3_fs_tag_inode(_metadata, self, variant, variant->file_path);
5354 }
5355 
5356 /* Light version of layout1.release_inodes */
5357 TEST_F_FORK(layout3_fs, release_inodes)
5358 {
5359         const struct rule layer1[] = {
5360                 {
5361                         .path = TMP_DIR,
5362                         .access = LANDLOCK_ACCESS_FS_READ_DIR,
5363                 },
5364                 {},
5365         };
5366         int ruleset_fd;
5367 
5368         if (self->skip_test)
5369                 SKIP(return, "this filesystem is not supported (test)");
5370 
5371         /* Clean up for the teardown to not fail. */
5372         if (self->has_created_file)
5373                 EXPECT_EQ(0, remove_path(variant->file_path));
5374 
5375         if (self->has_created_dir) {
5376                 char *dir_path = dirname_alloc(variant->file_path);
5377 
5378                 /* Don't check for error because of cgroup specificities. */
5379                 remove_path(dir_path);
5380                 free(dir_path);
5381         }
5382 
5383         ruleset_fd =
5384                 create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_DIR, layer1);
5385         ASSERT_LE(0, ruleset_fd);
5386 
5387         /* Unmount the filesystem while it is being used by a ruleset. */
5388         set_cap(_metadata, CAP_SYS_ADMIN);
5389         ASSERT_EQ(0, umount(TMP_DIR));
5390         clear_cap(_metadata, CAP_SYS_ADMIN);
5391 
5392         /* Replaces with a new mount point to simplify FIXTURE_TEARDOWN. */
5393         set_cap(_metadata, CAP_SYS_ADMIN);
5394         ASSERT_EQ(0, mount_opt(&mnt_tmp, TMP_DIR));
5395         clear_cap(_metadata, CAP_SYS_ADMIN);
5396 
5397         enforce_ruleset(_metadata, ruleset_fd);
5398         ASSERT_EQ(0, close(ruleset_fd));
5399 
5400         /* Checks that access to the new mount point is denied. */
5401         ASSERT_EQ(EACCES, test_open(TMP_DIR, O_RDONLY));
5402 }
5403 
5404 TEST_HARNESS_MAIN
5405 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php