ASoC: qcom: Fix of-node refcount unbalance in qcom_snd_parse_of() [Linux 5.1]

ASoC: qcom: Fix of-node refcount unbalance in qcom_snd_parse_of() [Linux 5.1]

This Linux kernel change "ASoC: qcom: Fix of-node refcount unbalance in qcom_snd_parse_of()" 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:51 2019 +0100. The commit for this change in Linux stable tree is 70b7732 (patch).

ASoC: qcom: Fix of-node refcount unbalance in qcom_snd_parse_of()

Although qcom_snd_parse_of() tries to manage the of-node refcount,
there are still a few places that lead to the unblanced refcount in
the error code path.  Namely,

- for_each_child_of_node() needs to unreference the iterator node if
  aborting the loop in the middle,
- cpu, codec and platform node objects have to be unreferenced at each
  iteration,
- platform and codec node objects have to be referred before jumping
  to the error handling code that unreference them unconditionally.

This patch tries to address these by moving the assignment of platform
and codec node objects to the beginning of the loop and adding the
of_node_put() calls adequately.

Fixes: c25e295cd77b ("ASoC: qcom: Add support to parse common audio device nodes")
Cc: Patrick Lai <[email protected]>
Cc: Banajit Goswami <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Mark Brown <[email protected]>

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

 sound/soc/qcom/common.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c
index 4715527..5661025 100644
--- a/sound/soc/qcom/common.c
+++ b/sound/soc/qcom/common.c
@@ -42,6 +42,9 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
    link = card->dai_link;
    for_each_child_of_node(dev->of_node, np) {
        cpu = of_get_child_by_name(np, "cpu");
+       platform = of_get_child_by_name(np, "platform");
+       codec = of_get_child_by_name(np, "codec");
+
        if (!cpu) {
            dev_err(dev, "Can't find cpu DT node\n");
            ret = -EINVAL;
@@ -63,8 +66,6 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
            goto err;
        }

-       platform = of_get_child_by_name(np, "platform");
-       codec = of_get_child_by_name(np, "codec");
        if (codec && platform) {
            link->platform_of_node = of_parse_phandle(platform,
                    "sound-dai",
@@ -100,10 +101,15 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
        link->dpcm_capture = 1;
        link->stream_name = link->name;
        link++;
+
+       of_node_put(cpu);
+       of_node_put(codec);
+       of_node_put(platform);
    }

    return 0;
 err:
+   of_node_put(np);
    of_node_put(cpu);
    of_node_put(codec);
    of_node_put(platform);

Leave a Reply

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