diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2008-05-07 03:22:39 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-05-07 03:29:00 -0400 |
commit | 7f3d4ee108c184ab215036051087aaaaa8de7661 (patch) | |
tree | 373f4f928f0687ca84478964b43c26e3ec9cec70 | |
parent | 07416d29bcf608257f1e5280642dcbe0021518a3 (diff) |
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: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | fs/splice.c | 29 | ||||
-rw-r--r-- | include/linux/fs.h | 1 | ||||
-rw-r--r-- | mm/filemap.c | 2 |
3 files changed, 14 insertions, 18 deletions
diff --git a/fs/splice.c b/fs/splice.c index 633f58ebfb72..cece15b4ef72 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -811,24 +811,19 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
811 | { | 811 | { |
812 | struct address_space *mapping = out->f_mapping; | 812 | struct address_space *mapping = out->f_mapping; |
813 | struct inode *inode = mapping->host; | 813 | struct inode *inode = mapping->host; |
814 | int killsuid, killpriv; | 814 | struct splice_desc sd = { |
815 | .total_len = len, | ||
816 | .flags = flags, | ||
817 | .pos = *ppos, | ||
818 | .u.file = out, | ||
819 | }; | ||
815 | ssize_t ret; | 820 | ssize_t ret; |
816 | int err = 0; | ||
817 | |||
818 | killpriv = security_inode_need_killpriv(out->f_path.dentry); | ||
819 | killsuid = should_remove_suid(out->f_path.dentry); | ||
820 | if (unlikely(killsuid || killpriv)) { | ||
821 | mutex_lock(&inode->i_mutex); | ||
822 | if (killpriv) | ||
823 | err = security_inode_killpriv(out->f_path.dentry); | ||
824 | if (!err && killsuid) | ||
825 | err = __remove_suid(out->f_path.dentry, killsuid); | ||
826 | mutex_unlock(&inode->i_mutex); | ||
827 | if (err) | ||
828 | return err; | ||
829 | } | ||
830 | 821 | ||
831 | ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); | 822 | inode_double_lock(inode, pipe->inode); |
823 | ret = remove_suid(out->f_path.dentry); | ||
824 | if (likely(!ret)) | ||
825 | ret = __splice_from_pipe(pipe, &sd, pipe_to_file); | ||
826 | inode_double_unlock(inode, pipe->inode); | ||
832 | if (ret > 0) { | 827 | if (ret > 0) { |
833 | unsigned long nr_pages; | 828 | unsigned long nr_pages; |
834 | 829 | ||
@@ -840,6 +835,8 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
840 | * sync it. | 835 | * sync it. |
841 | */ | 836 | */ |
842 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { | 837 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { |
838 | int err; | ||
839 | |||
843 | mutex_lock(&inode->i_mutex); | 840 | mutex_lock(&inode->i_mutex); |
844 | err = generic_osync_inode(inode, mapping, | 841 | err = generic_osync_inode(inode, mapping, |
845 | OSYNC_METADATA|OSYNC_DATA); | 842 | OSYNC_METADATA|OSYNC_DATA); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 7e0fa9e64479..f413085f748e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1816,7 +1816,6 @@ extern void iget_failed(struct inode *); | |||
1816 | extern void clear_inode(struct inode *); | 1816 | extern void clear_inode(struct inode *); |
1817 | extern void destroy_inode(struct inode *); | 1817 | extern void destroy_inode(struct inode *); |
1818 | extern struct inode *new_inode(struct super_block *); | 1818 | extern struct inode *new_inode(struct super_block *); |
1819 | extern int __remove_suid(struct dentry *, int); | ||
1820 | extern int should_remove_suid(struct dentry *); | 1819 | extern int should_remove_suid(struct dentry *); |
1821 | extern int remove_suid(struct dentry *); | 1820 | extern int remove_suid(struct dentry *); |
1822 | 1821 | ||
diff --git a/mm/filemap.c b/mm/filemap.c index 239d36163bbe..2dead9adf8b7 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -1655,7 +1655,7 @@ int should_remove_suid(struct dentry *dentry) | |||
1655 | } | 1655 | } |
1656 | EXPORT_SYMBOL(should_remove_suid); | 1656 | EXPORT_SYMBOL(should_remove_suid); |
1657 | 1657 | ||
1658 | int __remove_suid(struct dentry *dentry, int kill) | 1658 | static int __remove_suid(struct dentry *dentry, int kill) |
1659 | { | 1659 | { |
1660 | struct iattr newattrs; | 1660 | struct iattr newattrs; |
1661 | 1661 | ||