aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2017-07-19 11:56:42 -0400
committerBob Peterson <rpeterso@redhat.com>2017-07-19 11:58:54 -0400
commit914cea93dd89f00b41c1d8ff93f17be47356a36a (patch)
tree877c42ffbe2f7317bd27d8f5cd526b60211e5729
parent283c9a97be1d7ab2cce2630b5f6cc793f3b387a1 (diff)
gfs2: Don't clear SGID when inheriting ACLs
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 Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Bob Peterson <rpeterso@redhat.com>
-rw-r--r--fs/gfs2/acl.c27
1 files 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)
86 char *data; 86 char *data;
87 const char *name = gfs2_acl_name(type); 87 const char *name = gfs2_acl_name(type);
88 88
89 if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode)))
90 return -E2BIG;
91
92 if (type == ACL_TYPE_ACCESS) {
93 umode_t mode = inode->i_mode;
94
95 error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
96 if (error)
97 return error;
98 if (mode != inode->i_mode)
99 mark_inode_dirty(inode);
100 }
101
102 if (acl) { 89 if (acl) {
103 len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0); 90 len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0);
104 if (len == 0) 91 if (len == 0)
@@ -130,6 +117,9 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
130 bool need_unlock = false; 117 bool need_unlock = false;
131 int ret; 118 int ret;
132 119
120 if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode)))
121 return -E2BIG;
122
133 ret = gfs2_rsqa_alloc(ip); 123 ret = gfs2_rsqa_alloc(ip);
134 if (ret) 124 if (ret)
135 return ret; 125 return ret;
@@ -140,7 +130,18 @@ int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
140 return ret; 130 return ret;
141 need_unlock = true; 131 need_unlock = true;
142 } 132 }
133 if (type == ACL_TYPE_ACCESS && acl) {
134 umode_t mode = inode->i_mode;
135
136 ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
137 if (ret)
138 goto unlock;
139 if (mode != inode->i_mode)
140 mark_inode_dirty(inode);
141 }
142
143 ret = __gfs2_set_acl(inode, acl, type); 143 ret = __gfs2_set_acl(inode, acl, type);
144unlock:
144 if (need_unlock) 145 if (need_unlock)
145 gfs2_glock_dq_uninit(&gh); 146 gfs2_glock_dq_uninit(&gh);
146 return ret; 147 return ret;