From 5835d6677d5efd0f9ea68759894a7f46443deff6 Mon Sep 17 00:00:00 2001 From: bluhm Date: Tue, 7 Dec 2021 17:28:46 +0000 Subject: [PATCH] In ipo_tdb the flow contains a reference counted TDB cache. This may prevent that tdb_free() is called. It is not a real leak as ipsecctl -F or termination of iked flush this cache when they remove the IPsec policy. Move the code from tdb_free() to tdb_delete(), then the kernel does the cleanup itself. OK mvs@ tobhe@ --- sys/netinet/ip_ipsp.c | 27 +++++++++++++++++---------- sys/netinet/ip_ipsp.h | 3 ++- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c index 4789c635473..551a589631e 100644 --- a/sys/netinet/ip_ipsp.c +++ b/sys/netinet/ip_ipsp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.c,v 1.261 2021/12/03 19:04:49 tobhe Exp $ */ +/* $OpenBSD: ip_ipsp.c,v 1.262 2021/12/07 17:28:46 bluhm Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), @@ -922,6 +922,19 @@ tdb_unlink_locked(struct tdb *tdbp) #endif /* IPSEC */ } +void +tdb_cleanspd(struct tdb *tdbp) +{ + struct ipsec_policy *ipo; + + while ((ipo = TAILQ_FIRST(&tdbp->tdb_policy_head)) != NULL) { + TAILQ_REMOVE(&tdbp->tdb_policy_head, ipo, ipo_tdb_next); + tdb_unref(ipo->ipo_tdb); + ipo->ipo_tdb = NULL; + ipo->ipo_last_searched = 0; /* Force a re-search. */ + } +} + void tdb_unbundle(struct tdb *tdbp) { @@ -1001,6 +1014,8 @@ tdb_dodelete(struct tdb *tdbp, int locked) else tdb_unlink(tdbp); + /* cleanup SPD references */ + tdb_cleanspd(tdbp); /* release tdb_onext/tdb_inext references */ tdb_unbundle(tdbp); /* delete timeouts and release references */ @@ -1043,8 +1058,6 @@ tdb_alloc(u_int rdomain) void tdb_free(struct tdb *tdbp) { - struct ipsec_policy *ipo; - NET_ASSERT_LOCKED(); if (tdbp->tdb_xform) { @@ -1057,13 +1070,7 @@ tdb_free(struct tdb *tdbp) pfsync_delete_tdb(tdbp); #endif - /* Cleanup SPD references. */ - while ((ipo = TAILQ_FIRST(&tdbp->tdb_policy_head)) != NULL) { - TAILQ_REMOVE(&tdbp->tdb_policy_head, ipo, ipo_tdb_next); - tdb_unref(ipo->ipo_tdb); - ipo->ipo_tdb = NULL; - ipo->ipo_last_searched = 0; /* Force a re-search. */ - } + KASSERT(TAILQ_EMPTY(&tdbp->tdb_policy_head)); if (tdbp->tdb_ids) { ipsp_ids_free(tdbp->tdb_ids); diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h index 06d069fe949..bb8b1a6fb29 100644 --- a/sys/netinet/ip_ipsp.h +++ b/sys/netinet/ip_ipsp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.h,v 1.227 2021/12/03 19:04:49 tobhe Exp $ */ +/* $OpenBSD: ip_ipsp.h,v 1.228 2021/12/07 17:28:46 bluhm Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), @@ -577,6 +577,7 @@ void tdb_free(struct tdb *); int tdb_init(struct tdb *, u_int16_t, struct ipsecinit *); void tdb_unlink(struct tdb *); void tdb_unlink_locked(struct tdb *); +void tdb_cleanspd(struct tdb *); void tdb_unbundle(struct tdb *); void tdb_deltimeouts(struct tdb *); int tdb_walk(u_int, int (*)(struct tdb *, void *, int), void *); -- 2.20.1