Linux Sound subsystem development
 help / color / mirror / Atom feed
* [PATCH] ALSA: pcm: oss: Serialize final setup list cleanup
@ 2026-10-17  7:27 Cen Zhang
  2026-10-17  8:19 ` Takashi Iwai
  0 siblings, 1 reply; 3+ messages in thread
From: Cen Zhang @ 2026-10-17  7:27 UTC (permalink / raw)
  To: perex, tiwai; +Cc: linux-sound, linux-kernel, baijiaju1990, jjzuming, zzzccc427

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

---
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index bd19328dca9e..ac7f6f1384fc 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -3111,6 +3111,7 @@ static void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
 		struct snd_pcm_str *pstr = &pcm->streams[stream];
 		snd_info_free_entry(pstr->oss.proc_entry);
 		pstr->oss.proc_entry = NULL;
+		guard(mutex)(&pstr->oss.setup_mutex);
 		snd_pcm_oss_proc_free_setup_list(pstr);
 	}
 }

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-17  8:44 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-17  7:27 [PATCH] ALSA: pcm: oss: Serialize final setup list cleanup Cen Zhang
2026-10-17  8:19 ` Takashi Iwai
2026-10-17  8:43   ` Cen Zhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox