Add TDB reference counting to ipsp_spd_lookup(). If an output
authorbluhm <bluhm@openbsd.org>
Fri, 3 Dec 2021 17:18:34 +0000 (17:18 +0000)
committerbluhm <bluhm@openbsd.org>
Fri, 3 Dec 2021 17:18:34 +0000 (17:18 +0000)
pointer is passed to the function, it will return a refcounted TDB.
The ref happens when ipsp_spd_inp() copies the pointer from
ipo->ipo_tdb.  The caller of ipsp_spd_lookup() has to unref after
using it.
tested by Hrvoje Popovski; OK mvs@ tobhe@

sys/net/if_bridge.c
sys/netinet/ip_output.c
sys/netinet/ip_spd.c
sys/netinet6/ip6_forward.c
sys/netinet6/ip6_output.c

index c7ebf80..9bc7c3e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_bridge.c,v 1.360 2021/12/01 12:51:09 bluhm Exp $   */
+/*     $OpenBSD: if_bridge.c,v 1.361 2021/12/03 17:18:34 bluhm Exp $   */
 
 /*
  * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -1606,11 +1606,14 @@ bridge_ipsec(struct ifnet *ifp, struct ether_header *eh, int hassnap,
                            tdb->tdb_tap)) == NULL ||
                            pf_test(af, dir, encif, &m) != PF_PASS) {
                                m_freem(m);
+                               tdb_unref(tdb);
                                return (1);
                        }
-                       if (m == NULL)
+                       if (m == NULL) {
+                               tdb_unref(tdb);
                                return (1);
-                       else if (af == AF_INET)
+                       }
+                       if (af == AF_INET)
                                in_proto_cksum_out(m, encif);
 #ifdef INET6
                        else if (af == AF_INET6)
@@ -1628,6 +1631,7 @@ bridge_ipsec(struct ifnet *ifp, struct ether_header *eh, int hassnap,
                                    ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG);
                        else
                                error = ipsp_process_packet(m, tdb, af, 0);
+                       tdb_unref(tdb);
                        return (1);
                } else
                        return (0);
index a27f69a..a8f240a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_output.c,v 1.376 2021/12/01 12:51:09 bluhm Exp $   */
+/*     $OpenBSD: ip_output.c,v 1.377 2021/12/03 17:18:34 bluhm Exp $   */
 /*     $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $  */
 
 /*
@@ -523,6 +523,9 @@ done:
        if (ro == &iproute && ro->ro_rt)
                rtfree(ro->ro_rt);
        if_put(ifp);
+#ifdef IPSEC
+       tdb_unref(tdb);
+#endif /* IPSEC */
        return (error);
 
 bad:
@@ -558,6 +561,7 @@ ip_output_ipsec_lookup(struct mbuf *m, int hlen, struct inpcb *inp,
                    !memcmp(&tdbi->dst, &tdb->tdb_dst,
                    sizeof(union sockaddr_union))) {
                        /* no IPsec needed */
+                       tdb_unref(tdb);
                        *tdbout = NULL;
                        return 0;
                }
index f8fad96..b1c49b2 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_spd.c,v 1.107 2021/12/01 12:51:09 bluhm Exp $ */
+/* $OpenBSD: ip_spd.c,v 1.108 2021/12/03 17:18:34 bluhm Exp $ */
 /*
  * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
  *
@@ -825,9 +825,10 @@ ipsp_spd_inp(struct mbuf *m, struct inpcb *inp, struct ipsec_policy *ipo,
 
  justreturn:
        if (tdbout != NULL) {
-               if (ipo != NULL)
+               if (ipo != NULL) {
+                       tdb_ref(ipo->ipo_tdb);
                        *tdbout = ipo->ipo_tdb;
-               else
+               else
                        *tdbout = NULL;
        }
        return 0;
index c838aee..4b933ec 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip6_forward.c,v 1.103 2021/12/01 12:51:09 bluhm Exp $ */
+/*     $OpenBSD: ip6_forward.c,v 1.104 2021/12/03 17:18:34 bluhm Exp $ */
 /*     $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $    */
 
 /*
@@ -397,4 +397,7 @@ freecopy:
 out:
        rtfree(rt);
        if_put(ifp);
+#ifdef IPSEC
+       tdb_unref(tdb);
+#endif /* IPSEC */
 }
index fc7aee1..ac28bec 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip6_output.c,v 1.262 2021/12/01 12:51:09 bluhm Exp $  */
+/*     $OpenBSD: ip6_output.c,v 1.263 2021/12/03 17:18:34 bluhm Exp $  */
 /*     $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $    */
 
 /*
@@ -220,7 +220,7 @@ ip6_output(struct mbuf *m, struct ip6_pktopts *opt, struct route_in6 *ro,
        }
 
 #ifdef IPSEC
-       if (ipsec_in_use || inp) {
+       if (ipsec_in_use || inp != NULL) {
                error = ip6_output_ipsec_lookup(m, inp, &tdb);
                if (error) {
                        /*
@@ -433,7 +433,7 @@ reroute:
        }
 
 #ifdef IPSEC
-       if (tdb) {
+       if (tdb != NULL) {
                /*
                 * XXX what should we do if ip6_hlim == 0 and the
                 * packet gets tunneled?
@@ -762,12 +762,15 @@ reroute:
                ip6stat_inc(ip6s_fragmented);
 
 done:
-       if_put(ifp);
        if (ro == &ip6route && ro->ro_rt) {
                rtfree(ro->ro_rt);
        } else if (ro_pmtu == &ip6route && ro_pmtu->ro_rt) {
                rtfree(ro_pmtu->ro_rt);
        }
+       if_put(ifp);
+#ifdef IPSEC
+       tdb_unref(tdb);
+#endif /* IPSEC */
        return (error);
 
 freehdrs:
@@ -2770,6 +2773,7 @@ ip6_output_ipsec_lookup(struct mbuf *m, struct inpcb *inp, struct tdb **tdbout)
                    !memcmp(&tdbi->dst, &tdb->tdb_dst,
                    sizeof(union sockaddr_union))) {
                        /* no IPsec needed */
+                       tdb_unref(tdb);
                        *tdbout = NULL;
                        return 0;
                }