mirror-linux/sound/core/seq
Zhang Cen 60a1969fae ALSA: seq: Serialize UMP output teardown with event_input
seq_ump_process_event() borrows client->out_rfile.output without
synchronizing with the first-open and last-close transition in
seq_ump_client_open() and seq_ump_client_close().

The last output unuse can therefore drop opened[STR_OUT] to zero and
release the rawmidi file while an in-flight event_input callback is still
inside snd_rawmidi_kernel_write(). That leaves the rawmidi substream
runtime exposed to teardown before the write path has taken its own
buffer reference.

Add a per-client rwlock for the event_input-visible output file. Publish
a newly opened output file under the write side, and hold the read side
from the output lookup through snd_rawmidi_kernel_write(). The last
output close copies and clears the visible output file under the write
side, then drops the lock and releases the saved rawmidi file. Use
IRQ-safe rwlock guards because event_input can also be reached from
atomic sequencer delivery.

The buggy scenario involves two paths, with each column showing the
order within that path:

path A label: event_input path         path B label: last unuse path
1. seq_ump_process_event() reads       1. seq_ump_client_close()
   client->out_rfile.output.              drops opened[STR_OUT] to zero.
2. snd_rawmidi_kernel_write1()         2. snd_rawmidi_kernel_release()
   has not yet pinned runtime.            closes the output file.
3. The writer continues using          3. close_substream() frees
   the borrowed substream.                substream->runtime.

This keeps the output substream and runtime alive for the full
event_input write while keeping rawmidi release outside the rwlock.

KASAN reproduced this as a slab-use-after-free in
snd_rawmidi_kernel_write1(), with allocation through
seq_ump_use()/snd_seq_port_connect() and free through
seq_ump_unuse()/snd_seq_port_disconnect().

Suggested-by: Takashi Iwai <tiwai@suse.de>

Validation reproduced this kernel report:
KASAN slab-use-after-free in snd_rawmidi_kernel_write1+0x9d/0x400
RIP: 0033:0x7f5528af837f
Read of size 8
Call trace:
  dump_stack_lvl+0x73/0xb0 (?:?)
  print_report+0xd1/0x650 (?:?)
  srso_alias_return_thunk+0x5/0xfbef5 (?:?)
  __virt_addr_valid+0x1a7/0x340 (?:?)
  kasan_complete_mode_report_info+0x64/0x200 (?:?)
  kasan_report+0xf7/0x130 (?:?)
  snd_rawmidi_kernel_write1+0x9d/0x400 (?:?)
  __asan_load8+0x82/0xb0 (?:?)
  update_stack_state+0x1ef/0x2d0 (?:?)
  snd_rawmidi_kernel_write+0x1a/0x20 (?:?)
  seq_ump_process_event+0xd4/0x120 (sound/core/seq/seq_ump_client.c:82)
  __snd_seq_deliver_single_event+0x8a/0xe0 (?:?)
  snd_seq_deliver_from_ump+0x2b2/0xd60 (?:?)
  lock_acquire+0x14e/0x2e0 (?:?)
  find_held_lock+0x31/0x90 (?:?)
  snd_seq_port_use_ptr+0xa6/0xe0 (?:?)
  __kasan_check_write+0x18/0x20 (?:?)
  do_raw_read_unlock+0x32/0xa0 (?:?)
  _raw_read_unlock+0x26/0x50 (?:?)
  snd_seq_deliver_single_event+0x45c/0x4b0 (?:?)
  snd_seq_deliver_event+0x10d/0x1b0 (?:?)
  snd_seq_client_enqueue_event+0x192/0x240 (?:?)
  snd_seq_write+0x2cd/0x450 (?:?)
  apparmor_file_permission+0x20/0x30 (?:?)
  security_file_permission+0x51/0x60 (?:?)
  vfs_write+0x1ce/0x850 (?:?)
  __fget_files+0x12b/0x220 (?:?)
  lock_release+0xc8/0x2a0 (?:?)
  __rcu_read_unlock+0x74/0x2d0 (?:?)
  __fget_files+0x135/0x220 (?:?)
  ksys_write+0x15a/0x180 (?:?)
  rcu_is_watching+0x24/0x60 (?:?)
  __x64_sys_write+0x46/0x60 (?:?)
  x64_sys_call+0x7d/0x20d0 (?:?)
  do_syscall_64+0xc1/0x360 (arch/x86/entry/syscall_64.c:87)
  entry_SYSCALL_64_after_hwframe+0x77/0x7f (?:?)

Fixes: 81fd444aa3 ("ALSA: seq: Bind UMP device")
Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
Link: https://patch.msgid.link/20260520103249.3048345-1-rollkingzzc@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2026-05-20 13:10:40 +02:00
..
oss ALSA: seq_oss: return full count for successful SEQ_FULLSIZE writes 2026-03-27 14:40:24 +01:00
Kconfig ALSA: seq: Make dependency on UMP clearer 2025-01-01 13:56:48 +01:00
Makefile ALSA: core: Use *-y instead of *-objs in Makefile 2024-05-08 18:17:32 +02:00
seq.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
seq_clientmgr.c ALSA: seq: Fix UMP group 16 filtering 2026-05-06 09:56:54 +02:00
seq_clientmgr.h ALSA: seq: Fix UMP group 16 filtering 2026-05-06 09:56:54 +02:00
seq_compat.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
seq_dummy.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
seq_fifo.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
seq_fifo.h ALSA: seq: Clean up fifo locking with guard 2025-08-29 11:52:36 +02:00
seq_info.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
seq_info.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
seq_lock.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
seq_lock.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
seq_memory.c Convert more 'alloc_obj' cases to default GFP_KERNEL arguments 2026-02-21 20:03:00 -08:00
seq_memory.h ALSA: seq: Add UMP support 2023-05-23 12:11:21 +02:00
seq_midi.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
seq_midi_emul.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
seq_midi_event.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
seq_ports.c ALSA: seq: avoid past-the-end iterator in snd_seq_create_port() 2026-05-19 07:39:06 +02:00
seq_ports.h ALSA: seq: Clean up port locking with auto cleanup 2025-08-29 11:52:35 +02:00
seq_prioq.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
seq_prioq.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
seq_queue.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
seq_queue.h ALSA: seq: Clean up queue locking with auto cleanup 2025-08-29 11:52:35 +02:00
seq_system.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
seq_system.h ALSA: seq: Notify UMP EP and FB changes 2025-01-12 13:12:21 +01:00
seq_timer.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
seq_timer.h ALSA: seq: Remove unused declarations 2024-08-17 16:32:31 +02:00
seq_ump_client.c ALSA: seq: Serialize UMP output teardown with event_input 2026-05-20 13:10:40 +02:00
seq_ump_convert.c ALSA: core/seq: Optimize the return logic in cc_ev_to_ump_midi2 2026-03-27 14:40:24 +01:00
seq_ump_convert.h ALSA: seq: Fix delivery of UMP events to group ports 2025-05-11 15:58:06 +02:00
seq_virmidi.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00