Skip to content

Commit 9799392

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 b5296f0 commit 9799392

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
@@ -3030,7 +3030,7 @@ extern int ext4_inode_attach_jinode(struct inode *inode);
30303030
extern int ext4_can_truncate(struct inode *inode);
30313031
extern int ext4_truncate(struct inode *);
30323032
extern int ext4_break_layouts(struct inode *);
3033-
extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
3033+
extern int ext4_punch_hole(struct file *file, loff_t offset, loff_t length);
30343034
extern void ext4_set_inode_flags(struct inode *, bool init);
30353035
extern int ext4_alloc_da_blocks(struct inode *inode);
30363036
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
@@ -4501,9 +4501,9 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
45014501
return ret > 0 ? ret2 : ret;
45024502
}
45034503

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

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

45084508
static long ext4_zero_range(struct file *file, loff_t offset,
45094509
loff_t len, int mode)
@@ -4575,6 +4575,10 @@ static long ext4_zero_range(struct file *file, loff_t offset,
45754575
/* Wait all existing dio workers, newcomers will block on i_rwsem */
45764576
inode_dio_wait(inode);
45774577

4578+
ret = file_modified(file);
4579+
if (ret)
4580+
goto out_mutex;
4581+
45784582
/* Preallocate the range including the unaligned edges */
45794583
if (partial_begin || partial_end) {
45804584
ret = ext4_alloc_file_blocks(file,
@@ -4691,7 +4695,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
46914695
return -EOPNOTSUPP;
46924696

46934697
if (mode & FALLOC_FL_PUNCH_HOLE) {
4694-
ret = ext4_punch_hole(inode, offset, len);
4698+
ret = ext4_punch_hole(file, offset, len);
46954699
goto exit;
46964700
}
46974701

@@ -4700,12 +4704,12 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
47004704
goto exit;
47014705

47024706
if (mode & FALLOC_FL_COLLAPSE_RANGE) {
4703-
ret = ext4_collapse_range(inode, offset, len);
4707+
ret = ext4_collapse_range(file, offset, len);
47044708
goto exit;
47054709
}
47064710

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

@@ -4741,6 +4745,10 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
47414745
/* Wait all existing dio workers, newcomers will block on i_rwsem */
47424746
inode_dio_wait(inode);
47434747

4748+
ret = file_modified(file);
4749+
if (ret)
4750+
goto out;
4751+
47444752
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, flags);
47454753
if (ret)
47464754
goto out;
@@ -5242,8 +5250,9 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
52425250
* This implements the fallocate's collapse range functionality for ext4
52435251
* Returns: 0 and non-zero on error.
52445252
*/
5245-
static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
5253+
static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
52465254
{
5255+
struct inode *inode = file_inode(file);
52475256
struct super_block *sb = inode->i_sb;
52485257
struct address_space *mapping = inode->i_mapping;
52495258
ext4_lblk_t punch_start, punch_stop;
@@ -5295,6 +5304,10 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
52955304
/* Wait for existing dio to complete */
52965305
inode_dio_wait(inode);
52975306

5307+
ret = file_modified(file);
5308+
if (ret)
5309+
goto out_mutex;
5310+
52985311
/*
52995312
* Prevent page faults from reinstantiating pages we have released from
53005313
* page cache.
@@ -5388,8 +5401,9 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
53885401
* by len bytes.
53895402
* Returns 0 on success, error otherwise.
53905403
*/
5391-
static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
5404+
static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
53925405
{
5406+
struct inode *inode = file_inode(file);
53935407
struct super_block *sb = inode->i_sb;
53945408
struct address_space *mapping = inode->i_mapping;
53955409
handle_t *handle;
@@ -5446,6 +5460,10 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
54465460
/* Wait for existing dio to complete */
54475461
inode_dio_wait(inode);
54485462

5463+
ret = file_modified(file);
5464+
if (ret)
5465+
goto out_mutex;
5466+
54495467
/*
54505468
* Prevent page faults from reinstantiating pages we have released from
54515469
* page cache.

fs/ext4/inode.c

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

3947-
int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
3947+
int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
39483948
{
3949+
struct inode *inode = file_inode(file);
39493950
struct super_block *sb = inode->i_sb;
39503951
ext4_lblk_t first_block, stop_block;
39513952
struct address_space *mapping = inode->i_mapping;
@@ -4007,6 +4008,10 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
40074008
/* Wait all existing dio workers, newcomers will block on i_rwsem */
40084009
inode_dio_wait(inode);
40094010

4011+
ret = file_modified(file);
4012+
if (ret)
4013+
goto out_mutex;
4014+
40104015
/*
40114016
* Prevent page faults from reinstantiating pages we have released from
40124017
* page cache.

0 commit comments

Comments
 (0)