netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv2 net] bonding: fix missed rcu protection
@ 2022-05-17  8:23 Hangbin Liu
  2022-05-17 17:32 ` Jonathan Toppins
  2022-05-17 17:54 ` Jakub Kicinski
  0 siblings, 2 replies; 7+ messages in thread
From: Hangbin Liu @ 2022-05-17  8:23 UTC (permalink / raw)
  To: netdev
  Cc: Jay Vosburgh, Veaceslav Falico, Andy Gospodarek,
	David S . Miller, Jakub Kicinski, David Ahern, Jonathan Toppins,
	Eric Dumazet, Paolo Abeni, Hangbin Liu,
	syzbot+92beb3d46aab498710fa, Vladimir Oltean

When removing the rcu_read_lock in bond_ethtool_get_ts_info() as
discussed [1], I didn't notice it could be called via setsockopt,
which doesn't hold rcu lock, as syzbot pointed:

  Call Trace:
   <TASK>
   __dump_stack lib/dump_stack.c:88 [inline]
   dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106
   bond_option_active_slave_get_rcu include/net/bonding.h:353 [inline]
   bond_ethtool_get_ts_info+0x32c/0x3a0 drivers/net/bonding/bond_main.c:5595
   __ethtool_get_ts_info+0x173/0x240 net/ethtool/common.c:554
   ethtool_get_phc_vclocks+0x99/0x110 net/ethtool/common.c:568
   sock_timestamping_bind_phc net/core/sock.c:869 [inline]
   sock_set_timestamping+0x3a3/0x7e0 net/core/sock.c:916
   sock_setsockopt+0x543/0x2ec0 net/core/sock.c:1221
   __sys_setsockopt+0x55e/0x6a0 net/socket.c:2223
   __do_sys_setsockopt net/socket.c:2238 [inline]
   __se_sys_setsockopt net/socket.c:2235 [inline]
   __x64_sys_setsockopt+0xba/0x150 net/socket.c:2235
   do_syscall_x64 arch/x86/entry/common.c:50 [inline]
   do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
   entry_SYSCALL_64_after_hwframe+0x44/0xae
  RIP: 0033:0x7f8902c8eb39

Fix it by adding rcu_read_lock and take a ref on the real_dev.

[1] https://lore.kernel.org/netdev/27565.1642742439@famine/

Reported-by: syzbot+92beb3d46aab498710fa@syzkaller.appspotmail.com
Fixes: aa6034678e87 ("bonding: use rcu_dereference_rtnl when get bonding active slave")
Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Suggested-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>

---
v2: add ref on the real_dev as Jakub and Paolo suggested.
---
 drivers/net/bonding/bond_main.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 38e152548126..fcaa5ccea7af 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -5591,24 +5591,35 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev,
 	const struct ethtool_ops *ops;
 	struct net_device *real_dev;
 	struct phy_device *phydev;
+	int ret = 0;
 
+	rcu_read_lock();
 	real_dev = bond_option_active_slave_get_rcu(bond);
 	if (real_dev) {
+		dev_hold(real_dev);
+		rcu_read_unlock();
 		ops = real_dev->ethtool_ops;
 		phydev = real_dev->phydev;
 
 		if (phy_has_tsinfo(phydev)) {
-			return phy_ts_info(phydev, info);
+			ret = phy_ts_info(phydev, info);
+			goto out;
 		} else if (ops->get_ts_info) {
-			return ops->get_ts_info(real_dev, info);
+			ret = ops->get_ts_info(real_dev, info);
+			goto out;
 		}
+	} else {
+		rcu_read_unlock();
 	}
 
 	info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE |
 				SOF_TIMESTAMPING_SOFTWARE;
 	info->phc_index = -1;
 
-	return 0;
+out:
+	if (real_dev)
+		dev_put(real_dev);
+	return ret;
 }
 
 static const struct ethtool_ops bond_ethtool_ops = {
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCHv2 net] bonding: fix missed rcu protection
  2022-05-17  8:23 [PATCHv2 net] bonding: fix missed rcu protection Hangbin Liu
@ 2022-05-17 17:32 ` Jonathan Toppins
  2022-05-18  2:18   ` Hangbin Liu
  2022-05-19 14:34   ` Vladimir Oltean
  2022-05-17 17:54 ` Jakub Kicinski
  1 sibling, 2 replies; 7+ messages in thread
From: Jonathan Toppins @ 2022-05-17 17:32 UTC (permalink / raw)
  To: liuhangbin
  Cc: andy, davem, dsahern, eric.dumazet, j.vosburgh, jtoppins, kuba,
	netdev, pabeni, syzbot+92beb3d46aab498710fa, vfalico,
	vladimir.oltean, Eric Dumazet, linux-kernel

Signed-off-by: Jonathan Toppins <jtoppins@redhat.com>
---
RESEND, list still didn't receive my last version

The diffstat is slightly larger but IMO a slightly more readable version.
When I was reading v2 I found myself jumping around.
I only compile tested it, so YMMV.

If this amount of change is too much v2 from Hangbin looks correct to
me.

 drivers/net/bonding/bond_main.c | 31 ++++++++++++++++++++-----------
 1 file changed, 20 insertions(+), 11 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 38e152548126..f9d27b63c454 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -5591,23 +5591,32 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev,
 	const struct ethtool_ops *ops;
 	struct net_device *real_dev;
 	struct phy_device *phydev;
+	int ret = 0;
 
+	rcu_read_lock();
 	real_dev = bond_option_active_slave_get_rcu(bond);
-	if (real_dev) {
-		ops = real_dev->ethtool_ops;
-		phydev = real_dev->phydev;
-
-		if (phy_has_tsinfo(phydev)) {
-			return phy_ts_info(phydev, info);
-		} else if (ops->get_ts_info) {
-			return ops->get_ts_info(real_dev, info);
-		}
-	}
+	if (real_dev)
+		dev_hold(real_dev);
+	rcu_read_unlock();
+
+	if (!real_dev)
+		goto software;
 
+	ops = real_dev->ethtool_ops;
+	phydev = real_dev->phydev;
+
+	if (phy_has_tsinfo(phydev))
+		ret = phy_ts_info(phydev, info);
+	else if (ops->get_ts_info)
+		ret = ops->get_ts_info(real_dev, info);
+
+	dev_put(real_dev);
+	return ret;
+
+software:
 	info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE |
 				SOF_TIMESTAMPING_SOFTWARE;
 	info->phc_index = -1;
-
 	return 0;
 }
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCHv2 net] bonding: fix missed rcu protection
  2022-05-17  8:23 [PATCHv2 net] bonding: fix missed rcu protection Hangbin Liu
  2022-05-17 17:32 ` Jonathan Toppins
@ 2022-05-17 17:54 ` Jakub Kicinski
  2022-05-17 18:25   ` Stephen Hemminger
  1 sibling, 1 reply; 7+ messages in thread
From: Jakub Kicinski @ 2022-05-17 17:54 UTC (permalink / raw)
  To: Hangbin Liu
  Cc: netdev, Jay Vosburgh, Veaceslav Falico, Andy Gospodarek,
	David S . Miller, David Ahern, Jonathan Toppins, Eric Dumazet,
	Paolo Abeni, syzbot+92beb3d46aab498710fa, Vladimir Oltean

On Tue, 17 May 2022 16:23:12 +0800 Hangbin Liu wrote:
> +	rcu_read_lock();
>  	real_dev = bond_option_active_slave_get_rcu(bond);
>  	if (real_dev) {
> +		dev_hold(real_dev);
> +		rcu_read_unlock();
>  		ops = real_dev->ethtool_ops;
>  		phydev = real_dev->phydev;
>  
>  		if (phy_has_tsinfo(phydev)) {
> -			return phy_ts_info(phydev, info);
> +			ret = phy_ts_info(phydev, info);
> +			goto out;
>  		} else if (ops->get_ts_info) {
> -			return ops->get_ts_info(real_dev, info);
> +			ret = ops->get_ts_info(real_dev, info);
> +			goto out;
>  		}
> +	} else {
> +		rcu_read_unlock();
>  	}
>  
>  	info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE |
>  				SOF_TIMESTAMPING_SOFTWARE;
>  	info->phc_index = -1;
>  
> -	return 0;
> +out:
> +	if (real_dev)
> +		dev_put(real_dev);

dev_hold() and dev_put() can take NULL these days, for better or worse.
I think the code simplification is worth making use of that, even tho
it will make the backport slightly more tricky (perhaps make a not of
this in the commit message).

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCHv2 net] bonding: fix missed rcu protection
  2022-05-17 17:54 ` Jakub Kicinski
@ 2022-05-17 18:25   ` Stephen Hemminger
  0 siblings, 0 replies; 7+ messages in thread
From: Stephen Hemminger @ 2022-05-17 18:25 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Hangbin Liu, netdev, Jay Vosburgh, Veaceslav Falico,
	Andy Gospodarek, David S . Miller, David Ahern, Jonathan Toppins,
	Eric Dumazet, Paolo Abeni, syzbot+92beb3d46aab498710fa,
	Vladimir Oltean

On Tue, 17 May 2022 10:54:45 -0700
Jakub Kicinski <kuba@kernel.org> wrote:

> dev_hold() and dev_put() can take NULL these days, for better or worse.
> I think the code simplification is worth making use of that, even tho
> it will make the backport slightly more tricky (perhaps make a not of
> this in the commit message).

Since that is so, would be worth having coccinelle script to cleanup
existing code.

See scripts/coccinelle/ifnullfree.cocci for similar example.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCHv2 net] bonding: fix missed rcu protection
  2022-05-17 17:32 ` Jonathan Toppins
@ 2022-05-18  2:18   ` Hangbin Liu
  2022-05-18 15:54     ` Jonathan Toppins
  2022-05-19 14:34   ` Vladimir Oltean
  1 sibling, 1 reply; 7+ messages in thread
From: Hangbin Liu @ 2022-05-18  2:18 UTC (permalink / raw)
  To: Jonathan Toppins
  Cc: andy, davem, dsahern, eric.dumazet, j.vosburgh, kuba, netdev,
	pabeni, syzbot+92beb3d46aab498710fa, vfalico, vladimir.oltean,
	Eric Dumazet, linux-kernel

On Tue, May 17, 2022 at 01:32:58PM -0400, Jonathan Toppins wrote:
> Signed-off-by: Jonathan Toppins <jtoppins@redhat.com>
> ---
> RESEND, list still didn't receive my last version
> 
> The diffstat is slightly larger but IMO a slightly more readable version.
> When I was reading v2 I found myself jumping around.

Hi Jon,

Thanks for the commit. But..

> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index 38e152548126..f9d27b63c454 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -5591,23 +5591,32 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev,
>  	const struct ethtool_ops *ops;
>  	struct net_device *real_dev;
>  	struct phy_device *phydev;
> +	int ret = 0;
>  
> +	rcu_read_lock();
>  	real_dev = bond_option_active_slave_get_rcu(bond);
> -	if (real_dev) {
> -		ops = real_dev->ethtool_ops;
> -		phydev = real_dev->phydev;
> -
> -		if (phy_has_tsinfo(phydev)) {
> -			return phy_ts_info(phydev, info);
> -		} else if (ops->get_ts_info) {
> -			return ops->get_ts_info(real_dev, info);
> -		}
> -	}
> +	if (real_dev)
> +		dev_hold(real_dev);
> +	rcu_read_unlock();
> +
> +	if (!real_dev)
> +		goto software;
>  
> +	ops = real_dev->ethtool_ops;
> +	phydev = real_dev->phydev;
> +
> +	if (phy_has_tsinfo(phydev))
> +		ret = phy_ts_info(phydev, info);
> +	else if (ops->get_ts_info)
> +		ret = ops->get_ts_info(real_dev, info);
	else {
		dev_put(real_dev);
		goto software;
	}

Here we need another check and goto software if !phy_has_tsinfo() and
no ops->get_ts_info. With this change we also have 2 goto and dev_put().

> +
> +	dev_put(real_dev);
> +	return ret;
> +
> +software:
>  	info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE |
>  				SOF_TIMESTAMPING_SOFTWARE;
>  	info->phc_index = -1;
> -
>  	return 0;
>  }

As Jakub remind, dev_hold() and dev_put() can take NULL now. So how about
this new patch:

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 38e152548126..b5c5196e03ee 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -5591,16 +5591,23 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev,
 	const struct ethtool_ops *ops;
 	struct net_device *real_dev;
 	struct phy_device *phydev;
+	int ret = 0;
 
+	rcu_read_lock();
 	real_dev = bond_option_active_slave_get_rcu(bond);
+	dev_hold(real_dev);
+	rcu_read_unlock();
+
 	if (real_dev) {
 		ops = real_dev->ethtool_ops;
 		phydev = real_dev->phydev;
 
 		if (phy_has_tsinfo(phydev)) {
-			return phy_ts_info(phydev, info);
+			ret = phy_ts_info(phydev, info);
+			goto out;
 		} else if (ops->get_ts_info) {
-			return ops->get_ts_info(real_dev, info);
+			ret = ops->get_ts_info(real_dev, info);
+			goto out;
 		}
 	}
 
@@ -5608,7 +5615,9 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev,
 				SOF_TIMESTAMPING_SOFTWARE;
 	info->phc_index = -1;
 
-	return 0;
+out:
+	dev_put(real_dev);
+	return ret;
 }

Thanks
Hangbin

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCHv2 net] bonding: fix missed rcu protection
  2022-05-18  2:18   ` Hangbin Liu
@ 2022-05-18 15:54     ` Jonathan Toppins
  0 siblings, 0 replies; 7+ messages in thread
From: Jonathan Toppins @ 2022-05-18 15:54 UTC (permalink / raw)
  To: Hangbin Liu
  Cc: andy, davem, dsahern, eric.dumazet, j.vosburgh, kuba, netdev,
	pabeni, syzbot+92beb3d46aab498710fa, vfalico, vladimir.oltean,
	Eric Dumazet, linux-kernel

On 5/17/22 22:18, Hangbin Liu wrote:
> On Tue, May 17, 2022 at 01:32:58PM -0400, Jonathan Toppins wrote:
>> Signed-off-by: Jonathan Toppins <jtoppins@redhat.com>
>> ---
>> RESEND, list still didn't receive my last version
>>
>> The diffstat is slightly larger but IMO a slightly more readable version.
>> When I was reading v2 I found myself jumping around.
> 
> Hi Jon,
> 
> Thanks for the commit. But..
> 
>> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
>> index 38e152548126..f9d27b63c454 100644
>> --- a/drivers/net/bonding/bond_main.c
>> +++ b/drivers/net/bonding/bond_main.c
>> @@ -5591,23 +5591,32 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev,
>>   	const struct ethtool_ops *ops;
>>   	struct net_device *real_dev;
>>   	struct phy_device *phydev;
>> +	int ret = 0;
>>   
>> +	rcu_read_lock();
>>   	real_dev = bond_option_active_slave_get_rcu(bond);
>> -	if (real_dev) {
>> -		ops = real_dev->ethtool_ops;
>> -		phydev = real_dev->phydev;
>> -
>> -		if (phy_has_tsinfo(phydev)) {
>> -			return phy_ts_info(phydev, info);
>> -		} else if (ops->get_ts_info) {
>> -			return ops->get_ts_info(real_dev, info);
>> -		}
>> -	}
>> +	if (real_dev)
>> +		dev_hold(real_dev);
>> +	rcu_read_unlock();
>> +
>> +	if (!real_dev)
>> +		goto software;
>>   
>> +	ops = real_dev->ethtool_ops;
>> +	phydev = real_dev->phydev;
>> +
>> +	if (phy_has_tsinfo(phydev))
>> +		ret = phy_ts_info(phydev, info);
>> +	else if (ops->get_ts_info)
>> +		ret = ops->get_ts_info(real_dev, info);
> 	else {
> 		dev_put(real_dev);
> 		goto software;
> 	}
> 
> Here we need another check and goto software if !phy_has_tsinfo() and
> no ops->get_ts_info. With this change we also have 2 goto and dev_put().

Ah yes. I cannot think of a way to make this simpler. The patch below 
looks good.

> 
>> +
>> +	dev_put(real_dev);
>> +	return ret;
>> +
>> +software:
>>   	info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE |
>>   				SOF_TIMESTAMPING_SOFTWARE;
>>   	info->phc_index = -1;
>> -
>>   	return 0;
>>   }
> 
> As Jakub remind, dev_hold() and dev_put() can take NULL now. So how about
> this new patch:
> 
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index 38e152548126..b5c5196e03ee 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -5591,16 +5591,23 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev,
>   	const struct ethtool_ops *ops;
>   	struct net_device *real_dev;
>   	struct phy_device *phydev;
> +	int ret = 0;
>   
> +	rcu_read_lock();
>   	real_dev = bond_option_active_slave_get_rcu(bond);
> +	dev_hold(real_dev);
> +	rcu_read_unlock();
> +
>   	if (real_dev) {
>   		ops = real_dev->ethtool_ops;
>   		phydev = real_dev->phydev;
>   
>   		if (phy_has_tsinfo(phydev)) {
> -			return phy_ts_info(phydev, info);
> +			ret = phy_ts_info(phydev, info);
> +			goto out;
>   		} else if (ops->get_ts_info) {
> -			return ops->get_ts_info(real_dev, info);
> +			ret = ops->get_ts_info(real_dev, info);
> +			goto out;
>   		}
>   	}
>   
> @@ -5608,7 +5615,9 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev,
>   				SOF_TIMESTAMPING_SOFTWARE;
>   	info->phc_index = -1;
>   
> -	return 0;
> +out:
> +	dev_put(real_dev);
> +	return ret;
>   }
> 
> Thanks
> Hangbin
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCHv2 net] bonding: fix missed rcu protection
  2022-05-17 17:32 ` Jonathan Toppins
  2022-05-18  2:18   ` Hangbin Liu
@ 2022-05-19 14:34   ` Vladimir Oltean
  1 sibling, 0 replies; 7+ messages in thread
From: Vladimir Oltean @ 2022-05-19 14:34 UTC (permalink / raw)
  To: Jonathan Toppins
  Cc: liuhangbin, andy, davem, dsahern, eric.dumazet, j.vosburgh, kuba,
	netdev, pabeni, syzbot+92beb3d46aab498710fa, vfalico,
	Eric Dumazet, linux-kernel

On Tue, May 17, 2022 at 01:32:58PM -0400, Jonathan Toppins wrote:
> Signed-off-by: Jonathan Toppins <jtoppins@redhat.com>
> ---
> RESEND, list still didn't receive my last version
> 
> The diffstat is slightly larger but IMO a slightly more readable version.
> When I was reading v2 I found myself jumping around.
> I only compile tested it, so YMMV.
> 
> If this amount of change is too much v2 from Hangbin looks correct to
> me.

Seems to be too big of a change for what the issue is, yes, sorry.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-05-19 14:34 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-17  8:23 [PATCHv2 net] bonding: fix missed rcu protection Hangbin Liu
2022-05-17 17:32 ` Jonathan Toppins
2022-05-18  2:18   ` Hangbin Liu
2022-05-18 15:54     ` Jonathan Toppins
2022-05-19 14:34   ` Vladimir Oltean
2022-05-17 17:54 ` Jakub Kicinski
2022-05-17 18:25   ` Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).