aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2018-06-17 18:11:20 -0400
committerTheodore Ts'o <tytso@mit.edu>2018-06-17 18:11:20 -0400
commitbfe0a5f47ada40d7984de67e59a7d3390b9b9ecc (patch)
treebb20c9d7def61a74f3d0e1686358849ac9110309
parentc37e9e013469521d9adb932d17a1795c139b36db (diff)
ext4: add more mount time checks of the superblock
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: Theodore Ts'o <tytso@mit.edu> Cc: stable@kernel.org
-rw-r--r--fs/ext4/super.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 1f955c128e0d..b37b00befd65 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3793,6 +3793,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3793 le32_to_cpu(es->s_log_block_size)); 3793 le32_to_cpu(es->s_log_block_size));
3794 goto failed_mount; 3794 goto failed_mount;
3795 } 3795 }
3796 if (le32_to_cpu(es->s_log_cluster_size) >
3797 (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
3798 ext4_msg(sb, KERN_ERR,
3799 "Invalid log cluster size: %u",
3800 le32_to_cpu(es->s_log_cluster_size));
3801 goto failed_mount;
3802 }
3796 3803
3797 if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) { 3804 if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) {
3798 ext4_msg(sb, KERN_ERR, 3805 ext4_msg(sb, KERN_ERR,
@@ -3939,13 +3946,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3939 "block size (%d)", clustersize, blocksize); 3946 "block size (%d)", clustersize, blocksize);
3940 goto failed_mount; 3947 goto failed_mount;
3941 } 3948 }
3942 if (le32_to_cpu(es->s_log_cluster_size) >
3943 (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
3944 ext4_msg(sb, KERN_ERR,
3945 "Invalid log cluster size: %u",
3946 le32_to_cpu(es->s_log_cluster_size));
3947 goto failed_mount;
3948 }
3949 sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) - 3949 sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
3950 le32_to_cpu(es->s_log_block_size); 3950 le32_to_cpu(es->s_log_block_size);
3951 sbi->s_clusters_per_group = 3951 sbi->s_clusters_per_group =
@@ -3966,10 +3966,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3966 } 3966 }
3967 } else { 3967 } else {
3968 if (clustersize != blocksize) { 3968 if (clustersize != blocksize) {
3969 ext4_warning(sb, "fragment/cluster size (%d) != " 3969 ext4_msg(sb, KERN_ERR,
3970 "block size (%d)", clustersize, 3970 "fragment/cluster size (%d) != "
3971 blocksize); 3971 "block size (%d)", clustersize, blocksize);
3972 clustersize = blocksize; 3972 goto failed_mount;
3973 } 3973 }
3974 if (sbi->s_blocks_per_group > blocksize * 8) { 3974 if (sbi->s_blocks_per_group > blocksize * 8) {
3975 ext4_msg(sb, KERN_ERR, 3975 ext4_msg(sb, KERN_ERR,
@@ -4023,6 +4023,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
4023 ext4_blocks_count(es)); 4023 ext4_blocks_count(es));
4024 goto failed_mount; 4024 goto failed_mount;
4025 } 4025 }
4026 if ((es->s_first_data_block == 0) && (es->s_log_block_size == 0) &&
4027 (sbi->s_cluster_ratio == 1)) {
4028 ext4_msg(sb, KERN_WARNING, "bad geometry: first data "
4029 "block is 0 with a 1k block and cluster size");
4030 goto failed_mount;
4031 }
4032
4026 blocks_count = (ext4_blocks_count(es) - 4033 blocks_count = (ext4_blocks_count(es) -
4027 le32_to_cpu(es->s_first_data_block) + 4034 le32_to_cpu(es->s_first_data_block) +
4028 EXT4_BLOCKS_PER_GROUP(sb) - 1); 4035 EXT4_BLOCKS_PER_GROUP(sb) - 1);
@@ -4058,6 +4065,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
4058 ret = -ENOMEM; 4065 ret = -ENOMEM;
4059 goto failed_mount; 4066 goto failed_mount;
4060 } 4067 }
4068 if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) !=
4069 le32_to_cpu(es->s_inodes_count)) {
4070 ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu",
4071 le32_to_cpu(es->s_inodes_count),
4072 ((u64)sbi->s_groups_count * sbi->s_inodes_per_group));
4073 ret = -EINVAL;
4074 goto failed_mount;
4075 }
4061 4076
4062 bgl_lock_init(sbi->s_blockgroup_lock); 4077 bgl_lock_init(sbi->s_blockgroup_lock);
4063 4078