Commit b115243a authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'ipv6-convert-rtm_-new-del-addr-and-more-to-per-netns-rtnl'

Kuniyuki Iwashima says:

====================
ipv6: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL.

This series converts RTM_NEWADDR/RTM_DELADDR and some more
RTNL users in addrconf.c to per-netns RTNL.

v1: https://lore.kernel.org/20250114080516.46155-1-kuniyu@amazon.com
====================

Link: https://patch.msgid.link/20250115080608.28127-1-kuniyu@amazon.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents ba5f7850 7bcf45dd
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -347,6 +347,11 @@ static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)
	return rcu_dereference_rtnl(dev->ip6_ptr);
}

static inline struct inet6_dev *__in6_dev_get_rtnl_net(const struct net_device *dev)
{
	return rtnl_net_dereference(dev_net(dev), dev->ip6_ptr);
}

/**
 * __in6_dev_stats_get - get inet6_dev pointer for stats
 * @dev: network device
+123 −130
Original line number Diff line number Diff line
@@ -852,7 +852,7 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
	struct inet6_dev *idev;

	for_each_netdev(net, dev) {
		idev = __in6_dev_get(dev);
		idev = __in6_dev_get_rtnl_net(dev);
		if (idev) {
			int changed = (!idev->cnf.forwarding) ^ (!newf);

@@ -865,13 +865,12 @@ static void addrconf_forward_change(struct net *net, __s32 newf)

static int addrconf_fixup_forwarding(const struct ctl_table *table, int *p, int newf)
{
	struct net *net;
	struct net *net = (struct net *)table->extra2;
	int old;

	if (!rtnl_trylock())
	if (!rtnl_net_trylock(net))
		return restart_syscall();

	net = (struct net *)table->extra2;
	old = *p;
	WRITE_ONCE(*p, newf);

@@ -881,7 +880,7 @@ static int addrconf_fixup_forwarding(const struct ctl_table *table, int *p, int
						     NETCONFA_FORWARDING,
						     NETCONFA_IFINDEX_DEFAULT,
						     net->ipv6.devconf_dflt);
		rtnl_unlock();
		rtnl_net_unlock(net);
		return 0;
	}

@@ -903,7 +902,7 @@ static int addrconf_fixup_forwarding(const struct ctl_table *table, int *p, int
						     net->ipv6.devconf_all);
	} else if ((!newf) ^ (!old))
		dev_forward_change((struct inet6_dev *)table->extra1);
	rtnl_unlock();
	rtnl_net_unlock(net);

	if (newf)
		rt6_purge_dflt_routers(net);
@@ -916,7 +915,7 @@ static void addrconf_linkdown_change(struct net *net, __s32 newf)
	struct inet6_dev *idev;

	for_each_netdev(net, dev) {
		idev = __in6_dev_get(dev);
		idev = __in6_dev_get_rtnl_net(dev);
		if (idev) {
			int changed = (!idev->cnf.ignore_routes_with_linkdown) ^ (!newf);

@@ -933,13 +932,12 @@ static void addrconf_linkdown_change(struct net *net, __s32 newf)

static int addrconf_fixup_linkdown(const struct ctl_table *table, int *p, int newf)
{
	struct net *net;
	struct net *net = (struct net *)table->extra2;
	int old;

	if (!rtnl_trylock())
	if (!rtnl_net_trylock(net))
		return restart_syscall();

	net = (struct net *)table->extra2;
	old = *p;
	WRITE_ONCE(*p, newf);

@@ -950,7 +948,7 @@ static int addrconf_fixup_linkdown(const struct ctl_table *table, int *p, int ne
						     NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
						     NETCONFA_IFINDEX_DEFAULT,
						     net->ipv6.devconf_dflt);
		rtnl_unlock();
		rtnl_net_unlock(net);
		return 0;
	}

@@ -964,7 +962,8 @@ static int addrconf_fixup_linkdown(const struct ctl_table *table, int *p, int ne
						     NETCONFA_IFINDEX_ALL,
						     net->ipv6.devconf_all);
	}
	rtnl_unlock();

	rtnl_net_unlock(net);

	return 1;
}
@@ -2980,11 +2979,11 @@ int addrconf_set_dstaddr(struct net *net, void __user *arg)
	if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
		return -EFAULT;

	rtnl_lock();
	rtnl_net_lock(net);
	dev = __dev_get_by_index(net, ireq.ifr6_ifindex);
	if (dev && dev->type == ARPHRD_SIT)
		err = addrconf_set_sit_dstaddr(net, dev, &ireq);
	rtnl_unlock();
	rtnl_net_unlock(net);
	return err;
}

@@ -3008,39 +3007,25 @@ static int ipv6_mc_config(struct sock *sk, bool join,
/*
 *	Manual configuration of address on an interface
 */
static int inet6_addr_add(struct net *net, int ifindex,
			  struct ifa6_config *cfg,
static int inet6_addr_add(struct net *net, struct net_device *dev,
			  struct ifa6_config *cfg, clock_t expires, u32 flags,
			  struct netlink_ext_ack *extack)
{
	struct inet6_ifaddr *ifp;
	struct inet6_dev *idev;
	struct net_device *dev;
	unsigned long timeout;
	clock_t expires;
	u32 flags;

	ASSERT_RTNL();
	ASSERT_RTNL_NET(net);

	if (cfg->plen > 128) {
		NL_SET_ERR_MSG_MOD(extack, "Invalid prefix length");
		return -EINVAL;
	}

	/* check the lifetime */
	if (!cfg->valid_lft || cfg->preferred_lft > cfg->valid_lft) {
		NL_SET_ERR_MSG_MOD(extack, "address lifetime invalid");
		return -EINVAL;
	}

	if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR && cfg->plen != 64) {
		NL_SET_ERR_MSG_MOD(extack, "address with \"mngtmpaddr\" flag must have a prefix length of 64");
		return -EINVAL;
	}

	dev = __dev_get_by_index(net, ifindex);
	if (!dev)
		return -ENODEV;

	idev = addrconf_add_dev(dev);
	if (IS_ERR(idev)) {
		NL_SET_ERR_MSG_MOD(extack, "IPv6 is disabled on this device");
@@ -3049,7 +3034,7 @@ static int inet6_addr_add(struct net *net, int ifindex,

	if (cfg->ifa_flags & IFA_F_MCAUTOJOIN) {
		int ret = ipv6_mc_config(net->ipv6.mc_autojoin_sk,
					 true, cfg->pfx, ifindex);
					 true, cfg->pfx, dev->ifindex);

		if (ret < 0) {
			NL_SET_ERR_MSG_MOD(extack, "Multicast auto join failed");
@@ -3059,24 +3044,6 @@ static int inet6_addr_add(struct net *net, int ifindex,

	cfg->scope = ipv6_addr_scope(cfg->pfx);

	timeout = addrconf_timeout_fixup(cfg->valid_lft, HZ);
	if (addrconf_finite_timeout(timeout)) {
		expires = jiffies_to_clock_t(timeout * HZ);
		cfg->valid_lft = timeout;
		flags = RTF_EXPIRES;
	} else {
		expires = 0;
		flags = 0;
		cfg->ifa_flags |= IFA_F_PERMANENT;
	}

	timeout = addrconf_timeout_fixup(cfg->preferred_lft, HZ);
	if (addrconf_finite_timeout(timeout)) {
		if (timeout == 0)
			cfg->ifa_flags |= IFA_F_DEPRECATED;
		cfg->preferred_lft = timeout;
	}

	ifp = ipv6_add_addr(idev, cfg, true, extack);
	if (!IS_ERR(ifp)) {
		if (!(cfg->ifa_flags & IFA_F_NOPREFIXROUTE)) {
@@ -3104,7 +3071,7 @@ static int inet6_addr_add(struct net *net, int ifindex,
		return 0;
	} else if (cfg->ifa_flags & IFA_F_MCAUTOJOIN) {
		ipv6_mc_config(net->ipv6.mc_autojoin_sk, false,
			       cfg->pfx, ifindex);
			       cfg->pfx, dev->ifindex);
	}

	return PTR_ERR(ifp);
@@ -3129,7 +3096,7 @@ static int inet6_addr_del(struct net *net, int ifindex, u32 ifa_flags,
		return -ENODEV;
	}

	idev = __in6_dev_get(dev);
	idev = __in6_dev_get_rtnl_net(dev);
	if (!idev) {
		NL_SET_ERR_MSG_MOD(extack, "IPv6 is disabled on this device");
		return -ENXIO;
@@ -3170,6 +3137,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
		.preferred_lft = INFINITY_LIFE_TIME,
		.valid_lft = INFINITY_LIFE_TIME,
	};
	struct net_device *dev;
	struct in6_ifreq ireq;
	int err;

@@ -3182,9 +3150,13 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
	cfg.pfx = &ireq.ifr6_addr;
	cfg.plen = ireq.ifr6_prefixlen;

	rtnl_lock();
	err = inet6_addr_add(net, ireq.ifr6_ifindex, &cfg, NULL);
	rtnl_unlock();
	rtnl_net_lock(net);
	dev = __dev_get_by_index(net, ireq.ifr6_ifindex);
	if (dev)
		err = inet6_addr_add(net, dev, &cfg, 0, 0, NULL);
	else
		err = -ENODEV;
	rtnl_net_unlock(net);
	return err;
}

@@ -3199,10 +3171,10 @@ int addrconf_del_ifaddr(struct net *net, void __user *arg)
	if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
		return -EFAULT;

	rtnl_lock();
	rtnl_net_lock(net);
	err = inet6_addr_del(net, ireq.ifr6_ifindex, 0, &ireq.ifr6_addr,
			     ireq.ifr6_prefixlen, NULL);
	rtnl_unlock();
	rtnl_net_unlock(net);
	return err;
}

@@ -4205,6 +4177,7 @@ static void addrconf_dad_work(struct work_struct *w)
	struct inet6_dev *idev = ifp->idev;
	bool bump_id, disable_ipv6 = false;
	struct in6_addr mcaddr;
	struct net *net;

	enum {
		DAD_PROCESS,
@@ -4212,7 +4185,9 @@ static void addrconf_dad_work(struct work_struct *w)
		DAD_ABORT,
	} action = DAD_PROCESS;

	rtnl_lock();
	net = dev_net(idev->dev);

	rtnl_net_lock(net);

	spin_lock_bh(&ifp->lock);
	if (ifp->state == INET6_IFADDR_STATE_PREDAD) {
@@ -4222,7 +4197,7 @@ static void addrconf_dad_work(struct work_struct *w)
		action = DAD_ABORT;
		ifp->state = INET6_IFADDR_STATE_POSTDAD;

		if ((READ_ONCE(dev_net(idev->dev)->ipv6.devconf_all->accept_dad) > 1 ||
		if ((READ_ONCE(net->ipv6.devconf_all->accept_dad) > 1 ||
		     READ_ONCE(idev->cnf.accept_dad) > 1) &&
		    !idev->cnf.disable_ipv6 &&
		    !(ifp->flags & IFA_F_STABLE_PRIVACY)) {
@@ -4304,7 +4279,7 @@ static void addrconf_dad_work(struct work_struct *w)
		      ifp->dad_nonce);
out:
	in6_ifa_put(ifp);
	rtnl_unlock();
	rtnl_net_unlock(net);
}

/* ifp->idev must be at least read locked */
@@ -4752,9 +4727,9 @@ static void addrconf_verify_work(struct work_struct *w)
	struct net *net = container_of(to_delayed_work(w), struct net,
				       ipv6.addr_chk_work);

	rtnl_lock();
	rtnl_net_lock(net);
	addrconf_verify_rtnl(net);
	rtnl_unlock();
	rtnl_net_unlock(net);
}

static void addrconf_verify(struct net *net)
@@ -4817,8 +4792,12 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
	/* We ignore other flags so far. */
	ifa_flags &= IFA_F_MANAGETEMPADDR;

	return inet6_addr_del(net, ifm->ifa_index, ifa_flags, pfx,
	rtnl_net_lock(net);
	err = inet6_addr_del(net, ifm->ifa_index, ifa_flags, pfx,
			     ifm->ifa_prefixlen, extack);
	rtnl_net_unlock(net);

	return err;
}

static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp,
@@ -4867,19 +4846,14 @@ static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp,
}

static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
			     struct ifa6_config *cfg)
			     struct ifa6_config *cfg, clock_t expires,
			     u32 flags)
{
	u32 flags;
	clock_t expires;
	unsigned long timeout;
	bool was_managetempaddr;
	bool had_prefixroute;
	bool new_peer = false;
	bool had_prefixroute;

	ASSERT_RTNL();

	if (!cfg->valid_lft || cfg->preferred_lft > cfg->valid_lft)
		return -EINVAL;
	ASSERT_RTNL_NET(net);

	if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR &&
	    (ifp->flags & IFA_F_TEMPORARY || ifp->prefix_len != 64))
@@ -4888,24 +4862,6 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
	if (!(ifp->flags & IFA_F_TENTATIVE) || ifp->flags & IFA_F_DADFAILED)
		cfg->ifa_flags &= ~IFA_F_OPTIMISTIC;

	timeout = addrconf_timeout_fixup(cfg->valid_lft, HZ);
	if (addrconf_finite_timeout(timeout)) {
		expires = jiffies_to_clock_t(timeout * HZ);
		cfg->valid_lft = timeout;
		flags = RTF_EXPIRES;
	} else {
		expires = 0;
		flags = 0;
		cfg->ifa_flags |= IFA_F_PERMANENT;
	}

	timeout = addrconf_timeout_fixup(cfg->preferred_lft, HZ);
	if (addrconf_finite_timeout(timeout)) {
		if (timeout == 0)
			cfg->ifa_flags |= IFA_F_DEPRECATED;
		cfg->preferred_lft = timeout;
	}

	if (cfg->peer_pfx &&
	    memcmp(&ifp->peer_addr, cfg->peer_pfx, sizeof(struct in6_addr))) {
		if (!ipv6_addr_any(&ifp->peer_addr))
@@ -4990,13 +4946,16 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
		  struct netlink_ext_ack *extack)
{
	struct net *net = sock_net(skb->sk);
	struct ifaddrmsg *ifm;
	struct nlattr *tb[IFA_MAX+1];
	struct in6_addr *peer_pfx;
	struct inet6_ifaddr *ifa;
	struct net_device *dev;
	struct inet6_dev *idev;
	struct ifa6_config cfg;
	struct ifaddrmsg *ifm;
	unsigned long timeout;
	clock_t expires;
	u32 flags;
	int err;

	err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
@@ -5019,8 +4978,18 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
	if (tb[IFA_PROTO])
		cfg.ifa_proto = nla_get_u8(tb[IFA_PROTO]);

	cfg.ifa_flags = nla_get_u32_default(tb[IFA_FLAGS], ifm->ifa_flags);

	/* We ignore other flags so far. */
	cfg.ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS |
			 IFA_F_MANAGETEMPADDR | IFA_F_NOPREFIXROUTE |
			 IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC;

	cfg.ifa_flags |= IFA_F_PERMANENT;
	cfg.valid_lft = INFINITY_LIFE_TIME;
	cfg.preferred_lft = INFINITY_LIFE_TIME;
	expires = 0;
	flags = 0;

	if (tb[IFA_CACHEINFO]) {
		struct ifa_cacheinfo *ci;
@@ -5028,24 +4997,43 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
		ci = nla_data(tb[IFA_CACHEINFO]);
		cfg.valid_lft = ci->ifa_valid;
		cfg.preferred_lft = ci->ifa_prefered;

		if (!cfg.valid_lft || cfg.preferred_lft > cfg.valid_lft) {
			NL_SET_ERR_MSG_MOD(extack, "address lifetime invalid");
			return -EINVAL;
		}

		timeout = addrconf_timeout_fixup(cfg.valid_lft, HZ);
		if (addrconf_finite_timeout(timeout)) {
			cfg.ifa_flags &= ~IFA_F_PERMANENT;
			cfg.valid_lft = timeout;
			expires = jiffies_to_clock_t(timeout * HZ);
			flags = RTF_EXPIRES;
		}

		timeout = addrconf_timeout_fixup(cfg.preferred_lft, HZ);
		if (addrconf_finite_timeout(timeout)) {
			if (timeout == 0)
				cfg.ifa_flags |= IFA_F_DEPRECATED;

			cfg.preferred_lft = timeout;
		}
	}

	rtnl_net_lock(net);

	dev =  __dev_get_by_index(net, ifm->ifa_index);
	if (!dev) {
		NL_SET_ERR_MSG_MOD(extack, "Unable to find the interface");
		return -ENODEV;
		err = -ENODEV;
		goto unlock;
	}

	cfg.ifa_flags = nla_get_u32_default(tb[IFA_FLAGS], ifm->ifa_flags);

	/* We ignore other flags so far. */
	cfg.ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS |
			 IFA_F_MANAGETEMPADDR | IFA_F_NOPREFIXROUTE |
			 IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC;

	idev = ipv6_find_idev(dev);
	if (IS_ERR(idev))
		return PTR_ERR(idev);
	if (IS_ERR(idev)) {
		err = PTR_ERR(idev);
		goto unlock;
	}

	if (!ipv6_allow_optimistic_dad(net, idev))
		cfg.ifa_flags &= ~IFA_F_OPTIMISTIC;
@@ -5053,7 +5041,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
	if (cfg.ifa_flags & IFA_F_NODAD &&
	    cfg.ifa_flags & IFA_F_OPTIMISTIC) {
		NL_SET_ERR_MSG(extack, "IFA_F_NODAD and IFA_F_OPTIMISTIC are mutually exclusive");
		return -EINVAL;
		err = -EINVAL;
		goto unlock;
	}

	ifa = ipv6_get_ifaddr(net, cfg.pfx, dev, 1);
@@ -5062,7 +5051,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
		 * It would be best to check for !NLM_F_CREATE here but
		 * userspace already relies on not having to provide this.
		 */
		return inet6_addr_add(net, ifm->ifa_index, &cfg, extack);
		err = inet6_addr_add(net, dev, &cfg, expires, flags, extack);
		goto unlock;
	}

	if (nlh->nlmsg_flags & NLM_F_EXCL ||
@@ -5070,10 +5060,12 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
		NL_SET_ERR_MSG_MOD(extack, "address already assigned");
		err = -EEXIST;
	} else {
		err = inet6_addr_modify(net, ifa, &cfg);
		err = inet6_addr_modify(net, ifa, &cfg, expires, flags);
	}

	in6_ifa_put(ifa);
unlock:
	rtnl_net_unlock(net);

	return err;
}
@@ -6370,7 +6362,7 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
	struct inet6_dev *idev;

	for_each_netdev(net, dev) {
		idev = __in6_dev_get(dev);
		idev = __in6_dev_get_rtnl_net(dev);
		if (idev) {
			int changed = (!idev->cnf.disable_ipv6) ^ (!newf);

@@ -6391,7 +6383,7 @@ static int addrconf_disable_ipv6(const struct ctl_table *table, int *p, int newf
		return 0;
	}

	if (!rtnl_trylock())
	if (!rtnl_net_trylock(net))
		return restart_syscall();

	old = *p;
@@ -6400,10 +6392,11 @@ static int addrconf_disable_ipv6(const struct ctl_table *table, int *p, int newf
	if (p == &net->ipv6.devconf_all->disable_ipv6) {
		WRITE_ONCE(net->ipv6.devconf_dflt->disable_ipv6, newf);
		addrconf_disable_change(net, newf);
	} else if ((!newf) ^ (!old))
	} else if ((!newf) ^ (!old)) {
		dev_disable_change((struct inet6_dev *)table->extra1);
	}

	rtnl_unlock();
	rtnl_net_unlock(net);
	return 0;
}

@@ -6446,20 +6439,20 @@ static int addrconf_sysctl_proxy_ndp(const struct ctl_table *ctl, int write,
	if (write && old != new) {
		struct net *net = ctl->extra2;

		if (!rtnl_trylock())
		if (!rtnl_net_trylock(net))
			return restart_syscall();

		if (valp == &net->ipv6.devconf_dflt->proxy_ndp)
		if (valp == &net->ipv6.devconf_dflt->proxy_ndp) {
			inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
						     NETCONFA_PROXY_NEIGH,
						     NETCONFA_IFINDEX_DEFAULT,
						     net->ipv6.devconf_dflt);
		else if (valp == &net->ipv6.devconf_all->proxy_ndp)
		} else if (valp == &net->ipv6.devconf_all->proxy_ndp) {
			inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
						     NETCONFA_PROXY_NEIGH,
						     NETCONFA_IFINDEX_ALL,
						     net->ipv6.devconf_all);
		else {
		} else {
			struct inet6_dev *idev = ctl->extra1;

			inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
@@ -6467,7 +6460,7 @@ static int addrconf_sysctl_proxy_ndp(const struct ctl_table *ctl, int write,
						     idev->dev->ifindex,
						     &idev->cnf);
		}
		rtnl_unlock();
		rtnl_net_unlock(net);
	}

	return ret;
@@ -6487,7 +6480,7 @@ static int addrconf_sysctl_addr_gen_mode(const struct ctl_table *ctl, int write,
		.mode = ctl->mode,
	};

	if (!rtnl_trylock())
	if (!rtnl_net_trylock(net))
		return restart_syscall();

	new_val = *((u32 *)ctl->data);
@@ -6517,7 +6510,7 @@ static int addrconf_sysctl_addr_gen_mode(const struct ctl_table *ctl, int write,

			WRITE_ONCE(net->ipv6.devconf_dflt->addr_gen_mode, new_val);
			for_each_netdev(net, dev) {
				idev = __in6_dev_get(dev);
				idev = __in6_dev_get_rtnl_net(dev);
				if (idev &&
				    idev->cnf.addr_gen_mode != new_val) {
					WRITE_ONCE(idev->cnf.addr_gen_mode,
@@ -6531,7 +6524,7 @@ static int addrconf_sysctl_addr_gen_mode(const struct ctl_table *ctl, int write,
	}

out:
	rtnl_unlock();
	rtnl_net_unlock(net);

	return ret;
}
@@ -6553,7 +6546,7 @@ static int addrconf_sysctl_stable_secret(const struct ctl_table *ctl, int write,
	lctl.maxlen = IPV6_MAX_STRLEN;
	lctl.data = str;

	if (!rtnl_trylock())
	if (!rtnl_net_trylock(net))
		return restart_syscall();

	if (!write && !secret->initialized) {
@@ -6583,7 +6576,7 @@ static int addrconf_sysctl_stable_secret(const struct ctl_table *ctl, int write,
		struct net_device *dev;

		for_each_netdev(net, dev) {
			struct inet6_dev *idev = __in6_dev_get(dev);
			struct inet6_dev *idev = __in6_dev_get_rtnl_net(dev);

			if (idev) {
				WRITE_ONCE(idev->cnf.addr_gen_mode,
@@ -6598,7 +6591,7 @@ static int addrconf_sysctl_stable_secret(const struct ctl_table *ctl, int write,
	}

out:
	rtnl_unlock();
	rtnl_net_unlock(net);

	return err;
}
@@ -6682,7 +6675,7 @@ int addrconf_disable_policy(const struct ctl_table *ctl, int *valp, int val)
		return 0;
	}

	if (!rtnl_trylock())
	if (!rtnl_net_trylock(net))
		return restart_syscall();

	WRITE_ONCE(*valp, val);
@@ -6691,7 +6684,7 @@ int addrconf_disable_policy(const struct ctl_table *ctl, int *valp, int val)
		struct net_device *dev;

		for_each_netdev(net, dev) {
			idev = __in6_dev_get(dev);
			idev = __in6_dev_get_rtnl_net(dev);
			if (idev)
				addrconf_disable_policy_idev(idev, val);
		}
@@ -6700,7 +6693,7 @@ int addrconf_disable_policy(const struct ctl_table *ctl, int *valp, int val)
		addrconf_disable_policy_idev(idev, val);
	}

	rtnl_unlock();
	rtnl_net_unlock(net);
	return 0;
}

@@ -7413,9 +7406,9 @@ static const struct rtnl_msg_handler addrconf_rtnl_msg_handlers[] __initconst_or
	{.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_GETLINK,
	 .dumpit = inet6_dump_ifinfo, .flags = RTNL_FLAG_DUMP_UNLOCKED},
	{.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_NEWADDR,
	 .doit = inet6_rtm_newaddr},
	 .doit = inet6_rtm_newaddr, .flags = RTNL_FLAG_DOIT_PERNET},
	{.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_DELADDR,
	 .doit = inet6_rtm_deladdr},
	 .doit = inet6_rtm_deladdr, .flags = RTNL_FLAG_DOIT_PERNET},
	{.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_GETADDR,
	 .doit = inet6_rtm_getaddr, .dumpit = inet6_dump_ifaddr,
	 .flags = RTNL_FLAG_DOIT_UNLOCKED | RTNL_FLAG_DUMP_UNLOCKED},
@@ -7457,9 +7450,9 @@ int __init addrconf_init(void)
		goto out_nowq;
	}

	rtnl_lock();
	rtnl_net_lock(&init_net);
	idev = ipv6_add_dev(blackhole_netdev);
	rtnl_unlock();
	rtnl_net_unlock(&init_net);
	if (IS_ERR(idev)) {
		err = PTR_ERR(idev);
		goto errlo;
@@ -7509,17 +7502,17 @@ void addrconf_cleanup(void)

	rtnl_af_unregister(&inet6_ops);

	rtnl_lock();
	rtnl_net_lock(&init_net);

	/* clean dev list */
	for_each_netdev(&init_net, dev) {
		if (__in6_dev_get(dev) == NULL)
		if (!__in6_dev_get_rtnl_net(dev))
			continue;
		addrconf_ifdown(dev, true);
	}
	addrconf_ifdown(init_net.loopback_dev, true);

	rtnl_unlock();
	rtnl_net_unlock(&init_net);

	destroy_workqueue(addrconf_wq);
}