Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 Oct 2009 17:55:42 +0000 (UTC)
From:      Qing Li <qingli@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r198301 - head/sys/netinet
Message-ID:  <200910201755.n9KHtgT9073966@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: qingli
Date: Tue Oct 20 17:55:42 2009
New Revision: 198301
URL: http://svn.freebsd.org/changeset/base/198301

Log:
  In the ARP callout timer expiration function, the current time_second
  is compared against the entry expiration time value (that was set based
  on time_second) to check if the current time is larger than the set
  expiration time. Due to the +/- timer granularity value, the comparison
  returns false, causing the alternative code to be executed. The
  alternative code path freed the memory without removing that entry
  from the table list, causing a use-after-free bug.
  
  Reviewed by:	discussed with kmacy
  MFC after:	immediately
  Verified by:	rnoland, yongari

Modified:
  head/sys/netinet/if_ether.c

Modified: head/sys/netinet/if_ether.c
==============================================================================
--- head/sys/netinet/if_ether.c	Tue Oct 20 17:50:36 2009	(r198300)
+++ head/sys/netinet/if_ether.c	Tue Oct 20 17:55:42 2009	(r198301)
@@ -175,18 +175,18 @@ arptimer(void *arg)
 	CURVNET_SET(ifp->if_vnet);
 	IF_AFDATA_LOCK(ifp);
 	LLE_WLOCK(lle);
-	if (((lle->la_flags & LLE_DELETED) ||
-	    (time_second >= lle->la_expire)) &&
-	    (!callout_pending(&lle->la_timer) &&
+	if ((!callout_pending(&lle->la_timer) &&
 	    callout_active(&lle->la_timer))) {
 		(void) llentry_free(lle);
 		ARPSTAT_INC(timeouts);
-	} else {
-		/*
-		 * Still valid, just drop our reference
-		 */
-		LLE_FREE_LOCKED(lle);
+	} 
+#ifdef DIAGNOSTICS
+	else {
+		struct sockaddr *l3addr = L3_ADDR(lle);
+		log(LOG_INFO, "arptimer issue: %p, IPv4 address: \"%s\"\n", lle,
+		    inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
 	}
+#endif
 	IF_AFDATA_UNLOCK(ifp);
 	CURVNET_RESTORE();
 }
@@ -377,7 +377,7 @@ retry:
 
 	if (renew) {
 		LLE_ADDREF(la);
-		la->la_expire = time_second;
+		la->la_expire = time_second + V_arpt_down;
 		callout_reset(&la->la_timer, hz * V_arpt_down, arptimer, la);
 		la->la_asked++;
 		LLE_WUNLOCK(la);



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