aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/mixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/mixer.c')
-rw-r--r--sound/usb/mixer.c29
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;