Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Jan 2019 20:24:53 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r343454 - in stable/12/sys: netinet netinet6
Message-ID:  <201901252024.x0PKOrYc003351@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }
 



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