Linux Sound subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Cen Zhang" <zzzccc427@gmail.com>
Cc: linux-sound@vger.kernel.org
Subject: Re: [PATCH v3] ALSA: pcm: Drain proc callbacks at device disconnect
Date: Thu, 22 Oct 2026 11:17:33 +0000	[thread overview]
Message-ID: <sashiko-outbox-181365@kernel.org> (raw)
In-Reply-To: <pm-pmb-2439c851f82c443c3600-v7-2774a482b7f03e1fef60@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] ALSA: info: snd_info_disconnect_entry() allows proc subtree republishing
--

commit 734aaf0e640d58ff92175c5964010543a8f73ca6
Author: Cen Zhang <zzzccc427@gmail.com>

ALSA: pcm: Drain proc callbacks at device disconnect

This commit introduces snd_info_disconnect_entry() to remove procfs nodes and
drain their callbacks without freeing the info entries, and calls it from
snd_pcm_dev_disconnect() after dropping open_mutex so that buffered prealloc
proc writes cannot run after PCM buffer teardown.

> diff --git a/sound/core/info.c b/sound/core/info.c
> index c4d57d0809adf..023b4736aa6de 100644
> --- a/sound/core/info.c
> +++ b/sound/core/info.c
> @@ -737,6 +737,23 @@ static void snd_info_clear_entries(struct snd_info_entry *entry)
>  	entry->p = NULL;
>  }
>  
> +/**
> + * snd_info_disconnect_entry - remove proc nodes and drain their callbacks
> + * @entry: root of the info entry subtree
> + *
> + * Retains the info entries for snd_info_free_entry().  Callers must serialize
> + * registration and destruction, and must not hold locks needed by callbacks.
> + */
> +void snd_info_disconnect_entry(struct snd_info_entry *entry)
> +{
> +	if (entry && entry->p) {
> +		proc_remove(entry->p);
> +		guard(mutex)(&info_mutex);
> +		snd_info_clear_entries(entry);
> +	}
> +}
> +EXPORT_SYMBOL(snd_info_disconnect_entry);

[Severity: High]
Can a disconnected PCM stream proc subtree be republished if
snd_info_card_register() runs before snd_pcm_free_stream() frees the
entries?

In sound/core/pcm.c, snd_pcm_stream_proc_init() attaches pstr->proc_root to
pcm->card->proc_root->children via snd_info_create_card_entry(). When
snd_pcm_dev_disconnect() calls snd_pcm_stream_proc_disconnect() ->
snd_info_disconnect_entry(pstr->proc_root), snd_info_clear_entries() clears
entry->p to NULL across the subtree while leaving pstr->proc_root linked on
card->proc_root->children:

sound/core/info.c:snd_info_clear_entries() {
	if (!entry->p)
		return;
	list_for_each_entry(p, &entry->children, list)
		snd_info_clear_entries(p);
	entry->p = NULL;
}

During HDA codec unbind in sound/hda/common/bind.c,
hda_codec_driver_remove() disconnects the codec PCMs and then waits for
active references before freeing the PCM devices:

sound/hda/common/bind.c:hda_codec_driver_remove() {
	...
	snd_hda_codec_disconnect_pcms(codec);
	snd_hda_jack_tbl_disconnect(codec);
	snd_refcount_sync(&codec->pcm_ref);
	snd_power_sync_ref(codec->bus->card);

	if (driver->ops->remove)
		driver->ops->remove(codec);
	snd_hda_codec_cleanup_for_unbind(codec);
}

While hda_codec_driver_remove() is waiting in snd_refcount_sync() (for
example, while userspace holds an open PCM file descriptor on that codec),
binding or reconfiguring another codec on the same card calls
hda_codec_driver_probe() (in sound/hda/common/bind.c) or reconfig_codec()
(in sound/hda/common/sysfs.c) -> snd_card_register() ->
snd_info_card_register() -> snd_info_register(card->proc_root):

sound/core/info.c:snd_info_register() {
	if (!entry->p) {
		err = __snd_info_register(entry);
		if (err < 0)
			return err;
	}

	list_for_each_entry(p, &entry->children, list) {
		err = snd_info_register(p);
		if (err < 0)
			return err;
	}
}

Because the disconnected pstr->proc_root subtree is still on
card->proc_root->children with entry->p == NULL, snd_info_register() treats
it as unregistered and calls __snd_info_register() on the subtree,
recreating the procfs nodes (including subN/prealloc).

When the unbinding codec then reaches snd_hda_codec_cleanup_for_unbind() ->
codec_release_pcms() -> snd_device_free(), __snd_device_disconnect() (in
sound/core/device.c) is skipped because dev->state is already
SNDRV_DEV_DISCONNECTED. snd_pcm_free() then calls
snd_pcm_lib_preallocate_free_for_all() while the republished prealloc proc
node is still active, reintroducing the race with
snd_info_text_entry_release() -> snd_pcm_lib_preallocate_proc_write() and
allowing concurrent list traversal on card->proc_root->children between
snd_info_register() and snd_info_free_entry().

Should snd_info_disconnect_entry() unlink the entry from
entry->parent->children or otherwise prevent snd_info_register() from
re-registering a disconnected subtree?

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/pm-pmb-2439c851f82c443c3600-v7-2774a482b7f03e1fef60@gmail.com?part=1

  reply	other threads:[~2026-10-22 11:17 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-22 10:58 [PATCH v3] ALSA: pcm: Drain proc callbacks at device disconnect Cen Zhang
2026-10-22 11:17 ` sashiko-bot [this message]
2026-10-23 13:40 ` 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=sashiko-outbox-181365@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --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