diff options
Diffstat (limited to 'sound/usb/mixer.c')
| -rw-r--r-- | sound/usb/mixer.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c63c84b54969..e7d441d0e839 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
| @@ -753,8 +753,9 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state, | |||
| 753 | struct uac_mixer_unit_descriptor *desc) | 753 | struct uac_mixer_unit_descriptor *desc) |
| 754 | { | 754 | { |
| 755 | int mu_channels; | 755 | int mu_channels; |
| 756 | void *c; | ||
| 756 | 757 | ||
| 757 | if (desc->bLength < 11) | 758 | if (desc->bLength < sizeof(*desc)) |
| 758 | return -EINVAL; | 759 | return -EINVAL; |
| 759 | if (!desc->bNrInPins) | 760 | if (!desc->bNrInPins) |
| 760 | return -EINVAL; | 761 | return -EINVAL; |
| @@ -763,6 +764,8 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state, | |||
| 763 | case UAC_VERSION_1: | 764 | case UAC_VERSION_1: |
| 764 | case UAC_VERSION_2: | 765 | case UAC_VERSION_2: |
| 765 | default: | 766 | default: |
| 767 | if (desc->bLength < sizeof(*desc) + desc->bNrInPins + 1) | ||
| 768 | return 0; /* no bmControls -> skip */ | ||
| 766 | mu_channels = uac_mixer_unit_bNrChannels(desc); | 769 | mu_channels = uac_mixer_unit_bNrChannels(desc); |
| 767 | break; | 770 | break; |
| 768 | case UAC_VERSION_3: | 771 | case UAC_VERSION_3: |
| @@ -772,7 +775,11 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state, | |||
| 772 | } | 775 | } |
| 773 | 776 | ||
| 774 | if (!mu_channels) | 777 | if (!mu_channels) |
| 775 | return -EINVAL; | 778 | return 0; |
| 779 | |||
| 780 | c = uac_mixer_unit_bmControls(desc, state->mixer->protocol); | ||
| 781 | if (c - (void *)desc + (mu_channels - 1) / 8 >= desc->bLength) | ||
| 782 | return 0; /* no bmControls -> skip */ | ||
| 776 | 783 | ||
| 777 | return mu_channels; | 784 | return mu_channels; |
| 778 | } | 785 | } |
| @@ -944,7 +951,7 @@ static int check_input_term(struct mixer_build *state, int id, | |||
| 944 | struct uac_mixer_unit_descriptor *d = p1; | 951 | struct uac_mixer_unit_descriptor *d = p1; |
| 945 | 952 | ||
| 946 | err = uac_mixer_unit_get_channels(state, d); | 953 | err = uac_mixer_unit_get_channels(state, d); |
| 947 | if (err < 0) | 954 | if (err <= 0) |
| 948 | return err; | 955 | return err; |
| 949 | 956 | ||
| 950 | term->channels = err; | 957 | term->channels = err; |
| @@ -2068,11 +2075,15 @@ static int parse_audio_input_terminal(struct mixer_build *state, int unitid, | |||
| 2068 | 2075 | ||
| 2069 | if (state->mixer->protocol == UAC_VERSION_2) { | 2076 | if (state->mixer->protocol == UAC_VERSION_2) { |
| 2070 | struct uac2_input_terminal_descriptor *d_v2 = raw_desc; | 2077 | struct uac2_input_terminal_descriptor *d_v2 = raw_desc; |
| 2078 | if (d_v2->bLength < sizeof(*d_v2)) | ||
| 2079 | return -EINVAL; | ||
| 2071 | control = UAC2_TE_CONNECTOR; | 2080 | control = UAC2_TE_CONNECTOR; |
| 2072 | term_id = d_v2->bTerminalID; | 2081 | term_id = d_v2->bTerminalID; |
| 2073 | bmctls = le16_to_cpu(d_v2->bmControls); | 2082 | bmctls = le16_to_cpu(d_v2->bmControls); |
| 2074 | } else if (state->mixer->protocol == UAC_VERSION_3) { | 2083 | } else if (state->mixer->protocol == UAC_VERSION_3) { |
| 2075 | struct uac3_input_terminal_descriptor *d_v3 = raw_desc; | 2084 | struct uac3_input_terminal_descriptor *d_v3 = raw_desc; |
| 2085 | if (d_v3->bLength < sizeof(*d_v3)) | ||
| 2086 | return -EINVAL; | ||
| 2076 | control = UAC3_TE_INSERTION; | 2087 | control = UAC3_TE_INSERTION; |
| 2077 | term_id = d_v3->bTerminalID; | 2088 | term_id = d_v3->bTerminalID; |
| 2078 | bmctls = le32_to_cpu(d_v3->bmControls); | 2089 | bmctls = le32_to_cpu(d_v3->bmControls); |
| @@ -2118,7 +2129,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, | |||
| 2118 | if (err < 0) | 2129 | if (err < 0) |
| 2119 | continue; | 2130 | continue; |
| 2120 | /* no bmControls field (e.g. Maya44) -> ignore */ | 2131 | /* no bmControls field (e.g. Maya44) -> ignore */ |
| 2121 | if (desc->bLength <= 10 + input_pins) | 2132 | if (!num_outs) |
| 2122 | continue; | 2133 | continue; |
| 2123 | err = check_input_term(state, desc->baSourceID[pin], &iterm); | 2134 | err = check_input_term(state, desc->baSourceID[pin], &iterm); |
| 2124 | if (err < 0) | 2135 | if (err < 0) |
| @@ -2314,7 +2325,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, | |||
| 2314 | char *name) | 2325 | char *name) |
| 2315 | { | 2326 | { |
| 2316 | struct uac_processing_unit_descriptor *desc = raw_desc; | 2327 | struct uac_processing_unit_descriptor *desc = raw_desc; |
| 2317 | int num_ins = desc->bNrInPins; | 2328 | int num_ins; |
| 2318 | struct usb_mixer_elem_info *cval; | 2329 | struct usb_mixer_elem_info *cval; |
| 2319 | struct snd_kcontrol *kctl; | 2330 | struct snd_kcontrol *kctl; |
| 2320 | int i, err, nameid, type, len; | 2331 | int i, err, nameid, type, len; |
| @@ -2329,7 +2340,13 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, | |||
| 2329 | 0, NULL, default_value_info | 2340 | 0, NULL, default_value_info |
| 2330 | }; | 2341 | }; |
| 2331 | 2342 | ||
| 2332 | if (desc->bLength < 13 || desc->bLength < 13 + num_ins || | 2343 | if (desc->bLength < 13) { |
| 2344 | usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid); | ||
| 2345 | return -EINVAL; | ||
| 2346 | } | ||
| 2347 | |||
| 2348 | num_ins = desc->bNrInPins; | ||
| 2349 | if (desc->bLength < 13 + num_ins || | ||
| 2333 | desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) { | 2350 | desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) { |
| 2334 | usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid); | 2351 | usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid); |
| 2335 | return -EINVAL; | 2352 | return -EINVAL; |
