Skip to content

Commit f9f0e9e

Browse files
committed
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: 0bfe5e4 ("ALSA: usb-audio: Check mixer unit descriptors more strictly") Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 1bc8d18 commit f9f0e9e

File tree

1 file changed

+28
-8
lines changed

1 file changed

+28
-8
lines changed

sound/usb/mixer.c

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
739739
struct uac_mixer_unit_descriptor *desc)
740740
{
741741
int mu_channels;
742-
void *c;
743742

744743
if (desc->bLength < sizeof(*desc))
745744
return -EINVAL;
@@ -762,13 +761,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
762761
break;
763762
}
764763

765-
if (!mu_channels)
766-
return 0;
767-
768-
c = uac_mixer_unit_bmControls(desc, state->mixer->protocol);
769-
if (c - (void *)desc + (mu_channels - 1) / 8 >= desc->bLength)
770-
return 0; /* no bmControls -> skip */
771-
772764
return mu_channels;
773765
}
774766

@@ -2009,6 +2001,31 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
20092001
* Mixer Unit
20102002
*/
20112003

2004+
/* check whether the given in/out overflows bmMixerControls matrix */
2005+
static bool mixer_bitmap_overflow(struct uac_mixer_unit_descriptor *desc,
2006+
int protocol, int num_ins, int num_outs)
2007+
{
2008+
u8 *hdr = (u8 *)desc;
2009+
u8 *c = uac_mixer_unit_bmControls(desc, protocol);
2010+
size_t rest; /* remaining bytes after bmMixerControls */
2011+
2012+
switch (protocol) {
2013+
case UAC_VERSION_1:
2014+
default:
2015+
rest = 1; /* iMixer */
2016+
break;
2017+
case UAC_VERSION_2:
2018+
rest = 2; /* bmControls + iMixer */
2019+
break;
2020+
case UAC_VERSION_3:
2021+
rest = 6; /* bmControls + wMixerDescrStr */
2022+
break;
2023+
}
2024+
2025+
/* overflow? */
2026+
return c + (num_ins * num_outs + 7) / 8 + rest > hdr + hdr[0];
2027+
}
2028+
20122029
/*
20132030
* build a mixer unit control
20142031
*
@@ -2137,6 +2154,9 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
21372154
if (err < 0)
21382155
return err;
21392156
num_ins += iterm.channels;
2157+
if (mixer_bitmap_overflow(desc, state->mixer->protocol,
2158+
num_ins, num_outs))
2159+
break;
21402160
for (; ich < num_ins; ich++) {
21412161
int och, ich_has_controls = 0;
21422162

0 commit comments

Comments
 (0)