Re: [PATCH] f2fs: fix shift-out-of-bounds in f2fs_fill_super

From: Chao Yu
Date: Sun Jan 29 2023 - 04:18:56 EST


On 2023/1/29 15:55, Yangtao Li wrote:
syzbot reported a bug which could cause shift-out-of-bounds issue:

UBSAN: shift-out-of-bounds in fs/f2fs/super.c:4184:41
shift exponent 613 is too large for 64-bit type 'loff_t' (aka 'long long')
CPU: 1 PID: 5467 Comm: syz-executor.0 Not tainted 6.2.0-rc5-syzkaller #0
Hardware name: Google Compute Engine/Google Compute Engine,
BIOS Google 01/12/2023
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0x1b1/0x290 lib/dump_stack.c:106
ubsan_epilogue lib/ubsan.c:151 [inline]
__ubsan_handle_shift_out_of_bounds+0x33d/0x3a0 lib/ubsan.c:321
f2fs_fill_super+0x5518/0x6ee0 fs/f2fs/super.c:4184
mount_bdev+0x26c/0x3a0 fs/super.c:1359
legacy_get_tree+0xea/0x180 fs/fs_context.c:610
vfs_get_tree+0x88/0x270 fs/super.c:1489
do_new_mount+0x289/0xad0 fs/namespace.c:3145
do_mount fs/namespace.c:3488 [inline]
__do_sys_mount fs/namespace.c:3697 [inline]
__se_sys_mount+0x2d3/0x3c0 fs/namespace.c:3674
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd
</TASK>

Since currently only 4kb block size is supported by f2fs,
let's use 4kb directly to avoid triggering UBSAN exception.

It doesn't fix the root cause...

How can we get invalid raw_super->log_blocksize value after below sanity check
in sanity_check_raw_super():

/* Currently, support only 4KB block size */
if (le32_to_cpu(raw_super->log_blocksize) != F2FS_BLKSIZE_BITS) {
f2fs_info(sbi, "Invalid log_blocksize (%u), supports only %u",
le32_to_cpu(raw_super->log_blocksize),
F2FS_BLKSIZE_BITS);
return -EFSCORRUPTED;
}

Thanks,


Reported-by: syzbot+fea4bcda5eb938ee88ed@xxxxxxxxxxxxxxxxxxxxxxxxx
Signed-off-by: Yangtao Li <frank.li@xxxxxxxx>
---
fs/f2fs/super.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index d8a65645ee48..41c2bbd3e719 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -4174,8 +4174,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
if (err)
goto free_options;
- sb->s_maxbytes = max_file_blocks(NULL) <<
- le32_to_cpu(raw_super->log_blocksize);
+ /* Currently, support only 4KB block size */
+ sb->s_maxbytes = max_file_blocks(NULL) << F2FS_BLKSIZE_BITS;
sb->s_max_links = F2FS_LINK_MAX;
err = f2fs_setup_casefold(sbi);