[PATCH v2 1/8] fs: don't use IOP_XATTR for posix acls

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The POSIX ACL api doesn't use the xattr handler infrastructure anymore.
If we keep relying on IOP_XATTR we will have to find a way to raise
IOP_XATTR during inode_init_always() if a filesystem doesn't implement
any xattrs other than POSIX ACLs. That's not done today but is in
principle possible. A prior version introduced SB_I_XATTR to this end.
Instead of this affecting all filesystems let those filesystems that
explicitly disable xattrs for some inodes disable POSIX ACLs by raising
IOP_NOACL.

Link: https://lore.kernel.org/linux-ext4/20230130091615.GB5178@xxxxxx
Signed-off-by: Christian Brauner (Microsoft) <brauner@xxxxxxxxxx>
---
Changes in v2:
- Patch introduced.
---
 fs/bad_inode.c         |  3 ++-
 fs/btrfs/inode.c       |  2 +-
 fs/libfs.c             |  3 ++-
 fs/overlayfs/copy_up.c |  4 ++--
 fs/posix_acl.c         |  4 ++--
 fs/reiserfs/inode.c    |  2 +-
 fs/reiserfs/namei.c    |  4 ++--
 fs/reiserfs/xattr.c    |  4 ++--
 fs/xattr.c             |  2 +-
 include/linux/fs.h     |  1 +
 include/linux/xattr.h  | 11 +++++++++++
 11 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 92737166203f..524e5e35b5d6 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -16,6 +16,7 @@
 #include <linux/namei.h>
 #include <linux/poll.h>
 #include <linux/fiemap.h>
+#include <linux/xattr.h>
 
 static int bad_file_open(struct inode *inode, struct file *filp)
 {
@@ -212,7 +213,7 @@ void make_bad_inode(struct inode *inode)
 	inode->i_atime = inode->i_mtime = inode->i_ctime =
 		current_time(inode);
 	inode->i_op = &bad_inode_ops;	
-	inode->i_opflags &= ~IOP_XATTR;
+	inode_xattr_disable(inode);
 	inode->i_fop = &bad_file_ops;	
 }
 EXPORT_SYMBOL(make_bad_inode);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 98a800b8bd43..c015e554d186 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5840,7 +5840,7 @@ static struct inode *new_simple_dir(struct super_block *s,
 	 * associated with the dentry
 	 */
 	inode->i_op = &simple_dir_inode_operations;
-	inode->i_opflags &= ~IOP_XATTR;
+	inode_xattr_disable(inode);
 	inode->i_fop = &simple_dir_operations;
 	inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
 	inode->i_mtime = current_time(inode);
diff --git a/fs/libfs.c b/fs/libfs.c
index aada4e7c8713..78052d91d60f 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -23,6 +23,7 @@
 #include <linux/fsnotify.h>
 #include <linux/unicode.h>
 #include <linux/fscrypt.h>
+#include <linux/xattr.h>
 
 #include <linux/uaccess.h>
 
@@ -1375,7 +1376,7 @@ void make_empty_dir_inode(struct inode *inode)
 	inode->i_blocks = 0;
 
 	inode->i_op = &empty_dir_inode_operations;
-	inode->i_opflags &= ~IOP_XATTR;
+	inode_xattr_disable(inode);
 	inode->i_fop = &empty_dir_operations;
 }
 
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index c14e90764e35..0b48f0aa9558 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -81,8 +81,8 @@ int ovl_copy_xattr(struct super_block *sb, const struct path *oldpath, struct de
 	int error = 0;
 	size_t slen;
 
-	if (!(old->d_inode->i_opflags & IOP_XATTR) ||
-	    !(new->d_inode->i_opflags & IOP_XATTR))
+	if (inode_xattr_disabled(old->d_inode) ||
+	    inode_xattr_disabled(new->d_inode))
 		return 0;
 
 	list_size = vfs_listxattr(old, NULL, 0);
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index d7bc81fc0840..315d3926a13a 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -1095,7 +1095,7 @@ int vfs_set_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
 	if (error)
 		goto out_inode_unlock;
 
-	if (inode->i_opflags & IOP_XATTR)
+	if (!(inode->i_opflags & IOP_NOACL))
 		error = set_posix_acl(mnt_userns, dentry, acl_type, kacl);
 	else if (unlikely(is_bad_inode(inode)))
 		error = -EIO;
@@ -1205,7 +1205,7 @@ int vfs_remove_acl(struct user_namespace *mnt_userns, struct dentry *dentry,
 	if (error)
 		goto out_inode_unlock;
 
-	if (inode->i_opflags & IOP_XATTR)
+	if (!(inode->i_opflags & IOP_NOACL))
 		error = set_posix_acl(mnt_userns, dentry, acl_type, NULL);
 	else if (unlikely(is_bad_inode(inode)))
 		error = -EIO;
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index c7d1fa526dea..2a7037b165f0 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2089,7 +2089,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 	 */
 	if (IS_PRIVATE(dir) || dentry == REISERFS_SB(sb)->priv_root) {
 		inode->i_flags |= S_PRIVATE;
-		inode->i_opflags &= ~IOP_XATTR;
+		inode_xattr_disable(inode);
 	}
 
 	if (reiserfs_posixacl(inode->i_sb)) {
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 0b8aa99749f1..4e2f121d6819 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -378,12 +378,12 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
 
 		/*
 		 * Propagate the private flag so we know we're
-		 * in the priv tree.  Also clear IOP_XATTR
+		 * in the priv tree.  Also clear xattrs
 		 * since we don't have xattrs on xattr files.
 		 */
 		if (IS_PRIVATE(dir)) {
 			inode->i_flags |= S_PRIVATE;
-			inode->i_opflags &= ~IOP_XATTR;
+			inode_xattr_disable(inode);
 		}
 	}
 	reiserfs_write_unlock(dir->i_sb);
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 8b2d52443f41..2c326b57d4bc 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -889,7 +889,7 @@ static int create_privroot(struct dentry *dentry)
 	}
 
 	d_inode(dentry)->i_flags |= S_PRIVATE;
-	d_inode(dentry)->i_opflags &= ~IOP_XATTR;
+	inode_xattr_disable(d_inode(dentry));
 	reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
 		      "storage.\n", PRIVROOT_NAME);
 
@@ -977,7 +977,7 @@ int reiserfs_lookup_privroot(struct super_block *s)
 		d_set_d_op(dentry, &xattr_lookup_poison_ops);
 		if (d_really_is_positive(dentry)) {
 			d_inode(dentry)->i_flags |= S_PRIVATE;
-			d_inode(dentry)->i_opflags &= ~IOP_XATTR;
+			inode_xattr_disable(d_inode(dentry));
 		}
 	} else
 		err = PTR_ERR(dentry);
diff --git a/fs/xattr.c b/fs/xattr.c
index adab9a70b536..89b6c122056d 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -468,7 +468,7 @@ 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 && !inode_xattr_disabled(inode)) {
 		error = inode->i_op->listxattr(dentry, list, size);
 	} else {
 		error = security_inode_listsecurity(inode, list, size);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c1769a2c5d70..f4cbac68598a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -582,6 +582,7 @@ is_uncached_acl(struct posix_acl *acl)
 #define IOP_NOFOLLOW	0x0004
 #define IOP_XATTR	0x0008
 #define IOP_DEFAULT_READLINK	0x0010
+#define IOP_NOACL	0x0020
 
 struct fsnotify_mark_connector;
 
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 2e7dd44926e4..23bbe98cfc16 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -109,5 +109,16 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
 			  char *buffer, size_t size);
 void simple_xattr_add(struct simple_xattrs *xattrs,
 		      struct simple_xattr *new_xattr);
+static inline void inode_xattr_disable(struct inode *inode)
+{
+	inode->i_opflags &= ~IOP_XATTR;
+	inode->i_opflags |= IOP_NOACL;
+}
+
+static inline bool inode_xattr_disabled(struct inode *inode)
+{
+	return !(inode->i_opflags & IOP_XATTR) &&
+	       (inode->i_opflags & IOP_NOACL);
+}
 
 #endif	/* _LINUX_XATTR_H */

-- 
2.34.1




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux