All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Doruk Tan Ozturk <doruk@0sec.ai>
Cc: Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>,
	linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] ALSA: seq: fix use-after-free of borrowed substream in snd-seq-midi
Date: Thu, 11 Jun 2026 09:25:56 +0200	[thread overview]
Message-ID: <87pl1xk06z.wl-tiwai@suse.de> (raw)
In-Reply-To: <20260610200336.33979-1-doruk@0sec.ai>

On Wed, 10 Jun 2026 22:03:36 +0200,
Doruk Tan Ozturk wrote:
> 
> event_process_midi() borrows the rawmidi output substream via
> msynth->output_rfile.output and uses it through dump_midi() ->
> snd_rawmidi_kernel_write() -> snd_rawmidi_kernel_write1() without
> synchronizing against a concurrent port unsubscribe.
> 
> A concurrent UNSUBSCRIBE_PORT on the output connection runs the
> unuse callback midisynth_unuse() -> snd_rawmidi_kernel_release() ->
> close_substream() -> snd_rawmidi_runtime_free(), freeing
> substream->runtime while an in-flight event_input callback is still
> inside snd_rawmidi_kernel_write1(). The borrowed substream runtime is
> exposed to teardown before the write path takes its own buffer
> reference (snd_rawmidi_buffer_ref()), so the early derefs of
> substream->runtime / runtime->buffer read freed memory.
> 
> The buggy scenario involves two paths, with each column showing the
> order within that path:
> 
>   path A: event_input path                path B: last unuse path
>   1. event_process_midi() reads           1. midisynth_unuse() runs on the
>      msynth->output_rfile.output.            last UNSUBSCRIBE_PORT.
>   2. snd_rawmidi_kernel_write1() has      2. snd_rawmidi_kernel_release()
>      not yet pinned runtime.                 closes the output file.
>   3. The writer continues using           3. close_substream() frees
>      the borrowed substream.                 substream->runtime.
> 
> This is the snd-seq-midi sibling of the UMP-bridge race fixed by
> commit 60a1969fae62 ("ALSA: seq: Serialize UMP output teardown with
> event_input"); mirror its approach here.
> 
> Add a per-msynth rwlock for the event_input-visible output file.
> Publish a newly opened output file under the write side once it is
> fully set up, and hold the read side from the output lookup through
> snd_rawmidi_kernel_write() in event_process_midi(). The last unuse
> copies and clears the visible output file under the write side, then
> drops the lock and drains/releases the saved rawmidi file outside it
> (drain/release may sleep). Use IRQ-safe rwlock guards because
> event_input can be reached from atomic sequencer delivery.
> 
> Reproduced under KASAN: a single subscription to the midisynth output
> port (so the subscriber count oscillates 0<->1 and every unsubscribe
> frees the runtime via snd_rawmidi_kernel_release) is raced against a
> flood of events driving event_process_midi -> snd_rawmidi_kernel_write1.
> The narrow window (the runtime is read before snd_rawmidi_buffer_ref())
> was widened with an injected delay to land the race deterministically;
> the freed object is the kmalloc-192 snd_rawmidi_runtime. With this patch
> applied the same forced race shows no use-after-free.
> 
>   BUG: KASAN: slab-use-after-free in snd_rawmidi_kernel_write1+0x73e/0x800
>   Read of size 8 at addr ffff88800b04f310 by task seqmidi_uaf2/84
>   Call Trace:
>    snd_rawmidi_kernel_write1+0x73e/0x800
>    __dump_midi+0x70/0x100
>    dump_var_event+0x290/0x320
>    event_process_midi+0x1ff/0x310
>    snd_seq_deliver_single_event+0x1e6/0x670
>    snd_seq_deliver_event+0x323/0x5f0
>    snd_seq_client_enqueue_event.constprop.0+0x226/0x400
>    snd_seq_write+0x2f1/0x530
>    vfs_write+0x21e/0xd30
>    ksys_write+0x17c/0x1c0
>    do_syscall_64+0xf9/0x540
> 
>   Allocated by task 85:
>    open_substream+0xc7/0x7a0
>    rawmidi_open_priv+0x3df/0x660
>    snd_rawmidi_kernel_open+0x95/0x140
>    midisynth_use+0xda/0x1f0
>    check_and_subscribe_port+0x707/0xbd0
>    snd_seq_ioctl_subscribe_port+0x1f4/0x400
> 
>   Freed by task 85:
>    close_substream.part.0+0x1f9/0x790
>    rawmidi_release_priv+0x1b0/0x240
>    snd_rawmidi_kernel_release+0x2d/0xb0
>    __delete_and_unsubscribe_port+0x1b9/0x3c0
>    snd_seq_ioctl_unsubscribe_port+0x1ee/0x400
> 
>   The buggy address belongs to the object at ffff88800b04f300
>    which belongs to the cache kmalloc-192 of size 192
> 
> Found by 0sec.
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: stable@vger.kernel.org
> Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>

There has been already a similar fix queued in sound.git tree for-next
branch:
ef7607ab1c8adc6258fb1b27d08e26aecdc18a58
    ALSA: seq: midi: Serialize output teardown with event_input

I believe this already addressed the bug.

Let me know if there is still anything missing.


thanks,

Takashi

  reply	other threads:[~2026-06-11  7:25 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-10 20:03 [PATCH] ALSA: seq: fix use-after-free of borrowed substream in snd-seq-midi Doruk Tan Ozturk
2026-06-11  7:25 ` Takashi Iwai [this message]
2026-06-15  0:28   ` Doruk Tan Ozturk
2026-06-15  7:26     ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87pl1xk06z.wl-tiwai@suse.de \
    --to=tiwai@suse.de \
    --cc=doruk@0sec.ai \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.