Whamcloud - gitweb
ext2fs_open2: Add more checks for filesystem consistency
authorThiemo Nagel <thiemo.nagel@ph.tum.de>
Tue, 20 Jan 2009 04:16:10 +0000 (23:16 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 20 Jan 2009 04:16:10 +0000 (23:16 -0500)
Add more checks to assure the filesystem is sane to avoid later
division by zero errors.

Patch adds consistency checks on superblock to fix serveral crashes:
* require EXT2_INODES_PER_GROUP != 0
* require EXT2_DESC_PER_BLOCK != 0
* require s_first_data_block < s_blocks_count
* require group_desc_count * EXT2_INODES_PER_GROUP == s_inodes_count

Signed-off-by: Thiemo Nagel <thiemo.nagel@ph.tum.de>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
lib/ext2fs/openfs.c

index 841aa34..cdfeaec 100644 (file)
@@ -243,7 +243,11 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                goto cleanup;
        }
        fs->fragsize = EXT2_FRAG_SIZE(fs->super);
-       fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group *
+       if (EXT2_INODES_PER_GROUP(fs->super) == 0) {
+               retval = EXT2_ET_CORRUPT_SUPERBLOCK;
+               goto cleanup;
+       }
+       fs->inode_blocks_per_group = ((EXT2_INODES_PER_GROUP(fs->super) *
                                       EXT2_INODE_SIZE(fs->super) +
                                       EXT2_BLOCK_SIZE(fs->super) - 1) /
                                      EXT2_BLOCK_SIZE(fs->super));
@@ -275,13 +279,20 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
        blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super);
        if (blocks_per_group == 0 ||
            blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) ||
-           fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super)) {
+           fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super) ||
+           EXT2_DESC_PER_BLOCK(fs->super) == 0 ||
+           fs->super->s_first_data_block >= fs->super->s_blocks_count) {
                retval = EXT2_ET_CORRUPT_SUPERBLOCK;
                goto cleanup;
        }
        fs->group_desc_count = ext2fs_div_ceil(fs->super->s_blocks_count -
                                               fs->super->s_first_data_block,
                                               blocks_per_group);
+       if (fs->group_desc_count * EXT2_INODES_PER_GROUP(fs->super) !=
+           fs->super->s_inodes_count) {
+               retval = EXT2_ET_CORRUPT_SUPERBLOCK;
+               goto cleanup;
+       }
        fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
                                          EXT2_DESC_PER_BLOCK(fs->super));
        retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,