* [PATCH] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process()
@ 2026-03-10 18:38 gaggery.tsai
2026-03-11 16:31 ` Mark Brown
2026-03-12 14:32 ` [PATCH v2] " gaggery.tsai
0 siblings, 2 replies; 9+ messages in thread
From: gaggery.tsai @ 2026-03-10 18:38 UTC (permalink / raw)
To: linux-sound, patches
Cc: ckeepax, mstrozek, yung-chuan.liao, pierre-louis.bossart, broonie,
TsaiGaggery, stable
From: TsaiGaggery <gaggery.tsai@intel.com>
sdca_jack_process() unconditionally dereferences component->card and
card->snd_card at the top of the function. This causes a NULL pointer
dereference when the SDCA IRQ handler fires after the ASoC card has
been torn down.
The crash occurs deterministically on platforms where snd_soc_bind_card()
fails (e.g. due to missing machine driver support). The sequence is:
1. soc_probe_component() sets component->card and calls
snd_soc_component_probe(), which registers the SDCA IRQ handler
via sdca_irq_populate() / devm_request_threaded_irq().
2. snd_soc_bind_card() fails (e.g. sof_sdw returns -ENOTSUPP when
no matching machine driver is found for the codec configuration).
3. soc_cleanup_card_resources() -> soc_remove_component() sets
component->card = NULL.
4. The SDCA IRQ handler remains registered because it is tied to
device lifetime (devm), not card lifetime.
5. A subsequent SoundWire alert fires via
cdns_update_slave_status_work() -> sdw_handle_slave_status() ->
handle_nested_irq() -> detected_mode_handler() ->
sdca_jack_process(), which dereferences the now-NULL
component->card, causing the crash at offset 0xa0
(offsetof(struct snd_soc_card, snd_card)).
BUG: kernel NULL pointer dereference, address: 00000000000000a0
RIP: 0010:sdca_jack_process+0x47/0x470 [snd_soc_sdca]
Call Trace:
detected_mode_handler+0x2e/0x70 [snd_soc_sdca]
handle_nested_irq+0xa9/0x120
regmap_irq_thread+0x1d5/0x320
handle_nested_irq+0xa9/0x120
sdw_handle_slave_status+0xe92/0x17d0 [soundwire_bus]
cdns_update_slave_status_work+0x25e/0x470 [soundwire_cadence]
Fix this by deferring the rwsem and kctl initialization until after
a NULL check on card and card->snd_card, returning -ENODEV if the
card is not available. This is consistent with the same defensive
pattern used by existing SDCA codec drivers (e.g. rt721-sdca.c,
rt712-sdca.c).
Tested on Intel Panther Lake with Cirrus Logic CS42L45/CS35L57
SoundWire codecs. The crash reproduces reliably when
snd_soc_bind_card() fails and can be triggered by any unsupported
codec configuration that causes card registration to return an error.
Fixes: 82e12800f563 ("ASoC: SDCA: Add ability to connect SDCA jacks to ASoC jacks")
Cc: stable@vger.kernel.org
Cc: Charles Keepax <ckeepax@opensource.cirrus.com>
Cc: Maciej Strozek <mstrozek@opensource.cirrus.com>
Cc: Bard Liao <yung-chuan.liao@linux.intel.com>
Cc: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
---
sound/soc/sdca/sdca_jack.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c
index 49d317d3b8c8..b52d88a08634 100644
--- a/sound/soc/sdca/sdca_jack.c
+++ b/sound/soc/sdca/sdca_jack.c
@@ -37,13 +37,21 @@ int sdca_jack_process(struct sdca_interrupt *interrupt)
struct device *dev = interrupt->dev;
struct snd_soc_component *component = interrupt->component;
struct snd_soc_card *card = component->card;
- struct rw_semaphore *rwsem = &card->snd_card->controls_rwsem;
+ struct rw_semaphore *rwsem;
struct jack_state *state = interrupt->priv;
- struct snd_kcontrol *kctl = state->kctl;
+ struct snd_kcontrol *kctl;
struct snd_ctl_elem_value *ucontrol __free(kfree) = NULL;
unsigned int reg, val;
int ret;
+ if (!card || !card->snd_card) {
+ dev_dbg(dev, "card not yet bound, deferring jack event\n");
+ return -ENODEV;
+ }
+
+ rwsem = &card->snd_card->controls_rwsem;
+ kctl = state->kctl;
+
guard(rwsem_write)(rwsem);
if (!kctl) {
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process()
2026-03-10 18:38 [PATCH] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process() gaggery.tsai
@ 2026-03-11 16:31 ` Mark Brown
2026-03-11 17:45 ` Tsai, Gaggery
2026-03-12 14:32 ` [PATCH v2] " gaggery.tsai
1 sibling, 1 reply; 9+ messages in thread
From: Mark Brown @ 2026-03-11 16:31 UTC (permalink / raw)
To: gaggery.tsai
Cc: linux-sound, patches, ckeepax, mstrozek, yung-chuan.liao,
pierre-louis.bossart, stable
[-- Attachment #1: Type: text/plain, Size: 685 bytes --]
On Tue, Mar 10, 2026 at 11:38:29AM -0700, gaggery.tsai@intel.com wrote:
> sdca_jack_process() unconditionally dereferences component->card and
> card->snd_card at the top of the function. This causes a NULL pointer
> dereference when the SDCA IRQ handler fires after the ASoC card has
> been torn down.
> + if (!card || !card->snd_card) {
> + dev_dbg(dev, "card not yet bound, deferring jack event\n");
> + return -ENODEV;
> + }
> +
> + rwsem = &card->snd_card->controls_rwsem;
> + kctl = state->kctl;
> +
Don't we still have a time of check/time of use issue here while the
card is being removed - do we do something to stop interrupts being
delivered after the card is unbound?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process()
2026-03-11 16:31 ` Mark Brown
@ 2026-03-11 17:45 ` Tsai, Gaggery
2026-03-11 17:50 ` Charles Keepax
0 siblings, 1 reply; 9+ messages in thread
From: Tsai, Gaggery @ 2026-03-11 17:45 UTC (permalink / raw)
To: Mark Brown
Cc: linux-sound@vger.kernel.org, patches@opensource.cirrus.com,
ckeepax@opensource.cirrus.com, mstrozek@opensource.cirrus.com,
yung-chuan.liao@linux.intel.com, pierre-louis.bossart@linux.dev,
stable@vger.kernel.org
Thanks for the review. You're right, I'll send a v2 that also disables the SDCA IRQs in the component remove path to close the TOCTOU window, keeping the NULL guard as defense-in-depth.
________________________________________
From: Mark Brown
Sent: Wednesday, March 11, 2026 9:31 AM
To: Tsai, Gaggery
Cc: linux-sound@vger.kernel.org; patches@opensource.cirrus.com; ckeepax@opensource.cirrus.com; mstrozek@opensource.cirrus.com; yung-chuan.liao@linux.intel.com; pierre-louis.bossart@linux.dev; stable@vger.kernel.org
Subject: Re: [PATCH] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process()
On Tue, Mar 10, 2026 at 11:38:29AM -0700, gaggery.tsai@intel.com wrote:
> sdca_jack_process() unconditionally dereferences component->card and
> card->snd_card at the top of the function. This causes a NULL pointer
> dereference when the SDCA IRQ handler fires after the ASoC card has
> been torn down.
> + if (!card || !card->snd_card) {
> + dev_dbg(dev, "card not yet bound, deferring jack event\n");
> + return -ENODEV;
> + }
> +
> + rwsem = &card->snd_card->controls_rwsem;
> + kctl = state->kctl;
> +
Don't we still have a time of check/time of use issue here while the
card is being removed - do we do something to stop interrupts being
delivered after the card is unbound?
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process()
2026-03-11 17:45 ` Tsai, Gaggery
@ 2026-03-11 17:50 ` Charles Keepax
0 siblings, 0 replies; 9+ messages in thread
From: Charles Keepax @ 2026-03-11 17:50 UTC (permalink / raw)
To: Tsai, Gaggery
Cc: Mark Brown, linux-sound@vger.kernel.org,
patches@opensource.cirrus.com, mstrozek@opensource.cirrus.com,
yung-chuan.liao@linux.intel.com, pierre-louis.bossart@linux.dev,
stable@vger.kernel.org
On Wed, Mar 11, 2026 at 05:45:07PM +0000, Tsai, Gaggery wrote:
> Thanks for the review. You're right, I'll send a v2 that also
> disables the SDCA IRQs in the component remove path to close
> the TOCTOU window, keeping the NULL guard as defense-in-depth.
Yeah I think disabling the IRQs would be the better fix.
Thanks,
Charles
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process()
2026-03-10 18:38 [PATCH] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process() gaggery.tsai
2026-03-11 16:31 ` Mark Brown
@ 2026-03-12 14:32 ` gaggery.tsai
2026-03-12 17:32 ` Mark Brown
2026-03-13 9:54 ` Charles Keepax
1 sibling, 2 replies; 9+ messages in thread
From: gaggery.tsai @ 2026-03-12 14:32 UTC (permalink / raw)
To: linux-sound
Cc: ckeepax, mstrozek, yung-chuan.liao, pierre-louis.bossart, stable,
TsaiGaggery
From: TsaiGaggery <gaggery.tsai@intel.com>
sdca_jack_process() unconditionally dereferences component->card and
card->snd_card at the top of the function. This causes a NULL pointer
dereference when the SDCA IRQ handler fires after the ASoC card has
been torn down.
The crash occurs deterministically on platforms where snd_soc_bind_card()
fails (e.g. due to missing machine driver support). The sequence is:
1. soc_probe_component() sets component->card and calls
snd_soc_component_probe(), which registers the SDCA IRQ handler
via sdca_irq_populate() / devm_request_threaded_irq().
2. snd_soc_bind_card() fails (e.g. sof_sdw returns -ENOTSUPP when
no matching machine driver is found for the codec configuration).
3. soc_cleanup_card_resources() -> soc_remove_component() sets
component->card = NULL.
4. The SDCA IRQ handler remains registered because it is tied to
device lifetime (devm), not card lifetime.
5. A subsequent SoundWire alert fires via
cdns_update_slave_status_work() -> sdw_handle_slave_status() ->
handle_nested_irq() -> detected_mode_handler() ->
sdca_jack_process(), which dereferences the now-NULL
component->card, causing the crash at offset 0xa0
(offsetof(struct snd_soc_card, snd_card)).
BUG: kernel NULL pointer dereference, address: 00000000000000a0
RIP: 0010:sdca_jack_process+0x47/0x470 [snd_soc_sdca]
Call Trace:
detected_mode_handler+0x2e/0x70 [snd_soc_sdca]
handle_nested_irq+0xa9/0x120
regmap_irq_thread+0x1d5/0x320
handle_nested_irq+0xa9/0x120
sdw_handle_slave_status+0xe92/0x17d0 [soundwire_bus]
cdns_update_slave_status_work+0x25e/0x470 [soundwire_cadence]
Fix this in two ways:
1. Add a .remove callback to class_function_component_drv that calls
sdca_irq_disable() before the component is removed and
component->card is set to NULL. Since disable_irq() includes
synchronize_irq(), this guarantees no handler is running when
the card pointer is cleared, eliminating the TOCTOU race.
2. Keep a NULL guard in sdca_jack_process() as defense-in-depth,
returning -ENODEV if card or card->snd_card is NULL.
Tested on Intel Panther Lake with Cirrus Logic CS42L45/CS35L57
SoundWire codecs. The crash reproduces reliably when
snd_soc_bind_card() fails and can be triggered by any unsupported
codec configuration that causes card registration to return an error.
Fixes: 82e12800f563 ("ASoC: SDCA: Add ability to connect SDCA jacks to ASoC jacks")
Cc: stable@vger.kernel.org
Cc: Charles Keepax <ckeepax@opensource.cirrus.com>
Cc: Maciej Strozek <mstrozek@opensource.cirrus.com>
Cc: Bard Liao <yung-chuan.liao@linux.intel.com>
Cc: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Signed-off-by: Gaggery Tsai <gaggery.tsai@intel.com>
---
sound/soc/sdca/sdca_class_function.c | 9 +++++++++
sound/soc/sdca/sdca_jack.c | 12 ++++++++++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c
index 98fd3fd1052b..a43ad5262db2 100644
--- a/sound/soc/sdca/sdca_class_function.c
+++ b/sound/soc/sdca/sdca_class_function.c
@@ -207,8 +207,17 @@ static int class_function_set_jack(struct snd_soc_component *component,
return sdca_jack_set_jack(core->irq_info, jack);
}
+static void class_function_component_remove(struct snd_soc_component *component)
+{
+ struct class_function_drv *drv = snd_soc_component_get_drvdata(component);
+ struct sdca_class_drv *core = drv->core;
+
+ sdca_irq_disable(drv->function, core->irq_info);
+}
+
static const struct snd_soc_component_driver class_function_component_drv = {
.probe = class_function_component_probe,
+ .remove = class_function_component_remove,
.endianness = 1,
};
diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c
index 49d317d3b8c8..b52d88a08634 100644
--- a/sound/soc/sdca/sdca_jack.c
+++ b/sound/soc/sdca/sdca_jack.c
@@ -37,13 +37,21 @@ int sdca_jack_process(struct sdca_interrupt *interrupt)
struct device *dev = interrupt->dev;
struct snd_soc_component *component = interrupt->component;
struct snd_soc_card *card = component->card;
- struct rw_semaphore *rwsem = &card->snd_card->controls_rwsem;
+ struct rw_semaphore *rwsem;
struct jack_state *state = interrupt->priv;
- struct snd_kcontrol *kctl = state->kctl;
+ struct snd_kcontrol *kctl;
struct snd_ctl_elem_value *ucontrol __free(kfree) = NULL;
unsigned int reg, val;
int ret;
+ if (!card || !card->snd_card) {
+ dev_dbg(dev, "card not yet bound, deferring jack event\n");
+ return -ENODEV;
+ }
+
+ rwsem = &card->snd_card->controls_rwsem;
+ kctl = state->kctl;
+
guard(rwsem_write)(rwsem);
if (!kctl) {
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v2] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process()
2026-03-12 14:32 ` [PATCH v2] " gaggery.tsai
@ 2026-03-12 17:32 ` Mark Brown
2026-03-13 9:54 ` Charles Keepax
1 sibling, 0 replies; 9+ messages in thread
From: Mark Brown @ 2026-03-12 17:32 UTC (permalink / raw)
To: gaggery.tsai
Cc: linux-sound, ckeepax, mstrozek, yung-chuan.liao,
pierre-louis.bossart, stable
[-- Attachment #1: Type: text/plain, Size: 1177 bytes --]
On Thu, Mar 12, 2026 at 07:32:18AM -0700, gaggery.tsai@intel.com wrote:
> sdca_jack_process() unconditionally dereferences component->card and
> card->snd_card at the top of the function. This causes a NULL pointer
> dereference when the SDCA IRQ handler fires after the ASoC card has
> been torn down.
Please don't send new patches in reply to old patches or serieses, this
makes it harder for both people and tools to understand what is going
on - it can bury things in mailboxes and make it difficult to keep track
of what current patches are, both for the new patches and the old ones.
> +static void class_function_component_remove(struct snd_soc_component *component)
> +{
> + struct class_function_drv *drv = snd_soc_component_get_drvdata(component);
> + struct sdca_class_drv *core = drv->core;
> +
> + sdca_irq_disable(drv->function, core->irq_info);
> +}
This is an ASoC level remove so the driver itself is never unbound but
I'm not seeing anything that undoes this disable so an ASoC level rebind
will leave the interrupt disabled. Do we need to start off with the
interrupt disabled and only enable it during bind so we can have the
bind/unbind be symmetric?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v2] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process()
2026-03-12 14:32 ` [PATCH v2] " gaggery.tsai
2026-03-12 17:32 ` Mark Brown
@ 2026-03-13 9:54 ` Charles Keepax
2026-03-13 13:28 ` Mark Brown
1 sibling, 1 reply; 9+ messages in thread
From: Charles Keepax @ 2026-03-13 9:54 UTC (permalink / raw)
To: gaggery.tsai
Cc: linux-sound, mstrozek, yung-chuan.liao, pierre-louis.bossart,
stable
On Thu, Mar 12, 2026 at 07:32:18AM -0700, gaggery.tsai@intel.com wrote:
> From: TsaiGaggery <gaggery.tsai@intel.com>
> +static void class_function_component_remove(struct snd_soc_component *component)
> +{
> + struct class_function_drv *drv = snd_soc_component_get_drvdata(component);
> + struct sdca_class_drv *core = drv->core;
> +
> + sdca_irq_disable(drv->function, core->irq_info);
> +}
Yeah as Mark notes this is really just postponing the issues till
you rebind the card.
> + if (!card || !card->snd_card) {
> + dev_dbg(dev, "card not yet bound, deferring jack event\n");
> + return -ENODEV;
> + }
> +
> + rwsem = &card->snd_card->controls_rwsem;
> + kctl = state->kctl;
> +
This is really a bit overly defensive, its just a driver bug if
this is called without these.
Let me have a look at this today, I think really the problem is
we shouldn't be devm'ing the IRQs since they are not being
handled at device probe time.
Thanks,
Charles
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH v2] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process()
2026-03-13 9:54 ` Charles Keepax
@ 2026-03-13 13:28 ` Mark Brown
2026-03-13 14:28 ` Charles Keepax
0 siblings, 1 reply; 9+ messages in thread
From: Mark Brown @ 2026-03-13 13:28 UTC (permalink / raw)
To: Charles Keepax
Cc: gaggery.tsai, linux-sound, mstrozek, yung-chuan.liao,
pierre-louis.bossart, stable
[-- Attachment #1: Type: text/plain, Size: 268 bytes --]
On Fri, Mar 13, 2026 at 09:54:28AM +0000, Charles Keepax wrote:
> Let me have a look at this today, I think really the problem is
> we shouldn't be devm'ing the IRQs since they are not being
> handled at device probe time.
Yes, or just request them on normal probe.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process()
2026-03-13 13:28 ` Mark Brown
@ 2026-03-13 14:28 ` Charles Keepax
0 siblings, 0 replies; 9+ messages in thread
From: Charles Keepax @ 2026-03-13 14:28 UTC (permalink / raw)
To: Mark Brown
Cc: gaggery.tsai, linux-sound, mstrozek, yung-chuan.liao,
pierre-louis.bossart, stable
On Fri, Mar 13, 2026 at 01:28:23PM +0000, Mark Brown wrote:
> On Fri, Mar 13, 2026 at 09:54:28AM +0000, Charles Keepax wrote:
>
> > Let me have a look at this today, I think really the problem is
> > we shouldn't be devm'ing the IRQs since they are not being
> > handled at device probe time.
>
> Yes, or just request them on normal probe.
If memory serves the issue was as some of the IRQs actually
depend on interfacing with controls created by the card it was
nicer to register the IRQs fairly late, and probably nicer to
remove them if the card goes away. Although that said, we did end
up having to deal with the IRQs happening before the controls
anyway (since there wasn't actually a good callback for that) so
it might be worth re-assessing that decision.
Thanks,
Charles
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-03-13 14:29 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-10 18:38 [PATCH] ASoC: SDCA: Fix NULL pointer dereference in sdca_jack_process() gaggery.tsai
2026-03-11 16:31 ` Mark Brown
2026-03-11 17:45 ` Tsai, Gaggery
2026-03-11 17:50 ` Charles Keepax
2026-03-12 14:32 ` [PATCH v2] " gaggery.tsai
2026-03-12 17:32 ` Mark Brown
2026-03-13 9:54 ` Charles Keepax
2026-03-13 13:28 ` Mark Brown
2026-03-13 14:28 ` Charles Keepax
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox