| From e07293ae13895d76d19a63a5d2ace6160818deb6 Mon Sep 17 00:00:00 2001 |
| From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> |
| Date: Tue, 7 Jul 2020 15:37:45 -0500 |
| Subject: [PATCH] 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c |
| index 3570d714ee88..b14bea746875 100644 |
| --- a/sound/soc/soc-topology.c |
| +++ b/sound/soc/soc-topology.c |
| @@ -1281,17 +1281,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. |
| -- |
| 2.27.0 |
| |