On Wed, May 29, 2019 at 08:43:12PM +0300, Amir Goldstein wrote: > Because generic_copy_file_range doesn't hold the destination inode lock > throughout the copy, strip setuid bits before and after copy. > > The destination inode mtime is updated before and after the copy and the > source inode atime is updated after the copy, similar to > generic_file_read_iter(). > > Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> Looks reasonable, Reviewed-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> --D > --- > fs/read_write.c | 23 +++++++++++++++++++++-- > 1 file changed, 21 insertions(+), 2 deletions(-) > > diff --git a/fs/read_write.c b/fs/read_write.c > index cec7e7b1f693..706ea5f276a7 100644 > --- a/fs/read_write.c > +++ b/fs/read_write.c > @@ -1590,8 +1590,27 @@ ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in, > struct file *file_out, loff_t pos_out, > size_t len, unsigned int flags) > { > - return do_splice_direct(file_in, &pos_in, file_out, &pos_out, > - len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0); > + struct inode *inode_out = file_inode(file_out); > + int ret, err; > + > + /* Should inode_out lock be held throughout the copy operation? */ > + inode_lock(inode_out); > + err = file_modified(file_out); > + inode_unlock(inode_out); > + if (err) > + return err; > + > + ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out, > + len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0); > + > + file_accessed(file_in); > + > + /* To be on the safe side, remove privs also after copy */ > + inode_lock(inode_out); > + err = file_modified(file_out); > + inode_unlock(inode_out); > + > + return err ?: ret; > } > EXPORT_SYMBOL(generic_copy_file_range); > > -- > 2.17.1 >