From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6896A41F362; Thu, 30 Jul 2026 14:52:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785423152; cv=none; b=Xaa2i1uAr2gAXowUTOFvb8q7KaKhh1uS3FUu5vhZybvqFynIORqGnRnbrw/MBfsFH0Ry2yCNYkMgANexau5wBQiQyvTS6BHGvHchqlYwv/Ng69sUG5hR6vJsWdDX8WZcu48ULHWCinHzlkLCpSwiNf0Sb4hyO38LSMFvzXwZwQA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785423152; c=relaxed/simple; bh=PSPumQr1nMVfF7ByU6zRyd2xcNKRyaOxuuF5Ot5OZa4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PLsfmYO7uA+Q16p0pZRTvNzBSiRO1GjLJCl4tqVy6cdaJxHXDKy9yOoFiIGAb2WwzvS9juo89EKZe1D9KlVeRpvHXrwcXlU26w4z5VwRHFfdVdZ8IV3FY+DvXzHbof7Bs1PGQEASQTaPDtcDdk9cKRlOZ2b1azW5HaquQXa6CLQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=1ZQ6K52w; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="1ZQ6K52w" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BF9FC1F000E9; Thu, 30 Jul 2026 14:52:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1785423151; bh=67Hf4FXrujuCEm++K11F4NdsheDk2kqyYCXkhxu16l4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=1ZQ6K52wjidSXi/8qJcvXpqtDbAyY0otnHJm36YHK6ZVXWzq5A/14feuLjLDj1c+i 11WnASAz0sX2BPWPmOdx/305ipySA9A8rnL7GqJgIpR4vk/9yg7pJUEugXddpKzaeJ opALEFVfyp7xg/OXdD8syGLZ9O9bBKbce9fqXlV4= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Pavitra Jha , Sabrina Dubroca , Antonio Quartulli Subject: [PATCH 7.1 683/744] ovpn: fix peer refcount leak in TCP error paths Date: Thu, 30 Jul 2026 16:15:56 +0200 Message-ID: <20260730141458.780867069@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260730141444.267951807@linuxfoundation.org> References: <20260730141444.267951807@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 7.1-stable review patch. If anyone has any objections, please let me know. ------------------ From: Pavitra Jha commit 63bbe18fc03062f483c627838a566a707b62da79 upstream. When either the TCP RX or TX error path calls ovpn_peer_hold() followed by schedule_work(&peer->tcp.defer_del_work), and the work item is already pending from the other path, schedule_work() returns false and the work runs only once. Since ovpn_tcp_peer_del_work() calls ovpn_peer_put() exactly once, the extra reference taken by the losing path is never dropped, leaking the peer object. The race window: CPU0 (strparser/RX error): CPU1 (tcp_tx_work/TX error): ovpn_peer_hold() <- refcnt+1 ovpn_peer_hold() <- refcnt+2 schedule_work() <- queued schedule_work() <- NO-OP (work already pending) ovpn_tcp_peer_del_work runs: ovpn_peer_del() ovpn_peer_put() <- refcnt+1 <- peer never freed Fix by checking the return value of schedule_work() in both paths and calling ovpn_peer_put() to drop the extra reference if the work was already pending. ovpn_peer_hold() is kept unconditional in the TX path as it cannot fail at that point. Fixes: a6a5e87b3ee4 ("ovpn: avoid sleep in atomic context in TCP RX error path") Cc: stable@vger.kernel.org Signed-off-by: Pavitra Jha Reviewed-by: Sabrina Dubroca Signed-off-by: Antonio Quartulli Signed-off-by: Greg Kroah-Hartman --- drivers/net/ovpn/tcp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) --- a/drivers/net/ovpn/tcp.c +++ b/drivers/net/ovpn/tcp.c @@ -151,7 +151,8 @@ err: /* take reference for deferred peer deletion. should never fail */ if (WARN_ON(!ovpn_peer_hold(peer))) goto err_nopeer; - schedule_work(&peer->tcp.defer_del_work); + if (!schedule_work(&peer->tcp.defer_del_work)) + ovpn_peer_put(peer); ovpn_dev_dstats_rx_dropped(peer->ovpn->dev); err_nopeer: kfree_skb(skb); @@ -283,7 +284,8 @@ static void ovpn_tcp_send_sock(struct ov * stream therefore we abort the connection */ ovpn_peer_hold(peer); - schedule_work(&peer->tcp.defer_del_work); + if (!schedule_work(&peer->tcp.defer_del_work)) + ovpn_peer_put(peer); /* we bail out immediately and keep tx_in_progress set * to true. This way we prevent more TX attempts