aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2016-07-05 20:01:52 -0400
committerMister Oyster <oysterized@gmail.com>2017-12-31 01:44:58 +0100
commitb7e52c7a982fe106c039f54907443b926c7f224c (patch)
treef177973baef8ac4a7d1745880720ec50b16b1387 /fs
parentcbe7359580f5f9007a3b5690b5794795a117049d (diff)
ext4: validate s_reserved_gdt_blocks on mount
If s_reserved_gdt_blocks is extremely large, it's possible for ext4_init_block_bitmap(), which is called when ext4 sets up an uninitialized block bitmap, to corrupt random kernel memory. Add the same checks which e2fsck has --- it must never be larger than blocksize / sizeof(__u32) --- and then add a backup check in ext4_init_block_bitmap() in case the superblock gets modified after the file system is mounted. Reported-by: Vegard Nossum <vegard.nossum@oracle.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Cc: stable@vger.kernel.org [@nathanchance: fixed conflicts] Signed-off-by: Nathan Chancellor <natechancellor@gmail.com> Signed-off-by: Joe Maples <joe@frap129.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/balloc.c3
-rw-r--r--fs/ext4/super.c7
2 files changed, 10 insertions, 0 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 83a6f497c..e1d4495ac 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -209,6 +209,9 @@ static int ext4_init_block_bitmap(struct super_block *sb,
memset(bh->b_data, 0, sb->s_blocksize);
bit_max = ext4_num_base_meta_clusters(sb, block_group);
+ if ((bit_max >> 3) >= bh->b_size)
+ return -EFSCORRUPTED;
+
for (bit = 0; bit < bit_max; bit++)
ext4_set_bit(bit, bh->b_data);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 5f9db470d..c1d91e575 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3403,6 +3403,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
goto failed_mount;
}
+ if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) {
+ ext4_msg(sb, KERN_ERR,
+ "Number of reserved GDT blocks insanely large: %d",
+ le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks));
+ goto failed_mount;
+ }
+
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT) &&
es->s_encryption_level) {
ext4_msg(sb, KERN_ERR, "Unsupported encryption level %d",