Re: [syzbot] [usb?] KMSAN: kernel-infoleak in raw_ioctl (2)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jul 23, 2024 at 10:55 PM syzbot
<syzbot+17ca2339e34a1d863aad@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit:    2c9b3512402e Merge tag 'for-linus' of git://git.kernel.org..
> git tree:       upstream
> console+strace: https://syzkaller.appspot.com/x/log.txt?x=1197b6b5980000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=6bfb33a8ad10458f
> dashboard link: https://syzkaller.appspot.com/bug?extid=17ca2339e34a1d863aad
> compiler:       Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1626b995980000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=1572eb21980000
>
> Downloadable assets:
> disk image: https://storage.googleapis.com/syzbot-assets/f8543636ba6c/disk-2c9b3512.raw.xz
> vmlinux: https://storage.googleapis.com/syzbot-assets/403c612b7ac5/vmlinux-2c9b3512.xz
> kernel image: https://storage.googleapis.com/syzbot-assets/88dc686d170a/bzImage-2c9b3512.xz
>
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+17ca2339e34a1d863aad@xxxxxxxxxxxxxxxxxxxxxxxxx
>
> =====================================================
> BUG: KMSAN: kernel-infoleak in instrument_copy_to_user include/linux/instrumented.h:114 [inline]
> BUG: KMSAN: kernel-infoleak in _copy_to_user+0xbc/0x110 lib/usercopy.c:45
>  instrument_copy_to_user include/linux/instrumented.h:114 [inline]
>  _copy_to_user+0xbc/0x110 lib/usercopy.c:45
>  copy_to_user include/linux/uaccess.h:191 [inline]
>  raw_ioctl_ep0_read drivers/usb/gadget/legacy/raw_gadget.c:786 [inline]
>  raw_ioctl+0x3d2e/0x5440 drivers/usb/gadget/legacy/raw_gadget.c:1315
>  vfs_ioctl fs/ioctl.c:51 [inline]
>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>  __se_sys_ioctl+0x261/0x450 fs/ioctl.c:893
>  __x64_sys_ioctl+0x96/0xe0 fs/ioctl.c:893
>  x64_sys_call+0x1a06/0x3c10 arch/x86/include/generated/asm/syscalls_64.h:17
>  do_syscall_x64 arch/x86/entry/common.c:52 [inline]
>  do_syscall_64+0xcd/0x1e0 arch/x86/entry/common.c:83
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>
> Uninit was created at:
>  slab_post_alloc_hook mm/slub.c:3985 [inline]
>  slab_alloc_node mm/slub.c:4028 [inline]
>  __do_kmalloc_node mm/slub.c:4148 [inline]
>  __kmalloc_noprof+0x661/0xf30 mm/slub.c:4161
>  kmalloc_noprof include/linux/slab.h:685 [inline]
>  raw_alloc_io_data drivers/usb/gadget/legacy/raw_gadget.c:675 [inline]
>  raw_ioctl_ep0_read drivers/usb/gadget/legacy/raw_gadget.c:778 [inline]
>  raw_ioctl+0x3bcb/0x5440 drivers/usb/gadget/legacy/raw_gadget.c:1315
>  vfs_ioctl fs/ioctl.c:51 [inline]
>  __do_sys_ioctl fs/ioctl.c:907 [inline]
>  __se_sys_ioctl+0x261/0x450 fs/ioctl.c:893
>  __x64_sys_ioctl+0x96/0xe0 fs/ioctl.c:893
>  x64_sys_call+0x1a06/0x3c10 arch/x86/include/generated/asm/syscalls_64.h:17
>  do_syscall_x64 arch/x86/entry/common.c:52 [inline]
>  do_syscall_64+0xcd/0x1e0 arch/x86/entry/common.c:83
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
>
> Bytes 0-4095 of 4096 are uninitialized
> Memory access of size 4096 starts at ffff888116edb000
> Data copied to user address 00007ffefdca74d8
>
> CPU: 0 PID: 5057 Comm: syz-executor289 Not tainted 6.10.0-syzkaller-11185-g2c9b3512402e #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 06/27/2024
> =====================================================

Hi Alex,

This appears to be some kind of a bug in KMSAN.

I applied a debugging patch that prints the data submitted by ath9k,
tracks the data being copied to Raw Gadget, and prints the data copied
to userspace by Raw Gadget (attached). I see that the submitted and
the copied data match (at least, the first 8 bytes). I also see that
the data is copied from ath9k to Raw Gadget as intended. So the data
should be initialized. However, somehow, KMSAN doesn't track that.

The bug is reproducible via the C reproducer, but you have to keep it
running for a minute or so. The output with the debugging patch is
somewhat messy due to multiple threads being involved, but you can
start unveiling it backwards from the kernel address printed in the
KMSAN report.

Thanks!
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 0c7841f95228..e41954a98294 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -1083,6 +1083,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
 		transfer = min_t(size_t, len, 4096);
 		memcpy(buf, data, transfer);
 
+pr_err("! ath9k: transfer = %d, buf = %px, bytes = %lx\n", (int)transfer, buf, *(unsigned long *)buf);
 		err = usb_control_msg(hif_dev->udev,
 				      usb_sndctrlpipe(hif_dev->udev, 0),
 				      FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT,
diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
index 399fca32a8ac..0af20ac56602 100644
--- a/drivers/usb/gadget/legacy/raw_gadget.c
+++ b/drivers/usb/gadget/legacy/raw_gadget.c
@@ -783,6 +783,9 @@ static int raw_ioctl_ep0_read(struct raw_dev *dev, unsigned long value)
 		goto free;
 
 	length = min(io.length, (unsigned int)ret);
+current->kmsan_ctx.allow_reporting = false;
+if (length >= 8) pr_err("! ep0_read: length = %u, data = %px, bytes = %lx\n", length, data, *(unsigned long *)data);
+current->kmsan_ctx.allow_reporting = true;
 	if (copy_to_user((void __user *)(value + sizeof(io)), data, length))
 		ret = -EFAULT;
 	else
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index f37b0d8386c1..1690e4906c43 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -1350,7 +1350,10 @@ static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
 		if (to_host)
 			memcpy(ubuf, rbuf, len);
 		else
+{
+pr_err("! dummy: memcpy(%px, %px, %u)\n", rbuf, ubuf, len);
 			memcpy(rbuf, ubuf, len);
+}
 		return len;
 	}
 
@@ -1379,7 +1382,10 @@ static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
 		if (to_host)
 			memcpy(ubuf, rbuf, this_sg);
 		else
+{
+pr_err("! dummy: memcpy(%px, %px, %u)\n", rbuf, ubuf, len);
 			memcpy(rbuf, ubuf, this_sg);
+}
 		len -= this_sg;
 
 		if (!len)

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux