Re: [PATCH 04/11] gfs2: Don't clear SGID when inheriting ACLs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu 22-06-17 15:31:08, Jan Kara wrote:
> When new directory 'DIR1' is created in a directory 'DIR0' with SGID bit
> set, DIR1 is expected to have SGID bit set (and owning group equal to
> the owning group of 'DIR0'). However when 'DIR0' also has some default
> ACLs that 'DIR1' inherits, setting these ACLs will result in SGID bit on
> 'DIR1' to get cleared if user is not member of the owning group.
> 
> Fix the problem by moving posix_acl_update_mode() out of
> __gfs2_set_acl() into gfs2_set_acl(). That way the function will not be
> called when inheriting ACLs which is what we want as it prevents SGID
> bit clearing and the mode has been properly set by posix_acl_create()
> anyway.
> 
> Fixes: 073931017b49d9458aa351605b43a7e34598caef
> CC: stable@xxxxxxxxxxxxxxx
> CC: cluster-devel@xxxxxxxxxx
> CC: Bob Peterson <rpeterso@xxxxxxxxxx>
> Signed-off-by: Jan Kara <jack@xxxxxxx>

Bob, can you please pick up this fix? Thanks!

								Honza

> ---
>  fs/gfs2/acl.c | 27 ++++++++++++++-------------
>  1 file changed, 14 insertions(+), 13 deletions(-)
> 
> diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
> index 2524807ee070..a6d962323790 100644
> --- a/fs/gfs2/acl.c
> +++ b/fs/gfs2/acl.c
> @@ -86,19 +86,6 @@ int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
>  	char *data;
>  	const char *name = gfs2_acl_name(type);
>  
> -	if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode)))
> -		return -E2BIG;
> -
> -	if (type == ACL_TYPE_ACCESS) {
> -		umode_t mode = inode->i_mode;
> -
> -		error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
> -		if (error)
> -			return error;
> -		if (mode != inode->i_mode)
> -			mark_inode_dirty(inode);
> -	}
> -
>  	if (acl) {
>  		len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0);
>  		if (len == 0)
> @@ -130,6 +117,9 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
>  	bool need_unlock = false;
>  	int ret;
>  
> +	if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode)))
> +		return -E2BIG;
> +
>  	ret = gfs2_rsqa_alloc(ip);
>  	if (ret)
>  		return ret;
> @@ -140,7 +130,18 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
>  			return ret;
>  		need_unlock = true;
>  	}
> +	if (type == ACL_TYPE_ACCESS && acl) {
> +		umode_t mode = inode->i_mode;
> +
> +		ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
> +		if (ret)
> +			goto unlock;
> +		if (mode != inode->i_mode)
> +			mark_inode_dirty(inode);
> +	}
> +
>  	ret = __gfs2_set_acl(inode, acl, type);
> +unlock:
>  	if (need_unlock)
>  		gfs2_glock_dq_uninit(&gh);
>  	return ret;
> -- 
> 2.12.3
> 
-- 
Jan Kara <jack@xxxxxxxx>
SUSE Labs, CR



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]