Skip to content

Commit c00c5e1

Browse files
committed
Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 fixes from Ted Ts'o: "Fix some syzbot-detected bugs, as well as other bugs found by I/O injection testing. Change ext4's fallocate to consistently drop set[ug]id bits when an fallocate operation might possibly change the user-visible contents of a file. Also, improve handling of potentially invalid values in the the s_overhead_cluster superblock field to avoid ext4 returning a negative number of free blocks" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: jbd2: fix a potential race while discarding reserved buffers after an abort ext4: update the cached overhead value in the superblock ext4: force overhead calculation if the s_overhead_cluster makes no sense ext4: fix overhead calculation to account for the reserved gdt blocks ext4, doc: fix incorrect h_reserved size ext4: limit length to bitmap_maxbytes - blocksize in punch_hole ext4: fix use-after-free in ext4_search_dir ext4: fix bug_on in start_this_handle during umount filesystem ext4: fix symlink file size not match to file content ext4: fix fallocate to use file_modified to update permissions consistently
2 parents 2e5991f + 23e3d7f commit c00c5e1

File tree

9 files changed

+101
-26
lines changed

9 files changed

+101
-26
lines changed

Documentation/filesystems/ext4/attributes.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ The beginning of an extended attribute block is in
7676
- Checksum of the extended attribute block.
7777
* - 0x14
7878
- \_\_u32
79-
- h\_reserved[2]
79+
- h\_reserved[3]
8080
- Zero.
8181

8282
The checksum is calculated against the FS UUID, the 64-bit block number

fs/ext4/ext4.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2273,6 +2273,10 @@ static inline int ext4_forced_shutdown(struct ext4_sb_info *sbi)
22732273
* Structure of a directory entry
22742274
*/
22752275
#define EXT4_NAME_LEN 255
2276+
/*
2277+
* Base length of the ext4 directory entry excluding the name length
2278+
*/
2279+
#define EXT4_BASE_DIR_LEN (sizeof(struct ext4_dir_entry_2) - EXT4_NAME_LEN)
22762280

22772281
struct ext4_dir_entry {
22782282
__le32 inode; /* Inode number */
@@ -3032,7 +3036,7 @@ extern int ext4_inode_attach_jinode(struct inode *inode);
30323036
extern int ext4_can_truncate(struct inode *inode);
30333037
extern int ext4_truncate(struct inode *);
30343038
extern int ext4_break_layouts(struct inode *);
3035-
extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
3039+
extern int ext4_punch_hole(struct file *file, loff_t offset, loff_t length);
30363040
extern void ext4_set_inode_flags(struct inode *, bool init);
30373041
extern int ext4_alloc_da_blocks(struct inode *inode);
30383042
extern void ext4_set_aops(struct inode *inode);
@@ -3064,6 +3068,7 @@ int ext4_fileattr_set(struct user_namespace *mnt_userns,
30643068
struct dentry *dentry, struct fileattr *fa);
30653069
int ext4_fileattr_get(struct dentry *dentry, struct fileattr *fa);
30663070
extern void ext4_reset_inode_seed(struct inode *inode);
3071+
int ext4_update_overhead(struct super_block *sb);
30673072

30683073
/* migrate.c */
30693074
extern int ext4_ext_migrate(struct inode *);

fs/ext4/extents.c

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

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

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

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

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

46924696
if (mode & FALLOC_FL_PUNCH_HOLE) {
4693-
ret = ext4_punch_hole(inode, offset, len);
4697+
ret = ext4_punch_hole(file, offset, len);
46944698
goto exit;
46954699
}
46964700

@@ -4699,12 +4703,12 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
46994703
goto exit;
47004704

47014705
if (mode & FALLOC_FL_COLLAPSE_RANGE) {
4702-
ret = ext4_collapse_range(inode, offset, len);
4706+
ret = ext4_collapse_range(file, offset, len);
47034707
goto exit;
47044708
}
47054709

47064710
if (mode & FALLOC_FL_INSERT_RANGE) {
4707-
ret = ext4_insert_range(inode, offset, len);
4711+
ret = ext4_insert_range(file, offset, len);
47084712
goto exit;
47094713
}
47104714

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

4747+
ret = file_modified(file);
4748+
if (ret)
4749+
goto out;
4750+
47434751
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, flags);
47444752
if (ret)
47454753
goto out;
@@ -5241,8 +5249,9 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
52415249
* This implements the fallocate's collapse range functionality for ext4
52425250
* Returns: 0 and non-zero on error.
52435251
*/
5244-
static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
5252+
static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
52455253
{
5254+
struct inode *inode = file_inode(file);
52465255
struct super_block *sb = inode->i_sb;
52475256
struct address_space *mapping = inode->i_mapping;
52485257
ext4_lblk_t punch_start, punch_stop;
@@ -5294,6 +5303,10 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
52945303
/* Wait for existing dio to complete */
52955304
inode_dio_wait(inode);
52965305

5306+
ret = file_modified(file);
5307+
if (ret)
5308+
goto out_mutex;
5309+
52975310
/*
52985311
* Prevent page faults from reinstantiating pages we have released from
52995312
* page cache.
@@ -5387,8 +5400,9 @@ static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
53875400
* by len bytes.
53885401
* Returns 0 on success, error otherwise.
53895402
*/
5390-
static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
5403+
static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
53915404
{
5405+
struct inode *inode = file_inode(file);
53925406
struct super_block *sb = inode->i_sb;
53935407
struct address_space *mapping = inode->i_mapping;
53945408
handle_t *handle;
@@ -5445,6 +5459,10 @@ static int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
54455459
/* Wait for existing dio to complete */
54465460
inode_dio_wait(inode);
54475461

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

fs/ext4/inode.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3953,12 +3953,14 @@ int ext4_break_layouts(struct inode *inode)
39533953
* Returns: 0 on success or negative on failure
39543954
*/
39553955

3956-
int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
3956+
int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
39573957
{
3958+
struct inode *inode = file_inode(file);
39583959
struct super_block *sb = inode->i_sb;
39593960
ext4_lblk_t first_block, stop_block;
39603961
struct address_space *mapping = inode->i_mapping;
3961-
loff_t first_block_offset, last_block_offset;
3962+
loff_t first_block_offset, last_block_offset, max_length;
3963+
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
39623964
handle_t *handle;
39633965
unsigned int credits;
39643966
int ret = 0, ret2 = 0;
@@ -4001,6 +4003,14 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
40014003
offset;
40024004
}
40034005

4006+
/*
4007+
* For punch hole the length + offset needs to be within one block
4008+
* before last range. Adjust the length if it goes beyond that limit.
4009+
*/
4010+
max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
4011+
if (offset + length > max_length)
4012+
length = max_length - offset;
4013+
40044014
if (offset & (sb->s_blocksize - 1) ||
40054015
(offset + length) & (sb->s_blocksize - 1)) {
40064016
/*
@@ -4016,6 +4026,10 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
40164026
/* Wait all existing dio workers, newcomers will block on i_rwsem */
40174027
inode_dio_wait(inode);
40184028

4029+
ret = file_modified(file);
4030+
if (ret)
4031+
goto out_mutex;
4032+
40194033
/*
40204034
* Prevent page faults from reinstantiating pages we have released from
40214035
* page cache.

fs/ext4/ioctl.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,3 +1652,19 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
16521652
return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
16531653
}
16541654
#endif
1655+
1656+
static void set_overhead(struct ext4_super_block *es, const void *arg)
1657+
{
1658+
es->s_overhead_clusters = cpu_to_le32(*((unsigned long *) arg));
1659+
}
1660+
1661+
int ext4_update_overhead(struct super_block *sb)
1662+
{
1663+
struct ext4_sb_info *sbi = EXT4_SB(sb);
1664+
1665+
if (sb_rdonly(sb) || sbi->s_overhead == 0 ||
1666+
sbi->s_overhead == le32_to_cpu(sbi->s_es->s_overhead_clusters))
1667+
return 0;
1668+
1669+
return ext4_update_superblocks_fn(sb, set_overhead, &sbi->s_overhead);
1670+
}

fs/ext4/namei.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,10 +1466,10 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
14661466

14671467
de = (struct ext4_dir_entry_2 *)search_buf;
14681468
dlimit = search_buf + buf_size;
1469-
while ((char *) de < dlimit) {
1469+
while ((char *) de < dlimit - EXT4_BASE_DIR_LEN) {
14701470
/* this code is executed quadratically often */
14711471
/* do minimal checking `by hand' */
1472-
if ((char *) de + de->name_len <= dlimit &&
1472+
if (de->name + de->name_len <= dlimit &&
14731473
ext4_match(dir, fname, de)) {
14741474
/* found a match - just to be sure, do
14751475
* a full check */

fs/ext4/page-io.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,10 @@ static void ext4_finish_bio(struct bio *bio)
134134
continue;
135135
}
136136
clear_buffer_async_write(bh);
137-
if (bio->bi_status)
137+
if (bio->bi_status) {
138+
set_buffer_write_io_error(bh);
138139
buffer_io_error(bh);
140+
}
139141
} while ((bh = bh->b_this_page) != head);
140142
spin_unlock_irqrestore(&head->b_uptodate_lock, flags);
141143
if (!under_io) {

fs/ext4/super.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,20 +1199,25 @@ static void ext4_put_super(struct super_block *sb)
11991199
int aborted = 0;
12001200
int i, err;
12011201

1202-
ext4_unregister_li_request(sb);
1203-
ext4_quota_off_umount(sb);
1204-
1205-
flush_work(&sbi->s_error_work);
1206-
destroy_workqueue(sbi->rsv_conversion_wq);
1207-
ext4_release_orphan_info(sb);
1208-
12091202
/*
12101203
* Unregister sysfs before destroying jbd2 journal.
12111204
* Since we could still access attr_journal_task attribute via sysfs
12121205
* path which could have sbi->s_journal->j_task as NULL
1206+
* Unregister sysfs before flush sbi->s_error_work.
1207+
* Since user may read /proc/fs/ext4/xx/mb_groups during umount, If
1208+
* read metadata verify failed then will queue error work.
1209+
* flush_stashed_error_work will call start_this_handle may trigger
1210+
* BUG_ON.
12131211
*/
12141212
ext4_unregister_sysfs(sb);
12151213

1214+
ext4_unregister_li_request(sb);
1215+
ext4_quota_off_umount(sb);
1216+
1217+
flush_work(&sbi->s_error_work);
1218+
destroy_workqueue(sbi->rsv_conversion_wq);
1219+
ext4_release_orphan_info(sb);
1220+
12161221
if (sbi->s_journal) {
12171222
aborted = is_journal_aborted(sbi->s_journal);
12181223
err = jbd2_journal_destroy(sbi->s_journal);
@@ -4172,9 +4177,11 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp,
41724177
ext4_fsblk_t first_block, last_block, b;
41734178
ext4_group_t i, ngroups = ext4_get_groups_count(sb);
41744179
int s, j, count = 0;
4180+
int has_super = ext4_bg_has_super(sb, grp);
41754181

41764182
if (!ext4_has_feature_bigalloc(sb))
4177-
return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) +
4183+
return (has_super + ext4_bg_num_gdb(sb, grp) +
4184+
(has_super ? le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) : 0) +
41784185
sbi->s_itb_per_group + 2);
41794186

41804187
first_block = le32_to_cpu(sbi->s_es->s_first_data_block) +
@@ -5282,9 +5289,18 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
52825289
* Get the # of file system overhead blocks from the
52835290
* superblock if present.
52845291
*/
5285-
if (es->s_overhead_clusters)
5286-
sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters);
5287-
else {
5292+
sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters);
5293+
/* ignore the precalculated value if it is ridiculous */
5294+
if (sbi->s_overhead > ext4_blocks_count(es))
5295+
sbi->s_overhead = 0;
5296+
/*
5297+
* If the bigalloc feature is not enabled recalculating the
5298+
* overhead doesn't take long, so we might as well just redo
5299+
* it to make sure we are using the correct value.
5300+
*/
5301+
if (!ext4_has_feature_bigalloc(sb))
5302+
sbi->s_overhead = 0;
5303+
if (sbi->s_overhead == 0) {
52885304
err = ext4_calculate_overhead(sb);
52895305
if (err)
52905306
goto failed_mount_wq;
@@ -5602,6 +5618,8 @@ static int ext4_fill_super(struct super_block *sb, struct fs_context *fc)
56025618
ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
56035619
"Quota mode: %s.", descr, ext4_quota_mode(sb));
56045620

5621+
/* Update the s_overhead_clusters if necessary */
5622+
ext4_update_overhead(sb);
56055623
return 0;
56065624

56075625
free_sbi:

fs/jbd2/commit.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,6 @@ void jbd2_journal_commit_transaction(journal_t *journal)
488488
jbd2_journal_wait_updates(journal);
489489

490490
commit_transaction->t_state = T_SWITCH;
491-
write_unlock(&journal->j_state_lock);
492491

493492
J_ASSERT (atomic_read(&commit_transaction->t_outstanding_credits) <=
494493
journal->j_max_transaction_buffers);
@@ -508,6 +507,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
508507
* has reserved. This is consistent with the existing behaviour
509508
* that multiple jbd2_journal_get_write_access() calls to the same
510509
* buffer are perfectly permissible.
510+
* We use journal->j_state_lock here to serialize processing of
511+
* t_reserved_list with eviction of buffers from journal_unmap_buffer().
511512
*/
512513
while (commit_transaction->t_reserved_list) {
513514
jh = commit_transaction->t_reserved_list;
@@ -527,6 +528,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
527528
jbd2_journal_refile_buffer(journal, jh);
528529
}
529530

531+
write_unlock(&journal->j_state_lock);
530532
/*
531533
* Now try to drop any written-back buffers from the journal's
532534
* checkpoint lists. We do this *before* commit because it potentially

0 commit comments

Comments
 (0)