diff options
author | 2020-09-02 12:36:12 +0000 | |
---|---|---|
committer | 2020-09-02 12:36:12 +0000 | |
commit | 548012a22ded9d254d0730ec3ed5b498078cb094 (patch) | |
tree | 23559649cdecf643256fa7084ef4b5e5d66f07bf | |
parent | KNF and comment tweaks (diff) | |
download | wireguard-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.c | 29 | ||||
-rw-r--r-- | sys/dev/usb/usb.c | 8 |
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 |