Author: markj
Date: Fri Jan 25 20:24:53 2019
New Revision: 343454
URL: https://svnweb.freebsd.org/changeset/base/343454

Log:
  MFC r343363, r343364:
  Fix an LLE lookup race.
  
  PR:   234296

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

Modified: stable/12/sys/netinet/in.c
==============================================================================
--- stable/12/sys/netinet/in.c  Fri Jan 25 20:20:27 2019        (r343453)
+++ stable/12/sys/netinet/in.c  Fri Jan 25 20:24:53 2019        (r343454)
@@ -1378,15 +1378,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);
 
@@ -1395,6 +1393,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: stable/12/sys/netinet6/in6.c
==============================================================================
--- stable/12/sys/netinet6/in6.c        Fri Jan 25 20:20:27 2019        
(r343453)
+++ stable/12/sys/netinet6/in6.c        Fri Jan 25 20:24:53 2019        
(r343454)
@@ -2315,16 +2315,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);
 
@@ -2332,6 +2329,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