Linux Audio

Check our new training course

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