]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ALSA: usb-audio: Bound MIDI endpoint descriptor scans
authorCássio Gabriel <cassiogabrielcontato@gmail.com>
Thu, 7 May 2026 03:40:51 +0000 (00:40 -0300)
committerTakashi Iwai <tiwai@suse.de>
Thu, 7 May 2026 10:58:09 +0000 (12:58 +0200)
snd_usbmidi_get_ms_info() validates the internal MIDIStreaming endpoint
descriptor size before using baAssocJackID[], but the descriptor walker can
still return a class-specific endpoint descriptor whose bLength exceeds the
remaining bytes in the endpoint-extra scan.

That leaves later flexible-array reads bounded by bLength, but not by the
remaining bytes in the endpoint-extra scan.

Stop walking when bLength is zero or
extends past the remaining endpoint-extra scan.

Fixes: 5c6cd7021a05 ("ALSA: usb-audio: Fix case when USB MIDI interface has more than one extra endpoint descriptor")
Cc: stable@vger.kernel.org
Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
Link: https://patch.msgid.link/20260507-usb-midi-endpoint-scan-bounds-v1-1-329d7348160e@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/usb/midi.c

index 0a5b8941ebdaaf327944ed2e4b80946a33e1dba8..d87e3f357cf71b216df74bf9e666cf2ab642c973 100644 (file)
@@ -1951,15 +1951,17 @@ static struct usb_ms_endpoint_descriptor *find_usb_ms_endpoint_descriptor(
        while (extralen > 3) {
                struct usb_ms_endpoint_descriptor *ms_ep =
                                (struct usb_ms_endpoint_descriptor *)extra;
+               int length = ms_ep->bLength;
 
-               if (ms_ep->bLength > 3 &&
+               if (!length || length > extralen)
+                       break;
+
+               if (length > 3 &&
                    ms_ep->bDescriptorType == USB_DT_CS_ENDPOINT &&
                    ms_ep->bDescriptorSubtype == UAC_MS_GENERAL)
                        return ms_ep;
-               if (!extra[0])
-                       break;
-               extralen -= extra[0];
-               extra += extra[0];
+               extralen -= length;
+               extra += length;
        }
        return NULL;
 }