[PATCH OLK-6.6] ALSA: hda/cs35l41: Fix firmware load work teardown
From: Cássio Gabriel <cassiogabrielcontato@gmail.com> stable inclusion from stable-v6.12.97 commit 8947215c0136c9d905e4a46d824824f8b48a2e5b category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/16770 CVE: CVE-2026-64481 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit b65020d5398f499c09498c9786dba6d67ae57664 ] cs35l41_hda creates ALSA controls whose private data points at the cs35l41_hda object. The firmware load control can also queue fw_load_work. Those controls are not removed on component unbind, and device remove only cancels fw_load_work through cs35l41_remove_dsp(). That helper is skipped when halo_initialized is false. With firmware_autostart disabled, a firmware load can be requested before the DSP has been initialized. If the component or device is removed before the queued work runs, the worker can run after teardown and dereference driver state that is no longer valid. Track the created controls and remove them on unbind so no new control callback can reach the driver data or queue more work. Then cancel fw_load_work to drain any request that was already queued. Also cancel the work unconditionally during device remove before runtime PM teardown. Fixes: 47ceabd99a28 ("ALSA: hda: cs35l41: Support Firmware switching and reloading") Fixes: 4c870513fbb0 ("ALSA: hda: cs35l41: Add read-only ALSA control for forced mute") Cc: stable@vger.kernel.org Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com> Reviewed-by: Stefan Binding <sbinding@opensource.cirrus.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20260511-alsa-hda-cs35l41-fw-work-teardown-v1-1-118... Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Conflicts: sound/pci/hda/cs35l41_hda.c sound/pci/hda/cs35l41_hda.h [Context Conflicts] Signed-off-by: Lin Ruifeng <linruifeng4@huawei.com> --- sound/pci/hda/cs35l41_hda.c | 66 +++++++++++++++++++++++++++++-------- sound/pci/hda/cs35l41_hda.h | 5 +++ 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 4b7c355d97d2..63fec4c5ffbd 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -1072,6 +1072,43 @@ static int cs35l41_fw_type_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ct return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(hda_cs_dsp_fw_ids), hda_cs_dsp_fw_ids); } +static void cs35l41_remove_controls(struct cs35l41_hda *cs35l41) +{ + if (!cs35l41->codec) + return; + + snd_ctl_remove(cs35l41->codec->card, cs35l41->mute_override_ctl); + cs35l41->mute_override_ctl = NULL; + + snd_ctl_remove(cs35l41->codec->card, cs35l41->fw_load_ctl); + cs35l41->fw_load_ctl = NULL; + + snd_ctl_remove(cs35l41->codec->card, cs35l41->fw_type_ctl); + cs35l41->fw_type_ctl = NULL; +} + +static int cs35l41_add_control(struct cs35l41_hda *cs35l41, + struct snd_kcontrol_new *ctl, + struct snd_kcontrol **kctl) +{ + int ret; + + *kctl = snd_ctl_new1(ctl, cs35l41); + if (!*kctl) + return -ENOMEM; + + ret = snd_ctl_add(cs35l41->codec->card, *kctl); + if (ret) { + dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", ctl->name, ret); + *kctl = NULL; + return ret; + } + + dev_dbg(cs35l41->dev, "Added Control %s\n", ctl->name); + + return 0; +} + static int cs35l41_create_controls(struct cs35l41_hda *cs35l41) { char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; @@ -1097,23 +1134,19 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41) scnprintf(fw_load_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Load", cs35l41->amp_name); - ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35l41)); - if (ret) { - dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_type_ctl.name, ret); - return ret; - } - - dev_dbg(cs35l41->dev, "Added Control %s\n", fw_type_ctl.name); - - ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_load_ctl, cs35l41)); - if (ret) { - dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_load_ctl.name, ret); - return ret; - } + ret = cs35l41_add_control(cs35l41, &fw_type_ctl, &cs35l41->fw_type_ctl); + if (ret) + goto err; - dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name); + ret = cs35l41_add_control(cs35l41, &fw_load_ctl, &cs35l41->fw_load_ctl); + if (ret) + goto err; return 0; + +err: + cs35l41_remove_controls(cs35l41); + return ret; } static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data) @@ -1189,6 +1222,10 @@ static void cs35l41_hda_unbind(struct device *dev, struct device *master, void * sleep_flags = lock_system_sleep(); device_link_remove(&cs35l41->codec->core.dev, cs35l41->dev); unlock_system_sleep(sleep_flags); + + cs35l41_remove_controls(cs35l41); + cancel_work_sync(&cs35l41->fw_load_work); + cs35l41->codec = NULL; } } @@ -1707,6 +1744,7 @@ void cs35l41_hda_remove(struct device *dev) cs35l41_remove_dsp(cs35l41); component_del(cs35l41->dev, &cs35l41_hda_comp_ops); + cancel_work_sync(&cs35l41->fw_load_work); pm_runtime_put_noidle(cs35l41->dev); diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h index b93bf762976e..e8992b2bc0e2 100644 --- a/sound/pci/hda/cs35l41_hda.h +++ b/sound/pci/hda/cs35l41_hda.h @@ -45,6 +45,8 @@ enum cs35l41_hda_gpio_function { CS35l41_SYNC, }; +struct snd_kcontrol; + struct cs35l41_hda { struct device *dev; struct regmap *regmap; @@ -62,6 +64,9 @@ struct cs35l41_hda { int speaker_id; struct mutex fw_mutex; struct work_struct fw_load_work; + struct snd_kcontrol *fw_type_ctl; + struct snd_kcontrol *fw_load_ctl; + struct snd_kcontrol *mute_override_ctl; struct regmap_irq_chip_data *irq_data; bool firmware_running; -- 2.34.1
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/25633 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/IK4... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/25633 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/IK4...
participants (2)
-
Lin Ruifeng -
patchwork bot