--- a/include/sound/rawmidi.h 2022-04-18 21:22:12.796709600 +0800 +++ b/include/sound/rawmidi.h 2022-04-18 21:37:16.707449200 +0800 @@ -64,7 +64,10 @@ struct snd_rawmidi_runtime { int buffer_ref; /* buffer reference count */ /* misc */ spinlock_t lock; - wait_queue_head_t sleep; + union { + wait_queue_head_t sleep; + struct rcu_head rcu; + }; /* event handler (new bytes, input only) */ void (*event)(struct snd_rawmidi_substream *substream); /* defers calls to event [input] or ops->trigger [output] */ --- a/sound/core/rawmidi.c 2022-04-18 21:22:38.396495200 +0800 +++ b/sound/core/rawmidi.c 2022-04-18 21:50:05.563505500 +0800 @@ -169,13 +169,20 @@ static int snd_rawmidi_runtime_create(st return 0; } -static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream) +static void snd_rawmidi_runtime_free_rcufn(struct rcu_head *r) { - struct snd_rawmidi_runtime *runtime = substream->runtime; + struct snd_rawmidi_runtime *runtime = container_of(r, struct snd_rawmidi_runtime, rcu); kvfree(runtime->buffer); kfree(runtime); +} + +static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream) +{ + struct snd_rawmidi_runtime *runtime = substream->runtime; + substream->runtime = NULL; + call_rcu(&runtime->rcu, snd_rawmidi_runtime_free_rcufn); return 0; } @@ -1404,6 +1411,8 @@ int snd_rawmidi_transmit(struct snd_rawm int result; unsigned long flags; + if (!runtime) + return -EBADFD; spin_lock_irqsave(&runtime->lock, flags); if (!substream->opened) result = -EBADFD;