All of lore.kernel.org
 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 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.