From 9efa8de32dad33b5e43ee18ea3141dc1a259fa5e Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 30 Jul 2017 23:38:44 -0400 Subject: [PATCH] add patch dont-clear-sgid-when-inheriting-ACLs --- dont-clear-sgid-when-inheriting-ACLs | 90 ++++++++++++++++++++++++++++++++++++ series | 1 + timestamps | 7 +-- 3 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 dont-clear-sgid-when-inheriting-ACLs diff --git a/dont-clear-sgid-when-inheriting-ACLs b/dont-clear-sgid-when-inheriting-ACLs new file mode 100644 index 00000000..f8c2f1ed --- /dev/null +++ b/dont-clear-sgid-when-inheriting-ACLs @@ -0,0 +1,90 @@ +ext4: Don't clear SGID when inheriting ACLs + +From: Jan Kara + +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 +__ext4_set_acl() into ext4_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@vger.kernel.org +Signed-off-by: Theodore Ts'o +Signed-off-by: Jan Kara +Reviewed-by: Andreas Gruenbacher +--- + fs/ext4/acl.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c +index 2985cd0a640d..46ff2229ff5e 100644 +--- a/fs/ext4/acl.c ++++ b/fs/ext4/acl.c +@@ -189,18 +189,10 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type, + void *value = NULL; + size_t size = 0; + int error; +- int update_mode = 0; +- umode_t mode = inode->i_mode; + + switch (type) { + case ACL_TYPE_ACCESS: + name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; +- if (acl) { +- error = posix_acl_update_mode(inode, &mode, &acl); +- if (error) +- return error; +- update_mode = 1; +- } + break; + + case ACL_TYPE_DEFAULT: +@@ -224,11 +216,6 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type, + kfree(value); + if (!error) { + set_cached_acl(inode, type, acl); +- if (update_mode) { +- inode->i_mode = mode; +- inode->i_ctime = current_time(inode); +- ext4_mark_inode_dirty(handle, inode); +- } + } + + return error; +@@ -240,6 +227,8 @@ ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type) + handle_t *handle; + int error, credits, retries = 0; + size_t acl_size = acl ? ext4_acl_size(acl->a_count) : 0; ++ umode_t mode = inode->i_mode; ++ int update_mode = 0; + + error = dquot_initialize(inode); + if (error) +@@ -254,7 +243,20 @@ ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type) + if (IS_ERR(handle)) + return PTR_ERR(handle); + ++ if ((type == ACL_TYPE_ACCESS) && acl) { ++ error = posix_acl_update_mode(inode, &mode, &acl); ++ if (error) ++ goto out_stop; ++ update_mode = 1; ++ } ++ + error = __ext4_set_acl(handle, inode, type, acl, 0 /* xattr_flags */); ++ if (!error && update_mode) { ++ inode->i_mode = mode; ++ inode->i_ctime = current_time(inode); ++ ext4_mark_inode_dirty(handle, inode); ++ } ++out_stop: + ext4_journal_stop(handle); + if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) + goto retry; diff --git a/series b/series index 0ffb02b2..d07c233d 100644 --- a/series +++ b/series @@ -3,6 +3,7 @@ correct-comment-references-to-ext4_ext_direct_IO remove-unused-metadata-accounting-variables preserve-i_mode-if-ext4_set_acl-fails +dont-clear-sgid-when-inheriting-ACLs #################################################### # unstable patches diff --git a/timestamps b/timestamps index 3b0d8210..9d7acf6c 100755 --- a/timestamps +++ b/timestamps @@ -36,6 +36,7 @@ touch -d @1501467224 add-ext4-journal-lazy-mount-option touch -d @1501468000 correct-comment-references-to-ext4_ext_direct_IO touch -d @1501468211 remove-unused-metadata-accounting-variables touch -d @1501469021 preserve-i_mode-if-ext4_set_acl-fails -touch -d @1501469044 series -touch -d @1501469048 status -touch -d @1501469052 timestamps +touch -d @1501469199 series +touch -d @1501471981 dont-clear-sgid-when-inheriting-ACLs +touch -d @1501471981 status +touch -d @1501472316 timestamps -- 2.11.4.GIT