internal: add may_write_xattr()
authorChristian Brauner <brauner@kernel.org>
Thu, 29 Sep 2022 08:47:36 +0000 (10:47 +0200)
committerChristian Brauner (Microsoft) <brauner@kernel.org>
Thu, 20 Oct 2022 08:13:29 +0000 (10:13 +0200)
Split out the generic checks whether an inode allows writing xattrs. Since
security.* and system.* xattrs don't have any restrictions and we're going
to split out posix acls into a dedicated api we will use this helper to
check whether we can write posix acls.

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

index 6f0386b34faeca2656575ebd176777239eefa488..aa5f240496d967442f9740ed179ae740e967c46d 100644 (file)
@@ -232,5 +232,6 @@ ssize_t do_getxattr(struct user_namespace *mnt_userns,
 int setxattr_copy(const char __user *name, struct xattr_ctx *ctx);
 int do_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                struct xattr_ctx *ctx);
+int may_write_xattr(struct user_namespace *mnt_userns, struct inode *inode);
 
 ssize_t __kernel_write_iter(struct file *file, struct iov_iter *from, loff_t *pos);
index 61107b6bbed29211786d2eda0318499d95f525fe..31b5ac65ca34c33f1f95dece90f3bacdf5a91c74 100644 (file)
@@ -80,6 +80,31 @@ xattr_resolve_name(struct inode *inode, const char **name)
        return ERR_PTR(-EOPNOTSUPP);
 }
 
+/**
+ * may_write_xattr - check whether inode allows writing xattr
+ * @mnt_userns:        User namespace of the mount the inode was found from
+ * @inode: the inode on which to set an xattr
+ *
+ * Check whether the inode allows writing xattrs. Specifically, we can never
+ * set or remove an extended attribute on a read-only filesystem  or on an
+ * immutable / append-only inode.
+ *
+ * We also need to ensure that the inode has a mapping in the mount to
+ * not risk writing back invalid i_{g,u}id values.
+ *
+ * Return: On success zero is returned. On error a negative errno is returned.
+ */
+int may_write_xattr(struct user_namespace *mnt_userns, struct inode *inode)
+{
+       if (IS_IMMUTABLE(inode))
+               return -EPERM;
+       if (IS_APPEND(inode))
+               return -EPERM;
+       if (HAS_UNMAPPED_ID(mnt_userns, inode))
+               return -EPERM;
+       return 0;
+}
+
 /*
  * Check permissions for extended attribute access.  This is a bit complicated
  * because different namespaces have very different rules.
@@ -88,20 +113,12 @@ static int
 xattr_permission(struct user_namespace *mnt_userns, struct inode *inode,
                 const char *name, int mask)
 {
-       /*
-        * We can never set or remove an extended attribute on a read-only
-        * filesystem  or on an immutable / append-only inode.
-        */
        if (mask & MAY_WRITE) {
-               if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-                       return -EPERM;
-               /*
-                * Updating an xattr will likely cause i_uid and i_gid
-                * to be writen back improperly if their true value is
-                * unknown to the vfs.
-                */
-               if (HAS_UNMAPPED_ID(mnt_userns, inode))
-                       return -EPERM;
+               int ret;
+
+               ret = may_write_xattr(mnt_userns, inode);
+               if (ret)
+                       return ret;
        }
 
        /*