From: Greg Kroah-Hartman Date: Sun, 27 Oct 2019 07:59:15 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v4.4.198~37 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fcccc5b90850552b0abc117f0dc7e9885a8eddb9;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: usb-ldusb-fix-memleak-on-disconnect.patch usb-ldusb-fix-read-info-leaks.patch usb-legousbtower-fix-memleak-on-disconnect.patch usb-serial-ti_usb_3410_5052-fix-port-close-races.patch usb-udc-lpc32xx-fix-bad-bit-shift-operation.patch usb-usblp-fix-use-after-free-on-disconnect.patch --- diff --git a/queue-4.4/series b/queue-4.4/series index 1d83e345d10..1aaa38091ef 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -16,3 +16,9 @@ sctp-change-sctp_prot-.no_autobind-with-true.patch net-avoid-potential-infinite-loop-in-tc_ctl_action.patch ipv4-return-enetunreach-if-we-can-t-create-route-but-saddr-is-valid.patch memfd-fix-locking-when-tagging-pins.patch +usb-legousbtower-fix-memleak-on-disconnect.patch +usb-udc-lpc32xx-fix-bad-bit-shift-operation.patch +usb-serial-ti_usb_3410_5052-fix-port-close-races.patch +usb-ldusb-fix-memleak-on-disconnect.patch +usb-usblp-fix-use-after-free-on-disconnect.patch +usb-ldusb-fix-read-info-leaks.patch diff --git a/queue-4.4/usb-ldusb-fix-memleak-on-disconnect.patch b/queue-4.4/usb-ldusb-fix-memleak-on-disconnect.patch new file mode 100644 index 00000000000..90471431182 --- /dev/null +++ b/queue-4.4/usb-ldusb-fix-memleak-on-disconnect.patch @@ -0,0 +1,37 @@ +From b14a39048c1156cfee76228bf449852da2f14df8 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 10 Oct 2019 14:58:34 +0200 +Subject: USB: ldusb: fix memleak on disconnect + +From: Johan Hovold + +commit b14a39048c1156cfee76228bf449852da2f14df8 upstream. + +If disconnect() races with release() after a process has been +interrupted, release() could end up returning early and the driver would +fail to free its driver data. + +Fixes: 2824bd250f0b ("[PATCH] USB: add ldusb driver") +Cc: stable # 2.6.13 +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20191010125835.27031-2-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/misc/ldusb.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/usb/misc/ldusb.c ++++ b/drivers/usb/misc/ldusb.c +@@ -384,10 +384,7 @@ static int ld_usb_release(struct inode * + goto exit; + } + +- if (mutex_lock_interruptible(&dev->mutex)) { +- retval = -ERESTARTSYS; +- goto exit; +- } ++ mutex_lock(&dev->mutex); + + if (dev->open_count != 1) { + retval = -ENODEV; diff --git a/queue-4.4/usb-ldusb-fix-read-info-leaks.patch b/queue-4.4/usb-ldusb-fix-read-info-leaks.patch new file mode 100644 index 00000000000..fd307669c40 --- /dev/null +++ b/queue-4.4/usb-ldusb-fix-read-info-leaks.patch @@ -0,0 +1,75 @@ +From 7a6f22d7479b7a0b68eadd308a997dd64dda7dae Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 18 Oct 2019 17:19:54 +0200 +Subject: USB: ldusb: fix read info leaks + +From: Johan Hovold + +commit 7a6f22d7479b7a0b68eadd308a997dd64dda7dae upstream. + +Fix broken read implementation, which could be used to trigger slab info +leaks. + +The driver failed to check if the custom ring buffer was still empty +when waking up after having waited for more data. This would happen on +every interrupt-in completion, even if no data had been added to the +ring buffer (e.g. on disconnect events). + +Due to missing sanity checks and uninitialised (kmalloced) ring-buffer +entries, this meant that huge slab info leaks could easily be triggered. + +Note that the empty-buffer check after wakeup is enough to fix the info +leak on disconnect, but let's clear the buffer on allocation and add a +sanity check to read() to prevent further leaks. + +Fixes: 2824bd250f0b ("[PATCH] USB: add ldusb driver") +Cc: stable # 2.6.13 +Reported-by: syzbot+6fe95b826644f7f12b0b@syzkaller.appspotmail.com +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20191018151955.25135-2-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/misc/ldusb.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/usb/misc/ldusb.c ++++ b/drivers/usb/misc/ldusb.c +@@ -468,7 +468,7 @@ static ssize_t ld_usb_read(struct file * + + /* wait for data */ + spin_lock_irq(&dev->rbsl); +- if (dev->ring_head == dev->ring_tail) { ++ while (dev->ring_head == dev->ring_tail) { + dev->interrupt_in_done = 0; + spin_unlock_irq(&dev->rbsl); + if (file->f_flags & O_NONBLOCK) { +@@ -479,11 +479,16 @@ static ssize_t ld_usb_read(struct file * + if (retval < 0) + goto unlock_exit; + } else { +- spin_unlock_irq(&dev->rbsl); ++ spin_lock_irq(&dev->rbsl); + } ++ spin_unlock_irq(&dev->rbsl); + + /* actual_buffer contains actual_length + interrupt_in_buffer */ + actual_buffer = (size_t*)(dev->ring_buffer + dev->ring_tail*(sizeof(size_t)+dev->interrupt_in_endpoint_size)); ++ if (*actual_buffer > dev->interrupt_in_endpoint_size) { ++ retval = -EIO; ++ goto unlock_exit; ++ } + bytes_to_read = min(count, *actual_buffer); + if (bytes_to_read < *actual_buffer) + dev_warn(&dev->intf->dev, "Read buffer overflow, %zd bytes dropped\n", +@@ -703,7 +708,9 @@ static int ld_usb_probe(struct usb_inter + dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); + + dev->interrupt_in_endpoint_size = usb_endpoint_maxp(dev->interrupt_in_endpoint); +- dev->ring_buffer = kmalloc(ring_buffer_size*(sizeof(size_t)+dev->interrupt_in_endpoint_size), GFP_KERNEL); ++ dev->ring_buffer = kcalloc(ring_buffer_size, ++ sizeof(size_t) + dev->interrupt_in_endpoint_size, ++ GFP_KERNEL); + if (!dev->ring_buffer) { + dev_err(&intf->dev, "Couldn't allocate ring_buffer\n"); + goto error; diff --git a/queue-4.4/usb-legousbtower-fix-memleak-on-disconnect.patch b/queue-4.4/usb-legousbtower-fix-memleak-on-disconnect.patch new file mode 100644 index 00000000000..13a7482a05b --- /dev/null +++ b/queue-4.4/usb-legousbtower-fix-memleak-on-disconnect.patch @@ -0,0 +1,37 @@ +From b6c03e5f7b463efcafd1ce141bd5a8fc4e583ae2 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 10 Oct 2019 14:58:35 +0200 +Subject: USB: legousbtower: fix memleak on disconnect + +From: Johan Hovold + +commit b6c03e5f7b463efcafd1ce141bd5a8fc4e583ae2 upstream. + +If disconnect() races with release() after a process has been +interrupted, release() could end up returning early and the driver would +fail to free its driver data. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20191010125835.27031-3-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/misc/legousbtower.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/usb/misc/legousbtower.c ++++ b/drivers/usb/misc/legousbtower.c +@@ -425,10 +425,7 @@ static int tower_release (struct inode * + goto exit; + } + +- if (mutex_lock_interruptible(&dev->lock)) { +- retval = -ERESTARTSYS; +- goto exit; +- } ++ mutex_lock(&dev->lock); + + if (dev->open_count != 1) { + dev_dbg(&dev->udev->dev, "%s: device not opened exactly once\n", diff --git a/queue-4.4/usb-serial-ti_usb_3410_5052-fix-port-close-races.patch b/queue-4.4/usb-serial-ti_usb_3410_5052-fix-port-close-races.patch new file mode 100644 index 00000000000..5cc1567c17f --- /dev/null +++ b/queue-4.4/usb-serial-ti_usb_3410_5052-fix-port-close-races.patch @@ -0,0 +1,53 @@ +From 6f1d1dc8d540a9aa6e39b9cb86d3a67bbc1c8d8d Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 11 Oct 2019 11:57:35 +0200 +Subject: USB: serial: ti_usb_3410_5052: fix port-close races + +From: Johan Hovold + +commit 6f1d1dc8d540a9aa6e39b9cb86d3a67bbc1c8d8d upstream. + +Fix races between closing a port and opening or closing another port on +the same device which could lead to a failure to start or stop the +shared interrupt URB. The latter could potentially cause a +use-after-free or worse in the completion handler on driver unbind. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/ti_usb_3410_5052.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +--- a/drivers/usb/serial/ti_usb_3410_5052.c ++++ b/drivers/usb/serial/ti_usb_3410_5052.c +@@ -542,7 +542,6 @@ static void ti_close(struct usb_serial_p + struct ti_port *tport; + int port_number; + int status; +- int do_unlock; + unsigned long flags; + + tdev = usb_get_serial_data(port->serial); +@@ -569,16 +568,13 @@ static void ti_close(struct usb_serial_p + "%s - cannot send close port command, %d\n" + , __func__, status); + +- /* if mutex_lock is interrupted, continue anyway */ +- do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock); ++ mutex_lock(&tdev->td_open_close_lock); + --tport->tp_tdev->td_open_port_count; +- if (tport->tp_tdev->td_open_port_count <= 0) { ++ if (tport->tp_tdev->td_open_port_count == 0) { + /* last port is closed, shut down interrupt urb */ + usb_kill_urb(port->serial->port[0]->interrupt_in_urb); +- tport->tp_tdev->td_open_port_count = 0; + } +- if (do_unlock) +- mutex_unlock(&tdev->td_open_close_lock); ++ mutex_unlock(&tdev->td_open_close_lock); + } + + diff --git a/queue-4.4/usb-udc-lpc32xx-fix-bad-bit-shift-operation.patch b/queue-4.4/usb-udc-lpc32xx-fix-bad-bit-shift-operation.patch new file mode 100644 index 00000000000..24b3d951bb3 --- /dev/null +++ b/queue-4.4/usb-udc-lpc32xx-fix-bad-bit-shift-operation.patch @@ -0,0 +1,48 @@ +From b987b66ac3a2bc2f7b03a0ba48a07dc553100c07 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Mon, 14 Oct 2019 14:18:30 -0500 +Subject: usb: udc: lpc32xx: fix bad bit shift operation + +From: Gustavo A. R. Silva + +commit b987b66ac3a2bc2f7b03a0ba48a07dc553100c07 upstream. + +It seems that the right variable to use in this case is *i*, instead of +*n*, otherwise there is an undefined behavior when right shifiting by more +than 31 bits when multiplying n by 8; notice that *n* can take values +equal or greater than 4 (4, 8, 16, ...). + +Also, notice that under the current conditions (bl = 3), we are skiping +the handling of bytes 3, 7, 31... So, fix this by updating this logic +and limit *bl* up to 4 instead of up to 3. + +This fix is based on function udc_stuff_fifo(). + +Addresses-Coverity-ID: 1454834 ("Bad bit shift operation") +Fixes: 24a28e428351 ("USB: gadget driver for LPC32xx") +Cc: stable@vger.kernel.org +Signed-off-by: Gustavo A. R. Silva +Link: https://lore.kernel.org/r/20191014191830.GA10721@embeddedor +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/udc/lpc32xx_udc.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/usb/gadget/udc/lpc32xx_udc.c ++++ b/drivers/usb/gadget/udc/lpc32xx_udc.c +@@ -1225,11 +1225,11 @@ static void udc_pop_fifo(struct lpc32xx_ + tmp = readl(USBD_RXDATA(udc->udp_baseaddr)); + + bl = bytes - n; +- if (bl > 3) +- bl = 3; ++ if (bl > 4) ++ bl = 4; + + for (i = 0; i < bl; i++) +- data[n + i] = (u8) ((tmp >> (n * 8)) & 0xFF); ++ data[n + i] = (u8) ((tmp >> (i * 8)) & 0xFF); + } + break; + diff --git a/queue-4.4/usb-usblp-fix-use-after-free-on-disconnect.patch b/queue-4.4/usb-usblp-fix-use-after-free-on-disconnect.patch new file mode 100644 index 00000000000..529f3ae4c5f --- /dev/null +++ b/queue-4.4/usb-usblp-fix-use-after-free-on-disconnect.patch @@ -0,0 +1,51 @@ +From 7a759197974894213621aa65f0571b51904733d6 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 15 Oct 2019 19:55:22 +0200 +Subject: USB: usblp: fix use-after-free on disconnect + +From: Johan Hovold + +commit 7a759197974894213621aa65f0571b51904733d6 upstream. + +A recent commit addressing a runtime PM use-count regression, introduced +a use-after-free by not making sure we held a reference to the struct +usb_interface for the lifetime of the driver data. + +Fixes: 9a31535859bf ("USB: usblp: fix runtime PM after driver unbind") +Cc: stable +Reported-by: syzbot+cd24df4d075c319ebfc5@syzkaller.appspotmail.com +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20191015175522.18490-1-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/class/usblp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/class/usblp.c ++++ b/drivers/usb/class/usblp.c +@@ -458,6 +458,7 @@ static void usblp_cleanup(struct usblp * + kfree(usblp->readbuf); + kfree(usblp->device_id_string); + kfree(usblp->statusbuf); ++ usb_put_intf(usblp->intf); + kfree(usblp); + } + +@@ -1120,7 +1121,7 @@ static int usblp_probe(struct usb_interf + init_waitqueue_head(&usblp->wwait); + init_usb_anchor(&usblp->urbs); + usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; +- usblp->intf = intf; ++ usblp->intf = usb_get_intf(intf); + + /* Malloc device ID string buffer to the largest expected length, + * since we can re-query it on an ioctl and a dynamic string +@@ -1209,6 +1210,7 @@ abort: + kfree(usblp->readbuf); + kfree(usblp->statusbuf); + kfree(usblp->device_id_string); ++ usb_put_intf(usblp->intf); + kfree(usblp); + abort_ret: + return retval;