All of lore.kernel.org
 help / color / mirror / Atom feed
From: "xuyang2018.jy@fujitsu.com" <xuyang2018.jy@fujitsu.com>
To: Christian Brauner <brauner@kernel.org>
Cc: "david@fromorbit.com" <david@fromorbit.com>,
	"djwong@kernel.org" <djwong@kernel.org>,
	"linux-fsdevel@vger.kernel.org" <linux-fsdevel@vger.kernel.org>,
	"fstests@vger.kernel.org" <fstests@vger.kernel.org>
Subject: Re: [PATCH v3 4/5] idmapped-mounts: Add new setgid_create_umask test
Date: Wed, 13 Apr 2022 09:45:11 +0000	[thread overview]
Message-ID: <6256A9F2.2030801@fujitsu.com> (raw)
In-Reply-To: <20220413085946.bh2cii5q5isx2odr@wittgenstein>

on 2022/4/13 16:59, Christian Brauner wrote:
> On Tue, Apr 12, 2022 at 07:33:45PM +0800, Yang Xu wrote:
>> 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.
>>
>> Here we only use umask(S_IXGRP) to check whether inode strip
>> S_ISGID works correctly.
>>
>> Signed-off-by: Yang Xu<xuyang2018.jy@fujitsu.com>
>> ---
>>   src/idmapped-mounts/idmapped-mounts.c | 505 +++++++++++++++++++++++++-
>>   tests/generic/680                     |  26 ++
>>   tests/generic/680.out                 |   2 +
>>   3 files changed, 532 insertions(+), 1 deletion(-)
>>   create mode 100755 tests/generic/680
>>   create mode 100644 tests/generic/680.out
>>
>> diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c
>> index 02f91558..e6c14586 100644
>> --- a/src/idmapped-mounts/idmapped-mounts.c
>> +++ b/src/idmapped-mounts/idmapped-mounts.c
>> @@ -14146,6 +14146,494 @@ out:
>>   	return fret;
>>   }
>>
>> +/* The following tests are concerned with setgid inheritance. These can be
>> + * 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 inheritthe
>> + * setgid bit if the caller is in the group of the directory.
>> + *
>> + * 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.
>> + *
>> + * Use umask(S_IXGRP) to check whether inode strip S_ISGID works correctly.
>> + */
>> +static int setgid_create_umask(void)
>> +{
>> +	int fret = -1;
>> +	int file1_fd = -EBADF;
>> +	int tmpfile_fd = -EBADF;
>> +	pid_t pid;
>> +	bool supported = false;
>> +	char path[PATH_MAX];
>> +	mode_t mode;
>> +
>> +	if (!caps_supported())
>> +		return 0;
>> +
>> +	if (fchmod(t_dir1_fd, S_IRUSR |
>> +			      S_IWUSR |
>> +			      S_IRGRP |
>> +			      S_IWGRP |
>> +			      S_IROTH |
>> +			      S_IWOTH |
>> +			      S_IXUSR |
>> +			      S_IXGRP |
>> +			      S_IXOTH |
>> +			      S_ISGID), 0) {
>> +		log_stderr("failure: fchmod");
>> +		goto out;
>> +	}
>> +
>> +	   /* Verify that the setgid bit got raised. */
>> +	if (!is_setgid(t_dir1_fd, "", AT_EMPTY_PATH)) {
>> +		log_stderr("failure: is_setgid");
>> +		goto out;
>> +	}
>> +
>> +	supported = openat_tmpfile_supported(t_dir1_fd);
>> +
>> +	/* Only umask with S_IXGRP because inode strip S_ISGID will check mode
>> +	 * whether has group execute or search permission.
>> +	 */
>> +	umask(S_IXGRP);
>> +	mode = umask(S_IXGRP);
>> +	if (!(mode&  S_IXGRP))
>> +		die("failure: umask");
>> +
>> +	pid = fork();
>> +	if (pid<  0) {
>> +		log_stderr("failure: fork");
>> +		goto out;
>> +	}
>> +	if (pid == 0) {
>> +		if (!switch_ids(0, 10000))
>> +			die("failure: switch_ids");
>> +
>> +		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);
>> +		if (file1_fd<  0)
>> +			die("failure: create");
>> +
>> +		/* Neither in_group_p() nor capable_wrt_inode_uidgid() so setgid
>> +		 * bit needs to be stripped.
>> +		 */
>> +		if (is_setgid(t_dir1_fd, FILE1, 0))
>> +			die("failure: is_setgid");
>
> This test is wrong. Specifically, it is a false positive. I have
> explained this in more detail on v2 of this patchset.
>
> You want to test that umask(S_IXGRP) + setgid inheritance work together
> correctly. First, we need to establish what that means because from your
> patch series it at least seems to me as you're not completely clear
> about what you want to test just yet.
>
> A requested setgid bit for a non-directory object is only considered for
> stripping if S_IXGRP is simultaneously requested. In other words, both
> S_SISGID and S_IXGRP must be requested for the new file in order for
> additional checks such as CAP_FSETID to become relevant.
Yes, only keep S_IXGRP, then we can run into the next judgement for 
group and cap_fsetid.
>
> We need to distinguish two cases afaict:
>
> 1. The filesystem does support ACLs and has an applicable ACL
> -------------------------------------------------------------
>
> umask(S_IXGRP) is not used by the kernel and thus S_IXGRP is not
> stripped (unless the ACL does make it so) and so when e.g.
> inode_init_owner() is called we do not expect the file to inherit the
> setgid bit.
>
> This is what your test above is handling correctly. But it is a false
> positive because what you're trying to test is the behavior of
> umask(S_IXGRP) but it is made irrelevant by ACL support of the
> underlying filesystem.
I test this situation in the next patch as below:
umask(S_IXGRP);
snprintf(t_buf, sizeof(t_buf), "setfacl -d -m u::rwx,g::rwx,o::rwx,m:rw 
%s/%s", t_mountpoint, T_DIR1)

and
umask(S_IXGRP);
snprintf(t_buf, sizeof(t_buf), "setfacl -d -m u::rwx,g::rw,o::rwx, 
%s/%s", t_mountpoint, T_DIR1

>
> 2. The filesystem does not support ACLs, has been mounted without
> -----------------------------------------------------------------
> support for it, or has no applicable ACL
> ----------------------------------------
>
> umask(S_IXGRP) is used by the kernel and will be stripped from the mode.
> So when inode_init_owner() is called we expect the file to inherit the
> setgid bit.
This is why my kernel patch put strip setgid code into vfs.
xfs will inherit the setgid bit but ext4 not because the new_inode 
function and posix_acl_create function order(S_IXGRP mode has been 
stripped before pass to inode_init_owner).
>
> This means the test for this case needs to be:
>
> 	file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
> 	if (file1_fd<  0)
> 		die("failure: create");
> 	
> 	/*
> 	 * S_IXGRP will have been removed due to umask(S_IXGRP) so we expect the
> 	 * new file to be S_ISGID.
No No No, see the kernel patch url
https://patchwork.kernel.org/project/linux-fsdevel/patch/1648461389-2225-2-git-send-email-xuyang2018.jy@fujitsu.com/
> 	 */
> 	if (!is_setgid(t_dir1_fd, FILE1, 0))
> 		die("failure: is_setgid");
>
> And additionally you might want to also add a new helper is_ixgrp() to
> add an additional check:
>
> /*
>   * S_IXGRP will have been removed due to umask(S_IXGRP) so we expect the
>   * new file to not be S_IXGRP.
>   */
> if (is_ixgrp(t_dir1_fd, FILE1, 0))
> 	die("failure: is_ixgrp");
This sound reasonable.
>
>
> ---
>
> So for the umask() tests you need to first check whether the underlying
> filesystem does support ACLs and remember that somewhere. If it does
> support ACLs, then you should first remove any ACLs set on the
> directories you're performing the tests on. Then you can run your
> umask() tests.
Yes, I can just add a remove step in the beginning.

ps: When I writing my v2 kernel patch, I found I still miss the GRPID 
testcase in fstests.

Best Regrads
Yang Xu

  reply	other threads:[~2022-04-13  9:46 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-12 11:33 [PATCH v3 1/5] idmapped-mounts: Reset errno to zero after detect fs_allow_idmap Yang Xu
2022-04-12 11:33 ` [PATCH v3 2/5] idmapped-mounts: Add mknodat operation in setgid test Yang Xu
2022-04-13  7:59   ` Christian Brauner
2022-04-13  8:31     ` xuyang2018.jy
2022-04-13  9:05       ` Christian Brauner
2022-04-12 11:33 ` [PATCH v3 3/5] idmapped-mounts: Add open with O_TMPFILE " Yang Xu
2022-04-13  8:07   ` Christian Brauner
2022-04-13  8:48     ` xuyang2018.jy
2022-04-12 11:33 ` [PATCH v3 4/5] idmapped-mounts: Add new setgid_create_umask test Yang Xu
2022-04-13  8:59   ` Christian Brauner
2022-04-13  9:45     ` xuyang2018.jy [this message]
2022-04-13  9:59       ` Christian Brauner
2022-04-13 10:09         ` xuyang2018.jy
2022-04-12 11:33 ` [PATCH v3 5/5] idmapped-mounts: Add new setgid_create_acl test Yang Xu
2022-04-13  7:50 ` [PATCH v3 1/5] idmapped-mounts: Reset errno to zero after detect fs_allow_idmap Christian Brauner
2022-05-07  1:33 ` xuyang2018.jy
2022-05-07  8:52   ` Zorro Lang
2022-05-07  9:12     ` xuyang2018.jy
2022-05-07 11:40     ` Christian Brauner
2022-05-07 12:26       ` Zorro Lang

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=6256A9F2.2030801@fujitsu.com \
    --to=xuyang2018.jy@fujitsu.com \
    --cc=brauner@kernel.org \
    --cc=david@fromorbit.com \
    --cc=djwong@kernel.org \
    --cc=fstests@vger.kernel.org \
    --cc=linux-fsdevel@vger.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.