summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/usbip/stub_rx.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
index c6022602749e..3e9d46358dde 100644
--- a/drivers/staging/usbip/stub_rx.c
+++ b/drivers/staging/usbip/stub_rx.c
@@ -424,6 +424,60 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir)
return 0;
}
+static void masking_bogus_flags(struct urb *urb)
+{
+ int xfertype;
+ struct usb_device *dev;
+ struct usb_host_endpoint *ep;
+ int is_out;
+ unsigned int allowed;
+
+ if (!urb || urb->hcpriv || !urb->complete)
+ return;
+ dev = urb->dev;
+ if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
+ return;
+
+ ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out)
+ [usb_pipeendpoint(urb->pipe)];
+ if (!ep)
+ return;
+
+ xfertype = usb_endpoint_type(&ep->desc);
+ if (xfertype == USB_ENDPOINT_XFER_CONTROL) {
+ struct usb_ctrlrequest *setup =
+ (struct usb_ctrlrequest *) urb->setup_packet;
+
+ if (!setup)
+ return;
+ is_out = !(setup->bRequestType & USB_DIR_IN) ||
+ !setup->wLength;
+ } else {
+ is_out = usb_endpoint_dir_out(&ep->desc);
+ }
+
+ /* enforce simple/standard policy */
+ allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
+ URB_NO_INTERRUPT | URB_DIR_MASK | URB_FREE_BUFFER);
+ switch (xfertype) {
+ case USB_ENDPOINT_XFER_BULK:
+ if (is_out)
+ allowed |= URB_ZERO_PACKET;
+ /* FALLTHROUGH */
+ case USB_ENDPOINT_XFER_CONTROL:
+ allowed |= URB_NO_FSBR; /* only affects UHCI */
+ /* FALLTHROUGH */
+ default: /* all non-iso endpoints */
+ if (!is_out)
+ allowed |= URB_SHORT_NOT_OK;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ allowed |= URB_ISO_ASAP;
+ break;
+ }
+ urb->transfer_flags &= allowed;
+}
+
static void stub_recv_cmd_submit(struct stub_device *sdev,
struct usbip_header *pdu)
{
@@ -490,6 +544,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
/* no need to submit an intercepted request, but harmless? */
tweak_special_requests(priv->urb);
+ masking_bogus_flags(priv->urb);
/* urb is now ready to submit */
ret = usb_submit_urb(priv->urb, GFP_KERNEL);