USB: check the endpoint type against the pipe type
authorAlan Stern <stern@rowland.harvard.edu>
Fri, 11 Dec 2009 21:20:20 +0000 (16:20 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 2 Mar 2010 22:53:07 +0000 (14:53 -0800)
This patch (as1316) adds some error checking to usb_submit_urb().
It's conditional on CONFIG_USB_DEBUG, so it won't affect normal users.
The new check makes sure that the actual type of the endpoint
described by urb->pipe agrees with the type encoded in the pipe value.

The USB error code documentation is updated to include the code
returned by the new check, and the usbfs SUBMITURB handler is updated
to use the correct pipe type when legacy user code tries to submit a
bulk transfer to an interrupt endpoint.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Documentation/usb/error-codes.txt
drivers/usb/core/devio.c
drivers/usb/core/urb.c

index 9cf83e8c27b8f94208d7ad0ebc4587d82430164d..d83703ea74b21285fbe6fea9eff1d00753eb51e0 100644 (file)
@@ -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 a678186f218fa84dc8b5fadcb8b196ff54898b06..431d17287a86fdad7581b55a4f3be4e860143594 100644 (file)
@@ -1104,13 +1104,25 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                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)
                        return -EINVAL;
                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;
+               break;
+
        case USBDEVFS_URB_TYPE_ISO:
                /* arbitrary limit */
                if (uurb->number_of_packets < 1 ||
@@ -1143,14 +1155,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                uurb->buffer_length = totlen;
                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;
-               break;
-
        default:
                return -EINVAL;
        }
index e7cae1334693cf6a88327c331104411ce8092880..e2bd153cbd89151afb935ab2c4a76cf4261e30c9 100644 (file)
@@ -387,6 +387,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
        {
        unsigned int    orig_flags = urb->transfer_flags;
        unsigned int    allowed;
+       static int pipetypes[4] = {
+               PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
+       };
+
+       /* Check that the pipe's type matches the endpoint's type */
+       if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+               return -EPIPE;          /* The most suitable error code :-) */
 
        /* enforce simple/standard policy */
        allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |