[PATCH] ovpn: Fix use-after-free when releasing peers in unlock_ovpn()

Wentao Liang posted 1 patch 1 week ago
drivers/net/ovpn/peer.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
[PATCH] ovpn: Fix use-after-free when releasing peers in unlock_ovpn()
Posted by Wentao Liang 1 week ago
unlock_ovpn() walks the release list with llist_for_each_entry() and
drops the last reference of each peer in the loop body. Advancing to the
next entry then reads peer->release_entry.next from an object that has
already been scheduled for freeing, which is a use-after-free. Use
llist_for_each_entry_safe() so the next pointer is read before the peer
is released.

Fixes: 80747caef33d ("ovpn: introduce the ovpn_peer object")
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
 drivers/net/ovpn/peer.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index a09d61296425..12ebc5affdd0 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -26,11 +26,11 @@ static void unlock_ovpn(struct ovpn_priv *ovpn,
 			 struct llist_head *release_list)
 	__releases(&ovpn->lock)
 {
-	struct ovpn_peer *peer;
+	struct ovpn_peer *peer, *tmp;
 
 	spin_unlock_bh(&ovpn->lock);
 
-	llist_for_each_entry(peer, release_list->first, release_entry) {
+	llist_for_each_entry_safe(peer, tmp, release_list->first, release_entry) {
 		ovpn_socket_release(peer);
 		ovpn_peer_put(peer);
 	}
-- 
2.34.1