]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
UBUNTU: SAUCE: overlayfs: Skip permission checking for trusted.overlayfs.* xattrs
authorSeth Forshee <seth.forshee@canonical.com>
Tue, 19 Jan 2016 19:12:02 +0000 (13:12 -0600)
committerPaolo Pisati <paolo.pisati@canonical.com>
Tue, 2 Nov 2021 07:24:41 +0000 (08:24 +0100)
The original mounter had CAP_SYS_ADMIN in the user namespace
where the mount happened, and the vfs has validated that the user
has permission to do the requested operation. This is sufficient
for allowing the kernel to write these specific xattrs, so we can
bypass the permission checks for these xattrs.

To support this, export __vfs_setxattr_noperm and add an similar
__vfs_removexattr_noperm which is also exported. Use these when
setting or removing trusted.overlayfs.* xattrs.

BugLink: http://bugs.launchpad.net/bugs/1531747
BugLink: http://bugs.launchpad.net/bugs/1534961
BugLink: http://bugs.launchpad.net/bugs/1535150
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
fs/overlayfs/overlayfs.h
fs/xattr.c
include/linux/xattr.h

index 3894f3347955215f74a075bd9dfb55dd440eb637..260ad76ad1cd8f6514b8463c8d306553c4861b8b 100644 (file)
@@ -200,7 +200,13 @@ static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
                                  size_t size)
 {
        const char *name = ovl_xattr(ofs, ox);
-       int err = vfs_setxattr(&init_user_ns, dentry, name, value, size, 0);
+       struct inode *inode = dentry->d_inode;
+       int err;
+
+       inode_lock(inode);
+       err = __vfs_setxattr_noperm(&init_user_ns, dentry, name, value, size, 0);
+       inode_unlock(inode);
+
        pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, 0) = %i\n",
                 dentry, name, min((int)size, 48), value, size, err);
        return err;
@@ -210,7 +216,13 @@ static inline int ovl_do_removexattr(struct ovl_fs *ofs, struct dentry *dentry,
                                     enum ovl_xattr ox)
 {
        const char *name = ovl_xattr(ofs, ox);
-       int err = vfs_removexattr(&init_user_ns, dentry, name);
+       struct inode *inode = dentry->d_inode;
+       int err;
+
+       inode_lock(inode);
+       err = __vfs_removexattr_noperm(&init_user_ns, dentry, name);
+       inode_unlock(inode);
+
        pr_debug("removexattr(%pd2, \"%s\") = %i\n", dentry, name, err);
        return err;
 }
index 5c8c5175b385c274eaac9a239ba0749b9372ff98..38468c619c9a086c3ea50d9b9570e5ec1cb7366b 100644 (file)
@@ -237,6 +237,7 @@ int __vfs_setxattr_noperm(struct user_namespace *mnt_userns,
 
        return error;
 }
+EXPORT_SYMBOL_GPL(__vfs_setxattr_noperm);
 
 /**
  * __vfs_setxattr_locked - set an extended attribute while holding the inode
@@ -470,6 +471,34 @@ __vfs_removexattr(struct user_namespace *mnt_userns, struct dentry *dentry,
 }
 EXPORT_SYMBOL(__vfs_removexattr);
 
+/**
+ *  __vfs_removexattr_noperm - perform removexattr operation without
+ *  performing permission checks.
+ *
+ *  @dentry - object to perform setxattr on
+ *  @name - xattr name to set
+ *
+ *  returns the result of the internal setxattr or setsecurity operations.
+ *
+ *  This function requires the caller to lock the inode's i_mutex before it
+ *  is executed. It also assumes that the caller will make the appropriate
+ *  permission checks.
+ */
+int
+__vfs_removexattr_noperm(struct user_namespace *mnt_userns,
+                        struct dentry *dentry, const char *name)
+{
+       int error;
+
+       error =__vfs_removexattr(mnt_userns, dentry, name);
+       if (!error) {
+               fsnotify_xattr(dentry);
+               evm_inode_post_removexattr(dentry, name);
+       }
+       return error;
+}
+EXPORT_SYMBOL_GPL(__vfs_removexattr_noperm);
+
 /**
  * __vfs_removexattr_locked - set an extended attribute while holding the inode
  * lock
@@ -500,12 +529,7 @@ __vfs_removexattr_locked(struct user_namespace *mnt_userns,
        if (error)
                goto out;
 
-       error = __vfs_removexattr(mnt_userns, dentry, name);
-
-       if (!error) {
-               fsnotify_xattr(dentry);
-               evm_inode_post_removexattr(dentry, name);
-       }
+       error = __vfs_removexattr_noperm(mnt_userns, dentry, name);
 
 out:
        return error;
index 4c379d23ec6e73b9590fba7c16e1152fb79376fd..077b3844f2eeb60f357005ed003390aa901a81f7 100644 (file)
@@ -63,6 +63,7 @@ int __vfs_setxattr_locked(struct user_namespace *, struct dentry *,
 int vfs_setxattr(struct user_namespace *, struct dentry *, const char *,
                 const void *, size_t, int);
 int __vfs_removexattr(struct user_namespace *, struct dentry *, const char *);
+int __vfs_removexattr_noperm(struct user_namespace *, struct dentry *, const char *);
 int __vfs_removexattr_locked(struct user_namespace *, struct dentry *,
                             const char *, struct inode **);
 int vfs_removexattr(struct user_namespace *, struct dentry *, const char *);