diff --git a/sound/usb/card.c b/sound/usb/card.c index 8fccc15b6769..35ca342ec138 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -271,6 +271,11 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) return -EINVAL; } + if (h1->bLength < sizeof(*h1)) { + dev_err(&dev->dev, "cannot find UAC_HEADER\n"); + return -EINVAL; + } + if (!h1->bInCollection) { snd_printk(KERN_INFO "skipping empty audio interface (v1)\n"); return -EINVAL; diff --git a/sound/usb/stream.c b/sound/usb/stream.c index a0392e7c5784..c58d33a68abe 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -404,13 +404,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT); if (!csep || csep->bLength < 7 || - csep->bDescriptorSubtype != UAC_EP_GENERAL) { - snd_printk(KERN_WARNING "%d:%u:%d : no or invalid" - " class specific endpoint descriptor\n", - chip->dev->devnum, iface_no, - altsd->bAlternateSetting); - return 0; - } + csep->bDescriptorSubtype != UAC_EP_GENERAL) + goto error; if (protocol == UAC_VERSION_1) { attributes = csep->bmAttributes; @@ -418,6 +413,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, struct uac2_iso_endpoint_descriptor *csep2 = (struct uac2_iso_endpoint_descriptor *) csep; + if (csep2->bLength < sizeof(*csep2)) + goto error; attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX; /* emulate the endpoint attributes of a v1 device */ @@ -426,6 +423,13 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, } return attributes; + + error: + snd_printk(KERN_WARNING "%d:%u:%d : no or invalid" + " class specific endpoint descriptor\n", + chip->dev->devnum, iface_no, + altsd->bAlternateSetting); + return 0; } /* find an input terminal descriptor (either UAC1 or UAC2) with the given @@ -433,13 +437,17 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, */ static void * snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, - int terminal_id) + int terminal_id, bool uac2) { struct uac2_input_terminal_descriptor *term = NULL; + size_t minlen = uac2 ? sizeof(struct uac2_input_terminal_descriptor) : + sizeof(struct uac_input_terminal_descriptor); while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, ctrl_iface->extralen, term, UAC_INPUT_TERMINAL))) { + if (term->bLength < minlen) + continue; if (term->bTerminalID == terminal_id) return term; } @@ -456,7 +464,8 @@ static struct uac2_output_terminal_descriptor * while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, ctrl_iface->extralen, term, UAC_OUTPUT_TERMINAL))) { - if (term->bTerminalID == terminal_id) + if (term->bLength >= sizeof(*term) && + term->bTerminalID == terminal_id) return term; } @@ -543,7 +552,8 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) format = le16_to_cpu(as->wFormatTag); /* remember the format value */ iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, - as->bTerminalLink); + as->bTerminalLink, + false); if (iterm) { num_channels = iterm->bNrChannels; chconfig = le16_to_cpu(iterm->wChannelConfig); @@ -576,7 +586,8 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) /* lookup the terminal associated to this interface * to extract the clock */ input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, - as->bTerminalLink); + as->bTerminalLink, + true); if (input_term) { clock = input_term->bCSourceID; chconfig = le32_to_cpu(input_term->bmChannelConfig);