ASoC: simple-card: Fix of-node refcount unbalance in DAI-link parser
authorTakashi Iwai <tiwai@suse.de>
Tue, 19 Feb 2019 15:46:49 +0000 (16:46 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 20 Feb 2019 12:12:37 +0000 (12:12 +0000)
The function simple_for_each_link() has a few missing places that
forgot unrefereing of-nodes after the use.  The main do-while loop
may abort when loop=0, and this leaves the node object still
referenced.  A similar leak is found in the error handling of NULL
codec that aborts the loop as well.  Last but not least, the inner
for_each_child_of_node() loop may abort in the middle, and this leaks
the refcount of the iterator node.

This patch addresses these missing refcount issues.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/generic/simple-card.c

index 092963e90e1ef8de473946778718e59444e12ad9..7147bba45a2a61b0830ed49e6057edb3935c9c03 100644 (file)
@@ -442,6 +442,7 @@ static int simple_for_each_link(struct simple_priv *priv,
        struct device_node *top = dev->of_node;
        struct device_node *node;
        bool is_top = 0;
+       int ret = 0;
 
        /* Check if it has dai-link */
        node = of_get_child_by_name(top, PREFIX "dai-link");
@@ -456,13 +457,14 @@ static int simple_for_each_link(struct simple_priv *priv,
                struct device_node *codec;
                struct device_node *np;
                int num = of_get_child_count(node);
-               int ret;
 
                /* get codec */
                codec = of_get_child_by_name(node, is_top ?
                                             PREFIX "codec" : "codec");
-               if (!codec)
-                       return -ENODEV;
+               if (!codec) {
+                       ret = -ENODEV;
+                       goto error;
+               }
 
                of_node_put(codec);
 
@@ -485,14 +487,18 @@ static int simple_for_each_link(struct simple_priv *priv,
                        else
                                ret = func_noml(priv, np, codec, li, is_top);
 
-                       if (ret < 0)
-                               return ret;
+                       if (ret < 0) {
+                               of_node_put(np);
+                               goto error;
+                       }
                }
 
                node = of_get_next_child(top, node);
        } while (!is_top && node);
 
-       return 0;
+ error:
+       of_node_put(node);
+       return ret;
 }
 
 static int simple_parse_aux_devs(struct device_node *node,