Skip to content

Commit e500902

Browse files
zhangyi089gregkh
authored andcommitted
ext4: clear buffer verified flag if read meta block from disk
commit d9befed upstream. The metadata buffer is no longer trusted after we read it from disk again because it is not uptodate for some reasons (e.g. failed to write back). Otherwise we may get below memory corruption problem in ext4_ext_split()->memset() if we read stale data from the newly allocated extent block on disk which has been failed to async write out but miss verify again since the verified bit has already been set on the buffer. [ 29.774674] BUG: unable to handle kernel paging request at ffff88841949d000 ... [ 29.783317] Oops: 0002 [#2] SMP [ 29.784219] R10: 00000000000f4240 R11: 0000000000002e28 R12: ffff88842fa1c800 [ 29.784627] CPU: 1 PID: 126 Comm: kworker/u4:3 Tainted: G D W [ 29.785546] R13: ffffffff9cddcc20 R14: ffffffff9cddd420 R15: ffff88842fa1c2f8 [ 29.786679] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),BIOS ?-20190727_0738364 [ 29.787588] FS: 0000000000000000(0000) GS:ffff88842fa00000(0000) knlGS:0000000000000000 [ 29.789288] Workqueue: writeback wb_workfn [ 29.790319] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 29.790321] (flush-8:0) [ 29.790844] CR2: 0000000000000008 CR3: 00000004234f2000 CR4: 00000000000006f0 [ 29.791924] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 29.792839] RIP: 0010:__memset+0x24/0x30 [ 29.793739] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 29.794256] Code: 90 90 90 90 90 90 0f 1f 44 00 00 49 89 f9 48 89 d1 83 e2 07 48 c1 e9 033 [ 29.795161] Kernel panic - not syncing: Fatal exception in interrupt ... [ 29.808149] Call Trace: [ 29.808475] ext4_ext_insert_extent+0x102e/0x1be0 [ 29.809085] ext4_ext_map_blocks+0xa89/0x1bb0 [ 29.809652] ext4_map_blocks+0x290/0x8a0 [ 29.809085] ext4_ext_map_blocks+0xa89/0x1bb0 [ 29.809652] ext4_map_blocks+0x290/0x8a0 [ 29.810161] ext4_writepages+0xc85/0x17c0 ... Fix this by clearing buffer's verified bit if we read meta block from disk again. Signed-off-by: zhangyi (F) <yi.zhang@huawei.com> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200924073337.861472-2-yi.zhang@huawei.com Signed-off-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 357cc4c commit e500902

File tree

5 files changed

+8
-1
lines changed

5 files changed

+8
-1
lines changed

fs/ext4/balloc.c

+1
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group,
494494
* submit the buffer_head for reading
495495
*/
496496
set_buffer_new(bh);
497+
clear_buffer_verified(bh);
497498
trace_ext4_read_block_bitmap_load(sb, block_group, ignore_locked);
498499
bh->b_end_io = ext4_end_bitmap_read;
499500
get_bh(bh);

fs/ext4/extents.c

+1
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ __read_extent_tree_block(const char *function, unsigned int line,
501501

502502
if (!bh_uptodate_or_lock(bh)) {
503503
trace_ext4_ext_load_extent(inode, pblk, _RET_IP_);
504+
clear_buffer_verified(bh);
504505
err = bh_submit_read(bh);
505506
if (err < 0)
506507
goto errout;

fs/ext4/ialloc.c

+1
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
188188
/*
189189
* submit the buffer_head for reading
190190
*/
191+
clear_buffer_verified(bh);
191192
trace_ext4_load_inode_bitmap(sb, block_group);
192193
bh->b_end_io = ext4_end_bitmap_read;
193194
get_bh(bh);

fs/ext4/inode.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
884884
return bh;
885885
if (!bh || ext4_buffer_uptodate(bh))
886886
return bh;
887+
clear_buffer_verified(bh);
887888
ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &bh);
888889
wait_on_buffer(bh);
889890
if (buffer_uptodate(bh))
@@ -909,9 +910,11 @@ int ext4_bread_batch(struct inode *inode, ext4_lblk_t block, int bh_count,
909910

910911
for (i = 0; i < bh_count; i++)
911912
/* Note that NULL bhs[i] is valid because of holes. */
912-
if (bhs[i] && !ext4_buffer_uptodate(bhs[i]))
913+
if (bhs[i] && !ext4_buffer_uptodate(bhs[i])) {
914+
clear_buffer_verified(bhs[i]);
913915
ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1,
914916
&bhs[i]);
917+
}
915918

916919
if (!wait)
917920
return 0;

fs/ext4/super.c

+1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ ext4_sb_bread(struct super_block *sb, sector_t block, int op_flags)
156156
return ERR_PTR(-ENOMEM);
157157
if (ext4_buffer_uptodate(bh))
158158
return bh;
159+
clear_buffer_verified(bh);
159160
ll_rw_block(REQ_OP_READ, REQ_META | op_flags, 1, &bh);
160161
wait_on_buffer(bh);
161162
if (buffer_uptodate(bh))

0 commit comments

Comments
 (0)