forked from luck/tmp_suning_uos_patched
ALSA: usb-audio: Check mixer unit descriptors more strictly
We've had some sanity checks of the mixer unit descriptors but they are too loose and some corner cases are overlooked. Add more strict checks in uac_mixer_unit_get_channels() for avoiding possible OOB accesses by malformed descriptors. This also changes the semantics of uac_mixer_unit_get_channels() slightly. Now it returns zero for the cases where the descriptor lacks of bmControls instead of -EINVAL. Then the caller side skips the mixer creation for such unit while it keeps parsing it. This corresponds to the case like Maya44. Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
f4351a199c
commit
0bfe5e434e
|
@ -753,8 +753,9 @@ 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 < 11)
|
if (desc->bLength < sizeof(*desc))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!desc->bNrInPins)
|
if (!desc->bNrInPins)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -763,6 +764,8 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
|
||||||
case UAC_VERSION_1:
|
case UAC_VERSION_1:
|
||||||
case UAC_VERSION_2:
|
case UAC_VERSION_2:
|
||||||
default:
|
default:
|
||||||
|
if (desc->bLength < sizeof(*desc) + desc->bNrInPins + 1)
|
||||||
|
return 0; /* no bmControls -> skip */
|
||||||
mu_channels = uac_mixer_unit_bNrChannels(desc);
|
mu_channels = uac_mixer_unit_bNrChannels(desc);
|
||||||
break;
|
break;
|
||||||
case UAC_VERSION_3:
|
case UAC_VERSION_3:
|
||||||
|
@ -772,7 +775,11 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mu_channels)
|
if (!mu_channels)
|
||||||
return -EINVAL;
|
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;
|
||||||
}
|
}
|
||||||
|
@ -944,7 +951,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
||||||
struct uac_mixer_unit_descriptor *d = p1;
|
struct uac_mixer_unit_descriptor *d = p1;
|
||||||
|
|
||||||
err = uac_mixer_unit_get_channels(state, d);
|
err = uac_mixer_unit_get_channels(state, d);
|
||||||
if (err < 0)
|
if (err <= 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
term->channels = err;
|
term->channels = err;
|
||||||
|
@ -2118,7 +2125,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
continue;
|
continue;
|
||||||
/* no bmControls field (e.g. Maya44) -> ignore */
|
/* no bmControls field (e.g. Maya44) -> ignore */
|
||||||
if (desc->bLength <= 10 + input_pins)
|
if (!num_outs)
|
||||||
continue;
|
continue;
|
||||||
err = check_input_term(state, desc->baSourceID[pin], &iterm);
|
err = check_input_term(state, desc->baSourceID[pin], &iterm);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user