Commit 9ccad874 authored by Theodore Ts'o's avatar Theodore Ts'o Committed by Greg Kroah-Hartman

ext4: add more mount time checks of the superblock

commit bfe0a5f4 upstream.

The kernel's ext4 mount-time checks were more permissive than
e2fsprogs's libext2fs checks when opening a file system.  The
superblock is considered too insane for debugfs or e2fsck to operate
on it, the kernel has no business trying to mount it.

This will make file system fuzzing tools work harder, but the failure
cases that they find will be more useful and be easier to evaluate.
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent ff6c9646
...@@ -3485,6 +3485,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3485,6 +3485,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
le32_to_cpu(es->s_log_block_size)); le32_to_cpu(es->s_log_block_size));
goto failed_mount; goto failed_mount;
} }
if (le32_to_cpu(es->s_log_cluster_size) >
(EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
ext4_msg(sb, KERN_ERR,
"Invalid log cluster size: %u",
le32_to_cpu(es->s_log_cluster_size));
goto failed_mount;
}
if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) { if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) {
ext4_msg(sb, KERN_ERR, ext4_msg(sb, KERN_ERR,
...@@ -3630,13 +3637,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3630,13 +3637,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
"block size (%d)", clustersize, blocksize); "block size (%d)", clustersize, blocksize);
goto failed_mount; goto failed_mount;
} }
if (le32_to_cpu(es->s_log_cluster_size) >
(EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
ext4_msg(sb, KERN_ERR,
"Invalid log cluster size: %u",
le32_to_cpu(es->s_log_cluster_size));
goto failed_mount;
}
sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) - sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
le32_to_cpu(es->s_log_block_size); le32_to_cpu(es->s_log_block_size);
sbi->s_clusters_per_group = sbi->s_clusters_per_group =
...@@ -3657,10 +3657,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3657,10 +3657,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
} }
} else { } else {
if (clustersize != blocksize) { if (clustersize != blocksize) {
ext4_warning(sb, "fragment/cluster size (%d) != " ext4_msg(sb, KERN_ERR,
"block size (%d)", clustersize, "fragment/cluster size (%d) != "
blocksize); "block size (%d)", clustersize, blocksize);
clustersize = blocksize; goto failed_mount;
} }
if (sbi->s_blocks_per_group > blocksize * 8) { if (sbi->s_blocks_per_group > blocksize * 8) {
ext4_msg(sb, KERN_ERR, ext4_msg(sb, KERN_ERR,
...@@ -3714,6 +3714,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3714,6 +3714,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
ext4_blocks_count(es)); ext4_blocks_count(es));
goto failed_mount; goto failed_mount;
} }
if ((es->s_first_data_block == 0) && (es->s_log_block_size == 0) &&
(sbi->s_cluster_ratio == 1)) {
ext4_msg(sb, KERN_WARNING, "bad geometry: first data "
"block is 0 with a 1k block and cluster size");
goto failed_mount;
}
blocks_count = (ext4_blocks_count(es) - blocks_count = (ext4_blocks_count(es) -
le32_to_cpu(es->s_first_data_block) + le32_to_cpu(es->s_first_data_block) +
EXT4_BLOCKS_PER_GROUP(sb) - 1); EXT4_BLOCKS_PER_GROUP(sb) - 1);
...@@ -3749,6 +3756,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3749,6 +3756,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
ret = -ENOMEM; ret = -ENOMEM;
goto failed_mount; goto failed_mount;
} }
if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) !=
le32_to_cpu(es->s_inodes_count)) {
ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu",
le32_to_cpu(es->s_inodes_count),
((u64)sbi->s_groups_count * sbi->s_inodes_per_group));
ret = -EINVAL;
goto failed_mount;
}
bgl_lock_init(sbi->s_blockgroup_lock); bgl_lock_init(sbi->s_blockgroup_lock);
......
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