Commit 7f3d4ee1 authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Jens Axboe

vfs: splice remove_suid() cleanup

generic_file_splice_write() duplicates remove_suid() just because it
doesn't hold i_mutex.  But it grabs i_mutex inside splice_from_pipe()
anyway, so this is rather pointless.

Move locking to generic_file_splice_write() and call remove_suid() and
__splice_from_pipe() instead.
Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 07416d29
...@@ -811,24 +811,19 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, ...@@ -811,24 +811,19 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
{ {
struct address_space *mapping = out->f_mapping; struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
int killsuid, killpriv; struct splice_desc sd = {
.total_len = len,
.flags = flags,
.pos = *ppos,
.u.file = out,
};
ssize_t ret; ssize_t ret;
int err = 0;
killpriv = security_inode_need_killpriv(out->f_path.dentry); inode_double_lock(inode, pipe->inode);
killsuid = should_remove_suid(out->f_path.dentry); ret = remove_suid(out->f_path.dentry);
if (unlikely(killsuid || killpriv)) { if (likely(!ret))
mutex_lock(&inode->i_mutex); ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
if (killpriv) inode_double_unlock(inode, pipe->inode);
err = security_inode_killpriv(out->f_path.dentry);
if (!err && killsuid)
err = __remove_suid(out->f_path.dentry, killsuid);
mutex_unlock(&inode->i_mutex);
if (err)
return err;
}
ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
if (ret > 0) { if (ret > 0) {
unsigned long nr_pages; unsigned long nr_pages;
...@@ -840,6 +835,8 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, ...@@ -840,6 +835,8 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
* sync it. * sync it.
*/ */
if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
int err;
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
err = generic_osync_inode(inode, mapping, err = generic_osync_inode(inode, mapping,
OSYNC_METADATA|OSYNC_DATA); OSYNC_METADATA|OSYNC_DATA);
......
...@@ -1816,7 +1816,6 @@ extern void iget_failed(struct inode *); ...@@ -1816,7 +1816,6 @@ extern void iget_failed(struct inode *);
extern void clear_inode(struct inode *); extern void clear_inode(struct inode *);
extern void destroy_inode(struct inode *); extern void destroy_inode(struct inode *);
extern struct inode *new_inode(struct super_block *); extern struct inode *new_inode(struct super_block *);
extern int __remove_suid(struct dentry *, int);
extern int should_remove_suid(struct dentry *); extern int should_remove_suid(struct dentry *);
extern int remove_suid(struct dentry *); extern int remove_suid(struct dentry *);
......
...@@ -1655,7 +1655,7 @@ int should_remove_suid(struct dentry *dentry) ...@@ -1655,7 +1655,7 @@ int should_remove_suid(struct dentry *dentry)
} }
EXPORT_SYMBOL(should_remove_suid); EXPORT_SYMBOL(should_remove_suid);
int __remove_suid(struct dentry *dentry, int kill) static int __remove_suid(struct dentry *dentry, int kill)
{ {
struct iattr newattrs; struct iattr newattrs;
......
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