cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fs_test.c (107935B)


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