From 687c9324014dfdd106e333f7cf085335119b20fb Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 30 Jul 2017 22:44:19 -0400 Subject: [PATCH] add patch preserve-i_mode-if-ext4_set_acl-fails --- preserve-i_mode-if-ext4_set_acl-fails | 67 +++++++++++++++++++++++++++++++++++ series | 1 + timestamps | 7 ++-- 3 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 preserve-i_mode-if-ext4_set_acl-fails diff --git a/preserve-i_mode-if-ext4_set_acl-fails b/preserve-i_mode-if-ext4_set_acl-fails new file mode 100644 index 00000000..e5e50484 --- /dev/null +++ b/preserve-i_mode-if-ext4_set_acl-fails @@ -0,0 +1,67 @@ +ext4: preserve i_mode if __ext4_set_acl() fails + +From: "Ernesto A. Fernández" + +When changing a file's acl mask, __ext4_set_acl() will first set the group +bits of i_mode to the value of the mask, and only then set the actual +extended attribute representing the new acl. + +If the second part fails (due to lack of space, for example) and the file +had no acl attribute to begin with, the system will from now on assume +that the mask permission bits are actual group permission bits, potentially +granting access to the wrong users. + +Prevent this by only changing the inode mode after the acl has been set. + +Signed-off-by: Ernesto A. Fernández +Signed-off-by: Theodore Ts'o +Reviewed-by: Jan Kara +--- + fs/ext4/acl.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c +index 09441ae..2985cd0 100644 +--- a/fs/ext4/acl.c ++++ b/fs/ext4/acl.c +@@ -189,16 +189,17 @@ __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, &inode->i_mode, &acl); ++ error = posix_acl_update_mode(inode, &mode, &acl); + if (error) + return error; +- inode->i_ctime = current_time(inode); +- ext4_mark_inode_dirty(handle, inode); ++ update_mode = 1; + } + break; + +@@ -221,8 +222,14 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type, + value, size, xattr_flags); + + kfree(value); +- if (!error) ++ 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; + } +-- +2.1.4 + + diff --git a/series b/series index ae90f945..0ffb02b2 100644 --- a/series +++ b/series @@ -2,6 +2,7 @@ correct-comment-references-to-ext4_ext_direct_IO remove-unused-metadata-accounting-variables +preserve-i_mode-if-ext4_set_acl-fails #################################################### # unstable patches diff --git a/timestamps b/timestamps index faa34ea5..3b0d8210 100755 --- a/timestamps +++ b/timestamps @@ -35,6 +35,7 @@ touch -d @1501467223 load-jmap-from-journal 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 @1501468462 series -touch -d @1501468465 status -touch -d @1501468471 timestamps +touch -d @1501469021 preserve-i_mode-if-ext4_set_acl-fails +touch -d @1501469044 series +touch -d @1501469048 status +touch -d @1501469052 timestamps -- 2.11.4.GIT