Re: [PATCH] ext4: init error handle resource before init group descriptors

From: Jan Kara
Date: Thu Jan 19 2023 - 10:36:04 EST


On Thu 19-01-23 09:37:11, Ye Bin wrote:
> From: Ye Bin <yebin10@xxxxxxxxxx>
>
> Now, 's_err_report' timer is init after ext4_group_desc_init() when fill
> super. Theoretically, ext4_group_desc_init() may access to error handle
> as follows:
> __ext4_fill_super
> ext4_group_desc_init
> ext4_check_descriptors
> ext4_get_group_desc
> ext4_error
> ext4_handle_error
> ext4_commit_super
> ext4_update_super
> if (!es->s_error_count)
> mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ);
> --> Accessing Uninitialized Variables
> timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
>
> Maybe above issue is just theoretical, as ext4_check_descriptors() didn't
> judge 'gpd' which get from ext4_get_group_desc(), if access to error handle
> ext4_get_group_desc() will return NULL, then will trigger null-ptr-deref in
> ext4_check_descriptors().
> However, from the perspective of pure code, it is better to initialize
> resource that may need to be used first.

Looks good to me. Feel free to add:

Reviewed-by: Jan Kara <jack@xxxxxxx>

Honza

> fs/ext4/super.c | 19 +++++++------------
> 1 file changed, 7 insertions(+), 12 deletions(-)
>
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index b31db521d6bf..dc3907dff13a 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -4738,7 +4738,6 @@ static int ext4_group_desc_init(struct super_block *sb,
> struct ext4_sb_info *sbi = EXT4_SB(sb);
> unsigned int db_count;
> ext4_fsblk_t block;
> - int ret;
> int i;
>
> db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
> @@ -4778,8 +4777,7 @@ static int ext4_group_desc_init(struct super_block *sb,
> ext4_msg(sb, KERN_ERR,
> "can't read group descriptor %d", i);
> sbi->s_gdb_count = i;
> - ret = PTR_ERR(bh);
> - goto out;
> + return PTR_ERR(bh);
> }
> rcu_read_lock();
> rcu_dereference(sbi->s_group_desc)[i] = bh;
> @@ -4788,13 +4786,10 @@ static int ext4_group_desc_init(struct super_block *sb,
> sbi->s_gdb_count = db_count;
> if (!ext4_check_descriptors(sb, logical_sb_block, first_not_zeroed)) {
> ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
> - ret = -EFSCORRUPTED;
> - goto out;
> + return -EFSCORRUPTED;
> }
> +
> return 0;
> -out:
> - ext4_group_desc_free(sbi);
> - return ret;
> }
>
> static int ext4_load_and_init_journal(struct super_block *sb,
> @@ -5220,14 +5215,14 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
> if (ext4_geometry_check(sb, es))
> goto failed_mount;
>
> - err = ext4_group_desc_init(sb, es, logical_sb_block, &first_not_zeroed);
> - if (err)
> - goto failed_mount;
> -
> timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
> spin_lock_init(&sbi->s_error_lock);
> INIT_WORK(&sbi->s_error_work, flush_stashed_error_work);
>
> + err = ext4_group_desc_init(sb, es, logical_sb_block, &first_not_zeroed);
> + if (err)
> + goto failed_mount3;
> +
> /* Register extent status tree shrinker */
> if (ext4_es_register_shrinker(sbi))
> goto failed_mount3;
> --
> 2.31.1
>
--
Jan Kara <jack@xxxxxxxx>
SUSE Labs, CR