diff options
author | Takashi Iwai <tiwai@suse.de> | 2019-02-19 16:46:49 +0100 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-02-20 12:12:37 +0000 |
commit | 0b9c9ed6dd3b61b1d3ef1638786a7216006f67c5 (patch) | |
tree | b7d7b6fbc425ed891d940edf38825aa36cafa8c2 /sound/soc/generic | |
parent | 44662f90cda7ce0b65e77a7f1eefe45fb9053a4e (diff) | |
download | linux-next-0b9c9ed6dd3b61b1d3ef1638786a7216006f67c5.tar.gz |
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/soc/generic')
-rw-r--r-- | sound/soc/generic/simple-card.c | 18 |
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, |