git: a841961da752 - main - if_ovpn: free crp, mbuf, and release refcount on crypto_dispatch() failure

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Mon, 10 Aug 2026 13:23:08 UTC
The branch main has been updated by kp:

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

commit a841961da75218ddd5b4e9e784c9fe5148ffe781
Author:     LuisCastellanos-dev <ing.castellanosdz@gmail.com>
AuthorDate: 2026-08-10 13:09:22 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2026-08-10 13:09:30 +0000

    if_ovpn: free crp, mbuf, and release refcount on crypto_dispatch() failure
    
    When crypto_dispatch() or crypto_dispatch_async() returns non-zero,
    the registered callback is never invoked. In both ovpn_transmit_to_peer()
    and ovpn_udp_input(), if_ovpn.c did not free the cryptop request, release
    the peer/sc reference count, or free the mbuf on dispatch failure.
    
    This results in three simultaneous leaks per failed dispatch:
    - crp allocated via crypto_getreq() is never freed
    - peer->refcount (encrypt) or sc->refcount (decrypt) incremented but
      never decremented
    - mbuf passed to crypto_use_mbuf() is never freed
    
    The leaks are reachable under memory pressure when the OCF scheduler
    returns ENOMEM from crypto_dispatch(). The registered callbacks
    (ovpn_encrypt_tx_cb, ovpn_decrypt_rx_cb) correctly handle crp_etype
    for crypto operation failures; this fix addresses the separate
    dispatch-level failure path where no callback is invoked.
    
    Found during code review following FreeBSD-SA-26:52.if_wg.
    
    Reviewed by:    kp
    Differential Revision:  https://reviews.freebsd.org/D58754
---
 sys/net/if_ovpn.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c
index 19fab11f3dde..28e60efaeaa5 100644
--- a/sys/net/if_ovpn.c
+++ b/sys/net/if_ovpn.c
@@ -2188,6 +2188,9 @@ ovpn_transmit_to_peer(struct ifnet *ifp, struct mbuf *m,
 	else
 		ret = crypto_dispatch(crp);
 	if (ret) {
+		crypto_freereq(crp);
+		ovpn_peer_release_ref(peer, false);
+		m_freem(m);
 		OVPN_COUNTER_ADD(sc, lost_data_pkts_out, 1);
 		if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
 	}
@@ -2636,6 +2639,9 @@ ovpn_udp_input(struct mbuf *m, int off, struct inpcb *inp,
 	else
 		ret = crypto_dispatch(crp);
 	if (ret != 0) {
+		crypto_freereq(crp);
+		atomic_add_int(&sc->refcount, -1);
+		m_freem(m);
 		OVPN_COUNTER_ADD(sc, lost_data_pkts_in, 1);
 		if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1);
 	}