xfs: use generic posix ACL infrastructure
authorChristoph Hellwig <hch@infradead.org>
Fri, 20 Dec 2013 13:16:50 +0000 (05:16 -0800)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 26 Jan 2014 04:58:21 +0000 (23:58 -0500)
Also don't bother to set up a .get_acl method for symlinks as we do not
support access control (ACLs or even mode bits) for symlinks in Linux,
and create inodes with the proper mode instead of fixing it up later.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/xfs/xfs_acl.c
fs/xfs/xfs_acl.h
fs/xfs/xfs_iops.c
fs/xfs/xfs_iops.h
fs/xfs/xfs_xattr.c

index 057ae2d502dc2bf2559b0ada386d493cdc563e2b..0ecec1896f25439f198c53c93bc058ff3bff9c89 100644 (file)
@@ -124,16 +124,12 @@ struct posix_acl *
 xfs_get_acl(struct inode *inode, int type)
 {
        struct xfs_inode *ip = XFS_I(inode);
-       struct posix_acl *acl;
+       struct posix_acl *acl = NULL;
        struct xfs_acl *xfs_acl;
        unsigned char *ea_name;
        int error;
        int len;
 
-       acl = get_cached_acl(inode, type);
-       if (acl != ACL_NOT_CACHED)
-               return acl;
-
        trace_xfs_get_acl(ip);
 
        switch (type) {
@@ -164,10 +160,8 @@ xfs_get_acl(struct inode *inode, int type)
                 * cache entry, for any other error assume it is transient and
                 * leave the cache entry as ACL_NOT_CACHED.
                 */
-               if (error == -ENOATTR) {
-                       acl = NULL;
+               if (error == -ENOATTR)
                        goto out_update_cache;
-               }
                goto out;
        }
 
@@ -183,15 +177,12 @@ out:
 }
 
 STATIC int
-xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+__xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
 {
        struct xfs_inode *ip = XFS_I(inode);
        unsigned char *ea_name;
        int error;
 
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
        switch (type) {
        case ACL_TYPE_ACCESS:
                ea_name = SGI_ACL_FILE;
@@ -282,131 +273,23 @@ posix_acl_default_exists(struct inode *inode)
        return xfs_acl_exists(inode, SGI_ACL_DEFAULT);
 }
 
-/*
- * No need for i_mutex because the inode is not yet exposed to the VFS.
- */
 int
-xfs_inherit_acl(struct inode *inode, struct posix_acl *acl)
+xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
-       umode_t mode = inode->i_mode;
-       int error = 0, inherit = 0;
-
-       if (S_ISDIR(inode->i_mode)) {
-               error = xfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
-               if (error)
-                       goto out;
-       }
-
-       error = __posix_acl_create(&acl, GFP_KERNEL, &mode);
-       if (error < 0)
-               return error;
-
-       /*
-        * If __posix_acl_create returns a positive value we need to
-        * inherit a permission that can't be represented using the Unix
-        * mode bits and we actually need to set an ACL.
-        */
-       if (error > 0)
-               inherit = 1;
-
-       error = xfs_set_mode(inode, mode);
-       if (error)
-               goto out;
-
-       if (inherit)
-               error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl);
-
-out:
-       posix_acl_release(acl);
-       return error;
-}
-
-int
-xfs_acl_chmod(struct inode *inode)
-{
-       struct posix_acl *acl;
-       int error;
-
-       if (S_ISLNK(inode->i_mode))
-               return -EOPNOTSUPP;
-
-       acl = xfs_get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR(acl) || !acl)
-               return PTR_ERR(acl);
-
-       error = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
-       if (error)
-               return error;
-
-       error = xfs_set_acl(inode, ACL_TYPE_ACCESS, acl);
-       posix_acl_release(acl);
-       return error;
-}
-
-static int
-xfs_xattr_acl_get(struct dentry *dentry, const char *name,
-               void *value, size_t size, int type)
-{
-       struct posix_acl *acl;
-       int error;
-
-       acl = xfs_get_acl(dentry->d_inode, type);
-       if (IS_ERR(acl))
-               return PTR_ERR(acl);
-       if (acl == NULL)
-               return -ENODATA;
-
-       error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
-       posix_acl_release(acl);
-
-       return error;
-}
-
-static int
-xfs_xattr_acl_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
-{
-       struct inode *inode = dentry->d_inode;
-       struct posix_acl *acl = NULL;
        int error = 0;
 
-       if (flags & XATTR_CREATE)
-               return -EINVAL;
-       if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
-               return value ? -EACCES : 0;
-       if (!inode_owner_or_capable(inode))
-               return -EPERM;
-
-       if (!value)
+       if (!acl)
                goto set_acl;
 
-       acl = posix_acl_from_xattr(&init_user_ns, value, size);
-       if (!acl) {
-               /*
-                * acl_set_file(3) may request that we set default ACLs with
-                * zero length -- defend (gracefully) against that here.
-                */
-               goto out;
-       }
-       if (IS_ERR(acl)) {
-               error = PTR_ERR(acl);
-               goto out;
-       }
-
-       error = posix_acl_valid(acl);
-       if (error)
-               goto out_release;
-
        error = -EINVAL;
        if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb)))
-               goto out_release;
+               return error;
 
        if (type == ACL_TYPE_ACCESS) {
                umode_t mode = inode->i_mode;
                error = posix_acl_equiv_mode(acl, &mode);
 
                if (error <= 0) {
-                       posix_acl_release(acl);
                        acl = NULL;
 
                        if (error < 0)
@@ -415,27 +298,9 @@ xfs_xattr_acl_set(struct dentry *dentry, const char *name,
 
                error = xfs_set_mode(inode, mode);
                if (error)
-                       goto out_release;
+                       return error;
        }
 
  set_acl:
-       error = xfs_set_acl(inode, type, acl);
- out_release:
-       posix_acl_release(acl);
- out:
-       return error;
+       return __xfs_set_acl(inode, type, acl);
 }
-
-const struct xattr_handler xfs_xattr_acl_access_handler = {
-       .prefix = POSIX_ACL_XATTR_ACCESS,
-       .flags  = ACL_TYPE_ACCESS,
-       .get    = xfs_xattr_acl_get,
-       .set    = xfs_xattr_acl_set,
-};
-
-const struct xattr_handler xfs_xattr_acl_default_handler = {
-       .prefix = POSIX_ACL_XATTR_DEFAULT,
-       .flags  = ACL_TYPE_DEFAULT,
-       .get    = xfs_xattr_acl_get,
-       .set    = xfs_xattr_acl_set,
-};
index 4016a567b83cc2e00d46b5f4629bfc83785a7dff..5dc163744511b7c4de1f93e1dd33080d8becd062 100644 (file)
@@ -60,20 +60,15 @@ struct xfs_acl {
 
 #ifdef CONFIG_XFS_POSIX_ACL
 extern struct posix_acl *xfs_get_acl(struct inode *inode, int type);
-extern int xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl);
-extern int xfs_acl_chmod(struct inode *inode);
+extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
 extern int posix_acl_access_exists(struct inode *inode);
 extern int posix_acl_default_exists(struct inode *inode);
-
-extern const struct xattr_handler xfs_xattr_acl_access_handler;
-extern const struct xattr_handler xfs_xattr_acl_default_handler;
 #else
 static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type)
 {
        return NULL;
 }
-# define xfs_inherit_acl(inode, default_acl)           0
-# define xfs_acl_chmod(inode)                          0
+# define xfs_set_acl                                   NULL
 # define posix_acl_access_exists(inode)                        0
 # define posix_acl_default_exists(inode)               0
 #endif /* CONFIG_XFS_POSIX_ACL */
index a3dad17b135159602e15ad767d5dd57cf6cdaeeb..d47fbee3121e50fe9a0b4104fcb6df75c21e13be 100644 (file)
@@ -123,7 +123,7 @@ xfs_vn_mknod(
 {
        struct inode    *inode;
        struct xfs_inode *ip = NULL;
-       struct posix_acl *default_acl = NULL;
+       struct posix_acl *default_acl, *acl;
        struct xfs_name name;
        int             error;
 
@@ -139,14 +139,9 @@ xfs_vn_mknod(
                rdev = 0;
        }
 
-       if (IS_POSIXACL(dir)) {
-               default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT);
-               if (IS_ERR(default_acl))
-                       return PTR_ERR(default_acl);
-
-               if (!default_acl)
-                       mode &= ~current_umask();
-       }
+       error = posix_acl_create(dir, &mode, &default_acl, &acl);
+       if (error)
+               return error;
 
        xfs_dentry_to_name(&name, dentry, mode);
        error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
@@ -159,22 +154,30 @@ xfs_vn_mknod(
        if (unlikely(error))
                goto out_cleanup_inode;
 
+#ifdef CONFIG_XFS_POSIX_ACL
        if (default_acl) {
-               error = -xfs_inherit_acl(inode, default_acl);
-               default_acl = NULL;
-               if (unlikely(error))
+               error = xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+               if (error)
                        goto out_cleanup_inode;
        }
-
+       if (acl) {
+               error = xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
+               if (error)
+                       goto out_cleanup_inode;
+       }
+#endif
 
        d_instantiate(dentry, inode);
+ out_free_acl:
+       if (default_acl)
+               posix_acl_release(default_acl);
+       if (acl)
+               posix_acl_release(acl);
        return -error;
 
  out_cleanup_inode:
        xfs_cleanup_inode(dir, inode, dentry);
- out_free_acl:
-       posix_acl_release(default_acl);
-       return -error;
+       goto out_free_acl;
 }
 
 STATIC int
@@ -672,7 +675,7 @@ xfs_setattr_nonsize(
         *           Posix ACL code seems to care about this issue either.
         */
        if ((mask & ATTR_MODE) && !(flags & XFS_ATTR_NOACL)) {
-               error = -xfs_acl_chmod(inode);
+               error = -posix_acl_chmod(inode, inode->i_mode);
                if (error)
                        return XFS_ERROR(error);
        }
@@ -1041,6 +1044,7 @@ xfs_vn_fiemap(
 
 static const struct inode_operations xfs_inode_operations = {
        .get_acl                = xfs_get_acl,
+       .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
@@ -1068,6 +1072,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
        .mknod                  = xfs_vn_mknod,
        .rename                 = xfs_vn_rename,
        .get_acl                = xfs_get_acl,
+       .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
@@ -1094,6 +1099,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
        .mknod                  = xfs_vn_mknod,
        .rename                 = xfs_vn_rename,
        .get_acl                = xfs_get_acl,
+       .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
@@ -1107,7 +1113,6 @@ static const struct inode_operations xfs_symlink_inode_operations = {
        .readlink               = generic_readlink,
        .follow_link            = xfs_vn_follow_link,
        .put_link               = kfree_put_link,
-       .get_acl                = xfs_get_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
index d2c5057b5cc4b4b701d05478e045cbf02a3ed408..1c34e4335920021d5829c5507be2f2c6c6bf60e1 100644 (file)
@@ -30,7 +30,7 @@ extern void xfs_setup_inode(struct xfs_inode *);
 /*
  * Internal setattr interfaces.
  */
-#define XFS_ATTR_NOACL         0x01    /* Don't call xfs_acl_chmod */
+#define XFS_ATTR_NOACL         0x01    /* Don't call posix_acl_chmod */
 
 extern int xfs_setattr_nonsize(struct xfs_inode *ip, struct iattr *vap,
                               int flags);
index 9d479073ba415d6b482fbecbf160b6b99e4e859c..78ed92a46fdd3323c9bada9a35257f839285c630 100644 (file)
@@ -102,8 +102,8 @@ const struct xattr_handler *xfs_xattr_handlers[] = {
        &xfs_xattr_trusted_handler,
        &xfs_xattr_security_handler,
 #ifdef CONFIG_XFS_POSIX_ACL
-       &xfs_xattr_acl_access_handler,
-       &xfs_xattr_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
 #endif
        NULL
 };