Commit 0b5263d1 authored by Amir Goldstein's avatar Amir Goldstein Committed by Christian Brauner

remap_range: move file_start_write() to after permission hook

In vfs code, file_start_write() is usually called after the permission
hook in rw_verify_area().  vfs_dedupe_file_range_one() is an exception
to this rule.

In vfs_dedupe_file_range_one(), move file_start_write() to after the
the rw_verify_area() checks to make them "start-write-safe".

This is needed for fanotify "pre content" events.
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Link: https://lore.kernel.org/r/20231122122715.2561213-8-amir73il@gmail.comReviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent dfad3705
...@@ -420,7 +420,7 @@ loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in, ...@@ -420,7 +420,7 @@ loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in,
EXPORT_SYMBOL(vfs_clone_file_range); EXPORT_SYMBOL(vfs_clone_file_range);
/* Check whether we are allowed to dedupe the destination file */ /* Check whether we are allowed to dedupe the destination file */
static bool allow_file_dedupe(struct file *file) static bool may_dedupe_file(struct file *file)
{ {
struct mnt_idmap *idmap = file_mnt_idmap(file); struct mnt_idmap *idmap = file_mnt_idmap(file);
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
...@@ -445,24 +445,29 @@ loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, ...@@ -445,24 +445,29 @@ loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos,
WARN_ON_ONCE(remap_flags & ~(REMAP_FILE_DEDUP | WARN_ON_ONCE(remap_flags & ~(REMAP_FILE_DEDUP |
REMAP_FILE_CAN_SHORTEN)); REMAP_FILE_CAN_SHORTEN));
ret = mnt_want_write_file(dst_file);
if (ret)
return ret;
/* /*
* This is redundant if called from vfs_dedupe_file_range(), but other * This is redundant if called from vfs_dedupe_file_range(), but other
* callers need it and it's not performance sesitive... * callers need it and it's not performance sesitive...
*/ */
ret = remap_verify_area(src_file, src_pos, len, false); ret = remap_verify_area(src_file, src_pos, len, false);
if (ret) if (ret)
goto out_drop_write; return ret;
ret = remap_verify_area(dst_file, dst_pos, len, true); ret = remap_verify_area(dst_file, dst_pos, len, true);
if (ret) if (ret)
goto out_drop_write; return ret;
/*
* This needs to be called after remap_verify_area() because of
* sb_start_write() and before may_dedupe_file() because the mount's
* MAY_WRITE need to be checked with mnt_get_write_access_file() held.
*/
ret = mnt_want_write_file(dst_file);
if (ret)
return ret;
ret = -EPERM; ret = -EPERM;
if (!allow_file_dedupe(dst_file)) if (!may_dedupe_file(dst_file))
goto out_drop_write; goto out_drop_write;
ret = -EXDEV; ret = -EXDEV;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment