* [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 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@gmail.com, andy@greyhouse.net, davem@davemloft.net, dsahern@gmail.com, eric.dumazet@gmail.com, j.vosburgh@gmail.com, kuba@kernel.org, netdev@vger.kernel.org, pabeni@redhat.com, syzbot+92beb3d46aab498710fa@syzkaller.appspotmail.com, vfalico@gmail.com, Eric Dumazet, linux-kernel@vger.kernel.org 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
* 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
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).