Skip to content

Commit 00b5b7a

Browse files
liuhangbinPaolo Abeni
authored andcommitted
net/ipv6: delete temporary address if mngtmpaddr is removed or unmanaged
RFC8981 section 3.4 says that existing temporary addresses must have their lifetimes adjusted so that no temporary addresses should ever remain "valid" or "preferred" longer than the incoming SLAAC Prefix Information. This would strongly imply in Linux's case that if the "mngtmpaddr" address is deleted or un-flagged as such, its corresponding temporary addresses must be cleared out right away. But now the temporary address is renewed even after ‘mngtmpaddr’ is removed or becomes unmanaged as manage_tempaddrs() set temporary addresses prefered/valid time to 0, and later in addrconf_verify_rtnl() all checkings failed to remove the addresses. Fix this by deleting the temporary address directly for these situations. Fixes: 778964f ("ipv6/addrconf: fix timing bug in tempaddr regen") Signed-off-by: Hangbin Liu <[email protected]> Reviewed-by: David Ahern <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 59c5e14 commit 00b5b7a

File tree

1 file changed

+29
-12
lines changed

1 file changed

+29
-12
lines changed

net/ipv6/addrconf.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2570,6 +2570,24 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
25702570
return idev;
25712571
}
25722572

2573+
static void delete_tempaddrs(struct inet6_dev *idev,
2574+
struct inet6_ifaddr *ifp)
2575+
{
2576+
struct inet6_ifaddr *ift, *tmp;
2577+
2578+
write_lock_bh(&idev->lock);
2579+
list_for_each_entry_safe(ift, tmp, &idev->tempaddr_list, tmp_list) {
2580+
if (ift->ifpub != ifp)
2581+
continue;
2582+
2583+
in6_ifa_hold(ift);
2584+
write_unlock_bh(&idev->lock);
2585+
ipv6_del_addr(ift);
2586+
write_lock_bh(&idev->lock);
2587+
}
2588+
write_unlock_bh(&idev->lock);
2589+
}
2590+
25732591
static void manage_tempaddrs(struct inet6_dev *idev,
25742592
struct inet6_ifaddr *ifp,
25752593
__u32 valid_lft, __u32 prefered_lft,
@@ -3124,11 +3142,12 @@ static int inet6_addr_del(struct net *net, int ifindex, u32 ifa_flags,
31243142
in6_ifa_hold(ifp);
31253143
read_unlock_bh(&idev->lock);
31263144

3127-
if (!(ifp->flags & IFA_F_TEMPORARY) &&
3128-
(ifa_flags & IFA_F_MANAGETEMPADDR))
3129-
manage_tempaddrs(idev, ifp, 0, 0, false,
3130-
jiffies);
31313145
ipv6_del_addr(ifp);
3146+
3147+
if (!(ifp->flags & IFA_F_TEMPORARY) &&
3148+
(ifp->flags & IFA_F_MANAGETEMPADDR))
3149+
delete_tempaddrs(idev, ifp);
3150+
31323151
addrconf_verify_rtnl(net);
31333152
if (ipv6_addr_is_multicast(pfx)) {
31343153
ipv6_mc_config(net->ipv6.mc_autojoin_sk,
@@ -4952,14 +4971,12 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
49524971
}
49534972

49544973
if (was_managetempaddr || ifp->flags & IFA_F_MANAGETEMPADDR) {
4955-
if (was_managetempaddr &&
4956-
!(ifp->flags & IFA_F_MANAGETEMPADDR)) {
4957-
cfg->valid_lft = 0;
4958-
cfg->preferred_lft = 0;
4959-
}
4960-
manage_tempaddrs(ifp->idev, ifp, cfg->valid_lft,
4961-
cfg->preferred_lft, !was_managetempaddr,
4962-
jiffies);
4974+
if (was_managetempaddr && !(ifp->flags & IFA_F_MANAGETEMPADDR))
4975+
delete_tempaddrs(ifp->idev, ifp);
4976+
else
4977+
manage_tempaddrs(ifp->idev, ifp, cfg->valid_lft,
4978+
cfg->preferred_lft, !was_managetempaddr,
4979+
jiffies);
49634980
}
49644981

49654982
addrconf_verify_rtnl(net);

0 commit comments

Comments
 (0)