tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Reboot resistant USB bug



Terry Moore <tmm%mcci.com@localhost> wrote:

> Your code looks like a change to the core USB stack. You're using a
> get-descriptor failure to trigger a stuff. If I'm right about where the
> change is located, at that layer, the code has no idea if that failure might
> be expected. You're just substituting a value. You don't actually know that
> the device is the device you think it is, because you don't know if someone
> put you to sleep, and swapped devices on that port, and rebooted.

I did not post the whole patch for the sake of clarity, but it seems it was a
mistake. Please find it below.

The substituted values are chosen based on vendorId/producId obtained earlier
from the device descriptor (which fortunately does not get corrupted). If one
swaps the device, I understand the struct usbd_device on which we operate is not
the same anymore, and productId/vendorId are up to date. 

--- sys/dev/usb/FILES.orig
+++ sys/dev/usb/FILES
@@ -3,8 +3,9 @@
 FILES                  this file
 Makefile               to install .h files
 Makefile.usbdevs       to run devlist2h.awk
 TODO                   just a list of things to do
+desc_fake.c            workaround USB devices with broken descriptors
 devlist2h.awk          script to generate usbdevs*.h
 ehci.c                 Host controller driver for EHCI (just a stub now)
 ehcireg.h              Hardware definitions for EHCI (just a stub now)
 ehcivar.h              API for ehci.c
--- sys/dev/usb/files.usb.orig
+++ sys/dev/usb/files.usb
@@ -96,8 +96,9 @@
 attach usb at usbus
 file   dev/usb/usb.c                   usb                     needs-flag
 file   dev/usb/usbdi.c                 usb
 file   dev/usb/usbdi_util.c            usb
+file   dev/usb/desc_fake.c             usb
 file   dev/usb/usb_subr.c              usb
 file   dev/usb/usb_quirks.c            usb
 
 define usb_dma: usb
--- sys/dev/usb/usbdi_util.h.orig
+++ sys/dev/usb/usbdi_util.h
@@ -44,8 +44,10 @@
                                     usb_bos_descriptor_t *);
 usbd_status    usbd_get_bos_desc_full(struct usbd_device *, int, void *, int);
 usbd_status    usbd_get_device_desc(struct usbd_device *,
                                     usb_device_descriptor_t *);
+usbd_status    usbd_get_desc_fake(struct usbd_device *, int,
+                                  int, int, void *);
 usbd_status    usbd_set_address(struct usbd_device *, int);
 usbd_status    usbd_get_port_status(struct usbd_device *,
                                     int, usb_port_status_t *);
 usbd_status    usbd_get_port_status_ext(struct usbd_device *,
--- sys/dev/usb/desc_fake.c.orig
+++ sys/dev/usb/desc_fake.c
@@ -0,0 +1,145 @@
+#include <sys/types.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbhist.h>
+ 
+#define DPRINTF(FMT,A,B,C,D)    USBHIST_LOG(usbdebug,FMT,A,B,C,D)
+#define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(usbdebug,N,FMT,A,B,C,D)
+
+struct desc_fake {
+       uint16_t idVendor;
+       uint16_t idProduct;
+       const usb_descriptor_t **desc;
+};
+
+#define _USETW(w) { (w) & 0x00ff, ((w) & 0xff00) >> 8 }
+
+/*
+ * NXP PN533 NFC chip
+ */
+
+static const usb_endpoint_descriptor_t desc_ep_pn533_in = {
+       /* bLength */           sizeof(desc_ep_pn533_in),
+       /* bDescriptorType */   UDESC_ENDPOINT,
+       /* bEndpointAddress */  UE_DIR_IN | 0x04,
+       /* bmAttributes */      UE_BULK,
+       /* wMaxPacketSize */    _USETW(0x0040),
+       /* bInterval */         0x04, /* 255ms */
+};
+
+static const usb_endpoint_descriptor_t desc_ep_pn533_out = {
+       /* bLength */           sizeof(desc_ep_pn533_in),
+       /* bDescriptorType */   UDESC_ENDPOINT,
+       /* bEndpointAddress */  UE_DIR_OUT | 0x04,
+       /* bmAttributes */      UE_BULK,
+       /* wMaxPacketSize */    _USETW(0x0040),
+       /* bInterval */         0x04, /* 255ms */
+};
+
+static const usb_interface_descriptor_t desc_iface_pn533 = {
+       /* bLength */            sizeof(desc_iface_pn533),
+       /* bDescriptorType */    UDESC_INTERFACE,
+       /* bInterfaceNumber */   0,
+       /* bAlternateSetting */  0,
+       /* bNumEndpoints */      2,
+       /* bInterfaceClass */    0xff,
+       /* bInterfaceSubClass */ 0xff,
+       /* bInterfaceProtocol */ 0xff,
+       /* iInterface */         0,
+};
+
+static const usb_config_descriptor_t desc_conf_pn533 = {
+       /* bLength */            sizeof(desc_conf_pn533),
+       /* bDescriptorType */    UDESC_CONFIG,
+       /* wTotalLength  */      _USETW(sizeof(desc_conf_pn533) +
+                                       sizeof(desc_iface_pn533) +
+                                       sizeof(desc_ep_pn533_in) +
+                                       sizeof(desc_ep_pn533_out)
+                                ),
+       /* bNumInterfac */       1,
+       /* bConfigurationValue */1,
+       /* iConfiguration */     0,
+       /* bmAttributes */       UC_ATTR_MBO,
+       /* bMaxPower */          0x32, /* 100mA */
+};
+
+static const usb_descriptor_t *desc_pn533[] = {
+       (const usb_descriptor_t *)&desc_conf_pn533,
+       (const usb_descriptor_t *)&desc_iface_pn533,
+       (const usb_descriptor_t *)&desc_ep_pn533_out,
+       (const usb_descriptor_t *)&desc_ep_pn533_in,
+       NULL
+};
+
+static const struct desc_fake desc_fake[] = {
+    { 0x04cc, 0x2533, desc_pn533 },    /* NXP / PN533 */
+    { 0x04e6, 0x5591, desc_pn533 },    /* SCM Micro / SCL3711-NFC&RW */
+    { 0x04e6, 0x5594, desc_pn533 },    /* SCM Micro / SCL3712-NFC&RW */
+    { 0x0000, 0x0000, NULL },
+};
+
+usbd_status
+usbd_get_desc_fake(struct usbd_device *dev, int type,
+                  int index, int len, void *desc)
+{
+       USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
+       const usb_device_descriptor_t *dd = usbd_get_device_descriptor(dev);
+       const struct desc_fake *df;
+       const usb_descriptor_t *ub;
+       int i = 0;
+       int j = 0;
+       usbd_status err = USBD_INVAL;
+
+       for (df = desc_fake; df->desc ; df++) {
+               if (UGETW(dd->idVendor) == df->idVendor &&
+                   UGETW(dd->idProduct) == df->idProduct)
+                       break;
+       }
+
+       if (df->desc == NULL) {
+               DPRINTF("%04x/%04x: no fake descriptors",
+                       UGETW(dd->idVendor), UGETW(dd->idProduct), 0, 0);
+               goto out;
+       }
+
+       for (j = 0; df->desc[j]; j++) {
+               ub = df->desc[j];
+               if (ub->bDescriptorType == type && i++ == index)
+                       break;
+       }
+
+       if (df->desc[j] == NULL) {
+               DPRINTF("%04x/%04x: no fake descriptor type = %d, len = %d",
+                      UGETW(dd->idVendor), UGETW(dd->idProduct), type, len);
+               goto out;
+       }
+
+       do {
+               ub = df->desc[j];
+
+               if (ub->bLength > len) {
+                       DPRINTF("%04x/%04x: short buf len = %d, bLength = %d",
+                               UGETW(dd->idVendor), UGETW(dd->idProduct),
+                               type, ub->bLength);
+                       goto out;
+               }
+
+               memcpy(desc, ub, ub->bLength);
+               DPRINTF("%04x/%04x: Use fake descriptor type %d",
+                       UGETW(dd->idVendor), UGETW(dd->idProduct),
+                       type, 0);
+
+               desc = (char *)desc + ub->bLength;
+               len -= ub->bLength;
+               j++;
+       } while (len && df->desc[j] && df->desc[j]->bDescriptorType != type);
+
+       err = USBD_NORMAL_COMPLETION;
+
+       DPRINTF("%04x/%04x: Using fake USB descriptors\n",
+               UGETW(dd->idVendor), UGETW(dd->idProduct), 0, 0);
+out:
+       DPRINTF("return err = %d", err, 0, 0, 0);
+       return err;     
+}



-- 
Emmanuel Dreyfus
http://hcpnet.free.fr/pubz
manu%netbsd.org@localhost


Home | Main Index | Thread Index | Old Index