From 94fd3919df39b08269ae4eb091ce9cc3378e8532 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 24 Jul 2017 17:07:51 -0700 Subject: [PATCH] 3.18-stable patches added patches: af_key-fix-sadb_x_ipsecrequest-parsing.patch md-don-t-use-flush_signals-in-userspace-processes.patch pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch usb-cdc-acm-add-device-id-for-quirky-printer.patch usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch xhci-fix-20000ms-port-resume-timeout.patch xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch --- ..._key-fix-sadb_x_ipsecrequest-parsing.patch | 146 ++++++++++++++++++ ...flush_signals-in-userspace-processes.patch | 70 +++++++++ ...us-of-pci-devices-across-hibernation.patch | 93 +++++++++++ queue-3.18/series | 8 + ...acm-add-device-id-for-quirky-printer.patch | 33 ++++ ...hsc_resume-for-usbhsf_runtime_pwctrl.patch | 37 +++++ ...-to-avoid-a-null-pointer-dereference.patch | 44 ++++++ ...xhci-fix-20000ms-port-resume-timeout.patch | 41 +++++ ...cleaning-up-streams-for-removed-host.patch | 51 ++++++ 9 files changed, 523 insertions(+) create mode 100644 queue-3.18/af_key-fix-sadb_x_ipsecrequest-parsing.patch create mode 100644 queue-3.18/md-don-t-use-flush_signals-in-userspace-processes.patch create mode 100644 queue-3.18/pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch create mode 100644 queue-3.18/usb-cdc-acm-add-device-id-for-quirky-printer.patch create mode 100644 queue-3.18/usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch create mode 100644 queue-3.18/usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch create mode 100644 queue-3.18/xhci-fix-20000ms-port-resume-timeout.patch create mode 100644 queue-3.18/xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch diff --git a/queue-3.18/af_key-fix-sadb_x_ipsecrequest-parsing.patch b/queue-3.18/af_key-fix-sadb_x_ipsecrequest-parsing.patch new file mode 100644 index 00000000000..aa4187d28a4 --- /dev/null +++ b/queue-3.18/af_key-fix-sadb_x_ipsecrequest-parsing.patch @@ -0,0 +1,146 @@ +From 096f41d3a8fcbb8dde7f71379b1ca85fe213eded Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Thu, 13 Apr 2017 18:35:59 +0800 +Subject: af_key: Fix sadb_x_ipsecrequest parsing + +From: Herbert Xu + +commit 096f41d3a8fcbb8dde7f71379b1ca85fe213eded upstream. + +The parsing of sadb_x_ipsecrequest is broken in a number of ways. +First of all we're not verifying sadb_x_ipsecrequest_len. This +is needed when the structure carries addresses at the end. Worse +we don't even look at the length when we parse those optional +addresses. + +The migration code had similar parsing code that's better but +it also has some deficiencies. The length is overcounted first +of all as it includes the header itself. It also fails to check +the length before dereferencing the sa_family field. + +This patch fixes those problems in parse_sockaddr_pair and then +uses it in parse_ipsecrequest. + +Reported-by: Andrey Konovalov +Signed-off-by: Herbert Xu +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman + +--- + net/key/af_key.c | 47 ++++++++++++++++++++++++++--------------------- + 1 file changed, 26 insertions(+), 21 deletions(-) + +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -65,6 +65,10 @@ struct pfkey_sock { + } dump; + }; + ++static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, ++ xfrm_address_t *saddr, xfrm_address_t *daddr, ++ u16 *family); ++ + static inline struct pfkey_sock *pfkey_sk(struct sock *sk) + { + return (struct pfkey_sock *)sk; +@@ -1921,19 +1925,14 @@ parse_ipsecrequest(struct xfrm_policy *x + + /* addresses present only in tunnel mode */ + if (t->mode == XFRM_MODE_TUNNEL) { +- u8 *sa = (u8 *) (rq + 1); +- int family, socklen; ++ int err; + +- family = pfkey_sockaddr_extract((struct sockaddr *)sa, +- &t->saddr); +- if (!family) +- return -EINVAL; +- +- socklen = pfkey_sockaddr_len(family); +- if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen), +- &t->id.daddr) != family) +- return -EINVAL; +- t->encap_family = family; ++ err = parse_sockaddr_pair( ++ (struct sockaddr *)(rq + 1), ++ rq->sadb_x_ipsecrequest_len - sizeof(*rq), ++ &t->saddr, &t->id.daddr, &t->encap_family); ++ if (err) ++ return err; + } else + t->encap_family = xp->family; + +@@ -1953,7 +1952,11 @@ parse_ipsecrequests(struct xfrm_policy * + if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy)) + return -EINVAL; + +- while (len >= sizeof(struct sadb_x_ipsecrequest)) { ++ while (len >= sizeof(*rq)) { ++ if (len < rq->sadb_x_ipsecrequest_len || ++ rq->sadb_x_ipsecrequest_len < sizeof(*rq)) ++ return -EINVAL; ++ + if ((err = parse_ipsecrequest(xp, rq)) < 0) + return err; + len -= rq->sadb_x_ipsecrequest_len; +@@ -2416,7 +2419,6 @@ out: + return err; + } + +-#ifdef CONFIG_NET_KEY_MIGRATE + static int pfkey_sockaddr_pair_size(sa_family_t family) + { + return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); +@@ -2428,7 +2430,7 @@ static int parse_sockaddr_pair(struct so + { + int af, socklen; + +- if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) ++ if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) + return -EINVAL; + + af = pfkey_sockaddr_extract(sa, saddr); +@@ -2444,6 +2446,7 @@ static int parse_sockaddr_pair(struct so + return 0; + } + ++#ifdef CONFIG_NET_KEY_MIGRATE + static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, + struct xfrm_migrate *m) + { +@@ -2451,13 +2454,14 @@ static int ipsecrequests_to_migrate(stru + struct sadb_x_ipsecrequest *rq2; + int mode; + +- if (len <= sizeof(struct sadb_x_ipsecrequest) || +- len < rq1->sadb_x_ipsecrequest_len) ++ if (len < sizeof(*rq1) || ++ len < rq1->sadb_x_ipsecrequest_len || ++ rq1->sadb_x_ipsecrequest_len < sizeof(*rq1)) + return -EINVAL; + + /* old endoints */ + err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1), +- rq1->sadb_x_ipsecrequest_len, ++ rq1->sadb_x_ipsecrequest_len - sizeof(*rq1), + &m->old_saddr, &m->old_daddr, + &m->old_family); + if (err) +@@ -2466,13 +2470,14 @@ static int ipsecrequests_to_migrate(stru + rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len); + len -= rq1->sadb_x_ipsecrequest_len; + +- if (len <= sizeof(struct sadb_x_ipsecrequest) || +- len < rq2->sadb_x_ipsecrequest_len) ++ if (len <= sizeof(*rq2) || ++ len < rq2->sadb_x_ipsecrequest_len || ++ rq2->sadb_x_ipsecrequest_len < sizeof(*rq2)) + return -EINVAL; + + /* new endpoints */ + err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1), +- rq2->sadb_x_ipsecrequest_len, ++ rq2->sadb_x_ipsecrequest_len - sizeof(*rq2), + &m->new_saddr, &m->new_daddr, + &m->new_family); + if (err) diff --git a/queue-3.18/md-don-t-use-flush_signals-in-userspace-processes.patch b/queue-3.18/md-don-t-use-flush_signals-in-userspace-processes.patch new file mode 100644 index 00000000000..246c4935999 --- /dev/null +++ b/queue-3.18/md-don-t-use-flush_signals-in-userspace-processes.patch @@ -0,0 +1,70 @@ +From f9c79bc05a2a91f4fba8bfd653579e066714b1ec Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Wed, 7 Jun 2017 19:05:31 -0400 +Subject: md: don't use flush_signals in userspace processes + +From: Mikulas Patocka + +commit f9c79bc05a2a91f4fba8bfd653579e066714b1ec upstream. + +The function flush_signals clears all pending signals for the process. It +may be used by kernel threads when we need to prepare a kernel thread for +responding to signals. However using this function for an userspaces +processes is incorrect - clearing signals without the program expecting it +can cause misbehavior. + +The raid1 and raid5 code uses flush_signals in its request routine because +it wants to prepare for an interruptible wait. This patch drops +flush_signals and uses sigprocmask instead to block all signals (including +SIGKILL) around the schedule() call. The signals are not lost, but the +schedule() call won't respond to them. + +Signed-off-by: Mikulas Patocka +Acked-by: NeilBrown +Signed-off-by: Shaohua Li +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/raid1.c | 5 ++++- + drivers/md/raid5.c | 5 ++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1120,13 +1120,16 @@ static void make_request(struct mddev *m + */ + DEFINE_WAIT(w); + for (;;) { +- flush_signals(current); ++ sigset_t full, old; + prepare_to_wait(&conf->wait_barrier, + &w, TASK_INTERRUPTIBLE); + if (bio_end_sector(bio) <= mddev->suspend_lo || + bio->bi_iter.bi_sector >= mddev->suspend_hi) + break; ++ sigfillset(&full); ++ sigprocmask(SIG_BLOCK, &full, &old); + schedule(); ++ sigprocmask(SIG_SETMASK, &old, NULL); + } + finish_wait(&conf->wait_barrier, &w); + } +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -4705,12 +4705,15 @@ static void make_request(struct mddev *m + * userspace, we want an interruptible + * wait. + */ +- flush_signals(current); + prepare_to_wait(&conf->wait_for_overlap, + &w, TASK_INTERRUPTIBLE); + if (logical_sector >= mddev->suspend_lo && + logical_sector < mddev->suspend_hi) { ++ sigset_t full, old; ++ sigfillset(&full); ++ sigprocmask(SIG_BLOCK, &full, &old); + schedule(); ++ sigprocmask(SIG_SETMASK, &old, NULL); + do_prepare = true; + } + goto retry; diff --git a/queue-3.18/pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch b/queue-3.18/pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch new file mode 100644 index 00000000000..6c4baf6c566 --- /dev/null +++ b/queue-3.18/pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch @@ -0,0 +1,93 @@ +From e60514bd4485c0c7c5a7cf779b200ce0b95c70d6 Mon Sep 17 00:00:00 2001 +From: Chen Yu +Date: Thu, 25 May 2017 16:49:07 +0800 +Subject: PCI/PM: Restore the status of PCI devices across hibernation + +From: Chen Yu + +commit e60514bd4485c0c7c5a7cf779b200ce0b95c70d6 upstream. + +Currently we saw a lot of "No irq handler" errors during hibernation, which +caused the system hang finally: + + ata4.00: qc timeout (cmd 0xec) + ata4.00: failed to IDENTIFY (I/O error, err_mask=0x4) + ata4.00: revalidation failed (errno=-5) + ata4: SATA link up 6.0 Gbps (SStatus 133 SControl 300) + do_IRQ: 31.151 No irq handler for vector + +According to above logs, there is an interrupt triggered and it is +dispatched to CPU31 with a vector number 151, but there is no handler for +it, thus this IRQ will not get acked and will cause an IRQ flood which +kills the system. To be more specific, the 31.151 is an interrupt from the +AHCI host controller. + +After some investigation, the reason why this issue is triggered is because +the thaw_noirq() function does not restore the MSI/MSI-X settings across +hibernation. + +The scenario is illustrated below: + + 1. Before hibernation, IRQ 34 is the handler for the AHCI device, which + is bound to CPU31. + + 2. Hibernation starts, the AHCI device is put into low power state. + + 3. All the nonboot CPUs are put offline, so IRQ 34 has to be migrated to + the last alive one - CPU0. + + 4. After the snapshot has been created, all the nonboot CPUs are brought + up again; IRQ 34 remains bound to CPU0. + + 5. AHCI devices are put into D0. + + 6. The snapshot is written to the disk. + +The issue is triggered in step 6. The AHCI interrupt should be delivered +to CPU0, however it is delivered to the original CPU31 instead, which +causes the "No irq handler" issue. + +Ying Huang has provided a clue that, in step 3 it is possible that writing +to the register might not take effect as the PCI devices have been +suspended. + +In step 3, the IRQ 34 affinity should be modified from CPU31 to CPU0, but +in fact it is not. In __pci_write_msi_msg(), if the device is already in +low power state, the low level MSI message entry will not be updated but +cached. During the device restore process after a normal suspend/resume, +pci_restore_msi_state() writes the cached MSI back to the hardware. + +But this is not the case for hibernation. pci_restore_msi_state() is not +currently called in pci_pm_thaw_noirq(), although pci_save_state() has +saved the necessary PCI cached information in pci_pm_freeze_noirq(). + +Restore the PCI status for the device during hibernation. Otherwise the +status might be lost across hibernation (for example, settings for MSI, +MSI-X, ATS, ACS, IOV, etc.), which might cause problems during hibernation. + +Suggested-by: Ying Huang +Suggested-by: Rafael J. Wysocki +Signed-off-by: Chen Yu +[bhelgaas: changelog] +Signed-off-by: Bjorn Helgaas +Reviewed-by: Rafael J. Wysocki +Cc: Len Brown +Cc: Dan Williams +Cc: Rui Zhang +Cc: Ying Huang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/pci-driver.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -925,6 +925,7 @@ static int pci_pm_thaw_noirq(struct devi + return pci_legacy_resume_early(dev); + + pci_update_current_state(pci_dev, PCI_D0); ++ pci_restore_state(pci_dev); + + if (drv && drv->pm && drv->pm->thaw_noirq) + error = drv->pm->thaw_noirq(dev); diff --git a/queue-3.18/series b/queue-3.18/series index 1f73e9e9b0b..904faa2b93a 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -20,3 +20,11 @@ powerpc-64-fix-atomic64_inc_not_zero-to-return-an-int.patch powerpc-fix-emulation-of-mcrf-in-emulate_step.patch powerpc-fix-emulation-of-mfocrf-in-emulate_step.patch powerpc-asm-mark-cr0-as-clobbered-in-mftb.patch +af_key-fix-sadb_x_ipsecrequest-parsing.patch +pci-pm-restore-the-status-of-pci-devices-across-hibernation.patch +xhci-fix-20000ms-port-resume-timeout.patch +xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch +usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch +usb-cdc-acm-add-device-id-for-quirky-printer.patch +usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch +md-don-t-use-flush_signals-in-userspace-processes.patch diff --git a/queue-3.18/usb-cdc-acm-add-device-id-for-quirky-printer.patch b/queue-3.18/usb-cdc-acm-add-device-id-for-quirky-printer.patch new file mode 100644 index 00000000000..6d14f2885d1 --- /dev/null +++ b/queue-3.18/usb-cdc-acm-add-device-id-for-quirky-printer.patch @@ -0,0 +1,33 @@ +From fe855789d605590e57f9cd968d85ecce46f5c3fd Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Wed, 12 Jul 2017 15:08:39 +0200 +Subject: USB: cdc-acm: add device-id for quirky printer + +From: Johan Hovold + +commit fe855789d605590e57f9cd968d85ecce46f5c3fd upstream. + +Add device-id entry for DATECS FP-2000 fiscal printer needing the +NO_UNION_NORMAL quirk. + +Reported-by: Anton Avramov +Signed-off-by: Johan Hovold +Acked-by: Oliver Neukum +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/class/cdc-acm.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1776,6 +1776,9 @@ static const struct usb_device_id acm_id + { USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */ + .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ + }, ++ { USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */ ++ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ ++ }, + + { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */ + .driver_info = CLEAR_HALT_CONDITIONS, diff --git a/queue-3.18/usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch b/queue-3.18/usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch new file mode 100644 index 00000000000..b77b25fd154 --- /dev/null +++ b/queue-3.18/usb-renesas_usbhs-fix-usbhsc_resume-for-usbhsf_runtime_pwctrl.patch @@ -0,0 +1,37 @@ +From 59a0879a0e17b2e43ecdc5e3299da85b8410d7ce Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda +Date: Wed, 19 Jul 2017 16:16:54 +0900 +Subject: usb: renesas_usbhs: fix usbhsc_resume() for !USBHSF_RUNTIME_PWCTRL + +From: Yoshihiro Shimoda + +commit 59a0879a0e17b2e43ecdc5e3299da85b8410d7ce upstream. + +This patch fixes an issue that some registers may be not initialized +after resume if the USBHSF_RUNTIME_PWCTRL is not set. Otherwise, +if a cable is not connected, the driver will not enable INTENB0.VBSE +after resume. And then, the driver cannot detect the VBUS. + +Fixes: ca8a282a5373 ("usb: gadget: renesas_usbhs: add suspend/resume support") +Signed-off-by: Yoshihiro Shimoda +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/renesas_usbhs/common.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/renesas_usbhs/common.c ++++ b/drivers/usb/renesas_usbhs/common.c +@@ -699,8 +699,10 @@ static int usbhsc_resume(struct device * + struct usbhs_priv *priv = dev_get_drvdata(dev); + struct platform_device *pdev = usbhs_priv_to_pdev(priv); + +- if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) ++ if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) { + usbhsc_power_ctrl(priv, 1); ++ usbhs_mod_autonomy_mode(priv); ++ } + + usbhs_platform_call(priv, phy_reset, pdev); + diff --git a/queue-3.18/usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch b/queue-3.18/usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch new file mode 100644 index 00000000000..707b9130734 --- /dev/null +++ b/queue-3.18/usb-storage-return-on-error-to-avoid-a-null-pointer-dereference.patch @@ -0,0 +1,44 @@ +From 446230f52a5bef593554510302465eabab45a372 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Thu, 6 Jul 2017 16:06:32 +0100 +Subject: usb: storage: return on error to avoid a null pointer dereference + +From: Colin Ian King + +commit 446230f52a5bef593554510302465eabab45a372 upstream. + +When us->extra is null the driver is not initialized, however, a +later call to osd200_scsi_to_ata is made that dereferences +us->extra, causing a null pointer dereference. The code +currently detects and reports that the driver is not initialized; +add a return to avoid the subsequent dereference issue in this +check. + +Thanks to Alan Stern for pointing out that srb->result needs setting +to DID_ERROR << 16 + +Detected by CoverityScan, CID#100308 ("Dereference after null check") + +Signed-off-by: Colin Ian King +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/storage/isd200.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/usb/storage/isd200.c ++++ b/drivers/usb/storage/isd200.c +@@ -1522,8 +1522,11 @@ static void isd200_ata_command(struct sc + + /* Make sure driver was initialized */ + +- if (us->extra == NULL) ++ if (us->extra == NULL) { + usb_stor_dbg(us, "ERROR Driver not initialized\n"); ++ srb->result = DID_ERROR << 16; ++ return; ++ } + + scsi_set_resid(srb, 0); + /* scsi_bufflen might change in protocol translation to ata */ diff --git a/queue-3.18/xhci-fix-20000ms-port-resume-timeout.patch b/queue-3.18/xhci-fix-20000ms-port-resume-timeout.patch new file mode 100644 index 00000000000..f0393e7b49f --- /dev/null +++ b/queue-3.18/xhci-fix-20000ms-port-resume-timeout.patch @@ -0,0 +1,41 @@ +From a54408d0a004757789863d74e29c2297edae0b4d Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Thu, 20 Jul 2017 14:48:29 +0300 +Subject: xhci: fix 20000ms port resume timeout + +From: Mathias Nyman + +commit a54408d0a004757789863d74e29c2297edae0b4d upstream. + +A uncleared PLC (port link change) bit will prevent furuther port event +interrupts for that port. Leaving it uncleared caused get_port_status() +to timeout after 20000ms while waiting to get the final port event +interrupt for resume -> U0 state change. + +This is a targeted fix for a specific case where we get a port resume event +racing with xhci resume. The port event interrupt handler notices xHC is +not yet running and bails out early, leaving PLC uncleared. + +The whole xhci port resuming needs more attention, but while working on it +it anyways makes sense to always ensure PLC is cleared in get_port_status +before setting a new link state and waiting for its completion. + +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-hub.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -651,6 +651,9 @@ static u32 xhci_get_port_status(struct u + clear_bit(wIndex, &bus_state->resuming_ports); + + set_bit(wIndex, &bus_state->rexit_ports); ++ ++ xhci_test_and_clear_bit(xhci, port_array, wIndex, ++ PORT_PLC); + xhci_set_link_state(xhci, port_array, wIndex, + XDEV_U0); + diff --git a/queue-3.18/xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch b/queue-3.18/xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch new file mode 100644 index 00000000000..5f856259131 --- /dev/null +++ b/queue-3.18/xhci-fix-null-pointer-dereference-when-cleaning-up-streams-for-removed-host.patch @@ -0,0 +1,51 @@ +From 4b895868bb2da60a386a17cde3bf9ecbc70c79f4 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Thu, 20 Jul 2017 14:48:26 +0300 +Subject: xhci: Fix NULL pointer dereference when cleaning up streams for removed host + +From: Mathias Nyman + +commit 4b895868bb2da60a386a17cde3bf9ecbc70c79f4 upstream. + +This off by one in stream_id indexing caused NULL pointer dereference and +soft lockup on machines with USB attached SCSI devices connected to a +hotpluggable xhci controller. + +The code that cleans up pending URBs for dead hosts tried to dereference +a stream ring at the invalid stream_id 0. +ep->stream_info->stream_rings[0] doesn't point to a ring. + +Start looping stream_id from 1 like in all the other places in the driver, +and check that the ring exists before trying to kill URBs on it. + +Reported-by: rocko r +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-ring.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -782,13 +782,16 @@ static void xhci_kill_endpoint_urbs(stru + (ep->ep_state & EP_GETTING_NO_STREAMS)) { + int stream_id; + +- for (stream_id = 0; stream_id < ep->stream_info->num_streams; ++ for (stream_id = 1; stream_id < ep->stream_info->num_streams; + stream_id++) { ++ ring = ep->stream_info->stream_rings[stream_id]; ++ if (!ring) ++ continue; ++ + xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, + "Killing URBs for slot ID %u, ep index %u, stream %u", +- slot_id, ep_index, stream_id + 1); +- xhci_kill_ring_urbs(xhci, +- ep->stream_info->stream_rings[stream_id]); ++ slot_id, ep_index, stream_id); ++ xhci_kill_ring_urbs(xhci, ring); + } + } else { + ring = ep->ring; -- 2.47.3