All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ASoC: soc-core: fix use-after-free in snd_soc_unbind_card()
@ 2026-03-08 11:09 Matteo Cotifava
  2026-03-09 15:01 ` Mark Brown
  0 siblings, 1 reply; 8+ messages in thread
From: Matteo Cotifava @ 2026-03-08 11:09 UTC (permalink / raw)
  To: lgirdwood, broonie
  Cc: perex, tiwai, srini, cujomalainey, linux-sound, linux-kernel,
	Matteo Cotifava

When a sound card is unbound (e.g. on module removal) while a PCM
stream close is pending, a race between the close delayed work and
soc_cleanup_card_resources() can cause a use-after-free:

  BUG: KASAN: use-after-free in snd_soc_dapm_stream_event+0x39c/0x430
  Read of size 8 at addr ffff00000a29a918 by task kworker/u8:0/8

  CPU: 2 PID: 8 Comm: kworker/u8:0 Not tainted 5.15.71 #1
  Hardware name: NXP i.MX8MM
  Workqueue: events_power_efficient close_delayed_work
  Call trace:
   snd_soc_dapm_stream_event+0x39c/0x430
   snd_soc_close_delayed_work+0x208/0x2ac
   close_delayed_work+0x3c/0x54
   process_one_work+0x670/0xfd4
   worker_thread+0x84c/0xe74
   kthread+0x370/0x410
   ret_from_fork+0x10/0x20

  Allocated by task 8:
   snd_soc_dapm_new_control_unlocked+0x2c/0xbc4
   snd_soc_dapm_new_dai_widgets+0x12c/0x35c
   soc_probe_component+0x418/0xbb0
   snd_soc_bind_card+0xa38/0x2200

  Freed by task 488:
   snd_soc_dapm_free_widget+0x384/0x520
   snd_soc_dapm_free+0x11c/0x284
   soc_remove_component+0xd4/0x1b0
   soc_cleanup_card_resources+0x184/0x700
   snd_soc_unregister_card+0x1dc/0x240
   __device_release_driver+0x2b0/0x584
   driver_detach+0x190/0x290
   asoc_simple_card_exit+0x18/0x30 [snd_soc_simple_card]
   __arm64_sys_delete_module+0x2f0/0x4b0

The PCM close path schedules rtd->delayed_work with a timer delay
(pmdown_time). snd_soc_unbind_card() calls
snd_soc_flush_all_delayed_work(), but flush_delayed_work() does not
execute if the delayed work timer has not fired yet and the work item
has not been enqueued in the workqueue. Cleanup then frees DAPM
widgets, after which the timer fires and the work runs against freed
memory.

Replace snd_soc_flush_all_delayed_work() with a new
snd_soc_cancel_all_delayed_work() in the unbind path to guarantee
that any pending or running delayed work is cancelled or awaited
before card resources are released.

Also fix soc_free_pcm_runtime() to use cancel_delayed_work_sync()
unconditionally instead of the racy conditional flush. The original
check of delayed_work_pending() followed by flush_delayed_work() has
a time window where the work can become pending between the two
calls.

Fixes: e894efef9ac7 ("ASoC: core: add support to card rebind")
Fixes: 9c9b65203492 ("ASoC: core: only flush inited work during free")
Signed-off-by: Matteo Cotifava <cotifavamatteo@gmail.com>
---
 sound/soc/soc-core.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index d0fffef65daf..0f459679d459 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -462,8 +462,7 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd)
 
 	list_del(&rtd->list);
 
-	if (delayed_work_pending(&rtd->delayed_work))
-		flush_delayed_work(&rtd->delayed_work);
+	cancel_delayed_work_sync(&rtd->delayed_work);
 	snd_soc_pcm_component_free(rtd);
 
 	/*
@@ -616,6 +615,14 @@ static void snd_soc_flush_all_delayed_work(struct snd_soc_card *card)
 		flush_delayed_work(&rtd->delayed_work);
 }
 
+static void snd_soc_cancel_all_delayed_work(struct snd_soc_card *card)
+{
+	struct snd_soc_pcm_runtime *rtd;
+
+	for_each_card_rtds(card, rtd)
+		cancel_delayed_work_sync(&rtd->delayed_work);
+}
+
 #ifdef CONFIG_PM_SLEEP
 static void soc_playback_digital_mute(struct snd_soc_card *card, int mute)
 {
@@ -2149,7 +2156,7 @@ static void snd_soc_unbind_card(struct snd_soc_card *card)
 {
 	if (snd_soc_card_is_instantiated(card)) {
 		card->instantiated = false;
-		snd_soc_flush_all_delayed_work(card);
+		snd_soc_cancel_all_delayed_work(card);
 
 		soc_cleanup_card_resources(card);
 	}
-- 
2.39.5


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

end of thread, other threads:[~2026-03-10  0:36 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-08 11:09 [PATCH] ASoC: soc-core: fix use-after-free in snd_soc_unbind_card() Matteo Cotifava
2026-03-09 15:01 ` Mark Brown
2026-03-09 21:49   ` matteo.cotifava
2026-03-09 21:54   ` [PATCH v2 0/2] ASoC: soc-core: fix use-after-free in close_delayed_work matteo.cotifava
2026-03-09 21:54     ` [PATCH v2 1/2] ASoC: soc-core: drop delayed_work_pending() check before flush matteo.cotifava
2026-03-09 21:54     ` [PATCH v2 2/2] ASoC: soc-core: flush delayed work before removing DAIs and widgets matteo.cotifava
2026-03-09 22:08     ` [PATCH v2 0/2] ASoC: soc-core: fix use-after-free in close_delayed_work Mark Brown
2026-03-10  0:36     ` Mark Brown

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.