add patch fix-inode-checksum-calculation-if-i_extra_size-is-too-small
[ext4-patch-queue.git] / validate-that-metadata-blocks-do-not-overlap-superblock
blob713cce5f5b81491a923babcf1f595ec8edc7897c
1 ext4: validate that metadata blocks do not overlap superblock
3 A number of fuzzing failures seem to be caused by allocation bitmaps
4 or other metadata blocks being pointed at the superblock.
6 This can cause kernel BUG or WARNings once the superblock is
7 overwritten, so validate the group descriptor blocks to make sure this
8 doesn't happen.
10 Cc: stable@vger.kernel.org
11 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
12 ---
13  fs/ext4/super.c | 18 +++++++++++++++++-
14  1 file changed, 17 insertions(+), 1 deletion(-)
16 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
17 index e2622ba..2942fda 100644
18 --- a/fs/ext4/super.c
19 +++ b/fs/ext4/super.c
20 @@ -2211,6 +2211,7 @@ void ext4_group_desc_csum_set(struct super_block *sb, __u32 block_group,
22  /* Called at mount-time, super-block is locked */
23  static int ext4_check_descriptors(struct super_block *sb,
24 +                                 ext4_fsblk_t sb_block,
25                                   ext4_group_t *first_not_zeroed)
26  {
27         struct ext4_sb_info *sbi = EXT4_SB(sb);
28 @@ -2241,6 +2242,11 @@ static int ext4_check_descriptors(struct super_block *sb,
29                         grp = i;
31                 block_bitmap = ext4_block_bitmap(sb, gdp);
32 +               if (block_bitmap == sb_block) {
33 +                       ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
34 +                                "Block bitmap for group %u overlaps "
35 +                                "superblock", i);
36 +               }
37                 if (block_bitmap < first_block || block_bitmap > last_block) {
38                         ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
39                                "Block bitmap for group %u not in group "
40 @@ -2248,6 +2254,11 @@ static int ext4_check_descriptors(struct super_block *sb,
41                         return 0;
42                 }
43                 inode_bitmap = ext4_inode_bitmap(sb, gdp);
44 +               if (inode_bitmap == sb_block) {
45 +                       ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
46 +                                "Inode bitmap for group %u overlaps "
47 +                                "superblock", i);
48 +               }
49                 if (inode_bitmap < first_block || inode_bitmap > last_block) {
50                         ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
51                                "Inode bitmap for group %u not in group "
52 @@ -2255,6 +2266,11 @@ static int ext4_check_descriptors(struct super_block *sb,
53                         return 0;
54                 }
55                 inode_table = ext4_inode_table(sb, gdp);
56 +               if (inode_table == sb_block) {
57 +                       ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
58 +                                "Inode table for group %u overlaps "
59 +                                "superblock", i);
60 +               }
61                 if (inode_table < first_block ||
62                     inode_table + sbi->s_itb_per_group - 1 > last_block) {
63                         ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
64 @@ -3757,7 +3773,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
65                         goto failed_mount2;
66                 }
67         }
68 -       if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
69 +       if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) {
70                 ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
71                 ret = -EFSCORRUPTED;
72                 goto failed_mount2;