summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-02-19 16:46:49 +0100
committerMark Brown <broonie@kernel.org>2019-02-20 12:12:37 +0000
commit0b9c9ed6dd3b61b1d3ef1638786a7216006f67c5 (patch)
treeb7d7b6fbc425ed891d940edf38825aa36cafa8c2 /sound
parent44662f90cda7ce0b65e77a7f1eefe45fb9053a4e (diff)
downloadlinux-stable-0b9c9ed6dd3b61b1d3ef1638786a7216006f67c5.tar.gz
linux-stable-0b9c9ed6dd3b61b1d3ef1638786a7216006f67c5.tar.bz2
linux-stable-0b9c9ed6dd3b61b1d3ef1638786a7216006f67c5.zip
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 <tiwai@suse.de> Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/generic/simple-card.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 092963e90e1e..7147bba45a2a 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,