aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2021-03-24 23:51:45 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2021-03-25 20:22:58 +0000
commit47c00a9835926e96e562c67fa28e4432e99d9c56 (patch)
tree46e003f1893ada95095dd24f0e0fedf44b1cdcd9
parentaf85312e8a6f34ea7c8af77b9841fab6b5559e25 (diff)
downloadsrc-47c00a9835926e96e562c67fa28e4432e99d9c56.tar.gz
src-47c00a9835926e96e562c67fa28e4432e99d9c56.zip
Plug nexthop group refcount leak.
In case with batch route delete via rib_walk_del(), when some paths from the multipath route gets deleted, old multipath group were not freed. PR: 254496 Reported by: Zhenlei Huang <zlei.huang@gmail.com> (cherry picked from commit 66f138563becf12d5c21924f816d2a45c3a1ed7a)
-rw-r--r--sys/net/route/route_ctl.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c
index 58b89c28f945..af3853041ac6 100644
--- a/sys/net/route/route_ctl.c
+++ b/sys/net/route/route_ctl.c
@@ -130,6 +130,7 @@ vnet_rtzone_destroy()
static void
destroy_rtentry(struct rtentry *rt)
{
+#ifdef VIMAGE
struct nhop_object *nh = rt->rt_nhop;
/*
@@ -146,9 +147,10 @@ destroy_rtentry(struct rtentry *rt)
}
#endif
CURVNET_SET(nhop_get_vnet(nh));
+#endif
/* Unreference nexthop */
- nhop_free_any(nh);
+ nhop_free_any(rt->rt_nhop);
uma_zfree(V_rtzone, rt);
@@ -1252,7 +1254,6 @@ rt_checkdelroute(struct radix_node *rn, void *arg)
struct rt_delinfo *di;
struct rt_addrinfo *info;
struct rtentry *rt;
- int error;
di = (struct rt_delinfo *)arg;
rt = (struct rtentry *)rn;
@@ -1261,7 +1262,8 @@ rt_checkdelroute(struct radix_node *rn, void *arg)
info->rti_info[RTAX_DST] = rt_key(rt);
info->rti_info[RTAX_NETMASK] = rt_mask(rt);
- error = rt_unlinkrte(di->rnh, info, &di->rc);
+ if (rt_unlinkrte(di->rnh, info, &di->rc) != 0)
+ return (0);
/*
* Add deleted rtentries to the list to GC them
@@ -1270,10 +1272,18 @@ rt_checkdelroute(struct radix_node *rn, void *arg)
* XXX: Delayed notifications not implemented
* for nexthop updates.
*/
- if ((error == 0) && (di->rc.rc_cmd == RTM_DELETE)) {
+ if (di->rc.rc_cmd == RTM_DELETE) {
/* Add to the list and return */
rt->rt_chain = di->head;
di->head = rt;
+#ifdef ROUTE_MPATH
+ } else {
+ /*
+ * RTM_CHANGE to a diferent nexthop or nexthop group.
+ * Free old multipath group.
+ */
+ nhop_free_any(di->rc.rc_nh_old);
+#endif
}
return (0);