Commit 9a4b2410 authored by Shiraz Saleem's avatar Shiraz Saleem Committed by Jason Gunthorpe
Browse files

i40iw: Do an RCU lookup in i40iw_add_ipv4_addr

The in_dev_for_each_ifa_rtnl() iterator in i40iw_add_ipv4_addr requires
that the rtnl lock be held. But the rtnl_trylock/unlock scheme in this
function does not guarantee it.

Replace the rtnl locking with an RCU lookup using
in_dev_for_each_ifa_rcu()

Fixes: 8e06af71 ("i40iw: add main, hdr, status")
Link: https://lore.kernel.org/r/20200204223840.2151-1-shiraz.saleem@intel.com


Signed-off-by: default avatarShiraz Saleem <shiraz.saleem@intel.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent d7e2d343
Loading
Loading
Loading
Loading
+6 −12
Original line number Diff line number Diff line
@@ -1212,22 +1212,19 @@ static void i40iw_add_ipv4_addr(struct i40iw_device *iwdev)
{
	struct net_device *dev;
	struct in_device *idev;
	bool got_lock = true;
	u32 ip_addr;

	if (!rtnl_trylock())
		got_lock = false;

	for_each_netdev(&init_net, dev) {
	rcu_read_lock();
	for_each_netdev_rcu(&init_net, dev) {
		if ((((rdma_vlan_dev_vlan_id(dev) < 0xFFFF) &&
		      (rdma_vlan_dev_real_dev(dev) == iwdev->netdev)) ||
		    (dev == iwdev->netdev)) && (dev->flags & IFF_UP)) {
		    (dev == iwdev->netdev)) && (READ_ONCE(dev->flags) & IFF_UP)) {
			const struct in_ifaddr *ifa;

			idev = in_dev_get(dev);
			idev = __in_dev_get_rcu(dev);
			if (!idev)
				continue;
			in_dev_for_each_ifa_rtnl(ifa, idev) {
			in_dev_for_each_ifa_rcu(ifa, idev) {
				i40iw_debug(&iwdev->sc_dev, I40IW_DEBUG_CM,
					    "IP=%pI4, vlan_id=%d, MAC=%pM\n", &ifa->ifa_address,
					     rdma_vlan_dev_vlan_id(dev), dev->dev_addr);
@@ -1239,12 +1236,9 @@ static void i40iw_add_ipv4_addr(struct i40iw_device *iwdev)
						       true,
						       I40IW_ARP_ADD);
			}

			in_dev_put(idev);
		}
	}
	if (got_lock)
		rtnl_unlock();
	rcu_read_unlock();
}

/**