mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] ALSA: rawmidi: Drain input work before freeing the runtime
@ 2026-10-13  7:54 Cen Zhang
  2026-10-13  9:42 ` Takashi Iwai
  0 siblings, 1 reply; 2+ messages in thread
From: Cen Zhang @ 2026-10-13  7:54 UTC (permalink / raw)
  To: perex, tiwai, phucduc.bui, len.bao, hariconscious, sammiee5311,
	kees, akhilarul324, cezary.rojewski
  Cc: linux-sound, linux-kernel, baijiaju1990, jjzuming, zzzccc427

The input runtime embeds event_work, so the work must be drained before
close_substream() frees the runtime. The cancellation in
snd_rawmidi_input_trigger() runs before close clears substream->opened,
leaving a window for snd_rawmidi_receive() to enqueue more work.

With a sequencer subscription to a USB MIDI input port, an in-flight
completion can overlap the last subscription's midisynth_unsubscribe():

1. snd_usbmidi_input_data() observes input_triggered and is delayed
   before calling snd_rawmidi_receive().
2. Unsubscribe enters close_substream(), clears input_triggered through
   the provider trigger callback and returns from cancel_work_sync().
   The substream is still opened.
3. The completion resumes. snd_rawmidi_receive() takes substream->lock,
   sees opened set and queues runtime->event_work before dropping the
   lock.
4. Close clears opened under that lock, closes the provider and frees
   the runtime. Stopping USB URBs does not drain the raw-MIDI work.
5. The queued work runs and snd_rawmidi_input_event_work() reads event
   or substream from the freed runtime, causing a use-after-free.

Cancel input event_work again after clearing opened, before closing the
provider or releasing the runtime's private data. Receive holds
substream->lock through its opened check and work enqueue, so once close
has cleared opened under that lock, no further receive can queue work.
The final cancellation therefore drains any late work before the
runtime is freed. Keep it outside the spinlock so a running callback can
finish.

Fixes: b3c705aa9e91 ("ALSA: rawmidi - Use workq for event handling")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---

diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index c43cedb5c12158978054400d4c22adf00eaf6b1d..630d9fc8e9da0a0e7d6a2eded6aed531b094b932 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -607,6 +607,9 @@ static void close_substream(struct snd_rawmidi *rmidi,
 		substream->opened = 0;
 		substream->append = 0;
 	}
+	/* Drain input work queued after the earlier cancellation. */
+	if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)
+		cancel_work_sync(&substream->runtime->event_work);
 	substream->ops->close(substream);
 	if (substream->runtime->private_free)
 		substream->runtime->private_free(substream);

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] ALSA: rawmidi: Drain input work before freeing the runtime
  2026-10-13  7:54 [PATCH] ALSA: rawmidi: Drain input work before freeing the runtime Cen Zhang
@ 2026-10-13  9:42 ` Takashi Iwai
  0 siblings, 0 replies; 2+ messages in thread
From: Takashi Iwai @ 2026-10-13  9:42 UTC (permalink / raw)
  To: Cen Zhang
  Cc: perex, tiwai, phucduc.bui, len.bao, hariconscious, sammiee5311,
	kees, akhilarul324, cezary.rojewski, linux-sound, linux-kernel,
	baijiaju1990, jjzuming

On Tue, 13 Oct 2026 09:54:35 +0200,
Cen Zhang wrote:
> 
> The input runtime embeds event_work, so the work must be drained before
> close_substream() frees the runtime. The cancellation in
> snd_rawmidi_input_trigger() runs before close clears substream->opened,
> leaving a window for snd_rawmidi_receive() to enqueue more work.
> 
> With a sequencer subscription to a USB MIDI input port, an in-flight
> completion can overlap the last subscription's midisynth_unsubscribe():
> 
> 1. snd_usbmidi_input_data() observes input_triggered and is delayed
>    before calling snd_rawmidi_receive().
> 2. Unsubscribe enters close_substream(), clears input_triggered through
>    the provider trigger callback and returns from cancel_work_sync().
>    The substream is still opened.
> 3. The completion resumes. snd_rawmidi_receive() takes substream->lock,
>    sees opened set and queues runtime->event_work before dropping the
>    lock.
> 4. Close clears opened under that lock, closes the provider and frees
>    the runtime. Stopping USB URBs does not drain the raw-MIDI work.
> 5. The queued work runs and snd_rawmidi_input_event_work() reads event
>    or substream from the freed runtime, causing a use-after-free.
> 
> Cancel input event_work again after clearing opened, before closing the
> provider or releasing the runtime's private data. Receive holds
> substream->lock through its opened check and work enqueue, so once close
> has cleared opened under that lock, no further receive can queue work.
> The final cancellation therefore drains any late work before the
> runtime is freed. Keep it outside the spinlock so a running callback can
> finish.
> 
> Fixes: b3c705aa9e91 ("ALSA: rawmidi - Use workq for event handling")
> Assisted-by: LLM
> Signed-off-by: Cen Zhang <zzzccc427@gmail.com>

Applied to for-next branch now.  Thanks.


Takashi

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-13  9:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-13  7:54 [PATCH] ALSA: rawmidi: Drain input work before freeing the runtime Cen Zhang
2026-10-13  9:42 ` Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®