aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2009-12-11 16:20:20 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-02 17:53:07 -0500
commitf661c6f8c67bd55e93348f160d590ff9edf08904 (patch)
tree9b5abdda44f9bfb0b6a6dcb51217701a67ed40a0
parenta91b0c502285fd0c569fae1222fdd945ef739233 (diff)
USB: check the endpoint type against the pipe type
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>
-rw-r--r--Documentation/usb/error-codes.txt6
-rw-r--r--drivers/usb/core/devio.c22
-rw-r--r--drivers/usb/core/urb.c7
3 files changed, 24 insertions, 11 deletions
diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
index 9cf83e8c27b8..d83703ea74b2 100644
--- a/Documentation/usb/error-codes.txt
+++ b/Documentation/usb/error-codes.txt
@@ -41,8 +41,8 @@ USB-specific:
41 41
42-EFBIG Host controller driver can't schedule that many ISO frames. 42-EFBIG Host controller driver can't schedule that many ISO frames.
43 43
44-EPIPE Specified endpoint is stalled. For non-control endpoints, 44-EPIPE The pipe type specified in the URB doesn't match the
45 reset this status with usb_clear_halt(). 45 endpoint's actual type.
46 46
47-EMSGSIZE (a) endpoint maxpacket size is zero; it is not usable 47-EMSGSIZE (a) endpoint maxpacket size is zero; it is not usable
48 in the current interface altsetting. 48 in the current interface altsetting.
@@ -60,6 +60,8 @@ USB-specific:
60 60
61-EHOSTUNREACH URB was rejected because the device is suspended. 61-EHOSTUNREACH URB was rejected because the device is suspended.
62 62
63-ENOEXEC A control URB doesn't contain a Setup packet.
64
63 65
64************************************************************************** 66**************************************************************************
65* Error codes returned by in urb->status * 67* Error codes returned by in urb->status *
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index a678186f218f..431d17287a86 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1104,13 +1104,25 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
1104 case USB_ENDPOINT_XFER_CONTROL: 1104 case USB_ENDPOINT_XFER_CONTROL:
1105 case USB_ENDPOINT_XFER_ISOC: 1105 case USB_ENDPOINT_XFER_ISOC:
1106 return -EINVAL; 1106 return -EINVAL;
1107 /* allow single-shot interrupt transfers, at bogus rates */ 1107 case USB_ENDPOINT_XFER_INT:
1108 /* allow single-shot interrupt transfers */
1109 uurb->type = USBDEVFS_URB_TYPE_INTERRUPT;
1110 goto interrupt_urb;
1108 } 1111 }
1109 uurb->number_of_packets = 0; 1112 uurb->number_of_packets = 0;
1110 if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) 1113 if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
1111 return -EINVAL; 1114 return -EINVAL;
1112 break; 1115 break;
1113 1116
1117 case USBDEVFS_URB_TYPE_INTERRUPT:
1118 if (!usb_endpoint_xfer_int(&ep->desc))
1119 return -EINVAL;
1120 interrupt_urb:
1121 uurb->number_of_packets = 0;
1122 if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
1123 return -EINVAL;
1124 break;
1125
1114 case USBDEVFS_URB_TYPE_ISO: 1126 case USBDEVFS_URB_TYPE_ISO:
1115 /* arbitrary limit */ 1127 /* arbitrary limit */
1116 if (uurb->number_of_packets < 1 || 1128 if (uurb->number_of_packets < 1 ||
@@ -1143,14 +1155,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
1143 uurb->buffer_length = totlen; 1155 uurb->buffer_length = totlen;
1144 break; 1156 break;
1145 1157
1146 case USBDEVFS_URB_TYPE_INTERRUPT:
1147 uurb->number_of_packets = 0;
1148 if (!usb_endpoint_xfer_int(&ep->desc))
1149 return -EINVAL;
1150 if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
1151 return -EINVAL;
1152 break;
1153
1154 default: 1158 default:
1155 return -EINVAL; 1159 return -EINVAL;
1156 } 1160 }
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index e7cae1334693..e2bd153cbd89 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -387,6 +387,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
387 { 387 {
388 unsigned int orig_flags = urb->transfer_flags; 388 unsigned int orig_flags = urb->transfer_flags;
389 unsigned int allowed; 389 unsigned int allowed;
390 static int pipetypes[4] = {
391 PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
392 };
393
394 /* Check that the pipe's type matches the endpoint's type */
395 if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
396 return -EPIPE; /* The most suitable error code :-) */
390 397
391 /* enforce simple/standard policy */ 398 /* enforce simple/standard policy */
392 allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | 399 allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |