diff options
author | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2021-03-24 23:51:45 +0000 |
---|---|---|
committer | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2021-03-25 20:22:58 +0000 |
commit | 47c00a9835926e96e562c67fa28e4432e99d9c56 (patch) | |
tree | 46e003f1893ada95095dd24f0e0fedf44b1cdcd9 | |
parent | af85312e8a6f34ea7c8af77b9841fab6b5559e25 (diff) | |
download | src-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.c | 18 |
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); |