Linux Sound subsystem development
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Cen Zhang <zzzccc427@gmail.com>
Cc: perex@perex.cz, tiwai@suse.com, linux-sound@vger.kernel.org,
	linux-kernel@vger.kernel.org, baijiaju1990@gmail.com,
	jjzuming@gmail.com
Subject: Re: [PATCH] ALSA: pcm: oss: Serialize final setup list cleanup
Date: Sat, 17 Oct 2026 10:19:40 +0200	[thread overview]
Message-ID: <87o6cs20yr.wl-tiwai@suse.de> (raw)
In-Reply-To: <pm-pmb-a4703edca61d34aa679b-v6-680f350d78e44f9de7a7@gmail.com>

On Sat, 17 Oct 2026 09:27:19 +0200,
Cen Zhang wrote:
> 
> OSS setup nodes and their task names must remain valid throughout
> snd_pcm_oss_look_for_setup(). The lookup holds setup_mutex while
> comparing names, traversing the list and copying a matched record, but
> snd_pcm_oss_proc_done() frees that list without taking the mutex.
> 
> With verbose proc support enabled, an OSS open on a stream with a
> populated setup list can overlap HDA codec unbind. The card remains
> registered, so the card-file reference does not prevent the PCM
> component from being freed.
> 
> The lookup runs before pcm->open_mutex is taken and before the driver
> acquires a PCM reference. Codec unbind disconnects the PCM and drains
> existing codec PCM references first. Its cleanup then reaches
> snd_pcm_free() through codec_release_pcms() and snd_device_free(). The
> n_unregister callback invokes snd_pcm_oss_unregister_minor() and
> snd_pcm_oss_proc_done().
> 
> Both columns below access the setup list of the same PCM stream. Without
> this fix, cleanup does not take setup_mutex:
> 
>   OSS open                        HDA PCM teardown
>   --------                        ----------------
>   snd_pcm_oss_look_for_setup()
>     lock(setup_mutex)
>     setup = setup_list
>                                   snd_pcm_oss_proc_done()
>                                     snd_info_free_entry()
>                                     /* no setup_mutex held */
>                                     snd_pcm_oss_proc_free_setup_list()
>                                       kfree(setup->task_name)
>                                       kfree(setup)
>     read setup->task_name
>     or setup->next -> UAF
> 
> Take setup_mutex around final list cleanup, as the proc clear/erase path
> already does. This waits for the active lookup to finish its reads and
> copy before freeing the nodes. Acquire the mutex after
> snd_info_free_entry() so proc callback rundown can finish without
> waiting on a mutex held by teardown.
> 
> KASAN report as below:
> 
>     BUG: KASAN: slab-use-after-free in snd_pcm_oss_look_for_setup+0x30c/0x3c0
>     Read of size 8 at addr ffff888106ecc2c0 by task pmbdossuaf/427
> 
>     CPU: 3 UID: 0 PID: 427 Comm: pmbdossuaf Not tainted 7.2.0-rc6-pmb-alsa-functional-v2+ #1 PREEMPT(lazy)
>     Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
>     Call Trace:
>      <TASK>
>      dump_stack_lvl+0x93/0xd0
>      print_report+0xce/0x630
>      ? snd_pcm_oss_look_for_setup+0x30c/0x3c0
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      ? __virt_addr_valid+0x20d/0x410
>      ? snd_pcm_oss_look_for_setup+0x30c/0x3c0
>      kasan_report+0xe0/0x110
>      ? snd_pcm_oss_look_for_setup+0x30c/0x3c0
>      snd_pcm_oss_look_for_setup+0x30c/0x3c0
>      snd_pcm_oss_open+0xd38/0x1240
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      ? avc_has_perm_noaudit+0x4a/0x330
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      ? find_held_lock+0x2b/0x80
>      ? __pfx_snd_pcm_oss_open+0x10/0x10
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      ? __lock_acquire+0x466/0x2260
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      ? lock_release+0xc8/0x280
>      ? __pfx_snd_pcm_oss_open+0x10/0x10
>      soundcore_open+0x3ae/0x510
>      ? __pfx_soundcore_open+0x10/0x10
>      chrdev_open+0x21f/0x660
>      ? __pfx_chrdev_open+0x10/0x10
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      do_dentry_open+0x5c8/0x1300
>      ? __pfx_chrdev_open+0x10/0x10
>      ? security_inode_permission+0x5d/0xb0
>      vfs_open+0x87/0x390
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      path_openat+0x2460/0x3cd0
>      ? do_syscall_64+0x115/0x6a0
>      ? entry_SYSCALL_64_after_hwframe+0x77/0x7f
>      ? __pfx_path_openat+0x10/0x10
>      do_file_open+0x21e/0x470
>      ? __pfx_do_file_open+0x10/0x10
>      ? _raw_spin_unlock+0x23/0x40
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      ? alloc_fd+0x3a6/0x6b0
>      do_sys_openat2+0xf4/0x1b0
>      ? __pfx_do_sys_openat2+0x10/0x10
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      __x64_sys_openat+0x136/0x1e0
>      ? __pfx___x64_sys_openat+0x10/0x10
>      ? irqentry_exit+0xbe/0x820
>      ? srso_alias_return_thunk+0x5/0xfbef5
>      do_syscall_64+0x115/0x6a0
>      entry_SYSCALL_64_after_hwframe+0x77/0x7f
>     RIP: 0033:0x7f687d8c4687
>     Code: 48 89 fa 4c 89 df e8 58 b3 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
>     RSP: 002b:00007ffca02dde50 EFLAGS: 00000202 ORIG_RAX: 0000000000000101
>     RAX: ffffffffffffffda RBX: 00007f687d830780 RCX: 00007f687d8c4687
>     RDX: 0000000000080801 RSI: 00007f687d518b90 RDI: ffffffffffffff9c
>     RBP: 00007f687d66e1c8 R08: 0000000000000000 R09: 0000000000000000
>     R10: 0000000000000000 R11: 0000000000000202 R12: 00000000000001ff
>     R13: 00007f687d356830 R14: 00007ffca02ddf30 R15: 00007f687d518b90
>      </TASK>
> 
>     Allocated by task 426:
>      kasan_save_stack+0x33/0x60
>      kasan_save_track+0x14/0x30
>      __kasan_kmalloc+0xaa/0xb0
>      __kmalloc_cache_noprof+0x251/0x610
>      snd_pcm_oss_proc_write+0x619/0x950
>      snd_info_text_entry_release+0x100/0x260
>      close_pdeo.part.0+0xe0/0x2e0
>      close_pdeo+0x161/0x180
>      proc_reg_release+0x185/0x1f0
>      __fput+0x39f/0xa60
>      fput_close_sync+0xff/0x200
>      __x64_sys_close+0x8c/0xf0
>      do_syscall_64+0x115/0x6a0
>      entry_SYSCALL_64_after_hwframe+0x77/0x7f
> 
>     Freed by task 428:
>      kasan_save_stack+0x33/0x60
>      kasan_save_track+0x14/0x30
>      kasan_save_free_info+0x3b/0x60
>      __kasan_slab_free+0x5f/0x80
>      kfree+0x307/0x580
>      snd_pcm_oss_proc_free_setup_list+0x9c/0x140
>      snd_pcm_oss_unregister_minor+0x203/0x450
>      snd_pcm_free+0xb0/0x180
>      __snd_device_free+0x193/0x3f0
>      snd_device_free+0xcf/0x190
>      snd_hda_codec_cleanup_for_unbind+0x1b3/0xad0
>      hda_codec_driver_remove+0x1c4/0x2e0
>      device_remove+0x12a/0x170
>      device_release_driver_internal+0x471/0x650
>      unbind_store+0xfd/0x110
>      drv_attr_store+0x79/0xb0
>      sysfs_kf_write+0xed/0x140
>      kernfs_fop_write_iter+0x34b/0x500
>      vfs_write+0x637/0x1010
>      ksys_write+0x111/0x200
>      do_syscall_64+0x115/0x6a0
>      entry_SYSCALL_64_after_hwframe+0x77/0x7f
> 
>     The buggy address belongs to the object at ffff888106ecc2c0
>      which belongs to the cache kmalloc-32 of size 32
>     The buggy address is located 0 bytes inside of
>      freed 32-byte region [ffff888106ecc2c0, ffff888106ecc2e0)
> 
>     The buggy address belongs to the physical page:
>     page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x106ecc
>     flags: 0x200000000000000(node=0|zone=2)
>     page_type: f5(slab)
>     raw: 0200000000000000 ffff888100042780 dead000000000100 dead000000000122
>     raw: 0000000000000000 0000000000400040 00000000f5000000 0000000000000000
>     page dumped because: kasan: bad access detected
> 
>     Memory state around the buggy address:
>      ffff888106ecc180: fa fb fb fb fc fc fc fc fa fb fb fb fc fc fc fc
>      ffff888106ecc200: fa fb fb fb fc fc fc fc fa fb fb fb fc fc fc fc
>     >ffff888106ecc280: fa fb fb fb fc fc fc fc fa fb fb fb fc fc fc fc
>                                                ^
>      ffff888106ecc300: fa fb fb fb fc fc fc fc fa fb fb fb fc fc fc fc
>      ffff888106ecc380: fa fb fb fb fc fc fc fc fa fb fb fb fc fc fc fc
>     ==================================================================
> 
> Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
> Assisted-by: LLM

How can this happen?  The PCM proc file belongs to the card, and
snd_oss_proc_done() is called from snd_pcm_free() at the card removal,
where all opened descriptors must have been released before reaching
this point and no new open is allowed any longer.


thanks,

Takashi

  reply	other threads:[~2026-10-17  8:19 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-17  7:27 [PATCH] ALSA: pcm: oss: Serialize final setup list cleanup Cen Zhang
2026-10-17  8:19 ` Takashi Iwai [this message]
2026-10-17  8:43   ` Cen Zhang

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=87o6cs20yr.wl-tiwai@suse.de \
    --to=tiwai@suse.de \
    --cc=baijiaju1990@gmail.com \
    --cc=jjzuming@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.com \
    --cc=zzzccc427@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox