Message ID | 153938921180.8361.13556945128095535605.stgit@magnolia (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | fs: fixes for serious clone/dedupe problems | expand |
> +/* Update inode timestamps and remove security privileges when remapping. */ > +int generic_remap_file_range_touch(struct file *file, bool is_dedupe) > +{ > + int ret; > + > + /* If can't alter the file contents, we're done. */ > + if (is_dedupe) > + return 0; > + > + /* Update the timestamps, since we can alter file contents. */ > + if (!(file->f_mode & FMODE_NOCMTIME)) { > + ret = file_update_time(file); > + if (ret) > + return ret; > + } > + > + /* > + * Clear the security bits if the process is not being run by root. > + * This keeps people from modifying setuid and setgid binaries. > + */ > + return file_remove_privs(file); > +} > +EXPORT_SYMBOL(generic_remap_file_range_touch); The name seems a little out of touch with what it actually does. Also why a bool argument instead of the more descriptive flags which introduced a few patches ago?
On Sun, Oct 14, 2018 at 10:21:31AM -0700, Christoph Hellwig wrote: > > +/* Update inode timestamps and remove security privileges when remapping. */ > > +int generic_remap_file_range_touch(struct file *file, bool is_dedupe) > > +{ > > + int ret; > > + > > + /* If can't alter the file contents, we're done. */ > > + if (is_dedupe) > > + return 0; > > + > > + /* Update the timestamps, since we can alter file contents. */ > > + if (!(file->f_mode & FMODE_NOCMTIME)) { > > + ret = file_update_time(file); > > + if (ret) > > + return ret; > > + } > > + > > + /* > > + * Clear the security bits if the process is not being run by root. > > + * This keeps people from modifying setuid and setgid binaries. > > + */ > > + return file_remove_privs(file); > > +} > > +EXPORT_SYMBOL(generic_remap_file_range_touch); > > The name seems a little out of touch with what it actually does. I originally thought "touch" because it updates [cm]time. :) Though looking at the final code, I think this can just be called from the end of generic_remap_file_range_prep, so we can skip the export and all that other stuff. > Also why a bool argument instead of the more descriptive flags which > introduced a few patches ago? Hmm, yes, the remap_flags transition can move up to before this patch. --D
On Mon, Oct 15, 2018 at 09:30:01AM -0700, Darrick J. Wong wrote: > I originally thought "touch" because it updates [cm]time. :) > > Though looking at the final code, I think this can just be called from > the end of generic_remap_file_range_prep, so we can skip the export and > all that other stuff. I though about that, but the locking didn't seem to quite work out between xfs and ocfs. Nevermind the big elephant of actually converting btrfs to the "VFS" helper - I think if that doesn't work out it is rather questionable how generic they actually are.
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 36c56dfbe485..ee1ed11379b3 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -4855,6 +4855,14 @@ int ocfs2_reflink_remap_range(struct file *file_in, if (ret <= 0) goto out_unlock; + /* + * Update inode timestamps and remove security privileges before we + * take the ilock. + */ + ret = generic_remap_file_range_touch(file_out, is_dedupe); + if (ret) + goto out_unlock; + /* Lock out changes to the allocation maps and remap. */ down_write(&OCFS2_I(inode_in)->ip_alloc_sem); if (!same_inode) diff --git a/fs/read_write.c b/fs/read_write.c index ff6fcb3b99dd..7b837d12f75d 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1806,6 +1806,30 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, } EXPORT_SYMBOL(generic_remap_file_range_prep); +/* Update inode timestamps and remove security privileges when remapping. */ +int generic_remap_file_range_touch(struct file *file, bool is_dedupe) +{ + int ret; + + /* If can't alter the file contents, we're done. */ + if (is_dedupe) + return 0; + + /* Update the timestamps, since we can alter file contents. */ + if (!(file->f_mode & FMODE_NOCMTIME)) { + ret = file_update_time(file); + if (ret) + return ret; + } + + /* + * Clear the security bits if the process is not being run by root. + * This keeps people from modifying setuid and setgid binaries. + */ + return file_remove_privs(file); +} +EXPORT_SYMBOL(generic_remap_file_range_touch); + int do_clone_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, u64 len) { diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index a7757a128a78..99f2ea4fcaba 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1371,28 +1371,13 @@ xfs_reflink_remap_prep( truncate_inode_pages_range(&inode_out->i_data, pos_out, PAGE_ALIGN(pos_out + *len) - 1); - /* If we're altering the file contents... */ - if (!is_dedupe) { - /* - * ...update the timestamps (which will grab the ilock again - * from xfs_fs_dirty_inode, so we have to call it before we - * take the ilock). - */ - if (!(file_out->f_mode & FMODE_NOCMTIME)) { - ret = file_update_time(file_out); - if (ret) - goto out_unlock; - } - - /* - * ...clear the security bits if the process is not being run - * by root. This keeps people from modifying setuid and setgid - * binaries. - */ - ret = file_remove_privs(file_out); - if (ret) - goto out_unlock; - } + /* + * Update inode timestamps and remove security privileges before we + * take the ilock. + */ + ret = generic_remap_file_range_touch(file_out, is_dedupe); + if (ret) + goto out_unlock; return 1; out_unlock: diff --git a/include/linux/fs.h b/include/linux/fs.h index 686905be04c0..91fd3c77763b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1847,6 +1847,7 @@ extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *, extern int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, u64 *count, bool is_dedupe); +extern int generic_remap_file_range_touch(struct file *file, bool is_dedupe); extern int do_clone_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, u64 len); extern int vfs_clone_file_range(struct file *file_in, loff_t pos_in,