diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2005-12-27 21:35:15 (GMT) |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-12-27 21:35:15 (GMT) |
commit | 6732badee0dad467fcc9dd0168af8677b2b1bc2f (patch) | |
tree | 43fd9fbb5759de0e4a182d473621699b1ff453bc /net/ipv6 | |
parent | 79cac2a221ce18642550a13bed0f0203514923ea (diff) | |
download | linux-6732badee0dad467fcc9dd0168af8677b2b1bc2f.tar.xz |
[IPV6]: Fix addrconf dead lock.
We need to release idev->lcok before we call addrconf_dad_stop().
It calls ipv6_addr_del(), which will hold idev->lock.
Bug spotted by Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 2a6439e..a60585f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2467,11 +2467,9 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) return; } - if (idev->if_flags & IF_READY) { - addrconf_dad_kick(ifp); - spin_unlock_bh(&ifp->lock); - } else { + if (!(idev->if_flags & IF_READY)) { spin_unlock_bh(&ifp->lock); + read_unlock_bh(&idev->lock); /* * If the defice is not ready: * - keep it tentative if it is a permanent address. @@ -2479,7 +2477,10 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) */ in6_ifa_hold(ifp); addrconf_dad_stop(ifp); + return; } + addrconf_dad_kick(ifp); + spin_unlock_bh(&ifp->lock); out: read_unlock_bh(&idev->lock); } |