Patch (2.4.6) for my Dimage Camera

Hello,

I've recently got an USB Konica Minolta Dimage X21 camera. When I
plugged this camera I got the following errors:

Jun  9 09:11:56 snoopy kernel: hub.c: new USB device 00:1d.0-1, assigned address 2
Jun  9 09:11:56 snoopy kernel: usb.c: invalid descriptor length of 1
Jun  9 09:11:56 snoopy kernel: usb.c: unable to get device 2 configuration (error=-22)
Jun  9 09:11:57 snoopy kernel: hub.c: new USB device 00:1d.0-1, assigned address 3
Jun  9 09:11:57 snoopy kernel: usb.c: invalid descriptor length of 0
Jun  9 09:11:57 snoopy kernel: usb.c: unable to get device 3 configuration (error=-22)

with a 2.4.26 kernel. I take a look at the code.  The problem arises
at the "end of the end" of the configuration parsing. In usb.c
(usb_parse_endpoint) the size variable became negative.  It seems that
the camera gives erroneous information to the usb module: either the
size of the "configuration buffer" is to big or the bLenght of a
"Class Specific or Vendor Specific descriptors" is invalid. Any way
what happened with my camera is that at 

usb.c line 1329:        size -= header->bLength;

size became negative when usb.c parsed the _last_ endpoint (after the
code skipped one or two (I forgot) Class Specific or Vendor Specific
descriptors).

By the way, as the "while test" compare size which is an int to a
size_t value, on my machine, the while loop continue until it found an
"invalid descriptor length" :o/. So it seems to me that some safety
check should be done in the 3 while loops which skip and save the "Class
Specific or Vendor Specific descriptors".

I propose a simple fix (patch against 2.4.26 attached): If size become
negative a configuration error is generated, but if this happen when
you parse the last end point (so that my camera can be recognized by
Linux).

Ok, the attached patch is a quick hack, but if you are not happy
with it I'm sure that you, usb developers, will found the right
solution.

Thanks for the usb support, Olivier Chapuis


PS:
- please cc I'm not subscribed to the list.
- I take a look to the 2.6 code (usb/core/config.c) and I do not
think that my camera will be recognized by a 2.6 kernel ... sorry
no patch.
- If I well understand the "manual", size_t (the "return" type of
sizeof) is either unsigned int or unsigned long int. If you compare an
int and an unsigned int you can get some surprising result this is not
the case if you compare an int and an unsigned long int.  It seems
that on my machine the type of size_t is unsigned int. I generally do
not care about such details as I never compare a signed and an
unsigned int so maybe I miss something.
--- drivers/usb/usb.c.orig      2004-06-12 08:19:28.000000000 +0200
+++ drivers/usb/usb.c   2004-06-12 08:21:54.000000000 +0200
@@ -1306,7 +1306,7 @@
        /*  descriptors */
        begin = buffer;
        numskipped = 0;
-       while (size >= sizeof(struct usb_descriptor_header)) {
+       while (size > 0 && size >= sizeof(struct usb_descriptor_header)) {
                header = (struct usb_descriptor_header *)buffer;
 
                if (header->bLength < 2) {
@@ -1327,6 +1327,9 @@
 
                buffer += header->bLength;
                size -= header->bLength;
+               /* if size is negative (it should not but ...) either we
+                * currently parse the last endpoint and we will accept the
+                * configuration or an error is generated later */
                parsed += header->bLength;
        }
        if (numskipped)
@@ -1432,6 +1435,11 @@
                        buffer += header->bLength;
                        parsed += header->bLength;
                        size -= header->bLength;
+                       if (size < 0)
+                       {
+                               err("ran out of descriptors parsing");
+                               return -1;
+                       }
                }
 
                if (numskipped)
@@ -1566,6 +1574,11 @@
 
                        buffer += header->bLength;
                        size -= header->bLength;
+                       if (size < 0)
+                       {
+                               err("ran out of descriptors parsing");
+                               return -1;
+                       }
                }
                if (numskipped)
                        dbg("skipped %d class/vendor specific endpoint descriptors", 
numskipped);
@@ -1596,6 +1609,11 @@
                buffer += retval;
                size -= retval;
        }
+       if (size < 0)
+       {
+               warn("ran out of parsing data at end of config, bypass!");
+               size = 0;
+       }
 
        return size;
 }

Reply via email to