summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-06-27 11:05:53 +0000
committerrwatson <rwatson@FreeBSD.org>2009-06-27 11:05:53 +0000
commit3b6551a921beb7f1408f05c3730aa5802bd6e79c (patch)
treef507e266469cd795237647e79f7ed84eb2c6afb7 /sys/netinet6
parent5cfc09d074a45a6010e2cbbb541bd752a348d917 (diff)
downloadFreeBSD-src-3b6551a921beb7f1408f05c3730aa5802bd6e79c.zip
FreeBSD-src-3b6551a921beb7f1408f05c3730aa5802bd6e79c.tar.gz
In in6_update_ifa(), jump to 'cleanup' rather than returning directly
in one additional case, avoiding an ifaddr reference leak. Defer releasing the in6_ifaddr's in6_ifaddrhead reference until the end of in6_unlink_ifa(), as callers are inconsistent regarding whether or not they hold a reference across the call. This avoids using the ifaddr after it may have been freed. Reported by: tegge Reviewed by: tegge Approved by: re (blanket) MFC after: 6 weeks
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/in6.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index f415877..645e107 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -970,8 +970,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
"%s on %s (errno=%d)\n",
ip6_sprintf(ip6buf, &llsol), if_name(ifp),
error));
- in6_purgeaddr((struct ifaddr *)ia);
- return (error);
+ goto cleanup;
}
LIST_INSERT_HEAD(&ia->ia6_memberships,
imm, i6mm_chain);
@@ -1378,10 +1377,14 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
IF_ADDR_UNLOCK(ifp);
ifa_free(&ia->ia_ifa); /* if_addrhead */
+ /*
+ * Defer the release of what might be the last reference to the
+ * in6_ifaddr so that it can't be freed before the remainder of the
+ * cleanup.
+ */
IN6_IFADDR_WLOCK();
TAILQ_REMOVE(&V_in6_ifaddrhead, ia, ia_link);
IN6_IFADDR_WUNLOCK();
- ifa_free(&ia->ia_ifa); /* in6_ifaddrhead */
/*
* Release the reference to the base prefix. There should be a
@@ -1404,7 +1407,7 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
if ((ia->ia6_flags & IN6_IFF_AUTOCONF)) {
pfxlist_onlink_check();
}
-
+ ifa_free(&ia->ia_ifa); /* in6_ifaddrhead */
splx(s);
}
OpenPOWER on IntegriCloud