If del_nbp()->cancel_delayed_work(carrier_check) fails, port_carrier_check()
may run later and access an already freed container (struct net_bridge_port).
With this patch, carrier_check owns a reference to "struct net_bridge_port",
not net_device, so it is always safe to acces the container.
port_carrier_check() uses p->dev->br_port == NULL as indication that net_bridge_port
is under destruction. Otherwise it assumes that p->dev->br_port == p.
Signed-off-by: Oleg Nesterov <redacted>
Acked-By: David Howells <dhowells@redhat.com>
From: Stephen Hemminger <hidden> Date: 2007-02-21 00:25:06
On Wed, 21 Feb 2007 01:19:41 +0300
Oleg Nesterov [off-list ref] wrote:
quoted hunk
If del_nbp()->cancel_delayed_work(carrier_check) fails, port_carrier_check()
may run later and access an already freed container (struct net_bridge_port).
With this patch, carrier_check owns a reference to "struct net_bridge_port",
not net_device, so it is always safe to acces the container.
port_carrier_check() uses p->dev->br_port == NULL as indication that net_bridge_port
is under destruction. Otherwise it assumes that p->dev->br_port == p.
Signed-off-by: Oleg Nesterov <redacted>
Acked-By: David Howells <dhowells@redhat.com>
Moving this around is problematic.
The ordering here was chosen to be RCU friendly so that
p->dev indicates the port is in process of being deleted but traffic
may still be using old reference, but new traffic should not use it.
Probably the best thing to do is pull the whole delayed work queue
and auto port speed stuff. When STP is moved to user space then
it can do the ethtool op there.
--
Stephen Hemminger [off-list ref]
On Tue, Feb 20, 2007 at 04:24:34PM -0800, Stephen Hemminger wrote:
On Wed, 21 Feb 2007 01:19:41 +0300
Oleg Nesterov [off-list ref] wrote:
quoted
If del_nbp()->cancel_delayed_work(carrier_check) fails, port_carrier_check()
may run later and access an already freed container (struct net_bridge_port).
With this patch, carrier_check owns a reference to "struct net_bridge_port",
not net_device, so it is always safe to acces the container.
port_carrier_check() uses p->dev->br_port == NULL as indication that net_bridge_port
is under destruction. Otherwise it assumes that p->dev->br_port == p.
Signed-off-by: Oleg Nesterov <redacted>
Acked-By: David Howells <dhowells@redhat.com>
Moving this around is problematic.
The ordering here was chosen to be RCU friendly so that
p->dev indicates the port is in process of being deleted but traffic
may still be using old reference, but new traffic should not use it.
I have known issues with RCU, but dare to disagree here.
It's done during call_rcu, so anything RCU friendly shouldn't
see this at the moment at all. It could be needed for those
with refcounting - than it should be checked, if there is
anything more than port_carrier_check.
I don't have enough time to check this deep enough, but at
the moment I think this patch is right (there is really a
very short race time between calling this function and
container_of).
Regards,
Jarek P.
On Wed, Feb 21, 2007 at 09:23:45AM +0100, Jarek Poplawski wrote:
...
I have known issues with RCU, but dare to disagree here.
It's done during call_rcu, so anything RCU friendly shouldn't
see this at the moment at all. It could be needed for those
with refcounting - than it should be checked, if there is
anything more than port_carrier_check.
Sorry for this than-ing!
(It's my next favorite issue after RCU.)
Jarek P.
Moving this around is problematic.
The ordering here was chosen to be RCU friendly so that
p->dev indicates the port is in process of being deleted but traffic
may still be using old reference, but new traffic should not use it.
But it is still RCU friendly? destroy_nbp() is rcu-callback which
calls release_nbp() if we have a last reference to ->kobj. This
means that dev_put() may be done a bit later, but not earlier.
And RCU can only garantee "not before", any rcu-callback could be
delayed unpredictably.
Stephen, I know nothing about net/, and
Probably the best thing to do is pull the whole delayed work queue
and auto port speed stuff. When STP is moved to user space then
it can do the ethtool op there.
I can't understand any single word in the paragraph above :)
But the bug (the stable tree has it too) is real. If this patch is
really wrong, could you please take care of it?
Oleg.
From: Stephen Hemminger <hidden> Date: 2007-02-21 18:56:26
This is what I was suggesting by getting rid of the work queue completely.
---
net/bridge/br_if.c | 34 ++++++++--------------------------
net/bridge/br_notify.c | 25 +++++++++++--------------
net/bridge/br_private.h | 5 ++---
3 files changed, 21 insertions(+), 43 deletions(-)
@@ -42,51 +42,48 @@br=p->br;-spin_lock_bh(&br->lock);switch(event){caseNETDEV_CHANGEMTU:dev_set_mtu(br->dev,br_min_mtu(br));break;caseNETDEV_CHANGEADDR:+spin_lock_bh(&br->lock);br_fdb_changeaddr(p,dev->dev_addr);br_ifinfo_notify(RTM_NEWLINK,p);br_stp_recalculate_bridge_id(br);+spin_unlock_bh(&br->lock);break;caseNETDEV_CHANGE:-if(br->dev->flags&IFF_UP)-if(schedule_delayed_work(&p->carrier_check,-BR_PORT_DEBOUNCE))-dev_hold(dev);+br_port_carrier_check(p);break;caseNETDEV_FEAT_CHANGE:-if(br->dev->flags&IFF_UP)+spin_lock_bh(&br->lock);+if(netif_running(br->dev))br_features_recompute(br);--/* could do recursive feature change notification-*butwhowouldcare??-*/+spin_unlock_bh(&br->lock);break;caseNETDEV_DOWN:+spin_lock_bh(&br->lock);if(br->dev->flags&IFF_UP)br_stp_disable_port(p);+spin_unlock_bh(&br->lock);break;caseNETDEV_UP:+spin_lock_bh(&br->lock);if(netif_carrier_ok(dev)&&(br->dev->flags&IFF_UP))br_stp_enable_port(p);+spin_unlock_bh(&br->lock);break;caseNETDEV_UNREGISTER:-spin_unlock_bh(&br->lock);br_del_if(br,dev);-gotodone;+break;}-spin_unlock_bh(&br->lock);-done:returnNOTIFY_DONE;}---bridge.orig/net/bridge/br_private.h2007-02-2110:22:43.000000000-0800+++bridge/net/bridge/br_private.h2007-02-2110:53:49.000000000-0800
May I ask you to redo this patch on top of
[PATCH 1/3] net/bridge/br_if.c: don't use _WORK_NAR
http://marc.theaimsgroup.com/?l=linux-kernel&m=117183517612775
?
We are removing the _NAR stuff, it would be nice to do this in a separate
patch.
Thanks!
Oleg.
May I ask you to redo this patch on top of
[PATCH 1/3] net/bridge/br_if.c: don't use _WORK_NAR
http://marc.theaimsgroup.com/?l=linux-kernel&m=117183517612775
?
We are removing the _NAR stuff, it would be nice to do this in a separate
patch.
Thanks!
Oleg.
I would rather put it in a bugfix patchset for 2.6.21 and 2.6.20-stable
--
Stephen Hemminger [off-list ref]
Of course my opinion shouldn't matter here, but it looks
like withdrawing (or giving up) to the older way. So I'm
not excited, but I trust there is a reason for this.
Cheers,
Jarek P.