net: cdc_ncm: only the control intf can be probed
[deliverable/linux.git] / drivers / net / usb / cdc_ncm.c
index b8de8ddd6d98fa1c19ea254d9c9363cea5e6d1cd..5aa3e60851d0f76a0092c6edba9f7e3ff91ce9e7 100644 (file)
@@ -372,6 +372,7 @@ static const struct ethtool_ops cdc_ncm_ethtool_ops = {
 
 int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting)
 {
+       const struct usb_cdc_union_desc *union_desc = NULL;
        struct cdc_ncm_ctx *ctx;
        struct usb_driver *driver;
        u8 *buf;
@@ -393,6 +394,9 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
        /* store ctx pointer in device data field */
        dev->data[0] = (unsigned long)ctx;
 
+       /* only the control interface can be successfully probed */
+       ctx->control = intf;
+
        /* get some pointers */
        driver = driver_of(intf);
        buf = intf->cur_altsetting->extra;
@@ -406,16 +410,16 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
 
                switch (buf[2]) {
                case USB_CDC_UNION_TYPE:
-                       if (buf[0] < sizeof(*(ctx->union_desc)))
+                       if (buf[0] < sizeof(*union_desc))
                                break;
 
-                       ctx->union_desc =
-                                       (const struct usb_cdc_union_desc *)buf;
-
-                       ctx->control = usb_ifnum_to_if(dev->udev,
-                                       ctx->union_desc->bMasterInterface0);
+                       union_desc = (const struct usb_cdc_union_desc *)buf;
+                       /* the master must be the interface we are probing */
+                       if (intf->cur_altsetting->desc.bInterfaceNumber !=
+                           union_desc->bMasterInterface0)
+                               goto error;
                        ctx->data = usb_ifnum_to_if(dev->udev,
-                                       ctx->union_desc->bSlaveInterface0);
+                                                   union_desc->bSlaveInterface0);
                        break;
 
                case USB_CDC_ETHERNET_TYPE:
@@ -458,15 +462,13 @@ advance:
        }
 
        /* some buggy devices have an IAD but no CDC Union */
-       if (!ctx->union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) {
-               ctx->control = intf;
+       if (!union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) {
                ctx->data = usb_ifnum_to_if(dev->udev, intf->cur_altsetting->desc.bInterfaceNumber + 1);
                dev_dbg(&intf->dev, "CDC Union missing - got slave from IAD\n");
        }
 
        /* check if we got everything */
-       if ((ctx->control == NULL) || (ctx->data == NULL) ||
-           ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf))))
+       if (!ctx->data || (!ctx->mbim_desc && !ctx->ether_desc))
                goto error;
 
        /* claim data interface, if different from control */
This page took 0.026694 seconds and 5 git commands to generate.