ASoC: topology: fix kernel oops on route addition error
authorPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Tue, 7 Jul 2020 20:37:45 +0000 (15:37 -0500)
committerMark Brown <broonie@kernel.org>
Wed, 8 Jul 2020 13:25:18 +0000 (14:25 +0100)
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>
sound/soc/soc-topology.c

index 43e5745..f336a9c 100644 (file)
@@ -1261,17 +1261,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.