summaryrefslogtreecommitdiff
path: root/net/bridge
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@mellanox.com>2016-01-27 17:16:43 +0300
committerDavid S. Miller <davem@davemloft.net>2016-01-29 03:21:31 +0300
commit4f2c6ae5c64c353fb1b0425e4747e5603feadba1 (patch)
tree75e57cd0d11cd1cd39eb12784472b1aff6537242 /net/bridge
parent7d0105b5334b9722b7d33acad613096dfcf3330e (diff)
downloadlinux-4f2c6ae5c64c353fb1b0425e4747e5603feadba1.tar.xz
switchdev: Require RTNL mutex to be held when sending FDB notifications
When switchdev drivers process FDB notifications from the underlying device they resolve the netdev to which the entry points to and notify the bridge using the switchdev notifier. However, since the RTNL mutex is not held there is nothing preventing the netdev from disappearing in the middle, which will cause br_switchdev_event() to dereference a non-existing netdev. Make switchdev drivers hold the lock at the beginning of the notification processing session and release it once it ends, after notifying the bridge. Also, remove switchdev_mutex and fdb_lock, as they are no longer needed when RTNL mutex is held. Fixes: 03bf0c281234 ("switchdev: introduce switchdev notifier") Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br.c3
1 files changed, 1 insertions, 2 deletions
diff --git a/net/bridge/br.c b/net/bridge/br.c
index a1abe4936fe1..3addc05b9a16 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -121,6 +121,7 @@ static struct notifier_block br_device_notifier = {
.notifier_call = br_device_event
};
+/* called with RTNL */
static int br_switchdev_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
@@ -130,7 +131,6 @@ static int br_switchdev_event(struct notifier_block *unused,
struct switchdev_notifier_fdb_info *fdb_info;
int err = NOTIFY_DONE;
- rtnl_lock();
p = br_port_get_rtnl(dev);
if (!p)
goto out;
@@ -155,7 +155,6 @@ static int br_switchdev_event(struct notifier_block *unused,
}
out:
- rtnl_unlock();
return err;
}