USB: usbip: fix potential out-of-bounds write
[pandora-kernel.git] / drivers / staging / usbip / usbip_common.c
index 3b7a847..4fbef0c 100644 (file)
@@ -761,26 +761,25 @@ EXPORT_SYMBOL_GPL(usbip_recv_iso);
  * buffer and iso packets need to be stored and be in propeper endian in urb
  * before calling this function
  */
-int usbip_pad_iso(struct usbip_device *ud, struct urb *urb)
+void usbip_pad_iso(struct usbip_device *ud, struct urb *urb)
 {
        int np = urb->number_of_packets;
        int i;
-       int ret;
        int actualoffset = urb->actual_length;
 
        if (!usb_pipeisoc(urb->pipe))
-               return 0;
+               return;
 
        /* if no packets or length of data is 0, then nothing to unpack */
        if (np == 0 || urb->actual_length == 0)
-               return 0;
+               return;
 
        /*
         * if actual_length is transfer_buffer_length then no padding is
         * present.
        */
        if (urb->actual_length == urb->transfer_buffer_length)
-               return 0;
+               return;
 
        /*
         * loop over all packets from last to first (to prevent overwritting
@@ -792,8 +791,6 @@ int usbip_pad_iso(struct usbip_device *ud, struct urb *urb)
                        urb->transfer_buffer + actualoffset,
                        urb->iso_frame_desc[i].actual_length);
        }
-
-       return ret;
 }
 EXPORT_SYMBOL_GPL(usbip_pad_iso);
 
@@ -823,6 +820,17 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
        if (!(size > 0))
                return 0;
 
+       if (size > urb->transfer_buffer_length) {
+               /* should not happen, probably malicious packet */
+               if (ud->side == USBIP_STUB) {
+                       usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+                       return 0;
+               } else {
+                       usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+                       return -EPIPE;
+               }
+       }
+
        ret = usbip_xmit(0, ud->tcp_socket, (char *)urb->transfer_buffer,
                         size, 0);
        if (ret != size) {