Re: [Bug] UBSAN: shift-out-of-bounds in sg_build_indirect
From: Sam Sun
Date: Tue Apr 09 2024 - 08:51:41 EST
On Mon, Mar 25, 2024 at 8:57 PM Sam Sun <samsun1006219@xxxxxxxxx> wrote:
>
> Dear developers and maintainers,
>
> We encountered a shift-out-of-bounds bug while using our modified
> Syzkaller. It is tested against linux kernel 6.9-rc1. Kernel config
> and C repro are attached to this email. The UBSAN report is listed
> below.
>
> ================================================================================
> UBSAN: shift-out-of-bounds in /home/sy/linux-original/drivers/scsi/sg.c:1902:13
> shift exponent 64 is too large for 32-bit type 'int'
> CPU: 1 PID: 8078 Comm: syz-executor748 Not tainted 6.7.0-rc7 #1
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
> 1.13.0-1ubuntu1.1 04/01/2014
> Call Trace:
> <TASK>
> __dump_stack lib/dump_stack.c:88 [inline]
> dump_stack_lvl+0x136/0x150 lib/dump_stack.c:106
> ubsan_epilogue lib/ubsan.c:217 [inline]
> __ubsan_handle_shift_out_of_bounds+0x24b/0x430 lib/ubsan.c:387
> sg_build_indirect.cold+0x1b/0x20 drivers/scsi/sg.c:1902
> sg_build_reserve+0xc4/0x180 drivers/scsi/sg.c:2012
> sg_add_sfp drivers/scsi/sg.c:2194 [inline]
> sg_open+0xde4/0x1810 drivers/scsi/sg.c:350
> chrdev_open+0x269/0x770 fs/char_dev.c:414
> do_dentry_open+0x6d3/0x18d0 fs/open.c:948
> do_open fs/namei.c:3622 [inline]
> path_openat+0x1e1e/0x26d0 fs/namei.c:3779
> do_filp_open+0x1c9/0x410 fs/namei.c:3809
> do_sys_openat2+0x160/0x1c0 fs/open.c:1437
> do_sys_open fs/open.c:1452 [inline]
> __do_sys_openat fs/open.c:1468 [inline]
> __se_sys_openat fs/open.c:1463 [inline]
> __x64_sys_openat+0x140/0x1f0 fs/open.c:1463
> do_syscall_x64 arch/x86/entry/common.c:52 [inline]
> do_syscall_64+0x40/0x110 arch/x86/entry/common.c:83
> entry_SYSCALL_64_after_hwframe+0x63/0x6b
> RIP: 0033:0x7f48cf37f80b
> Code: 25 00 00 41 00 3d 00 00 41 00 74 4b 64 8b 04 25 18 00 00 00 85
> c0 75 67 44 89 e2 48 89 ee bf 9c ff ff ff b8 01 01 00 00 0f 05 <48> 3d
> 00 f0 ff ff 0f 87 91 00 00 00 48 8b 4c 24 28 64 48 33 0c 25
> RSP: 002b:00007ffd29cd7d40 EFLAGS: 00000246 ORIG_RAX: 0000000000000101
> RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f48cf37f80b
> RDX: 0000000000000041 RSI: 00007ffd29cd7dc0 RDI: 00000000ffffff9c
> RBP: 00007ffd29cd7dc0 R08: 000000000000ffff R09: 00007ffd29cd7c50
> R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000041
> R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
> </TASK>
> ================================================================================
>
> If you have any questions, please contact us.
> Reported by: Yue Sun <samsun1006219@xxxxxxxxx>
> Reported by: xingwei lee <xrivendell7@xxxxxxxxx>
>
> Best Regards,
> Yue
We further analyzed the root cause of this bug. In function
sg_build_indirect of drivers/scsi/sg.c, variable order of line 1900 is
calculated out using get_order(num), and num comes from
scatter_elem_sz. If scatter_elem_sz is equal or below zero, the order
returned will be 52, so that PAGE_SHIFT + order is 64, which is larger
than 32 bits int range, causing shift-out-of bound. This bug is tested
and still remains in the latest upstream linux (6.9-rc3).
If you have any questions, please contact us.
Best,
Yue