Re: [PATCH] ALSA: usb-audio: fix OOB write in snd_usbmidi_akai_output()

Takashi Iwai <[email protected]>
Newsgroups org.kernel.vger.linux-sound,org.kernel.vger.stable
Message-ID <[email protected]>
On Sun, 26 Jul 2026 07:20:40 +0200,
Baul Lee wrote:
> 
> snd_usbmidi_akai_output() computes its fill-loop bound
> 
> 	buf_end = ep->max_transfer - MAX_AKAI_SYSEX_LEN - 1;
> 
> as a signed int, so a small device-advertised bulk-OUT max_transfer
> makes buf_end negative.  The loop guard then compares the u32
> urb->transfer_buffer_length against that negative int: the usual
> arithmetic conversion turns buf_end into a large unsigned value, so the
> guard stays true and each iteration keeps appending SysEx framing and
> payload bytes past the end of the URB transfer buffer, which is only
> max_transfer bytes long.
> 
> A USB device that advertises a tiny bulk-OUT endpoint can therefore
> trigger an attacker-length- and content-controlled heap out-of-bounds
> write when a process writes to the created /dev/snd/midiC*D* node.
> 
> Perform the comparison in signed arithmetic so that a negative buf_end
> stops the loop instead of wrapping to a huge unsigned bound.
> 
> Discovered by XBOW, triaged by Baul Lee <[email protected]>
> 
> Fixes: 4434ade8c933 ("ALSA: usb-audio: add support for Akai MPD16")
> Reported-by: Federico Kirschbaum <[email protected]>
> Reported-by: Baul Lee <[email protected]>
> Cc: [email protected]
> Signed-off-by: Baul Lee <[email protected]>
> ---
>  sound/usb/midi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/sound/usb/midi.c b/sound/usb/midi.c
> index d87e3f357cf7..cc7df77632a1 100644
> --- a/sound/usb/midi.c
> +++ b/sound/usb/midi.c
> @@ -799,7 +799,7 @@ static void snd_usbmidi_akai_output(struct snd_usb_midi_out_endpoint *ep,
>  	buf_end = ep->max_transfer - MAX_AKAI_SYSEX_LEN - 1;
>  
>  	/* only try adding more data when there's space for at least 1 SysEx */
> -	while (urb->transfer_buffer_length < buf_end) {
> +	while ((int)urb->transfer_buffer_length < buf_end) {
>  		count = snd_rawmidi_transmit_peek(substream,
>  						  tmp, MAX_AKAI_SYSEX_LEN);
>  		if (!count) {

The code change looks correct, but I believe the intention can be
understandable by a more explicit check like the below.
Could you verify it and submit v2 if it works?


thanks,

Takashi

-- 8< --
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -797,6 +797,8 @@ static void snd_usbmidi_akai_output(struct snd_usb_midi_out_endpoint *ep,
 
 	msg = urb->transfer_buffer + urb->transfer_buffer_length;
 	buf_end = ep->max_transfer - MAX_AKAI_SYSEX_LEN - 1;
+	if (buf_end <= 0)
+		return;
 
 	/* only try adding more data when there's space for at least 1 SysEx */
 	while (urb->transfer_buffer_length < buf_end) {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.