aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMarco Baffo <marco@mandelbit.com>2026-06-08 16:04:46 +0200
committerAntonio Quartulli <antonio@openvpn.net>2026-07-20 15:49:55 +0200
commite1ad6fe5db719874efa45b2caf9934552e09fc43 (patch)
tree14743d3560d9426422a0eea9978b8134b0b227d4
parentselftests/net: ovpn: fix getaddrinfo memory leak in ovpn_parse_remote() (diff)
ovpn: fix use after free in unlock_ovpn()
unlock_ovpn() iterates over the release_list using llist_for_each_entry() and drops the peer reference inside the loop body via ovpn_peer_put(). If this drops the last reference, the peer is eventually freed. However, llist_for_each_entry() reads peer->release_entry.next in the loop advance expression, which runs after the body. By that time the peer may have already been freed, resulting in a use after free when advancing to the next list entry. Fix this by using llist_for_each_entry_safe(), which caches the next pointer before executing the loop body. Fixes: 80747caef33d ("ovpn: introduce the ovpn_peer object") Signed-off-by: Marco Baffo <marco@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
-rw-r--r--drivers/net/ovpn/peer.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index 2b6096d8b1cc..8fdbb5050690 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -26,11 +26,12 @@ static void unlock_ovpn(struct ovpn_priv *ovpn,
struct llist_head *release_list)
__releases(&ovpn->lock)
{
- struct ovpn_peer *peer;
+ struct ovpn_peer *peer, *next;
spin_unlock_bh(&ovpn->lock);
- llist_for_each_entry(peer, release_list->first, release_entry) {
+ llist_for_each_entry_safe(peer, next, release_list->first,
+ release_entry) {
ovpn_socket_release(peer);
ovpn_peer_put(peer);
}