| From 5b9554dc5bf008ae7f68a52e3d7e76c0920938a2 Mon Sep 17 00:00:00 2001 |
| From: Theodore Ts'o <tytso@mit.edu> |
| Date: Tue, 5 Jul 2016 20:01:52 -0400 |
| Subject: ext4: validate s_reserved_gdt_blocks on mount |
| |
| From: Theodore Ts'o <tytso@mit.edu> |
| |
| commit 5b9554dc5bf008ae7f68a52e3d7e76c0920938a2 upstream. |
| |
| 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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/ext4/balloc.c | 3 +++ |
| fs/ext4/super.c | 7 +++++++ |
| 2 files changed, 10 insertions(+) |
| |
| --- a/fs/ext4/balloc.c |
| +++ b/fs/ext4/balloc.c |
| @@ -208,6 +208,9 @@ static int ext4_init_block_bitmap(struct |
| 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); |
| |
| --- a/fs/ext4/super.c |
| +++ b/fs/ext4/super.c |
| @@ -3372,6 +3372,13 @@ static int ext4_fill_super(struct super_ |
| 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 (sbi->s_mount_opt & EXT4_MOUNT_DAX) { |
| if (blocksize != PAGE_SIZE) { |
| ext4_msg(sb, KERN_ERR, |