summaryrefslogtreecommitdiffstats
path: root/fs/f2fs/acl.c
diff options
context:
space:
mode:
authorChao Yu <yuchao0@huawei.com>2020-12-25 16:52:27 +0800
committerJaegeuk Kim <jaegeuk@kernel.org>2021-01-27 15:20:00 -0800
commit17232e830afb800acdcc22ae8980bf9d330393ef (patch)
tree34ea7dfc5aef6aeadfc4dd47e2819de6eec82a33 /fs/f2fs/acl.c
parenta28d9aa1a2c7c774c38f2da1a662434bc29cb98e (diff)
downloadlinux-stable-17232e830afb800acdcc22ae8980bf9d330393ef.tar.gz
linux-stable-17232e830afb800acdcc22ae8980bf9d330393ef.tar.bz2
linux-stable-17232e830afb800acdcc22ae8980bf9d330393ef.zip
f2fs: enhance to update i_mode and acl atomically in f2fs_setattr()
Previously, in f2fs_setattr(), we don't update S_ISUID|S_ISGID|S_ISVTX bits with S_IRWXUGO bits and acl entries atomically, so in error path, chmod() may partially success, this patch enhances to make chmod() flow being atomical. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/acl.c')
-rw-r--r--fs/f2fs/acl.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 1e5e9b1136ee..732ec10e7890 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -200,6 +200,27 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
return __f2fs_get_acl(inode, type, NULL);
}
+static int f2fs_acl_update_mode(struct inode *inode, umode_t *mode_p,
+ struct posix_acl **acl)
+{
+ umode_t mode = inode->i_mode;
+ int error;
+
+ if (is_inode_flag_set(inode, FI_ACL_MODE))
+ mode = F2FS_I(inode)->i_acl_mode;
+
+ error = posix_acl_equiv_mode(*acl, &mode);
+ if (error < 0)
+ return error;
+ if (error == 0)
+ *acl = NULL;
+ if (!in_group_p(inode->i_gid) &&
+ !capable_wrt_inode_uidgid(inode, CAP_FSETID))
+ mode &= ~S_ISGID;
+ *mode_p = mode;
+ return 0;
+}
+
static int __f2fs_set_acl(struct inode *inode, int type,
struct posix_acl *acl, struct page *ipage)
{
@@ -213,7 +234,7 @@ static int __f2fs_set_acl(struct inode *inode, int type,
case ACL_TYPE_ACCESS:
name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl && !ipage) {
- error = posix_acl_update_mode(inode, &mode, &acl);
+ error = f2fs_acl_update_mode(inode, &mode, &acl);
if (error)
return error;
set_acl_inode(inode, mode);