From: Greg Kroah-Hartman Date: Mon, 9 Jan 2017 10:32:16 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.4.42~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=87291c4c5355ab369cab815c7dfb04ca4cf7da48;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: usb-host-xhci-fix-possible-wild-pointer-when-handling-abort-command.patch usb-return-error-code-when-platform_get_irq-fails.patch usb-serial-cyberjack-fix-null-deref-at-open.patch usb-serial-garmin_gps-fix-memory-leak-on-failed-urb-submit.patch usb-serial-io_edgeport-fix-null-deref-at-open.patch usb-serial-io_ti-fix-another-null-deref-at-open.patch usb-serial-io_ti-fix-i-o-after-disconnect.patch usb-serial-io_ti-fix-null-deref-at-open.patch usb-serial-iuu_phoenix-fix-null-deref-at-open.patch usb-serial-keyspan_pda-verify-endpoints-at-probe.patch usb-serial-kobil_sct-fix-null-deref-in-write.patch usb-serial-mos7720-fix-null-deref-at-open.patch usb-serial-mos7720-fix-parallel-probe.patch usb-serial-mos7720-fix-parport-use-after-free-on-probe-errors.patch usb-serial-mos7720-fix-use-after-free-on-probe-errors.patch usb-serial-mos7840-fix-null-deref-at-open.patch usb-serial-omninet-fix-null-derefs-at-open-and-disconnect.patch usb-serial-oti6858-fix-null-deref-at-open.patch usb-serial-pl2303-fix-null-deref-at-open.patch usb-serial-quatech2-fix-sleep-while-atomic-in-close.patch usb-serial-spcp8x5-fix-null-deref-at-open.patch usb-serial-ti_usb_3410_5052-fix-null-deref-at-open.patch usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-apollo-lake.patch usb-xhci-fix-return-value-of-xhci_setup_device.patch usb-xhci-hold-lock-over-xhci_abort_cmd_ring.patch usb-xhci-mem-use-passed-in-gfp-flags-instead-of-gfp_kernel.patch xhci-free-xhci-virtual-devices-with-leaf-nodes-first.patch xhci-handle-command-completion-and-timeout-race.patch --- diff --git a/queue-4.9/series b/queue-4.9/series index ddc8b5e1702..39d80a3a75c 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -33,3 +33,31 @@ usb-dummy-hcd-fix-bug-in-stop_activity-handle-ep0.patch usb-gadget-composite-test-get_alt-presence-instead-of-set_alt.patch usb-dwc3-core-avoid-overflow-events.patch usb-xhci-fix-possible-wild-pointer.patch +usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-apollo-lake.patch +xhci-free-xhci-virtual-devices-with-leaf-nodes-first.patch +usb-xhci-fix-return-value-of-xhci_setup_device.patch +usb-host-xhci-fix-possible-wild-pointer-when-handling-abort-command.patch +xhci-handle-command-completion-and-timeout-race.patch +usb-xhci-hold-lock-over-xhci_abort_cmd_ring.patch +usb-return-error-code-when-platform_get_irq-fails.patch +usb-serial-omninet-fix-null-derefs-at-open-and-disconnect.patch +usb-serial-quatech2-fix-sleep-while-atomic-in-close.patch +usb-serial-pl2303-fix-null-deref-at-open.patch +usb-serial-keyspan_pda-verify-endpoints-at-probe.patch +usb-serial-spcp8x5-fix-null-deref-at-open.patch +usb-serial-io_ti-fix-null-deref-at-open.patch +usb-serial-io_ti-fix-another-null-deref-at-open.patch +usb-serial-io_ti-fix-i-o-after-disconnect.patch +usb-serial-iuu_phoenix-fix-null-deref-at-open.patch +usb-serial-garmin_gps-fix-memory-leak-on-failed-urb-submit.patch +usb-serial-ti_usb_3410_5052-fix-null-deref-at-open.patch +usb-serial-io_edgeport-fix-null-deref-at-open.patch +usb-serial-oti6858-fix-null-deref-at-open.patch +usb-serial-cyberjack-fix-null-deref-at-open.patch +usb-serial-kobil_sct-fix-null-deref-in-write.patch +usb-serial-mos7840-fix-null-deref-at-open.patch +usb-serial-mos7720-fix-null-deref-at-open.patch +usb-serial-mos7720-fix-use-after-free-on-probe-errors.patch +usb-serial-mos7720-fix-parport-use-after-free-on-probe-errors.patch +usb-serial-mos7720-fix-parallel-probe.patch +usb-xhci-mem-use-passed-in-gfp-flags-instead-of-gfp_kernel.patch diff --git a/queue-4.9/usb-host-xhci-fix-possible-wild-pointer-when-handling-abort-command.patch b/queue-4.9/usb-host-xhci-fix-possible-wild-pointer-when-handling-abort-command.patch new file mode 100644 index 00000000000..ceed98172df --- /dev/null +++ b/queue-4.9/usb-host-xhci-fix-possible-wild-pointer-when-handling-abort-command.patch @@ -0,0 +1,36 @@ +From 2a7cfdf37b7c08ac29df4c62ea5ccb01474b6597 Mon Sep 17 00:00:00 2001 +From: Baolin Wang +Date: Tue, 3 Jan 2017 18:28:47 +0200 +Subject: usb: host: xhci: Fix possible wild pointer when handling abort command + +From: Baolin Wang + +commit 2a7cfdf37b7c08ac29df4c62ea5ccb01474b6597 upstream. + +When current command was supposed to be aborted, host will free the command +in handle_cmd_completion() function. But it might be still referenced by +xhci->current_cmd, which need to set NULL. + +Signed-off-by: Baolin Wang +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-ring.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1368,8 +1368,11 @@ static void handle_cmd_completion(struct + */ + if (cmd_comp_code == COMP_CMD_ABORT) { + xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; +- if (cmd->status == COMP_CMD_ABORT) ++ if (cmd->status == COMP_CMD_ABORT) { ++ if (xhci->current_cmd == cmd) ++ xhci->current_cmd = NULL; + goto event_handled; ++ } + } + + cmd_type = TRB_FIELD_TO_TYPE(le32_to_cpu(cmd_trb->generic.field[3])); diff --git a/queue-4.9/usb-return-error-code-when-platform_get_irq-fails.patch b/queue-4.9/usb-return-error-code-when-platform_get_irq-fails.patch new file mode 100644 index 00000000000..7a18db133dc --- /dev/null +++ b/queue-4.9/usb-return-error-code-when-platform_get_irq-fails.patch @@ -0,0 +1,40 @@ +From 28bedb5ae463b9f7e5195cbc93f1795e374bdef8 Mon Sep 17 00:00:00 2001 +From: Pan Bian +Date: Tue, 3 Jan 2017 18:28:45 +0200 +Subject: usb: return error code when platform_get_irq fails + +From: Pan Bian + +commit 28bedb5ae463b9f7e5195cbc93f1795e374bdef8 upstream. + +In function xhci_mtk_probe(), variable ret takes the return value. Its +value should be negative on failures. However, when the call to function +platform_get_irq() fails, it does not set the error code, and 0 will be +returned. 0 indicates no error. As a result, the callers of function +xhci_mtk_probe() will not be able to detect the error. This patch fixes +the bug by assigning the return value of platform_get_irq() to variable +ret if it fails. + +Signed-off-by: Pan Bian +Reviewed-by: Matthias Brugger +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-mtk.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -560,8 +560,10 @@ static int xhci_mtk_probe(struct platfor + goto disable_ldos; + + irq = platform_get_irq(pdev, 0); +- if (irq < 0) ++ if (irq < 0) { ++ ret = irq; + goto disable_clk; ++ } + + /* Initialize dma_mask and coherent_dma_mask to 32-bits */ + ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); diff --git a/queue-4.9/usb-serial-cyberjack-fix-null-deref-at-open.patch b/queue-4.9/usb-serial-cyberjack-fix-null-deref-at-open.patch new file mode 100644 index 00000000000..a7f9b88d4bb --- /dev/null +++ b/queue-4.9/usb-serial-cyberjack-fix-null-deref-at-open.patch @@ -0,0 +1,57 @@ +From 3dca01114dcecb1cf324534cd8d75fd1306a516b Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:40 +0100 +Subject: USB: serial: cyberjack: fix NULL-deref at open + +From: Johan Hovold + +commit 3dca01114dcecb1cf324534cd8d75fd1306a516b upstream. + +Fix NULL-pointer dereference when clearing halt at open should the device +lack a bulk-out endpoint. + +Unable to handle kernel NULL pointer dereference at virtual address 00000030 +... +PC is at cyberjack_open+0x40/0x9c [cyberjack] + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/cyberjack.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/usb/serial/cyberjack.c ++++ b/drivers/usb/serial/cyberjack.c +@@ -50,6 +50,7 @@ + #define CYBERJACK_PRODUCT_ID 0x0100 + + /* Function prototypes */ ++static int cyberjack_attach(struct usb_serial *serial); + static int cyberjack_port_probe(struct usb_serial_port *port); + static int cyberjack_port_remove(struct usb_serial_port *port); + static int cyberjack_open(struct tty_struct *tty, +@@ -77,6 +78,7 @@ static struct usb_serial_driver cyberjac + .description = "Reiner SCT Cyberjack USB card reader", + .id_table = id_table, + .num_ports = 1, ++ .attach = cyberjack_attach, + .port_probe = cyberjack_port_probe, + .port_remove = cyberjack_port_remove, + .open = cyberjack_open, +@@ -100,6 +102,14 @@ struct cyberjack_private { + short wrsent; /* Data already sent */ + }; + ++static int cyberjack_attach(struct usb_serial *serial) ++{ ++ if (serial->num_bulk_out < serial->num_ports) ++ return -ENODEV; ++ ++ return 0; ++} ++ + static int cyberjack_port_probe(struct usb_serial_port *port) + { + struct cyberjack_private *priv; diff --git a/queue-4.9/usb-serial-garmin_gps-fix-memory-leak-on-failed-urb-submit.patch b/queue-4.9/usb-serial-garmin_gps-fix-memory-leak-on-failed-urb-submit.patch new file mode 100644 index 00000000000..3948f719b11 --- /dev/null +++ b/queue-4.9/usb-serial-garmin_gps-fix-memory-leak-on-failed-urb-submit.patch @@ -0,0 +1,30 @@ +From c4ac4496e835b78a45dfbf74f6173932217e4116 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:41 +0100 +Subject: USB: serial: garmin_gps: fix memory leak on failed URB submit + +From: Johan Hovold + +commit c4ac4496e835b78a45dfbf74f6173932217e4116 upstream. + +Make sure to free the URB transfer buffer in case submission fails (e.g. +due to a disconnect). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/garmin_gps.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/serial/garmin_gps.c ++++ b/drivers/usb/serial/garmin_gps.c +@@ -1043,6 +1043,7 @@ static int garmin_write_bulk(struct usb_ + "%s - usb_submit_urb(write bulk) failed with status = %d\n", + __func__, status); + count = status; ++ kfree(buffer); + } + + /* we are done with this urb, so let the host driver diff --git a/queue-4.9/usb-serial-io_edgeport-fix-null-deref-at-open.patch b/queue-4.9/usb-serial-io_edgeport-fix-null-deref-at-open.patch new file mode 100644 index 00000000000..ee74a781913 --- /dev/null +++ b/queue-4.9/usb-serial-io_edgeport-fix-null-deref-at-open.patch @@ -0,0 +1,41 @@ +From 0dd408425eb21ddf26a692b3c8044c9e7d1a7948 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:42 +0100 +Subject: USB: serial: io_edgeport: fix NULL-deref at open + +From: Johan Hovold + +commit 0dd408425eb21ddf26a692b3c8044c9e7d1a7948 upstream. + +Fix NULL-pointer dereference when initialising URBs at open should a +non-EPIC device lack a bulk-in or interrupt-in endpoint. + +Unable to handle kernel NULL pointer dereference at virtual address 00000028 +... +PC is at edge_open+0x24c/0x3e8 [io_edgeport] + +Note that the EPIC-device probe path has the required sanity checks so +this makes those checks partially redundant. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/io_edgeport.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/usb/serial/io_edgeport.c ++++ b/drivers/usb/serial/io_edgeport.c +@@ -2754,6 +2754,11 @@ static int edge_startup(struct usb_seria + EDGE_COMPATIBILITY_MASK1, + EDGE_COMPATIBILITY_MASK2 }; + ++ if (serial->num_bulk_in < 1 || serial->num_interrupt_in < 1) { ++ dev_err(&serial->interface->dev, "missing endpoints\n"); ++ return -ENODEV; ++ } ++ + dev = serial->dev; + + /* create our private serial structure */ diff --git a/queue-4.9/usb-serial-io_ti-fix-another-null-deref-at-open.patch b/queue-4.9/usb-serial-io_ti-fix-another-null-deref-at-open.patch new file mode 100644 index 00000000000..c3fe48d5bc5 --- /dev/null +++ b/queue-4.9/usb-serial-io_ti-fix-another-null-deref-at-open.patch @@ -0,0 +1,68 @@ +From 4f9785cc99feeb3673993b471f646b4dbaec2cc1 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:44 +0100 +Subject: USB: serial: io_ti: fix another NULL-deref at open + +From: Johan Hovold + +commit 4f9785cc99feeb3673993b471f646b4dbaec2cc1 upstream. + +In case a device is left in "boot-mode" we must not register any port +devices in order to avoid a NULL-pointer dereference on open due to +missing endpoints. This could be used by a malicious device to trigger +an OOPS: + +Unable to handle kernel NULL pointer dereference at virtual address 00000030 +... +[] (edge_open [io_ti]) from [] (serial_port_activate+0x68/0x98 [usbserial]) +[] (serial_port_activate [usbserial]) from [] (tty_port_open+0x9c/0xe8) +[] (tty_port_open) from [] (serial_open+0x48/0x6c [usbserial]) +[] (serial_open [usbserial]) from [] (tty_open+0xcc/0x5cc) + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/io_ti.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/usb/serial/io_ti.c ++++ b/drivers/usb/serial/io_ti.c +@@ -1508,7 +1508,7 @@ stayinbootmode: + dev_dbg(dev, "%s - STAYING IN BOOT MODE\n", __func__); + serial->product_info.TiMode = TI_MODE_BOOT; + +- return 0; ++ return 1; + } + + static int ti_do_config(struct edgeport_port *port, int feature, int on) +@@ -2563,14 +2563,18 @@ static int edge_startup(struct usb_seria + + mutex_init(&edge_serial->es_lock); + edge_serial->serial = serial; ++ INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work); + usb_set_serial_data(serial, edge_serial); + + status = download_fw(edge_serial); +- if (status) { ++ if (status < 0) { + kfree(edge_serial); + return status; + } + ++ if (status > 0) ++ return 1; /* bind but do not register any ports */ ++ + product_id = le16_to_cpu( + edge_serial->serial->dev->descriptor.idProduct); + +@@ -2582,7 +2586,6 @@ static int edge_startup(struct usb_seria + } + } + +- INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work); + edge_heartbeat_schedule(edge_serial); + + return 0; diff --git a/queue-4.9/usb-serial-io_ti-fix-i-o-after-disconnect.patch b/queue-4.9/usb-serial-io_ti-fix-i-o-after-disconnect.patch new file mode 100644 index 00000000000..2b5ed4c4690 --- /dev/null +++ b/queue-4.9/usb-serial-io_ti-fix-i-o-after-disconnect.patch @@ -0,0 +1,35 @@ +From 2330d0a853da260d8a9834a70df448032b9ff623 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:45 +0100 +Subject: USB: serial: io_ti: fix I/O after disconnect + +From: Johan Hovold + +commit 2330d0a853da260d8a9834a70df448032b9ff623 upstream. + +Cancel the heartbeat work on driver unbind in order to avoid I/O after +disconnect in case the port is held open. + +Note that the cancel in release() is still needed to stop the heartbeat +after late probe errors. + +Fixes: 26c78daade0f ("USB: io_ti: Add heartbeat to keep idle EP/416 ports from disconnecting") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/io_ti.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/serial/io_ti.c ++++ b/drivers/usb/serial/io_ti.c +@@ -2593,6 +2593,9 @@ static int edge_startup(struct usb_seria + + static void edge_disconnect(struct usb_serial *serial) + { ++ struct edgeport_serial *edge_serial = usb_get_serial_data(serial); ++ ++ cancel_delayed_work_sync(&edge_serial->heartbeat_work); + } + + static void edge_release(struct usb_serial *serial) diff --git a/queue-4.9/usb-serial-io_ti-fix-null-deref-at-open.patch b/queue-4.9/usb-serial-io_ti-fix-null-deref-at-open.patch new file mode 100644 index 00000000000..21c2021834a --- /dev/null +++ b/queue-4.9/usb-serial-io_ti-fix-null-deref-at-open.patch @@ -0,0 +1,43 @@ +From a323fefc6f5079844dc62ffeb54f491d0242ca35 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:43 +0100 +Subject: USB: serial: io_ti: fix NULL-deref at open + +From: Johan Hovold + +commit a323fefc6f5079844dc62ffeb54f491d0242ca35 upstream. + +Fix NULL-pointer dereference when clearing halt at open should a +malicious device lack the expected endpoints when in download mode. + +Unable to handle kernel NULL pointer dereference at virtual address 00000030 +... +[] (edge_open [io_ti]) from [] (serial_port_activate+0x68/0x98 [usbserial]) +[] (serial_port_activate [usbserial]) from [] (tty_port_open+0x9c/0xe8) +[] (tty_port_open) from [] (serial_open+0x48/0x6c [usbserial]) +[] (serial_open [usbserial]) from [] (tty_open+0xcc/0x5cc) + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/io_ti.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/usb/serial/io_ti.c ++++ b/drivers/usb/serial/io_ti.c +@@ -2549,6 +2549,13 @@ static int edge_startup(struct usb_seria + int status; + u16 product_id; + ++ /* Make sure we have the required endpoints when in download mode. */ ++ if (serial->interface->cur_altsetting->desc.bNumEndpoints > 1) { ++ if (serial->num_bulk_in < serial->num_ports || ++ serial->num_bulk_out < serial->num_ports) ++ return -ENODEV; ++ } ++ + /* create our private serial structure */ + edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); + if (!edge_serial) diff --git a/queue-4.9/usb-serial-iuu_phoenix-fix-null-deref-at-open.patch b/queue-4.9/usb-serial-iuu_phoenix-fix-null-deref-at-open.patch new file mode 100644 index 00000000000..e1514774267 --- /dev/null +++ b/queue-4.9/usb-serial-iuu_phoenix-fix-null-deref-at-open.patch @@ -0,0 +1,52 @@ +From 90507d54f712d81b74815ef3a4bbb555cd9fab2f Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:47 +0100 +Subject: USB: serial: iuu_phoenix: fix NULL-deref at open + +From: Johan Hovold + +commit 90507d54f712d81b74815ef3a4bbb555cd9fab2f upstream. + +Fix NULL-pointer dereference at open should the device lack a bulk-in or +bulk-out endpoint: + +Unable to handle kernel NULL pointer dereference at virtual address 00000030 +... +PC is at iuu_open+0x78/0x59c [iuu_phoenix] + +Fixes: 07c3b1a10016 ("USB: remove broken usb-serial num_endpoints +check") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/iuu_phoenix.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/usb/serial/iuu_phoenix.c ++++ b/drivers/usb/serial/iuu_phoenix.c +@@ -68,6 +68,16 @@ struct iuu_private { + u32 clk; + }; + ++static int iuu_attach(struct usb_serial *serial) ++{ ++ unsigned char num_ports = serial->num_ports; ++ ++ if (serial->num_bulk_in < num_ports || serial->num_bulk_out < num_ports) ++ return -ENODEV; ++ ++ return 0; ++} ++ + static int iuu_port_probe(struct usb_serial_port *port) + { + struct iuu_private *priv; +@@ -1196,6 +1206,7 @@ static struct usb_serial_driver iuu_devi + .tiocmset = iuu_tiocmset, + .set_termios = iuu_set_termios, + .init_termios = iuu_init_termios, ++ .attach = iuu_attach, + .port_probe = iuu_port_probe, + .port_remove = iuu_port_remove, + }; diff --git a/queue-4.9/usb-serial-keyspan_pda-verify-endpoints-at-probe.patch b/queue-4.9/usb-serial-keyspan_pda-verify-endpoints-at-probe.patch new file mode 100644 index 00000000000..b4037c56c2c --- /dev/null +++ b/queue-4.9/usb-serial-keyspan_pda-verify-endpoints-at-probe.patch @@ -0,0 +1,55 @@ +From 5d9b0f859babe96175cd33d7162a9463a875ffde Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:48 +0100 +Subject: USB: serial: keyspan_pda: verify endpoints at probe + +From: Johan Hovold + +commit 5d9b0f859babe96175cd33d7162a9463a875ffde upstream. + +Check for the expected endpoints in attach() and fail loudly if not +present. + +Note that failing to do this appears to be benign since da280e348866 +("USB: keyspan_pda: clean up write-urb busy handling") which prevents a +NULL-pointer dereference in write() by never marking a non-existent +write-urb as free. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/keyspan_pda.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/usb/serial/keyspan_pda.c ++++ b/drivers/usb/serial/keyspan_pda.c +@@ -699,6 +699,19 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda + MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); + #endif + ++static int keyspan_pda_attach(struct usb_serial *serial) ++{ ++ unsigned char num_ports = serial->num_ports; ++ ++ if (serial->num_bulk_out < num_ports || ++ serial->num_interrupt_in < num_ports) { ++ dev_err(&serial->interface->dev, "missing endpoints\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ + static int keyspan_pda_port_probe(struct usb_serial_port *port) + { + +@@ -776,6 +789,7 @@ static struct usb_serial_driver keyspan_ + .break_ctl = keyspan_pda_break_ctl, + .tiocmget = keyspan_pda_tiocmget, + .tiocmset = keyspan_pda_tiocmset, ++ .attach = keyspan_pda_attach, + .port_probe = keyspan_pda_port_probe, + .port_remove = keyspan_pda_port_remove, + }; diff --git a/queue-4.9/usb-serial-kobil_sct-fix-null-deref-in-write.patch b/queue-4.9/usb-serial-kobil_sct-fix-null-deref-in-write.patch new file mode 100644 index 00000000000..c3408660803 --- /dev/null +++ b/queue-4.9/usb-serial-kobil_sct-fix-null-deref-in-write.patch @@ -0,0 +1,59 @@ +From 21ce57840243c7b70fbc1ebd3dceeb70bb6e9e09 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:49 +0100 +Subject: USB: serial: kobil_sct: fix NULL-deref in write + +From: Johan Hovold + +commit 21ce57840243c7b70fbc1ebd3dceeb70bb6e9e09 upstream. + +Fix NULL-pointer dereference in write() should the device lack the +expected interrupt-out endpoint: + +Unable to handle kernel NULL pointer dereference at virtual address 00000054 +... +PC is at kobil_write+0x144/0x2a0 [kobil_sct] + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/kobil_sct.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/usb/serial/kobil_sct.c ++++ b/drivers/usb/serial/kobil_sct.c +@@ -51,6 +51,7 @@ + + + /* Function prototypes */ ++static int kobil_attach(struct usb_serial *serial); + static int kobil_port_probe(struct usb_serial_port *probe); + static int kobil_port_remove(struct usb_serial_port *probe); + static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); +@@ -86,6 +87,7 @@ static struct usb_serial_driver kobil_de + .description = "KOBIL USB smart card terminal", + .id_table = id_table, + .num_ports = 1, ++ .attach = kobil_attach, + .port_probe = kobil_port_probe, + .port_remove = kobil_port_remove, + .ioctl = kobil_ioctl, +@@ -113,6 +115,16 @@ struct kobil_private { + }; + + ++static int kobil_attach(struct usb_serial *serial) ++{ ++ if (serial->num_interrupt_out < serial->num_ports) { ++ dev_err(&serial->interface->dev, "missing interrupt-out endpoint\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ + static int kobil_port_probe(struct usb_serial_port *port) + { + struct usb_serial *serial = port->serial; diff --git a/queue-4.9/usb-serial-mos7720-fix-null-deref-at-open.patch b/queue-4.9/usb-serial-mos7720-fix-null-deref-at-open.patch new file mode 100644 index 00000000000..0955b7b673d --- /dev/null +++ b/queue-4.9/usb-serial-mos7720-fix-null-deref-at-open.patch @@ -0,0 +1,41 @@ +From b05aebc25fdc5aeeac3ee29f0dc9f58dd07c13cc Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:50 +0100 +Subject: USB: serial: mos7720: fix NULL-deref at open + +From: Johan Hovold + +commit b05aebc25fdc5aeeac3ee29f0dc9f58dd07c13cc upstream. + +Fix NULL-pointer dereference at port open if a device lacks the expected +bulk in and out endpoints. + +Unable to handle kernel NULL pointer dereference at virtual address 00000030 +... +[] (mos7720_open [mos7720]) from [] (serial_port_activate+0x68/0x98 [usbserial]) +[] (serial_port_activate [usbserial]) from [] (tty_port_open+0x9c/0xe8) +[] (tty_port_open) from [] (serial_open+0x48/0x6c [usbserial]) +[] (serial_open [usbserial]) from [] (tty_open+0xcc/0x5cc) + +Fixes: 0f64478cbc7a ("USB: add USB serial mos7720 driver") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7720.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/usb/serial/mos7720.c ++++ b/drivers/usb/serial/mos7720.c +@@ -1920,6 +1920,11 @@ static int mos7720_startup(struct usb_se + u16 product; + int ret_val; + ++ if (serial->num_bulk_in < 2 || serial->num_bulk_out < 2) { ++ dev_err(&serial->interface->dev, "missing bulk endpoints\n"); ++ return -ENODEV; ++ } ++ + product = le16_to_cpu(serial->dev->descriptor.idProduct); + dev = serial->dev; + diff --git a/queue-4.9/usb-serial-mos7720-fix-parallel-probe.patch b/queue-4.9/usb-serial-mos7720-fix-parallel-probe.patch new file mode 100644 index 00000000000..f9bb6fe179d --- /dev/null +++ b/queue-4.9/usb-serial-mos7720-fix-parallel-probe.patch @@ -0,0 +1,93 @@ +From fde1faf872ed86d88e245191bc15a8e57368cd1c Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:53 +0100 +Subject: USB: serial: mos7720: fix parallel probe + +From: Johan Hovold + +commit fde1faf872ed86d88e245191bc15a8e57368cd1c upstream. + +A static usb-serial-driver structure that is used to initialise the +interrupt URB was modified during probe depending on the currently +probed device type, something which could break a parallel probe of a +device of a different type. + +Fix this up by overriding the default completion callback for MCS7715 +devices in attach() instead. We may want to use two usb-serial driver +instances for the two types later. + +Fixes: fb088e335d78 ("USB: serial: add support for serial port on the moschip 7715") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7720.c | 30 +++++++----------------------- + 1 file changed, 7 insertions(+), 23 deletions(-) + +--- a/drivers/usb/serial/mos7720.c ++++ b/drivers/usb/serial/mos7720.c +@@ -65,8 +65,6 @@ struct moschip_port { + struct urb *write_urb_pool[NUM_URBS]; + }; + +-static struct usb_serial_driver moschip7720_2port_driver; +- + #define USB_VENDOR_ID_MOSCHIP 0x9710 + #define MOSCHIP_DEVICE_ID_7720 0x7720 + #define MOSCHIP_DEVICE_ID_7715 0x7715 +@@ -970,25 +968,6 @@ static void mos7720_bulk_out_data_callba + tty_port_tty_wakeup(&mos7720_port->port->port); + } + +-/* +- * mos77xx_probe +- * this function installs the appropriate read interrupt endpoint callback +- * depending on whether the device is a 7720 or 7715, thus avoiding costly +- * run-time checks in the high-frequency callback routine itself. +- */ +-static int mos77xx_probe(struct usb_serial *serial, +- const struct usb_device_id *id) +-{ +- if (id->idProduct == MOSCHIP_DEVICE_ID_7715) +- moschip7720_2port_driver.read_int_callback = +- mos7715_interrupt_callback; +- else +- moschip7720_2port_driver.read_int_callback = +- mos7720_interrupt_callback; +- +- return 0; +-} +- + static int mos77xx_calc_num_ports(struct usb_serial *serial) + { + u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); +@@ -1949,6 +1928,12 @@ static int mos7720_startup(struct usb_se + tmp->interrupt_in_endpointAddress; + serial->port[1]->interrupt_in_urb = NULL; + serial->port[1]->interrupt_in_buffer = NULL; ++ ++ if (serial->port[0]->interrupt_in_urb) { ++ struct urb *urb = serial->port[0]->interrupt_in_urb; ++ ++ urb->complete = mos7715_interrupt_callback; ++ } + } + + /* setting configuration feature to one */ +@@ -2063,7 +2048,6 @@ static struct usb_serial_driver moschip7 + .close = mos7720_close, + .throttle = mos7720_throttle, + .unthrottle = mos7720_unthrottle, +- .probe = mos77xx_probe, + .attach = mos7720_startup, + .release = mos7720_release, + .port_probe = mos7720_port_probe, +@@ -2077,7 +2061,7 @@ static struct usb_serial_driver moschip7 + .chars_in_buffer = mos7720_chars_in_buffer, + .break_ctl = mos7720_break, + .read_bulk_callback = mos7720_bulk_in_callback, +- .read_int_callback = NULL /* dynamically assigned in probe() */ ++ .read_int_callback = mos7720_interrupt_callback, + }; + + static struct usb_serial_driver * const serial_drivers[] = { diff --git a/queue-4.9/usb-serial-mos7720-fix-parport-use-after-free-on-probe-errors.patch b/queue-4.9/usb-serial-mos7720-fix-parport-use-after-free-on-probe-errors.patch new file mode 100644 index 00000000000..cc2c28f7a09 --- /dev/null +++ b/queue-4.9/usb-serial-mos7720-fix-parport-use-after-free-on-probe-errors.patch @@ -0,0 +1,55 @@ +From 75dd211e773afcbc264677b0749d1cf7d937ab2d Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:52 +0100 +Subject: USB: serial: mos7720: fix parport use-after-free on probe errors + +From: Johan Hovold + +commit 75dd211e773afcbc264677b0749d1cf7d937ab2d upstream. + +Do not submit the interrupt URB until after the parport has been +successfully registered to avoid another use-after-free in the +completion handler when accessing the freed parport private data in case +of a racing completion. + +Fixes: b69578df7e98 ("USB: usbserial: mos7720: add support for parallel port on moschip 7715") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7720.c | 18 ++++++++---------- + 1 file changed, 8 insertions(+), 10 deletions(-) + +--- a/drivers/usb/serial/mos7720.c ++++ b/drivers/usb/serial/mos7720.c +@@ -1955,22 +1955,20 @@ static int mos7720_startup(struct usb_se + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000); + +- /* start the interrupt urb */ +- ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL); +- if (ret_val) +- dev_err(&dev->dev, +- "%s - Error %d submitting control urb\n", +- __func__, ret_val); +- + #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT + if (product == MOSCHIP_DEVICE_ID_7715) { + ret_val = mos7715_parport_init(serial); +- if (ret_val < 0) { +- usb_kill_urb(serial->port[0]->interrupt_in_urb); ++ if (ret_val < 0) + return ret_val; +- } + } + #endif ++ /* start the interrupt urb */ ++ ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL); ++ if (ret_val) { ++ dev_err(&dev->dev, "failed to submit interrupt urb: %d\n", ++ ret_val); ++ } ++ + /* LSR For Port 1 */ + read_mos_reg(serial, 0, MOS7720_LSR, &data); + dev_dbg(&dev->dev, "LSR:%x\n", data); diff --git a/queue-4.9/usb-serial-mos7720-fix-use-after-free-on-probe-errors.patch b/queue-4.9/usb-serial-mos7720-fix-use-after-free-on-probe-errors.patch new file mode 100644 index 00000000000..dec986f5947 --- /dev/null +++ b/queue-4.9/usb-serial-mos7720-fix-use-after-free-on-probe-errors.patch @@ -0,0 +1,50 @@ +From 91a1ff4d53c5184d383d0baeeaeab6f9736f2ff3 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:51 +0100 +Subject: USB: serial: mos7720: fix use-after-free on probe errors + +From: Johan Hovold + +commit 91a1ff4d53c5184d383d0baeeaeab6f9736f2ff3 upstream. + +The interrupt URB was submitted on probe but never stopped on probe +errors. This can lead to use-after-free issues in the completion +handler when accessing the freed usb-serial struct: + +Unable to handle kernel paging request at virtual address 6b6b6be7 +... +[] (mos7715_interrupt_callback [mos7720]) from [] (__usb_hcd_giveback_urb+0x80/0x140) +[] (__usb_hcd_giveback_urb) from [] (usb_hcd_giveback_urb+0x50/0x138) +[] (usb_hcd_giveback_urb) from [] (musb_giveback+0xc8/0x1cc) + +Fixes: b69578df7e98 ("USB: usbserial: mos7720: add support for parallel port on moschip 7715") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7720.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/usb/serial/mos7720.c ++++ b/drivers/usb/serial/mos7720.c +@@ -1965,8 +1965,10 @@ static int mos7720_startup(struct usb_se + #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT + if (product == MOSCHIP_DEVICE_ID_7715) { + ret_val = mos7715_parport_init(serial); +- if (ret_val < 0) ++ if (ret_val < 0) { ++ usb_kill_urb(serial->port[0]->interrupt_in_urb); + return ret_val; ++ } + } + #endif + /* LSR For Port 1 */ +@@ -1978,6 +1980,8 @@ static int mos7720_startup(struct usb_se + + static void mos7720_release(struct usb_serial *serial) + { ++ usb_kill_urb(serial->port[0]->interrupt_in_urb); ++ + #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT + /* close the parallel port */ + diff --git a/queue-4.9/usb-serial-mos7840-fix-null-deref-at-open.patch b/queue-4.9/usb-serial-mos7840-fix-null-deref-at-open.patch new file mode 100644 index 00000000000..f6e06b2826a --- /dev/null +++ b/queue-4.9/usb-serial-mos7840-fix-null-deref-at-open.patch @@ -0,0 +1,55 @@ +From 5c75633ef751dd4cd8f443dc35152c1ae563162e Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:55 +0100 +Subject: USB: serial: mos7840: fix NULL-deref at open + +From: Johan Hovold + +commit 5c75633ef751dd4cd8f443dc35152c1ae563162e upstream. + +Fix NULL-pointer dereference in open() should the device lack the +expected endpoints: + +Unable to handle kernel NULL pointer dereference at virtual address 00000030 +... +PC is at mos7840_open+0x88/0x8dc [mos7840] + +Note that we continue to treat the interrupt-in endpoint as optional for +now. + +Fixes: 3f5429746d91 ("USB: Moschip 7840 USB-Serial Driver") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7840.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/usb/serial/mos7840.c ++++ b/drivers/usb/serial/mos7840.c +@@ -2116,6 +2116,17 @@ static int mos7840_calc_num_ports(struct + return mos7840_num_ports; + } + ++static int mos7840_attach(struct usb_serial *serial) ++{ ++ if (serial->num_bulk_in < serial->num_ports || ++ serial->num_bulk_out < serial->num_ports) { ++ dev_err(&serial->interface->dev, "missing endpoints\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ + static int mos7840_port_probe(struct usb_serial_port *port) + { + struct usb_serial *serial = port->serial; +@@ -2391,6 +2402,7 @@ static struct usb_serial_driver moschip7 + .tiocmset = mos7840_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, + .get_icount = usb_serial_generic_get_icount, ++ .attach = mos7840_attach, + .port_probe = mos7840_port_probe, + .port_remove = mos7840_port_remove, + .read_bulk_callback = mos7840_bulk_in_callback, diff --git a/queue-4.9/usb-serial-omninet-fix-null-derefs-at-open-and-disconnect.patch b/queue-4.9/usb-serial-omninet-fix-null-derefs-at-open-and-disconnect.patch new file mode 100644 index 00000000000..a7e8b1fd007 --- /dev/null +++ b/queue-4.9/usb-serial-omninet-fix-null-derefs-at-open-and-disconnect.patch @@ -0,0 +1,68 @@ +From a5bc01949e3b19d8a23b5eabc6fc71bb50dc820e Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:58 +0100 +Subject: USB: serial: omninet: fix NULL-derefs at open and disconnect + +From: Johan Hovold + +commit a5bc01949e3b19d8a23b5eabc6fc71bb50dc820e upstream. + +Fix NULL-pointer dereferences at open() and disconnect() should the +device lack the expected bulk-out endpoints: + +Unable to handle kernel NULL pointer dereference at virtual address 000000b4 +... +[c0170ff0>] (__lock_acquire) from [] (lock_acquire+0x108/0x264) +[] (lock_acquire) from [] (_raw_spin_lock_irqsave+0x58/0x6c) +[] (_raw_spin_lock_irqsave) from [] (tty_port_tty_set+0x28/0xa4) +[] (tty_port_tty_set) from [] (omninet_open+0x30/0x40 [omninet]) +[] (omninet_open [omninet]) from [] (serial_port_activate+0x68/0x98 [usbserial]) + +Unable to handle kernel NULL pointer dereference at virtual address 00000234 +... +[] (omninet_disconnect [omninet]) from [] (usb_serial_disconnect+0xe4/0x100 [usbserial]) + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/omninet.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/usb/serial/omninet.c ++++ b/drivers/usb/serial/omninet.c +@@ -38,6 +38,7 @@ static int omninet_write(struct tty_str + const unsigned char *buf, int count); + static int omninet_write_room(struct tty_struct *tty); + static void omninet_disconnect(struct usb_serial *serial); ++static int omninet_attach(struct usb_serial *serial); + static int omninet_port_probe(struct usb_serial_port *port); + static int omninet_port_remove(struct usb_serial_port *port); + +@@ -56,6 +57,7 @@ static struct usb_serial_driver zyxel_om + .description = "ZyXEL - omni.net lcd plus usb", + .id_table = id_table, + .num_ports = 1, ++ .attach = omninet_attach, + .port_probe = omninet_port_probe, + .port_remove = omninet_port_remove, + .open = omninet_open, +@@ -104,6 +106,17 @@ struct omninet_data { + __u8 od_outseq; /* Sequence number for bulk_out URBs */ + }; + ++static int omninet_attach(struct usb_serial *serial) ++{ ++ /* The second bulk-out endpoint is used for writing. */ ++ if (serial->num_bulk_out < 2) { ++ dev_err(&serial->interface->dev, "missing endpoints\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ + static int omninet_port_probe(struct usb_serial_port *port) + { + struct omninet_data *od; diff --git a/queue-4.9/usb-serial-oti6858-fix-null-deref-at-open.patch b/queue-4.9/usb-serial-oti6858-fix-null-deref-at-open.patch new file mode 100644 index 00000000000..4372cbffa88 --- /dev/null +++ b/queue-4.9/usb-serial-oti6858-fix-null-deref-at-open.patch @@ -0,0 +1,67 @@ +From 5afeef2366db14587b65558bbfd5a067542e07fb Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:39:59 +0100 +Subject: USB: serial: oti6858: fix NULL-deref at open + +From: Johan Hovold + +commit 5afeef2366db14587b65558bbfd5a067542e07fb upstream. + +Fix NULL-pointer dereference in open() should the device lack the +expected endpoints: + +Unable to handle kernel NULL pointer dereference at virtual address 00000030 +... +PC is at oti6858_open+0x30/0x1d0 [oti6858] + +Note that a missing interrupt-in endpoint would have caused open() to +fail. + +Fixes: 49cdee0ed0fc ("USB: oti6858 usb-serial driver (in Nokia CA-42 +cable)") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/oti6858.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/usb/serial/oti6858.c ++++ b/drivers/usb/serial/oti6858.c +@@ -134,6 +134,7 @@ static int oti6858_chars_in_buffer(struc + static int oti6858_tiocmget(struct tty_struct *tty); + static int oti6858_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear); ++static int oti6858_attach(struct usb_serial *serial); + static int oti6858_port_probe(struct usb_serial_port *port); + static int oti6858_port_remove(struct usb_serial_port *port); + +@@ -158,6 +159,7 @@ static struct usb_serial_driver oti6858_ + .write_bulk_callback = oti6858_write_bulk_callback, + .write_room = oti6858_write_room, + .chars_in_buffer = oti6858_chars_in_buffer, ++ .attach = oti6858_attach, + .port_probe = oti6858_port_probe, + .port_remove = oti6858_port_remove, + }; +@@ -324,6 +326,20 @@ static void send_data(struct work_struct + usb_serial_port_softint(port); + } + ++static int oti6858_attach(struct usb_serial *serial) ++{ ++ unsigned char num_ports = serial->num_ports; ++ ++ if (serial->num_bulk_in < num_ports || ++ serial->num_bulk_out < num_ports || ++ serial->num_interrupt_in < num_ports) { ++ dev_err(&serial->interface->dev, "missing endpoints\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ + static int oti6858_port_probe(struct usb_serial_port *port) + { + struct oti6858_private *priv; diff --git a/queue-4.9/usb-serial-pl2303-fix-null-deref-at-open.patch b/queue-4.9/usb-serial-pl2303-fix-null-deref-at-open.patch new file mode 100644 index 00000000000..eb49d4853a6 --- /dev/null +++ b/queue-4.9/usb-serial-pl2303-fix-null-deref-at-open.patch @@ -0,0 +1,47 @@ +From 76ab439ed1b68778e9059c79ecc5d14de76c89a8 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:40:00 +0100 +Subject: USB: serial: pl2303: fix NULL-deref at open + +From: Johan Hovold + +commit 76ab439ed1b68778e9059c79ecc5d14de76c89a8 upstream. + +Fix NULL-pointer dereference in open() should a type-0 or type-1 device +lack the expected endpoints: + +Unable to handle kernel NULL pointer dereference at virtual address 00000030 +... +PC is at pl2303_open+0x38/0xec [pl2303] + +Note that a missing interrupt-in endpoint would have caused open() to +fail. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/pl2303.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/usb/serial/pl2303.c ++++ b/drivers/usb/serial/pl2303.c +@@ -220,9 +220,17 @@ static int pl2303_probe(struct usb_seria + static int pl2303_startup(struct usb_serial *serial) + { + struct pl2303_serial_private *spriv; ++ unsigned char num_ports = serial->num_ports; + enum pl2303_type type = TYPE_01; + unsigned char *buf; + ++ if (serial->num_bulk_in < num_ports || ++ serial->num_bulk_out < num_ports || ++ serial->num_interrupt_in < num_ports) { ++ dev_err(&serial->interface->dev, "missing endpoints\n"); ++ return -ENODEV; ++ } ++ + spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); + if (!spriv) + return -ENOMEM; diff --git a/queue-4.9/usb-serial-quatech2-fix-sleep-while-atomic-in-close.patch b/queue-4.9/usb-serial-quatech2-fix-sleep-while-atomic-in-close.patch new file mode 100644 index 00000000000..0b23d9e30d9 --- /dev/null +++ b/queue-4.9/usb-serial-quatech2-fix-sleep-while-atomic-in-close.patch @@ -0,0 +1,42 @@ +From f09d1886a41e9063b43da493ef0e845ac8afd2fa Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:40:01 +0100 +Subject: USB: serial: quatech2: fix sleep-while-atomic in close + +From: Johan Hovold + +commit f09d1886a41e9063b43da493ef0e845ac8afd2fa upstream. + +The write URB was being killed using the synchronous interface while +holding a spin lock in close(). + +Simply drop the lock and busy-flag update, something which would have +been taken care of by the completion handler if the URB was in flight. + +Fixes: f7a33e608d9a ("USB: serial: add quatech2 usb to serial driver") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/quatech2.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/usb/serial/quatech2.c ++++ b/drivers/usb/serial/quatech2.c +@@ -408,16 +408,12 @@ static void qt2_close(struct usb_serial_ + { + struct usb_serial *serial; + struct qt2_port_private *port_priv; +- unsigned long flags; + int i; + + serial = port->serial; + port_priv = usb_get_serial_port_data(port); + +- spin_lock_irqsave(&port_priv->urb_lock, flags); + usb_kill_urb(port_priv->write_urb); +- port_priv->urb_in_use = false; +- spin_unlock_irqrestore(&port_priv->urb_lock, flags); + + /* flush the port transmit buffer */ + i = usb_control_msg(serial->dev, diff --git a/queue-4.9/usb-serial-spcp8x5-fix-null-deref-at-open.patch b/queue-4.9/usb-serial-spcp8x5-fix-null-deref-at-open.patch new file mode 100644 index 00000000000..01e5759bd75 --- /dev/null +++ b/queue-4.9/usb-serial-spcp8x5-fix-null-deref-at-open.patch @@ -0,0 +1,54 @@ +From cc0909248258f679c4bb4cd315565d40abaf6bc6 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:40:02 +0100 +Subject: USB: serial: spcp8x5: fix NULL-deref at open + +From: Johan Hovold + +commit cc0909248258f679c4bb4cd315565d40abaf6bc6 upstream. + +Fix NULL-pointer dereference in open() should the device lack the +expected endpoints: + +Unable to handle kernel NULL pointer dereference at virtual address 00000030 +... +PC is at spcp8x5_open+0x30/0xd0 [spcp8x5] + +Fixes: 619a6f1d1423 ("USB: add usb-serial spcp8x5 driver") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/spcp8x5.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/usb/serial/spcp8x5.c ++++ b/drivers/usb/serial/spcp8x5.c +@@ -154,6 +154,19 @@ static int spcp8x5_probe(struct usb_seri + return 0; + } + ++static int spcp8x5_attach(struct usb_serial *serial) ++{ ++ unsigned char num_ports = serial->num_ports; ++ ++ if (serial->num_bulk_in < num_ports || ++ serial->num_bulk_out < num_ports) { ++ dev_err(&serial->interface->dev, "missing endpoints\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ + static int spcp8x5_port_probe(struct usb_serial_port *port) + { + const struct usb_device_id *id = usb_get_serial_data(port->serial); +@@ -477,6 +490,7 @@ static struct usb_serial_driver spcp8x5_ + .tiocmget = spcp8x5_tiocmget, + .tiocmset = spcp8x5_tiocmset, + .probe = spcp8x5_probe, ++ .attach = spcp8x5_attach, + .port_probe = spcp8x5_port_probe, + .port_remove = spcp8x5_port_remove, + }; diff --git a/queue-4.9/usb-serial-ti_usb_3410_5052-fix-null-deref-at-open.patch b/queue-4.9/usb-serial-ti_usb_3410_5052-fix-null-deref-at-open.patch new file mode 100644 index 00000000000..7a36b6f61a8 --- /dev/null +++ b/queue-4.9/usb-serial-ti_usb_3410_5052-fix-null-deref-at-open.patch @@ -0,0 +1,40 @@ +From ef079936d3cd09e63612834fe2698eeada0d8e3f Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 3 Jan 2017 16:40:03 +0100 +Subject: USB: serial: ti_usb_3410_5052: fix NULL-deref at open + +From: Johan Hovold + +commit ef079936d3cd09e63612834fe2698eeada0d8e3f upstream. + +Fix NULL-pointer dereference in open() should a malicious device lack +the expected endpoints: + +Unable to handle kernel NULL pointer dereference at virtual address 00000030 +.. +[] (ti_open [ti_usb_3410_5052]) from [] (serial_port_activate+0x68/0x98 [usbserial]) + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/ti_usb_3410_5052.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/usb/serial/ti_usb_3410_5052.c ++++ b/drivers/usb/serial/ti_usb_3410_5052.c +@@ -579,6 +579,13 @@ static int ti_startup(struct usb_serial + goto free_tdev; + } + ++ if (serial->num_bulk_in < serial->num_ports || ++ serial->num_bulk_out < serial->num_ports) { ++ dev_err(&serial->interface->dev, "missing endpoints\n"); ++ status = -ENODEV; ++ goto free_tdev; ++ } ++ + return 0; + + free_tdev: diff --git a/queue-4.9/usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-apollo-lake.patch b/queue-4.9/usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-apollo-lake.patch new file mode 100644 index 00000000000..7694ec4a2f8 --- /dev/null +++ b/queue-4.9/usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-apollo-lake.patch @@ -0,0 +1,32 @@ +From 6c97cfc1a097b1e0786c836e92b7a72b4d031e25 Mon Sep 17 00:00:00 2001 +From: Wan Ahmad Zainie +Date: Tue, 3 Jan 2017 18:28:52 +0200 +Subject: usb: xhci: apply XHCI_PME_STUCK_QUIRK to Intel Apollo Lake + +From: Wan Ahmad Zainie + +commit 6c97cfc1a097b1e0786c836e92b7a72b4d031e25 upstream. + +Intel Apollo Lake also requires XHCI_PME_STUCK_QUIRK. +Adding its PCI ID to quirk. + +Signed-off-by: Wan Ahmad Zainie +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-pci.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -165,7 +165,8 @@ static void xhci_pci_quirks(struct devic + pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI || +- pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI)) { ++ pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI || ++ pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI)) { + xhci->quirks |= XHCI_PME_STUCK_QUIRK; + } + if (pdev->vendor == PCI_VENDOR_ID_INTEL && diff --git a/queue-4.9/usb-xhci-fix-return-value-of-xhci_setup_device.patch b/queue-4.9/usb-xhci-fix-return-value-of-xhci_setup_device.patch new file mode 100644 index 00000000000..5f43f527e42 --- /dev/null +++ b/queue-4.9/usb-xhci-fix-return-value-of-xhci_setup_device.patch @@ -0,0 +1,42 @@ +From 90797aee5d6902b49a453c97d83c326408aeb5a8 Mon Sep 17 00:00:00 2001 +From: Lu Baolu +Date: Tue, 3 Jan 2017 18:28:44 +0200 +Subject: usb: xhci: fix return value of xhci_setup_device() + +From: Lu Baolu + +commit 90797aee5d6902b49a453c97d83c326408aeb5a8 upstream. + +xhci_setup_device() should return failure with correct error number +when xhci host has died, removed or halted. + +During usb device enumeration, if usb host is not accessible (died, +removed or halted), the hc_driver->address_device() should return +a corresponding error code to usb core. But current xhci driver just +returns success. This misleads usb core to continue the enumeration +by reading the device descriptor, which will result in failure, and +users will get a misleading message like "device descriptor read/8, +error -110". + +Signed-off-by: Lu Baolu +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -3783,8 +3783,10 @@ static int xhci_setup_device(struct usb_ + + mutex_lock(&xhci->mutex); + +- if (xhci->xhc_state) /* dying, removing or halted */ ++ if (xhci->xhc_state) { /* dying, removing or halted */ ++ ret = -ESHUTDOWN; + goto out; ++ } + + if (!udev->slot_id) { + xhci_dbg_trace(xhci, trace_xhci_dbg_address, diff --git a/queue-4.9/usb-xhci-hold-lock-over-xhci_abort_cmd_ring.patch b/queue-4.9/usb-xhci-hold-lock-over-xhci_abort_cmd_ring.patch new file mode 100644 index 00000000000..6e27af30b9a --- /dev/null +++ b/queue-4.9/usb-xhci-hold-lock-over-xhci_abort_cmd_ring.patch @@ -0,0 +1,72 @@ +From 4dea70778c0f48b4385c7720c363ec8d37a401b4 Mon Sep 17 00:00:00 2001 +From: Lu Baolu +Date: Tue, 3 Jan 2017 18:28:49 +0200 +Subject: usb: xhci: hold lock over xhci_abort_cmd_ring() + +From: Lu Baolu + +commit 4dea70778c0f48b4385c7720c363ec8d37a401b4 upstream. + +In command timer function, xhci_handle_command_timeout(), xhci->lock +is unlocked before call into xhci_abort_cmd_ring(). This might cause +race between the timer function and the event handler. + +The xhci_abort_cmd_ring() function sets the CMD_RING_ABORT bit in the +command register and polling it until the setting takes effect. A stop +command ring event might be handled between writing the abort bit and +polling for it. The event handler will restart the command ring, which +causes the failure of polling, and we ever believed that we failed to +stop it. + +As a bonus, this also fixes some issues of calling functions without +locking in xhci_handle_command_timeout(). + +Signed-off-by: Lu Baolu +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-ring.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1291,29 +1291,34 @@ void xhci_handle_command_timeout(unsigne + hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) && + (hw_ring_state & CMD_RING_RUNNING)) { +- spin_unlock_irqrestore(&xhci->lock, flags); + xhci_dbg(xhci, "Command timeout\n"); + ret = xhci_abort_cmd_ring(xhci); + if (unlikely(ret == -ESHUTDOWN)) { + xhci_err(xhci, "Abort command ring failed\n"); + xhci_cleanup_command_queue(xhci); ++ spin_unlock_irqrestore(&xhci->lock, flags); + usb_hc_died(xhci_to_hcd(xhci)->primary_hcd); + xhci_dbg(xhci, "xHCI host controller is dead.\n"); ++ ++ return; + } +- return; ++ ++ goto time_out_completed; + } + + /* command ring failed to restart, or host removed. Bail out */ + if (second_timeout || xhci->xhc_state & XHCI_STATE_REMOVING) { +- spin_unlock_irqrestore(&xhci->lock, flags); + xhci_dbg(xhci, "command timed out twice, ring start fail?\n"); + xhci_cleanup_command_queue(xhci); +- return; ++ ++ goto time_out_completed; + } + + /* command timeout on stopped ring, ring can't be aborted */ + xhci_dbg(xhci, "Command timeout on stopped ring\n"); + xhci_handle_stopped_cmd_ring(xhci, xhci->current_cmd); ++ ++time_out_completed: + spin_unlock_irqrestore(&xhci->lock, flags); + return; + } diff --git a/queue-4.9/usb-xhci-mem-use-passed-in-gfp-flags-instead-of-gfp_kernel.patch b/queue-4.9/usb-xhci-mem-use-passed-in-gfp-flags-instead-of-gfp_kernel.patch new file mode 100644 index 00000000000..3b67e1a7f8f --- /dev/null +++ b/queue-4.9/usb-xhci-mem-use-passed-in-gfp-flags-instead-of-gfp_kernel.patch @@ -0,0 +1,42 @@ +From c95a9f83711bf53faeb4ed9bbb63a3f065613dfb Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Thu, 10 Nov 2016 22:33:17 +0300 +Subject: usb: xhci-mem: use passed in GFP flags instead of GFP_KERNEL + +From: Dan Carpenter + +commit c95a9f83711bf53faeb4ed9bbb63a3f065613dfb upstream. + +We normally use the passed in gfp flags for allocations, it's just these +two which were missed. + +Fixes: 22d45f01a836 ("usb/xhci: replace pci_*_consistent() with dma_*_coherent()") +Cc: Mathias Nyman +Signed-off-by: Dan Carpenter +Acked-by: Sebastian Andrzej Siewior +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-mem.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -2418,7 +2418,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, + * "physically contiguous and 64-byte (cache line) aligned". + */ + xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma, +- GFP_KERNEL); ++ flags); + if (!xhci->dcbaa) + goto fail; + memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa)); +@@ -2514,7 +2514,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, + + xhci->erst.entries = dma_alloc_coherent(dev, + sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS, &dma, +- GFP_KERNEL); ++ flags); + if (!xhci->erst.entries) + goto fail; + xhci_dbg_trace(xhci, trace_xhci_dbg_init, diff --git a/queue-4.9/xhci-free-xhci-virtual-devices-with-leaf-nodes-first.patch b/queue-4.9/xhci-free-xhci-virtual-devices-with-leaf-nodes-first.patch new file mode 100644 index 00000000000..dd561fbc4f9 --- /dev/null +++ b/queue-4.9/xhci-free-xhci-virtual-devices-with-leaf-nodes-first.patch @@ -0,0 +1,81 @@ +From ee8665e28e8d90ce69d4abe5a469c14a8707ae0e Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Tue, 3 Jan 2017 18:28:43 +0200 +Subject: xhci: free xhci virtual devices with leaf nodes first + +From: Mathias Nyman + +commit ee8665e28e8d90ce69d4abe5a469c14a8707ae0e upstream. + +the tt_info provided by a HS hub might be in use to by a child device +Make sure we free the devices in the correct order. + +This is needed in special cases such as when xhci controller is +reset when resuming from hibernate, and all virt_devices are freed. + +Also free the virt_devices starting from max slot_id as children +more commonly have higher slot_id than parent. + +Reported-by: Guenter Roeck +Tested-by: Guenter Roeck +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-mem.c | 38 ++++++++++++++++++++++++++++++++++++-- + 1 file changed, 36 insertions(+), 2 deletions(-) + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -979,6 +979,40 @@ void xhci_free_virt_device(struct xhci_h + xhci->devs[slot_id] = NULL; + } + ++/* ++ * Free a virt_device structure. ++ * If the virt_device added a tt_info (a hub) and has children pointing to ++ * that tt_info, then free the child first. Recursive. ++ * We can't rely on udev at this point to find child-parent relationships. ++ */ ++void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_id) ++{ ++ struct xhci_virt_device *vdev; ++ struct list_head *tt_list_head; ++ struct xhci_tt_bw_info *tt_info, *next; ++ int i; ++ ++ vdev = xhci->devs[slot_id]; ++ if (!vdev) ++ return; ++ ++ tt_list_head = &(xhci->rh_bw[vdev->real_port - 1].tts); ++ list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) { ++ /* is this a hub device that added a tt_info to the tts list */ ++ if (tt_info->slot_id == slot_id) { ++ /* are any devices using this tt_info? */ ++ for (i = 1; i < HCS_MAX_SLOTS(xhci->hcs_params1); i++) { ++ vdev = xhci->devs[i]; ++ if (vdev && (vdev->tt_info == tt_info)) ++ xhci_free_virt_devices_depth_first( ++ xhci, i); ++ } ++ } ++ } ++ /* we are now at a leaf device */ ++ xhci_free_virt_device(xhci, slot_id); ++} ++ + int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, + struct usb_device *udev, gfp_t flags) + { +@@ -1829,8 +1863,8 @@ void xhci_mem_cleanup(struct xhci_hcd *x + } + } + +- for (i = 1; i < MAX_HC_SLOTS; ++i) +- xhci_free_virt_device(xhci, i); ++ for (i = HCS_MAX_SLOTS(xhci->hcs_params1); i > 0; i--) ++ xhci_free_virt_devices_depth_first(xhci, i); + + dma_pool_destroy(xhci->segment_pool); + xhci->segment_pool = NULL; diff --git a/queue-4.9/xhci-handle-command-completion-and-timeout-race.patch b/queue-4.9/xhci-handle-command-completion-and-timeout-race.patch new file mode 100644 index 00000000000..a373a082bfb --- /dev/null +++ b/queue-4.9/xhci-handle-command-completion-and-timeout-race.patch @@ -0,0 +1,48 @@ +From a5a1b9514154437aa1ed35c291191f82fd3e941a Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Tue, 3 Jan 2017 18:28:48 +0200 +Subject: xhci: Handle command completion and timeout race + +From: Mathias Nyman + +commit a5a1b9514154437aa1ed35c291191f82fd3e941a upstream. + +If we get a command completion event at the same time as the command +timeout work starts on another cpu we might end up aborting the wrong +command. + +If the command completion takes the xhci lock before the timeout work, it +will handle the command, pick the next command, mark it as current_cmd, and +re-queue the timeout work. When the timeout work finally gets the lock +It will start aborting the wrong command. + +This case can be resolved by checking if the timeout work is pending inside +the timeout function itself. A new timeout work can only be pending if the +command completed and a new command was queued. + +If there are no more commands pending then command completion will set +the current_cmd to NULL, which is already handled in the timeout work. + +Reported-by: Baolin Wang +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-ring.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1273,7 +1273,11 @@ void xhci_handle_command_timeout(unsigne + + spin_lock_irqsave(&xhci->lock, flags); + +- if (!xhci->current_cmd) { ++ /* ++ * If timeout work is pending, or current_cmd is NULL, it means we ++ * raced with command completion. Command is handled so just return. ++ */ ++ if (!xhci->current_cmd || timer_pending(&xhci->cmd_timer)) { + spin_unlock_irqrestore(&xhci->lock, flags); + return; + }