Commit f9f0e9ed authored by Takashi Iwai's avatar Takashi Iwai

ALSA: usb-audio: Check mixer unit bitmap yet more strictly

The bmControls (for UAC1) or bmMixerControls (for UAC2/3) bitmap has a
variable size depending on both input and output pins.  Its size is to
fit with input * output bits.  The problem is that the input size
can't be determined simply from the unit descriptor itself but it
needs to parse the whole connected sources.  Although the
uac_mixer_unit_get_channels() tries to check some possible overflow of
this bitmap, it's incomplete due to the lack of the  evaluation of
input pins.

For covering possible overflows, this patch adds the bitmap overflow
check in the loop of input pins in parse_audio_mixer_unit().

Fixes: 0bfe5e43 ("ALSA: usb-audio: Check mixer unit descriptors more strictly")
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 1bc8d18c
...@@ -739,7 +739,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state, ...@@ -739,7 +739,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
struct uac_mixer_unit_descriptor *desc) struct uac_mixer_unit_descriptor *desc)
{ {
int mu_channels; int mu_channels;
void *c;
if (desc->bLength < sizeof(*desc)) if (desc->bLength < sizeof(*desc))
return -EINVAL; return -EINVAL;
...@@ -762,13 +761,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state, ...@@ -762,13 +761,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
break; break;
} }
if (!mu_channels)
return 0;
c = uac_mixer_unit_bmControls(desc, state->mixer->protocol);
if (c - (void *)desc + (mu_channels - 1) / 8 >= desc->bLength)
return 0; /* no bmControls -> skip */
return mu_channels; return mu_channels;
} }
...@@ -2009,6 +2001,31 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, ...@@ -2009,6 +2001,31 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
* Mixer Unit * Mixer Unit
*/ */
/* check whether the given in/out overflows bmMixerControls matrix */
static bool mixer_bitmap_overflow(struct uac_mixer_unit_descriptor *desc,
int protocol, int num_ins, int num_outs)
{
u8 *hdr = (u8 *)desc;
u8 *c = uac_mixer_unit_bmControls(desc, protocol);
size_t rest; /* remaining bytes after bmMixerControls */
switch (protocol) {
case UAC_VERSION_1:
default:
rest = 1; /* iMixer */
break;
case UAC_VERSION_2:
rest = 2; /* bmControls + iMixer */
break;
case UAC_VERSION_3:
rest = 6; /* bmControls + wMixerDescrStr */
break;
}
/* overflow? */
return c + (num_ins * num_outs + 7) / 8 + rest > hdr + hdr[0];
}
/* /*
* build a mixer unit control * build a mixer unit control
* *
...@@ -2137,6 +2154,9 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, ...@@ -2137,6 +2154,9 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
if (err < 0) if (err < 0)
return err; return err;
num_ins += iterm.channels; num_ins += iterm.channels;
if (mixer_bitmap_overflow(desc, state->mixer->protocol,
num_ins, num_outs))
break;
for (; ich < num_ins; ich++) { for (; ich < num_ins; ich++) {
int och, ich_has_controls = 0; int och, ich_has_controls = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment