* [PATCH v2] ALSA: hda: cs35l41: Fix ACPI device reference leak on probe failure
@ 2026-10-11 11:42 Ma Ke
2026-10-12 7:39 ` Takashi Iwai
0 siblings, 1 reply; 2+ messages in thread
From: Ma Ke @ 2026-10-11 11:42 UTC (permalink / raw)
To: david.rhodes, rf, perex, tiwai, sbinding
Cc: linux-sound, patches, linux-kernel, akpm, Ma Ke, stable
cs35l41_hda_probe() takes an acpi_device through
cs35l41_hda_read_acpi() and stores it in cs35l41->dacpi. It is
released in the err: label, which
is reached from every later failure.
One failure is not routed there:
ret = cs35l41_hda_read_acpi(cs35l41, device_name, id);
if (ret)
return dev_err_probe(cs35l41->dev, ret, "...");
cs35l41->acpi_subsystem_id is allocated inside cs35l41_hda_read_acpi()
before that point, so it is leaked whenever the function fails.
Route the failure through a new err_acpi label that releases it.
That label must not release cs35l41->dacpi a second time. Every
failure path in cs35l41_hda_read_acpi() that can be taken after the
assignment already drops that reference: cs35l41_hda_parse_acpi() does
so in its own err: label, and the !physdev path does it directly.
Clear cs35l41->dacpi wherever it is dropped, so the pointer never
outlives the reference and the put in err_acpi is a no-op on those
paths.
Found by code review.
Fixes: 447106e92a0c ("ALSA: hda: cs35l41: Support mute notifications for CS35L41 HDA")
Cc: stable@vger.kernel.org
Signed-off-by: Ma Ke <make_ruc2021@163.com>
---
Changes in v2:
- v1 released cs35l41->dacpi from the new err_acpi label, but
cs35l41_hda_parse_acpi() already drops that reference in its own err:
label, so the reference would have been dropped a second time. Clear
cs35l41->dacpi there as well, not only on the !physdev path.
Reported by Sashiko; thanks to Takashi Iwai for pointing it out.
- The leak being fixed and the diff are otherwise unchanged from v1.
---
sound/hda/codecs/side-codecs/cs35l41_hda.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.c b/sound/hda/codecs/side-codecs/cs35l41_hda.c
index 62296be45c55..3a8e04f73f79 100644
--- a/sound/hda/codecs/side-codecs/cs35l41_hda.c
+++ b/sound/hda/codecs/side-codecs/cs35l41_hda.c
@@ -1908,6 +1908,7 @@ int cs35l41_hda_parse_acpi(struct cs35l41_hda *cs35l41, struct device *physdev,
hw_cfg->gpio1.valid = false;
hw_cfg->gpio2.valid = false;
acpi_dev_put(cs35l41->dacpi);
+ cs35l41->dacpi = NULL;
return ret;
}
@@ -1929,6 +1930,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
struct device *physdev __free(put_device) =
get_device(acpi_get_first_physical_node(adev));
if (!physdev) {
+ cs35l41->dacpi = NULL;
acpi_dev_put(adev);
return -ENODEV;
}
@@ -1986,8 +1988,10 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
dev_set_drvdata(dev, cs35l41);
ret = cs35l41_hda_read_acpi(cs35l41, device_name, id);
- if (ret)
- return dev_err_probe(cs35l41->dev, ret, "Platform not supported\n");
+ if (ret) {
+ dev_err_probe(cs35l41->dev, ret, "Platform not supported\n");
+ goto err_acpi;
+ }
if (IS_ERR(cs35l41->reset_gpio)) {
ret = PTR_ERR(cs35l41->reset_gpio);
@@ -2066,6 +2070,12 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
return 0;
+err_acpi:
+ acpi_dev_put(cs35l41->dacpi);
+ kfree(cs35l41->acpi_subsystem_id);
+
+ return ret;
+
err_pm:
pm_runtime_dont_use_autosuspend(cs35l41->dev);
pm_runtime_disable(cs35l41->dev);
--
2.43.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH v2] ALSA: hda: cs35l41: Fix ACPI device reference leak on probe failure
2026-10-11 11:42 [PATCH v2] ALSA: hda: cs35l41: Fix ACPI device reference leak on probe failure Ma Ke
@ 2026-10-12 7:39 ` Takashi Iwai
0 siblings, 0 replies; 2+ messages in thread
From: Takashi Iwai @ 2026-10-12 7:39 UTC (permalink / raw)
To: Ma Ke
Cc: david.rhodes, rf, perex, tiwai, sbinding, linux-sound, patches,
linux-kernel, akpm, stable
On Sun, 11 Oct 2026 13:42:51 +0200,
Ma Ke wrote:
>
> cs35l41_hda_probe() takes an acpi_device through
> cs35l41_hda_read_acpi() and stores it in cs35l41->dacpi. It is
> released in the err: label, which
> is reached from every later failure.
>
> One failure is not routed there:
>
> ret = cs35l41_hda_read_acpi(cs35l41, device_name, id);
> if (ret)
> return dev_err_probe(cs35l41->dev, ret, "...");
>
> cs35l41->acpi_subsystem_id is allocated inside cs35l41_hda_read_acpi()
> before that point, so it is leaked whenever the function fails.
>
> Route the failure through a new err_acpi label that releases it.
>
> That label must not release cs35l41->dacpi a second time. Every
> failure path in cs35l41_hda_read_acpi() that can be taken after the
> assignment already drops that reference: cs35l41_hda_parse_acpi() does
> so in its own err: label, and the !physdev path does it directly.
> Clear cs35l41->dacpi wherever it is dropped, so the pointer never
> outlives the reference and the put in err_acpi is a no-op on those
> paths.
>
> Found by code review.
>
> Fixes: 447106e92a0c ("ALSA: hda: cs35l41: Support mute notifications for CS35L41 HDA")
> Cc: stable@vger.kernel.org
> Signed-off-by: Ma Ke <make_ruc2021@163.com>
Now Sashiko complains other things; please verify whether they are
valid or not.
Through those developments, I'm thinking whether it'd be cleaner
rather to move the unref and kfree into the caller side, i.e. doing it
only in cs35l41_hda_probe() error path (but conditionally), instead,
so something like below.
thanks,
Takashi
diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.c b/sound/hda/codecs/side-codecs/cs35l41_hda.c
index 62296be45c55..e6f0ae39876d 100644
--- a/sound/hda/codecs/side-codecs/cs35l41_hda.c
+++ b/sound/hda/codecs/side-codecs/cs35l41_hda.c
@@ -1907,7 +1907,6 @@ int cs35l41_hda_parse_acpi(struct cs35l41_hda *cs35l41, struct device *physdev,
hw_cfg->valid = false;
hw_cfg->gpio1.valid = false;
hw_cfg->gpio2.valid = false;
- acpi_dev_put(cs35l41->dacpi);
return ret;
}
@@ -1928,10 +1927,8 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
cs35l41->dacpi = adev;
struct device *physdev __free(put_device) =
get_device(acpi_get_first_physical_node(adev));
- if (!physdev) {
- acpi_dev_put(adev);
+ if (!physdev)
return -ENODEV;
- }
sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
if (IS_ERR(sub))
@@ -1986,8 +1983,10 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
dev_set_drvdata(dev, cs35l41);
ret = cs35l41_hda_read_acpi(cs35l41, device_name, id);
- if (ret)
- return dev_err_probe(cs35l41->dev, ret, "Platform not supported\n");
+ if (ret) {
+ dev_err_probe(cs35l41->dev, ret, "Platform not supported\n");
+ goto err_acpi;
+ }
if (IS_ERR(cs35l41->reset_gpio)) {
ret = PTR_ERR(cs35l41->reset_gpio);
@@ -2076,6 +2075,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio);
gpiod_put(cs35l41->cs_gpio);
+err_acpi:
acpi_dev_put(cs35l41->dacpi);
kfree(cs35l41->acpi_subsystem_id);
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-12 7:39 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-11 11:42 [PATCH v2] ALSA: hda: cs35l41: Fix ACPI device reference leak on probe failure Ma Ke
2026-10-12 7:39 ` Takashi Iwai
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®