Message ID | 20180618032232.25481-5-tytso@mit.edu |
---|---|
State | Accepted, archived |
Headers | show |
Series | [1/5] ext4: never move the system.data xattr out of the inode body | expand |
> On Jun 17, 2018, at 9:22 PM, Theodore Ts'o <tytso@mit.edu> wrote: > > 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> I thought the last hunk would conflict with Jan's patch series, but that is for e2fsck and this is for ext4... Reviewed-by: Andreas Dilger <adilger@dilger.ca> > --- > fs/ext4/super.c | 37 ++++++++++++++++++++++++++----------- > 1 file 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) > le32_to_cpu(es->s_log_block_size)); > 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)) { > ext4_msg(sb, KERN_ERR, > @@ -3939,13 +3946,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) > "block size (%d)", clustersize, blocksize); > 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) - > le32_to_cpu(es->s_log_block_size); > sbi->s_clusters_per_group = > @@ -3966,10 +3966,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) > } > } else { > if (clustersize != blocksize) { > - ext4_warning(sb, "fragment/cluster size (%d) != " > - "block size (%d)", clustersize, > - blocksize); > - clustersize = blocksize; > + ext4_msg(sb, KERN_ERR, > + "fragment/cluster size (%d) != " > + "block size (%d)", clustersize, blocksize); > + goto failed_mount; > } > if (sbi->s_blocks_per_group > blocksize * 8) { > ext4_msg(sb, KERN_ERR, > @@ -4023,6 +4023,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) > ext4_blocks_count(es)); > 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) - > le32_to_cpu(es->s_first_data_block) + > EXT4_BLOCKS_PER_GROUP(sb) - 1); > @@ -4058,6 +4065,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) > ret = -ENOMEM; > 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; > + } Cheers, Andreas
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) le32_to_cpu(es->s_log_block_size)); 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)) { ext4_msg(sb, KERN_ERR, @@ -3939,13 +3946,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) "block size (%d)", clustersize, blocksize); 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) - le32_to_cpu(es->s_log_block_size); sbi->s_clusters_per_group = @@ -3966,10 +3966,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) } } else { if (clustersize != blocksize) { - ext4_warning(sb, "fragment/cluster size (%d) != " - "block size (%d)", clustersize, - blocksize); - clustersize = blocksize; + ext4_msg(sb, KERN_ERR, + "fragment/cluster size (%d) != " + "block size (%d)", clustersize, blocksize); + goto failed_mount; } if (sbi->s_blocks_per_group > blocksize * 8) { ext4_msg(sb, KERN_ERR, @@ -4023,6 +4023,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ext4_blocks_count(es)); 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) - le32_to_cpu(es->s_first_data_block) + EXT4_BLOCKS_PER_GROUP(sb) - 1); @@ -4058,6 +4065,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ret = -ENOMEM; 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);
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> --- fs/ext4/super.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-)