]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
fs: add __remove_file_privs() with flags parameter
authorStefan Roesch <shr@fb.com>
Thu, 23 Jun 2022 17:51:51 +0000 (10:51 -0700)
committerJens Axboe <axboe@kernel.dk>
Mon, 25 Jul 2022 00:39:31 +0000 (18:39 -0600)
This adds the function __remove_file_privs, which allows the caller to
pass the kiocb flags parameter.

No intended functional changes in this patch.

Signed-off-by: Stefan Roesch <shr@fb.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Link: https://lore.kernel.org/r/20220623175157.1715274-9-shr@fb.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/inode.c

index bd4da9c5207eabb0cec8722ee3d30acd963169bf..a2e18379c8a6209cdb7fec124e8f8bfc3c0b5011 100644 (file)
@@ -2010,36 +2010,43 @@ static int __remove_privs(struct user_namespace *mnt_userns,
        return notify_change(mnt_userns, dentry, &newattrs, NULL);
 }
 
-/*
- * Remove special file priviledges (suid, capabilities) when file is written
- * to or truncated.
- */
-int file_remove_privs(struct file *file)
+static int __file_remove_privs(struct file *file, unsigned int flags)
 {
        struct dentry *dentry = file_dentry(file);
        struct inode *inode = file_inode(file);
+       int error;
        int kill;
-       int error = 0;
 
-       /*
-        * Fast path for nothing security related.
-        * As well for non-regular files, e.g. blkdev inodes.
-        * For example, blkdev_write_iter() might get here
-        * trying to remove privs which it is not allowed to.
-        */
        if (IS_NOSEC(inode) || !S_ISREG(inode->i_mode))
                return 0;
 
        kill = dentry_needs_remove_privs(dentry);
-       if (kill < 0)
+       if (kill <= 0)
                return kill;
-       if (kill)
-               error = __remove_privs(file_mnt_user_ns(file), dentry, kill);
+
+       if (flags & IOCB_NOWAIT)
+               return -EAGAIN;
+
+       error = __remove_privs(file_mnt_user_ns(file), dentry, kill);
        if (!error)
                inode_has_no_xattr(inode);
 
        return error;
 }
+
+/**
+ * file_remove_privs - remove special file privileges (suid, capabilities)
+ * @file: file to remove privileges from
+ *
+ * When file is modified by a write or truncation ensure that special
+ * file privileges are removed.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int file_remove_privs(struct file *file)
+{
+       return __file_remove_privs(file, 0);
+}
 EXPORT_SYMBOL(file_remove_privs);
 
 /**
@@ -2090,18 +2097,28 @@ int file_update_time(struct file *file)
 }
 EXPORT_SYMBOL(file_update_time);
 
-/* Caller must hold the file's inode lock */
+/**
+ * file_modified - handle mandated vfs changes when modifying a file
+ * @file: file that was modified
+ *
+ * When file has been modified ensure that special
+ * file privileges are removed and time settings are updated.
+ *
+ * Context: Caller must hold the file's inode lock.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
 int file_modified(struct file *file)
 {
-       int err;
+       int ret;
 
        /*
         * Clear the security bits if the process is not being run by root.
         * This keeps people from modifying setuid and setgid binaries.
         */
-       err = file_remove_privs(file);
-       if (err)
-               return err;
+       ret = __file_remove_privs(file, 0);
+       if (ret)
+               return ret;
 
        if (unlikely(file->f_mode & FMODE_NOCMTIME))
                return 0;