Commit 5b2a1953 authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller

IPv6: addrconf timer race

The Router Solicitation timer races with device state changes
because it doesn't lock the device. Use local variable to avoid
one repeated dereference.
Signed-off-by: default avatarStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 122e4519
...@@ -2739,28 +2739,29 @@ static int addrconf_ifdown(struct net_device *dev, int how) ...@@ -2739,28 +2739,29 @@ static int addrconf_ifdown(struct net_device *dev, int how)
static void addrconf_rs_timer(unsigned long data) static void addrconf_rs_timer(unsigned long data)
{ {
struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data;
struct inet6_dev *idev = ifp->idev;
if (ifp->idev->cnf.forwarding) read_lock(&idev->lock);
if (idev->dead || !(idev->if_flags & IF_READY))
goto out; goto out;
if (ifp->idev->if_flags & IF_RA_RCVD) { if (idev->cnf.forwarding)
/* goto out;
* Announcement received after solicitation
* was sent /* Announcement received after solicitation was sent */
*/ if (idev->if_flags & IF_RA_RCVD)
goto out; goto out;
}
spin_lock(&ifp->lock); spin_lock(&ifp->lock);
if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { if (ifp->probes++ < idev->cnf.rtr_solicits) {
/* The wait after the last probe can be shorter */ /* The wait after the last probe can be shorter */
addrconf_mod_timer(ifp, AC_RS, addrconf_mod_timer(ifp, AC_RS,
(ifp->probes == ifp->idev->cnf.rtr_solicits) ? (ifp->probes == idev->cnf.rtr_solicits) ?
ifp->idev->cnf.rtr_solicit_delay : idev->cnf.rtr_solicit_delay :
ifp->idev->cnf.rtr_solicit_interval); idev->cnf.rtr_solicit_interval);
spin_unlock(&ifp->lock); spin_unlock(&ifp->lock);
ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); ndisc_send_rs(idev->dev, &ifp->addr, &in6addr_linklocal_allrouters);
} else { } else {
spin_unlock(&ifp->lock); spin_unlock(&ifp->lock);
/* /*
...@@ -2768,10 +2769,11 @@ static void addrconf_rs_timer(unsigned long data) ...@@ -2768,10 +2769,11 @@ static void addrconf_rs_timer(unsigned long data)
* assumption any longer. * assumption any longer.
*/ */
printk(KERN_DEBUG "%s: no IPv6 routers present\n", printk(KERN_DEBUG "%s: no IPv6 routers present\n",
ifp->idev->dev->name); idev->dev->name);
} }
out: out:
read_unlock(&idev->lock);
in6_ifa_put(ifp); in6_ifa_put(ifp);
} }
......
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