summaryrefslogtreecommitdiff
path: root/sound/usb
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2025-02-18 12:40:24 +0100
committerTakashi Iwai <tiwai@suse.de>2025-02-18 13:17:15 +0100
commita3bdd8f5c2217e1cb35db02c2eed36ea20fb50f5 (patch)
tree45bdaf5d97ec2579e7b2ece7e86797dd8adf0113 /sound/usb
parente77aa4b2eaa7fb31b2a7a50214ecb946b2a8b0f6 (diff)
downloadlinux-a3bdd8f5c2217e1cb35db02c2eed36ea20fb50f5.tar.gz
linux-a3bdd8f5c2217e1cb35db02c2eed36ea20fb50f5.tar.bz2
linux-a3bdd8f5c2217e1cb35db02c2eed36ea20fb50f5.zip
ALSA: usb-audio: Avoid dropping MIDI events at closing multiple ports
We fixed the UAF issue in USB MIDI code by canceling the pending work at closing each MIDI output device in the commit below. However, this assumed that it's the only one that is tied with the endpoint, and it resulted in unexpected data truncations when multiple devices are assigned to a single endpoint and opened simultaneously. For addressing the unexpected MIDI message drops, simply replace cancel_work_sync() with flush_work(). The drain callback should have been already invoked before the close callback, hence the port->active flag must be already cleared. So this just assures that the pending work is finished before freeing the resources. Fixes: 0125de38122f ("ALSA: usb-audio: Cancel pending work at closing a MIDI substream") Reported-and-tested-by: John Keeping <jkeeping@inmusicbrands.com> Closes: https://lore.kernel.org/20250217111647.3368132-1-jkeeping@inmusicbrands.com Link: https://patch.msgid.link/20250218114024.23125-1-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/midi.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 737dd00e97b1..779d97d31f17 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -1145,7 +1145,7 @@ static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
{
struct usbmidi_out_port *port = substream->runtime->private_data;
- cancel_work_sync(&port->ep->work);
+ flush_work(&port->ep->work);
return substream_open(substream, 0, 0);
}