diff mbox series

Fix an OOB bug in uac_mixer_unit_bmControls

Message ID 20190819220005.10178-1-benquike@gmail.com (mailing list archive)
State New, archived
Headers show
Series Fix an OOB bug in uac_mixer_unit_bmControls | expand

Commit Message

Hui Peng Aug. 19, 2019, 10 p.m. UTC
`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@gmail.com>
Reported-by: Mathias Payer <mathias.payer@nebelwelt.net>
Signed-off-by: Hui Peng <benquike@gmail.com>
---
 sound/usb/mixer.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

Comments

Hui Peng Aug. 19, 2019, 10:01 p.m. UTC | #1
Sorry, this is the wrong patch. I will send it again.

On Mon, Aug 19, 2019 at 6:00 PM Hui Peng <benquike@gmail.com> 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@gmail.com>
> Reported-by: Mathias Payer <mathias.payer@nebelwelt.net>
> Signed-off-by: Hui Peng <benquike@gmail.com>
> ---
>  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
>
>
diff mbox series

Patch

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)