From 00cffb69405ad01fe7e9354fc4bcba6b4a5ed6ea Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Mon, 22 Aug 2016 17:22:11 +0200 Subject: [PATCH] ovl: Switch to generic_removexattr Commit d837a49bd57f ("ovl: fix POSIX ACL setting") switches from iop->setxattr from ovl_setxattr to generic_setxattr, so switch from ovl_removexattr to generic_removexattr as well. As far as permission checking goes, the same rules should apply in either case. While doing that, rename ovl_setxattr to ovl_xattr_set to indicate that this is not an iop->setxattr implementation and remove the unused inode argument. Move ovl_other_xattr_set above ovl_own_xattr_set so that they match the order of handlers in ovl_xattr_handlers. Signed-off-by: Andreas Gruenbacher Fixes: d837a49bd57f ("ovl: fix POSIX ACL setting") Signed-off-by: Miklos Szeredi Signed-off-by: Shan Hai Orabug: 26401569 (backport upstream commit 0e585ccc13b3edbb187fb4f1b7cc9397f17d64a9) Signed-off-by: Shan Hai Reviewed-by: Somasundaram Krishnasamy --- fs/overlayfs/dir.c | 2 +- fs/overlayfs/inode.c | 66 +++++++++++++--------------------------- fs/overlayfs/overlayfs.h | 5 ++- fs/overlayfs/super.c | 16 +++++----- 4 files changed, 32 insertions(+), 57 deletions(-) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index f4acef9dc1da..0149221bba43 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -960,7 +960,7 @@ const struct inode_operations ovl_dir_inode_operations = { .setxattr = generic_setxattr, .getxattr = ovl_getxattr, .listxattr = ovl_listxattr, - .removexattr = ovl_removexattr, + .removexattr = generic_removexattr, .get_acl = ovl_get_acl, .update_time = ovl_update_time, }; diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 23a6f2f30b39..7907411d23a6 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -217,24 +217,38 @@ static bool ovl_is_private_xattr(const char *name) sizeof(OVL_XATTR_PREFIX) - 1) == 0; } -int ovl_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) +int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags) { int err; - struct dentry *upperdentry; + struct path realpath; + enum ovl_path_type type = ovl_path_real(dentry, &realpath); const struct cred *old_cred; err = ovl_want_write(dentry); if (err) goto out; + if (!value && !OVL_TYPE_UPPER(type)) { + err = vfs_getxattr(realpath.dentry, name, NULL, 0); + if (err < 0) + goto out_drop_write; + } + err = ovl_copy_up(dentry); if (err) goto out_drop_write; - upperdentry = ovl_dentry_upper(dentry); + if (!OVL_TYPE_UPPER(type)) + ovl_path_upper(dentry, &realpath); + old_cred = ovl_override_creds(dentry->d_sb); - err = vfs_setxattr(upperdentry, name, value, size, flags); + if (value) + err = vfs_setxattr(realpath.dentry, name, value, size, flags); + else { + WARN_ON(flags != XATTR_REPLACE); + err = vfs_removexattr(realpath.dentry, name); + } revert_creds(old_cred); out_drop_write: @@ -290,44 +304,6 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) return res; } -int ovl_removexattr(struct dentry *dentry, const char *name) -{ - int err; - struct path realpath; - enum ovl_path_type type = ovl_path_real(dentry, &realpath); - const struct cred *old_cred; - - err = ovl_want_write(dentry); - if (err) - goto out; - - err = -ENODATA; - if (ovl_is_private_xattr(name)) - goto out_drop_write; - - if (!OVL_TYPE_UPPER(type)) { - old_cred = ovl_override_creds(dentry->d_sb); - err = vfs_getxattr(realpath.dentry, name, NULL, 0); - revert_creds(old_cred); - if (err < 0) - goto out_drop_write; - - err = ovl_copy_up(dentry); - if (err) - goto out_drop_write; - - ovl_path_upper(dentry, &realpath); - } - - old_cred = ovl_override_creds(dentry->d_sb); - err = vfs_removexattr(realpath.dentry, name); - revert_creds(old_cred); -out_drop_write: - ovl_drop_write(dentry); -out: - return err; -} - struct posix_acl *ovl_get_acl(struct inode *inode, int type) { struct inode *realinode = ovl_inode_real(inode, NULL); @@ -424,7 +400,7 @@ static const struct inode_operations ovl_file_inode_operations = { .setxattr = generic_setxattr, .getxattr = ovl_getxattr, .listxattr = ovl_listxattr, - .removexattr = ovl_removexattr, + .removexattr = generic_removexattr, .get_acl = ovl_get_acl, .update_time = ovl_update_time, }; @@ -438,7 +414,7 @@ static const struct inode_operations ovl_symlink_inode_operations = { .setxattr = generic_setxattr, .getxattr = ovl_getxattr, .listxattr = ovl_listxattr, - .removexattr = ovl_removexattr, + .removexattr = generic_removexattr, .update_time = ovl_update_time, }; diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index febcfb6b989e..f4784b824bba 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -183,12 +183,11 @@ int ovl_check_d_type_supported(struct path *realpath); /* inode.c */ int ovl_setattr(struct dentry *dentry, struct iattr *attr); int ovl_permission(struct inode *inode, int mask); -int ovl_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags); +int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags); ssize_t ovl_getxattr(struct dentry *dentry, const char *name, void *value, size_t size); ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); -int ovl_removexattr(struct dentry *dentry, const char *name); struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags); struct posix_acl *ovl_get_acl(struct inode *inode, int type); int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags); diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 72ef31afbdfc..82455d52f8fe 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -893,20 +893,13 @@ static int ovl_posix_acl_xattr_set(struct dentry *dentry, const char *name, posix_acl_release(acl); - return ovl_setxattr(dentry, name, value, size, flags); + return ovl_xattr_set(dentry, name, value, size, flags); out_acl_release: posix_acl_release(acl); return err; } -static int ovl_other_xattr_set(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags, - int handler_flags) -{ - return ovl_setxattr(dentry, name, value, size, flags); -} - static int ovl_own_xattr_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int handler_flags) @@ -914,6 +907,13 @@ static int ovl_own_xattr_set(struct dentry *dentry, const char *name, return -EPERM; } +static int ovl_other_xattr_set(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags, + int handler_flags) +{ + return ovl_xattr_set(dentry, name, value, size, flags); +} + static const struct xattr_handler __maybe_unused ovl_posix_acl_access_xattr_handler = { .prefix = XATTR_NAME_POSIX_ACL_ACCESS, -- 2.50.1