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

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.comSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 80175539
...@@ -2010,36 +2010,43 @@ static int __remove_privs(struct user_namespace *mnt_userns, ...@@ -2010,36 +2010,43 @@ static int __remove_privs(struct user_namespace *mnt_userns,
return notify_change(mnt_userns, dentry, &newattrs, NULL); return notify_change(mnt_userns, dentry, &newattrs, NULL);
} }
/* static int __file_remove_privs(struct file *file, unsigned int flags)
* Remove special file priviledges (suid, capabilities) when file is written
* to or truncated.
*/
int file_remove_privs(struct file *file)
{ {
struct dentry *dentry = file_dentry(file); struct dentry *dentry = file_dentry(file);
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
int error;
int kill; 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)) if (IS_NOSEC(inode) || !S_ISREG(inode->i_mode))
return 0; return 0;
kill = dentry_needs_remove_privs(dentry); kill = dentry_needs_remove_privs(dentry);
if (kill < 0) if (kill <= 0)
return kill; return kill;
if (kill)
if (flags & IOCB_NOWAIT)
return -EAGAIN;
error = __remove_privs(file_mnt_user_ns(file), dentry, kill); error = __remove_privs(file_mnt_user_ns(file), dentry, kill);
if (!error) if (!error)
inode_has_no_xattr(inode); inode_has_no_xattr(inode);
return error; 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); EXPORT_SYMBOL(file_remove_privs);
/** /**
...@@ -2090,18 +2097,28 @@ int file_update_time(struct file *file) ...@@ -2090,18 +2097,28 @@ int file_update_time(struct file *file)
} }
EXPORT_SYMBOL(file_update_time); 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 file_modified(struct file *file)
{ {
int err; int ret;
/* /*
* Clear the security bits if the process is not being run by root. * Clear the security bits if the process is not being run by root.
* This keeps people from modifying setuid and setgid binaries. * This keeps people from modifying setuid and setgid binaries.
*/ */
err = file_remove_privs(file); ret = __file_remove_privs(file, 0);
if (err) if (ret)
return err; return ret;
if (unlikely(file->f_mode & FMODE_NOCMTIME)) if (unlikely(file->f_mode & FMODE_NOCMTIME))
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment