From 31a6915f939004ea5404ccba73aec710ab4ff5ff Mon Sep 17 00:00:00 2001 From: bluhm Date: Fri, 3 Dec 2021 17:18:34 +0000 Subject: [PATCH] Add TDB reference counting to ipsp_spd_lookup(). If an output 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 | 10 +++++++--- sys/netinet/ip_output.c | 6 +++++- sys/netinet/ip_spd.c | 7 ++++--- sys/netinet6/ip6_forward.c | 5 ++++- sys/netinet6/ip6_output.c | 12 ++++++++---- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index c7ebf80173a..9bc7c3e7522 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -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); diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index a27f69ac583..a8f240a887f 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -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; } diff --git a/sys/netinet/ip_spd.c b/sys/netinet/ip_spd.c index f8fad967149..b1c49b21247 100644 --- a/sys/netinet/ip_spd.c +++ b/sys/netinet/ip_spd.c @@ -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; diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c index c838aeeed9f..4b933ec6852 100644 --- a/sys/netinet6/ip6_forward.c +++ b/sys/netinet6/ip6_forward.c @@ -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 */ } diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index fc7aee1f0c1..ac28becd3e9 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -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; } -- 2.20.1