remap_range: merge do_clone_file_range() into vfs_clone_file_range()
commitdfad37051a
("remap_range: move permission hooks out of do_clone_file_range()") moved the permission hooks from do_clone_file_range() out to its caller vfs_clone_file_range(), but left all the fast sanity checks in do_clone_file_range(). This makes the expensive security hooks be called in situations that they would not have been called before (e.g. fs does not support clone). The only reason for the do_clone_file_range() helper was that overlayfs did not use to be able to call vfs_clone_file_range() from copy up context with sb_writers lock held. However, since commitc63e56a4a6
("ovl: do not open/llseek lower file with upper sb_writers held"), overlayfs just uses an open coded version of vfs_clone_file_range(). Merge_clone_file_range() into vfs_clone_file_range(), restoring the original order of checks as it was before the regressing commit and adapt the overlayfs code to call vfs_clone_file_range() before the permission hooks that were added by commitca7ab48240
("ovl: add permission hooks outside of do_splice_direct()"). Note that in the merge of do_clone_file_range(), the file_start_write() context was reduced to cover ->remap_file_range() without holding it over the permission hooks, which was the reason for doing the regressing commit in the first place. Reported-and-tested-by: kernel test robot <oliver.sang@intel.com> Closes: https://lore.kernel.org/oe-lkp/202401312229.eddeb9a6-oliver.sang@intel.com Fixes:dfad37051a
("remap_range: move permission hooks out of do_clone_file_range()") Signed-off-by: Amir Goldstein <amir73il@gmail.com> Link: https://lore.kernel.org/r/20240202102258.1582671-1-amir73il@gmail.com Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
6613476e22
commit
853b8d7597
|
@ -265,20 +265,18 @@ static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry,
|
||||||
if (IS_ERR(old_file))
|
if (IS_ERR(old_file))
|
||||||
return PTR_ERR(old_file);
|
return PTR_ERR(old_file);
|
||||||
|
|
||||||
|
/* Try to use clone_file_range to clone up within the same fs */
|
||||||
|
cloned = vfs_clone_file_range(old_file, 0, new_file, 0, len, 0);
|
||||||
|
if (cloned == len)
|
||||||
|
goto out_fput;
|
||||||
|
|
||||||
|
/* Couldn't clone, so now we try to copy the data */
|
||||||
error = rw_verify_area(READ, old_file, &old_pos, len);
|
error = rw_verify_area(READ, old_file, &old_pos, len);
|
||||||
if (!error)
|
if (!error)
|
||||||
error = rw_verify_area(WRITE, new_file, &new_pos, len);
|
error = rw_verify_area(WRITE, new_file, &new_pos, len);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_fput;
|
goto out_fput;
|
||||||
|
|
||||||
/* Try to use clone_file_range to clone up within the same fs */
|
|
||||||
ovl_start_write(dentry);
|
|
||||||
cloned = do_clone_file_range(old_file, 0, new_file, 0, len, 0);
|
|
||||||
ovl_end_write(dentry);
|
|
||||||
if (cloned == len)
|
|
||||||
goto out_fput;
|
|
||||||
/* Couldn't clone, so now we try to copy the data */
|
|
||||||
|
|
||||||
/* Check if lower fs supports seek operation */
|
/* Check if lower fs supports seek operation */
|
||||||
if (old_file->f_mode & FMODE_LSEEK)
|
if (old_file->f_mode & FMODE_LSEEK)
|
||||||
skip_hole = true;
|
skip_hole = true;
|
||||||
|
|
|
@ -373,9 +373,9 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(generic_remap_file_range_prep);
|
EXPORT_SYMBOL(generic_remap_file_range_prep);
|
||||||
|
|
||||||
loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
|
loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
|
||||||
struct file *file_out, loff_t pos_out,
|
struct file *file_out, loff_t pos_out,
|
||||||
loff_t len, unsigned int remap_flags)
|
loff_t len, unsigned int remap_flags)
|
||||||
{
|
{
|
||||||
loff_t ret;
|
loff_t ret;
|
||||||
|
|
||||||
|
@ -391,23 +391,6 @@ loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
|
||||||
if (!file_in->f_op->remap_file_range)
|
if (!file_in->f_op->remap_file_range)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
ret = file_in->f_op->remap_file_range(file_in, pos_in,
|
|
||||||
file_out, pos_out, len, remap_flags);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
fsnotify_access(file_in);
|
|
||||||
fsnotify_modify(file_out);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(do_clone_file_range);
|
|
||||||
|
|
||||||
loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
|
|
||||||
struct file *file_out, loff_t pos_out,
|
|
||||||
loff_t len, unsigned int remap_flags)
|
|
||||||
{
|
|
||||||
loff_t ret;
|
|
||||||
|
|
||||||
ret = remap_verify_area(file_in, pos_in, len, false);
|
ret = remap_verify_area(file_in, pos_in, len, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -417,10 +400,14 @@ loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
file_start_write(file_out);
|
file_start_write(file_out);
|
||||||
ret = do_clone_file_range(file_in, pos_in, file_out, pos_out, len,
|
ret = file_in->f_op->remap_file_range(file_in, pos_in,
|
||||||
remap_flags);
|
file_out, pos_out, len, remap_flags);
|
||||||
file_end_write(file_out);
|
file_end_write(file_out);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
fsnotify_access(file_in);
|
||||||
|
fsnotify_modify(file_out);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(vfs_clone_file_range);
|
EXPORT_SYMBOL(vfs_clone_file_range);
|
||||||
|
|
|
@ -2101,9 +2101,6 @@ int __generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
|
||||||
int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
|
int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
|
||||||
struct file *file_out, loff_t pos_out,
|
struct file *file_out, loff_t pos_out,
|
||||||
loff_t *count, unsigned int remap_flags);
|
loff_t *count, unsigned int remap_flags);
|
||||||
extern loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
|
|
||||||
struct file *file_out, loff_t pos_out,
|
|
||||||
loff_t len, unsigned int remap_flags);
|
|
||||||
extern loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
|
extern loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
|
||||||
struct file *file_out, loff_t pos_out,
|
struct file *file_out, loff_t pos_out,
|
||||||
loff_t len, unsigned int remap_flags);
|
loff_t len, unsigned int remap_flags);
|
||||||
|
|
Loading…
Reference in New Issue