fs/ntfs3: Restore ntfs_xattr_get_acl and ntfs_xattr_set_acl functions
authorKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Fri, 22 Oct 2021 15:15:36 +0000 (18:15 +0300)
committerKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Tue, 23 Nov 2021 15:56:01 +0000 (18:56 +0300)
Apparently we need to maintain these functions with
ntfs_get_acl_ex and ntfs_set_acl_ex.
This commit fixes xfstest generic/099
Fixes: 95dd8b2c1ed0 ("fs/ntfs3: Remove unnecessary functions")
Reviewed-by: Kari Argillander <kari.argillander@gmail.com>
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3/xattr.c

index afd0ddad826ff49f661ce758bcbecec46921fd1c..56e774d0f56ae8c6982b042cd28cae67d115fe4d 100644 (file)
@@ -112,7 +112,7 @@ static int ntfs_read_ea(struct ntfs_inode *ni, struct EA_FULL **ea,
                return -ENOMEM;
 
        if (!size) {
-               ;
+               /* EA info persists, but xattr is empty. Looks like EA problem. */
        } else if (attr_ea->non_res) {
                struct runs_tree run;
 
@@ -619,6 +619,67 @@ int ntfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
        return ntfs_set_acl_ex(mnt_userns, inode, acl, type);
 }
 
+static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns,
+                             struct inode *inode, int type, void *buffer,
+                             size_t size)
+{
+       struct posix_acl *acl;
+       int err;
+
+       if (!(inode->i_sb->s_flags & SB_POSIXACL)) {
+               ntfs_inode_warn(inode, "add mount option \"acl\" to use acl");
+               return -EOPNOTSUPP;
+       }
+
+       acl = ntfs_get_acl(inode, type, false);
+       if (IS_ERR(acl))
+               return PTR_ERR(acl);
+
+       if (!acl)
+               return -ENODATA;
+
+       err = posix_acl_to_xattr(mnt_userns, acl, buffer, size);
+       posix_acl_release(acl);
+
+       return err;
+}
+
+static int ntfs_xattr_set_acl(struct user_namespace *mnt_userns,
+                             struct inode *inode, int type, const void *value,
+                             size_t size)
+{
+       struct posix_acl *acl;
+       int err;
+
+       if (!(inode->i_sb->s_flags & SB_POSIXACL)) {
+               ntfs_inode_warn(inode, "add mount option \"acl\" to use acl");
+               return -EOPNOTSUPP;
+       }
+
+       if (!inode_owner_or_capable(mnt_userns, inode))
+               return -EPERM;
+
+       if (!value) {
+               acl = NULL;
+       } else {
+               acl = posix_acl_from_xattr(mnt_userns, value, size);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+
+               if (acl) {
+                       err = posix_acl_valid(mnt_userns, acl);
+                       if (err)
+                               goto release_and_out;
+               }
+       }
+
+       err = ntfs_set_acl(mnt_userns, inode, acl, type);
+
+release_and_out:
+       posix_acl_release(acl);
+       return err;
+}
+
 /*
  * ntfs_init_acl - Initialize the ACLs of a new inode.
  *
@@ -785,6 +846,23 @@ static int ntfs_getxattr(const struct xattr_handler *handler, struct dentry *de,
                goto out;
        }
 
+#ifdef CONFIG_NTFS3_FS_POSIX_ACL
+       if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 &&
+            !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS,
+                    sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) ||
+           (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 &&
+            !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
+                    sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) {
+               /* TODO: init_user_ns? */
+               err = ntfs_xattr_get_acl(
+                       &init_user_ns, inode,
+                       name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1
+                               ? ACL_TYPE_ACCESS
+                               : ACL_TYPE_DEFAULT,
+                       buffer, size);
+               goto out;
+       }
+#endif
        /* Deal with NTFS extended attribute. */
        err = ntfs_get_ea(inode, name, name_len, buffer, size, NULL);
 
@@ -897,6 +975,22 @@ set_new_fa:
                goto out;
        }
 
+#ifdef CONFIG_NTFS3_FS_POSIX_ACL
+       if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 &&
+            !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS,
+                    sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) ||
+           (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 &&
+            !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
+                    sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) {
+               err = ntfs_xattr_set_acl(
+                       mnt_userns, inode,
+                       name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1
+                               ? ACL_TYPE_ACCESS
+                               : ACL_TYPE_DEFAULT,
+                       value, size);
+               goto out;
+       }
+#endif
        /* Deal with NTFS extended attribute. */
        err = ntfs_set_ea(inode, name, name_len, value, size, flags);