In sanity_check_raw_super(), if 1 << le32_to_cpu(raw_super->log_blocksize) != F2FS_BLKSIZE, then the block size is deemed to be invalid.
syzbot triggered a shift-out-of-bounds bug by assigning a value of 59 to le32_to_cpu(raw_super->log_blocksize). Although the value assigned itself isn't of much significance, this goes to show that even if the block size is invalid, le32_to_cpu(raw_super->log_blocksize) can be potentially evaluated to a value for which the shift exponent becomes too large for the unsigned int. Since 1 << le32_to_cpu(raw_super->log_blocksize) must be = 4096 for a valid block size, le32_to_cpu(raw_super->log_blocksize) must equal 12. Replacing the existing check with the more direct sanity check resolves this bug. Reported-by: syzbot+ca9a785f8ac472085...@syzkaller.appspotmail.com Tested-by: syzbot+ca9a785f8ac472085...@syzkaller.appspotmail.com Signed-off-by: Anant Thazhemadam <anant.thazhema...@gmail.com> --- fs/f2fs/super.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 33808c397580..4bc7372af43f 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2775,7 +2775,6 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, block_t total_sections, blocks_per_seg; struct f2fs_super_block *raw_super = (struct f2fs_super_block *) (bh->b_data + F2FS_SUPER_OFFSET); - unsigned int blocksize; size_t crc_offset = 0; __u32 crc = 0; @@ -2802,10 +2801,8 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, } /* Currently, support only 4KB block size */ - blocksize = 1 << le32_to_cpu(raw_super->log_blocksize); - if (blocksize != F2FS_BLKSIZE) { - f2fs_info(sbi, "Invalid blocksize (%u), supports only 4KB", - blocksize); + if (le32_to_cpu(raw_super->log_blocksize) != 12) { + f2fs_info(sbi, "Invalid blocksize. Only 4KB supported"); return -EFSCORRUPTED; } -- 2.25.1