Since we can't always rely on wTotalLength to be correct, use the
variable which has been used to malloc(9) cdesc to free(9) it again,
instead of freeing wTotalLength.  usbd_get_cdesc() already has the
feature built-in to return the length it has used to malloc(9) cdesc.

OK?


Index: ugen.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ugen.c,v
retrieving revision 1.106
diff -u -p -u -p -r1.106 ugen.c
--- ugen.c      13 May 2020 08:13:42 -0000      1.106
+++ ugen.c      27 Aug 2020 20:26:57 -0000
@@ -947,7 +947,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int
     int flag, struct proc *p)
 {
        struct ugen_endpoint *sce;
-       int err;
+       int err, cdesc_len;
        struct usbd_interface *iface;
        struct usb_config_desc *cd;
        usb_config_descriptor_t *cdesc;
@@ -1046,7 +1046,8 @@ ugen_do_ioctl(struct ugen_softc *sc, int
                break;
        case USB_GET_NO_ALT:
                ai = (struct usb_alt_interface *)addr;
-               cdesc = usbd_get_cdesc(sc->sc_udev, ai->uai_config_index, 0);
+               cdesc = usbd_get_cdesc(sc->sc_udev, ai->uai_config_index,
+                   &cdesc_len);
                if (cdesc == NULL)
                        return (EINVAL);
                idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0);
@@ -1056,7 +1057,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int
                }
                ai->uai_alt_no = usbd_get_no_alts(cdesc,
                    idesc->bInterfaceNumber);
-               free(cdesc, M_TEMP, UGETW(cdesc->wTotalLength));
+               free(cdesc, M_TEMP, cdesc_len);
                break;
        case USB_GET_DEVICE_DESC:
                *(usb_device_descriptor_t *)addr =
@@ -1064,15 +1065,17 @@ ugen_do_ioctl(struct ugen_softc *sc, int
                break;
        case USB_GET_CONFIG_DESC:
                cd = (struct usb_config_desc *)addr;
-               cdesc = usbd_get_cdesc(sc->sc_udev, cd->ucd_config_index, 0);
+               cdesc = usbd_get_cdesc(sc->sc_udev, cd->ucd_config_index,
+                   &cdesc_len);
                if (cdesc == NULL)
                        return (EINVAL);
                cd->ucd_desc = *cdesc;
-               free(cdesc, M_TEMP, UGETW(cdesc->wTotalLength));
+               free(cdesc, M_TEMP, cdesc_len);
                break;
        case USB_GET_INTERFACE_DESC:
                id = (struct usb_interface_desc *)addr;
-               cdesc = usbd_get_cdesc(sc->sc_udev, id->uid_config_index, 0);
+               cdesc = usbd_get_cdesc(sc->sc_udev, id->uid_config_index,
+                   &cdesc_len);
                if (cdesc == NULL)
                        return (EINVAL);
                if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX &&
@@ -1086,11 +1089,12 @@ ugen_do_ioctl(struct ugen_softc *sc, int
                        return (EINVAL);
                }
                id->uid_desc = *idesc;
-               free(cdesc, M_TEMP, UGETW(cdesc->wTotalLength));
+               free(cdesc, M_TEMP, cdesc_len);
                break;
        case USB_GET_ENDPOINT_DESC:
                ed = (struct usb_endpoint_desc *)addr;
-               cdesc = usbd_get_cdesc(sc->sc_udev, ed->ued_config_index, 0);
+               cdesc = usbd_get_cdesc(sc->sc_udev, ed->ued_config_index,
+                   &cdesc_len);
                if (cdesc == NULL)
                        return (EINVAL);
                if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX &&
@@ -1105,7 +1109,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int
                        return (EINVAL);
                }
                ed->ued_desc = *edesc;
-               free(cdesc, M_TEMP, UGETW(cdesc->wTotalLength));
+               free(cdesc, M_TEMP, cdesc_len);
                break;
        case USB_GET_FULL_DESC:
        {
@@ -1115,7 +1119,8 @@ ugen_do_ioctl(struct ugen_softc *sc, int
                struct usb_full_desc *fd = (struct usb_full_desc *)addr;
                int error;
 
-               cdesc = usbd_get_cdesc(sc->sc_udev, fd->ufd_config_index, &len);
+               cdesc = usbd_get_cdesc(sc->sc_udev, fd->ufd_config_index,
+                   &cdesc_len);
                if (cdesc == NULL)
                        return (EINVAL);
                if (len > fd->ufd_size)
@@ -1130,7 +1135,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int
                uio.uio_rw = UIO_READ;
                uio.uio_procp = p;
                error = uiomove((void *)cdesc, len, &uio);
-               free(cdesc, M_TEMP, UGETW(cdesc->wTotalLength));
+               free(cdesc, M_TEMP, cdesc_len);
                return (error);
        }
        case USB_DO_REQUEST:
Index: usb.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb.c,v
retrieving revision 1.125
diff -u -p -u -p -r1.125 usb.c
--- usb.c       27 Aug 2020 19:55:00 -0000      1.125
+++ usb.c       27 Aug 2020 20:26:57 -0000
@@ -516,7 +516,7 @@ usb_fill_udc_task(void *arg)
        struct usb_device_cdesc *udc = (struct usb_device_cdesc *)arg;
        struct usb_softc *sc;
        struct usbd_device *dev;
-       int addr = udc->udc_addr;
+       int addr = udc->udc_addr, cdesc_len;
        usb_config_descriptor_t *cdesc;
 
        /* check that the bus and device are still present */
@@ -530,11 +530,11 @@ usb_fill_udc_task(void *arg)
                return;
 
        cdesc = usbd_get_cdesc(sc->sc_bus->devices[addr],
-           udc->udc_config_index, 0);
+           udc->udc_config_index, &cdesc_len);
        if (cdesc == NULL)
                return;
        udc->udc_desc = *cdesc;
-       free(cdesc, M_TEMP, UGETW(cdesc->wTotalLength));
+       free(cdesc, M_TEMP, cdesc_len);
 }
 
 void

Reply via email to