Staging: usbip: Filtering illegal flags from remote driver
authorEndre Kollar <taxy443@gmail.com>
Tue, 27 Jul 2010 10:40:00 +0000 (12:40 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 27 Jul 2010 18:08:31 +0000 (11:08 -0700)
The usb_submit_urb function in debug mode monitors the bogus flags. The
client driver errors should not be conveyed to the local USB device.

Signed-off-by: Endre Kollar <taxy443@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/usbip/stub_rx.c

index c602260..3e9d463 100644 (file)
@@ -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);