Plug route leak in IP output.
authorbluhm <bluhm@openbsd.org>
Tue, 9 Apr 2024 11:05:05 +0000 (11:05 +0000)
committerbluhm <bluhm@openbsd.org>
Tue, 9 Apr 2024 11:05:05 +0000 (11:05 +0000)
If no struct route is passed to ip_output() or ip6_output(), it
uses its own iproute on the stack.  In that case any route entry
in the local route cache has to be freed.  After pf decides to
reroute, struct route is reset to NULL.  Then the route reference
counter has to be released.  Call rtfree() without needless NULL
check.

OK mvs@

sys/netinet/ip_output.c
sys/netinet6/ip6_output.c

index 0a60696..3154be3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_output.c,v 1.396 2024/02/22 14:25:58 bluhm Exp $   */
+/*     $OpenBSD: ip_output.c,v 1.397 2024/04/09 11:05:05 bluhm Exp $   */
 /*     $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $  */
 
 /*
@@ -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)
+                       rtfree(ro->ro_rt);
                ro = NULL;
                if_put(ifp); /* drop reference since target changed */
                ifp = NULL;
@@ -481,7 +483,7 @@ sendit:
        ipstat_inc(ips_fragmented);
 
 done:
-       if (ro == &iproute && ro->ro_rt)
+       if (ro == &iproute)
                rtfree(ro->ro_rt);
        if_put(ifp);
 #ifdef IPSEC
index 9451942..a2ba550 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip6_output.c,v 1.288 2024/02/28 10:57:20 bluhm Exp $  */
+/*     $OpenBSD: ip6_output.c,v 1.289 2024/04/09 11:05:05 bluhm Exp $  */
 /*     $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $    */
 
 /*
@@ -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)
+                       rtfree(ro->ro_rt);
                ro = NULL;
                if_put(ifp); /* drop reference since destination changed */
                ifp = NULL;
@@ -758,11 +760,10 @@ reroute:
  bad:
        m_freem(m);
  done:
-       if (ro == &iproute && ro->ro_rt) {
+       if (ro == &iproute)
                rtfree(ro->ro_rt);
-       } else if (ro_pmtu == &iproute && ro_pmtu->ro_rt) {
+       else if (ro_pmtu == &iproute)
                rtfree(ro_pmtu->ro_rt);
-       }
        if_put(ifp);
 #ifdef IPSEC
        tdb_unref(tdb);