Commit 88d1f877 authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Paolo Abeni
Browse files

ipv4: Convert devinet_ioctl() to per-netns RTNL except for SIOCSIFFLAGS.



Basically, devinet_ioctl() operates on a single netns.

However, ioctl(SIOCSIFFLAGS) will trigger the netdev notifier
that could touch another netdev in different netns.

Let's use per-netns RTNL helper in devinet_ioctl() and place
ASSERT_RTNL() for SIOCSIFFLAGS.

We will remove ASSERT_RTNL() once RTM_SETLINK and RTM_DELLINK
are converted.

Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 77453d42
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -589,9 +589,7 @@ static int inet_insert_ifa(struct in_ifaddr *ifa)

static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
{
	struct in_device *in_dev = __in_dev_get_rtnl(dev);

	ASSERT_RTNL();
	struct in_device *in_dev = __in_dev_get_rtnl_net(dev);

	ipv4_devconf_setall(in_dev);
	neigh_parms_data_state_setall(in_dev->arp_parms);
@@ -1129,7 +1127,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
		goto out;
	}

	rtnl_lock();
	rtnl_net_lock(net);

	ret = -ENODEV;
	dev = __dev_get_by_name(net, ifr->ifr_name);
@@ -1139,7 +1137,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
	if (colon)
		*colon = ':';

	in_dev = __in_dev_get_rtnl(dev);
	in_dev = __in_dev_get_rtnl_net(dev);
	if (in_dev) {
		if (tryaddrmatch) {
			/* Matthias Andree */
@@ -1149,7 +1147,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
			   This is checked above. */

			for (ifap = &in_dev->ifa_list;
			     (ifa = rtnl_dereference(*ifap)) != NULL;
			     (ifa = rtnl_net_dereference(net, *ifap)) != NULL;
			     ifap = &ifa->ifa_next) {
				if (!strcmp(ifr->ifr_name, ifa->ifa_label) &&
				    sin_orig.sin_addr.s_addr ==
@@ -1163,7 +1161,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
		   comparing just the label */
		if (!ifa) {
			for (ifap = &in_dev->ifa_list;
			     (ifa = rtnl_dereference(*ifap)) != NULL;
			     (ifa = rtnl_net_dereference(net, *ifap)) != NULL;
			     ifap = &ifa->ifa_next)
				if (!strcmp(ifr->ifr_name, ifa->ifa_label))
					break;
@@ -1205,6 +1203,9 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
				inet_del_ifa(in_dev, ifap, 1);
			break;
		}

		/* NETDEV_UP/DOWN/CHANGE could touch a peer dev */
		ASSERT_RTNL();
		ret = dev_change_flags(dev, ifr->ifr_flags, NULL);
		break;

@@ -1306,7 +1307,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
		break;
	}
done:
	rtnl_unlock();
	rtnl_net_unlock(net);
out:
	return ret;
}