Skip to content

Commit

Permalink
acl: don't depend on IOP_XATTR
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christian Brauner committed Mar 6, 2023
1 parent a1fbb60 commit e499214
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 9 deletions.
12 changes: 4 additions & 8 deletions fs/posix_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1131,12 +1131,10 @@ int vfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
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);
Expand Down Expand Up @@ -1241,12 +1239,10 @@ int vfs_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
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);
Expand Down
25 changes: 24 additions & 1 deletion fs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,28 @@ vfs_getxattr(struct mnt_idmap *idmap, struct dentry *dentry,
}
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)
{
Expand All @@ -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);
Expand Down

0 comments on commit e499214

Please sign in to comment.