ASoC: simple-card: Fix of-node refcount unbalance in DAI-link parser [Linux 5.1]

ASoC: simple-card: Fix of-node refcount unbalance in DAI-link parser [Linux 5.1]

This Linux kernel change "ASoC: simple-card: Fix of-node refcount unbalance in DAI-link parser" is included in the Linux 5.1 release. This change is authored by Takashi Iwai <tiwai [at] suse.de> on Tue Feb 19 16:46:49 2019 +0100. The commit for this change in Linux stable tree is 0b9c9ed (patch).

ASoC: simple-card: Fix of-node refcount unbalance in DAI-link parser

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 <[email protected]>
Acked-by: Kuninori Morimoto <[email protected]>
Signed-off-by: Mark Brown <[email protected]>

There are 18 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 sound/soc/generic/simple-card.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 092963e..7147bba 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -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,

Leave a Reply

Your email address will not be published. Required fields are marked *