Skip to content

Commit

Permalink
fs: add __remove_file_privs() with flags parameter
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stefan Roesch authored and axboe committed Jul 25, 2022
1 parent 8017553 commit faf99b5
Showing 1 changed file with 37 additions and 20 deletions.
57 changes: 37 additions & 20 deletions fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/**
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit faf99b5

Please sign in to comment.