[alsa-devel] [PATCH] Fix an OOB bug in uac_mixer_unit_bmControls
Hui Peng
benquike at gmail.com
Sat Aug 17 17:57:38 CEST 2019
Looking around, there are other suspicious codes. E.g., in the following
function, it seems to be the same as `uac_mixer_unit_bmControls`, but it is
accessing `desc->bNrInPins + 5`, in case of UAC_VERSION_1.
Is this intended?
static inline __u8
<https://elixir.bootlin.com/linux/latest/ident/__u8>
*uac_processing_unit_bmControls
<https://elixir.bootlin.com/linux/latest/ident/uac_processing_unit_bmControls>(struct
uac_processing_unit_descriptor
<https://elixir.bootlin.com/linux/latest/ident/uac_processing_unit_descriptor>
*desc,
int protocol <https://elixir.bootlin.com/linux/latest/ident/protocol>){
switch (protocol <https://elixir.bootlin.com/linux/latest/ident/protocol>) {
case UAC_VERSION_1
<https://elixir.bootlin.com/linux/latest/ident/UAC_VERSION_1>:
return &desc->baSourceID[desc->bNrInPins + 5];
case UAC_VERSION_2
<https://elixir.bootlin.com/linux/latest/ident/UAC_VERSION_2>:
return &desc->baSourceID[desc->bNrInPins + 6];
case UAC_VERSION_3
<https://elixir.bootlin.com/linux/latest/ident/UAC_VERSION_3>:
return &desc->baSourceID[desc->bNrInPins + 2];
default:
return NULL;
}}
On Sat, Aug 17, 2019 at 2:55 AM Takashi Iwai <tiwai at suse.de> wrote:
> On Sat, 17 Aug 2019 06:32:07 +0200,
> Hui Peng wrote:
> >
> > `uac_mixer_unit_get_channels` calls `uac_mixer_unit_bmControls`
> > to get pointer to bmControls field. The current implementation of
> > `uac_mixer_unit_get_channels` does properly check the size of
> > uac_mixer_unit_descriptor descriptor and may allow OOB access
> > in `uac_mixer_unit_bmControls`.
> >
> > Reported-by: Hui Peng <benquike at gmail.com>
> > Reported-by: Mathias Payer <mathias.payer at nebelwelt.net>
> > Signed-off-by: Hui Peng <benquike at gmail.com>
>
> Ah a good catch.
>
> One easier fix in this case would be to get the offset from
> uac_mixer_unit_bmControls(), e.g.
>
> /* calculate the offset of bmControls field */
> size_t bmc_offset = uac_mixer_unit_bmControls(NULL, protocol) -
> NULL;
> ....
> if (desc->bLength < bmc_offset)
> return 0;
>
> thanks,
>
> Takashi
>
>
> > ---
> > sound/usb/mixer.c | 25 ++++++++++++++++++-------
> > 1 file changed, 18 insertions(+), 7 deletions(-)
> >
> > diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
> > index b5927c3d5bc0..00e6274a63c3 100644
> > --- a/sound/usb/mixer.c
> > +++ b/sound/usb/mixer.c
> > @@ -738,28 +738,39 @@ static int get_cluster_channels_v3(struct
> mixer_build *state, unsigned int clust
> > static int uac_mixer_unit_get_channels(struct mixer_build *state,
> > struct uac_mixer_unit_descriptor
> *desc)
> > {
> > - int mu_channels;
> > + int mu_channels = 0;
> > void *c;
> >
> > - if (desc->bLength < sizeof(*desc))
> > - return -EINVAL;
> > if (!desc->bNrInPins)
> > return -EINVAL;
> > - if (desc->bLength < sizeof(*desc) + desc->bNrInPins)
> > - return -EINVAL;
> >
> > switch (state->mixer->protocol) {
> > case UAC_VERSION_1:
> > + // limit derived from uac_mixer_unit_bmControls
> > + if (desc->bLength < sizeof(*desc) + desc->bNrInPins + 4)
> > + return 0;
> > +
> > + mu_channels = uac_mixer_unit_bNrChannels(desc);
> > + break;
> > +
> > case UAC_VERSION_2:
> > - default:
> > - if (desc->bLength < sizeof(*desc) + desc->bNrInPins + 1)
> > + // limit derived from uac_mixer_unit_bmControls
> > + if (desc->bLength < sizeof(*desc) + desc->bNrInPins + 6)
> > return 0; /* no bmControls -> skip */
> > +
> > mu_channels = uac_mixer_unit_bNrChannels(desc);
> > break;
> > case UAC_VERSION_3:
> > + // limit derived from uac_mixer_unit_bmControls
> > + if (desc->bLength < sizeof(*desc) + desc->bNrInPins + 2)
> > + return 0; /* no bmControls -> skip */
> > +
> > mu_channels = get_cluster_channels_v3(state,
> > uac3_mixer_unit_wClusterDescrID(desc));
> > break;
> > +
> > + default:
> > + break;
> > }
> >
> > if (!mu_channels)
> > --
> > 2.22.1
> >
> >
>
More information about the Alsa-devel
mailing list