bridge: fix bridge netlink RCU usage
authorJohannes Berg <johannes.berg@intel.com>
Tue, 3 Mar 2015 15:02:16 +0000 (16:02 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 4 Mar 2015 05:20:22 +0000 (00:20 -0500)
When the STP timer fires, it can call br_ifinfo_notify(),
which in turn ends up in the new br_get_link_af_size().
This function is annotated to be using RTNL locking, which
clearly isn't the case here, and thus lockdep warns:

  ===============================
  [ INFO: suspicious RCU usage. ]
  3.19.0+ #569 Not tainted
  -------------------------------
  net/bridge/br_private.h:204 suspicious rcu_dereference_protected() usage!

Fix this by doing RCU locking here.

Fixes: b7853d73e39b ("bridge: add vlan info to bridge setlink and dellink notification messages")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bridge/br_netlink.c

index 3de0eef..c720839 100644 (file)
@@ -81,17 +81,19 @@ static size_t br_get_link_af_size_filtered(const struct net_device *dev,
        struct net_port_vlans *pv;
        int num_vlan_infos;
 
+       rcu_read_lock();
        if (br_port_exists(dev))
-               pv = nbp_get_vlan_info(br_port_get_rtnl(dev));
+               pv = nbp_get_vlan_info(br_port_get_rcu(dev));
        else if (dev->priv_flags & IFF_EBRIDGE)
                pv = br_get_vlan_info((struct net_bridge *)netdev_priv(dev));
        else
-               return 0;
-
-       if (!pv)
-               return 0;
+               pv = NULL;
+       if (pv)
+               num_vlan_infos = br_get_num_vlan_infos(pv, filter_mask);
+       else
+               num_vlan_infos = 0;
+       rcu_read_unlock();
 
-       num_vlan_infos = br_get_num_vlan_infos(pv, filter_mask);
        if (!num_vlan_infos)
                return 0;