Skip to content

Commit 5b2a195

Browse files
stephen hemmingerdavem330
authored andcommitted
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: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 122e451 commit 5b2a195

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

net/ipv6/addrconf.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2739,39 +2739,41 @@ static int addrconf_ifdown(struct net_device *dev, int how)
27392739
static void addrconf_rs_timer(unsigned long data)
27402740
{
27412741
struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data;
2742+
struct inet6_dev *idev = ifp->idev;
27422743

2743-
if (ifp->idev->cnf.forwarding)
2744+
read_lock(&idev->lock);
2745+
if (idev->dead || !(idev->if_flags & IF_READY))
27442746
goto out;
27452747

2746-
if (ifp->idev->if_flags & IF_RA_RCVD) {
2747-
/*
2748-
* Announcement received after solicitation
2749-
* was sent
2750-
*/
2748+
if (idev->cnf.forwarding)
2749+
goto out;
2750+
2751+
/* Announcement received after solicitation was sent */
2752+
if (idev->if_flags & IF_RA_RCVD)
27512753
goto out;
2752-
}
27532754

27542755
spin_lock(&ifp->lock);
2755-
if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) {
2756+
if (ifp->probes++ < idev->cnf.rtr_solicits) {
27562757
/* The wait after the last probe can be shorter */
27572758
addrconf_mod_timer(ifp, AC_RS,
2758-
(ifp->probes == ifp->idev->cnf.rtr_solicits) ?
2759-
ifp->idev->cnf.rtr_solicit_delay :
2760-
ifp->idev->cnf.rtr_solicit_interval);
2759+
(ifp->probes == idev->cnf.rtr_solicits) ?
2760+
idev->cnf.rtr_solicit_delay :
2761+
idev->cnf.rtr_solicit_interval);
27612762
spin_unlock(&ifp->lock);
27622763

2763-
ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters);
2764+
ndisc_send_rs(idev->dev, &ifp->addr, &in6addr_linklocal_allrouters);
27642765
} else {
27652766
spin_unlock(&ifp->lock);
27662767
/*
27672768
* Note: we do not support deprecated "all on-link"
27682769
* assumption any longer.
27692770
*/
27702771
printk(KERN_DEBUG "%s: no IPv6 routers present\n",
2771-
ifp->idev->dev->name);
2772+
idev->dev->name);
27722773
}
27732774

27742775
out:
2776+
read_unlock(&idev->lock);
27752777
in6_ifa_put(ifp);
27762778
}
27772779

0 commit comments

Comments
 (0)