| From 44de022c4382541cebdd6de4465d1f4f465ff1dd Mon Sep 17 00:00:00 2001 |
| From: Theodore Ts'o <tytso@mit.edu> |
| Date: Sun, 8 Jul 2018 19:35:02 -0400 |
| Subject: ext4: fix false negatives *and* false positives in ext4_check_descriptors() |
| |
| From: Theodore Ts'o <tytso@mit.edu> |
| |
| commit 44de022c4382541cebdd6de4465d1f4f465ff1dd upstream. |
| |
| Ext4_check_descriptors() was getting called before s_gdb_count was |
| initialized. So for file systems w/o the meta_bg feature, allocation |
| bitmaps could overlap the block group descriptors and ext4 wouldn't |
| notice. |
| |
| For file systems with the meta_bg feature enabled, there was a |
| fencepost error which would cause the ext4_check_descriptors() to |
| incorrectly believe that the block allocation bitmap overlaps with the |
| block group descriptor blocks, and it would reject the mount. |
| |
| Fix both of these problems. |
| |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Benjamin Gilbert <bgilbert@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/ext4/super.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/fs/ext4/super.c |
| +++ b/fs/ext4/super.c |
| @@ -2231,7 +2231,7 @@ static int ext4_check_descriptors(struct |
| struct ext4_sb_info *sbi = EXT4_SB(sb); |
| ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block); |
| ext4_fsblk_t last_block; |
| - ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0) + 1; |
| + ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0); |
| ext4_fsblk_t block_bitmap; |
| ext4_fsblk_t inode_bitmap; |
| ext4_fsblk_t inode_table; |
| @@ -3941,13 +3941,13 @@ static int ext4_fill_super(struct super_ |
| goto failed_mount2; |
| } |
| } |
| + 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 failed_mount2; |
| } |
| |
| - sbi->s_gdb_count = db_count; |
| get_random_bytes(&sbi->s_next_generation, sizeof(u32)); |
| spin_lock_init(&sbi->s_next_gen_lock); |
| |