svn commit: r343787 - in releng/12.0/sys: netinet netinet6
Ed Maste
emaste at FreeBSD.org
Tue Feb 5 17:59:51 UTC 2019
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);
}
More information about the svn-src-releng
mailing list