Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Jun 2015 12:23:05 +0000 (UTC)
From:      Ermal Luçi <eri@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r284512 - head/sys/netinet
Message-ID:  <201506171223.t5HCN5ni061270@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: eri
Date: Wed Jun 17 12:23:04 2015
New Revision: 284512
URL: https://svnweb.freebsd.org/changeset/base/284512

Log:
  If there is a system with a bpf consumer running and a packet is wanted
  to be transmitted but the arp cache entry expired, which triggers an arp request
  to be sent, the bpf code might want to sleep but crash the system due
  to a non sleep lock held from the arp entry not released properly.
  
  Release the lock before calling the arp request code to solve the issue
  as is done on all the other code paths.
  
  PR:	200323
  Approved by: ae, gnn(mentor)
  MFC after:	1 week
  Sponsored by:	Netgate
  Differential Revision:	https://reviews.freebsd.org/D2828

Modified:
  head/sys/netinet/if_ether.c

Modified: head/sys/netinet/if_ether.c
==============================================================================
--- head/sys/netinet/if_ether.c	Wed Jun 17 12:05:04 2015	(r284511)
+++ head/sys/netinet/if_ether.c	Wed Jun 17 12:23:04 2015	(r284512)
@@ -364,6 +364,7 @@ retry:
 	if ((la->la_flags & LLE_VALID) &&
 	    ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) {
 		bcopy(&la->ll_addr, desten, ifp->if_addrlen);
+		renew = 0;
 		/*
 		 * If entry has an expiry time and it is approaching,
 		 * see if we need to send an ARP request within this
@@ -371,14 +372,22 @@ retry:
 		 */
 		if (!(la->la_flags & LLE_STATIC) &&
 		    time_uptime + la->la_preempt > la->la_expire) {
-			arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL);
+			renew = 1;
 			la->la_preempt--;
 		}
 
 		if (pflags != NULL)
 			*pflags = la->la_flags;
-		error = 0;
-		goto done;
+
+		if (flags & LLE_EXCLUSIVE)
+			LLE_WUNLOCK(la);
+		else
+			LLE_RUNLOCK(la);
+
+		if (renew == 1)
+			arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL);
+
+		return (0);
 	}
 
 	if (la->la_flags & LLE_STATIC) {   /* should not happen! */



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