Commit fed20f2d authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

[IPV6] Fix a race when dad completed during shutting down its owner interface.

Bug was noticed by Herbert Xu <herbert@gondor.apana.org.au>.
Signed-off-by: default avatarHideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
parent c8033a72
...@@ -137,6 +137,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags); ...@@ -137,6 +137,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
static void addrconf_dad_timer(unsigned long data); static void addrconf_dad_timer(unsigned long data);
static void addrconf_dad_completed(struct inet6_ifaddr *ifp); static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
static void addrconf_rs_timer(unsigned long data); static void addrconf_rs_timer(unsigned long data);
static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
static void inet6_prefix_notify(int event, struct inet6_dev *idev, static void inet6_prefix_notify(int event, struct inet6_dev *idev,
...@@ -2049,7 +2050,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) ...@@ -2049,7 +2050,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
addrconf_del_timer(ifa); addrconf_del_timer(ifa);
write_unlock_bh(&idev->lock); write_unlock_bh(&idev->lock);
ipv6_ifa_notify(RTM_DELADDR, ifa); __ipv6_ifa_notify(RTM_DELADDR, ifa);
in6_ifa_put(ifa); in6_ifa_put(ifa);
write_lock_bh(&idev->lock); write_lock_bh(&idev->lock);
...@@ -2980,7 +2981,7 @@ static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = { ...@@ -2980,7 +2981,7 @@ static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {
.dumpit = inet6_dump_fib, }, .dumpit = inet6_dump_fib, },
}; };
static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
{ {
inet6_ifa_notify(event ? : RTM_NEWADDR, ifp); inet6_ifa_notify(event ? : RTM_NEWADDR, ifp);
...@@ -3005,6 +3006,16 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) ...@@ -3005,6 +3006,16 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
} }
} }
static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
{
read_lock_bh(&addrconf_lock);
if (ifp->idev->dead)
goto out;
__ipv6_ifa_notify(event, ifp);
out:
read_unlock_bh(&addrconf_lock);
}
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
static static
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment