Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Jun 2018 18:40:16 +0000 (UTC)
From:      Matt Macy <mmacy@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r335500 - head/sys/netinet
Message-ID:  <201806211840.w5LIeGMM074539@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mmacy
Date: Thu Jun 21 18:40:15 2018
New Revision: 335500
URL: https://svnweb.freebsd.org/changeset/base/335500

Log:
  in_pcblookup_hash: validate inp before return
  
  Post r335356 it is possible to have an inpcb on the hash lists that is
  partially torn down. Validate before using. Also as a side effect of this
  change the lock ordering issue between hash lock and inpcb no longer exists
  allowing some simplification.
  
  Reported by:	pho@

Modified:
  head/sys/netinet/in_pcb.c

Modified: head/sys/netinet/in_pcb.c
==============================================================================
--- head/sys/netinet/in_pcb.c	Thu Jun 21 18:13:04 2018	(r335499)
+++ head/sys/netinet/in_pcb.c	Thu Jun 21 18:40:15 2018	(r335500)
@@ -2214,7 +2214,6 @@ found:
 			INP_WUNLOCK(inp);
 		else
 			INP_RUNLOCK(inp);
-		INP_HASH_RUNLOCK(pcbinfo);
 		return (NULL);
 	} else if (!locked)
 		in_pcbref(inp);
@@ -2386,40 +2385,35 @@ in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in
     struct ifnet *ifp)
 {
 	struct inpcb *inp;
-	bool locked;
 
 	INP_HASH_RLOCK(pcbinfo);
 	inp = in_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport,
 	    (lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp);
 	if (inp != NULL) {
-		if (lookupflags & INPLOOKUP_WLOCKPCB)
-			locked = INP_TRY_WLOCK(inp);
-		else if (lookupflags & INPLOOKUP_RLOCKPCB)
-			locked = INP_TRY_RLOCK(inp);
-		else
-			panic("%s: locking bug", __func__);
-		if (!locked)
-			in_pcbref(inp);
-		INP_HASH_RUNLOCK(pcbinfo);
-		if (!locked) {
-			if (lookupflags & INPLOOKUP_WLOCKPCB) {
-				INP_WLOCK(inp);
-				if (in_pcbrele_wlocked(inp))
-					return (NULL);
-			} else {
-				INP_RLOCK(inp);
-				if (in_pcbrele_rlocked(inp))
-					return (NULL);
+		if (lookupflags & INPLOOKUP_WLOCKPCB) {
+			INP_WLOCK(inp);
+			if (__predict_false(inp->inp_flags2 & INP_FREED)) {
+				INP_WUNLOCK(inp);
+				inp = NULL;
 			}
-		}
+		} else if (lookupflags & INPLOOKUP_RLOCKPCB) {
+			INP_RLOCK(inp);
+			if (__predict_false(inp->inp_flags2 & INP_FREED)) {
+				INP_RUNLOCK(inp);
+				inp = NULL;
+			}
+		} else
+			panic("%s: locking bug", __func__);
 #ifdef INVARIANTS
-		if (lookupflags & INPLOOKUP_WLOCKPCB)
-			INP_WLOCK_ASSERT(inp);
-		else
-			INP_RLOCK_ASSERT(inp);
+		if (inp != NULL) {
+			if (lookupflags & INPLOOKUP_WLOCKPCB)
+				INP_WLOCK_ASSERT(inp);
+			else
+				INP_RLOCK_ASSERT(inp);
+		}
 #endif
-	} else
-		INP_HASH_RUNLOCK(pcbinfo);
+	}
+	INP_HASH_RUNLOCK(pcbinfo);
 	return (inp);
 }
 



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