diff options
| author | Jakub Kicinski <kuba@kernel.org> | 2025-01-20 12:16:07 -0800 | 
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2025-01-20 12:16:08 -0800 | 
| commit | b115243ab8bd92387cf524ba3a7d81eda8eca885 (patch) | |
| tree | b6599fd0b7f078385bcaa1086ba61a0f7b36d647 | |
| parent | ba5f78505fb4e3feb73d8e5249a13b3244dac4d9 (diff) | |
| parent | 7bcf45ddb8bb3d386072677ce4d86d1ec9896096 (diff) | |
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: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | include/net/addrconf.h | 5 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 253 | 
2 files changed, 128 insertions, 130 deletions
| diff --git a/include/net/addrconf.h b/include/net/addrconf.h index f8f91b2038ea..9e5e95988b9e 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -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 diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c3729382be3b..ac8cc1076536 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -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, -			      ifm->ifa_prefixlen, extack); +	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);  } | 
