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