git: 6905fd01cb64 - main - if_ovpn: ensure we're in vnet context when calling sorele()

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Mon, 14 Nov 2022 08:36:59 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=6905fd01cb64ca2853b8312880f18a6ae2068099

commit 6905fd01cb64ca2853b8312880f18a6ae2068099
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2022-11-10 12:54:09 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-11-14 08:36:44 +0000

    if_ovpn: ensure we're in vnet context when calling sorele()
    
    We reference count to ensure we don't release the socket while we still
    have data in flight. That means that we can end up releasing the socket
    from ovpn_encrypt_tx_cb().
    
    We must have a vnet context set when calling sorele() (which asserts
    this from within sofree()), so move the CURVNET_SET()/CURVNET_RESTORE()
    to ensure this is the case.
    
    While here also add a couple of assertions to make this more obvious,
    and to ease future debugging.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D37326
---
 sys/net/if_ovpn.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c
index 94d12fa25f1a..6ce5d07dc230 100644
--- a/sys/net/if_ovpn.c
+++ b/sys/net/if_ovpn.c
@@ -410,6 +410,8 @@ ovpn_peer_release_ref(struct ovpn_kpeer *peer, bool locked)
 {
 	struct ovpn_softc *sc;
 
+	CURVNET_ASSERT_SET();
+
 	atomic_add_int(&peer->refcount, -1);
 
 	if (atomic_load_int(&peer->refcount) > 0)
@@ -427,6 +429,8 @@ ovpn_peer_release_ref(struct ovpn_kpeer *peer, bool locked)
 		}
 	}
 
+	OVPN_ASSERT(sc);
+
 	/* The peer should have been removed from the list already. */
 	MPASS(ovpn_find_peer(sc, peer->peerid) == NULL);
 
@@ -633,6 +637,7 @@ _ovpn_del_peer(struct ovpn_softc *sc, uint32_t peerid)
 	int i;
 
 	OVPN_WASSERT(sc);
+	CURVNET_ASSERT_SET();
 
 	for (i = 0; i < OVPN_MAX_PEERS; i++) {
 		if (sc->peers[i] == NULL)
@@ -1441,17 +1446,19 @@ ovpn_encrypt_tx_cb(struct cryptop *crp)
 	int tunnel_len;
 	int ret;
 
+	CURVNET_SET(sc->ifp->if_vnet);
+	NET_EPOCH_ENTER(et);
+
 	if (crp->crp_etype != 0) {
 		crypto_freereq(crp);
 		ovpn_peer_release_ref(peer, false);
+		NET_EPOCH_EXIT(et);
+		CURVNET_RESTORE();
 		OVPN_COUNTER_ADD(sc, lost_data_pkts_out, 1);
 		m_freem(m);
 		return (0);
 	}
 
-	NET_EPOCH_ENTER(et);
-	CURVNET_SET(sc->ifp->if_vnet);
-
 	MPASS(crp->crp_buf.cb_type == CRYPTO_BUF_MBUF);
 
 	tunnel_len = m->m_pkthdr.len - sizeof(struct ovpn_wire_header);
@@ -1461,12 +1468,12 @@ ovpn_encrypt_tx_cb(struct cryptop *crp)
 		OVPN_COUNTER_ADD(sc, tunnel_bytes_sent, tunnel_len);
 	}
 
-	CURVNET_RESTORE();
-	NET_EPOCH_EXIT(et);
-
 	crypto_freereq(crp);
 	ovpn_peer_release_ref(peer, false);
 
+	NET_EPOCH_EXIT(et);
+	CURVNET_RESTORE();
+
 	return (0);
 }