From patchwork Wed Feb 4 14:14:41 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ralf Lici X-Patchwork-Id: 4749 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:6911:b0:80a:3855:ce6a with SMTP id o17csp3124771map; Wed, 4 Feb 2026 06:16:22 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXDjC2JMjE49ADMwlVg0JWYyjRwV6y7GAAhsqWQ+h2wOIHSBLObgwO6/Y/Z2USI2D9gp99sXXi/11E=@openvpn.net X-Received: by 2002:a05:6870:400d:b0:40a:5f51:c9e5 with SMTP id 586e51a60fabf-40a5f522243mr824344fac.42.1770214582082; Wed, 04 Feb 2026 06:16:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1770214582; cv=none; d=google.com; s=arc-20240605; b=NxdoYqtxRttWdqt4Hng6XoNNT1IyfuJhUAGdiAXK+HnvWtuNU/MYPRG1rExbB4VDko 97DBJknvYpnX7px6/vzTg5VkTm2IFnZEhS0peiyNhw2HL/xn9WcNUfVKKfe0rOwAOFmz Z1j2UaQNOnALS5KjxCxqmuuDLjd2DdFQgD5Ea46yeXEIxCv5QgrjrAeD8XTSJEb1uOXl PrwiPs88UiQ1u4og3yeUY4jMUT0VCu0gAUB9oM0p8sUp5tDiaPSM+GYcKn56dR1XBxTK S/WV4NeTMmISSSYLdaQwVfy6LGn/TBM0cweb0B8edw1GkW9lCPnp3oOIZjh5/o6GF1ml R/HQ== 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=m5A2z005XoiORiCcmzdt8AMf+sW3xZxHeXfVDaSathc=; fh=bDmbXayvKcQuWZaaz4JM7kgnS3MJBk3QUq2ehqNuBVc=; b=DTKHzGjlVDdK1nWlWc9TOXDNnXDkuiqbyhvApLXUt4cE+hOSekxI9nzFJccErrbgM4 1/V5TNBm9C34WNutxaVOPNxMs18CWEeRkh37NofGkKMZCufhsxnDo2jp4C1zxvW+delu WyP722C93YOw/kjMiyAcD8a9dg8mGCSyaghoFbmYJLdgs8iXV+gzSIt/G+YvMTv50Ybg rii25rQLh5OEuhYObrwYY4Y+DpaG3eXLuLmJaforwxEOdqwb9+uRKUKXy8lDKY+kEuDn dsdoPg460A2vY9Jc6NVT+um9itCn6kOvUKp6UIZwtT4IrdNJgEwu/N5hcm/ur0sGbfM5 jbDg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=eQZisFdG; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Yc5kNsOp; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=Dw1qtsba; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=google header.b=KYD8+F5t; 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-40a545cb049si1897441fac.370.2026.02.04.06.16.21 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 04 Feb 2026 06:16:21 -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=eQZisFdG; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Yc5kNsOp; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=Dw1qtsba; dkim=neutral (body hash did not verify) header.i=@mandelbit.com header.s=google header.b=KYD8+F5t; 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=m5A2z005XoiORiCcmzdt8AMf+sW3xZxHeXfVDaSathc=; b=eQZisFdGP9kd9YWwasjAVL46sl FxoL8p+QxJhE/3GkYlRomrQxy0SAayiUdyW2zZz79TuTAy/mTTzw+WPmAs76+0cBczgPcHaP+5Juc S3oKj97t3i4z414JhXZuwIIo2twH2BqQD0sF/9dit7S6oHgv38oFPPMUlE5f30NEzqco=; Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1vndfw-0003t3-Bb; Wed, 04 Feb 2026 14:16:13 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1vndfu-0003sp-KJ for openvpn-devel@lists.sourceforge.net; Wed, 04 Feb 2026 14:16:11 +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=4jVD5okv43vV1yGjworwUEWoqxgOrQQFhNgQYxfTs6U=; b=Yc5kNsOpNAvjLJrd7N/KDKLphv 6Kx6fokfPLV0Wf9Iz+jsVnHTVyM/vxCvaMuF5FAB5++sAYWumPIyN3gMrC/H8WQidMvawVk7N+Bko b85ftaTrt3XYeluzgmhC3Pnx/scbt//rcDsEPg2357FhrDG6QjTOUEtai7sRokeOOToc=; 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=4jVD5okv43vV1yGjworwUEWoqxgOrQQFhNgQYxfTs6U=; b=D w1qtsbawnfXK/nx42C3sHJq+hbQ9/ii9DTBPR9LnI2pQAjJsp4wMgaNXb4H+fiQ+2gptf4lJ8PHjD yFWVQ3v2yEKWU0tt3gAon8gtzpr2P9h66mk5Lw9OTXkvMH2ol/uTYUHQJiecQBRaavvBuWRWy1zOk 5M8Wme5RtfL0odsk=; 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 1vndfu-0000w7-QP for openvpn-devel@lists.sourceforge.net; Wed, 04 Feb 2026 14:16:11 +0000 Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-47ee07570deso58783435e9.1 for ; Wed, 04 Feb 2026 06:16:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mandelbit.com; s=google; t=1770214564; x=1770819364; 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=4jVD5okv43vV1yGjworwUEWoqxgOrQQFhNgQYxfTs6U=; b=KYD8+F5tsnGiHpD9+fFBSOsv1npgCvLJPMdkrBlMOjrmxTdAcHrcLpdpdt6RfNeYBX ApcXILJE/T2sUgLv2tvGDjmqCnDXnSH2Dnp67JiJxQoNzlmjrVm5FYhZvwpRh+dh1alY e9X86Yh3E+k7IzfayQYVfBlUXLMx5X398KgTp9p/uVngG485LhfSmdCclzGkmdjYKN/R p5IuUujhYQ2/cvI/nV+DyJJ6CCDelHsI2/W5s7MoxTEXAR4Pjy4uLgpb2N7/TgSGEwUJ vazFYGPQ/IKf9ogVB5amIDEYZ57kYqYmkG4THpRjlavkbNmYgIDUy3pByL7cAUWa1nq7 Eq9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770214564; x=1770819364; 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=4jVD5okv43vV1yGjworwUEWoqxgOrQQFhNgQYxfTs6U=; b=tlBqC3rtyjUT0zkfgeN8eUxgyEWLatogUqHj9UmRUimJD5cR3f+wMMrKLLt3Px8oyi dH1l/1UFRQxuW8ZFqpnOsi9gdfMpp3WFDZlnSr7VprL5Pcym4KqvOipBG6CKzTIzjMuy sjmKJD7aXflbXvloWZ/DAm3+T2aQ3NBpbNdlO5BSFwapp9af0Vdru6eHtLMAjjjtlhhj 2F/MVo6XEObfgXMxdLz2xW4xclrf4AYUwOTVhPYldrF+kPjQp6sgZ8Z//Vx89lHe1BXG 6erXihI+OB/Fz1FR4srMAHyU3RqmMqGa0wXHfdQKG67+ACG9X9aI9ZYjy8S5CI29qkQu 5jdg== X-Gm-Message-State: AOJu0YwsPLIZaJhY5nrpfxct1V0KigtyQR2+50zaiZiLSqSQJefPtt4P /jJUtseAjNArI0rGOFG0pba6cmV2eA1zap5jCuW9g/O5hXV8NWWzZ3nL9unBirLe7Vrf1e3Wib2 LmeQ6 X-Gm-Gg: AZuq6aJROMAyhsaRIR3JU020h+Sv3RV6EkYpEQ74cLDbUlm7Aiw6z2k7E34dYlR2T2K MLolKbRcxSPk75121pQ7E2pbrradhnZ2gmAY3jy0/8+bsRW2YfT/fbroY9cQz47sq1SD3dPeoRh t0j//dTmMvt9GIXXt/GK22lctGM1rFI+bw2F3MvULoAZvxJ5wGqzIG/fgsULnmbAxLIye3RCL4w LKfM5ucaURytYDhd2AtUL/xYCXAx8qdJzl8Td5QtN8fExSl0+hjPcdaZ4/hzwmF0Y6BSF4KQsoy PDubLYFyWlx8zf9OBaWhXK6N9Yj+Cy0oRjNcxtYxjOiar84yEOrR0xBSJLFV5hVEt7dkSviXBU5 eHCRDoIDYy1m8/OpsdyAZOsK/VoZoT9RSi2VzSa2kPp4LnWBGgA6V4zlZ94LWZlMEupS4M6NU5X D58DY+Bg== X-Received: by 2002:a05:600c:820a:b0:46e:4586:57e4 with SMTP id 5b1f17b1804b1-4830e987d12mr47682485e9.24.1770214563430; Wed, 04 Feb 2026 06:16:03 -0800 (PST) Received: from fedora ([2a01:e11:600c:d1a0:3dc8:57d2:efb7:51a8]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4831088d318sm75877975e9.10.2026.02.04.06.16.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Feb 2026 06:16:03 -0800 (PST) From: Ralf Lici To: openvpn-devel@lists.sourceforge.net Date: Wed, 4 Feb 2026 15:14:41 +0100 Message-ID: <20260204141441.528655-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-2.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_VALID Message has at least one valid DKIM or DK signature 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_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: 1vndfu-0000w7-QP Subject: [Openvpn-devel] [PATCH ovpn net] 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?1856204525561934733?= X-GMAIL-MSGID: =?utf-8?q?1856204525561934733?= 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 --- 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..ffe8db69d76d 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); + *((__force __be16 *)__skb_push(skb, 2)) = cpu_to_be16(pkt_len); ovpn_tcp_to_userspace(peer, strp->sk, skb); return; }