[Devel] [PATCH RHEL7 COMMIT] ext4: protect ext4_valid_block_bitmap from hardcore corruption
Konstantin Khorenko
khorenko at virtuozzo.com
Mon Apr 2 15:28:22 MSK 2018
The commit is pushed to "branch-rh7-3.10.0-693.21.1.vz7.46.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.21.1.vz7.46.2
------>
commit 07d08d6535d23b2b2f81d1569e5b4f2f40cbe4ca
Author: Dmitry Monakhov <dmonakhov at openvz.org>
Date: Mon Apr 2 15:28:22 2018 +0300
ext4: protect ext4_valid_block_bitmap from hardcore corruption
Assert that on-disk data values are in a expacted range, otherwise
later this result in accessing random memory regions like follows:
general protection fault: 0000 [#1] SMP
Modules linked in: binfmt_misc xt_CHECKSUM tun target_core_mod tcp_diag inet_diag ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle ip6table_raw iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat iptable_mangle iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter fuse kvm_intel kvm irqbypass i2c_piix4 sg ppdev virtio_balloon joydev parport_pc pcspkr parport ip_vs nf_conntrack libcrc32c br_netfilter veth overlay ip6_vzprivnet ip6_vznetstat ip_vznetstat ip_vzprivnet vziolimit vzevent vzlist vzstat vznetstat vznetdev vzmon vzdev bridge nfsd auth_rpcgss pio_kaio pio_nfs nfs_acl lockd grace pio_direct pfmt_raw
pfmt_ploop1 ploop ip_tables ext4 mbcache jbd2 sd_mod crc_t10dif crct10dif_generic sr_mod crct10dif_common cdrom ata_generic pata_acpi 8021q garp stp llc mrp virtio_net virtio_console virtio_scsi bochs_drm drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm ata_piix scsi_transport_iscsi drm floppy libata virtio_pci serio_raw i2c_core virtio_ring virtio sunrpc dm_mirror dm_region_hash dm_log dm_mod
CPU: 2 PID: 6711 Comm: vzctl ve: 0 Not tainted 3.10.0-693.1.1.vz7.37.31 #1 37.31
Hardware name: Virtuozzo KVM, BIOS 1.10.2-3.vz7.2 04/01/2014
task: ffff88022e0c5050 ti: ffff88021fa48000 task.ti: ffff88021fa48000
RIP: 0010:[<ffffffff813329d7>] [<ffffffff813329d7>] find_next_zero_bit+0x37/0xf0
RSP: 0018:ffff88021fa4bbc8 EFLAGS: 00010206
RAX: 03fffffffffff200 RBX: ffff8801f6334800 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000200 RDI: fffffffffffc8000
RBP: ffff88021fa4bbc8 R08: 1fff880096664000 R09: ffff8801f6334800
R10: ffff8800ae698660 R11: ffff88009c2981c0 R12: 0000000000000007
R13: ffff8801f6331000 R14: ffff88020b2d1680 R15: fffffffffffc8000
FS: 00007f637b9734c0(0000) GS:ffff88023fd00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f0330d3a4f0 CR3: 00000000ad516000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Stack:
ffff88021fa4bc28 ffffffffc029359e 0000000000000000 ffff8800ae698660
ffff88009c2981c0 ffff8801f6334800 0000000000000007 ffff8801f6331000
ffff88009c2981c0 0000000000000007 ffff8801f6334800 ffff88020b2d1680
Call Trace:
[<ffffffffc029359e>] ext4_validate_block_bitmap+0x2de/0x3c0 [ext4]
[<ffffffffc029413f>] ext4_read_block_bitmap_nowait+0x20f/0x5f0 [ext4]
[<ffffffffc0294539>] ext4_read_block_bitmap+0x19/0x60 [ext4]
[<ffffffffc02d8be6>] ext4_discard_preallocations+0x216/0x450 [ext4]
[<ffffffffc02c02da>] ext4_clear_inode+0x2a/0xb0 [ext4]
[<ffffffffc02a2020>] ext4_evict_inode+0x90/0x4f0 [ext4]
[<ffffffff81238229>] evict+0xa9/0x180
[<ffffffff8123833e>] dispose_list+0x3e/0x50
[<ffffffff812391b6>] evict_inodes+0xd6/0x140
[<ffffffff8121dee8>] generic_shutdown_super+0x48/0x100
[<ffffffff8121e367>] kill_block_super+0x27/0x70
[<ffffffffc02bb1ec>] ext4_kill_sb+0x4c/0x60 [ext4]
[<ffffffff8121e899>] deactivate_locked_super+0x49/0x80
[<ffffffff8121e916>] deactivate_super+0x46/0x60
[<ffffffff8123bfff>] cleanup_mnt+0x3f/0x80
[<ffffffff8123c092>] __cleanup_mnt+0x12/0x20
[<ffffffff810af9ed>] __task_work_run+0xad/0xd0
[<ffffffff8102aa84>] do_notify_resume+0x94/0xb0
[<ffffffff816b18fd>] int_signal+0x12/0x17
Code: 8a 00 00 00 48 89 d0 48 c1 e8 06 4c 8d 04 c7 48 89 d7 48 83 e7 c0 48 29 fe 83 e2 3f 75 76 48 f7 c6 c0 ff ff ff 0f 84 a7 00 00 00 <49> 8b 00 49 8d 50 08 48 83 f8 ff 74 1a eb 49 66 2e 0f 1f 84 00
RIP [<ffffffff813329d7>] find_next_zero_bit+0x37/0xf0
RSP <ffff88021fa4bbc8>
https://jira.sw.ru/browse/PSBM-78434
TODO: add testcase to xfstests
Signed-off-by: Dmitry Monakhov <dmonakhov at openvz.org>
---
fs/ext4/balloc.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 2763c597ccfe..267efdb7c1bf 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -341,20 +341,25 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb,
/* check whether block bitmap block number is set */
blk = ext4_block_bitmap(sb, desc);
offset = blk - group_first_block;
- if (!ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data))
+ if (EXT4_B2C(sbi, offset) >= bh->b_size * 8 ||
+ !ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data))
/* bad block bitmap */
return blk;
/* check whether the inode bitmap block number is set */
blk = ext4_inode_bitmap(sb, desc);
offset = blk - group_first_block;
- if (!ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data))
+ if (EXT4_B2C(sbi, offset) >= bh->b_size * 8 ||
+ !ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data))
/* bad block bitmap */
return blk;
/* check whether the inode table block number is set */
blk = ext4_inode_table(sb, desc);
offset = blk - group_first_block;
+ if (EXT4_B2C(sbi, offset + sbi->s_itb_per_group) >= bh->b_size * 8)
+ /* bad bitmap for inode tables */
+ return blk;
next_zero_bit = ext4_find_next_zero_bit(bh->b_data,
EXT4_B2C(sbi, offset + EXT4_SB(sb)->s_itb_per_group),
EXT4_B2C(sbi, offset));
More information about the Devel
mailing list