Commit ade4ba0d authored by Theodore Ts'o's avatar Theodore Ts'o Committed by Sasha Levin

ext4: validate that metadata blocks do not overlap superblock

[ Upstream commit 829fa70d ]

A number of fuzzing failures seem to be caused by allocation bitmaps
or other metadata blocks being pointed at the superblock.

This can cause kernel BUG or WARNings once the superblock is
overwritten, so validate the group descriptor blocks to make sure this
doesn't happen.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Signed-off-by: default avatarSasha Levin <alexander.levin@verizon.com>
parent db9e37a1
...@@ -2057,6 +2057,7 @@ void ext4_group_desc_csum_set(struct super_block *sb, __u32 block_group, ...@@ -2057,6 +2057,7 @@ void ext4_group_desc_csum_set(struct super_block *sb, __u32 block_group,
/* Called at mount-time, super-block is locked */ /* Called at mount-time, super-block is locked */
static int ext4_check_descriptors(struct super_block *sb, static int ext4_check_descriptors(struct super_block *sb,
ext4_fsblk_t sb_block,
ext4_group_t *first_not_zeroed) ext4_group_t *first_not_zeroed)
{ {
struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_sb_info *sbi = EXT4_SB(sb);
...@@ -2087,6 +2088,11 @@ static int ext4_check_descriptors(struct super_block *sb, ...@@ -2087,6 +2088,11 @@ static int ext4_check_descriptors(struct super_block *sb,
grp = i; grp = i;
block_bitmap = ext4_block_bitmap(sb, gdp); block_bitmap = ext4_block_bitmap(sb, gdp);
if (block_bitmap == sb_block) {
ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
"Block bitmap for group %u overlaps "
"superblock", i);
}
if (block_bitmap < first_block || block_bitmap > last_block) { if (block_bitmap < first_block || block_bitmap > last_block) {
ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
"Block bitmap for group %u not in group " "Block bitmap for group %u not in group "
...@@ -2094,6 +2100,11 @@ static int ext4_check_descriptors(struct super_block *sb, ...@@ -2094,6 +2100,11 @@ static int ext4_check_descriptors(struct super_block *sb,
return 0; return 0;
} }
inode_bitmap = ext4_inode_bitmap(sb, gdp); inode_bitmap = ext4_inode_bitmap(sb, gdp);
if (inode_bitmap == sb_block) {
ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
"Inode bitmap for group %u overlaps "
"superblock", i);
}
if (inode_bitmap < first_block || inode_bitmap > last_block) { if (inode_bitmap < first_block || inode_bitmap > last_block) {
ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
"Inode bitmap for group %u not in group " "Inode bitmap for group %u not in group "
...@@ -2101,6 +2112,11 @@ static int ext4_check_descriptors(struct super_block *sb, ...@@ -2101,6 +2112,11 @@ static int ext4_check_descriptors(struct super_block *sb,
return 0; return 0;
} }
inode_table = ext4_inode_table(sb, gdp); inode_table = ext4_inode_table(sb, gdp);
if (inode_table == sb_block) {
ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
"Inode table for group %u overlaps "
"superblock", i);
}
if (inode_table < first_block || if (inode_table < first_block ||
inode_table + sbi->s_itb_per_group - 1 > last_block) { inode_table + sbi->s_itb_per_group - 1 > last_block) {
ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
...@@ -3926,7 +3942,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3926,7 +3942,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
goto failed_mount2; goto failed_mount2;
} }
} }
if (!ext4_check_descriptors(sb, &first_not_zeroed)) { if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) {
ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
goto failed_mount2; goto failed_mount2;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment