Index | Thread | Search

From:
Alexander Bluhm <bluhm@openbsd.org>
Subject:
route reference leak
To:
tech@openbsd.org
Date:
Sat, 6 Apr 2024 17:18:41 +0200

Download raw body.

Thread
Hi,

We are leaking a route reference counter in ip_output() and
ip6_output().

If no struct route was passed to ip_output(), it uses its own iproute
on the stack.  If that is the case, we have to free any route entry
that we put into the local route cache.

In the pf reroute case, we reset struct route to NULL.  Before that,
free the route entry if it was allocated locally on the stack.

ok?

bluhm

Index: netinet/ip_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_output.c,v
diff -u -p -r1.396 ip_output.c
--- netinet/ip_output.c	22 Feb 2024 14:25:58 -0000	1.396
+++ netinet/ip_output.c	6 Apr 2024 14:49:07 -0000
@@ -417,6 +417,8 @@ sendit:
 	else if (m->m_pkthdr.pf.flags & PF_TAG_REROUTE) {
 		/* tag as generated to skip over pf_test on rerun */
 		m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
+		if (ro == &iproute && ro->ro_rt)
+			rtfree(ro->ro_rt);
 		ro = NULL;
 		if_put(ifp); /* drop reference since target changed */
 		ifp = NULL;
Index: netinet6/ip6_output.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
diff -u -p -r1.288 ip6_output.c
--- netinet6/ip6_output.c	28 Feb 2024 10:57:20 -0000	1.288
+++ netinet6/ip6_output.c	6 Apr 2024 14:49:07 -0000
@@ -635,6 +635,8 @@ reroute:
 		/* tag as generated to skip over pf_test on rerun */
 		m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
 		finaldst = ip6->ip6_dst;
+		if (ro == &iproute && ro->ro_rt)
+			rtfree(ro->ro_rt);
 		ro = NULL;
 		if_put(ifp); /* drop reference since destination changed */
 		ifp = NULL;