public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ASoC: SOF: Intel: hda: Fix NULL pointer dereference on SoundWire IRQ during removal
@ 2026-03-12 15:00 gaggery.tsai
  2026-03-12 15:08 ` [PATCH v2] " gaggery.tsai
  0 siblings, 1 reply; 3+ messages in thread
From: gaggery.tsai @ 2026-03-12 15:00 UTC (permalink / raw)
  To: linux-drivers-review-request
  Cc: pierre-louis.bossart, yung-chuan.liao, ranjani.sridharan, stable,
	TsaiGaggery

From: TsaiGaggery <gaggery.tsai@intel.com>

hda_sdw_exit() sets hdev->sdw to NULL after calling sdw_intel_exit(),
but the shared IPC IRQ handler is not freed until much later in
hda_dsp_remove(). If a SoundWire interrupt fires in this window, the
IRQ thread calls hda_dsp_sdw_thread() -> sdw_intel_thread() with a
NULL context pointer or with link->cdns already freed, causing a NULL
pointer dereference:

  BUG: kernel NULL pointer dereference, address: 00000000000003d0
  RIP: 0010:sdw_cdns_irq+0x9/0x2b0 [soundwire_cadence]
  Call Trace:
   sdw_intel_thread+0x2d/0x50 [soundwire_intel]
   hda_dsp_interrupt_thread+0x99/0x3a0 [snd_sof_intel_hda_generic]
   irq_thread_fn+0x25/0x60

The race window is between hda_sdw_exit() tearing down SoundWire
links and free_irq() in hda_dsp_remove(). During sdw_intel_exit() ->
sdw_intel_cleanup(), each link's auxiliary device is unregistered,
which clears link->cdns. Meanwhile the IRQ thread can still fire and
iterate the link list, calling sdw_cdns_irq() with a NULL cdns.

Fix this in three ways:

  1. In hda_sdw_exit(), disable SoundWire interrupts at the hardware
     level (hda_sdw_int_enable) and call synchronize_irq() BEFORE
     tearing down the SoundWire context, preventing new IRQ threads
     from entering the SoundWire path.

  2. Add a NULL guard for link->cdns in sdw_intel_thread() to handle
     the case where the IRQ thread races with individual link
     removal during sdw_intel_cleanup().

  3. Add a NULL guard in hda_dsp_sdw_thread() as defense-in-depth
     for the case where hdev->sdw is already NULL.

Tested on Intel Panther Lake with SoundWire codecs by manually
unbinding the SOF PCI device while audio was active.

Fixes: 722ba5f1f530 ("ASoC: SOF: Intel: hda: merge IPC, stream and SoundWire interrupt handlers")
Cc: stable@vger.kernel.org
Cc: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Cc: Bard Liao <yung-chuan.liao@linux.intel.com>
Cc: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
---
 drivers/soundwire/intel_init.c |  6 ++++--
 sound/soc/sof/intel/hda.c      | 11 +++++++++--
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c
index ad48d67fa935..e093a29f1590 100644
--- a/drivers/soundwire/intel_init.c
+++ b/drivers/soundwire/intel_init.c
@@ -145,8 +145,10 @@ irqreturn_t sdw_intel_thread(int irq, void *dev_id)
 	struct sdw_intel_ctx *ctx = dev_id;
 	struct sdw_intel_link_res *link;
 
-	list_for_each_entry(link, &ctx->link_list, list)
-		sdw_cdns_irq(irq, link->cdns);
+	list_for_each_entry(link, &ctx->link_list, list) {
+		if (link->cdns)
+			sdw_cdns_irq(irq, link->cdns);
+	}
 
 	return IRQ_HANDLED;
 }
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index c0cc7d3ce526..02a0e354414e 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -256,12 +256,17 @@ static int hda_sdw_exit(struct snd_sof_dev *sdev)
 
 	hdev = sdev->pdata->hw_pdata;
 
+	/* Disable SoundWire IRQ at the hardware level first to prevent
+	 * the IRQ handler from accessing hdev->sdw after it is freed.
+	 * synchronize_irq() ensures any in-flight handler has completed.
+	 */
+	hda_sdw_int_enable(sdev, false);
+	synchronize_irq(sdev->ipc_irq);
+
 	if (hdev->sdw)
 		sdw_intel_exit(hdev->sdw);
 	hdev->sdw = NULL;
 
-	hda_sdw_int_enable(sdev, false);
-
 	return 0;
 }
 
@@ -309,6 +314,8 @@ static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
 
 static irqreturn_t hda_dsp_sdw_thread(int irq, void *context)
 {
+	if (!context)
+		return IRQ_HANDLED;
 	return sdw_intel_thread(irq, context);
 }
 
-- 
2.43.0


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

end of thread, other threads:[~2026-03-20 20:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-12 15:00 [PATCH] ASoC: SOF: Intel: hda: Fix NULL pointer dereference on SoundWire IRQ during removal gaggery.tsai
2026-03-12 15:08 ` [PATCH v2] " gaggery.tsai
2026-03-20 20:34   ` Pierre-Louis Bossart

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