Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 27 Jun 2009 11:05:53 +0000 (UTC)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r195102 - head/sys/netinet6
Message-ID:  <200906271105.n5RB5rv5076207@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rwatson
Date: Sat Jun 27 11:05:53 2009
New Revision: 195102
URL: http://svn.freebsd.org/changeset/base/195102

Log:
  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

Modified:
  head/sys/netinet6/in6.c

Modified: head/sys/netinet6/in6.c
==============================================================================
--- head/sys/netinet6/in6.c	Sat Jun 27 10:45:58 2009	(r195101)
+++ head/sys/netinet6/in6.c	Sat Jun 27 11:05:53 2009	(r195102)
@@ -970,8 +970,7 @@ in6_update_ifa(struct ifnet *ifp, struct
 			    "%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, st
 	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, st
 	if ((ia->ia6_flags & IN6_IFF_AUTOCONF)) {
 		pfxlist_onlink_check();
 	}
-
+	ifa_free(&ia->ia_ifa);			/* in6_ifaddrhead */
 	splx(s);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906271105.n5RB5rv5076207>