ASoC: topology: fix kernel oops on route addition error

commit 6f0307df83f2aa6bdf656c2219c89ce96502d20e upstream.

When errors happens while loading graph components, the kernel oopses
while trying to remove all topology components. This can be
root-caused to a list pointing to memory that was already freed on
error.

remove_route() is already called on errors and will perform the
required cleanups so there's no need to free the route memory in
soc_tplg_dapm_graph_elems_load() if the route was added to the
list. We do however want to free the routes allocated but not added to
the list.

Fixes: 7df04ea7a31ea ('ASoC: topology: modify dapm route loading routine and add dapm route unloading')
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/20200707203749.113883-2-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Pierre-Louis Bossart 2020-07-07 15:37:45 -05:00 committed by Greg Kroah-Hartman
parent e60e53e685
commit a4fd00dd82

View File

@ -1284,17 +1284,29 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list);
ret = soc_tplg_add_route(tplg, routes[i]);
if (ret < 0)
if (ret < 0) {
/*
* this route was added to the list, it will
* be freed in remove_route() so increment the
* counter to skip it in the error handling
* below.
*/
i++;
break;
}
/* add route, but keep going if some fail */
snd_soc_dapm_add_routes(dapm, routes[i], 1);
}
/* free memory allocated for all dapm routes in case of error */
if (ret < 0)
for (i = 0; i < count ; i++)
kfree(routes[i]);
/*
* free memory allocated for all dapm routes not added to the
* list in case of error
*/
if (ret < 0) {
while (i < count)
kfree(routes[i++]);
}
/*
* free pointer to array of dapm routes as this is no longer needed.