f2fs: fix to do sanity check on segment bitmap of LFS curseg
As Jungyeon Reported in bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=203233 - Reproduces gcc poc_13.c ./run.sh f2fs - Kernel messages F2FS-fs (sdb): Bitmap was wrongly set, blk:4608 kernel BUG at fs/f2fs/segment.c:2133! RIP: 0010:update_sit_entry+0x35d/0x3e0 Call Trace: f2fs_allocate_data_block+0x16c/0x5a0 do_write_page+0x57/0x100 f2fs_do_write_node_page+0x33/0xa0 __write_node_page+0x270/0x4e0 f2fs_sync_node_pages+0x5df/0x670 f2fs_write_checkpoint+0x364/0x13a0 f2fs_sync_fs+0xa3/0x130 f2fs_do_sync_file+0x1a6/0x810 do_fsync+0x33/0x60 __x64_sys_fsync+0xb/0x10 do_syscall_64+0x43/0x110 entry_SYSCALL_64_after_hwframe+0x44/0xa9 The testcase fails because that, in fuzzed image, current segment was allocated with LFS type, its .next_blkoff should point to an unused block address, but actually, its bitmap shows it's not. So during allocation, f2fs crash when setting bitmap. Introducing sanity_check_curseg() to check such inconsistence of current in-used segment. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
4d11d13e27
commit
c854f4d681
|
@ -4239,6 +4239,41 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi)
|
|||
return init_victim_secmap(sbi);
|
||||
}
|
||||
|
||||
static int sanity_check_curseg(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
|
||||
* In LFS curseg, all blkaddr after .next_blkoff should be unused.
|
||||
*/
|
||||
for (i = 0; i < NO_CHECK_TYPE; i++) {
|
||||
struct curseg_info *curseg = CURSEG_I(sbi, i);
|
||||
struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
|
||||
unsigned int blkofs = curseg->next_blkoff;
|
||||
|
||||
if (f2fs_test_bit(blkofs, se->cur_valid_map))
|
||||
goto out;
|
||||
|
||||
if (curseg->alloc_type == SSR)
|
||||
continue;
|
||||
|
||||
for (blkofs += 1; blkofs < sbi->blocks_per_seg; blkofs++) {
|
||||
if (!f2fs_test_bit(blkofs, se->cur_valid_map))
|
||||
continue;
|
||||
out:
|
||||
f2fs_msg(sbi->sb, KERN_ERR,
|
||||
"Current segment's next free block offset is "
|
||||
"inconsistent with bitmap, logtype:%u, "
|
||||
"segno:%u, type:%u, next_blkoff:%u, blkofs:%u",
|
||||
i, curseg->segno, curseg->alloc_type,
|
||||
curseg->next_blkoff, blkofs);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update min, max modified time for cost-benefit GC algorithm
|
||||
*/
|
||||
|
@ -4334,6 +4369,10 @@ int f2fs_build_segment_manager(struct f2fs_sb_info *sbi)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = sanity_check_curseg(sbi);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
init_min_max_mtime(sbi);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue