lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <Pine.LNX.4.44L0.0912101525230.2680-100000@iolanthe.rowland.org>
Date:	Thu, 10 Dec 2009 15:38:35 -0500 (EST)
From:	Alan Stern <stern@...land.harvard.edu>
To:	Ondrej Zary <linux@...nbow-software.org>
cc:	linux-usb@...r.kernel.org, <linux-kernel@...r.kernel.org>
Subject: Re: debugging oops after disconnecting Nexio USB touchscreen

On Thu, 10 Dec 2009, Ondrej Zary wrote:

> Narrowed down the code to this 170-line module which reproduces my
> "rmmod usbtouchscreen" problem. Loading this module causes EHCI to fail.
> Looks like it fails after calling usb_kill_urb(). Can a buggy device cause
> this?

I don't think so.  But I am getting an idea of what the problem might 
be.  Try applying the patch below and see if it makes any difference 
(make sure that CONFIG_USB_DEBUG is enabled).

If the module stops messing up EHCI, try changing the source code:

> static int crashnexio_probe(struct usb_interface *intf,
> 			  const struct usb_device_id *id)
> {

...

> 	interface = intf->cur_altsetting;
> 	/* find first input endpoint */
> 	for (i = 0; i < interface->desc.bNumEndpoints; i++)
> 		if (usb_endpoint_dir_in(&interface->endpoint[i].desc)) {
> 			endpoint = &interface->endpoint[i].desc;
> 			break;
> 		}

Does the interface have more than one input endpoint?  (What does
"lsusb -v" show for the Nexio?)  If it does, how do you know the 
endpoint you want is the first one?

...

> 	usb_fill_bulk_urb(crashnexio->irq, udev,
> 			 usb_rcvintpipe(udev, endpoint->bEndpointAddress),

Either change this to usb_fill_int_urb() or else use usb_rcvbulkpipe().

...

> static int __init crashnexio_init(void)
> {
> 	return usb_register(&crashnexio_driver);
> }

You should also have an __exit routine.

Alan Stern




Index: 2.6.31/Documentation/usb/error-codes.txt
===================================================================
--- 2.6.31.orig/Documentation/usb/error-codes.txt
+++ 2.6.31/Documentation/usb/error-codes.txt
@@ -41,8 +41,8 @@ USB-specific:
 
 -EFBIG		Host controller driver can't schedule that many ISO frames.
 
--EPIPE		Specified endpoint is stalled.  For non-control endpoints,
-		reset this status with usb_clear_halt().
+-EPIPE		The pipe type specified in the URB doesn't match the
+		endpoint's actual type.
 
 -EMSGSIZE	(a) endpoint maxpacket size is zero; it is not usable
 		    in the current interface altsetting.
@@ -60,6 +60,8 @@ USB-specific:
 
 -EHOSTUNREACH	URB was rejected because the device is suspended.
 
+-ENOEXEC	A control URB doesn't contain a Setup packet.
+
 
 **************************************************************************
 *                   Error codes returned by in urb->status               *
Index: 2.6.31/drivers/usb/core/devio.c
===================================================================
--- 2.6.31.orig/drivers/usb/core/devio.c
+++ 2.6.31/drivers/usb/core/devio.c
@@ -1065,7 +1065,10 @@ static int proc_do_submiturb(struct dev_
 		case USB_ENDPOINT_XFER_CONTROL:
 		case USB_ENDPOINT_XFER_ISOC:
 			return -EINVAL;
-		/* allow single-shot interrupt transfers, at bogus rates */
+		case USB_ENDPOINT_XFER_INT:
+			/* allow single-shot interrupt transfers */
+			uurb->type = USBDEVFS_URB_TYPE_INTERRUPT;
+			goto interrupt_urb;
 		}
 		uurb->number_of_packets = 0;
 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
@@ -1073,6 +1076,16 @@ static int proc_do_submiturb(struct dev_
 		snoop(&ps->dev->dev, "bulk urb\n");
 		break;
 
+	case USBDEVFS_URB_TYPE_INTERRUPT:
+		if (!usb_endpoint_xfer_int(&ep->desc))
+			return -EINVAL;
+ interrupt_urb:
+		uurb->number_of_packets = 0;
+		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+			return -EINVAL;
+		snoop(&ps->dev->dev, "interrupt urb\n");
+		break;
+
 	case USBDEVFS_URB_TYPE_ISO:
 		/* arbitrary limit */
 		if (uurb->number_of_packets < 1 ||
@@ -1105,15 +1118,6 @@ static int proc_do_submiturb(struct dev_
 		snoop(&ps->dev->dev, "iso urb\n");
 		break;
 
-	case USBDEVFS_URB_TYPE_INTERRUPT:
-		uurb->number_of_packets = 0;
-		if (!usb_endpoint_xfer_int(&ep->desc))
-			return -EINVAL;
-		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
-			return -EINVAL;
-		snoop(&ps->dev->dev, "interrupt urb\n");
-		break;
-
 	default:
 		return -EINVAL;
 	}
Index: 2.6.31/drivers/usb/core/urb.c
===================================================================
--- 2.6.31.orig/drivers/usb/core/urb.c
+++ 2.6.31/drivers/usb/core/urb.c
@@ -387,6 +387,13 @@ int usb_submit_urb(struct urb *urb, gfp_
 	{
 	unsigned int	orig_flags = urb->transfer_flags;
 	unsigned int	allowed;
+	static int pipetypes[4] = {
+		PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
+	};
+
+	/* Check that pipe's type matches the endpoint's type */
+	if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+		return -EPIPE;
 
 	/* enforce simple/standard policy */
 	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ