diff options
-rw-r--r-- | fs/ext4/super.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 8ff8709828fd..517c90ad25bd 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -2041,8 +2041,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2041 | const char *descr; | 2041 | const char *descr; |
2042 | int ret = -EINVAL; | 2042 | int ret = -EINVAL; |
2043 | int blocksize; | 2043 | int blocksize; |
2044 | int db_count; | 2044 | unsigned int db_count; |
2045 | int i; | 2045 | unsigned int i; |
2046 | int needs_recovery, has_huge_files; | 2046 | int needs_recovery, has_huge_files; |
2047 | int features; | 2047 | int features; |
2048 | __u64 blocks_count; | 2048 | __u64 blocks_count; |
@@ -2331,20 +2331,30 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2331 | if (EXT4_BLOCKS_PER_GROUP(sb) == 0) | 2331 | if (EXT4_BLOCKS_PER_GROUP(sb) == 0) |
2332 | goto cantfind_ext4; | 2332 | goto cantfind_ext4; |
2333 | 2333 | ||
2334 | /* ensure blocks_count calculation below doesn't sign-extend */ | 2334 | /* |
2335 | if (ext4_blocks_count(es) + EXT4_BLOCKS_PER_GROUP(sb) < | 2335 | * It makes no sense for the first data block to be beyond the end |
2336 | le32_to_cpu(es->s_first_data_block) + 1) { | 2336 | * of the filesystem. |
2337 | printk(KERN_WARNING "EXT4-fs: bad geometry: block count %llu, " | 2337 | */ |
2338 | "first data block %u, blocks per group %lu\n", | 2338 | if (le32_to_cpu(es->s_first_data_block) >= ext4_blocks_count(es)) { |
2339 | ext4_blocks_count(es), | 2339 | printk(KERN_WARNING "EXT4-fs: bad geometry: first data" |
2340 | le32_to_cpu(es->s_first_data_block), | 2340 | "block %u is beyond end of filesystem (%llu)\n", |
2341 | EXT4_BLOCKS_PER_GROUP(sb)); | 2341 | le32_to_cpu(es->s_first_data_block), |
2342 | ext4_blocks_count(es)); | ||
2342 | goto failed_mount; | 2343 | goto failed_mount; |
2343 | } | 2344 | } |
2344 | blocks_count = (ext4_blocks_count(es) - | 2345 | blocks_count = (ext4_blocks_count(es) - |
2345 | le32_to_cpu(es->s_first_data_block) + | 2346 | le32_to_cpu(es->s_first_data_block) + |
2346 | EXT4_BLOCKS_PER_GROUP(sb) - 1); | 2347 | EXT4_BLOCKS_PER_GROUP(sb) - 1); |
2347 | do_div(blocks_count, EXT4_BLOCKS_PER_GROUP(sb)); | 2348 | do_div(blocks_count, EXT4_BLOCKS_PER_GROUP(sb)); |
2349 | if (blocks_count > ((uint64_t)1<<32) - EXT4_DESC_PER_BLOCK(sb)) { | ||
2350 | printk(KERN_WARNING "EXT4-fs: groups count too large: %u " | ||
2351 | "(block count %llu, first data block %u, " | ||
2352 | "blocks per group %lu)\n", sbi->s_groups_count, | ||
2353 | ext4_blocks_count(es), | ||
2354 | le32_to_cpu(es->s_first_data_block), | ||
2355 | EXT4_BLOCKS_PER_GROUP(sb)); | ||
2356 | goto failed_mount; | ||
2357 | } | ||
2348 | sbi->s_groups_count = blocks_count; | 2358 | sbi->s_groups_count = blocks_count; |
2349 | db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / | 2359 | db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / |
2350 | EXT4_DESC_PER_BLOCK(sb); | 2360 | EXT4_DESC_PER_BLOCK(sb); |