Skip to content

Commit c140f8b

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: "A large number of ext4 bug fixes, mostly buffer and memory leaks on error return cleanup paths" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: missing !bh check in ext4_xattr_inode_write() ext4: fix buffer leak in __ext4_read_dirblock() on error path ext4: fix buffer leak in ext4_expand_extra_isize_ea() on error path ext4: fix buffer leak in ext4_xattr_move_to_block() on error path ext4: release bs.bh before re-using in ext4_xattr_block_find() ext4: fix buffer leak in ext4_xattr_get_block() on error path ext4: fix possible leak of s_journal_flag_rwsem in error path ext4: fix possible leak of sbi->s_group_desc_leak in error path ext4: remove unneeded brelse call in ext4_xattr_inode_update_ref() ext4: avoid possible double brelse() in add_new_gdb() on error path ext4: avoid buffer leak in ext4_orphan_add() after prior errors ext4: avoid buffer leak on shutdown in ext4_mark_iloc_dirty() ext4: fix possible inode leak in the retry loop of ext4_resize_fs() ext4: fix missing cleanup if ext4_alloc_flex_bg_array() fails while resizing ext4: add missing brelse() update_backups()'s error path ext4: add missing brelse() add_new_gdb_meta_bg()'s error path ext4: add missing brelse() in set_flexbg_block_bitmap()'s error path ext4: avoid potential extra brelse in setup_new_flex_group_blocks()
2 parents b6df7b6 + eb6984f commit c140f8b

File tree

5 files changed

+51
-31
lines changed

5 files changed

+51
-31
lines changed

fs/ext4/inode.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -5835,9 +5835,10 @@ int ext4_mark_iloc_dirty(handle_t *handle,
58355835
{
58365836
int err = 0;
58375837

5838-
if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
5838+
if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) {
5839+
put_bh(iloc->bh);
58395840
return -EIO;
5840-
5841+
}
58415842
if (IS_I_VERSION(inode))
58425843
inode_inc_iversion(inode);
58435844

fs/ext4/namei.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
126126
if (!is_dx_block && type == INDEX) {
127127
ext4_error_inode(inode, func, line, block,
128128
"directory leaf block found instead of index block");
129+
brelse(bh);
129130
return ERR_PTR(-EFSCORRUPTED);
130131
}
131132
if (!ext4_has_metadata_csum(inode->i_sb) ||
@@ -2811,7 +2812,9 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
28112812
list_del_init(&EXT4_I(inode)->i_orphan);
28122813
mutex_unlock(&sbi->s_orphan_lock);
28132814
}
2814-
}
2815+
} else
2816+
brelse(iloc.bh);
2817+
28152818
jbd_debug(4, "superblock will point to %lu\n", inode->i_ino);
28162819
jbd_debug(4, "orphan inode %lu will point to %d\n",
28172820
inode->i_ino, NEXT_ORPHAN(inode));

fs/ext4/resize.c

+16-12
Original file line numberDiff line numberDiff line change
@@ -459,16 +459,18 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle,
459459

460460
BUFFER_TRACE(bh, "get_write_access");
461461
err = ext4_journal_get_write_access(handle, bh);
462-
if (err)
462+
if (err) {
463+
brelse(bh);
463464
return err;
465+
}
464466
ext4_debug("mark block bitmap %#04llx (+%llu/%u)\n",
465467
first_cluster, first_cluster - start, count2);
466468
ext4_set_bits(bh->b_data, first_cluster - start, count2);
467469

468470
err = ext4_handle_dirty_metadata(handle, NULL, bh);
471+
brelse(bh);
469472
if (unlikely(err))
470473
return err;
471-
brelse(bh);
472474
}
473475

474476
return 0;
@@ -605,7 +607,6 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
605607
bh = bclean(handle, sb, block);
606608
if (IS_ERR(bh)) {
607609
err = PTR_ERR(bh);
608-
bh = NULL;
609610
goto out;
610611
}
611612
overhead = ext4_group_overhead_blocks(sb, group);
@@ -618,9 +619,9 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
618619
ext4_mark_bitmap_end(EXT4_B2C(sbi, group_data[i].blocks_count),
619620
sb->s_blocksize * 8, bh->b_data);
620621
err = ext4_handle_dirty_metadata(handle, NULL, bh);
622+
brelse(bh);
621623
if (err)
622624
goto out;
623-
brelse(bh);
624625

625626
handle_ib:
626627
if (bg_flags[i] & EXT4_BG_INODE_UNINIT)
@@ -635,18 +636,16 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
635636
bh = bclean(handle, sb, block);
636637
if (IS_ERR(bh)) {
637638
err = PTR_ERR(bh);
638-
bh = NULL;
639639
goto out;
640640
}
641641

642642
ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb),
643643
sb->s_blocksize * 8, bh->b_data);
644644
err = ext4_handle_dirty_metadata(handle, NULL, bh);
645+
brelse(bh);
645646
if (err)
646647
goto out;
647-
brelse(bh);
648648
}
649-
bh = NULL;
650649

651650
/* Mark group tables in block bitmap */
652651
for (j = 0; j < GROUP_TABLE_COUNT; j++) {
@@ -685,7 +684,6 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
685684
}
686685

687686
out:
688-
brelse(bh);
689687
err2 = ext4_journal_stop(handle);
690688
if (err2 && !err)
691689
err = err2;
@@ -873,6 +871,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
873871
err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh);
874872
if (unlikely(err)) {
875873
ext4_std_error(sb, err);
874+
iloc.bh = NULL;
876875
goto exit_inode;
877876
}
878877
brelse(dind);
@@ -924,6 +923,7 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
924923
sizeof(struct buffer_head *),
925924
GFP_NOFS);
926925
if (!n_group_desc) {
926+
brelse(gdb_bh);
927927
err = -ENOMEM;
928928
ext4_warning(sb, "not enough memory for %lu groups",
929929
gdb_num + 1);
@@ -939,8 +939,6 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
939939
kvfree(o_group_desc);
940940
BUFFER_TRACE(gdb_bh, "get_write_access");
941941
err = ext4_journal_get_write_access(handle, gdb_bh);
942-
if (unlikely(err))
943-
brelse(gdb_bh);
944942
return err;
945943
}
946944

@@ -1124,8 +1122,10 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
11241122
backup_block, backup_block -
11251123
ext4_group_first_block_no(sb, group));
11261124
BUFFER_TRACE(bh, "get_write_access");
1127-
if ((err = ext4_journal_get_write_access(handle, bh)))
1125+
if ((err = ext4_journal_get_write_access(handle, bh))) {
1126+
brelse(bh);
11281127
break;
1128+
}
11291129
lock_buffer(bh);
11301130
memcpy(bh->b_data, data, size);
11311131
if (rest)
@@ -2023,7 +2023,7 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
20232023

20242024
err = ext4_alloc_flex_bg_array(sb, n_group + 1);
20252025
if (err)
2026-
return err;
2026+
goto out;
20272027

20282028
err = ext4_mb_alloc_groupinfo(sb, n_group + 1);
20292029
if (err)
@@ -2059,6 +2059,10 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
20592059
n_blocks_count_retry = 0;
20602060
free_flex_gd(flex_gd);
20612061
flex_gd = NULL;
2062+
if (resize_inode) {
2063+
iput(resize_inode);
2064+
resize_inode = NULL;
2065+
}
20622066
goto retry;
20632067
}
20642068

fs/ext4/super.c

+9-8
Original file line numberDiff line numberDiff line change
@@ -4075,6 +4075,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
40754075
sbi->s_groups_count = blocks_count;
40764076
sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count,
40774077
(EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
4078+
if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) !=
4079+
le32_to_cpu(es->s_inodes_count)) {
4080+
ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu",
4081+
le32_to_cpu(es->s_inodes_count),
4082+
((u64)sbi->s_groups_count * sbi->s_inodes_per_group));
4083+
ret = -EINVAL;
4084+
goto failed_mount;
4085+
}
40784086
db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
40794087
EXT4_DESC_PER_BLOCK(sb);
40804088
if (ext4_has_feature_meta_bg(sb)) {
@@ -4094,14 +4102,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
40944102
ret = -ENOMEM;
40954103
goto failed_mount;
40964104
}
4097-
if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) !=
4098-
le32_to_cpu(es->s_inodes_count)) {
4099-
ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu",
4100-
le32_to_cpu(es->s_inodes_count),
4101-
((u64)sbi->s_groups_count * sbi->s_inodes_per_group));
4102-
ret = -EINVAL;
4103-
goto failed_mount;
4104-
}
41054105

41064106
bgl_lock_init(sbi->s_blockgroup_lock);
41074107

@@ -4510,6 +4510,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
45104510
percpu_counter_destroy(&sbi->s_freeinodes_counter);
45114511
percpu_counter_destroy(&sbi->s_dirs_counter);
45124512
percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
4513+
percpu_free_rwsem(&sbi->s_journal_flag_rwsem);
45134514
failed_mount5:
45144515
ext4_ext_release(sb);
45154516
ext4_release_system_zone(sb);

fs/ext4/xattr.c

+19-8
Original file line numberDiff line numberDiff line change
@@ -1031,10 +1031,8 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
10311031
inode_lock(ea_inode);
10321032

10331033
ret = ext4_reserve_inode_write(handle, ea_inode, &iloc);
1034-
if (ret) {
1035-
iloc.bh = NULL;
1034+
if (ret)
10361035
goto out;
1037-
}
10381036

10391037
ref_count = ext4_xattr_inode_get_ref(ea_inode);
10401038
ref_count += ref_change;
@@ -1080,12 +1078,10 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
10801078
}
10811079

10821080
ret = ext4_mark_iloc_dirty(handle, ea_inode, &iloc);
1083-
iloc.bh = NULL;
10841081
if (ret)
10851082
ext4_warning_inode(ea_inode,
10861083
"ext4_mark_iloc_dirty() failed ret=%d", ret);
10871084
out:
1088-
brelse(iloc.bh);
10891085
inode_unlock(ea_inode);
10901086
return ret;
10911087
}
@@ -1388,6 +1384,12 @@ static int ext4_xattr_inode_write(handle_t *handle, struct inode *ea_inode,
13881384
bh = ext4_getblk(handle, ea_inode, block, 0);
13891385
if (IS_ERR(bh))
13901386
return PTR_ERR(bh);
1387+
if (!bh) {
1388+
WARN_ON_ONCE(1);
1389+
EXT4_ERROR_INODE(ea_inode,
1390+
"ext4_getblk() return bh = NULL");
1391+
return -EFSCORRUPTED;
1392+
}
13911393
ret = ext4_journal_get_write_access(handle, bh);
13921394
if (ret)
13931395
goto out;
@@ -2276,8 +2278,10 @@ static struct buffer_head *ext4_xattr_get_block(struct inode *inode)
22762278
if (!bh)
22772279
return ERR_PTR(-EIO);
22782280
error = ext4_xattr_check_block(inode, bh);
2279-
if (error)
2281+
if (error) {
2282+
brelse(bh);
22802283
return ERR_PTR(error);
2284+
}
22812285
return bh;
22822286
}
22832287

@@ -2397,6 +2401,8 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
23972401
error = ext4_xattr_block_set(handle, inode, &i, &bs);
23982402
} else if (error == -ENOSPC) {
23992403
if (EXT4_I(inode)->i_file_acl && !bs.s.base) {
2404+
brelse(bs.bh);
2405+
bs.bh = NULL;
24002406
error = ext4_xattr_block_find(inode, &i, &bs);
24012407
if (error)
24022408
goto cleanup;
@@ -2617,6 +2623,8 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
26172623
kfree(buffer);
26182624
if (is)
26192625
brelse(is->iloc.bh);
2626+
if (bs)
2627+
brelse(bs->bh);
26202628
kfree(is);
26212629
kfree(bs);
26222630

@@ -2696,7 +2704,6 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
26962704
struct ext4_inode *raw_inode, handle_t *handle)
26972705
{
26982706
struct ext4_xattr_ibody_header *header;
2699-
struct buffer_head *bh;
27002707
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
27012708
static unsigned int mnt_count;
27022709
size_t min_offs;
@@ -2737,13 +2744,17 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
27372744
* EA block can hold new_extra_isize bytes.
27382745
*/
27392746
if (EXT4_I(inode)->i_file_acl) {
2747+
struct buffer_head *bh;
2748+
27402749
bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
27412750
error = -EIO;
27422751
if (!bh)
27432752
goto cleanup;
27442753
error = ext4_xattr_check_block(inode, bh);
2745-
if (error)
2754+
if (error) {
2755+
brelse(bh);
27462756
goto cleanup;
2757+
}
27472758
base = BHDR(bh);
27482759
end = bh->b_data + bh->b_size;
27492760
min_offs = end - base;

0 commit comments

Comments
 (0)