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