From: Greg Kroah-Hartman Date: Thu, 19 Sep 2019 11:42:08 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v4.4.194~50 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=31066d2b07ab1efcd1ebf493f9d0abcf3a5a819c;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: media-tm6000-double-free-if-usb-disconnect-while-streaming.patch usb-usbcore-fix-slab-out-of-bounds-bug-during-device-reset.patch --- diff --git a/queue-4.9/media-tm6000-double-free-if-usb-disconnect-while-streaming.patch b/queue-4.9/media-tm6000-double-free-if-usb-disconnect-while-streaming.patch new file mode 100644 index 00000000000..a611d549490 --- /dev/null +++ b/queue-4.9/media-tm6000-double-free-if-usb-disconnect-while-streaming.patch @@ -0,0 +1,135 @@ +From 699bf94114151aae4dceb2d9dbf1a6312839dcae Mon Sep 17 00:00:00 2001 +From: Sean Young +Date: Tue, 13 Aug 2019 13:45:09 -0300 +Subject: media: tm6000: double free if usb disconnect while streaming + +From: Sean Young + +commit 699bf94114151aae4dceb2d9dbf1a6312839dcae upstream. + +The usb_bulk_urb will kfree'd on disconnect, so ensure the pointer is set +to NULL after each free. + +stop stream +urb killing +urb buffer free +tm6000: got start feed request tm6000_start_feed +tm6000: got start stream request tm6000_start_stream +tm6000: pipe reset +tm6000: got start feed request tm6000_start_feed +tm6000: got start feed request tm6000_start_feed +tm6000: got start feed request tm6000_start_feed +tm6000: got start feed request tm6000_start_feed +tm6000: IR URB failure: status: -71, length 0 +xhci_hcd 0000:00:14.0: ERROR unknown event type 37 +xhci_hcd 0000:00:14.0: ERROR unknown event type 37 +tm6000: error tm6000_urb_received +usb 1-2: USB disconnect, device number 5 +tm6000: disconnecting tm6000 #0 +================================================================== +BUG: KASAN: use-after-free in dvb_fini+0x75/0x140 [tm6000_dvb] +Read of size 8 at addr ffff888241044060 by task kworker/2:0/22 + +CPU: 2 PID: 22 Comm: kworker/2:0 Tainted: G W 5.3.0-rc4+ #1 +Hardware name: LENOVO 20KHCTO1WW/20KHCTO1WW, BIOS N23ET65W (1.40 ) 07/02/2019 +Workqueue: usb_hub_wq hub_event +Call Trace: + dump_stack+0x9a/0xf0 + print_address_description.cold+0xae/0x34f + __kasan_report.cold+0x75/0x93 + ? tm6000_fillbuf+0x390/0x3c0 [tm6000_alsa] + ? dvb_fini+0x75/0x140 [tm6000_dvb] + kasan_report+0xe/0x12 + dvb_fini+0x75/0x140 [tm6000_dvb] + tm6000_close_extension+0x51/0x80 [tm6000] + tm6000_usb_disconnect.cold+0xd4/0x105 [tm6000] + usb_unbind_interface+0xe4/0x390 + device_release_driver_internal+0x121/0x250 + bus_remove_device+0x197/0x260 + device_del+0x268/0x550 + ? __device_links_no_driver+0xd0/0xd0 + ? usb_remove_ep_devs+0x30/0x3b + usb_disable_device+0x122/0x400 + usb_disconnect+0x153/0x430 + hub_event+0x800/0x1e40 + ? trace_hardirqs_on_thunk+0x1a/0x20 + ? hub_port_debounce+0x1f0/0x1f0 + ? retint_kernel+0x10/0x10 + ? lock_is_held_type+0xf1/0x130 + ? hub_port_debounce+0x1f0/0x1f0 + ? process_one_work+0x4ae/0xa00 + process_one_work+0x4ba/0xa00 + ? pwq_dec_nr_in_flight+0x160/0x160 + ? do_raw_spin_lock+0x10a/0x1d0 + worker_thread+0x7a/0x5c0 + ? process_one_work+0xa00/0xa00 + kthread+0x1d5/0x200 + ? kthread_create_worker_on_cpu+0xd0/0xd0 + ret_from_fork+0x3a/0x50 + +Allocated by task 2682: + save_stack+0x1b/0x80 + __kasan_kmalloc.constprop.0+0xc2/0xd0 + usb_alloc_urb+0x28/0x60 + tm6000_start_feed+0x10a/0x300 [tm6000_dvb] + dmx_ts_feed_start_filtering+0x86/0x120 [dvb_core] + dvb_dmxdev_start_feed+0x121/0x180 [dvb_core] + dvb_dmxdev_filter_start+0xcb/0x540 [dvb_core] + dvb_demux_do_ioctl+0x7ed/0x890 [dvb_core] + dvb_usercopy+0x97/0x1f0 [dvb_core] + dvb_demux_ioctl+0x11/0x20 [dvb_core] + do_vfs_ioctl+0x5d8/0x9d0 + ksys_ioctl+0x5e/0x90 + __x64_sys_ioctl+0x3d/0x50 + do_syscall_64+0x74/0xe0 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + +Freed by task 22: + save_stack+0x1b/0x80 + __kasan_slab_free+0x12c/0x170 + kfree+0xfd/0x3a0 + xhci_giveback_urb_in_irq+0xfe/0x230 + xhci_td_cleanup+0x276/0x340 + xhci_irq+0x1129/0x3720 + __handle_irq_event_percpu+0x6e/0x420 + handle_irq_event_percpu+0x6f/0x100 + handle_irq_event+0x55/0x84 + handle_edge_irq+0x108/0x3b0 + handle_irq+0x2e/0x40 + do_IRQ+0x83/0x1a0 + +Cc: stable@vger.kernel.org +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/usb/tm6000/tm6000-dvb.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/media/usb/tm6000/tm6000-dvb.c ++++ b/drivers/media/usb/tm6000/tm6000-dvb.c +@@ -111,6 +111,7 @@ static void tm6000_urb_received(struct u + printk(KERN_ERR "tm6000: error %s\n", __func__); + kfree(urb->transfer_buffer); + usb_free_urb(urb); ++ dev->dvb->bulk_urb = NULL; + } + } + } +@@ -141,6 +142,7 @@ static int tm6000_start_stream(struct tm + dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); + if (dvb->bulk_urb->transfer_buffer == NULL) { + usb_free_urb(dvb->bulk_urb); ++ dvb->bulk_urb = NULL; + printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n"); + return -ENOMEM; + } +@@ -168,6 +170,7 @@ static int tm6000_start_stream(struct tm + + kfree(dvb->bulk_urb->transfer_buffer); + usb_free_urb(dvb->bulk_urb); ++ dvb->bulk_urb = NULL; + return ret; + } + diff --git a/queue-4.9/series b/queue-4.9/series index 50a42a0eb87..259866edc24 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -32,4 +32,6 @@ crypto-talitos-hmac-snoop-no-afeu-mode-requires-sw-icv-checking.patch drm-mediatek-mtk_drm_drv.c-add-of_node_put-before-goto.patch nvmem-use-the-same-permissions-for-eeprom-as-for-nvmem.patch x86-build-add-wnoaddress-of-packed-member-to-realmode_cflags-to-silence-gcc9-build-warning.patch +usb-usbcore-fix-slab-out-of-bounds-bug-during-device-reset.patch +media-tm6000-double-free-if-usb-disconnect-while-streaming.patch powerpc-mm-radix-use-the-right-page-size-for-vmemmap-mapping.patch diff --git a/queue-4.9/usb-usbcore-fix-slab-out-of-bounds-bug-during-device-reset.patch b/queue-4.9/usb-usbcore-fix-slab-out-of-bounds-bug-during-device-reset.patch new file mode 100644 index 00000000000..2b291988224 --- /dev/null +++ b/queue-4.9/usb-usbcore-fix-slab-out-of-bounds-bug-during-device-reset.patch @@ -0,0 +1,112 @@ +From 3dd550a2d36596a1b0ee7955da3b611c031d3873 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Wed, 4 Sep 2019 11:56:27 -0400 +Subject: USB: usbcore: Fix slab-out-of-bounds bug during device reset + +From: Alan Stern + +commit 3dd550a2d36596a1b0ee7955da3b611c031d3873 upstream. + +The syzbot fuzzer provoked a slab-out-of-bounds error in the USB core: + +BUG: KASAN: slab-out-of-bounds in memcmp+0xa6/0xb0 lib/string.c:904 +Read of size 1 at addr ffff8881d175bed6 by task kworker/0:3/2746 + +CPU: 0 PID: 2746 Comm: kworker/0:3 Not tainted 5.3.0-rc5+ #28 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS +Google 01/01/2011 +Workqueue: usb_hub_wq hub_event +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0xca/0x13e lib/dump_stack.c:113 + print_address_description+0x6a/0x32c mm/kasan/report.c:351 + __kasan_report.cold+0x1a/0x33 mm/kasan/report.c:482 + kasan_report+0xe/0x12 mm/kasan/common.c:612 + memcmp+0xa6/0xb0 lib/string.c:904 + memcmp include/linux/string.h:400 [inline] + descriptors_changed drivers/usb/core/hub.c:5579 [inline] + usb_reset_and_verify_device+0x564/0x1300 drivers/usb/core/hub.c:5729 + usb_reset_device+0x4c1/0x920 drivers/usb/core/hub.c:5898 + rt2x00usb_probe+0x53/0x7af +drivers/net/wireless/ralink/rt2x00/rt2x00usb.c:806 + +The error occurs when the descriptors_changed() routine (called during +a device reset) attempts to compare the old and new BOS and capability +descriptors. The length it uses for the comparison is the +wTotalLength value stored in BOS descriptor, but this value is not +necessarily the same as the length actually allocated for the +descriptors. If it is larger the routine will call memcmp() with a +length that is too big, thus reading beyond the end of the allocated +region and leading to this fault. + +The kernel reads the BOS descriptor twice: first to get the total +length of all the capability descriptors, and second to read it along +with all those other descriptors. A malicious (or very faulty) device +may send different values for the BOS descriptor fields each time. +The memory area will be allocated using the wTotalLength value read +the first time, but stored within it will be the value read the second +time. + +To prevent this possibility from causing any errors, this patch +modifies the BOS descriptor after it has been read the second time: +It sets the wTotalLength field to the actual length of the descriptors +that were read in and validated. Then the memcpy() call, or any other +code using these descriptors, will be able to rely on wTotalLength +being valid. + +Reported-and-tested-by: syzbot+35f4d916c623118d576e@syzkaller.appspotmail.com +Signed-off-by: Alan Stern +CC: +Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1909041154260.1722-100000@iolanthe.rowland.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/config.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -920,7 +920,7 @@ int usb_get_bos_descriptor(struct usb_de + struct usb_bos_descriptor *bos; + struct usb_dev_cap_header *cap; + struct usb_ssp_cap_descriptor *ssp_cap; +- unsigned char *buffer; ++ unsigned char *buffer, *buffer0; + int length, total_len, num, i, ssac; + __u8 cap_type; + int ret; +@@ -965,10 +965,12 @@ int usb_get_bos_descriptor(struct usb_de + ret = -ENOMSG; + goto err; + } ++ ++ buffer0 = buffer; + total_len -= length; ++ buffer += length; + + for (i = 0; i < num; i++) { +- buffer += length; + cap = (struct usb_dev_cap_header *)buffer; + + if (total_len < sizeof(*cap) || total_len < cap->bLength) { +@@ -982,8 +984,6 @@ int usb_get_bos_descriptor(struct usb_de + break; + } + +- total_len -= length; +- + if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { + dev_warn(ddev, "descriptor type invalid, skip\n"); + continue; +@@ -1018,7 +1018,11 @@ int usb_get_bos_descriptor(struct usb_de + default: + break; + } ++ ++ total_len -= length; ++ buffer += length; + } ++ dev->bos->desc->wTotalLength = cpu_to_le16(buffer - buffer0); + + return 0; +