KMSAN: kernel-infoleak in sg_scsi_ioctl

From: Hao Sun
Date: Mon Apr 12 2021 - 09:02:46 EST


Hi

When using Healer(https://github.com/SunHao-0/healer/tree/dev) to fuzz
the Linux kernel, I found the following bug report.

commit: 4ebaab5fb428374552175aa39832abf5cedb916a
version: linux 5.12
git tree: kmsan
kernel config and full log can be found in the attached file.

=====================================================
BUG: KMSAN: kernel-infoleak in kmsan_copy_to_user+0x9c/0xb0
mm/kmsan/kmsan_hooks.c:249
CPU: 2 PID: 23939 Comm: executor Not tainted 5.12.0-rc6+ #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
__dump_stack lib/dump_stack.c:79 [inline]
dump_stack+0x1ff/0x275 lib/dump_stack.c:120
kmsan_report+0xfb/0x1e0 mm/kmsan/kmsan_report.c:118
kmsan_internal_check_memory+0x48c/0x520 mm/kmsan/kmsan.c:437
kmsan_copy_to_user+0x9c/0xb0 mm/kmsan/kmsan_hooks.c:249
instrument_copy_to_user ./include/linux/instrumented.h:121 [inline]
_copy_to_user+0x112/0x1d0 lib/usercopy.c:33
copy_to_user ./include/linux/uaccess.h:209 [inline]
sg_scsi_ioctl+0xfa9/0x1180 block/scsi_ioctl.c:507
sg_ioctl_common+0x2713/0x4930 drivers/scsi/sg.c:1108
sg_ioctl+0x166/0x2d0 drivers/scsi/sg.c:1162
vfs_ioctl fs/ioctl.c:48 [inline]
__do_sys_ioctl fs/ioctl.c:753 [inline]
__se_sys_ioctl+0x2c2/0x400 fs/ioctl.c:739
__x64_sys_ioctl+0x4a/0x70 fs/ioctl.c:739
do_syscall_64+0xa2/0x120 arch/x86/entry/common.c:48
entry_SYSCALL_64_after_hwframe+0x44/0xae
RIP: 0033:0x47338d
Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48
89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d
01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fe31ab90c58 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 000000000059c128 RCX: 000000000047338d
RDX: 0000000020000040 RSI: 0000000000000001 RDI: 0000000000000003
RBP: 00000000004e8e5d R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 000000000059c128
R13: 00007ffe2284af2f R14: 00007ffe2284b0d0 R15: 00007fe31ab90dc0
Uninit was stored to memory at:
kmsan_save_stack_with_flags mm/kmsan/kmsan.c:121 [inline]
kmsan_internal_chain_origin+0xad/0x130 mm/kmsan/kmsan.c:289
kmsan_memcpy_memmove_metadata+0x25b/0x290 mm/kmsan/kmsan.c:226
kmsan_memcpy_metadata+0xb/0x10 mm/kmsan/kmsan.c:246
__msan_memcpy+0x46/0x60 mm/kmsan/kmsan_instr.c:110
bio_copy_kern_endio_read+0x3ee/0x560 block/blk-map.c:443
bio_endio+0xa1a/0xcc0 block/bio.c:1453
req_bio_endio block/blk-core.c:265 [inline]
blk_update_request+0xd4f/0x2190 block/blk-core.c:1456
scsi_end_request+0x111/0xc50 drivers/scsi/scsi_lib.c:570
scsi_io_completion+0x276/0x2840 drivers/scsi/scsi_lib.c:970
scsi_finish_command+0x6fc/0x720 drivers/scsi/scsi.c:214
scsi_softirq_done+0x205/0xa40 drivers/scsi/scsi_lib.c:1450
blk_complete_reqs block/blk-mq.c:576 [inline]
blk_done_softirq+0x133/0x1e0 block/blk-mq.c:581
__do_softirq+0x271/0x782 kernel/softirq.c:345

Uninit was created at:
kmsan_save_stack_with_flags+0x3c/0x90
kmsan_alloc_page+0xc4/0x1b0
__alloc_pages_nodemask+0xdb0/0x54a0
alloc_pages_current+0x671/0x990
blk_rq_map_kern+0xb8e/0x1310
sg_scsi_ioctl+0xc94/0x1180
sg_ioctl_common+0x2713/0x4930
sg_ioctl+0x166/0x2d0
__se_sys_ioctl+0x2c2/0x400
__x64_sys_ioctl+0x4a/0x70
do_syscall_64+0xa2/0x120
entry_SYSCALL_64_after_hwframe+0x44/0xae

Byte 0 of 1 is uninitialized
Memory access of size 1 starts at ffff99e033fb9360
Data copied to user address 0000000020000048

The following system call sequence (Syzlang format) can reproduce the crash:
# {Threaded:false Collide:false Repeat:false RepeatTimes:0 Procs:1
Slowdown:1 Sandbox:none Fault:false FaultCall:-1 FaultNth:0 Leak:false
NetInjection:true NetDevices:true NetReset:false Cgroups:false
BinfmtMisc:true CloseFDs:true KCSAN:false DevlinkPCI:true USB:true
VhciInjection:true Wifi:true IEEE802154:true Sysctl:true
UseTmpDir:true HandleSegv:true Repro:false Trace:false}

r0 = syz_open_dev$sg(&(0x7f0000000000)='/dev/sg#\x00', 0x0, 0x20000094b402)
ioctl$SG_GET_LOW_DMA(r0, 0x227a, &(0x7f0000000040))
ioctl$SCSI_IOCTL_SEND_COMMAND(r0, 0x1, &(0x7f0000000040)={0x0, 0x1, 0x1})

Using syz-execprog can run this reproduction program directly:
./syz-execprog -repeat 0 -procs 1 -slowdown 1 -enable tun -enable
netdev -enable binfmt-misc -enable close_fds -enable devlinkpci
-enable usb -enable vhci -enable wifi -enable ieee802154 -enable
sysctl repro.prog

Attachment: kmsan-config
Description: Binary data

Attachment: log
Description: Binary data