diff options
author | glebius <glebius@FreeBSD.org> | 2012-12-13 11:11:15 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2012-12-13 11:11:15 +0000 |
commit | 8137816adb03dc4adf599f4790b2f2cecbe5f5b4 (patch) | |
tree | e234b73341b1557dce509188f3ea487c6df2c5fa /sys/netinet6/nd6.c | |
parent | 2d5902ca92bed1978312dee52ee4a8d78fb4046a (diff) | |
download | FreeBSD-src-8137816adb03dc4adf599f4790b2f2cecbe5f5b4.zip FreeBSD-src-8137816adb03dc4adf599f4790b2f2cecbe5f5b4.tar.gz |
Fix problem in r238990. The LLE_LINKED flag should be tested prior to
entering llentry_free(), and in case if we lose the race, we should simply
perform LLE_FREE_LOCKED(). Otherwise, if the race is lost by the thread
performing arptimer(), it will remove two references from the lle instead
of one.
Reported by: Ian FREISLICH <ianf clue.co.za>
Diffstat (limited to 'sys/netinet6/nd6.c')
-rw-r--r-- | sys/netinet6/nd6.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 9993c77..5107f1d 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1108,8 +1108,14 @@ nd6_free(struct llentry *ln, int gc) LLE_WUNLOCK(ln); IF_AFDATA_LOCK(ifp); LLE_WLOCK(ln); - LLE_REMREF(ln); - llentry_free(ln); + + /* Guard against race with other llentry_free(). */ + if (ln->la_flags & LLE_LINKED) { + LLE_REMREF(ln); + llentry_free(ln); + } else + LLE_FREE_LOCKED(ln); + IF_AFDATA_UNLOCK(ifp); return (next); |