From: Greg Kroah-Hartman Date: Sat, 17 Oct 2015 20:51:29 +0000 (-0700) Subject: 3.14-stable patches X-Git-Tag: v3.10.91~42 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a3d52045e2b135577b477a7c6701915090c2a814;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: usb-whiteheat-fix-potential-null-deref-at-probe.patch usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch usb-xhci-clear-xhci_state_dying-on-start.patch xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch --- diff --git a/queue-3.14/series b/queue-3.14/series index 25ae10c2caa..7ac7b38592f 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -42,3 +42,7 @@ disabling-oplocks-leases-via-module-parm-enable_oplocks-broken-for-smb3.patch drm-qxl-only-report-first-monitor-as-connected-if-we-have-no-state.patch drm-qxl-recreate-the-primary-surface-when-the-bo-is-not-primary.patch drm-reject-dri1-hw-lock-ioctl-functions-for-kms-drivers.patch +usb-whiteheat-fix-potential-null-deref-at-probe.patch +usb-xhci-clear-xhci_state_dying-on-start.patch +xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch +usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch diff --git a/queue-3.14/usb-whiteheat-fix-potential-null-deref-at-probe.patch b/queue-3.14/usb-whiteheat-fix-potential-null-deref-at-probe.patch new file mode 100644 index 00000000000..b0b1393f321 --- /dev/null +++ b/queue-3.14/usb-whiteheat-fix-potential-null-deref-at-probe.patch @@ -0,0 +1,81 @@ +From cbb4be652d374f64661137756b8f357a1827d6a4 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Wed, 23 Sep 2015 11:41:42 -0700 +Subject: USB: whiteheat: fix potential null-deref at probe + +From: Johan Hovold + +commit cbb4be652d374f64661137756b8f357a1827d6a4 upstream. + +Fix potential null-pointer dereference at probe by making sure that the +required endpoints are present. + +The whiteheat driver assumes there are at least five pairs of bulk +endpoints, of which the final pair is used for the "command port". An +attempt to bind to an interface with fewer bulk endpoints would +currently lead to an oops. + +Fixes CVE-2015-5257. + +Reported-by: Moein Ghasemzadeh +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/whiteheat.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +--- a/drivers/usb/serial/whiteheat.c ++++ b/drivers/usb/serial/whiteheat.c +@@ -80,6 +80,8 @@ static int whiteheat_firmware_download( + static int whiteheat_firmware_attach(struct usb_serial *serial); + + /* function prototypes for the Connect Tech WhiteHEAT serial converter */ ++static int whiteheat_probe(struct usb_serial *serial, ++ const struct usb_device_id *id); + static int whiteheat_attach(struct usb_serial *serial); + static void whiteheat_release(struct usb_serial *serial); + static int whiteheat_port_probe(struct usb_serial_port *port); +@@ -116,6 +118,7 @@ static struct usb_serial_driver whitehea + .description = "Connect Tech - WhiteHEAT", + .id_table = id_table_std, + .num_ports = 4, ++ .probe = whiteheat_probe, + .attach = whiteheat_attach, + .release = whiteheat_release, + .port_probe = whiteheat_port_probe, +@@ -217,6 +220,34 @@ static int whiteheat_firmware_attach(str + /***************************************************************************** + * Connect Tech's White Heat serial driver functions + *****************************************************************************/ ++ ++static int whiteheat_probe(struct usb_serial *serial, ++ const struct usb_device_id *id) ++{ ++ struct usb_host_interface *iface_desc; ++ struct usb_endpoint_descriptor *endpoint; ++ size_t num_bulk_in = 0; ++ size_t num_bulk_out = 0; ++ size_t min_num_bulk; ++ unsigned int i; ++ ++ iface_desc = serial->interface->cur_altsetting; ++ ++ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { ++ endpoint = &iface_desc->endpoint[i].desc; ++ if (usb_endpoint_is_bulk_in(endpoint)) ++ ++num_bulk_in; ++ if (usb_endpoint_is_bulk_out(endpoint)) ++ ++num_bulk_out; ++ } ++ ++ min_num_bulk = COMMAND_PORT + 1; ++ if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk) ++ return -ENODEV; ++ ++ return 0; ++} ++ + static int whiteheat_attach(struct usb_serial *serial) + { + struct usb_serial_port *command_port; diff --git a/queue-3.14/usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch b/queue-3.14/usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch new file mode 100644 index 00000000000..88213e8651e --- /dev/null +++ b/queue-3.14/usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch @@ -0,0 +1,195 @@ +From 4758dcd19a7d9ba9610b38fecb93f65f56f86346 Mon Sep 17 00:00:00 2001 +From: Reyad Attiyat +Date: Thu, 6 Aug 2015 19:23:58 +0300 +Subject: usb: xhci: Add support for URB_ZERO_PACKET to bulk/sg transfers + +From: Reyad Attiyat + +commit 4758dcd19a7d9ba9610b38fecb93f65f56f86346 upstream. + +This commit checks for the URB_ZERO_PACKET flag and creates an extra +zero-length td if the urb transfer length is a multiple of the endpoint's +max packet length. + +Signed-off-by: Reyad Attiyat +Signed-off-by: Mathias Nyman +Cc: Oliver Neukum +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-ring.c | 66 +++++++++++++++++++++++++++++++++---------- + drivers/usb/host/xhci.c | 5 +++ + 2 files changed, 57 insertions(+), 14 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -3223,9 +3223,11 @@ static int queue_bulk_sg_tx(struct xhci_ + struct xhci_td *td; + struct scatterlist *sg; + int num_sgs; +- int trb_buff_len, this_sg_len, running_total; ++ int trb_buff_len, this_sg_len, running_total, ret; + unsigned int total_packet_count; ++ bool zero_length_needed; + bool first_trb; ++ int last_trb_num; + u64 addr; + bool more_trbs_coming; + +@@ -3241,13 +3243,27 @@ static int queue_bulk_sg_tx(struct xhci_ + total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, + usb_endpoint_maxp(&urb->ep->desc)); + +- trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], ++ ret = prepare_transfer(xhci, xhci->devs[slot_id], + ep_index, urb->stream_id, + num_trbs, urb, 0, mem_flags); +- if (trb_buff_len < 0) +- return trb_buff_len; ++ if (ret < 0) ++ return ret; + + urb_priv = urb->hcpriv; ++ ++ /* Deal with URB_ZERO_PACKET - need one more td/trb */ ++ zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET && ++ urb_priv->length == 2; ++ if (zero_length_needed) { ++ num_trbs++; ++ xhci_dbg(xhci, "Creating zero length td.\n"); ++ ret = prepare_transfer(xhci, xhci->devs[slot_id], ++ ep_index, urb->stream_id, ++ 1, urb, 1, mem_flags); ++ if (ret < 0) ++ return ret; ++ } ++ + td = urb_priv->td[0]; + + /* +@@ -3277,6 +3293,7 @@ static int queue_bulk_sg_tx(struct xhci_ + trb_buff_len = urb->transfer_buffer_length; + + first_trb = true; ++ last_trb_num = zero_length_needed ? 2 : 1; + /* Queue the first TRB, even if it's zero-length */ + do { + u32 field = 0; +@@ -3294,12 +3311,15 @@ static int queue_bulk_sg_tx(struct xhci_ + /* Chain all the TRBs together; clear the chain bit in the last + * TRB to indicate it's the last TRB in the chain. + */ +- if (num_trbs > 1) { ++ if (num_trbs > last_trb_num) { + field |= TRB_CHAIN; +- } else { +- /* FIXME - add check for ZERO_PACKET flag before this */ ++ } else if (num_trbs == last_trb_num) { + td->last_trb = ep_ring->enqueue; + field |= TRB_IOC; ++ } else if (zero_length_needed && num_trbs == 1) { ++ trb_buff_len = 0; ++ urb_priv->td[1]->last_trb = ep_ring->enqueue; ++ field |= TRB_IOC; + } + + /* Only set interrupt on short packet for IN endpoints */ +@@ -3361,7 +3381,7 @@ static int queue_bulk_sg_tx(struct xhci_ + if (running_total + trb_buff_len > urb->transfer_buffer_length) + trb_buff_len = + urb->transfer_buffer_length - running_total; +- } while (running_total < urb->transfer_buffer_length); ++ } while (num_trbs > 0); + + check_trb_math(urb, num_trbs, running_total); + giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, +@@ -3379,7 +3399,9 @@ int xhci_queue_bulk_tx(struct xhci_hcd * + int num_trbs; + struct xhci_generic_trb *start_trb; + bool first_trb; ++ int last_trb_num; + bool more_trbs_coming; ++ bool zero_length_needed; + int start_cycle; + u32 field, length_field; + +@@ -3410,7 +3432,6 @@ int xhci_queue_bulk_tx(struct xhci_hcd * + num_trbs++; + running_total += TRB_MAX_BUFF_SIZE; + } +- /* FIXME: this doesn't deal with URB_ZERO_PACKET - need one more */ + + ret = prepare_transfer(xhci, xhci->devs[slot_id], + ep_index, urb->stream_id, +@@ -3419,6 +3440,20 @@ int xhci_queue_bulk_tx(struct xhci_hcd * + return ret; + + urb_priv = urb->hcpriv; ++ ++ /* Deal with URB_ZERO_PACKET - need one more td/trb */ ++ zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET && ++ urb_priv->length == 2; ++ if (zero_length_needed) { ++ num_trbs++; ++ xhci_dbg(xhci, "Creating zero length td.\n"); ++ ret = prepare_transfer(xhci, xhci->devs[slot_id], ++ ep_index, urb->stream_id, ++ 1, urb, 1, mem_flags); ++ if (ret < 0) ++ return ret; ++ } ++ + td = urb_priv->td[0]; + + /* +@@ -3440,7 +3475,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd * + trb_buff_len = urb->transfer_buffer_length; + + first_trb = true; +- ++ last_trb_num = zero_length_needed ? 2 : 1; + /* Queue the first TRB, even if it's zero-length */ + do { + u32 remainder = 0; +@@ -3457,12 +3492,15 @@ int xhci_queue_bulk_tx(struct xhci_hcd * + /* Chain all the TRBs together; clear the chain bit in the last + * TRB to indicate it's the last TRB in the chain. + */ +- if (num_trbs > 1) { ++ if (num_trbs > last_trb_num) { + field |= TRB_CHAIN; +- } else { +- /* FIXME - add check for ZERO_PACKET flag before this */ ++ } else if (num_trbs == last_trb_num) { + td->last_trb = ep_ring->enqueue; + field |= TRB_IOC; ++ } else if (zero_length_needed && num_trbs == 1) { ++ trb_buff_len = 0; ++ urb_priv->td[1]->last_trb = ep_ring->enqueue; ++ field |= TRB_IOC; + } + + /* Only set interrupt on short packet for IN endpoints */ +@@ -3500,7 +3538,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd * + trb_buff_len = urb->transfer_buffer_length - running_total; + if (trb_buff_len > TRB_MAX_BUFF_SIZE) + trb_buff_len = TRB_MAX_BUFF_SIZE; +- } while (running_total < urb->transfer_buffer_length); ++ } while (num_trbs > 0); + + check_trb_math(urb, num_trbs, running_total); + giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -1320,6 +1320,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd + + if (usb_endpoint_xfer_isoc(&urb->ep->desc)) + size = urb->number_of_packets; ++ else if (usb_endpoint_is_bulk_out(&urb->ep->desc) && ++ urb->transfer_buffer_length > 0 && ++ urb->transfer_flags & URB_ZERO_PACKET && ++ !(urb->transfer_buffer_length % usb_endpoint_maxp(&urb->ep->desc))) ++ size = 2; + else + size = 1; + diff --git a/queue-3.14/usb-xhci-clear-xhci_state_dying-on-start.patch b/queue-3.14/usb-xhci-clear-xhci_state_dying-on-start.patch new file mode 100644 index 00000000000..b54a7d46f0f --- /dev/null +++ b/queue-3.14/usb-xhci-clear-xhci_state_dying-on-start.patch @@ -0,0 +1,33 @@ +From e5bfeab0ad515b4f6df39fe716603e9dc6d3dfd0 Mon Sep 17 00:00:00 2001 +From: Roger Quadros +Date: Mon, 21 Sep 2015 17:46:13 +0300 +Subject: usb: xhci: Clear XHCI_STATE_DYING on start + +From: Roger Quadros + +commit e5bfeab0ad515b4f6df39fe716603e9dc6d3dfd0 upstream. + +For whatever reason if XHCI died in the previous instant +then it will never recover on the next xhci_start unless we +clear the DYING flag. + +Signed-off-by: Roger Quadros +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -147,7 +147,8 @@ static int xhci_start(struct xhci_hcd *x + "waited %u microseconds.\n", + XHCI_MAX_HALT_USEC); + if (!ret) +- xhci->xhc_state &= ~XHCI_STATE_HALTED; ++ xhci->xhc_state &= ~(XHCI_STATE_HALTED | XHCI_STATE_DYING); ++ + return ret; + } + diff --git a/queue-3.14/xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch b/queue-3.14/xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch new file mode 100644 index 00000000000..125c56d5300 --- /dev/null +++ b/queue-3.14/xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch @@ -0,0 +1,53 @@ +From dca7794539eff04b786fb6907186989e5eaaa9c2 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Mon, 21 Sep 2015 17:46:16 +0300 +Subject: xhci: change xhci 1.0 only restrictions to support xhci 1.1 + +From: Mathias Nyman + +commit dca7794539eff04b786fb6907186989e5eaaa9c2 upstream. + +Some changes between xhci 0.96 and xhci 1.0 specifications forced us to +check the hci version in code, some of these checks were implemented as +hci_version == 1.0, which will not work with new xhci 1.1 controllers. + +xhci 1.1 behaves similar to xhci 1.0 in these cases, so change these +checks to hci_version >= 1.0 + +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-mem.c | 6 +++--- + drivers/usb/host/xhci-ring.c | 4 ++-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1402,10 +1402,10 @@ int xhci_endpoint_init(struct xhci_hcd * + * use Event Data TRBs, and we don't chain in a link TRB on short + * transfers, we're basically dividing by 1. + * +- * xHCI 1.0 specification indicates that the Average TRB Length should +- * be set to 8 for control endpoints. ++ * xHCI 1.0 and 1.1 specification indicates that the Average TRB Length ++ * should be set to 8 for control endpoints. + */ +- if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version == 0x100) ++ if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100) + ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8)); + else + ep_ctx->tx_info |= +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -3567,8 +3567,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd * + if (start_cycle == 0) + field |= 0x1; + +- /* xHCI 1.0 6.4.1.2.1: Transfer Type field */ +- if (xhci->hci_version == 0x100) { ++ /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */ ++ if (xhci->hci_version >= 0x100) { + if (urb->transfer_buffer_length > 0) { + if (setup->bRequestType & USB_DIR_IN) + field |= TRB_TX_TYPE(TRB_DATA_IN);