diff options
author | Darrick J. Wong <djwong@kernel.org> | 2022-03-10 13:14:39 -0800 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2022-04-18 20:59:42 -0700 |
commit | c4b17d9e421047d1eebb7db78c913fad34b0f55c (patch) | |
tree | b057ff0408ebac7ac6c05e6cae272e87ac7ed731 | |
parent | ad7bbbb030119f5b7866430e8f58e7ffb97185a3 (diff) |
btrfs: fix fallocate to use file_modified to update permissions consistentlyfalloc-permissions-fixes-5.18_2022-04-18
Since the initial introduction of (posix) fallocate back at the turn of
the century, it has been possible to use this syscall to change the
user-visible contents of files. This can happen by extending the file
size during a preallocation, or through any of the newer modes (punch,
zero range). Because the call can be used to change file contents, we
should treat it like we do any other modification to a file -- update
the mtime, and drop set[ug]id privileges/capabilities.
The VFS function file_modified() does all this for us if pass it a
locked inode, so let's make fallocate drop permissions correctly.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r-- | fs/btrfs/file.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index a0179cc62913..79e61c88b9e7 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -2918,8 +2918,9 @@ out: return ret; } -static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) +static int btrfs_punch_hole(struct file *file, loff_t offset, loff_t len) { + struct inode *inode = file_inode(file); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_root *root = BTRFS_I(inode)->root; struct extent_state *cached_state = NULL; @@ -2951,6 +2952,10 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len) goto out_only_mutex; } + ret = file_modified(file); + if (ret) + goto out_only_mutex; + lockstart = round_up(offset, btrfs_inode_sectorsize(BTRFS_I(inode))); lockend = round_down(offset + len, btrfs_inode_sectorsize(BTRFS_I(inode))) - 1; @@ -3177,11 +3182,12 @@ static int btrfs_zero_range_check_range_boundary(struct btrfs_inode *inode, return ret; } -static int btrfs_zero_range(struct inode *inode, +static int btrfs_zero_range(struct file *file, loff_t offset, loff_t len, const int mode) { + struct inode *inode = file_inode(file); struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info; struct extent_map *em; struct extent_changeset *data_reserved = NULL; @@ -3202,6 +3208,12 @@ static int btrfs_zero_range(struct inode *inode, goto out; } + ret = file_modified(file); + if (ret) { + free_extent_map(em); + goto out; + } + /* * Avoid hole punching and extent allocation for some cases. More cases * could be considered, but these are unlikely common and we keep things @@ -3391,7 +3403,7 @@ static long btrfs_fallocate(struct file *file, int mode, return -EOPNOTSUPP; if (mode & FALLOC_FL_PUNCH_HOLE) - return btrfs_punch_hole(inode, offset, len); + return btrfs_punch_hole(file, offset, len); /* * Only trigger disk allocation, don't trigger qgroup reserve @@ -3446,7 +3458,7 @@ static long btrfs_fallocate(struct file *file, int mode, goto out; if (mode & FALLOC_FL_ZERO_RANGE) { - ret = btrfs_zero_range(inode, offset, len, mode); + ret = btrfs_zero_range(file, offset, len, mode); btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP); return ret; } @@ -3528,6 +3540,9 @@ static long btrfs_fallocate(struct file *file, int mode, cur_offset = last_byte; } + if (!ret) + ret = file_modified(file); + /* * If ret is still 0, means we're OK to fallocate. * Or just cleanup the list and exit. |