aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2025-12-09 10:55:30 +0000
committerKristof Provost <kp@FreeBSD.org>2025-12-09 14:17:48 +0000
commit5e2bbfe387f7eac8f802c4b6ad2114f0e17bb5f2 (patch)
tree12486778e93b321f4510cb7216390c76f27a34bf
parent66129def7bdaf8a0447aba55e736d27687204555 (diff)
if_ovpn: use epoch to free peers
Avoid a possible use-after-free in the rx path. ovpn_decrypt_rx_cb() calls ovpn_finish_rx() which releases the lock, but continues to use the peer. Ensure that the peer cannot be freed until we're sure all potential users have stopped using it (i.e. have left net_epoch). Reported by: Kevin Day <kevin@your.org> MFC after: 1 week Sponsored by: Rubicon Communications, LLC ("Netgate")
-rw-r--r--sys/net/if_ovpn.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c
index 674df4d17eb4..ae09a1ce9db8 100644
--- a/sys/net/if_ovpn.c
+++ b/sys/net/if_ovpn.c
@@ -161,6 +161,7 @@ struct ovpn_kpeer {
struct callout ping_rcv;
counter_u64_t counters[OVPN_PEER_COUNTER_SIZE];
+ struct epoch_context epoch_ctx;
};
struct ovpn_counters {
@@ -569,6 +570,15 @@ ovpn_notify_float(struct ovpn_softc *sc, uint32_t peerid,
}
static void
+_ovpn_free_peer(struct epoch_context *ctx) {
+ struct ovpn_kpeer *peer = __containerof(ctx, struct ovpn_kpeer,
+ epoch_ctx);
+
+ uma_zfree_pcpu(pcpu_zone_4, peer->last_active);
+ free(peer, M_OVPN);
+}
+
+static void
ovpn_peer_release_ref(struct ovpn_kpeer *peer, bool locked)
{
struct ovpn_softc *sc;
@@ -606,8 +616,8 @@ ovpn_peer_release_ref(struct ovpn_kpeer *peer, bool locked)
callout_stop(&peer->ping_send);
callout_stop(&peer->ping_rcv);
- uma_zfree_pcpu(pcpu_zone_4, peer->last_active);
- free(peer, M_OVPN);
+
+ NET_EPOCH_CALL(_ovpn_free_peer, &peer->epoch_ctx);
if (! locked)
OVPN_WUNLOCK(sc);