All of lore.kernel.org
 help / color / mirror / Atom feed
From: Xiu Jianfeng <xiujianfeng@huawei.com>
To: <mic@digikod.net>, <paul@paul-moore.com>, <jmorris@namei.org>,
	<serge@hallyn.com>, <shuah@kernel.org>, <corbet@lwn.net>
Cc: <linux-security-module@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, <linux-kselftest@vger.kernel.org>,
	<linux-doc@vger.kernel.org>
Subject: [PATCH -next 3/5] landlock/selftests: add selftests for chmod and chown
Date: Mon, 22 Aug 2022 19:46:59 +0800	[thread overview]
Message-ID: <20220822114701.26975-4-xiujianfeng@huawei.com> (raw)
In-Reply-To: <20220822114701.26975-1-xiujianfeng@huawei.com>

Add the following simple testcases:
1. chmod/fchmod: remove S_IWUSR and restore S_IWUSR with or without
restriction.
2. chown/fchown: set original uid and gid with or without restriction,
because chown needs CAP_CHOWN and testcase framework don't have this
capability, setting original uid and gid is ok to cover landlock
function.

Signed-off-by: Xiu Jianfeng <xiujianfeng@huawei.com>
---
 tools/testing/selftests/landlock/fs_test.c | 228 +++++++++++++++++++++
 1 file changed, 228 insertions(+)

diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c
index 5b55b93b5570..f47b4ccd2b26 100644
--- a/tools/testing/selftests/landlock/fs_test.c
+++ b/tools/testing/selftests/landlock/fs_test.c
@@ -59,6 +59,9 @@ static const char file2_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f2";
 
 static const char dir_s3d1[] = TMP_DIR "/s3d1";
 static const char file1_s3d1[] = TMP_DIR "/s3d1/f1";
+static const char file2_s3d1[] = TMP_DIR "/s3d1/f2";
+static const char file3_s3d1[] = TMP_DIR "/s3d1/f3";
+
 /* dir_s3d2 is a mount point. */
 static const char dir_s3d2[] = TMP_DIR "/s3d1/s3d2";
 static const char dir_s3d3[] = TMP_DIR "/s3d1/s3d2/s3d3";
@@ -211,6 +214,8 @@ static void create_layout1(struct __test_metadata *const _metadata)
 	create_file(_metadata, file2_s2d3);
 
 	create_file(_metadata, file1_s3d1);
+	create_file(_metadata, file2_s3d1);
+	create_file(_metadata, file3_s3d1);
 	create_directory(_metadata, dir_s3d2);
 	set_cap(_metadata, CAP_SYS_ADMIN);
 	ASSERT_EQ(0, mount("tmp", dir_s3d2, "tmpfs", 0, "size=4m,mode=700"));
@@ -234,6 +239,8 @@ static void remove_layout1(struct __test_metadata *const _metadata)
 	EXPECT_EQ(0, remove_path(file1_s2d1));
 
 	EXPECT_EQ(0, remove_path(file1_s3d1));
+	EXPECT_EQ(0, remove_path(file2_s3d1));
+	EXPECT_EQ(0, remove_path(file3_s3d1));
 	EXPECT_EQ(0, remove_path(dir_s3d3));
 	set_cap(_metadata, CAP_SYS_ADMIN);
 	umount(dir_s3d2);
@@ -3272,6 +3279,227 @@ TEST_F_FORK(layout1, truncate)
 	EXPECT_EQ(0, test_creat(file_in_dir_w));
 }
 
+static int test_chmod(const char *path)
+{
+	int ret;
+	struct stat st;
+	mode_t mode;
+
+	ret = stat(path, &st);
+	if (ret < 0)
+		return errno;
+	/* save original mode in order to restore */
+	mode = st.st_mode & 0777;
+	/* remove S_IWUSR */
+	ret = chmod(path, mode & ~0200);
+	if (ret < 0)
+		return errno;
+	ret = stat(path, &st);
+	if (ret < 0)
+		return errno;
+	/* check if still has S_IWUSR */
+	if (st.st_mode & 0200)
+		return -EFAULT;
+	/* restore the original mode */
+	ret = chmod(path, mode);
+	if (ret < 0)
+		return errno;
+	return 0;
+}
+
+static int test_fchmod(const char *path)
+{
+	int ret, fd;
+	struct stat st;
+	mode_t mode;
+
+	ret = stat(path, &st);
+	if (ret < 0)
+		return errno;
+	/* save original mode in order to restore */
+	mode = st.st_mode & 0777;
+
+	fd = openat(AT_FDCWD, path, O_RDWR | O_CLOEXEC);
+	if (fd < 0)
+		return errno;
+	/* remove S_IWUSR */
+	ret = fchmod(fd, mode & ~0200);
+	if (ret < 0)
+		goto err;
+	ret = stat(path, &st);
+	if (ret < 0)
+		goto err;
+	/* check if still has S_IWUSR */
+	if (st.st_mode & 0200) {
+		ret = -1;
+		errno = -EFAULT;
+		goto err;
+	}
+	/* restore the original mode */
+	ret = fchmod(fd, mode);
+err:
+	if (close(fd) < 0)
+		return errno;
+	return ret ? errno : 0;
+}
+
+static int test_chown(const char *path)
+{
+	int ret;
+	struct stat st;
+
+	ret = stat(path, &st);
+	if (ret < 0)
+		return errno;
+	/*
+	 * chown needs CAP_CHOWN to modify uid and/or gid, however
+	 * there is no such capability when the testcases framework
+	 * setup, so just chown to original uid/gid, which can also
+	 * cover the function in landlock.
+	 */
+	ret = chown(path, st.st_uid, st.st_gid);
+	if (ret < 0)
+		return errno;
+	return 0;
+}
+
+static int test_fchown(const char *path)
+{
+	int ret, fd;
+	struct stat st;
+
+	ret = stat(path, &st);
+	if (ret < 0)
+		return errno;
+	fd = openat(AT_FDCWD, path, O_RDWR | O_CLOEXEC);
+	if (fd < 0)
+		return errno;
+	/*
+	 * fchown needs CAP_CHOWN to modify uid and/or gid, however
+	 * there is no such capability when the testcases framework
+	 * setup, so just fchown to original uid/gid, which can also
+	 * cover the function in landlock.
+	 */
+	ret = fchown(fd, st.st_uid, st.st_gid);
+	if (close(fd) < 0)
+		return errno;
+	return ret ? errno : 0;
+}
+
+TEST_F_FORK(layout1, unhandled_chmod)
+{
+	const struct rule rules[] = {
+		{
+			.path = file2_s3d1,
+			.access = LANDLOCK_ACCESS_FS_READ_FILE |
+				  LANDLOCK_ACCESS_FS_WRITE_FILE,
+		},
+		{
+			.path = file3_s3d1,
+			.access = LANDLOCK_ACCESS_FS_READ_FILE |
+				  LANDLOCK_ACCESS_FS_WRITE_FILE,
+		},
+		{},
+	};
+	const int ruleset_fd =
+		create_ruleset(_metadata, ACCESS_RW, rules);
+
+	ASSERT_LE(0, ruleset_fd);
+	enforce_ruleset(_metadata, ruleset_fd);
+	ASSERT_EQ(0, close(ruleset_fd));
+
+	ASSERT_EQ(0, test_chmod(file2_s3d1));
+	ASSERT_EQ(0, test_fchmod(file2_s3d1));
+	ASSERT_EQ(0, test_chmod(file3_s3d1));
+	ASSERT_EQ(0, test_chmod(dir_s3d1));
+}
+
+TEST_F_FORK(layout1, chmod)
+{
+	const struct rule rules[] = {
+		{
+			.path = file2_s3d1,
+			.access = LANDLOCK_ACCESS_FS_READ_FILE |
+				  LANDLOCK_ACCESS_FS_WRITE_FILE |
+				  LANDLOCK_ACCESS_FS_CHMOD,
+		},
+		{
+			.path = file3_s3d1,
+			.access = LANDLOCK_ACCESS_FS_READ_FILE |
+				  LANDLOCK_ACCESS_FS_WRITE_FILE,
+		},
+		{},
+	};
+	const int ruleset_fd =
+		create_ruleset(_metadata, ACCESS_RW | LANDLOCK_ACCESS_FS_CHMOD, rules);
+
+	ASSERT_LE(0, ruleset_fd);
+	enforce_ruleset(_metadata, ruleset_fd);
+	ASSERT_EQ(0, close(ruleset_fd));
+
+	ASSERT_EQ(0, test_chmod(file2_s3d1));
+	ASSERT_EQ(0, test_fchmod(file2_s3d1));
+	ASSERT_EQ(EACCES, test_chmod(file3_s3d1));
+	ASSERT_EQ(EACCES, test_chmod(dir_s3d1));
+}
+
+TEST_F_FORK(layout1, no_chown)
+{
+	const struct rule rules[] = {
+		{
+			.path = file2_s3d1,
+			.access = LANDLOCK_ACCESS_FS_READ_FILE |
+				  LANDLOCK_ACCESS_FS_WRITE_FILE,
+		},
+		{
+			.path = file3_s3d1,
+			.access = LANDLOCK_ACCESS_FS_READ_FILE |
+				  LANDLOCK_ACCESS_FS_WRITE_FILE,
+		},
+		{},
+	};
+	const int ruleset_fd =
+		create_ruleset(_metadata, ACCESS_RW, rules);
+
+	ASSERT_LE(0, ruleset_fd);
+	enforce_ruleset(_metadata, ruleset_fd);
+	ASSERT_EQ(0, close(ruleset_fd));
+
+	ASSERT_EQ(0, test_chown(file2_s3d1));
+	ASSERT_EQ(0, test_fchown(file2_s3d1));
+	ASSERT_EQ(0, test_chown(file3_s3d1));
+	ASSERT_EQ(0, test_chown(dir_s3d1));
+}
+
+TEST_F_FORK(layout1, chown)
+{
+	const struct rule rules[] = {
+		{
+			.path = file2_s3d1,
+			.access = LANDLOCK_ACCESS_FS_READ_FILE |
+				  LANDLOCK_ACCESS_FS_WRITE_FILE |
+				  LANDLOCK_ACCESS_FS_CHOWN,
+		},
+		{
+			.path = file3_s3d1,
+			.access = LANDLOCK_ACCESS_FS_READ_FILE |
+				  LANDLOCK_ACCESS_FS_WRITE_FILE,
+		},
+		{},
+	};
+	const int ruleset_fd =
+		create_ruleset(_metadata, ACCESS_RW | LANDLOCK_ACCESS_FS_CHOWN, rules);
+
+	ASSERT_LE(0, ruleset_fd);
+	enforce_ruleset(_metadata, ruleset_fd);
+	ASSERT_EQ(0, close(ruleset_fd));
+
+	ASSERT_EQ(0, test_chown(file2_s3d1));
+	ASSERT_EQ(0, test_fchown(file2_s3d1));
+	ASSERT_EQ(EACCES, test_chown(file3_s3d1));
+	ASSERT_EQ(EACCES, test_chown(dir_s3d1));
+}
+
 /* clang-format off */
 FIXTURE(layout1_bind) {};
 /* clang-format on */
-- 
2.17.1


  parent reply	other threads:[~2022-08-22 11:51 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-22 11:46 [PATCH -next 0/5] landlock: add chmod and chown support Xiu Jianfeng
2022-08-22 11:46 ` [PATCH -next 1/5] landlock: expand access_mask_t to u32 type Xiu Jianfeng
2022-08-22 11:46 ` [PATCH -next 2/5] landlock: add chmod and chown support Xiu Jianfeng
2022-08-22 18:25   ` Günther Noack
2022-08-22 21:07     ` Mickaël Salaün
2022-08-23 12:50       ` xiujianfeng
2022-08-24 11:44         ` Mickaël Salaün
2022-08-26  8:36           ` xiujianfeng
2022-08-26  9:36             ` Mickaël Salaün
2022-08-26 11:14               ` xiujianfeng
2022-08-26 11:32                 ` Mickaël Salaün
2022-08-22 11:46 ` Xiu Jianfeng [this message]
2022-08-22 18:53   ` [PATCH -next 3/5] landlock/selftests: add selftests for chmod and chown Günther Noack
2022-08-22 21:28     ` Mickaël Salaün
2022-08-24  8:27     ` xiujianfeng
2022-08-22 19:26   ` Günther Noack
2022-08-27 11:14     ` xiujianfeng
2022-08-27 16:57       ` Günther Noack
2022-08-22 11:47 ` [PATCH -next 4/5] landlock/samples: add chmod and chown support Xiu Jianfeng
2022-08-22 11:47 ` [PATCH -next 5/5] landlock: update chmod and chown support in document Xiu Jianfeng
2022-08-22 21:25   ` Mickaël Salaün
2022-08-22 19:17 ` [PATCH -next 0/5] landlock: add chmod and chown support Günther Noack
2022-08-22 19:35   ` Casey Schaufler
2022-08-22 21:18     ` Günther Noack
2022-08-22 21:21       ` Mickaël Salaün
2022-08-22 21:53         ` Casey Schaufler
2022-08-23 17:10           ` Mickaël Salaün

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220822114701.26975-4-xiujianfeng@huawei.com \
    --to=xiujianfeng@huawei.com \
    --cc=corbet@lwn.net \
    --cc=jmorris@namei.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=mic@digikod.net \
    --cc=paul@paul-moore.com \
    --cc=serge@hallyn.com \
    --cc=shuah@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.