summaryrefslogtreecommitdiff
path: root/sys/dev/usb/uvideo.c
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2008-07-23 14:10:59 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2008-07-23 14:10:59 +0000
commitc1ee1e009cac61f171c778a189023f8fd48027d7 (patch)
tree2bbe9b5076a3183414df3ae2ae60672bab2ba88f /sys/dev/usb/uvideo.c
parentdb4e46ccc6cb252c509e173c5a329779cdc35e58 (diff)
- Fix potential uvm_fault crash in
uvideo_vs_parse_desc_frame_uncompressed(). - If a VS alternate interface isn't valid (e.g. doesn't contain a UE_ISOCHRONOUS endpoint), abort attachment with a corresponding error message instead crashing the kernel. Tested and OK maja@
Diffstat (limited to 'sys/dev/usb/uvideo.c')
-rw-r--r--sys/dev/usb/uvideo.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/sys/dev/usb/uvideo.c b/sys/dev/usb/uvideo.c
index 9c55488efbf..0ec281dac79 100644
--- a/sys/dev/usb/uvideo.c
+++ b/sys/dev/usb/uvideo.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvideo.c,v 1.59 2008/07/22 16:24:40 mglocker Exp $ */
+/* $OpenBSD: uvideo.c,v 1.60 2008/07/23 14:10:58 mglocker Exp $ */
/*
* Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
@@ -553,7 +553,9 @@ uvideo_vs_parse_desc(struct uvideo_softc *sc, struct usb_attach_arg *uaa,
DPRINTF(1, "bInterfaceNumber=0x%02x, numalts=%d\n",
id->bInterfaceNumber, numalts);
- uvideo_vs_parse_desc_alt(sc, uaa, i, iface, numalts);
+ error = uvideo_vs_parse_desc_alt(sc, uaa, i, iface, numalts);
+ if (error != USBD_NORMAL_COMPLETION)
+ return (error);
}
/* XXX for now always use the first video stream */
@@ -718,7 +720,7 @@ uvideo_vs_parse_desc_frame(struct uvideo_softc *sc)
break;
case UDESCSUB_VS_FRAME_UNCOMPRESSED:
/* XXX do correct length calculation */
- if (desc->bLength > 11) {
+ if (desc->bLength > 25) {
if (uvideo_vs_parse_desc_frame_uncompressed(sc,
desc, &fmtidx))
return (1);
@@ -836,13 +838,18 @@ uvideo_vs_parse_desc_alt(struct uvideo_softc *sc, struct usb_attach_arg *uaa,
}
/* jump to corresponding endpoint descriptor */
- desc = usb_desc_iter_next(&iter);
- if (desc->bDescriptorType != UDESC_ENDPOINT)
- goto next;
+ while ((desc = usb_desc_iter_next(&iter))) {
+ if (desc->bDescriptorType == UDESC_ENDPOINT)
+ break;
+ }
ed = (usb_endpoint_descriptor_t *)(uint8_t *)desc;
DPRINTF(1, "bEndpointAddress=0x%02x, ", ed->bEndpointAddress);
DPRINTF(1, "wMaxPacketSize=%d\n", UGETW(ed->wMaxPacketSize));
+ /* we just support isoc endpoints yet */
+ if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
+ goto next;
+
/* save endpoint with largest bandwidth */
if (UGETW(ed->wMaxPacketSize) > vs->max_packet_size) {
vs->ifaceh = uaa->ifaces[iface];
@@ -856,6 +863,13 @@ next:
desc = usb_desc_iter_next(&iter);
}
+ /* check if we have found a valid alternate interface */
+ if (vs->ifaceh == NULL) {
+ printf("%s: no valid alternate interface found!\n",
+ DEVNAME(sc));
+ return (USBD_INVAL);
+ }
+
return (USBD_NORMAL_COMPLETION);
}
@@ -1606,7 +1620,7 @@ uvideo_dump_desc_all(struct uvideo_softc *sc)
printf("bDescriptorSubtype=0x%02x",
desc->bDescriptorSubtype);
/* XXX do correct length calculation */
- if (desc->bLength > 11) {
+ if (desc->bLength > 25) {
printf(" (UDESCSUB_VS_FRAME_"
"UNCOMPRESSED)\n");
uvideo_dump_desc_frame_uncompressed(