From patchwork Thu Feb 5 15:10:36 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ralf Lici X-Patchwork-Id: 4751 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:6911:b0:80a:3855:ce6a with SMTP id o17csp3839480map; Thu, 5 Feb 2026 07:11:08 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCUSN9HlaqexfKjTXltBf7ADNHW76RAgRbXgIllIf0e+REY0j51SBxJZi0NxiUnZLA8YXnhsvKWwfDE=@openvpn.net X-Received: by 2002:a05:6808:4f0e:b0:45e:69af:6bc6 with SMTP id 5614622812f47-462d587c56amr3371734b6e.13.1770304267749; Thu, 05 Feb 2026 07:11:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1770304267; cv=none; d=google.com; s=arc-20240605; b=Z3L4kE+DC1B/NXJr/K/Jw45jpE0UGaFh/znKZ2Q5psAkwe9y+SY/L95brxvpH7idvf AKfgeQOLDjp9YuyJ84bomje3JKjbP5qqTpB3gOAumkuj8+dW6xl8TjZvIIGohPiLD0zg ustts+Cj2H/ceY3SSn5aCkdXgUFpqawKZALHmunJ7vwYPUIHYxfTb+lbWxJji3DODzUz 48bdwa16k8z7tjgkImpDb2d2CAmpvm9FTC3Yg/EZv1fwHRnDz0u5Gvn5v7AKNLBX/Tn7 ueFkuONL/DOmBbZXYYIsY0jInyjYO8WaEeLTZllLFWzJDk7MMshyv5lIqC44v/UjcWz7 if+A== 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:message-id:date:to:from:dkim-signature:dkim-signature :dkim-signature:dkim-signature; bh=Wc1LFVMZ/IL7Kq0wAzfWnnPXSMxCHwyimz77dsDuMZk=; fh=bDmbXayvKcQuWZaaz4JM7kgnS3MJBk3QUq2ehqNuBVc=; b=O2+a6F7cRBwEKFkM0jxZBMML9cysJkxe4GyIWJWXD+KeysAcQPR+LV6y58iB0km12Q N0Lo8lymHgFMlXeVGf8aNX/RARnwvgTM4eAsTp5se3cFlCBxx0frjA8MIwblxrLmd3d9 4naxCS5+cpbm6nmQWsl7d7afULq+QpLKh5bL66kdz05mJocGagloBXWYkYfcppckKuzb MaIBv31EzsrW8wh39e8O18vNiQmuDeQ1jD9wFq+/hBjscAhNP+Y8vH5rIt1WEX9b9yHC rL5y0VRpMC58jEaX3sSuL6cdEv6e0Bh6WF++ZwVpDsO2tPbKJlVhERT7fu3jYL6L3/8V qlNg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b="Qr/oNhCI"; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Se0ncZJd; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=HzzVeIuo; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=google header.b=HklMBYNX; 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; dara=neutral header.i=@openvpn.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 586e51a60fabf-40a544a4be0si4517962fac.132.2026.02.05.07.11.07 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 05 Feb 2026 07:11:07 -0800 (PST) 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="Qr/oNhCI"; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Se0ncZJd; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=HzzVeIuo; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=google header.b=HklMBYNX; 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; dara=neutral header.i=@openvpn.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: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:In-Reply-To:References:List-Owner; bh=Wc1LFVMZ/IL7Kq0wAzfWnnPXSMxCHwyimz77dsDuMZk=; b=Qr/oNhCISLVrkbP3E7K/sQNr0/ cy0yMx5uyagoDb5Ra3mqFkls8Jue2rpFudIP60/5gEYbTTc3Mg7PgPdDALujW22PBMCW6+eLS7O0h rirtRoOkp7Vy5NPZHO2V1bnYLi5Ggn7SknFpBbacDThwlLOXpbFwsEjAviSSmak9wkK8=; 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 1vo10U-0001yh-GT; Thu, 05 Feb 2026 15:10:58 +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 1vo10T-0001yY-0W for openvpn-devel@lists.sourceforge.net; Thu, 05 Feb 2026 15:10:57 +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: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:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=IK3OTHNhsFcpgnb2QwtWj0MCBQGdeH2jZtf+GXhEugU=; b=Se0ncZJdCGGgNJDT8ekt9Z6ZNX 6NxgqjO6294yL6By2K9lTM0M5wAPHmPVObj5bVZ6EZe+zkIG72MlSDio+CL/HCffY0VTa/9mrD4po VuAFPtfkI5Y0+MBcqRCgtvoYZrFgg1Kz5FLjTO1Dwc+thWJP92VFw7eMZeZX0ibEpq2U=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version: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:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=IK3OTHNhsFcpgnb2QwtWj0MCBQGdeH2jZtf+GXhEugU=; b=H zzVeIuoV6T70cmcpnMaNaTHj2VX5gAxNGnyi0HsNrqofgNkBpt1FtzqSJ0uC49SqwgRV43HLEn2Jr gNjmPnWIrxnlKFs68/IlF0tIbpmrdgbQyBmqi19GqBBNlxyKXavV7DAH65xIxBvrNwtkZbJ2+YAtK 3GZbMCox1xiE6wdk=; Received: from mail-wm1-f41.google.com ([209.85.128.41]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.95) id 1vo10S-0003Nc-5p for openvpn-devel@lists.sourceforge.net; Thu, 05 Feb 2026 15:10:56 +0000 Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-47edd6111b4so11854365e9.1 for ; Thu, 05 Feb 2026 07:10:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=google; t=1770304244; x=1770909044; darn=lists.sourceforge.net; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=IK3OTHNhsFcpgnb2QwtWj0MCBQGdeH2jZtf+GXhEugU=; b=HklMBYNX8Epu6J0LbQf3RLvwgjDBiuSt8BuDL9CpLSGVLHKk9eg9+C8BDvFJKfo4zg Xbq5qdK2+7XOzXfNWOFSR0wlhGSWPQTs9JzrTHafUSUMe38w8gnbDnyLYpN3p8RQ9CZM wqLPsnpTx2/qhseldhc0jrYK6IF8alPcO/w27SiRJ8fsPsIl3t6bOb0iY/s9IGqcUpTS YyIqrkr8RpYsbIo7T7hlGrnzRf7yucrWEzCf/I4TPv/wsILwxb0Pdh7/1G0/Tr4mStSz FCCaELW9jRpCPAaalFVL9nBlS9Y76lOithgGqSa/qlAy+2BKDuSlC7HJ3xxfeACiBubm Ef2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770304244; x=1770909044; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=IK3OTHNhsFcpgnb2QwtWj0MCBQGdeH2jZtf+GXhEugU=; b=iFdqddTNJsjhAp11eoVM/2Sof/LRLTbwMBO59QWYTGr7oRf5Lm3hRvT4Y+5yLq+10T sNko+z99oX4p/tEXgqp1iId4/o+JrD6+6NSt1C3HNU6CRl3WE/3i3kzUgHwkdo1bS7pL P1gWQFoGRAtCWXM4tL4D5ttj1QIq6bMeKhhzahtxNQhfToANiIkvcoo0+m36b7GV1fUi 9V+To9KG+acNnqij95PQl5cx0cWD4NaZL00pwxSEBgjS0YLo5d8ijc8HjFjJfa/wNdUT BwQryZn1A11w/R3cYgOk5WJIpaOaEdBHf5VKQnEkJWR8olE/2RmbymUWBkj54Ee3/Nq3 kS6w== X-Gm-Message-State: AOJu0YyER9pcYA0xLIBEOEke13BlkDSc/mzqzfY6zi3A6TXhGM6Tva5m j0k0H/yqHrRSUVPPdupxr4kD+qmJWW8K80pfheQqMuZVaWsyiyF6lNgHSdjOwyZ2KNJEu50gXQ9 Uhi4F X-Gm-Gg: AZuq6aJ0sagzHj/JtE2m1zQXmAa91UxBU3gyL+iRRE6k8DvdMrnB/7y6VyrLvwOA0Lf sbjQcaJReAIYFSLkZCwg01gsfIrsRG7UroaT7AfiGKH02nkFskjjSUv2vV0kJeKZnpKJm+94+zc SXdwK2eNjRNRakCWJ9nF405T+PerF5zJiE1XPpuiFI58AJ2D4qddRShSM2MKSTzgc6smZzkS5/k r3DclyMPteT1K5l8jDvvcc0aeMUxISmo60zGEn78yeRQ7RlZR8DnUKdllrOvRv84ZnOsqtUgA2x O6ZE+OjFNyvHeF7hNlu06hqqGamfKJyZAeZDyaDua2UckMJI+v7zmNp6GLYMi+WHG4M06niNhxv iO8eRXgNC0rpz+AcDbDlDWOSyKLssIXsQgHxyEjOftL/X6CzoYT+VG0kTDhGNzS25eXfY58zA0B WHq00N/g== X-Received: by 2002:a05:600c:630a:b0:480:3a72:5238 with SMTP id 5b1f17b1804b1-4830e98ad35mr107007825e9.30.1770304244272; Thu, 05 Feb 2026 07:10:44 -0800 (PST) Received: from fedora ([2a01:e11:600c:d1a0:3dc8:57d2:efb7:51a8]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4830fc1744dsm96012495e9.2.2026.02.05.07.10.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Feb 2026 07:10:43 -0800 (PST) From: Ralf Lici To: openvpn-devel@lists.sourceforge.net Date: Thu, 5 Feb 2026 16:10:36 +0100 Message-ID: <20260205151036.743792-1-ralf@mandelbit.com> X-Mailer: git-send-email 2.52.0 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: When processing TCP stream data in ovpn_tcp_recv, we receive large cloned skbs from __strp_rcv that may contain multiple coalesced packets. The current implementation has two bugs: 1. Header offset overflow: Using pskb_pull with large offsets on coalesced skbs causes skb->data - skb->head to exceed the u16 storage of skb->network_header. This causes skb_reset_network_header to f [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.128.41 listed in wl.mailspike.net] X-Headers-End: 1vo10S-0003Nc-5p Subject: [Openvpn-devel] [PATCH ovpn net v2] ovpn: tcp - fix packet extraction from stream 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: Sabrina Dubroca Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1856298567752016949?= X-GMAIL-MSGID: =?utf-8?q?1856298567752016949?= When processing TCP stream data in ovpn_tcp_recv, we receive large cloned skbs from __strp_rcv that may contain multiple coalesced packets. The current implementation has two bugs: 1. Header offset overflow: Using pskb_pull with large offsets on coalesced skbs causes skb->data - skb->head to exceed the u16 storage of skb->network_header. This causes skb_reset_network_header to fail on the inner decapsulated packet, resulting in packet drops. 2. Unaligned protocol headers: Extracting packets from arbitrary positions within the coalesced TCP stream provides no alignment guarantees for the packet data causing performance penalties on architectures without efficient unaligned access. Additionally, openvpn's 2-byte length prefix on TCP packets causes the subsequent 4-byte opcode and packet ID fields to be inherently misaligned. Fix both issues by allocating a new skb for each openvpn packet and using skb_copy_bits to extract only the packet content into the new buffer, skipping the 2-byte length prefix. Also, check the length before invoking the function that performs the allocation to avoid creating an invalid skb. If the packet has to be forwarded to userspace the 2-byte prefix can be pushed to the head safely, without misalignment. As a side effect, this approach also avoids the expensive linearization that pskb_pull triggers on cloned skbs with page fragments. In testing, this resulted in TCP throughput improvements of up to 74%. Fixes: 11851cbd60ea ("ovpn: implement TCP transport") Signed-off-by: Ralf Lici --- Changes since v1: - updated the __skb_push usage for consistency with similar operations, such as in ovpn_tcp_send_skb drivers/net/ovpn/tcp.c | 53 ++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/drivers/net/ovpn/tcp.c b/drivers/net/ovpn/tcp.c index b7348da9b040..3fb33f20c872 100644 --- a/drivers/net/ovpn/tcp.c +++ b/drivers/net/ovpn/tcp.c @@ -70,37 +70,56 @@ static void ovpn_tcp_to_userspace(struct ovpn_peer *peer, struct sock *sk, peer->tcp.sk_cb.sk_data_ready(sk); } -static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb) +static struct sk_buff *ovpn_tcp_skb_packet(const struct ovpn_peer *peer, + struct sk_buff *orig_skb, + const int pkt_len, const int pkt_off) { - struct ovpn_peer *peer = container_of(strp, struct ovpn_peer, tcp.strp); - struct strp_msg *msg = strp_msg(skb); - size_t pkt_len = msg->full_len - 2; - size_t off = msg->offset + 2; - u8 opcode; + struct sk_buff *ovpn_skb; + int err; - /* ensure skb->data points to the beginning of the openvpn packet */ - if (!pskb_pull(skb, off)) { - net_warn_ratelimited("%s: packet too small for peer %u\n", - netdev_name(peer->ovpn->dev), peer->id); + /* create a new skb with only the content of the current packet */ + ovpn_skb = netdev_alloc_skb(peer->ovpn->dev, pkt_len); + if (unlikely(!ovpn_skb)) goto err; - } - /* strparser does not trim the skb for us, therefore we do it now */ - if (pskb_trim(skb, pkt_len) != 0) { - net_warn_ratelimited("%s: trimming skb failed for peer %u\n", + skb_copy_header(ovpn_skb, orig_skb); + err = skb_copy_bits(orig_skb, pkt_off, skb_put(ovpn_skb, pkt_len), + pkt_len); + if (unlikely(err)) { + net_warn_ratelimited("%s: skb_copy_bits failed for peer %u\n", netdev_name(peer->ovpn->dev), peer->id); + kfree_skb(ovpn_skb); goto err; } - /* we need the first 4 bytes of data to be accessible + consume_skb(orig_skb); + return ovpn_skb; +err: + kfree_skb(orig_skb); + return NULL; +} + +static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb) +{ + struct ovpn_peer *peer = container_of(strp, struct ovpn_peer, tcp.strp); + struct strp_msg *msg = strp_msg(skb); + int pkt_len = msg->full_len - 2; + u8 opcode; + + /* we need at least 4 bytes of data in the packet * to extract the opcode and the key ID later on */ - if (!pskb_may_pull(skb, OVPN_OPCODE_SIZE)) { + if (unlikely(pkt_len < OVPN_OPCODE_SIZE)) { net_warn_ratelimited("%s: packet too small to fetch opcode for peer %u\n", netdev_name(peer->ovpn->dev), peer->id); goto err; } + /* extract the packet into a new skb */ + skb = ovpn_tcp_skb_packet(peer, skb, pkt_len, msg->offset + 2); + if (unlikely(!skb)) + goto err; + /* DATA_V2 packets are handled in kernel, the rest goes to user space */ opcode = ovpn_opcode_from_skb(skb, 0); if (unlikely(opcode != OVPN_DATA_V2)) { @@ -113,7 +132,7 @@ static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb) /* The packet size header must be there when sending the packet * to userspace, therefore we put it back */ - skb_push(skb, 2); + *(__be16 *)__skb_push(skb, sizeof(u16)) = htons(pkt_len); ovpn_tcp_to_userspace(peer, strp->sk, skb); return; }