Fri Oct 21 10:56:35 2016 UTC ()
Delete rt_timers on RTM_DELETE surely

We want to ensure that a rtentry is referenced by nobody after
RTM_DELETE (except for the caller). However, rt_timer could
have a reference to the rtentry after that.


(ozaki-r)
diff -r1.178 -r1.179 src/sys/net/route.c

cvs diff -r1.178 -r1.179 src/sys/net/route.c (expand / switch to unified diff)

--- src/sys/net/route.c 2016/10/21 10:52:47 1.178
+++ src/sys/net/route.c 2016/10/21 10:56:35 1.179
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: route.c,v 1.178 2016/10/21 10:52:47 ozaki-r Exp $ */ 1/* $NetBSD: route.c,v 1.179 2016/10/21 10:56:35 ozaki-r Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Kevin M. Lahey of the Numerical Aerospace Simulation Facility, 8 * by Kevin M. Lahey of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center. 9 * NASA Ames Research Center.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -87,27 +87,27 @@ @@ -87,27 +87,27 @@
87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
88 * SUCH DAMAGE. 88 * SUCH DAMAGE.
89 * 89 *
90 * @(#)route.c 8.3 (Berkeley) 1/9/95 90 * @(#)route.c 8.3 (Berkeley) 1/9/95
91 */ 91 */
92 92
93#ifdef _KERNEL_OPT 93#ifdef _KERNEL_OPT
94#include "opt_inet.h" 94#include "opt_inet.h"
95#include "opt_route.h" 95#include "opt_route.h"
96#include "opt_net_mpsafe.h" 96#include "opt_net_mpsafe.h"
97#endif 97#endif
98 98
99#include <sys/cdefs.h> 99#include <sys/cdefs.h>
100__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.178 2016/10/21 10:52:47 ozaki-r Exp $"); 100__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.179 2016/10/21 10:56:35 ozaki-r Exp $");
101 101
102#include <sys/param.h> 102#include <sys/param.h>
103#ifdef RTFLUSH_DEBUG 103#ifdef RTFLUSH_DEBUG
104#include <sys/sysctl.h> 104#include <sys/sysctl.h>
105#endif 105#endif
106#include <sys/systm.h> 106#include <sys/systm.h>
107#include <sys/callout.h> 107#include <sys/callout.h>
108#include <sys/proc.h> 108#include <sys/proc.h>
109#include <sys/mbuf.h> 109#include <sys/mbuf.h>
110#include <sys/socket.h> 110#include <sys/socket.h>
111#include <sys/socketvar.h> 111#include <sys/socketvar.h>
112#include <sys/domain.h> 112#include <sys/domain.h>
113#include <sys/protosw.h> 113#include <sys/protosw.h>
@@ -463,27 +463,26 @@ rtfree(struct rtentry *rt) @@ -463,27 +463,26 @@ rtfree(struct rtentry *rt)
463 struct ifaddr *ifa; 463 struct ifaddr *ifa;
464 464
465 KASSERT(rt != NULL); 465 KASSERT(rt != NULL);
466 KASSERT(rt->rt_refcnt > 0); 466 KASSERT(rt->rt_refcnt > 0);
467 467
468 rt->rt_refcnt--; 468 rt->rt_refcnt--;
469#if defined(DEBUG) && !defined(NET_MPSAFE) 469#if defined(DEBUG) && !defined(NET_MPSAFE)
470 if (rt_getkey(rt) != NULL) 470 if (rt_getkey(rt) != NULL)
471 rtcache_check_rtrefcnt(rt_getkey(rt)->sa_family); 471 rtcache_check_rtrefcnt(rt_getkey(rt)->sa_family);
472#endif 472#endif
473 if (rt->rt_refcnt == 0 && (rt->rt_flags & RTF_UP) == 0) { 473 if (rt->rt_refcnt == 0 && (rt->rt_flags & RTF_UP) == 0) {
474 rt_assert_inactive(rt); 474 rt_assert_inactive(rt);
475 rttrash--; 475 rttrash--;
476 rt_timer_remove_all(rt); 
477 ifa = rt->rt_ifa; 476 ifa = rt->rt_ifa;
478 rt->rt_ifa = NULL; 477 rt->rt_ifa = NULL;
479 ifafree(ifa); 478 ifafree(ifa);
480 rt->rt_ifp = NULL; 479 rt->rt_ifp = NULL;
481 rt_destroy(rt); 480 rt_destroy(rt);
482 pool_put(&rtentry_pool, rt); 481 pool_put(&rtentry_pool, rt);
483 } 482 }
484} 483}
485 484
486/* 485/*
487 * Force a routing table entry to the specified 486 * Force a routing table entry to the specified
488 * destination to go through the given gateway. 487 * destination to go through the given gateway.
489 * Normally called as a result of a routing redirect 488 * Normally called as a result of a routing redirect
@@ -843,26 +842,27 @@ rtrequest1(int req, struct rt_addrinfo * @@ -843,26 +842,27 @@ rtrequest1(int req, struct rt_addrinfo *
843 if ((ifa = rt->rt_ifa)) { 842 if ((ifa = rt->rt_ifa)) {
844 if (ifa->ifa_flags & IFA_ROUTE && 843 if (ifa->ifa_flags & IFA_ROUTE &&
845 rt_ifa_connected(rt, ifa)) { 844 rt_ifa_connected(rt, ifa)) {
846 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, " 845 RT_DPRINTF("rt->_rt_key = %p, ifa = %p, "
847 "deleted IFA_ROUTE\n", 846 "deleted IFA_ROUTE\n",
848 (void *)rt->_rt_key, (void *)ifa); 847 (void *)rt->_rt_key, (void *)ifa);
849 ifa->ifa_flags &= ~IFA_ROUTE; 848 ifa->ifa_flags &= ~IFA_ROUTE;
850 } 849 }
851 if (ifa->ifa_rtrequest) 850 if (ifa->ifa_rtrequest)
852 ifa->ifa_rtrequest(RTM_DELETE, rt, info); 851 ifa->ifa_rtrequest(RTM_DELETE, rt, info);
853 ifa = NULL; 852 ifa = NULL;
854 } 853 }
855 rttrash++; 854 rttrash++;
 855 rt_timer_remove_all(rt);
856 if (ret_nrt) { 856 if (ret_nrt) {
857 *ret_nrt = rt; 857 *ret_nrt = rt;
858 rt->rt_refcnt++; 858 rt->rt_refcnt++;
859 } else if (rt->rt_refcnt <= 0) { 859 } else if (rt->rt_refcnt <= 0) {
860 /* Adjust the refcount */ 860 /* Adjust the refcount */
861 rt->rt_refcnt++; 861 rt->rt_refcnt++;
862 rtfree(rt); 862 rtfree(rt);
863 } 863 }
864 rtcache_clear_rtentry(dst->sa_family, rt); 864 rtcache_clear_rtentry(dst->sa_family, rt);
865 break; 865 break;
866 866
867 case RTM_ADD: 867 case RTM_ADD:
868 if (info->rti_ifa == NULL) { 868 if (info->rti_ifa == NULL) {
@@ -1326,28 +1326,28 @@ rt_timer_count(struct rttimer_queue *rtq @@ -1326,28 +1326,28 @@ rt_timer_count(struct rttimer_queue *rtq
1326 1326
1327static void 1327static void
1328rt_timer_remove_all(struct rtentry *rt) 1328rt_timer_remove_all(struct rtentry *rt)
1329{ 1329{
1330 struct rttimer *r; 1330 struct rttimer *r;
1331 1331
1332 while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) { 1332 while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) {
1333 LIST_REMOVE(r, rtt_link); 1333 LIST_REMOVE(r, rtt_link);
1334 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next); 1334 TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next);
1335 if (r->rtt_queue->rtq_count > 0) 1335 if (r->rtt_queue->rtq_count > 0)
1336 r->rtt_queue->rtq_count--; 1336 r->rtt_queue->rtq_count--;
1337 else 1337 else
1338 printf("rt_timer_remove_all: rtq_count reached 0\n"); 1338 printf("rt_timer_remove_all: rtq_count reached 0\n");
1339 rtfree(r->rtt_rt); 
1340 pool_put(&rttimer_pool, r); 1339 pool_put(&rttimer_pool, r);
 1340 rt->rt_refcnt--; /* XXX */
1341 } 1341 }
1342} 1342}
1343 1343
1344int 1344int
1345rt_timer_add(struct rtentry *rt, 1345rt_timer_add(struct rtentry *rt,
1346 void (*func)(struct rtentry *, struct rttimer *), 1346 void (*func)(struct rtentry *, struct rttimer *),
1347 struct rttimer_queue *queue) 1347 struct rttimer_queue *queue)
1348{ 1348{
1349 struct rttimer *r; 1349 struct rttimer *r;
1350 1350
1351 KASSERT(func != NULL); 1351 KASSERT(func != NULL);
1352 /* 1352 /*
1353 * If there's already a timer with this action, destroy it before 1353 * If there's already a timer with this action, destroy it before