acl: don't depend on IOP_XATTR
authorChristian Brauner <brauner@kernel.org>
Wed, 1 Feb 2023 13:15:01 +0000 (14:15 +0100)
committerChristian Brauner (Microsoft) <brauner@kernel.org>
Mon, 6 Mar 2023 08:59:20 +0000 (09:59 +0100)
All codepaths that don't want to implement POSIX ACLs should simply not
implement the associated inode operations instead of relying on
IOP_XATTR. That's the case for all filesystems today.

For vfs_listxattr() all filesystems that explicitly turn of xattrs for a
given inode all set inode->i_op to a dedicated set of inode operations
that doesn't implement ->listxattr().  We can remove the dependency of
vfs_listxattr() on IOP_XATTR.

Removing this dependency will allow us to decouple POSIX ACLs from
IOP_XATTR and they can still be listed even if no other xattr handlers
are implemented. Otherwise we would have to implement elaborate schemes
to raise IOP_XATTR even if sb->s_xattr is set to NULL.

Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
fs/posix_acl.c
fs/xattr.c

index e262c42..7fa1b73 100644 (file)
@@ -1131,12 +1131,10 @@ retry_deleg:
        if (error)
                goto out_inode_unlock;
 
-       if (inode->i_opflags & IOP_XATTR)
+       if (likely(!is_bad_inode(inode)))
                error = set_posix_acl(idmap, dentry, acl_type, kacl);
-       else if (unlikely(is_bad_inode(inode)))
-               error = -EIO;
        else
-               error = -EOPNOTSUPP;
+               error = -EIO;
        if (!error) {
                fsnotify_xattr(dentry);
                evm_inode_post_set_acl(dentry, acl_name, kacl);
@@ -1241,12 +1239,10 @@ retry_deleg:
        if (error)
                goto out_inode_unlock;
 
-       if (inode->i_opflags & IOP_XATTR)
+       if (likely(!is_bad_inode(inode)))
                error = set_posix_acl(idmap, dentry, acl_type, NULL);
-       else if (unlikely(is_bad_inode(inode)))
-               error = -EIO;
        else
-               error = -EOPNOTSUPP;
+               error = -EIO;
        if (!error) {
                fsnotify_xattr(dentry);
                evm_inode_post_remove_acl(idmap, dentry, acl_name);
index 95bb6b3..fcf67d8 100644 (file)
@@ -458,6 +458,28 @@ nolsm:
 }
 EXPORT_SYMBOL_GPL(vfs_getxattr);
 
+/**
+ * vfs_listxattr - retrieve \0 separated list of xattr names
+ * @dentry: the dentry from whose inode the xattr names are retrieved
+ * @list: buffer to store xattr names into
+ * @size: size of the buffer
+ *
+ * This function returns the names of all xattrs associated with the
+ * inode of @dentry.
+ *
+ * Note, for legacy reasons the vfs_listxattr() function lists POSIX
+ * ACLs as well. Since POSIX ACLs are decoupled from IOP_XATTR the
+ * vfs_listxattr() function doesn't check for this flag since a
+ * filesystem could implement POSIX ACLs without implementing any other
+ * xattrs.
+ *
+ * However, since all codepaths that remove IOP_XATTR also assign of
+ * inode operations that either don't implement or implement a stub
+ * ->listxattr() operation.
+ *
+ * Return: On success, the size of the buffer that was used. On error a
+ *         negative error code.
+ */
 ssize_t
 vfs_listxattr(struct dentry *dentry, char *list, size_t size)
 {
@@ -467,7 +489,8 @@ vfs_listxattr(struct dentry *dentry, char *list, size_t size)
        error = security_inode_listxattr(dentry);
        if (error)
                return error;
-       if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
+
+       if (inode->i_op->listxattr) {
                error = inode->i_op->listxattr(dentry, list, size);
        } else {
                error = security_inode_listsecurity(inode, list, size);