From patchwork Tue May 26 23:18:46 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 4980 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:4ec9:b0:861:c897:cb9d with SMTP id i9csp36360mas; Tue, 26 May 2026 16:19:37 -0700 (PDT) X-Forwarded-Encrypted: i=2; AFNElJ8rfZSrsrpoliE6atFm5VatCE0HxjEWX1o8qtpNuQJuvuJ21Cg3TgbVYU61JF979p6SXK4PZ3MAMIg=@openvpn.net X-Received: by 2002:a05:6820:611:b0:69d:a4a5:4467 with SMTP id 006d021491bc7-69da4a54e9fmr8019032eaf.43.1779837577745; Tue, 26 May 2026 16:19:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1779837577; cv=none; d=google.com; s=arc-20240605; b=auvWry/4qPQ95fBfdWcfqz5QrN/SZasO6gMmA8wR5NyDK8e3U4APDEx9FRgPIolp4z fH+zK35SlhEs5GfTSQKc9dey1jmj5s6TQOtlvT1Wt9LaWLzL20NZ9+yPGwQRbhldVjlx QVFJXn1uv16jGXTi5WPk/Rqzck5WhY0eprzDampYpgxikVf/0tzXM6rR8y57rtD2Zn7l 16f73P28hMrPtiTHgIOYLL6B2OZlJ0mDvtwlo+UCllXVk73MeWxw8e2r8D9Q3Hiz9Bj1 BnFsYLLYk8InAJTLJgm6sDr/vojvLFMQ7iyBUI8RWDgnwkNZ3XR4m8N3oYnReR5FyBWk N4YQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:content-transfer-encoding:cc:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature:dkim-signature; bh=mL4bJ+LSxd0VnrN4IeDEMjQG0xGPmibO1kB+/h5XxZQ=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=hLqGth6WNWTThFvIG3t+83AokDhlU+5Zt0Q/jJD6TPKsygykqspdQBXJxjlbxZ5Pyx wN9nCIg2sEAdoXwRkxkWoua88jPRZyxbhITFcTIgLo9BlxI0MzBVdV1yU4x3vdiRU7Wi nH3/KN5/JEr1g2h/y0IAKapa3IK+XuTXCrmL+60NRSeSGkOuVmfe7Bl5xOxaQYOj1wD7 CqeWvatWDAsdQUhaHaeM5J7Yp61RZfI4utc8kS6oG+ys5PCX5qm5008IESkkmgIudllB v8nkCOgGVZzSwvu1PR2RpLTBDjSYssVRP8Guupm9/e6zmfGKc39SXWmhi6Kby9TuxtQ7 R7mw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=DYk3n9rB; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=hsSH4ftg; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=b6YhAkiP; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=bsVIT0Pg; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 006d021491bc7-69d83d01739si8340704eaf.77.2026.05.26.16.19.37 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 May 2026 16:19:37 -0700 (PDT) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=DYk3n9rB; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=hsSH4ftg; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=b6YhAkiP; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=bsVIT0Pg; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type:Cc: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=mL4bJ+LSxd0VnrN4IeDEMjQG0xGPmibO1kB+/h5XxZQ=; b=DYk3n9rBbp049ZMs15DliaK4k2 +tnRc9iiY9AHFjxiUWeSZCbKlecZ/E6fpvSqVLCsS12+Dait708Go+XoIHR0Work5bIboAyISoNS5 Hc051cTGdBieWsiEQyZWNCa8++jrAfMKKH1Axk9M0oDF8+vquYFOOVFpN7dKVR2AKeNY=; Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1wS13Z-0007KZ-Sf; Tue, 26 May 2026 23:19:29 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1wS13X-0007Jv-Do for openvpn-devel@lists.sourceforge.net; Tue, 26 May 2026 23:19:27 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=3SO51xGxkJt8zJ1G/O5z8R+QSQzRGqAq8QHjtl6WKcA=; b=hsSH4ftghTETr7bw1nzK0kSjOF dUhn/SckAFupubDzbsVY+3HEt0MGfHrrthe+QceiSnkbvl/UV/6jN4LIySAlG3OH7AuO2ZOF+1W+G eCxXQ6yacOCX/BEsZ4tVtel0E3EVq/1tbPxWy5PgnOzDdwpqFGKT8t7SFD05KDSqocfI=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=3SO51xGxkJt8zJ1G/O5z8R+QSQzRGqAq8QHjtl6WKcA=; b=b6YhAkiPXi1YjvmZw+1+YnuXY7 SMtUowefuqHm2+2Y3jNe7PMwhRenap8U0rOYuUPrFR9EqF1nUeT2v2X417itQ0MwFi1mtxuM7354z qyx139SDjdAbN3h4bYmLstZnI7yv1EX78DMbToqWv6Vg+Mul6Y/azMN029dW/ML+6Vec=; Received: from mout-p-101.mailbox.org ([80.241.56.151]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wS13H-0000TX-0X for openvpn-devel@lists.sourceforge.net; Tue, 26 May 2026 23:19:12 +0000 Received: from smtp102.mailbox.org (smtp102.mailbox.org [10.196.197.102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4gQ7wy5k5vz9tht; Wed, 27 May 2026 01:18:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unstable.cc; s=MBO0001; t=1779837538; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3SO51xGxkJt8zJ1G/O5z8R+QSQzRGqAq8QHjtl6WKcA=; b=bsVIT0PgSIPUvJH6JjKkahUJWaJxVevIVr2l3LK9TzBpa9cB2BBzpQVF8j4wiaNSpN+Zsq H0dDnQlkg5b3BSv9bCdjMZDzBCawHv4krn9S2CeG+U0qWm/nbccyRTYoPiew3EV6FKnRTF Fyixb25ZMMzjWwHNdjM/Xf1zJCEgAFig96Dg6T7wBvt87bMgqtFTQAy5je8DOIGEjV/R1C NaLa/N0uUKK4s8NxRBO0SqInT3SqQxgHYSc3KZ9UXMHk9z6klQ8Pw7NKL75FzqCjYTaat8 ZYR3DL8n7kaGh1bsEauCZCYezmtXlp0JJWPOE/JiVpVlTFlzk2tfNf+psGRi9Q== From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Wed, 27 May 2026 01:18:46 +0200 Message-ID: <20260526231850.2511369-5-a@unstable.cc> In-Reply-To: <20260526231850.2511369-1-a@unstable.cc> References: <20260526231850.2511369-1-a@unstable.cc> MIME-Version: 1.0 X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-1.hosts.colo.sdot.me", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Antonio Quartulli The TCP error paths in ovpn_tcp_rcv() and ovpn_tcp_send_sock() take a peer reference and then schedule the deferred-delete work: ovpn_peer_hold(peer); schedule_work(&peer->tcp.defer_del_work); Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-Headers-End: 1wS13H-0000TX-0X Subject: [Openvpn-devel] [PATCH ovpn net 5/9] ovpn: tcp - fix peer reference leak on deferred deletion X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: 1866294968311535815 X-GMAIL-MSGID: 1866294968311535815 From: Antonio Quartulli The TCP error paths in ovpn_tcp_rcv() and ovpn_tcp_send_sock() take a peer reference and then schedule the deferred-delete work: ovpn_peer_hold(peer); schedule_work(&peer->tcp.defer_del_work); ovpn_tcp_peer_del_work() drops exactly one reference per run, but schedule_work() returns false and does not re-queue when the work is already pending. The reference, however, was taken unconditionally, so every hold+schedule that lands on an already-pending work leaks one peer reference. ovpn_tcp_rcv() is the strparser receive callback and has no guard against this: a TCP segment packed with packets whose length header is valid for the stream parser but whose payload is smaller than the opcode size passes ovpn_tcp_parse() and hits the error path. strparser delivers all complete messages in a loop, so many error invocations run before the scheduled work executes, leaking one reference each. A remote peer can exploit this to pin the peer (and the netdev reference it holds) forever, preventing interface teardown - a denial of service. Take the reference only when schedule_work() actually queues the work. schedule_work() flips the work pending bit atomically, so exactly one caller - even across the concurrent RX and TX paths - observes the idle->pending transition and acquires the single reference that the lone ovpn_peer_put() in the worker balances. ovpn_peer_del() is idempotent (ovpn_peer_remove() bails on an already-unhashed peer), so a work item re-queued while running stays refcount-balanced. Fixes: 11851cbd60ea ("ovpn: implement TCP transport") Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/tcp.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/net/ovpn/tcp.c b/drivers/net/ovpn/tcp.c index 433bd07a4f1b..6cf684699ada 100644 --- a/drivers/net/ovpn/tcp.c +++ b/drivers/net/ovpn/tcp.c @@ -148,10 +148,14 @@ static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb) ovpn_recv(peer, skb); return; 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); + /* schedule deferred peer deletion and take a reference only if the + * work was actually queued: the matching ovpn_peer_put() in + * ovpn_tcp_peer_del_work() runs once per queued work, so re-arming an + * already-pending work must not take another reference (it would be + * leaked, e.g. on a flood of invalid packets) + */ + if (schedule_work(&peer->tcp.defer_del_work)) + ovpn_peer_hold(peer); ovpn_dev_dstats_rx_dropped(peer->ovpn->dev); err_nopeer: kfree_skb(skb); @@ -280,15 +284,20 @@ static void ovpn_tcp_send_sock(struct ovpn_peer *peer, struct sock *sk) peer->id, ret); /* in case of TCP error we can't recover the VPN - * stream therefore we abort the connection + * stream therefore we abort the connection. + * + * Take a reference only if the work was actually + * queued: ovpn_tcp_peer_del_work() drops exactly one + * reference per run, so re-arming an already-pending + * work (e.g. already scheduled from the RX path) must + * not take another reference (it would be leaked). */ - ovpn_peer_hold(peer); - schedule_work(&peer->tcp.defer_del_work); + if (schedule_work(&peer->tcp.defer_del_work)) + ovpn_peer_hold(peer); /* we bail out immediately and keep tx_in_progress set - * to true. This way we prevent more TX attempts - * which would lead to more invocations of - * schedule_work() + * to true, so that no further TX is attempted on the + * aborted stream */ return; }