[PATCH] xhci: Detect out-of-bounds access to usb2_ports

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Out-of-bounds access was triggered on a Thinkpad Yoga during suspend or
by rmmod'ing the xhci-pci module, sometimes leading to a general
protection fault.

This is a defensive symptom fix; the error proper must occur somewhere
else, eg. when the udev with its portnum is left lingering around even
after the xhci struct has its num_usb2_ports reduced to zero, or maybe
when the udev is assigned to the wrong xhci. Anyway, this keeps nasty
crashes from happening in hard to debug situations (during suspend, not
even kdump could provide an error message).


Signed-off-by: Christian M. Amsüss <chrysn@xxxxxxxx>
---

On Mon, Dec 14, 2015 at 07:42:54PM +0100, chrysn wrote:
> [1.] One line summary of the problem:
> 
> general_protection when rmmod'ing xhci-pci

Some other observations around the issue: 

* rmmod'ing/modprobing xhci-pci is just a more convenient way of
  reproducing the issue; the problematic code section is being passed
  through on suspends as well (I placed debug messages there and
  observed them during suspend), I just seem never to have managed to
  get a kdump of such a situation / was always stuck with a black screen
  and dead device. The issue is more easily reproducible when the device
  is under any kind of load; a plain rmmod/modprobe loop with some sleep
  inbetween often does not trigger the issue, because while the
  out-of-bounds access still occurs, the addresses involved haven't
  changed, and there are still sufficiently valid pointers around for no
  general protection error to occur. Restarting a postgresql server in
  an endless loop in another terminal speeds up testing.

* This a symptom fix; I probably won't look deeper on my own, but would
  be happy to provide more details or test patches on the machine this
  occurs on.

 drivers/usb/host/xhci.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index d51ee0c..3c1f1f3 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4171,6 +4171,12 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
 
 	port_array = xhci->usb2_ports;
 	port_num = udev->portnum - 1;
+	if (port_num >= xhci->num_usb2_ports) {
+		dev_warn(&udev->dev, "%s: udev portnum exceeds num_usb2_ports, pretending there is no power management.\n",
+				__func__);
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		return 0;
+	}
 	pm_addr = port_array[port_num] + PORTPMSC;
 	pm_val = readl(pm_addr);
 	hlpm_addr = port_array[port_num] + PORTHLPMC;
-- 
2.8.0.rc3

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux