Sun Sep 1 11:00:31 2019 UTC ()
Pull up following revision(s) (requested by roy in ticket #131):

	sys/netinet6/nd6.c: revision 1.260

inet6: nd6_free assumes all routers are processed by kernel RA

This hasn't been the case for a long time if you're a dhcpcd
user with a default config. As such, it's possible for the default
IPv6 router as set by dhcpcd could be erroneously gc'ed by nd6_free.

This reduces the scope of the ND6_WLOCK taken as well as fixing an
issue where we write to ln->ln_state without a lock being held.


(martin)
diff -r1.256.2.2 -r1.256.2.3 src/sys/netinet6/nd6.c

cvs diff -r1.256.2.2 -r1.256.2.3 src/sys/netinet6/nd6.c (expand / switch to unified diff)

--- src/sys/netinet6/nd6.c 2019/08/26 13:42:36 1.256.2.2
+++ src/sys/netinet6/nd6.c 2019/09/01 11:00:31 1.256.2.3
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: nd6.c,v 1.256.2.2 2019/08/26 13:42:36 martin Exp $ */ 1/* $NetBSD: nd6.c,v 1.256.2.3 2019/09/01 11:00:31 martin Exp $ */
2/* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */ 2/* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */
3 3
4/* 4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -21,27 +21,27 @@ @@ -21,27 +21,27 @@
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE. 30 * SUCH DAMAGE.
31 */ 31 */
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.256.2.2 2019/08/26 13:42:36 martin Exp $"); 34__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.256.2.3 2019/09/01 11:00:31 martin Exp $");
35 35
36#ifdef _KERNEL_OPT 36#ifdef _KERNEL_OPT
37#include "opt_net_mpsafe.h" 37#include "opt_net_mpsafe.h"
38#endif 38#endif
39 39
40#include "bridge.h" 40#include "bridge.h"
41#include "carp.h" 41#include "carp.h"
42 42
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/systm.h> 44#include <sys/systm.h>
45#include <sys/callout.h> 45#include <sys/callout.h>
46#include <sys/kmem.h> 46#include <sys/kmem.h>
47#include <sys/mbuf.h> 47#include <sys/mbuf.h>
@@ -1179,129 +1179,116 @@ nd6_is_addr_neighbor(const struct sockad @@ -1179,129 +1179,116 @@ nd6_is_addr_neighbor(const struct sockad
1179 1179
1180 return 0; 1180 return 0;
1181} 1181}
1182 1182
1183/* 1183/*
1184 * Free an nd6 llinfo entry. 1184 * Free an nd6 llinfo entry.
1185 * Since the function would cause significant changes in the kernel, DO NOT 1185 * Since the function would cause significant changes in the kernel, DO NOT
1186 * make it global, unless you have a strong reason for the change, and are sure 1186 * make it global, unless you have a strong reason for the change, and are sure
1187 * that the change is safe. 1187 * that the change is safe.
1188 */ 1188 */
1189static void 1189static void
1190nd6_free(struct llentry *ln, int gc) 1190nd6_free(struct llentry *ln, int gc)
1191{ 1191{
1192 struct nd_defrouter *dr; 
1193 struct ifnet *ifp; 1192 struct ifnet *ifp;
1194 struct in6_addr *in6; 1193 struct in6_addr *in6;
1195 struct sockaddr_in6 sin6; 1194 struct sockaddr_in6 sin6;
1196 1195
1197 KASSERT(ln != NULL); 1196 KASSERT(ln != NULL);
1198 LLE_WLOCK_ASSERT(ln); 1197 LLE_WLOCK_ASSERT(ln);
1199 1198
1200 ifp = ln->lle_tbl->llt_ifp; 1199 ifp = ln->lle_tbl->llt_ifp;
1201 in6 = &ln->r_l3addr.addr6; 1200 in6 = &ln->r_l3addr.addr6;
1202 /* 1201 /*
1203 * we used to have pfctlinput(PRC_HOSTDEAD) here. 1202 * we used to have pfctlinput(PRC_HOSTDEAD) here.
1204 * even though it is not harmful, it was not really necessary. 1203 * even though it is not harmful, it was not really necessary.
1205 */ 1204 */
1206 1205
1207 if (!ip6_forwarding) { 1206 if (!ip6_forwarding && ln->ln_router) {
1208 ND6_WLOCK(); 1207 if (ln->ln_state == ND6_LLINFO_STALE && gc) {
1209 dr = nd6_defrouter_lookup(in6, ifp); 
1210 
1211 if (dr != NULL && dr->expire && 
1212 ln->ln_state == ND6_LLINFO_STALE && gc) { 
1213 /* 1208 /*
1214 * If the reason for the deletion is just garbage 1209 * If the reason for the deletion is just garbage
1215 * collection, and the neighbor is an active default 1210 * collection, and the neighbor is an active
1216 * router, do not delete it. Instead, reset the GC 1211 * router, do not delete it. Instead, reset the GC
1217 * timer using the router's lifetime. 1212 * timer using the router's lifetime.
1218 * Simply deleting the entry would affect default 1213 * Simply deleting the entry may affect default
1219 * router selection, which is not necessarily a good 1214 * router selection, which is not necessarily a good
1220 * thing, especially when we're using router preference 1215 * thing, especially when we're using router preference
1221 * values. 1216 * values.
1222 * XXX: the check for ln_state would be redundant, 1217 * XXX: the check for ln_state would be redundant,
1223 * but we intentionally keep it just in case. 1218 * but we intentionally keep it just in case.
1224 */ 1219 */
1225 if (dr->expire > time_uptime) 1220 if (ln->ln_expire > time_uptime)
1226 nd6_llinfo_settimer(ln, 1221 nd6_llinfo_settimer(ln,
1227 (dr->expire - time_uptime) * hz); 1222 (ln->ln_expire - time_uptime) * hz);
1228 else 1223 else
1229 nd6_llinfo_settimer(ln, nd6_gctimer * hz); 1224 nd6_llinfo_settimer(ln, nd6_gctimer * hz);
1230 ND6_UNLOCK(); 
1231 LLE_WUNLOCK(ln); 1225 LLE_WUNLOCK(ln);
1232 return; 1226 return;
1233 } 1227 }
1234 1228
1235 if (ln->ln_router || dr) { 1229 ND6_WLOCK();
1236 /* 
1237 * We need to unlock to avoid a LOR with nd6_rt_flush() 
1238 * with the rnh and for the calls to 
1239 * nd6_pfxlist_onlink_check() and nd6_defrouter_select() in the 
1240 * block further down for calls into nd6_lookup(). 
1241 * We still hold a ref. 
1242 */ 
1243 LLE_WUNLOCK(ln); 
1244 
1245 /* 
1246 * nd6_rt_flush must be called whether or not the neighbor 
1247 * is in the Default Router List. 
1248 * See a corresponding comment in nd6_na_input(). 
1249 */ 
1250 nd6_rt_flush(in6, ifp); 
1251 } 
1252 1230
1253 if (dr) { 1231 /*
1254 /* 1232 * We need to unlock to avoid a LOR with nd6_rt_flush()
1255 * Unreachablity of a router might affect the default 1233 * with the rnh and for the calls to
1256 * router selection and on-link detection of advertised 1234 * nd6_pfxlist_onlink_check() and nd6_defrouter_select() in the
1257 * prefixes. 1235 * block further down for calls into nd6_lookup().
1258 */ 1236 * We still hold a ref.
 1237 *
 1238 * Temporarily fake the state to choose a new default
 1239 * router and to perform on-link determination of
 1240 * prefixes correctly.
 1241 * Below the state will be set correctly,
 1242 * or the entry itself will be deleted.
 1243 */
 1244 ln->ln_state = ND6_LLINFO_INCOMPLETE;
 1245 LLE_WUNLOCK(ln);
1259 1246
1260 /* 1247 /*
1261 * Temporarily fake the state to choose a new default 1248 * nd6_rt_flush must be called whether or not the neighbor
1262 * router and to perform on-link determination of 1249 * is in the Default Router List.
1263 * prefixes correctly. 1250 * See a corresponding comment in nd6_na_input().
1264 * Below the state will be set correctly, 1251 */
1265 * or the entry itself will be deleted. 1252 nd6_rt_flush(in6, ifp);
1266 */ 
1267 ln->ln_state = ND6_LLINFO_INCOMPLETE; 
1268 1253
1269 /* 1254 /*
1270 * Since nd6_defrouter_select() does not affect the 1255 * Unreachablity of a router might affect the default
1271 * on-link determination and MIP6 needs the check 1256 * router selection and on-link detection of advertised
1272 * before the default router selection, we perform 1257 * prefixes.
1273 * the check now. 1258 *
1274 */ 1259 * Since nd6_defrouter_select() does not affect the
1275 nd6_pfxlist_onlink_check(); 1260 * on-link determination and MIP6 needs the check
 1261 * before the default router selection, we perform
 1262 * the check now.
 1263 */
 1264 nd6_pfxlist_onlink_check();
1276 1265
1277 /* 1266 /*
1278 * refresh default router list 1267 * refresh default router list
1279 */ 1268 */
1280 nd6_defrouter_select(); 1269 nd6_defrouter_select();
1281 } 
1282 1270
1283#ifdef __FreeBSD__ 1271#ifdef __FreeBSD__
1284 /* 1272 /*
1285 * If this entry was added by an on-link redirect, remove the 1273 * If this entry was added by an on-link redirect, remove the
1286 * corresponding host route. 1274 * corresponding host route.
1287 */ 1275 */
1288 if (ln->la_flags & LLE_REDIRECT) 1276 if (ln->la_flags & LLE_REDIRECT)
1289 nd6_free_redirect(ln); 1277 nd6_free_redirect(ln);
1290#endif 1278#endif
1291 ND6_UNLOCK(); 
1292 1279
1293 if (ln->ln_router || dr) 1280 ND6_UNLOCK();
1294 LLE_WLOCK(ln); 1281 LLE_WLOCK(ln);
1295 } 1282 }
1296 1283
1297 sockaddr_in6_init(&sin6, in6, 0, 0, 0); 1284 sockaddr_in6_init(&sin6, in6, 0, 0, 0);
1298 rt_clonedmsg(RTM_DELETE, sin6tosa(&sin6), 1285 rt_clonedmsg(RTM_DELETE, sin6tosa(&sin6),
1299 (const uint8_t *)&ln->ll_addr, ifp); 1286 (const uint8_t *)&ln->ll_addr, ifp);
1300 1287
1301 /* 1288 /*
1302 * Save to unlock. We still hold an extra reference and will not 1289 * Save to unlock. We still hold an extra reference and will not
1303 * free(9) in llentry_free() if someone else holds one as well. 1290 * free(9) in llentry_free() if someone else holds one as well.
1304 */ 1291 */
1305 LLE_WUNLOCK(ln); 1292 LLE_WUNLOCK(ln);
1306 IF_AFDATA_LOCK(ifp); 1293 IF_AFDATA_LOCK(ifp);
1307 LLE_WLOCK(ln); 1294 LLE_WLOCK(ln);