Skip to content

Commit ba50ea4

Browse files
Darrick J. Wonggregkh
Darrick J. Wong
authored andcommitted
ext4: fix fallocate to use file_modified to update permissions consistently
commit ad5cd4f upstream. 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, collapse, insert 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 <[email protected]> Link: https://lore.kernel.org/r/20220308185043.GA117678@magnolia Signed-off-by: Theodore Ts'o <[email protected]> Cc: [email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 67e4860 commit ba50ea4

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

fs/ext4/ext4.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3027,7 +3027,7 @@ extern int ext4_inode_attach_jinode(struct inode *inode);
30273027
extern int ext4_can_truncate(struct inode *inode);
30283028
extern int ext4_truncate(struct inode *);
30293029
extern int ext4_break_layouts(struct inode *);
3030-
extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
3030+
extern int ext4_punch_hole(struct file *file, loff_t offset, loff_t length);
30313031
extern void ext4_set_inode_flags(struct inode *, bool init);
30323032
extern int ext4_alloc_da_blocks(struct inode *inode);
30333033
extern void ext4_set_aops(struct inode *inode);

fs/ext4/extents.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4504,9 +4504,9 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
45044504
return ret > 0 ? ret2 : ret;
45054505
}
45064506

4507-
static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len);
4507+
static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len);
45084508

4509-
static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len);
4509+
static int ext4_insert_range(struct file *file, loff_t offset, loff_t len);
45104510

45114511
static long ext4_zero_range(struct file *file, loff_t offset,
45124512
loff_t len, int mode)
@@ -4578,6 +4578,10 @@ static long ext4_zero_range(struct file *file, loff_t offset,
45784578
/* Wait all existing dio workers, newcomers will block on i_mutex */
45794579
inode_dio_wait(inode);
45804580

4581+
ret = file_modified(file);
4582+
if (ret)
4583+
goto out_mutex;
4584+
45814585
/* Preallocate the range including the unaligned edges */
45824586
if (partial_begin || partial_end) {
45834587
ret = ext4_alloc_file_blocks(file,
@@ -4696,7 +4700,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
46964700
ext4_fc_start_update(inode);
46974701

46984702
if (mode & FALLOC_FL_PUNCH_HOLE) {
4699-
ret = ext4_punch_hole(inode, offset, len);
4703+
ret = ext4_punch_hole(file, offset, len);
47004704
goto exit;
47014705
}
47024706

@@ -4705,12 +4709,12 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
47054709
goto exit;
47064710

47074711
if (mode & FALLOC_FL_COLLAPSE_RANGE) {
4708-
ret = ext4_collapse_range(inode, offset, len);
4712+
ret = ext4_collapse_range(file, offset, len);
47094713
goto exit;
47104714
}
47114715

47124716
if (mode & FALLOC_FL_INSERT_RANGE) {
4713-
ret = ext4_insert_range(inode, offset, len);
4717+
ret = ext4_insert_range(file, offset, len);
47144718
goto exit;
47154719
}
47164720

@@ -4746,6 +4750,10 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
47464750
/* Wait all existing dio workers, newcomers will block on i_mutex */
47474751
inode_dio_wait(inode);
47484752

4753+
ret = file_modified(file);
4754+
if (ret)
4755+
goto out;
4756+
47494757
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, flags);
47504758
if (ret)
47514759
goto out;
@@ -5248,8 +5256,9 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
52485256
* This implements the fallocate's collapse range functionality for ext4
52495257
* Returns: 0 and non-zero on error.
52505258
*/
5251-
static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
5259+
static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
52525260
{
5261+
struct inode *inode = file_inode(file);
52535262
struct super_block *sb = inode->i_sb;
52545263
struct address_space *mapping = inode->i_mapping;
52555264
ext4_lblk_t punch_start, punch_stop;
@@ -5301,6 +5310,10 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
53015310
/* Wait for existing dio to complete */
53025311
inode_dio_wait(inode);
53035312

5313+
ret = file_modified(file);
5314+
if (ret)
5315+
goto out_mutex;
5316+
53045317
/*
53055318
* Prevent page faults from reinstantiating pages we have released from
53065319
* page cache.
@@ -5394,8 +5407,9 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
53945407
* by len bytes.
53955408
* Returns 0 on success, error otherwise.
53965409
*/
5397-
static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
5410+
static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
53985411
{
5412+
struct inode *inode = file_inode(file);
53995413
struct super_block *sb = inode->i_sb;
54005414
struct address_space *mapping = inode->i_mapping;
54015415
handle_t *handle;
@@ -5452,6 +5466,10 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
54525466
/* Wait for existing dio to complete */
54535467
inode_dio_wait(inode);
54545468

5469+
ret = file_modified(file);
5470+
if (ret)
5471+
goto out_mutex;
5472+
54555473
/*
54565474
* Prevent page faults from reinstantiating pages we have released from
54575475
* page cache.

fs/ext4/inode.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3939,8 +3939,9 @@ int ext4_break_layouts(struct inode *inode)
39393939
* Returns: 0 on success or negative on failure
39403940
*/
39413941

3942-
int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
3942+
int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
39433943
{
3944+
struct inode *inode = file_inode(file);
39443945
struct super_block *sb = inode->i_sb;
39453946
ext4_lblk_t first_block, stop_block;
39463947
struct address_space *mapping = inode->i_mapping;
@@ -4002,6 +4003,10 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
40024003
/* Wait all existing dio workers, newcomers will block on i_mutex */
40034004
inode_dio_wait(inode);
40044005

4006+
ret = file_modified(file);
4007+
if (ret)
4008+
goto out_mutex;
4009+
40054010
/*
40064011
* Prevent page faults from reinstantiating pages we have released from
40074012
* page cache.

0 commit comments

Comments
 (0)