summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormglocker <mglocker@openbsd.org>2020-09-02 12:36:12 +0000
committermglocker <mglocker@openbsd.org>2020-09-02 12:36:12 +0000
commit548012a22ded9d254d0730ec3ed5b498078cb094 (patch)
tree23559649cdecf643256fa7084ef4b5e5d66f07bf
parentKNF and comment tweaks (diff)
downloadwireguard-openbsd-548012a22ded9d254d0730ec3ed5b498078cb094.tar.xz
wireguard-openbsd-548012a22ded9d254d0730ec3ed5b498078cb094.zip
Don't rely on wTotalLength for usbd_get_cdesc() malloc/free but on the
actual length which has been allocated. We saw cases where the wTotalLength value is changing on a second read, e.g. when a USB device was waked up from sleep mode. ok mpi@
-rw-r--r--sys/dev/usb/ugen.c29
-rw-r--r--sys/dev/usb/usb.c8
2 files changed, 21 insertions, 16 deletions
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index 9128ffd1d46..8eec98c7d3a 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ugen.c,v 1.106 2020/05/13 08:13:42 mpi Exp $ */
+/* $OpenBSD: ugen.c,v 1.107 2020/09/02 12:36:12 mglocker Exp $ */
/* $NetBSD: ugen.c,v 1.63 2002/11/26 18:49:48 christos Exp $ */
/* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */
@@ -947,7 +947,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, caddr_t addr,
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 endpt, u_long cmd, caddr_t addr,
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 endpt, u_long cmd, caddr_t addr,
}
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 endpt, u_long cmd, caddr_t addr,
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 endpt, u_long cmd, caddr_t addr,
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 endpt, u_long cmd, caddr_t addr,
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 endpt, u_long cmd, caddr_t addr,
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 endpt, u_long cmd, caddr_t addr,
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:
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c
index 4ca725aad6d..f4a77afb01f 100644
--- a/sys/dev/usb/usb.c
+++ b/sys/dev/usb/usb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb.c,v 1.125 2020/08/27 19:55:00 mglocker Exp $ */
+/* $OpenBSD: usb.c,v 1.126 2020/09/02 12:36:12 mglocker Exp $ */
/* $NetBSD: usb.c,v 1.77 2003/01/01 00:10:26 thorpej Exp $ */
/*
@@ -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