diff options
author | Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> | 2019-02-01 11:05:12 -0600 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-02-02 17:13:09 +0100 |
commit | 199ed3e81c49a621ce6fcb630ab9f30d92db6718 (patch) | |
tree | 9b0e819eddbf9869c13923d475a7d8aa78ecac81 /sound/soc/soc-dapm.c | |
parent | 4bd8597dc36c376a2bb1ef2c72984615bdeb68de (diff) | |
download | lwn-199ed3e81c49a621ce6fcb630ab9f30d92db6718.tar.gz lwn-199ed3e81c49a621ce6fcb630ab9f30d92db6718.zip |
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>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r-- | sound/soc/soc-dapm.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 2c4c13419539..e71cd5b660ad 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -295,7 +295,22 @@ EXPORT_SYMBOL_GPL(dapm_mark_endpoints_dirty); static inline struct snd_soc_dapm_widget *dapm_cnew_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 { @@ -2412,6 +2427,7 @@ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w) kfree(w->kcontrols); kfree_const(w->name); + kfree_const(w->sname); kfree(w); } @@ -3469,6 +3485,7 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, else w->name = kstrdup_const(widget->name, GFP_KERNEL); if (w->name == NULL) { + kfree_const(w->sname); kfree(w); return ERR_PTR(-ENOMEM); } |