summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2016-08-01 00:51:02 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-09-11 09:59:58 +0200
commit553a1f6d027a8e0c59ca7bbe0f26a25d1881cfef (patch)
treedaf9444d19a5cc1b519c1fc1c8746ff9fa9c0521
parenta6e226c25157082a043cce63d14ecab68fdcc433 (diff)
downloadlinux-stable-553a1f6d027a8e0c59ca7bbe0f26a25d1881cfef.tar.gz
linux-stable-553a1f6d027a8e0c59ca7bbe0f26a25d1881cfef.tar.bz2
linux-stable-553a1f6d027a8e0c59ca7bbe0f26a25d1881cfef.zip
ext4: validate that metadata blocks do not overlap superblock
commit 829fa70dddadf9dd041d62b82cd7cea63943899d upstream. 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. Signed-off-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/ext4/super.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 4ce824197b81..712f84308bc8 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2071,6 +2071,7 @@ void ext4_group_desc_csum_set(struct super_block *sb, __u32 block_group,
/* Called at mount-time, super-block is locked */
static int ext4_check_descriptors(struct super_block *sb,
+ ext4_fsblk_t sb_block,
ext4_group_t *first_not_zeroed)
{
struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -2101,6 +2102,11 @@ static int ext4_check_descriptors(struct super_block *sb,
grp = i;
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) {
ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
"Block bitmap for group %u not in group "
@@ -2108,6 +2114,11 @@ static int ext4_check_descriptors(struct super_block *sb,
return 0;
}
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) {
ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
"Inode bitmap for group %u not in group "
@@ -2115,6 +2126,11 @@ static int ext4_check_descriptors(struct super_block *sb,
return 0;
}
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 ||
inode_table + sbi->s_itb_per_group - 1 > last_block) {
ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
@@ -3869,7 +3885,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
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!");
goto failed_mount2;
}