diff mbox series

[RFC,1/4] clk: clk-conf: properly release of nodes

Message ID 20220407133036.213217-2-nuno.sa@analog.com (mailing list archive)
State Changes Requested, archived
Headers show
Series Dynamic OF and use after free related fixes | expand

Commit Message

Nuno Sa April 7, 2022, 1:30 p.m. UTC
We need to call 'of_node_put()' when we are done with the node or on
error paths. Otherwise this can leak memory in DYNAMIC_OF setups.

Fixes: 86be408bfbd8 ("clk: Support for clock parents and rates assigned from device tree")
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
(cherry picked from commit 69eb47a26e7f728a5c052687380993cd9a0dd643)
---
 drivers/clk/clk-conf.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

Comments

Stephen Boyd April 21, 2022, 7:58 p.m. UTC | #1
Quoting Nuno Sá (2022-04-07 06:30:33)
> We need to call 'of_node_put()' when we are done with the node or on
> error paths. Otherwise this can leak memory in DYNAMIC_OF setups.
> 
> Fixes: 86be408bfbd8 ("clk: Support for clock parents and rates assigned from device tree")
> Signed-off-by: Nuno Sá <nuno.sa@analog.com>
> (cherry picked from commit 69eb47a26e7f728a5c052687380993cd9a0dd643)

This line should be removed.

> ---
>  drivers/clk/clk-conf.c | 18 ++++++++++++++----
>  1 file changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
> index 2ef819606c41..d6065cdf1540 100644
> --- a/drivers/clk/clk-conf.c
> +++ b/drivers/clk/clk-conf.c
> @@ -33,9 +33,12 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier)
>                         else
>                                 return rc;
>                 }
> -               if (clkspec.np == node && !clk_supplier)
> +               if (clkspec.np == node && !clk_supplier) {
> +                       of_node_put(clkspec.np);
>                         return 0;
> +               }
>                 pclk = of_clk_get_from_provider(&clkspec);
> +               of_node_put(clkspec.np);
>                 if (IS_ERR(pclk)) {
>                         if (PTR_ERR(pclk) != -EPROBE_DEFER)
>                                 pr_warn("clk: couldn't get parent clock %d for %pOF\n",

I suspect it would be easier to follow and fix if the code was
reorganized to have most of the contents inside this function as a
sub-routine that is called for each index. Then all the node putting and
clk putting can be in one place in that other function and this is a
simple loop around that stops on the first error.

> @@ -49,7 +52,7 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier)
>                         goto err;
>                 if (clkspec.np == node && !clk_supplier) {
>                         rc = 0;
> -                       goto err;
> +                       goto err_of_put;
>                 }
>                 clk = of_clk_get_from_provider(&clkspec);
>                 if (IS_ERR(clk)) {
Nuno Sa April 22, 2022, 7:18 a.m. UTC | #2
> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Thursday, April 21, 2022 9:58 PM
> To: Sa, Nuno <Nuno.Sa@analog.com>; linux-clk@vger.kernel.org
> Cc: Michael Turquette <mturquette@baylibre.com>
> Subject: Re: [RFC PATCH 1/4] clk: clk-conf: properly release of nodes
> 
> [External]
> 
> Quoting Nuno Sá (2022-04-07 06:30:33)
> > We need to call 'of_node_put()' when we are done with the node or
> on
> > error paths. Otherwise this can leak memory in DYNAMIC_OF setups.
> >
> > Fixes: 86be408bfbd8 ("clk: Support for clock parents and rates
> assigned from device tree")
> > Signed-off-by: Nuno Sá <nuno.sa@analog.com>
> > (cherry picked from commit
> 69eb47a26e7f728a5c052687380993cd9a0dd643)
> 
> This line should be removed.
> 

Yes, I know :). I Was just waiting for the review. Somehow I messed
up when preparing the patches to submit...

- Nuno Sá
Nuno Sa April 22, 2022, 7:20 a.m. UTC | #3
> -----Original Message-----
> From: Stephen Boyd <sboyd@kernel.org>
> Sent: Thursday, April 21, 2022 9:58 PM
> To: Sa, Nuno <Nuno.Sa@analog.com>; linux-clk@vger.kernel.org
> Cc: Michael Turquette <mturquette@baylibre.com>
> Subject: Re: [RFC PATCH 1/4] clk: clk-conf: properly release of nodes
> 
> [External]
> 
> Quoting Nuno Sá (2022-04-07 06:30:33)
> > We need to call 'of_node_put()' when we are done with the node or
> on
> > error paths. Otherwise this can leak memory in DYNAMIC_OF setups.
> >
> > Fixes: 86be408bfbd8 ("clk: Support for clock parents and rates
> assigned from device tree")
> > Signed-off-by: Nuno Sá <nuno.sa@analog.com>
> > (cherry picked from commit
> 69eb47a26e7f728a5c052687380993cd9a0dd643)
> 
> This line should be removed.
> 
> > ---
> >  drivers/clk/clk-conf.c | 18 ++++++++++++++----
> >  1 file changed, 14 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
> > index 2ef819606c41..d6065cdf1540 100644
> > --- a/drivers/clk/clk-conf.c
> > +++ b/drivers/clk/clk-conf.c
> > @@ -33,9 +33,12 @@ static int __set_clk_parents(struct
> device_node *node, bool clk_supplier)
> >                         else
> >                                 return rc;
> >                 }
> > -               if (clkspec.np == node && !clk_supplier)
> > +               if (clkspec.np == node && !clk_supplier) {
> > +                       of_node_put(clkspec.np);
> >                         return 0;
> > +               }
> >                 pclk = of_clk_get_from_provider(&clkspec);
> > +               of_node_put(clkspec.np);
> >                 if (IS_ERR(pclk)) {
> >                         if (PTR_ERR(pclk) != -EPROBE_DEFER)
> >                                 pr_warn("clk: couldn't get parent clock %d for
> %pOF\n",
> 
> I suspect it would be easier to follow and fix if the code was
> reorganized to have most of the contents inside this function as a
> sub-routine that is called for each index. Then all the node putting and
> clk putting can be in one place in that other function and this is a
> simple loop around that stops on the first error.
> 

Ups, forgot to answer this one. Yeah, I did not wanted to change much but
I agree that the code could be a bit refactored and I can do that in v2.

- Nuno Sá
diff mbox series

Patch

diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index 2ef819606c41..d6065cdf1540 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -33,9 +33,12 @@  static int __set_clk_parents(struct device_node *node, bool clk_supplier)
 			else
 				return rc;
 		}
-		if (clkspec.np == node && !clk_supplier)
+		if (clkspec.np == node && !clk_supplier) {
+			of_node_put(clkspec.np);
 			return 0;
+		}
 		pclk = of_clk_get_from_provider(&clkspec);
+		of_node_put(clkspec.np);
 		if (IS_ERR(pclk)) {
 			if (PTR_ERR(pclk) != -EPROBE_DEFER)
 				pr_warn("clk: couldn't get parent clock %d for %pOF\n",
@@ -49,7 +52,7 @@  static int __set_clk_parents(struct device_node *node, bool clk_supplier)
 			goto err;
 		if (clkspec.np == node && !clk_supplier) {
 			rc = 0;
-			goto err;
+			goto err_of_put;
 		}
 		clk = of_clk_get_from_provider(&clkspec);
 		if (IS_ERR(clk)) {
@@ -57,7 +60,7 @@  static int __set_clk_parents(struct device_node *node, bool clk_supplier)
 				pr_warn("clk: couldn't get assigned clock %d for %pOF\n",
 					index, node);
 			rc = PTR_ERR(clk);
-			goto err;
+			goto err_of_put;
 		}
 
 		rc = clk_set_parent(clk, pclk);
@@ -66,8 +69,11 @@  static int __set_clk_parents(struct device_node *node, bool clk_supplier)
 			       __clk_get_name(clk), __clk_get_name(pclk), rc);
 		clk_put(clk);
 		clk_put(pclk);
+		of_node_put(clkspec.np);
 	}
 	return 0;
+err_of_put:
+	of_node_put(clkspec.np);
 err:
 	clk_put(pclk);
 	return rc;
@@ -93,14 +99,17 @@  static int __set_clk_rates(struct device_node *node, bool clk_supplier)
 				else
 					return rc;
 			}
-			if (clkspec.np == node && !clk_supplier)
+			if (clkspec.np == node && !clk_supplier) {
+				of_node_put(clkspec.np);
 				return 0;
+			}
 
 			clk = of_clk_get_from_provider(&clkspec);
 			if (IS_ERR(clk)) {
 				if (PTR_ERR(clk) != -EPROBE_DEFER)
 					pr_warn("clk: couldn't get clock %d for %pOF\n",
 						index, node);
+				of_node_put(clkspec.np);
 				return PTR_ERR(clk);
 			}
 
@@ -110,6 +119,7 @@  static int __set_clk_rates(struct device_node *node, bool clk_supplier)
 				       __clk_get_name(clk), rate, rc,
 				       clk_get_rate(clk));
 			clk_put(clk);
+			of_node_put(clkspec.np);
 		}
 		index++;
 	}