Author: emaste
Date: Tue Feb  5 17:59:50 2019
New Revision: 343787
URL: https://svnweb.freebsd.org/changeset/base/343787

Log:
  MFS12 r343454: Fix an LLE lookup race
  
  PR:           234296
  Submitted by: markj
  Approved by:  so

Modified:
  releng/12.0/sys/netinet/in.c
  releng/12.0/sys/netinet6/in6.c
Directory Properties:
  releng/12.0/   (props changed)

Modified: releng/12.0/sys/netinet/in.c
==============================================================================
--- releng/12.0/sys/netinet/in.c        Tue Feb  5 17:57:30 2019        
(r343786)
+++ releng/12.0/sys/netinet/in.c        Tue Feb  5 17:59:50 2019        
(r343787)
@@ -1372,15 +1372,13 @@ in_lltable_lookup(struct lltable *llt, u_int flags, co
        IF_AFDATA_LOCK_ASSERT(llt->llt_ifp);
        KASSERT(l3addr->sa_family == AF_INET,
            ("sin_family %d", l3addr->sa_family));
-       lle = in_lltable_find_dst(llt, sin->sin_addr);
+       KASSERT((flags & (LLE_UNLOCKED | LLE_EXCLUSIVE)) !=
+           (LLE_UNLOCKED | LLE_EXCLUSIVE),
+           ("wrong lle request flags: %#x", flags));
 
+       lle = in_lltable_find_dst(llt, sin->sin_addr);
        if (lle == NULL)
                return (NULL);
-
-       KASSERT((flags & (LLE_UNLOCKED|LLE_EXCLUSIVE)) !=
-           (LLE_UNLOCKED|LLE_EXCLUSIVE),("wrong lle request flags: 0x%X",
-           flags));
-
        if (flags & LLE_UNLOCKED)
                return (lle);
 
@@ -1389,6 +1387,17 @@ in_lltable_lookup(struct lltable *llt, u_int flags, co
        else
                LLE_RLOCK(lle);
 
+       /*
+        * If the afdata lock is not held, the LLE may have been unlinked while
+        * we were blocked on the LLE lock.  Check for this case.
+        */
+       if (__predict_false((lle->la_flags & LLE_LINKED) == 0)) {
+               if (flags & LLE_EXCLUSIVE)
+                       LLE_WUNLOCK(lle);
+               else
+                       LLE_RUNLOCK(lle);
+               return (NULL);
+       }
        return (lle);
 }
 

Modified: releng/12.0/sys/netinet6/in6.c
==============================================================================
--- releng/12.0/sys/netinet6/in6.c      Tue Feb  5 17:57:30 2019        
(r343786)
+++ releng/12.0/sys/netinet6/in6.c      Tue Feb  5 17:59:50 2019        
(r343787)
@@ -2311,16 +2311,13 @@ in6_lltable_lookup(struct lltable *llt, u_int flags,
        IF_AFDATA_LOCK_ASSERT(llt->llt_ifp);
        KASSERT(l3addr->sa_family == AF_INET6,
            ("sin_family %d", l3addr->sa_family));
+       KASSERT((flags & (LLE_UNLOCKED | LLE_EXCLUSIVE)) !=
+           (LLE_UNLOCKED | LLE_EXCLUSIVE),
+           ("wrong lle request flags: %#x", flags));
 
        lle = in6_lltable_find_dst(llt, &sin6->sin6_addr);
-
        if (lle == NULL)
                return (NULL);
-
-       KASSERT((flags & (LLE_UNLOCKED|LLE_EXCLUSIVE)) !=
-           (LLE_UNLOCKED|LLE_EXCLUSIVE),("wrong lle request flags: 0x%X",
-           flags));
-
        if (flags & LLE_UNLOCKED)
                return (lle);
 
@@ -2328,6 +2325,18 @@ in6_lltable_lookup(struct lltable *llt, u_int flags,
                LLE_WLOCK(lle);
        else
                LLE_RLOCK(lle);
+
+       /*
+        * If the afdata lock is not held, the LLE may have been unlinked while
+        * we were blocked on the LLE lock.  Check for this case.
+        */
+       if (__predict_false((lle->la_flags & LLE_LINKED) == 0)) {
+               if (flags & LLE_EXCLUSIVE)
+                       LLE_WUNLOCK(lle);
+               else
+                       LLE_RUNLOCK(lle);
+               return (NULL);
+       }
        return (lle);
 }
 
_______________________________________________
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