Commit faf99b56 authored by Stefan Roesch's avatar Stefan Roesch Committed by Jens Axboe
Browse files

fs: add __remove_file_privs() with flags parameter



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: default avatarStefan Roesch <shr@fb.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Reviewed-by: default avatarChristian Brauner (Microsoft) <brauner@kernel.org>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Link: https://lore.kernel.org/r/20220623175157.1715274-9-shr@fb.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 80175539
Loading
Loading
Loading
Loading
+37 −20
Original line number Diff line number Diff line
@@ -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)

	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;