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);
 }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to