diff options
author | Keir Fraser <keir.fraser@cl.cam.ac.uk> | 2006-08-29 05:43:49 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-08-30 00:22:18 -0400 |
commit | 57f5f544f58ffa1d6c38630d0522c9c0be67c533 (patch) | |
tree | c47651ea2300b28e11d6898f67f73eab41a9423b /net/ipv6/addrconf.c | |
parent | fab2caf62ed03d83bd3a3598b859c3c345a8e8b5 (diff) |
[IPV6]: ipv6_add_addr should install dstentry earlier
ipv6_add_addr allocates a struct inet6_ifaddr and a dstentry, but it
doesn't install the dstentry in ifa->rt until after it releases the
addrconf_hash_lock. This means other CPUs will be able to see the new
address while it hasn't been initialized completely yet.
One possible fix would be to grab the ifp->lock spinlock when
creating the address struct; a simpler fix is to just move the
assignment.
Acked-by: jbeulich@novell.com
Acked-by: okir@suse.de
Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 0c5042e7380d..c7852b38e03e 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -578,6 +578,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
578 | ifa->flags = flags | IFA_F_TENTATIVE; | 578 | ifa->flags = flags | IFA_F_TENTATIVE; |
579 | ifa->cstamp = ifa->tstamp = jiffies; | 579 | ifa->cstamp = ifa->tstamp = jiffies; |
580 | 580 | ||
581 | ifa->rt = rt; | ||
582 | |||
581 | ifa->idev = idev; | 583 | ifa->idev = idev; |
582 | in6_dev_hold(idev); | 584 | in6_dev_hold(idev); |
583 | /* For caller */ | 585 | /* For caller */ |
@@ -603,8 +605,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
603 | } | 605 | } |
604 | #endif | 606 | #endif |
605 | 607 | ||
606 | ifa->rt = rt; | ||
607 | |||
608 | in6_ifa_hold(ifa); | 608 | in6_ifa_hold(ifa); |
609 | write_unlock(&idev->lock); | 609 | write_unlock(&idev->lock); |
610 | out2: | 610 | out2: |