Skip to content

Commit 853b8d7

Browse files
amir73ilbrauner
authored andcommitted
remap_range: merge do_clone_file_range() into vfs_clone_file_range()
commit dfad370 ("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 commit c63e56a ("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 commit ca7ab48 ("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 <[email protected]> Closes: https://lore.kernel.org/oe-lkp/[email protected] Fixes: dfad370 ("remap_range: move permission hooks out of do_clone_file_range()") Signed-off-by: Amir Goldstein <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Jan Kara <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent 6613476 commit 853b8d7

File tree

3 files changed

+15
-33
lines changed

3 files changed

+15
-33
lines changed

fs/overlayfs/copy_up.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -265,20 +265,18 @@ static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry,
265265
if (IS_ERR(old_file))
266266
return PTR_ERR(old_file);
267267

268+
/* Try to use clone_file_range to clone up within the same fs */
269+
cloned = vfs_clone_file_range(old_file, 0, new_file, 0, len, 0);
270+
if (cloned == len)
271+
goto out_fput;
272+
273+
/* Couldn't clone, so now we try to copy the data */
268274
error = rw_verify_area(READ, old_file, &old_pos, len);
269275
if (!error)
270276
error = rw_verify_area(WRITE, new_file, &new_pos, len);
271277
if (error)
272278
goto out_fput;
273279

274-
/* Try to use clone_file_range to clone up within the same fs */
275-
ovl_start_write(dentry);
276-
cloned = do_clone_file_range(old_file, 0, new_file, 0, len, 0);
277-
ovl_end_write(dentry);
278-
if (cloned == len)
279-
goto out_fput;
280-
/* Couldn't clone, so now we try to copy the data */
281-
282280
/* Check if lower fs supports seek operation */
283281
if (old_file->f_mode & FMODE_LSEEK)
284282
skip_hole = true;

fs/remap_range.c

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,9 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
373373
}
374374
EXPORT_SYMBOL(generic_remap_file_range_prep);
375375

376-
loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
377-
struct file *file_out, loff_t pos_out,
378-
loff_t len, unsigned int remap_flags)
376+
loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
377+
struct file *file_out, loff_t pos_out,
378+
loff_t len, unsigned int remap_flags)
379379
{
380380
loff_t ret;
381381

@@ -391,23 +391,6 @@ loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
391391
if (!file_in->f_op->remap_file_range)
392392
return -EOPNOTSUPP;
393393

394-
ret = file_in->f_op->remap_file_range(file_in, pos_in,
395-
file_out, pos_out, len, remap_flags);
396-
if (ret < 0)
397-
return ret;
398-
399-
fsnotify_access(file_in);
400-
fsnotify_modify(file_out);
401-
return ret;
402-
}
403-
EXPORT_SYMBOL(do_clone_file_range);
404-
405-
loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
406-
struct file *file_out, loff_t pos_out,
407-
loff_t len, unsigned int remap_flags)
408-
{
409-
loff_t ret;
410-
411394
ret = remap_verify_area(file_in, pos_in, len, false);
412395
if (ret)
413396
return ret;
@@ -417,10 +400,14 @@ loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
417400
return ret;
418401

419402
file_start_write(file_out);
420-
ret = do_clone_file_range(file_in, pos_in, file_out, pos_out, len,
421-
remap_flags);
403+
ret = file_in->f_op->remap_file_range(file_in, pos_in,
404+
file_out, pos_out, len, remap_flags);
422405
file_end_write(file_out);
406+
if (ret < 0)
407+
return ret;
423408

409+
fsnotify_access(file_in);
410+
fsnotify_modify(file_out);
424411
return ret;
425412
}
426413
EXPORT_SYMBOL(vfs_clone_file_range);

include/linux/fs.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,9 +2101,6 @@ int __generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
21012101
int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
21022102
struct file *file_out, loff_t pos_out,
21032103
loff_t *count, unsigned int remap_flags);
2104-
extern loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
2105-
struct file *file_out, loff_t pos_out,
2106-
loff_t len, unsigned int remap_flags);
21072104
extern loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
21082105
struct file *file_out, loff_t pos_out,
21092106
loff_t len, unsigned int remap_flags);

0 commit comments

Comments
 (0)