1) Make sure we have a complete endpoint descriptor header, otherwise

small overflow.
 2) Make sure the total length of the bos descriptor did not change in
    the meantime, otherwise severe memory corruption.
 3) Make sure we have a complete hid descriptor header, otherwise
    small overflow.
 4) Error out if the report descriptor is zero-sized, otherwise panic.

ok skrll@ mrg@
This commit is contained in:
maxv 2019-07-31 19:40:59 +00:00
parent 2d8834ad2a
commit 1815c58abf
2 changed files with 13 additions and 7 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: usb_subr.c,v 1.235 2019/07/23 17:21:33 maxv Exp $ */
/* $NetBSD: usb_subr.c,v 1.236 2019/07/31 19:40:59 maxv Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */
/*
@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.235 2019/07/23 17:21:33 maxv Exp $");
__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.236 2019/07/31 19:40:59 maxv Exp $");
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
@ -452,7 +452,8 @@ usbd_fill_iface_data(struct usbd_device *dev, int ifaceidx, int altidx)
DPRINTFN(10, "p=%#jx end=%#jx len=%jd type=%jd",
(uintptr_t)p, (uintptr_t)end, ed->bLength,
ed->bDescriptorType);
if (p + ed->bLength <= end && ed->bLength != 0 &&
if (p + ed->bLength <= end &&
ed->bLength >= USB_ENDPOINT_DESCRIPTOR_SIZE &&
ed->bDescriptorType == UDESC_ENDPOINT)
goto found;
if (ed->bLength == 0 ||
@ -659,7 +660,8 @@ usbd_set_config_index(struct usbd_device *dev, int index, int msg)
break;
usbd_delay_ms(dev, 200);
}
if (err || bdp->bDescriptorType != UDESC_BOS) {
if (err || bdp->bDescriptorType != UDESC_BOS ||
UGETW(bdp->wTotalLength) != UGETW(bd.wTotalLength)) {
DPRINTF("error %jd or bad desc %jd", err,
bdp->bDescriptorType, 0, 0);
kmem_free(bdp, blen);

View File

@ -1,4 +1,4 @@
/* $NetBSD: usbdi_util.c,v 1.73 2019/02/07 13:20:41 skrll Exp $ */
/* $NetBSD: usbdi_util.c,v 1.74 2019/07/31 19:40:59 maxv Exp $ */
/*
* Copyright (c) 1998, 2012 The NetBSD Foundation, Inc.
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.73 2019/02/07 13:20:41 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.74 2019/07/31 19:40:59 maxv Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@ -470,7 +470,9 @@ usbd_get_hid_descriptor(struct usbd_interface *ifc)
for (; p < end; p += hd->bLength) {
hd = (usb_hid_descriptor_t *)p;
if (p + hd->bLength <= end && hd->bDescriptorType == UDESC_HID)
if (p + hd->bLength <= end &&
hd->bLength >= USB_HID_DESCRIPTOR_SIZE(0) &&
hd->bDescriptorType == UDESC_HID)
return hd;
if (hd->bDescriptorType == UDESC_INTERFACE)
break;
@ -494,6 +496,8 @@ usbd_read_report_desc(struct usbd_interface *ifc, void **descp, int *sizep)
if (hid == NULL)
return USBD_IOERROR;
*sizep = UGETW(hid->descrs[0].wDescriptorLength);
if (*sizep == 0)
return USBD_INVAL;
*descp = kmem_alloc(*sizep, KM_SLEEP);
err = usbd_get_report_descriptor(dev, id->bInterfaceNumber,
*sizep, *descp);