All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/6] idmapped-mount: split setgid test from test-core
@ 2022-04-07 12:09 Yang Xu
  2022-04-07 12:09 ` [PATCH v2 2/6] idmapped-mounts: Add mknodat operation in setgid test Yang Xu
                   ` (5 more replies)
  0 siblings, 6 replies; 19+ messages in thread
From: Yang Xu @ 2022-04-07 12:09 UTC (permalink / raw)
  To: david, brauner, djwong; +Cc: linux-fsdevel, fstests, Yang Xu

Since we plan to increase setgid test covertage, it will find new bug
, so add a new test group test-setgid is better.

Also add a new test case to test test-setgid instead of miss it.

Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
---
 src/idmapped-mounts/idmapped-mounts.c | 19 +++++++++++++++----
 tests/generic/999                     | 26 ++++++++++++++++++++++++++
 tests/generic/999.out                 |  2 ++
 3 files changed, 43 insertions(+), 4 deletions(-)
 create mode 100755 tests/generic/999
 create mode 100644 tests/generic/999.out

diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
index 4cf6c3bb..dff6820f 100644
--- a/src/idmapped-mounts/idmapped-mounts.c
+++ b/src/idmapped-mounts/idmapped-mounts.c
@@ -13809,6 +13809,7 @@ static void usage(void)
 	fprintf(stderr, "--test-nested-userns                Run nested userns idmapped mount testsuite\n");
 	fprintf(stderr, "--test-btrfs                        Run btrfs specific idmapped mount testsuite\n");
 	fprintf(stderr, "--test-setattr-fix-968219708108     Run setattr regression tests\n");
+	fprintf(stderr, "--test-setgid                       Run setgid create tests\n");
 
 	_exit(EXIT_SUCCESS);
 }
@@ -13826,6 +13827,7 @@ static const struct option longopts[] = {
 	{"test-nested-userns",			no_argument,		0,	'n'},
 	{"test-btrfs",				no_argument,		0,	'b'},
 	{"test-setattr-fix-968219708108",	no_argument,		0,	'i'},
+	{"test-setgid",				no_argument,		0,	'j'},
 	{NULL,					0,			0,	  0},
 };
 
@@ -13866,9 +13868,6 @@ struct t_idmapped_mounts {
 	{ setattr_truncate,						false,	"setattr truncate",										},
 	{ setattr_truncate_idmapped,					true,	"setattr truncate on idmapped mounts",								},
 	{ setattr_truncate_idmapped_in_userns,				true,	"setattr truncate on idmapped mounts in user namespace",					},
-	{ setgid_create,						false,	"create operations in directories with setgid bit set",						},
-	{ setgid_create_idmapped,					true,	"create operations in directories with setgid bit set on idmapped mounts",			},
-	{ setgid_create_idmapped_in_userns,				true,	"create operations in directories with setgid bit set on idmapped mounts in user namespace",	},
 	{ setid_binaries,						false,	"setid binaries on regular mounts",								},
 	{ setid_binaries_idmapped_mounts,				true,	"setid binaries on idmapped mounts",								},
 	{ setid_binaries_idmapped_mounts_in_userns,			true,	"setid binaries on idmapped mounts in user namespace",						},
@@ -13923,6 +13922,12 @@ struct t_idmapped_mounts t_setattr_fix_968219708108[] = {
 	{ setattr_fix_968219708108,					true,	"test that setattr works correctly",								},
 };
 
+struct t_idmapped_mounts t_setgid[] = {
+	{ setgid_create,						false,	"create operations in directories with setgid bit set",						},
+	{ setgid_create_idmapped,					true,	"create operations in directories with setgid bit set on idmapped mounts",			},
+	{ setgid_create_idmapped_in_userns,				true,	"create operations in directories with setgid bit set on idmapped mounts in user namespace",	},
+};
+
 static bool run_test(struct t_idmapped_mounts suite[], size_t suite_size)
 {
 	int i;
@@ -14000,7 +14005,7 @@ int main(int argc, char *argv[])
 	int index = 0;
 	bool supported = false, test_btrfs = false, test_core = false,
 	     test_fscaps_regression = false, test_nested_userns = false,
-	     test_setattr_fix_968219708108 = false;
+	     test_setattr_fix_968219708108 = false, test_setgid = false;
 
 	while ((ret = getopt_long_only(argc, argv, "", longopts, &index)) != -1) {
 		switch (ret) {
@@ -14037,6 +14042,9 @@ int main(int argc, char *argv[])
 		case 'i':
 			test_setattr_fix_968219708108 = true;
 			break;
+		case 'j':
+			test_setgid = true;
+			break;
 		case 'h':
 			/* fallthrough */
 		default:
@@ -14106,6 +14114,9 @@ int main(int argc, char *argv[])
 		      ARRAY_SIZE(t_setattr_fix_968219708108)))
 		goto out;
 
+	if (test_setgid && !run_test(t_setgid, ARRAY_SIZE(t_setgid)))
+		goto out;
+
 	fret = EXIT_SUCCESS;
 
 out:
diff --git a/tests/generic/999 b/tests/generic/999
new file mode 100755
index 00000000..46a34804
--- /dev/null
+++ b/tests/generic/999
@@ -0,0 +1,26 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2022 FUJITSU LIMITED. All rights reserved
+#
+# FS QA Test 999
+#
+# Test that setgid bit behave correctly.
+#
+. ./common/preamble
+_begin_fstest auto quick cap idmapped mount perms rw
+
+# Import common functions.
+. ./common/filter
+
+# real QA test starts here
+
+_supported_fs generic
+_require_test
+
+echo "Silence is golden"
+
+$here/src/idmapped-mounts/idmapped-mounts --test-setgid --device "$TEST_DEV" \
+	--mount "$TEST_DIR" --fstype "$FSTYP"
+
+status=$?
+exit
diff --git a/tests/generic/999.out b/tests/generic/999.out
new file mode 100644
index 00000000..3b276ca8
--- /dev/null
+++ b/tests/generic/999.out
@@ -0,0 +1,2 @@
+QA output created by 999
+Silence is golden
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 2/6] idmapped-mounts: Add mknodat operation in setgid test
  2022-04-07 12:09 [PATCH v2 1/6] idmapped-mount: split setgid test from test-core Yang Xu
@ 2022-04-07 12:09 ` Yang Xu
  2022-04-07 13:40   ` Christian Brauner
  2022-04-07 12:09 ` [PATCH v2 3/6] idmapped-mounts: Reset errno to zero after detect fs_allow_idmap Yang Xu
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 19+ messages in thread
From: Yang Xu @ 2022-04-07 12:09 UTC (permalink / raw)
  To: david, brauner, djwong; +Cc: linux-fsdevel, fstests, Yang Xu

Since mknodat can create file, we should also check whether strip S_ISGID.
Also add new helper caps_down_fsetid to drop CAP_FSETID because strip S_ISGID
depond on this cap and keep other cap(ie CAP_MKNOD) because create character
device needs it when using mknod.

Only test mknodat with character device in setgid_create function because the another
two functions test mknodat with whiteout device.

Since kernel commit a3c751a50 ("vfs: allow unprivileged whiteout creation") in
v5.8-rc1, we can create whiteout device in userns test. Since kernel 5.12, mount_setattr
and MOUNT_ATTR_IDMAP was supported, we don't need to detect kernel whether allow
unprivileged whiteout creation. Using fs_allow_idmap as a proxy is safe.

Tested-by: Christian Brauner (Microsoft)<brauner@kernel.org>
Reviewed-by: Christian Brauner (Microsoft)<brauner@kernel.org>
Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
---
 src/idmapped-mounts/idmapped-mounts.c | 190 +++++++++++++++++++++++++-
 1 file changed, 183 insertions(+), 7 deletions(-)

diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
index dff6820f..e8a856de 100644
--- a/src/idmapped-mounts/idmapped-mounts.c
+++ b/src/idmapped-mounts/idmapped-mounts.c
@@ -241,6 +241,34 @@ static inline bool caps_supported(void)
 	return ret;
 }
 
+static int caps_down_fsetid(void)
+{
+	bool fret = false;
+#ifdef HAVE_SYS_CAPABILITY_H
+	cap_t caps = NULL;
+	cap_value_t cap = CAP_FSETID;
+	int ret = -1;
+
+	caps = cap_get_proc();
+	if (!caps)
+		goto out;
+
+	ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, 0);
+	if (ret)
+		goto out;
+
+	ret = cap_set_proc(caps);
+	if (ret)
+		goto out;
+
+	fret = true;
+
+out:
+	cap_free(caps);
+#endif
+	return fret;
+}
+
 /* caps_down - lower all effective caps */
 static int caps_down(void)
 {
@@ -7805,8 +7833,8 @@ out_unmap:
 #endif /* HAVE_LIBURING_H */
 
 /* The following tests are concerned with setgid inheritance. These can be
- * filesystem type specific. For xfs, if a new file or directory is created
- * within a setgid directory and irix_sgid_inhiert is set then inherit the
+ * filesystem type specific. For xfs, if a new file or directory or node is
+ * created within a setgid directory and irix_sgid_inhiert is set then inherit the
  * setgid bit if the caller is in the group of the directory.
  */
 static int setgid_create(void)
@@ -7863,15 +7891,41 @@ static int setgid_create(void)
 		if (!is_setgid(t_dir1_fd, DIR1, 0))
 			die("failure: is_setgid");
 
+		/* create a special file via mknodat() vfs_create */
+		if (mknodat(t_dir1_fd, DIR1 "/" FILE1, S_IFREG | S_ISGID | 0755, 0))
+			die("failure: mknodat");
+
+		if (!is_setgid(t_dir1_fd, DIR1 "/" FILE1, 0))
+			die("failure: is_setgid");
+
+		/* create a character device via mknodat() vfs_mknod */
+		if (mknodat(t_dir1_fd, CHRDEV1, S_IFCHR | S_ISGID | 0755, makedev(5, 1)))
+			die("failure: mknodat");
+
+		if (!is_setgid(t_dir1_fd, CHRDEV1, 0))
+			die("failure: is_setgid");
+
 		if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0))
 			die("failure: check ownership");
 
+		if (!expected_uid_gid(t_dir1_fd, DIR1 "/" FILE1, 0, 0, 0))
+			die("failure: check ownership");
+
+		if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0))
+			die("failure: check ownership");
+
 		if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0))
 			die("failure: check ownership");
 
 		if (unlinkat(t_dir1_fd, FILE1, 0))
 			die("failure: delete");
 
+		if (unlinkat(t_dir1_fd, DIR1 "/" FILE1, 0))
+			die("failure: delete");
+
+		if (unlinkat(t_dir1_fd, CHRDEV1, 0))
+			die("failure: delete");
+
 		if (unlinkat(t_dir1_fd, DIR1, AT_REMOVEDIR))
 			die("failure: delete");
 
@@ -7889,8 +7943,8 @@ static int setgid_create(void)
 		if (!switch_ids(0, 10000))
 			die("failure: switch_ids");
 
-		if (!caps_down())
-			die("failure: caps_down");
+		if (!caps_down_fsetid())
+			die("failure: caps_down_fsetid");
 
 		/* create regular file via open() */
 		file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
@@ -7917,6 +7971,19 @@ static int setgid_create(void)
 				die("failure: is_setgid");
 		}
 
+		/* create a special file via mknodat() vfs_create */
+		if (mknodat(t_dir1_fd, DIR1 "/" FILE1, S_IFREG | S_ISGID | 0755, 0))
+			die("failure: mknodat");
+
+		if (is_setgid(t_dir1_fd, DIR1 "/" FILE1, 0))
+			die("failure: is_setgid");
+
+		/* create a character device via mknodat() vfs_mknod */
+		if (mknodat(t_dir1_fd, CHRDEV1, S_IFCHR | S_ISGID | 0755, makedev(5, 1)))
+			die("failure: mknodat");
+
+		if (is_setgid(t_dir1_fd, CHRDEV1, 0))
+			die("failure: is_setgid");
 		/*
 		 * In setgid directories newly created files always inherit the
 		 * gid from the parent directory. Verify that the file is owned
@@ -7933,6 +8000,24 @@ static int setgid_create(void)
 		if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0))
 			die("failure: check ownership");
 
+		if (!expected_uid_gid(t_dir1_fd, DIR1 "/" FILE1, 0, 0, 0))
+			die("failure: check ownership");
+
+		if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0))
+			die("failure: check ownership");
+
+		if (unlinkat(t_dir1_fd, FILE1, 0))
+			die("failure: delete");
+
+		if (unlinkat(t_dir1_fd, DIR1 "/" FILE1, 0))
+			die("failure: delete");
+
+		if (unlinkat(t_dir1_fd, CHRDEV1, 0))
+			die("failure: delete");
+
+		if (unlinkat(t_dir1_fd, DIR1, AT_REMOVEDIR))
+			die("failure: delete");
+
 		exit(EXIT_SUCCESS);
 	}
 	if (wait_for_pid(pid))
@@ -8051,6 +8136,12 @@ static int setgid_create_idmapped(void)
 		if (!expected_uid_gid(open_tree_fd, DIR1, 0, 10000, 10000))
 			die("failure: check ownership");
 
+		if (unlinkat(open_tree_fd, FILE1, 0))
+			die("failure: delete");
+
+		if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
+			die("failure: delete");
+
 		exit(EXIT_SUCCESS);
 	}
 	if (wait_for_pid(pid))
@@ -8149,15 +8240,37 @@ static int setgid_create_idmapped_in_userns(void)
 		if (!is_setgid(open_tree_fd, DIR1, 0))
 			die("failure: is_setgid");
 
+		/* create a special file via mknodat() vfs_create */
+		if (mknodat(open_tree_fd, DIR1 "/" FILE1, S_IFREG | S_ISGID | 755, 0))
+			die("failure: mknodat");
+
+		if (!is_setgid(open_tree_fd, DIR1 "/" FILE1, 0))
+			die("failure: is_setgid");
+
+		if (mknodat(open_tree_fd, CHRDEV1, S_IFCHR | S_ISGID | 0755, 0))
+			die("failure: mknodat");
+
+		if (!is_setgid(open_tree_fd, CHRDEV1, 0))
+			die("failure: is_setgid");
+
 		if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
 			die("failure: check ownership");
 
 		if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
 			die("failure: check ownership");
 
+		if (!expected_uid_gid(open_tree_fd, DIR1 "/" FILE1, 0, 0, 0))
+			die("failure: check ownership");
+
+		if (!expected_uid_gid(open_tree_fd, CHRDEV1, 0, 0, 0))
+			die("failure: check ownership");
+
 		if (unlinkat(open_tree_fd, FILE1, 0))
 			die("failure: delete");
-
+		if (unlinkat(open_tree_fd, DIR1 "/" FILE1, 0))
+			die("failure: delete");
+		if (unlinkat(open_tree_fd, CHRDEV1, 0))
+			die("failure: delete");
 		if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
 			die("failure: delete");
 
@@ -8190,9 +8303,12 @@ static int setgid_create_idmapped_in_userns(void)
 			exit(EXIT_SUCCESS);
 		}
 
-		if (!switch_userns(attr.userns_fd, 0, 0, true))
+		if (!switch_userns(attr.userns_fd, 0, 0, false))
 			die("failure: switch_userns");
 
+		if (!caps_down_fsetid())
+			die("failure: caps_down_fsetid");
+
 		/* create regular file via open() */
 		file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
 		if (file1_fd < 0)
@@ -8218,6 +8334,20 @@ static int setgid_create_idmapped_in_userns(void)
 				die("failure: is_setgid");
 		}
 
+		/* create a special file via mknodat() vfs_create */
+		if (mknodat(open_tree_fd, DIR1 "/" FILE1, S_IFREG | S_ISGID | 0755, 0))
+			die("failure: mknodat");
+
+		if (is_setgid(open_tree_fd, DIR1 "/" FILE1, 0))
+			die("failure: is_setgid");
+
+		/* create a special file via mknodat() vfs_create */
+		if (mknodat(open_tree_fd, CHRDEV1, S_IFCHR | S_ISGID | 0755, 0))
+			die("failure: mknodat");
+
+		if (is_setgid(open_tree_fd, CHRDEV1, 0))
+			die("failure: is_setgid");
+
 		/*
 		 * In setgid directories newly created files always inherit the
 		 * gid from the parent directory. Verify that the file is owned
@@ -8234,9 +8364,21 @@ static int setgid_create_idmapped_in_userns(void)
 		if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 1000))
 			die("failure: check ownership");
 
+		if (!expected_uid_gid(open_tree_fd, DIR1 "/" FILE1, 0, 0, 1000))
+			die("failure: check ownership");
+
+		if (!expected_uid_gid(open_tree_fd, CHRDEV1, 0, 0, 1000))
+			die("failure: check ownership");
+
 		if (unlinkat(open_tree_fd, FILE1, 0))
 			die("failure: delete");
 
+		if (unlinkat(open_tree_fd, DIR1 "/" FILE1, 0))
+			die("failure: delete");
+
+		if (unlinkat(open_tree_fd, CHRDEV1, 0))
+			die("failure: delete");
+
 		if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
 			die("failure: delete");
 
@@ -8266,9 +8408,12 @@ static int setgid_create_idmapped_in_userns(void)
 			exit(EXIT_SUCCESS);
 		}
 
-		if (!switch_userns(attr.userns_fd, 0, 1000, true))
+		if (!switch_userns(attr.userns_fd, 0, 1000, false))
 			die("failure: switch_userns");
 
+		if (!caps_down_fsetid())
+			die("failure: caps_down_fsetid");
+
 		/* create regular file via open() */
 		file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
 		if (file1_fd < 0)
@@ -8295,12 +8440,43 @@ static int setgid_create_idmapped_in_userns(void)
 				die("failure: is_setgid");
 		}
 
+		/* create a special file via mknodat() vfs_create */
+		if (mknodat(open_tree_fd, DIR1 "/" FILE1, S_IFREG | S_ISGID | 0755, 0))
+			die("failure: mknodat");
+
+		if (is_setgid(open_tree_fd, DIR1 "/" FILE1, 0))
+			die("failure: is_setgid");
+
+		if (mknodat(open_tree_fd, CHRDEV1, S_IFCHR | S_ISGID | 0755, 0))
+			die("failure: mknodat");
+
+		if (is_setgid(open_tree_fd, CHRDEV1, 0))
+			die("failure: is_setgid");
+
 		if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
 			die("failure: check ownership");
 
 		if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
 			die("failure: check ownership");
 
+		if (!expected_uid_gid(open_tree_fd, DIR1 "/" FILE1, 0, 0, 0))
+			die("failure: check ownership");
+
+		if (!expected_uid_gid(open_tree_fd, CHRDEV1, 0, 0, 0))
+			die("failure: check ownership");
+
+		if (unlinkat(open_tree_fd, FILE1, 0))
+			die("failure: delete");
+
+		if (unlinkat(open_tree_fd, DIR1 "/" FILE1, 0))
+			die("failure: delete");
+
+		if (unlinkat(open_tree_fd, CHRDEV1, 0))
+			die("failure: delete");
+
+		if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
+			die("failure: delete");
+
 		exit(EXIT_SUCCESS);
 	}
 	if (wait_for_pid(pid))
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 3/6] idmapped-mounts: Reset errno to zero after detect fs_allow_idmap
  2022-04-07 12:09 [PATCH v2 1/6] idmapped-mount: split setgid test from test-core Yang Xu
  2022-04-07 12:09 ` [PATCH v2 2/6] idmapped-mounts: Add mknodat operation in setgid test Yang Xu
@ 2022-04-07 12:09 ` Yang Xu
  2022-04-07 12:59   ` Christian Brauner
  2022-04-07 12:09 ` [PATCH v2 4/6] idmapped-mounts: Add umask(S_IXGRP) wrapper for setgid_create* cases Yang Xu
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 19+ messages in thread
From: Yang Xu @ 2022-04-07 12:09 UTC (permalink / raw)
  To: david, brauner, djwong; +Cc: linux-fsdevel, fstests, Yang Xu

If we run case on old kernel that doesn't support mount_setattr and
then fail on our own function before call is_setgid/is_setuid function
to reset errno, run_test will print "Function not implement" error.

Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
---
 src/idmapped-mounts/idmapped-mounts.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
index e8a856de..d2638c64 100644
--- a/src/idmapped-mounts/idmapped-mounts.c
+++ b/src/idmapped-mounts/idmapped-mounts.c
@@ -14254,6 +14254,8 @@ int main(int argc, char *argv[])
 		die("failed to open %s", t_mountpoint_scratch);
 
 	t_fs_allow_idmap = fs_allow_idmap();
+	/*Don't copy ENOSYS errno to child proecss on older kernel*/
+	errno = 0;
 	if (supported) {
 		/*
 		 * Caller just wants to know whether the filesystem we're on
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 4/6] idmapped-mounts: Add umask(S_IXGRP) wrapper for setgid_create* cases
  2022-04-07 12:09 [PATCH v2 1/6] idmapped-mount: split setgid test from test-core Yang Xu
  2022-04-07 12:09 ` [PATCH v2 2/6] idmapped-mounts: Add mknodat operation in setgid test Yang Xu
  2022-04-07 12:09 ` [PATCH v2 3/6] idmapped-mounts: Reset errno to zero after detect fs_allow_idmap Yang Xu
@ 2022-04-07 12:09 ` Yang Xu
  2022-04-07 15:12   ` Christian Brauner
  2022-04-07 12:09 ` [PATCH v2 5/6] idmapped-mounts: Add setfacl(S_IXGRP) " Yang Xu
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 19+ messages in thread
From: Yang Xu @ 2022-04-07 12:09 UTC (permalink / raw)
  To: david, brauner, djwong; +Cc: linux-fsdevel, fstests, Yang Xu

Since stipping S_SIGID should check S_IXGRP, so umask it to check whether
works well.

Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
---
 src/idmapped-mounts/idmapped-mounts.c | 66 +++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
index d2638c64..d6769f08 100644
--- a/src/idmapped-mounts/idmapped-mounts.c
+++ b/src/idmapped-mounts/idmapped-mounts.c
@@ -8031,6 +8031,27 @@ out:
 	return fret;
 }
 
+static int setgid_create_umask(void)
+{
+	pid_t pid;
+
+	umask(S_IXGRP);
+	pid = fork();
+	if (pid < 0)
+		die("failure: fork");
+
+	if (pid == 0) {
+		if (setgid_create())
+			die("failure: setgid");
+		exit(EXIT_SUCCESS);
+	}
+
+	if (wait_for_pid(pid))
+		return -1;
+	else
+		return 0;
+}
+
 static int setgid_create_idmapped(void)
 {
 	int fret = -1;
@@ -8157,6 +8178,27 @@ out:
 	return fret;
 }
 
+static int setgid_create_idmapped_umask(void)
+{
+	pid_t pid;
+
+	umask(S_IXGRP);
+	pid = fork();
+	if (pid < 0)
+		die("failure: fork");
+
+	if (pid == 0) {
+		if (setgid_create_idmapped())
+			die("failure: setgid");
+		exit(EXIT_SUCCESS);
+	}
+
+	if (wait_for_pid(pid))
+		return -1;
+	else
+		return 0;
+}
+
 static int setgid_create_idmapped_in_userns(void)
 {
 	int fret = -1;
@@ -8492,6 +8534,27 @@ out:
 	return fret;
 }
 
+static int setgid_create_idmapped_in_userns_umask(void)
+{
+	pid_t pid;
+
+	umask(S_IXGRP);
+	pid = fork();
+	if (pid < 0)
+		die("failure: fork");
+
+	if (pid == 0) {
+		if (setgid_create_idmapped_in_userns())
+			die("failure: setgid");
+		exit(EXIT_SUCCESS);
+	}
+
+	if (wait_for_pid(pid))
+		return -1;
+	else
+		return 0;
+}
+
 #define PTR_TO_INT(p) ((int)((intptr_t)(p)))
 #define INT_TO_PTR(u) ((void *)((intptr_t)(u)))
 
@@ -14100,8 +14163,11 @@ struct t_idmapped_mounts t_setattr_fix_968219708108[] = {
 
 struct t_idmapped_mounts t_setgid[] = {
 	{ setgid_create,						false,	"create operations in directories with setgid bit set",						},
+	{ setgid_create_umask,						false,	"create operations in directories with setgid bit set by umask(S_IXGRP)",			},
 	{ setgid_create_idmapped,					true,	"create operations in directories with setgid bit set on idmapped mounts",			},
+	{ setgid_create_idmapped_umask,					true,	"create operations in directories with setgid bit set on idmapped mounts by umask(S_IXGRP)",	},
 	{ setgid_create_idmapped_in_userns,				true,	"create operations in directories with setgid bit set on idmapped mounts in user namespace",	},
+	{ setgid_create_idmapped_in_userns_umask,			true,   "create operations in directories with setgid bit set on idmapped mounts in user namespace by umask(S_IXGRP)",	},
 };
 
 static bool run_test(struct t_idmapped_mounts suite[], size_t suite_size)
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 5/6] idmapped-mounts: Add setfacl(S_IXGRP) wrapper for setgid_create* cases
  2022-04-07 12:09 [PATCH v2 1/6] idmapped-mount: split setgid test from test-core Yang Xu
                   ` (2 preceding siblings ...)
  2022-04-07 12:09 ` [PATCH v2 4/6] idmapped-mounts: Add umask(S_IXGRP) wrapper for setgid_create* cases Yang Xu
@ 2022-04-07 12:09 ` Yang Xu
  2022-04-07 12:09 ` [PATCH v2 6/6] idmapped-mounts: Add open with O_TMPFILE operation in setgid test Yang Xu
  2022-04-07 12:55 ` [PATCH v2 1/6] idmapped-mount: split setgid test from test-core Christian Brauner
  5 siblings, 0 replies; 19+ messages in thread
From: Yang Xu @ 2022-04-07 12:09 UTC (permalink / raw)
  To: david, brauner, djwong; +Cc: linux-fsdevel, fstests, Yang Xu

Since stipping S_SIGID should check S_IXGRP, so using sefacl to umask it to
check whether works well.

Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
---
 src/idmapped-mounts/idmapped-mounts.c | 75 +++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
index d6769f08..8f292228 100644
--- a/src/idmapped-mounts/idmapped-mounts.c
+++ b/src/idmapped-mounts/idmapped-mounts.c
@@ -8052,6 +8052,30 @@ static int setgid_create_umask(void)
 		return 0;
 }
 
+static int setgid_create_acl(void)
+{
+	pid_t pid;
+
+	snprintf(t_buf, sizeof(t_buf), "setfacl -d -m u::rwx,g::rw,o::rwx %s/%s", t_mountpoint, T_DIR1);
+	if (system(t_buf))
+		die("failure: system");
+
+	pid = fork();
+	if (pid < 0)
+		die("failure: fork");
+
+	if (pid == 0) {
+		if (setgid_create())
+			die("failure: setgid");
+		exit(EXIT_SUCCESS);
+	}
+
+	if (wait_for_pid(pid))
+		return -1;
+	else
+		return 0;
+}
+
 static int setgid_create_idmapped(void)
 {
 	int fret = -1;
@@ -8199,6 +8223,30 @@ static int setgid_create_idmapped_umask(void)
 		return 0;
 }
 
+static int setgid_create_idmapped_acl(void)
+{
+	pid_t pid;
+
+	snprintf(t_buf, sizeof(t_buf), "setfacl -d -m u::rwx,g::rw,o::rwx %s/%s", t_mountpoint, T_DIR1);
+	if (system(t_buf))
+		die("failure: system");
+
+	pid = fork();
+	if (pid < 0)
+		die("failure: fork");
+
+	if (pid == 0) {
+		if (setgid_create_idmapped())
+			die("failure: setgid");
+		exit(EXIT_SUCCESS);
+	}
+
+	if (wait_for_pid(pid))
+		return -1;
+	else
+		return 0;
+}
+
 static int setgid_create_idmapped_in_userns(void)
 {
 	int fret = -1;
@@ -8555,6 +8603,30 @@ static int setgid_create_idmapped_in_userns_umask(void)
 		return 0;
 }
 
+static int setgid_create_idmapped_in_userns_acl(void)
+{
+	pid_t pid;
+
+	snprintf(t_buf, sizeof(t_buf), "setfacl -d -m u::rwx,g::rw,o::rwx %s/%s", t_mountpoint, T_DIR1);
+	if (system(t_buf))
+		die("failure: system");
+
+	pid = fork();
+	if (pid < 0)
+		die("failure: fork");
+
+	if (pid == 0) {
+		if (setgid_create_idmapped_in_userns())
+			die("failure: setgid_create");
+		exit(EXIT_SUCCESS);
+	}
+
+	if (wait_for_pid(pid))
+		return -1;
+	else
+		return 0;
+}
+
 #define PTR_TO_INT(p) ((int)((intptr_t)(p)))
 #define INT_TO_PTR(u) ((void *)((intptr_t)(u)))
 
@@ -14164,10 +14236,13 @@ struct t_idmapped_mounts t_setattr_fix_968219708108[] = {
 struct t_idmapped_mounts t_setgid[] = {
 	{ setgid_create,						false,	"create operations in directories with setgid bit set",						},
 	{ setgid_create_umask,						false,	"create operations in directories with setgid bit set by umask(S_IXGRP)",			},
+	{ setgid_create_acl,						false,	"create operations in directories with setgid bit set by setfacl(S_IXGRP)",			},
 	{ setgid_create_idmapped,					true,	"create operations in directories with setgid bit set on idmapped mounts",			},
 	{ setgid_create_idmapped_umask,					true,	"create operations in directories with setgid bit set on idmapped mounts by umask(S_IXGRP)",	},
+	{ setgid_create_idmapped_acl,					true,	"create operations in directories with setgid bit set on idmapped mounts by setfacl(S_IXGRP)",	},
 	{ setgid_create_idmapped_in_userns,				true,	"create operations in directories with setgid bit set on idmapped mounts in user namespace",	},
 	{ setgid_create_idmapped_in_userns_umask,			true,   "create operations in directories with setgid bit set on idmapped mounts in user namespace by umask(S_IXGRP)",	},
+	{ setgid_create_idmapped_in_userns_acl,				true,	"create operations in directories with setgid bit set on idmapped mounts in user namespace by setfacl(S_IXGRP)",},
 };
 
 static bool run_test(struct t_idmapped_mounts suite[], size_t suite_size)
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 6/6] idmapped-mounts: Add open with O_TMPFILE operation in setgid test
  2022-04-07 12:09 [PATCH v2 1/6] idmapped-mount: split setgid test from test-core Yang Xu
                   ` (3 preceding siblings ...)
  2022-04-07 12:09 ` [PATCH v2 5/6] idmapped-mounts: Add setfacl(S_IXGRP) " Yang Xu
@ 2022-04-07 12:09 ` Yang Xu
  2022-04-07 13:43   ` Christian Brauner
  2022-04-07 12:55 ` [PATCH v2 1/6] idmapped-mount: split setgid test from test-core Christian Brauner
  5 siblings, 1 reply; 19+ messages in thread
From: Yang Xu @ 2022-04-07 12:09 UTC (permalink / raw)
  To: david, brauner, djwong; +Cc: linux-fsdevel, fstests, Yang Xu

Since we can create temp file by using O_TMPFILE flag and filesystem driver also
has this api, we should also check this operation whether strip S_ISGID.

Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
---
 src/idmapped-mounts/idmapped-mounts.c | 155 +++++++++++++++++++++++++-
 1 file changed, 154 insertions(+), 1 deletion(-)

diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
index 8f292228..362b8820 100644
--- a/src/idmapped-mounts/idmapped-mounts.c
+++ b/src/idmapped-mounts/idmapped-mounts.c
@@ -337,6 +337,24 @@ out:
 	return fret;
 }
 
+static bool openat_tmpfile_supported(int dirfd)
+{
+	int fd = -1;
+
+	fd = openat(dirfd, ".", O_TMPFILE | O_RDWR, S_IXGRP | S_ISGID);
+	if (fd == -1) {
+		if (errno == ENOTSUP)
+			return false;
+		else
+			return log_errno(false, "failure: create");
+	}
+
+	if (close(fd))
+		log_stderr("failure: close");
+
+	return true;
+}
+
 /* __expected_uid_gid - check whether file is owned by the provided uid and gid */
 static bool __expected_uid_gid(int dfd, const char *path, int flags,
 			       uid_t expected_uid, gid_t expected_gid, bool log)
@@ -7841,7 +7859,10 @@ static int setgid_create(void)
 {
 	int fret = -1;
 	int file1_fd = -EBADF;
+	int tmpfile_fd = -EBADF;
 	pid_t pid;
+	bool supported = false;
+	char path[PATH_MAX];
 
 	if (!caps_supported())
 		return 0;
@@ -7866,6 +7887,8 @@ static int setgid_create(void)
 		goto out;
 	}
 
+	supported = openat_tmpfile_supported(t_dir1_fd);
+
 	pid = fork();
 	if (pid < 0) {
 		log_stderr("failure: fork");
@@ -7883,9 +7906,24 @@ static int setgid_create(void)
 		if (!is_setgid(t_dir1_fd, FILE1, 0))
 			die("failure: is_setgid");
 
+		/* create tmpfile via filesystem tmpfile api */
+		if (supported) {
+			tmpfile_fd = openat(t_dir1_fd, ".", O_TMPFILE | O_RDWR, S_IXGRP | S_ISGID);
+			if (tmpfile_fd < 0)
+				die("failure: create");
+			/* link the temporary file into the filesystem, making it permanent */
+			snprintf(path, PATH_MAX,  "/proc/self/fd/%d", tmpfile_fd);
+			if (linkat(AT_FDCWD, path, t_dir1_fd, FILE2, AT_SYMLINK_FOLLOW))
+				die("failure: linkat");
+			if (close(tmpfile_fd))
+				die("failure: close");
+			if (!is_setgid(t_dir1_fd, FILE2, 0))
+				die("failure: is_setgid");
+		}
+
 		/* create directory */
 		if (mkdirat(t_dir1_fd, DIR1, 0000))
-			die("failure: create");
+			die("failure: mkdirat");
 
 		/* Directories always inherit the setgid bit. */
 		if (!is_setgid(t_dir1_fd, DIR1, 0))
@@ -7908,6 +7946,9 @@ static int setgid_create(void)
 		if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0))
 			die("failure: check ownership");
 
+		if (supported && !expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0))
+			die("failure: check ownership");
+
 		if (!expected_uid_gid(t_dir1_fd, DIR1 "/" FILE1, 0, 0, 0))
 			die("failure: check ownership");
 
@@ -7920,6 +7961,9 @@ static int setgid_create(void)
 		if (unlinkat(t_dir1_fd, FILE1, 0))
 			die("failure: delete");
 
+		if (supported && unlinkat(t_dir1_fd, FILE2, 0))
+			die("failure: delete");
+
 		if (unlinkat(t_dir1_fd, DIR1 "/" FILE1, 0))
 			die("failure: delete");
 
@@ -7957,6 +8001,21 @@ static int setgid_create(void)
 		if (is_setgid(t_dir1_fd, FILE1, 0))
 			die("failure: is_setgid");
 
+		/* create tmpfile via filesystem tmpfile api */
+		if (supported) {
+			tmpfile_fd = openat(t_dir1_fd, ".", O_TMPFILE | O_RDWR, S_IXGRP | S_ISGID);
+			if (tmpfile_fd < 0)
+				die("failure: create");
+			/* link the temporary file into the filesystem, making it permanent */
+			snprintf(path, PATH_MAX,  "/proc/self/fd/%d", tmpfile_fd);
+			if (linkat(AT_FDCWD, path, t_dir1_fd, FILE2, AT_SYMLINK_FOLLOW))
+				die("failure: linkat");
+			if (close(tmpfile_fd))
+				die("failure: close");
+			if (is_setgid(t_dir1_fd, FILE2, 0))
+				die("failure: is_setgid");
+		}
+
 		/* create directory */
 		if (mkdirat(t_dir1_fd, DIR1, 0000))
 			die("failure: create");
@@ -7992,6 +8051,9 @@ static int setgid_create(void)
 		if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0))
 			die("failure: check ownership");
 
+		if (supported && !expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0))
+			die("failure: check ownership");
+
 		/*
 		 * In setgid directories newly created directories always
 		 * inherit the gid from the parent directory. Verify that the
@@ -8009,6 +8071,9 @@ static int setgid_create(void)
 		if (unlinkat(t_dir1_fd, FILE1, 0))
 			die("failure: delete");
 
+		if (supported && unlinkat(t_dir1_fd, FILE2, 0))
+			die("failure: delete");
+
 		if (unlinkat(t_dir1_fd, DIR1 "/" FILE1, 0))
 			die("failure: delete");
 
@@ -8083,7 +8148,10 @@ static int setgid_create_idmapped(void)
 	struct mount_attr attr = {
 		.attr_set = MOUNT_ATTR_IDMAP,
 	};
+	int tmpfile_fd = -EBADF;
 	pid_t pid;
+	bool supported = false;
+	char path[PATH_MAX];
 
 	if (!caps_supported())
 		return 0;
@@ -8131,6 +8199,7 @@ static int setgid_create_idmapped(void)
 		goto out;
 	}
 
+	supported = openat_tmpfile_supported(open_tree_fd);
 	pid = fork();
 	if (pid < 0) {
 		log_stderr("failure: fork");
@@ -8151,6 +8220,21 @@ static int setgid_create_idmapped(void)
 		if (is_setgid(open_tree_fd, FILE1, 0))
 			die("failure: is_setgid");
 
+		/* create tmpfile via filesystem tmpfile api */
+		if (supported) {
+			tmpfile_fd = openat(open_tree_fd, ".", O_TMPFILE | O_RDWR, S_IXGRP | S_ISGID);
+			if (tmpfile_fd < 0)
+				die("failure: create");
+			/* link the temporary file into the filesystem, making it permanent */
+			snprintf(path, PATH_MAX,  "/proc/self/fd/%d", tmpfile_fd);
+			if (linkat(AT_FDCWD, path, open_tree_fd, FILE2, AT_SYMLINK_FOLLOW))
+				die("failure: linkat");
+			if (close(tmpfile_fd))
+				die("failure: close");
+			if (is_setgid(open_tree_fd, FILE2, 0))
+				die("failure: is_setgid");
+		}
+
 		/* create directory */
 		if (mkdirat(open_tree_fd, DIR1, 0000))
 			die("failure: create");
@@ -8173,6 +8257,9 @@ static int setgid_create_idmapped(void)
 		if (!expected_uid_gid(open_tree_fd, FILE1, 0, 10000, 10000))
 			die("failure: check ownership");
 
+		if (supported && !expected_uid_gid(open_tree_fd, FILE2, 0, 10000, 10000))
+			die("failure: check ownership");
+
 		/*
 		 * In setgid directories newly created directories always
 		 * inherit the gid from the parent directory. Verify that the
@@ -8254,7 +8341,10 @@ static int setgid_create_idmapped_in_userns(void)
 	struct mount_attr attr = {
 		.attr_set = MOUNT_ATTR_IDMAP,
 	};
+	int tmpfile_fd = -EBADF;
 	pid_t pid;
+	bool supported = false;
+	char path[PATH_MAX];
 
 	if (!caps_supported())
 		return 0;
@@ -8302,6 +8392,7 @@ static int setgid_create_idmapped_in_userns(void)
 		goto out;
 	}
 
+	supported = openat_tmpfile_supported(open_tree_fd);
 	pid = fork();
 	if (pid < 0) {
 		log_stderr("failure: fork");
@@ -8322,6 +8413,21 @@ static int setgid_create_idmapped_in_userns(void)
 		if (!is_setgid(open_tree_fd, FILE1, 0))
 			die("failure: is_setgid");
 
+		/* create tmpfile via filesystem tmpfile api */
+		if (supported) {
+			tmpfile_fd = openat(open_tree_fd, ".", O_TMPFILE | O_RDWR, S_IXGRP | S_ISGID);
+			if (tmpfile_fd < 0)
+				die("failure: create");
+			/* link the temporary file into the filesystem, making it permanent */
+			snprintf(path, PATH_MAX,  "/proc/self/fd/%d", tmpfile_fd);
+			if (linkat(AT_FDCWD, path, open_tree_fd, FILE2, AT_SYMLINK_FOLLOW))
+				die("failure: linkat");
+			if (close(tmpfile_fd))
+				die("failure: close");
+			if (!is_setgid(open_tree_fd, FILE2, 0))
+				die("failure: is_setgid");
+		}
+
 		/* create directory */
 		if (mkdirat(open_tree_fd, DIR1, 0000))
 			die("failure: create");
@@ -8346,6 +8452,9 @@ static int setgid_create_idmapped_in_userns(void)
 		if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
 			die("failure: check ownership");
 
+		if (supported && !expected_uid_gid(open_tree_fd, FILE2, 0, 0, 0))
+			die("failure: check ownership");
+
 		if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
 			die("failure: check ownership");
 
@@ -8357,6 +8466,8 @@ static int setgid_create_idmapped_in_userns(void)
 
 		if (unlinkat(open_tree_fd, FILE1, 0))
 			die("failure: delete");
+		if (supported && unlinkat(open_tree_fd, FILE2, 0))
+			die("failure: delete");
 		if (unlinkat(open_tree_fd, DIR1 "/" FILE1, 0))
 			die("failure: delete");
 		if (unlinkat(open_tree_fd, CHRDEV1, 0))
@@ -8410,6 +8521,21 @@ static int setgid_create_idmapped_in_userns(void)
 		if (is_setgid(open_tree_fd, FILE1, 0))
 			die("failure: is_setgid");
 
+		/* create tmpfile via filesystem tmpfile api */
+		if (supported) {
+			tmpfile_fd = openat(open_tree_fd, ".", O_TMPFILE | O_RDWR, S_IXGRP | S_ISGID);
+			if (tmpfile_fd < 0)
+				die("failure: create");
+			/* link the temporary file into the filesystem, making it permanent */
+			snprintf(path, PATH_MAX,  "/proc/self/fd/%d", tmpfile_fd);
+			if (linkat(AT_FDCWD, path, open_tree_fd, FILE2, AT_SYMLINK_FOLLOW))
+				die("failure: linkat");
+			if (close(tmpfile_fd))
+				die("failure: close");
+			if (is_setgid(open_tree_fd, FILE2, 0))
+				die("failure: is_setgid");
+		}
+
 		/* create directory */
 		if (mkdirat(open_tree_fd, DIR1, 0000))
 			die("failure: create");
@@ -8446,6 +8572,9 @@ static int setgid_create_idmapped_in_userns(void)
 		if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 1000))
 			die("failure: check ownership");
 
+		if (supported && !expected_uid_gid(open_tree_fd, FILE2, 0, 0, 1000))
+			die("failure: check ownership");
+
 		/*
 		 * In setgid directories newly created directories always
 		 * inherit the gid from the parent directory. Verify that the
@@ -8463,6 +8592,9 @@ static int setgid_create_idmapped_in_userns(void)
 		if (unlinkat(open_tree_fd, FILE1, 0))
 			die("failure: delete");
 
+		if (supported && unlinkat(open_tree_fd, FILE2, 0))
+			die("failure: delete");
+
 		if (unlinkat(open_tree_fd, DIR1 "/" FILE1, 0))
 			die("failure: delete");
 
@@ -8515,6 +8647,21 @@ static int setgid_create_idmapped_in_userns(void)
 		if (is_setgid(open_tree_fd, FILE1, 0))
 			die("failure: is_setgid");
 
+		/* create tmpfile via filesystem tmpfile api */
+		if (supported) {
+			tmpfile_fd = openat(open_tree_fd, ".", O_TMPFILE | O_RDWR, S_IXGRP | S_ISGID);
+			if (tmpfile_fd < 0)
+				die("failure: create");
+			/* link the temporary file into the filesystem, making it permanent */
+			snprintf(path, PATH_MAX,  "/proc/self/fd/%d", tmpfile_fd);
+			if (linkat(AT_FDCWD, path, open_tree_fd, FILE2, AT_SYMLINK_FOLLOW))
+				die("failure: linkat");
+			if (close(tmpfile_fd))
+				die("failure: close");
+			if (is_setgid(open_tree_fd, FILE2, 0))
+				die("failure: is_setgid");
+		}
+
 		/* create directory */
 		if (mkdirat(open_tree_fd, DIR1, 0000))
 			die("failure: create");
@@ -8546,6 +8693,9 @@ static int setgid_create_idmapped_in_userns(void)
 		if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
 			die("failure: check ownership");
 
+		if (supported && !expected_uid_gid(open_tree_fd, FILE2, 0, 0, 0))
+			die("failure: check ownership");
+
 		if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
 			die("failure: check ownership");
 
@@ -8558,6 +8708,9 @@ static int setgid_create_idmapped_in_userns(void)
 		if (unlinkat(open_tree_fd, FILE1, 0))
 			die("failure: delete");
 
+		if (supported && unlinkat(open_tree_fd, FILE2, 0))
+			die("failure: delete");
+
 		if (unlinkat(open_tree_fd, DIR1 "/" FILE1, 0))
 			die("failure: delete");
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/6] idmapped-mount: split setgid test from test-core
  2022-04-07 12:09 [PATCH v2 1/6] idmapped-mount: split setgid test from test-core Yang Xu
                   ` (4 preceding siblings ...)
  2022-04-07 12:09 ` [PATCH v2 6/6] idmapped-mounts: Add open with O_TMPFILE operation in setgid test Yang Xu
@ 2022-04-07 12:55 ` Christian Brauner
  2022-04-08  1:20   ` xuyang2018.jy
  5 siblings, 1 reply; 19+ messages in thread
From: Christian Brauner @ 2022-04-07 12:55 UTC (permalink / raw)
  To: Yang Xu; +Cc: david, djwong, linux-fsdevel, fstests

On Thu, Apr 07, 2022 at 08:09:30PM +0800, Yang Xu wrote:
> Since we plan to increase setgid test covertage, it will find new bug
> , so add a new test group test-setgid is better.
> 
> Also add a new test case to test test-setgid instead of miss it.
> 
> Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
> ---
>  src/idmapped-mounts/idmapped-mounts.c | 19 +++++++++++++++----
>  tests/generic/999                     | 26 ++++++++++++++++++++++++++
>  tests/generic/999.out                 |  2 ++

I actually didn't mean to split out the existing setgid tests. I mean
adding new ones for the test-cases you're adding. But how you did it
works for me too and is a bit nicer. I don't have a strong opinion so as
long as Dave and Darrick are fine with it then this seems good to me.

One note about the test name/numbering though. It seems you haven't
added the test using the provided xfstest infrastructure to do that.
Instead of manually adding the test you should run the "new" script.

You should run:

        ~/src/git/xfstests$ ./new generic

        Next test id is 678
        Append a name to the ID? Test name will be 678-$name. y,[n]:
        Creating test file '678'
        Add to group(s) [auto] (separate by space, ? for list): auto quick attr idmapped mount perms
        Creating skeletal script for you to edit ...

that'll automatically figure out the correct test number etc.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 3/6] idmapped-mounts: Reset errno to zero after detect fs_allow_idmap
  2022-04-07 12:09 ` [PATCH v2 3/6] idmapped-mounts: Reset errno to zero after detect fs_allow_idmap Yang Xu
@ 2022-04-07 12:59   ` Christian Brauner
  0 siblings, 0 replies; 19+ messages in thread
From: Christian Brauner @ 2022-04-07 12:59 UTC (permalink / raw)
  To: Yang Xu; +Cc: david, djwong, linux-fsdevel, fstests

On Thu, Apr 07, 2022 at 08:09:32PM +0800, Yang Xu wrote:
> If we run case on old kernel that doesn't support mount_setattr and
> then fail on our own function before call is_setgid/is_setuid function
> to reset errno, run_test will print "Function not implement" error.
> 
> Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
> ---
>  src/idmapped-mounts/idmapped-mounts.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
> index e8a856de..d2638c64 100644
> --- a/src/idmapped-mounts/idmapped-mounts.c
> +++ b/src/idmapped-mounts/idmapped-mounts.c
> @@ -14254,6 +14254,8 @@ int main(int argc, char *argv[])
>  		die("failed to open %s", t_mountpoint_scratch);
>  
>  	t_fs_allow_idmap = fs_allow_idmap();
> +	/*Don't copy ENOSYS errno to child proecss on older kernel*/

nit: s/proecess/process/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 2/6] idmapped-mounts: Add mknodat operation in setgid test
  2022-04-07 12:09 ` [PATCH v2 2/6] idmapped-mounts: Add mknodat operation in setgid test Yang Xu
@ 2022-04-07 13:40   ` Christian Brauner
  2022-04-08  3:02     ` xuyang2018.jy
  0 siblings, 1 reply; 19+ messages in thread
From: Christian Brauner @ 2022-04-07 13:40 UTC (permalink / raw)
  To: Yang Xu; +Cc: david, djwong, linux-fsdevel, fstests

On Thu, Apr 07, 2022 at 08:09:31PM +0800, Yang Xu wrote:
> Since mknodat can create file, we should also check whether strip S_ISGID.
> Also add new helper caps_down_fsetid to drop CAP_FSETID because strip S_ISGID
> depond on this cap and keep other cap(ie CAP_MKNOD) because create character
> device needs it when using mknod.
> 
> Only test mknodat with character device in setgid_create function because the another
> two functions test mknodat with whiteout device.
> 
> Since kernel commit a3c751a50 ("vfs: allow unprivileged whiteout creation") in
> v5.8-rc1, we can create whiteout device in userns test. Since kernel 5.12, mount_setattr
> and MOUNT_ATTR_IDMAP was supported, we don't need to detect kernel whether allow
> unprivileged whiteout creation. Using fs_allow_idmap as a proxy is safe.
> 
> Tested-by: Christian Brauner (Microsoft)<brauner@kernel.org>
> Reviewed-by: Christian Brauner (Microsoft)<brauner@kernel.org>
> Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
> ---
>  src/idmapped-mounts/idmapped-mounts.c | 190 +++++++++++++++++++++++++-
>  1 file changed, 183 insertions(+), 7 deletions(-)
> 
> diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
> index dff6820f..e8a856de 100644
> --- a/src/idmapped-mounts/idmapped-mounts.c
> +++ b/src/idmapped-mounts/idmapped-mounts.c
> @@ -241,6 +241,34 @@ static inline bool caps_supported(void)
>  	return ret;
>  }
>  
> +static int caps_down_fsetid(void)
> +{
> +	bool fret = false;
> +#ifdef HAVE_SYS_CAPABILITY_H
> +	cap_t caps = NULL;
> +	cap_value_t cap = CAP_FSETID;
> +	int ret = -1;
> +
> +	caps = cap_get_proc();
> +	if (!caps)
> +		goto out;
> +
> +	ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, 0);
> +	if (ret)
> +		goto out;
> +
> +	ret = cap_set_proc(caps);
> +	if (ret)
> +		goto out;
> +
> +	fret = true;
> +
> +out:
> +	cap_free(caps);
> +#endif
> +	return fret;
> +}
> +
>  /* caps_down - lower all effective caps */
>  static int caps_down(void)
>  {
> @@ -7805,8 +7833,8 @@ out_unmap:
>  #endif /* HAVE_LIBURING_H */
>  
>  /* The following tests are concerned with setgid inheritance. These can be
> - * filesystem type specific. For xfs, if a new file or directory is created
> - * within a setgid directory and irix_sgid_inhiert is set then inherit the
> + * filesystem type specific. For xfs, if a new file or directory or node is
> + * created within a setgid directory and irix_sgid_inhiert is set then inherit the
>   * setgid bit if the caller is in the group of the directory.
>   */
>  static int setgid_create(void)
> @@ -7863,15 +7891,41 @@ static int setgid_create(void)
>  		if (!is_setgid(t_dir1_fd, DIR1, 0))
>  			die("failure: is_setgid");
>  
> +		/* create a special file via mknodat() vfs_create */
> +		if (mknodat(t_dir1_fd, DIR1 "/" FILE1, S_IFREG | S_ISGID | 0755, 0))
> +			die("failure: mknodat");

Can you please replace 0755 with the corresponding flags everywhere?
I personally find them easier to parse but it's also what we've been
using mostly everywhere in the testsuite.

> +
> +		if (!is_setgid(t_dir1_fd, DIR1 "/" FILE1, 0))
> +			die("failure: is_setgid");
> +
> +		/* create a character device via mknodat() vfs_mknod */
> +		if (mknodat(t_dir1_fd, CHRDEV1, S_IFCHR | S_ISGID | 0755, makedev(5, 1)))
> +			die("failure: mknodat");
> +
> +		if (!is_setgid(t_dir1_fd, CHRDEV1, 0))
> +			die("failure: is_setgid");
> +
>  		if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0))
>  			die("failure: check ownership");
>  
> +		if (!expected_uid_gid(t_dir1_fd, DIR1 "/" FILE1, 0, 0, 0))
> +			die("failure: check ownership");
> +
> +		if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0))
> +			die("failure: check ownership");
> +
>  		if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0))
>  			die("failure: check ownership");
>  
>  		if (unlinkat(t_dir1_fd, FILE1, 0))
>  			die("failure: delete");
>  
> +		if (unlinkat(t_dir1_fd, DIR1 "/" FILE1, 0))
> +			die("failure: delete");
> +
> +		if (unlinkat(t_dir1_fd, CHRDEV1, 0))
> +			die("failure: delete");
> +
>  		if (unlinkat(t_dir1_fd, DIR1, AT_REMOVEDIR))
>  			die("failure: delete");
>  
> @@ -7889,8 +7943,8 @@ static int setgid_create(void)
>  		if (!switch_ids(0, 10000))
>  			die("failure: switch_ids");
>  
> -		if (!caps_down())
> -			die("failure: caps_down");
> +		if (!caps_down_fsetid())
> +			die("failure: caps_down_fsetid");
>  
>  		/* create regular file via open() */
>  		file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> @@ -7917,6 +7971,19 @@ static int setgid_create(void)
>  				die("failure: is_setgid");
>  		}
>  
> +		/* create a special file via mknodat() vfs_create */
> +		if (mknodat(t_dir1_fd, DIR1 "/" FILE1, S_IFREG | S_ISGID | 0755, 0))
> +			die("failure: mknodat");
> +
> +		if (is_setgid(t_dir1_fd, DIR1 "/" FILE1, 0))
> +			die("failure: is_setgid");
> +
> +		/* create a character device via mknodat() vfs_mknod */
> +		if (mknodat(t_dir1_fd, CHRDEV1, S_IFCHR | S_ISGID | 0755, makedev(5, 1)))
> +			die("failure: mknodat");
> +
> +		if (is_setgid(t_dir1_fd, CHRDEV1, 0))
> +			die("failure: is_setgid");

Right above this section you can see the following:

		if (xfs_irix_sgid_inherit_enabled()) {
			/* We're not in_group_p(). */
			if (is_setgid(t_dir1_fd, DIR1, 0))
				die("failure: is_setgid");
		} else {

which tests xfs specific behavior. If this is turned on then
t_dir1_fd/DIR1 won't bet a setgid directory.

Consequently the test:

		/* create a special file via mknodat() vfs_create */
		if (mknodat(t_dir1_fd, DIR1 "/" FILE1, S_IFREG | S_ISGID | 0755, 0))
			die("failure: mknodat");

		if (is_setgid(t_dir1_fd, DIR1 "/" FILE1, 0))
			die("failure: is_setgid");

will fail because the branch in the kernel that strips the setgid bit
won't be hit.

So afiact, you need to ensure that the setgid bit is raised in the if
(xfs_irix_sgid_inherit_enabled()) branch after having verified that the
directory hasn't inherited the setgid bit with the legacy irix behavior.

If you don't do that then the test will be a false negative for xfs with
the sysctl turned on. It's super rare but it'll be annoying if we have
to track this down later.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 6/6] idmapped-mounts: Add open with O_TMPFILE operation in setgid test
  2022-04-07 12:09 ` [PATCH v2 6/6] idmapped-mounts: Add open with O_TMPFILE operation in setgid test Yang Xu
@ 2022-04-07 13:43   ` Christian Brauner
  2022-04-08  3:58     ` xuyang2018.jy
  0 siblings, 1 reply; 19+ messages in thread
From: Christian Brauner @ 2022-04-07 13:43 UTC (permalink / raw)
  To: Yang Xu; +Cc: david, djwong, linux-fsdevel, fstests

On Thu, Apr 07, 2022 at 08:09:35PM +0800, Yang Xu wrote:
> Since we can create temp file by using O_TMPFILE flag and filesystem driver also
> has this api, we should also check this operation whether strip S_ISGID.
> 
> Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
> ---

This is a great addition, thanks!
Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 4/6] idmapped-mounts: Add umask(S_IXGRP) wrapper for setgid_create* cases
  2022-04-07 12:09 ` [PATCH v2 4/6] idmapped-mounts: Add umask(S_IXGRP) wrapper for setgid_create* cases Yang Xu
@ 2022-04-07 15:12   ` Christian Brauner
  2022-04-08  3:38     ` xuyang2018.jy
  0 siblings, 1 reply; 19+ messages in thread
From: Christian Brauner @ 2022-04-07 15:12 UTC (permalink / raw)
  To: Yang Xu; +Cc: david, djwong, linux-fsdevel, fstests

On Thu, Apr 07, 2022 at 08:09:33PM +0800, Yang Xu wrote:
> Since stipping S_SIGID should check S_IXGRP, so umask it to check whether
> works well.
> 
> Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
> ---
>  src/idmapped-mounts/idmapped-mounts.c | 66 +++++++++++++++++++++++++++
>  1 file changed, 66 insertions(+)
> 
> diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
> index d2638c64..d6769f08 100644
> --- a/src/idmapped-mounts/idmapped-mounts.c
> +++ b/src/idmapped-mounts/idmapped-mounts.c
> @@ -8031,6 +8031,27 @@ out:
>  	return fret;
>  }
>  
> +static int setgid_create_umask(void)
> +{
> +	pid_t pid;
> +
> +	umask(S_IXGRP);

Ok, this is migraine territory (not your fault ofc). So I think we want
to not just wrap the umask() and setfacl() code around the existing
setgid() tests. That's just so complex to reason about that the test
just adds confusion if we just hack it into existing functions.

Can you please add separate tests that don't just wrap existing tests
via umask()+fork() and instead add dedicated umask()-based and
acl()-based functions.

Do you have time to do that?

Right now it's confusing because there's an intricate relationship
between acls and current_umask() and that needs to be mentioned in the
respective tests.

The current_umask() is stripped from the mode directly in the vfs if the
filesystem either doesn't support acls or the filesystem has been
mounted without posic acl support.

If the filesystem does support acls then current_umask() stripping is
deferred to posix_acl_create(). So when the filesystem calls
posix_acl_create() and there are no acls set or not supported then
current_umask() will be stripped.

If the parent directory has a default acl then permissions are based off
of that and current_umask() is ignored. Specifically, if the ACL has an
ACL_MASK entry, the group permissions correspond to the permissions of
the ACL_MASK entry. Otherwise, if the ACL has no ACL_MASK entry, the
group permissions correspond to the permissions of the ACL_GROUP_OBJ
entry.

Yes, it's confusing which is why we need to clearly give both acls and
the umask() tests their separate functions and not just hack them into
the existing functions.

As it stands the umask() and posix acl() tests only pass by accident
because the filesystem you're testing on supports acls but doesn't strip
the S_IXGRP bit. So the current_umask() is ignored and that's why the
tests pass, I think. Otherwise they'd fail because they test the wrong
thing.

You can verify this by setting
export MOUNT_OPTIONS='-o noacl'
in your xfstests config.

You'll see the test fail just like it should:

ubuntu@imp1-vm:~/src/git/xfstests$ sudo ./check generic/999
FSTYP         -- ext4
PLATFORM      -- Linux/x86_64 imp1-vm 5.18.0-rc1-ovl-7d354bcd37d1 #273 SMP PREEMPT_DYNAMIC Thu Apr 7 11:07:08 UTC 2022
MKFS_OPTIONS  -- /dev/sda4
MOUNT_OPTIONS -- -o noacl /dev/sda4 /mnt/scratch

generic/999 2s ... [failed, exit status 1]- output mismatch (see /home/ubuntu/src/git/xfstests/results//generic/999.out.bad)
    --- tests/generic/999.out   2022-04-07 12:48:18.948000000 +0000
    +++ /home/ubuntu/src/git/xfstests/results//generic/999.out.bad      2022-04-07 14:19:28.517811054 +0000
    @@ -1,2 +1,5 @@
     QA output created by 999
     Silence is golden
    +idmapped-mounts.c: 8002: setgid_create - Success - failure: is_setgid
    +idmapped-mounts.c: 8110: setgid_create_umask - Success - failure: setgid
    +idmapped-mounts.c: 14428: run_test - No such file or directory - failure: create operations in directories with setgid bit set by umask(S_IXGRP)
    ...
    (Run 'diff -u /home/ubuntu/src/git/xfstests/tests/generic/999.out /home/ubuntu/src/git/xfstests/results//generic/999.out.bad'  to see the entire diff)
Ran: generic/999
Failures: generic/999
Failed 1 of 1 tests

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/6] idmapped-mount: split setgid test from test-core
  2022-04-07 12:55 ` [PATCH v2 1/6] idmapped-mount: split setgid test from test-core Christian Brauner
@ 2022-04-08  1:20   ` xuyang2018.jy
  2022-04-08 10:17     ` xuyang2018.jy
  0 siblings, 1 reply; 19+ messages in thread
From: xuyang2018.jy @ 2022-04-08  1:20 UTC (permalink / raw)
  To: Christian Brauner; +Cc: david, djwong, linux-fsdevel, fstests

on 2022/4/7 20:55, Christian Brauner wrote:
> On Thu, Apr 07, 2022 at 08:09:30PM +0800, Yang Xu wrote:
>> Since we plan to increase setgid test covertage, it will find new bug
>> , so add a new test group test-setgid is better.
>>
>> Also add a new test case to test test-setgid instead of miss it.
>>
>> Signed-off-by: Yang Xu<xuyang2018.jy@fujitsu.com>
>> ---
>>   src/idmapped-mounts/idmapped-mounts.c | 19 +++++++++++++++----
>>   tests/generic/999                     | 26 ++++++++++++++++++++++++++
>>   tests/generic/999.out                 |  2 ++
>
> I actually didn't mean to split out the existing setgid tests. I mean
> adding new ones for the test-cases you're adding. But how you did it
> works for me too and is a bit nicer. I don't have a strong opinion so as
> long as Dave and Darrick are fine with it then this seems good to me.
Ok, let's listen ..
>
> One note about the test name/numbering though. It seems you haven't
> added the test using the provided xfstest infrastructure to do that.
> Instead of manually adding the test you should run the "new" script.
>
> You should run:
>
>          ~/src/git/xfstests$ ./new generic
>
>          Next test id is 678
>          Append a name to the ID? Test name will be 678-$name. y,[n]:
>          Creating test file '678'
>          Add to group(s) [auto] (separate by space, ? for list): auto quick attr idmapped mount perms
>          Creating skeletal script for you to edit ...
>
> that'll automatically figure out the correct test number etc.
Thanks, TBH, I don't know this usage. I don't name to 678 because 
fstests patchwork has others new case(in reviewing), so I add a biger 
number.

Best Regards
Yang Xu

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 2/6] idmapped-mounts: Add mknodat operation in setgid test
  2022-04-07 13:40   ` Christian Brauner
@ 2022-04-08  3:02     ` xuyang2018.jy
  0 siblings, 0 replies; 19+ messages in thread
From: xuyang2018.jy @ 2022-04-08  3:02 UTC (permalink / raw)
  To: Christian Brauner; +Cc: david, djwong, linux-fsdevel, fstests

on 2022/4/7 21:40, Christian Brauner wrote:
> On Thu, Apr 07, 2022 at 08:09:31PM +0800, Yang Xu wrote:
>> Since mknodat can create file, we should also check whether strip S_ISGID.
>> Also add new helper caps_down_fsetid to drop CAP_FSETID because strip S_ISGID
>> depond on this cap and keep other cap(ie CAP_MKNOD) because create character
>> device needs it when using mknod.
>>
>> Only test mknodat with character device in setgid_create function because the another
>> two functions test mknodat with whiteout device.
>>
>> Since kernel commit a3c751a50 ("vfs: allow unprivileged whiteout creation") in
>> v5.8-rc1, we can create whiteout device in userns test. Since kernel 5.12, mount_setattr
>> and MOUNT_ATTR_IDMAP was supported, we don't need to detect kernel whether allow
>> unprivileged whiteout creation. Using fs_allow_idmap as a proxy is safe.
>>
>> Tested-by: Christian Brauner (Microsoft)<brauner@kernel.org>
>> Reviewed-by: Christian Brauner (Microsoft)<brauner@kernel.org>
>> Signed-off-by: Yang Xu<xuyang2018.jy@fujitsu.com>
>> ---
>>   src/idmapped-mounts/idmapped-mounts.c | 190 +++++++++++++++++++++++++-
>>   1 file changed, 183 insertions(+), 7 deletions(-)
>>
>> diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
>> index dff6820f..e8a856de 100644
>> --- a/src/idmapped-mounts/idmapped-mounts.c
>> +++ b/src/idmapped-mounts/idmapped-mounts.c
>> @@ -241,6 +241,34 @@ static inline bool caps_supported(void)
>>   	return ret;
>>   }
>>
>> +static int caps_down_fsetid(void)
>> +{
>> +	bool fret = false;
>> +#ifdef HAVE_SYS_CAPABILITY_H
>> +	cap_t caps = NULL;
>> +	cap_value_t cap = CAP_FSETID;
>> +	int ret = -1;
>> +
>> +	caps = cap_get_proc();
>> +	if (!caps)
>> +		goto out;
>> +
>> +	ret = cap_set_flag(caps, CAP_EFFECTIVE, 1,&cap, 0);
>> +	if (ret)
>> +		goto out;
>> +
>> +	ret = cap_set_proc(caps);
>> +	if (ret)
>> +		goto out;
>> +
>> +	fret = true;
>> +
>> +out:
>> +	cap_free(caps);
>> +#endif
>> +	return fret;
>> +}
>> +
>>   /* caps_down - lower all effective caps */
>>   static int caps_down(void)
>>   {
>> @@ -7805,8 +7833,8 @@ out_unmap:
>>   #endif /* HAVE_LIBURING_H */
>>
>>   /* The following tests are concerned with setgid inheritance. These can be
>> - * filesystem type specific. For xfs, if a new file or directory is created
>> - * within a setgid directory and irix_sgid_inhiert is set then inherit the
>> + * filesystem type specific. For xfs, if a new file or directory or node is
>> + * created within a setgid directory and irix_sgid_inhiert is set then inherit the
>>    * setgid bit if the caller is in the group of the directory.
>>    */
>>   static int setgid_create(void)
>> @@ -7863,15 +7891,41 @@ static int setgid_create(void)
>>   		if (!is_setgid(t_dir1_fd, DIR1, 0))
>>   			die("failure: is_setgid");
>>
>> +		/* create a special file via mknodat() vfs_create */
>> +		if (mknodat(t_dir1_fd, DIR1 "/" FILE1, S_IFREG | S_ISGID | 0755, 0))
>> +			die("failure: mknodat");
>
> Can you please replace 0755 with the corresponding flags everywhere?
> I personally find them easier to parse but it's also what we've been
> using mostly everywhere in the testsuite.
OK, will do.
>
>> +
>> +		if (!is_setgid(t_dir1_fd, DIR1 "/" FILE1, 0))
>> +			die("failure: is_setgid");
>> +
>> +		/* create a character device via mknodat() vfs_mknod */
>> +		if (mknodat(t_dir1_fd, CHRDEV1, S_IFCHR | S_ISGID | 0755, makedev(5, 1)))
>> +			die("failure: mknodat");
>> +
>> +		if (!is_setgid(t_dir1_fd, CHRDEV1, 0))
>> +			die("failure: is_setgid");
>> +
>>   		if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0))
>>   			die("failure: check ownership");
>>
>> +		if (!expected_uid_gid(t_dir1_fd, DIR1 "/" FILE1, 0, 0, 0))
>> +			die("failure: check ownership");
>> +
>> +		if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0))
>> +			die("failure: check ownership");
>> +
>>   		if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0))
>>   			die("failure: check ownership");
>>
>>   		if (unlinkat(t_dir1_fd, FILE1, 0))
>>   			die("failure: delete");
>>
>> +		if (unlinkat(t_dir1_fd, DIR1 "/" FILE1, 0))
>> +			die("failure: delete");
>> +
>> +		if (unlinkat(t_dir1_fd, CHRDEV1, 0))
>> +			die("failure: delete");
>> +
>>   		if (unlinkat(t_dir1_fd, DIR1, AT_REMOVEDIR))
>>   			die("failure: delete");
>>
>> @@ -7889,8 +7943,8 @@ static int setgid_create(void)
>>   		if (!switch_ids(0, 10000))
>>   			die("failure: switch_ids");
>>
>> -		if (!caps_down())
>> -			die("failure: caps_down");
>> +		if (!caps_down_fsetid())
>> +			die("failure: caps_down_fsetid");
>>
>>   		/* create regular file via open() */
>>   		file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
>> @@ -7917,6 +7971,19 @@ static int setgid_create(void)
>>   				die("failure: is_setgid");
>>   		}
>>
>> +		/* create a special file via mknodat() vfs_create */
>> +		if (mknodat(t_dir1_fd, DIR1 "/" FILE1, S_IFREG | S_ISGID | 0755, 0))
>> +			die("failure: mknodat");
>> +
>> +		if (is_setgid(t_dir1_fd, DIR1 "/" FILE1, 0))
>> +			die("failure: is_setgid");
>> +
>> +		/* create a character device via mknodat() vfs_mknod */
>> +		if (mknodat(t_dir1_fd, CHRDEV1, S_IFCHR | S_ISGID | 0755, makedev(5, 1)))
>> +			die("failure: mknodat");
>> +
>> +		if (is_setgid(t_dir1_fd, CHRDEV1, 0))
>> +			die("failure: is_setgid");
>
> Right above this section you can see the following:
>
> 		if (xfs_irix_sgid_inherit_enabled()) {
> 			/* We're not in_group_p(). */
> 			if (is_setgid(t_dir1_fd, DIR1, 0))
> 				die("failure: is_setgid");
> 		} else {
>
> which tests xfs specific behavior. If this is turned on then
> t_dir1_fd/DIR1 won't bet a setgid directory.
>
> Consequently the test:
>
> 		/* create a special file via mknodat() vfs_create */
> 		if (mknodat(t_dir1_fd, DIR1 "/" FILE1, S_IFREG | S_ISGID | 0755, 0))
> 			die("failure: mknodat");
>
> 		if (is_setgid(t_dir1_fd, DIR1 "/" FILE1, 0))
> 			die("failure: is_setgid");
>
> will fail because the branch in the kernel that strips the setgid bit
> won't be hit.
>
> So afiact, you need to ensure that the setgid bit is raised in the if
> (xfs_irix_sgid_inherit_enabled()) branch after having verified that the
> directory hasn't inherited the setgid bit with the legacy irix behavior.
>
> If you don't do that then the test will be a false negative for xfs with
> the sysctl turned on. It's super rare but it'll be annoying if we have
> to track this down later.
Good catch, will fix this.

Best Regards
Yang Xu

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 4/6] idmapped-mounts: Add umask(S_IXGRP) wrapper for setgid_create* cases
  2022-04-07 15:12   ` Christian Brauner
@ 2022-04-08  3:38     ` xuyang2018.jy
  0 siblings, 0 replies; 19+ messages in thread
From: xuyang2018.jy @ 2022-04-08  3:38 UTC (permalink / raw)
  To: Christian Brauner; +Cc: david, djwong, linux-fsdevel, fstests

on 2022/4/7 23:12, Christian Brauner wrote:
> On Thu, Apr 07, 2022 at 08:09:33PM +0800, Yang Xu wrote:
>> Since stipping S_SIGID should check S_IXGRP, so umask it to check whether
>> works well.
>>
>> Signed-off-by: Yang Xu<xuyang2018.jy@fujitsu.com>
>> ---
>>   src/idmapped-mounts/idmapped-mounts.c | 66 +++++++++++++++++++++++++++
>>   1 file changed, 66 insertions(+)
>>
>> diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
>> index d2638c64..d6769f08 100644
>> --- a/src/idmapped-mounts/idmapped-mounts.c
>> +++ b/src/idmapped-mounts/idmapped-mounts.c
>> @@ -8031,6 +8031,27 @@ out:
>>   	return fret;
>>   }
>>
>> +static int setgid_create_umask(void)
>> +{
>> +	pid_t pid;
>> +
>> +	umask(S_IXGRP);
>
> Ok, this is migraine territory (not your fault ofc). So I think we want
> to not just wrap the umask() and setfacl() code around the existing
> setgid() tests. That's just so complex to reason about that the test
> just adds confusion if we just hack it into existing functions.
>
> Can you please add separate tests that don't just wrap existing tests
> via umask()+fork() and instead add dedicated umask()-based and
> acl()-based functions.
Ok, I understand.
>
> Do you have time to do that?
Yes, I have time to do this. Yesterday I hurriedly sent out this 
patchset in order to get more comments in this week.
>
> Right now it's confusing because there's an intricate relationship
> between acls and current_umask() and that needs to be mentioned in the
> respective tests.
>
> The current_umask() is stripped from the mode directly in the vfs if the
> filesystem either doesn't support acls or the filesystem has been
> mounted without posic acl support.
>
> If the filesystem does support acls then current_umask() stripping is
> deferred to posix_acl_create(). So when the filesystem calls
> posix_acl_create() and there are no acls set or not supported then
> current_umask() will be stripped.
>
> If the parent directory has a default acl then permissions are based off
> of that and current_umask() is ignored. Specifically, if the ACL has an
> ACL_MASK entry, the group permissions correspond to the permissions of
> the ACL_MASK entry. Otherwise, if the ACL has no ACL_MASK entry, the
> group permissions correspond to the permissions of the ACL_GROUP_OBJ
> entry.
>
> Yes, it's confusing which is why we need to clearly give both acls and
> the umask() tests their separate functions and not just hack them into
> the existing functions.

Got it.
>
> As it stands the umask() and posix acl() tests only pass by accident
> because the filesystem you're testing on supports acls but doesn't strip
> the S_IXGRP bit. So the current_umask() is ignored and that's why the
> tests pass, I think. Otherwise they'd fail because they test the wrong
> thing.
Oh, yes.
>
> You can verify this by setting
> export MOUNT_OPTIONS='-o noacl'
> in your xfstests config.
>
> You'll see the test fail just like it should:
>
> ubuntu@imp1-vm:~/src/git/xfstests$ sudo ./check generic/999
> FSTYP         -- ext4
> PLATFORM      -- Linux/x86_64 imp1-vm 5.18.0-rc1-ovl-7d354bcd37d1 #273 SMP PREEMPT_DYNAMIC Thu Apr 7 11:07:08 UTC 2022
> MKFS_OPTIONS  -- /dev/sda4
> MOUNT_OPTIONS -- -o noacl /dev/sda4 /mnt/scratch
>
> generic/999 2s ... [failed, exit status 1]- output mismatch (see /home/ubuntu/src/git/xfstests/results//generic/999.out.bad)
>      --- tests/generic/999.out   2022-04-07 12:48:18.948000000 +0000
>      +++ /home/ubuntu/src/git/xfstests/results//generic/999.out.bad      2022-04-07 14:19:28.517811054 +0000
>      @@ -1,2 +1,5 @@
>       QA output created by 999
>       Silence is golden
>      +idmapped-mounts.c: 8002: setgid_create - Success - failure: is_setgid
>      +idmapped-mounts.c: 8110: setgid_create_umask - Success - failure: setgid
>      +idmapped-mounts.c: 14428: run_test - No such file or directory - failure: create operations in directories with setgid bit set by umask(S_IXGRP)
>      ...
>      (Run 'diff -u /home/ubuntu/src/git/xfstests/tests/generic/999.out /home/ubuntu/src/git/xfstests/results//generic/999.out.bad'  to see the entire diff)
> Ran: generic/999
> Failures: generic/999
> Failed 1 of 1 tests
I will design separate function for umask and acl, but I doubut whether 
we also need to test them in in_userns and idmaped_in_user situation.

ps: I will put umask and acl patch as the 5th/6th the patchset because 
other patch only has small nits and easy to modify.

Best Regards
Yang Xu

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 6/6] idmapped-mounts: Add open with O_TMPFILE operation in setgid test
  2022-04-07 13:43   ` Christian Brauner
@ 2022-04-08  3:58     ` xuyang2018.jy
  2022-04-08  7:34       ` Zorro Lang
  0 siblings, 1 reply; 19+ messages in thread
From: xuyang2018.jy @ 2022-04-08  3:58 UTC (permalink / raw)
  To: Christian Brauner
  Cc: david, djwong, linux-fsdevel, fstests, Zorro Lang, Eryu Guan

on 2022/4/7 21:43, Christian Brauner wrote:
> On Thu, Apr 07, 2022 at 08:09:35PM +0800, Yang Xu wrote:
>> Since we can create temp file by using O_TMPFILE flag and filesystem driver also
>> has this api, we should also check this operation whether strip S_ISGID.
>>
>> Signed-off-by: Yang Xu<xuyang2018.jy@fujitsu.com>
>> ---
>
> This is a great addition, thanks!
> Reviewed-by: Christian Brauner (Microsoft)<brauner@kernel.org>
Thanks for your review.

@Darrick @Eryu @Zorro
just a kindly question, not a push
xfstests has not update for 3 weeks and Eryu will take off maintainer.

Zorro lang has apply for this job. So when does xfstest can work well?

Best Regards
Yang Xu

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 6/6] idmapped-mounts: Add open with O_TMPFILE operation in setgid test
  2022-04-08  3:58     ` xuyang2018.jy
@ 2022-04-08  7:34       ` Zorro Lang
  2022-04-08  7:55         ` xuyang2018.jy
  0 siblings, 1 reply; 19+ messages in thread
From: Zorro Lang @ 2022-04-08  7:34 UTC (permalink / raw)
  To: xuyang2018.jy
  Cc: Christian Brauner, david, djwong, linux-fsdevel, fstests, Eryu Guan

On Fri, Apr 08, 2022 at 03:58:27AM +0000, xuyang2018.jy@fujitsu.com wrote:
> on 2022/4/7 21:43, Christian Brauner wrote:
> > On Thu, Apr 07, 2022 at 08:09:35PM +0800, Yang Xu wrote:
> >> Since we can create temp file by using O_TMPFILE flag and filesystem driver also
> >> has this api, we should also check this operation whether strip S_ISGID.
> >>
> >> Signed-off-by: Yang Xu<xuyang2018.jy@fujitsu.com>
> >> ---
> >
> > This is a great addition, thanks!
> > Reviewed-by: Christian Brauner (Microsoft)<brauner@kernel.org>
> Thanks for your review.
> 
> @Darrick @Eryu @Zorro
> just a kindly question, not a push
> xfstests has not update for 3 weeks and Eryu will take off maintainer.
> 
> Zorro lang has apply for this job. So when does xfstest can work well?

Hi Yang,

Sorry for the delay, I'm still waiting for the job handover, I have no
permission to push to kernel.org now. The transfer might need a few days/week,
Eryu is busy on other things :) He might merge the current patches on queue
when he get free time, then we can start the handover step by step.

Thanks,
Zorro

> 
> Best Regards
> Yang Xu


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 6/6] idmapped-mounts: Add open with O_TMPFILE operation in setgid test
  2022-04-08  7:34       ` Zorro Lang
@ 2022-04-08  7:55         ` xuyang2018.jy
  0 siblings, 0 replies; 19+ messages in thread
From: xuyang2018.jy @ 2022-04-08  7:55 UTC (permalink / raw)
  To: Christian Brauner, david, djwong, linux-fsdevel, fstests, Eryu Guan

on 2022/4/8 15:34, Zorro Lang wrote:
> On Fri, Apr 08, 2022 at 03:58:27AM +0000, xuyang2018.jy@fujitsu.com wrote:
>> on 2022/4/7 21:43, Christian Brauner wrote:
>>> On Thu, Apr 07, 2022 at 08:09:35PM +0800, Yang Xu wrote:
>>>> Since we can create temp file by using O_TMPFILE flag and filesystem driver also
>>>> has this api, we should also check this operation whether strip S_ISGID.
>>>>
>>>> Signed-off-by: Yang Xu<xuyang2018.jy@fujitsu.com>
>>>> ---
>>>
>>> This is a great addition, thanks!
>>> Reviewed-by: Christian Brauner (Microsoft)<brauner@kernel.org>
>> Thanks for your review.
>>
>> @Darrick @Eryu @Zorro
>> just a kindly question, not a push
>> xfstests has not update for 3 weeks and Eryu will take off maintainer.
>>
>> Zorro lang has apply for this job. So when does xfstest can work well?
>
> Hi Yang,
>
> Sorry for the delay, I'm still waiting for the job handover, I have no
> permission to push to kernel.org now. The transfer might need a few days/week,
> Eryu is busy on other things :) He might merge the current patches on queue
> when he get free time, then we can start the handover step by step.
Thanks for your reponse.

Best Regards
Yang Xu
>
> Thanks,
> Zorro
>
>>
>> Best Regards
>> Yang Xu
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/6] idmapped-mount: split setgid test from test-core
  2022-04-08  1:20   ` xuyang2018.jy
@ 2022-04-08 10:17     ` xuyang2018.jy
  2022-04-08 10:33       ` Christian Brauner
  0 siblings, 1 reply; 19+ messages in thread
From: xuyang2018.jy @ 2022-04-08 10:17 UTC (permalink / raw)
  To: Christian Brauner; +Cc: david, djwong, linux-fsdevel, fstests

on 2022/4/8 9:20, xuyang2018.jy@fujitsu.com wrote:
> on 2022/4/7 20:55, Christian Brauner wrote:
>> On Thu, Apr 07, 2022 at 08:09:30PM +0800, Yang Xu wrote:
>>> Since we plan to increase setgid test covertage, it will find new bug
>>> , so add a new test group test-setgid is better.
>>>
>>> Also add a new test case to test test-setgid instead of miss it.
>>>
>>> Signed-off-by: Yang Xu<xuyang2018.jy@fujitsu.com>
>>> ---
>>>    src/idmapped-mounts/idmapped-mounts.c | 19 +++++++++++++++----
>>>    tests/generic/999                     | 26 ++++++++++++++++++++++++++
>>>    tests/generic/999.out                 |  2 ++
>>
>> I actually didn't mean to split out the existing setgid tests. I mean
>> adding new ones for the test-cases you're adding. But how you did it
>> works for me too and is a bit nicer. I don't have a strong opinion so as
>> long as Dave and Darrick are fine with it then this seems good to me.
> Ok, let's listen ..
When I write v3, I add mknodat patch as 1st patch and tmpfile as 2nd 
patch(by using a file doesn't under DIR1 directory, so I don't need to 
concern about xfs_irix_sgid_inherit_enabled), errno reset to 0 as 3st 
patch. It seems this way can't introduce the new failure for generic/633.

So I will add a new group for umask and acl and add new case for them 
instead of split setgid case from test-core group.

ps: I doubt whether I need to send two patch sets(one is about 
mknodat,tmpfile,errno, the another is about umask,acl,new case).
What do you think about this?

Best Regards
Yang Xu
>>
>> One note about the test name/numbering though. It seems you haven't
>> added the test using the provided xfstest infrastructure to do that.
>> Instead of manually adding the test you should run the "new" script.
>>
>> You should run:
>>
>>           ~/src/git/xfstests$ ./new generic
>>
>>           Next test id is 678
>>           Append a name to the ID? Test name will be 678-$name. y,[n]:
>>           Creating test file '678'
>>           Add to group(s) [auto] (separate by space, ? for list): auto quick attr idmapped mount perms
>>           Creating skeletal script for you to edit ...
>>
>> that'll automatically figure out the correct test number etc.
> Thanks, TBH, I don't know this usage. I don't name to 678 because
> fstests patchwork has others new case(in reviewing), so I add a biger
> number.
>
> Best Regards
> Yang Xu

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/6] idmapped-mount: split setgid test from test-core
  2022-04-08 10:17     ` xuyang2018.jy
@ 2022-04-08 10:33       ` Christian Brauner
  0 siblings, 0 replies; 19+ messages in thread
From: Christian Brauner @ 2022-04-08 10:33 UTC (permalink / raw)
  To: xuyang2018.jy; +Cc: david, djwong, linux-fsdevel, fstests

On Fri, Apr 08, 2022 at 10:17:34AM +0000, xuyang2018.jy@fujitsu.com wrote:
> on 2022/4/8 9:20, xuyang2018.jy@fujitsu.com wrote:
> > on 2022/4/7 20:55, Christian Brauner wrote:
> >> On Thu, Apr 07, 2022 at 08:09:30PM +0800, Yang Xu wrote:
> >>> Since we plan to increase setgid test covertage, it will find new bug
> >>> , so add a new test group test-setgid is better.
> >>>
> >>> Also add a new test case to test test-setgid instead of miss it.
> >>>
> >>> Signed-off-by: Yang Xu<xuyang2018.jy@fujitsu.com>
> >>> ---
> >>>    src/idmapped-mounts/idmapped-mounts.c | 19 +++++++++++++++----
> >>>    tests/generic/999                     | 26 ++++++++++++++++++++++++++
> >>>    tests/generic/999.out                 |  2 ++
> >>
> >> I actually didn't mean to split out the existing setgid tests. I mean
> >> adding new ones for the test-cases you're adding. But how you did it
> >> works for me too and is a bit nicer. I don't have a strong opinion so as
> >> long as Dave and Darrick are fine with it then this seems good to me.
> > Ok, let's listen ..
> When I write v3, I add mknodat patch as 1st patch and tmpfile as 2nd 
> patch(by using a file doesn't under DIR1 directory, so I don't need to 
> concern about xfs_irix_sgid_inherit_enabled), errno reset to 0 as 3st 
> patch. It seems this way can't introduce the new failure for generic/633.

Sure.

> 
> So I will add a new group for umask and acl and add new case for them 
> instead of split setgid case from test-core group.

Yes. What I'd expect to see is something like:

struct t_idmapped_mounts t_setgid_umask[] = {
	{ setgid_create_umask,						false,	"blabla",     },
	{ setgid_create_umask_idmapped,					true,	"blabla",     },
	{ setgid_create_umask_idmapped_in_userns,			true,	"blabla",     },
};

struct t_idmapped_mounts t_setgid_acl[] = {
	{ setgid_create_acl,						false,	"blabla",	},
	{ setgid_create_acl_idmapped,					true,	"blabla",	},
	{ setgid_create_acl_idmapped_in_userns,				true,	"blabla",	},
};

and two command line switches:

--test-setgid-umask
--test-setgid-acl

and two tests:

generic/<idx>
generic/<idx + 1>

where one of them calls:

--test-setgid-umask

and the other one:

--test-setgid-acl

That's roughly how I think it should work. But if you have a better
approach, please propose it.

> 
> ps: I doubt whether I need to send two patch sets(one is about 
> mknodat,tmpfile,errno, the another is about umask,acl,new case).
> What do you think about this?

I think a single patch _series_ with multiple patches:
1. errno bugfix
2. mknodat()
3. tmpfile()
4. umask & new test case for it as sm like generic/<idx>
4. acl & new test case for it as sm like generic/<idx + 1>

Christian

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2022-04-08 10:34 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-07 12:09 [PATCH v2 1/6] idmapped-mount: split setgid test from test-core Yang Xu
2022-04-07 12:09 ` [PATCH v2 2/6] idmapped-mounts: Add mknodat operation in setgid test Yang Xu
2022-04-07 13:40   ` Christian Brauner
2022-04-08  3:02     ` xuyang2018.jy
2022-04-07 12:09 ` [PATCH v2 3/6] idmapped-mounts: Reset errno to zero after detect fs_allow_idmap Yang Xu
2022-04-07 12:59   ` Christian Brauner
2022-04-07 12:09 ` [PATCH v2 4/6] idmapped-mounts: Add umask(S_IXGRP) wrapper for setgid_create* cases Yang Xu
2022-04-07 15:12   ` Christian Brauner
2022-04-08  3:38     ` xuyang2018.jy
2022-04-07 12:09 ` [PATCH v2 5/6] idmapped-mounts: Add setfacl(S_IXGRP) " Yang Xu
2022-04-07 12:09 ` [PATCH v2 6/6] idmapped-mounts: Add open with O_TMPFILE operation in setgid test Yang Xu
2022-04-07 13:43   ` Christian Brauner
2022-04-08  3:58     ` xuyang2018.jy
2022-04-08  7:34       ` Zorro Lang
2022-04-08  7:55         ` xuyang2018.jy
2022-04-07 12:55 ` [PATCH v2 1/6] idmapped-mount: split setgid test from test-core Christian Brauner
2022-04-08  1:20   ` xuyang2018.jy
2022-04-08 10:17     ` xuyang2018.jy
2022-04-08 10:33       ` Christian Brauner

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.