ASoC: dapm: fix use-after-free issue with dailink sname
Commit 7620fe9161ce ("ASoC: topology: fix memory leak in soc_tplg_dapm_widget_create") fixed a memory leak issue, but additional tests and KASAN reports show a use-after-free in soc-dapm. The widgets are created with a kmemdup operating on a template. The "name" string is also duplicated, but the "sname" string is not. As a result, when the template is freed after widget creation, its sname string is still used. Fix by explicitly duplicating the "sname" string, and freeing it when required. Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
4bd8597dc3
commit
199ed3e81c
@ -295,7 +295,22 @@ EXPORT_SYMBOL_GPL(dapm_mark_endpoints_dirty);
|
|||||||
static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
|
static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
|
||||||
const struct snd_soc_dapm_widget *_widget)
|
const struct snd_soc_dapm_widget *_widget)
|
||||||
{
|
{
|
||||||
return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
|
struct snd_soc_dapm_widget *w;
|
||||||
|
|
||||||
|
w = kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
|
||||||
|
if (!w)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* w->name is duplicated in caller, but w->sname isn't.
|
||||||
|
* Duplicate it here if defined
|
||||||
|
*/
|
||||||
|
if (_widget->sname) {
|
||||||
|
w->sname = kstrdup_const(_widget->sname, GFP_KERNEL);
|
||||||
|
if (!w->sname)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dapm_kcontrol_data {
|
struct dapm_kcontrol_data {
|
||||||
@ -2412,6 +2427,7 @@ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w)
|
|||||||
|
|
||||||
kfree(w->kcontrols);
|
kfree(w->kcontrols);
|
||||||
kfree_const(w->name);
|
kfree_const(w->name);
|
||||||
|
kfree_const(w->sname);
|
||||||
kfree(w);
|
kfree(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3469,6 +3485,7 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
|
|||||||
else
|
else
|
||||||
w->name = kstrdup_const(widget->name, GFP_KERNEL);
|
w->name = kstrdup_const(widget->name, GFP_KERNEL);
|
||||||
if (w->name == NULL) {
|
if (w->name == NULL) {
|
||||||
|
kfree_const(w->sname);
|
||||||
kfree(w);
|
kfree(w);
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user