diff mbox series

[v3] net: mdiobus: fix an OF node reference leak

Message ID 20241216014055.324461-1-joe@pf.is.s.u-tokyo.ac.jp (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [v3] net: mdiobus: fix an OF node reference leak | expand

Checks

Context Check Description
netdev/series_format warning Single patches do not need cover letters; Target tree name not specified in the subject
netdev/tree_selection success Guessed tree name to be net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers fail 1 blamed authors not CCed: ioana.ciornei@nxp.com; 1 maintainers not CCed: ioana.ciornei@nxp.com
netdev/build_clang success Errors and warnings before: 5 this patch: 5
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 23 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-12-16--09-00 (tests: 795)

Commit Message

Joe Hattori Dec. 16, 2024, 1:40 a.m. UTC
fwnode_find_mii_timestamper() calls of_parse_phandle_with_fixed_args()
but does not decrement the refcount of the obtained OF node. Add an
of_node_put() call before returning from the function.

This bug was detected by an experimental static analysis tool that I am
developing.

Fixes: bc1bee3b87ee ("net: mdiobus: Introduce fwnode_mdiobus_register_phy()")
Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
---
Changes in v3:
- Call of_node_put() when arg.args_count != 1 holds.

Changes in v2:
- Call of_node_put() after calling register_mii_timestamper() to avoid
  UAF.
---
 drivers/net/mdio/fwnode_mdio.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

Comments

Andrew Lunn Dec. 16, 2024, 9:33 a.m. UTC | #1
On Mon, Dec 16, 2024 at 10:40:55AM +0900, Joe Hattori wrote:
> fwnode_find_mii_timestamper() calls of_parse_phandle_with_fixed_args()
> but does not decrement the refcount of the obtained OF node. Add an
> of_node_put() call before returning from the function.
> 
> This bug was detected by an experimental static analysis tool that I am
> developing.

Just out of curiosity, have you improved this tool so it now reports
the missing put you handled in version 3? I expect there is more code
with the same error which a static analyser should be able to find
when examining the abstract syntax tree.

> +++ b/drivers/net/mdio/fwnode_mdio.c
> @@ -41,6 +41,7 @@ static struct mii_timestamper *
>  fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
>  {
>  	struct of_phandle_args arg;
> +	struct mii_timestamper *mii_ts;
>  	int err;

The netdev subsystem wants variables declared longest first, shortest
last, also known as reverse Christmas tree. As you work in different
parts of the tree, you will find each subsystem has its own set of
rules you will need to learn.
  
>  	if (is_acpi_node(fwnode))
> @@ -53,10 +54,14 @@ fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
>  	else if (err)
>  		return ERR_PTR(err);
>  
> -	if (arg.args_count != 1)
> +	if (arg.args_count != 1) {
> +		of_node_put(arg.np);
>  		return ERR_PTR(-EINVAL);
> +	}
>  
> -	return register_mii_timestamper(arg.np, arg.args[0]);
> +	mii_ts = register_mii_timestamper(arg.np, arg.args[0]);
> +	of_node_put(arg.np);
> +	return mii_ts;
>  }

Although this is correct, a more normal practice is to put all the
cleanup at the end of the function and use a goto:

	if (arg.args_count != 1) {
		mii_ts = ERR_PTR(-EINVAL);
		goto put_node;
	}

	mii_ts = register_mii_timestamper(arg.np, arg.args[0]);

put_node:
        of_node_put(arg.np);
	return mii_ts;
}

This tends to be more scalable, especially when more cleanup is
required.

	Andrew
Joe Hattori Dec. 18, 2024, 3:54 a.m. UTC | #2
Thank you for your review.

On 12/16/24 18:33, Andrew Lunn wrote:
> On Mon, Dec 16, 2024 at 10:40:55AM +0900, Joe Hattori wrote:
>> fwnode_find_mii_timestamper() calls of_parse_phandle_with_fixed_args()
>> but does not decrement the refcount of the obtained OF node. Add an
>> of_node_put() call before returning from the function.
>>
>> This bug was detected by an experimental static analysis tool that I am
>> developing.
> 
> Just out of curiosity, have you improved this tool so it now reports
> the missing put you handled in version 3? I expect there is more code
> with the same error which a static analyser should be able to find
> when examining the abstract syntax tree.

Yes, and I am experimenting with other driver codes as well.

> 
>> +++ b/drivers/net/mdio/fwnode_mdio.c
>> @@ -41,6 +41,7 @@ static struct mii_timestamper *
>>   fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
>>   {
>>   	struct of_phandle_args arg;
>> +	struct mii_timestamper *mii_ts;
>>   	int err;
> 
> The netdev subsystem wants variables declared longest first, shortest
> last, also known as reverse Christmas tree. As you work in different
> parts of the tree, you will find each subsystem has its own set of
> rules you will need to learn.

TIL. Applied in the v4 patch.

>    
>>   	if (is_acpi_node(fwnode))
>> @@ -53,10 +54,14 @@ fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
>>   	else if (err)
>>   		return ERR_PTR(err);
>>   
>> -	if (arg.args_count != 1)
>> +	if (arg.args_count != 1) {
>> +		of_node_put(arg.np);
>>   		return ERR_PTR(-EINVAL);
>> +	}
>>   
>> -	return register_mii_timestamper(arg.np, arg.args[0]);
>> +	mii_ts = register_mii_timestamper(arg.np, arg.args[0]);
>> +	of_node_put(arg.np);
>> +	return mii_ts;
>>   }
> 
> Although this is correct, a more normal practice is to put all the
> cleanup at the end of the function and use a goto:
> 
> 	if (arg.args_count != 1) {
> 		mii_ts = ERR_PTR(-EINVAL);
> 		goto put_node;
> 	}
> 
> 	mii_ts = register_mii_timestamper(arg.np, arg.args[0]);
> 
> put_node:
>          of_node_put(arg.np);
> 	return mii_ts;
> }
> 
> This tends to be more scalable, especially when more cleanup is
> required.

Makes sense. Applied in the v4 patch as well.

> 
> 	Andrew

Best,
Joe
diff mbox series

Patch

diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c
index b156493d7084..b18a1934018e 100644
--- a/drivers/net/mdio/fwnode_mdio.c
+++ b/drivers/net/mdio/fwnode_mdio.c
@@ -41,6 +41,7 @@  static struct mii_timestamper *
 fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
 {
 	struct of_phandle_args arg;
+	struct mii_timestamper *mii_ts;
 	int err;
 
 	if (is_acpi_node(fwnode))
@@ -53,10 +54,14 @@  fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
 	else if (err)
 		return ERR_PTR(err);
 
-	if (arg.args_count != 1)
+	if (arg.args_count != 1) {
+		of_node_put(arg.np);
 		return ERR_PTR(-EINVAL);
+	}
 
-	return register_mii_timestamper(arg.np, arg.args[0]);
+	mii_ts = register_mii_timestamper(arg.np, arg.args[0]);
+	of_node_put(arg.np);
+	return mii_ts;
 }
 
 int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,