Skip to content

Commit

Permalink
ASoC: topology: fix oops/use-after-free case with dai driver
Browse files Browse the repository at this point in the history
rmmod/modprobe tests expose a kernel oops when accessing the dai
driver pointer. This comes from the topology design which operates in
multiple passes. Each object removal happens at a specific iteration,
and the code checks for the iteration (order) number after the memory
containing the order was freed.

Fix this be clearing a reference to the dai driver and check its
validity to avoid dereferences.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Guennadi Liakhovetski authored and Mark Brown committed Feb 2, 2019
1 parent 7aea8a9 commit 52abe6c
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 1 deletion.
2 changes: 1 addition & 1 deletion sound/soc/soc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order)
{
int err;

if (!dai || !dai->probed ||
if (!dai || !dai->probed || !dai->driver ||
dai->driver->remove_order != order)
return;

Expand Down
5 changes: 5 additions & 0 deletions sound/soc/soc-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,13 +502,18 @@ static void remove_dai(struct snd_soc_component *comp,
{
struct snd_soc_dai_driver *dai_drv =
container_of(dobj, struct snd_soc_dai_driver, dobj);
struct snd_soc_dai *dai;

if (pass != SOC_TPLG_PASS_PCM_DAI)
return;

if (dobj->ops && dobj->ops->dai_unload)
dobj->ops->dai_unload(comp, dobj);

list_for_each_entry(dai, &comp->dai_list, list)
if (dai->driver == dai_drv)
dai->driver = NULL;

kfree(dai_drv->name);
list_del(&dobj->list);
kfree(dai_drv);
Expand Down

0 comments on commit 52abe6c

Please sign in to comment.