From patchwork Tue Jul 28 11:48:47 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 5140 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:fd0b:b0:87d:ab56:3700 with SMTP id cw11csp485500mac; Tue, 28 Jul 2026 04:49:17 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+RonJknnaUrnMl0w+0whE4g0MWj1UgYH5ZllQWwbhlNFwf8KNRwSNKGhTUFsjHCXXNQHhDPCqf4TAm8=@openvpn.net X-Received: by 2002:a05:6830:81ec:b0:7e9:da5e:93f7 with SMTP id 46e09a7af769-7efff2c3c29mr1160425a34.26.1785239357554; Tue, 28 Jul 2026 04:49:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1785239357; cv=none; d=google.com; s=arc-20260327; b=kUxB5/amk4PcC43PI6RJzhI4GzBYeRIKr0eE3V/EN83wpnUuaFw0y/r38d8PDDcp1r VCchELkI++bgL8Oo+UCMQkYlnQLvb5/tRWFvpAQpPmmEal3j12xxJpm8WvuocDX6jBmF I4aRkjfXQIVBjAY5FDYqDp9wTL0CvuDEcRajq/1d9vSZ1g50Z01SuOrmSdOQgLB17m2o 96HWprNVOK0MNuvzpfSJpt8x8WGBBNE8Wx0u42ZzJxC81tRqm7zbJXzqCx3/q64flCLx WLuUoyun15PaEcXZzD7lfb/00zCYCjTH+I2hweS5UV6xnt8WNR2sue1sIyF2mZHw+TOI 0FgA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; 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=4JI7XNkscyUSBkFxU8QJIaqodb34DsucJL7LCK2HePQ=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=recsIqJ+cYl8uonxTfNwhvJR/cfIKYjXOHvYlSTB0IW+WwS1SaB3qw0g0LgcIPX4Uh 6GeNfBhC6AIQOi/dJ3L6RpJ7EWXjr5uvx9+8yVgtlUvh0pMVHjHjxe/F2qiYFcsp4s1P 2UvJtdGiPLJ80NqOjVQJiCG7S+3MMwoQIFyU2Rzc/zWl6syJ0S804uXQoE2YVNyfAxro rbwL/HVuTGvk6MvKiqb4KiHxsfKtZWaQL1i4zBSoWS+k4IVaSjvAWUsm3qLGJ+kutGnF iZNyZ91+XyrxjQZpPNhkCU3sugo7lzCOjzRboSpDKQhLlNJp1iYJ9+dRUtJARVL/OuaX dQBQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=Qipb2ScD; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=e+5Ep7NB; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=APMGQGnp; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=Fg4PMUav; 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 46e09a7af769-7ee49c3765asi12520491a34.61.2026.07.28.04.49.17 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jul 2026 04:49:17 -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=Qipb2ScD; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=e+5Ep7NB; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=APMGQGnp; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=Fg4PMUav; 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=4JI7XNkscyUSBkFxU8QJIaqodb34DsucJL7LCK2HePQ=; b=Qipb2ScDaj370sJGxZowuH+ZCd DRMOc4nf8piXu7EOsSINMDs57SryM+C1T/TyblXRb8bwGHDBjaFe1exfru9ij1kPZ/j7hwhMQQi7M hhHSJSt1jGqQljAHb9X4f9X4qjf2HU+q32vgWhF2WBcYIksWN9AzaiI7EWUSrQq/RQ9s=; 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 1wogJ6-0002oD-PZ; Tue, 28 Jul 2026 11:49:12 +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 1wogJ5-0002o4-7u for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49: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: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=tRaDtzA/BJj2zwxV9t0k38HHdjtHPPreMlLZlmWrfj4=; b=e+5Ep7NBXW95fLRn11aiXK9R9x fNKV3jdeDAh4rYbWfNXqJnREdfx2dHu1ra68mvjRaVZ6NcH0cQwUmRRX4oS3oskOMjTSU+GZ6BelH cTDSeE1vx9Ixw9AbDIFLwPR4LYYgcb1L0Jq3QKA8AtOFtj0BFSgxhymMy3q2lKWPIj4w=; 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=tRaDtzA/BJj2zwxV9t0k38HHdjtHPPreMlLZlmWrfj4=; b=APMGQGnpJJTxJqRjZ5qjxDiYga iCxSkVYaRYW8HGillYpBw7mJGw7jkU2aV2S78XsweatArO3WwEXnGAkUTORSbVj+5ts9tYBZy0cdc 0p8VLpwPHuigWsZdITtjnAIhqszSfo8BDH3qleiqqJT0KEKfCuGHCoFM0SC9DYh/S6vs=; Received: from mout-p-201.mailbox.org ([80.241.56.171]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wogJ7-0003Bi-7X for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:11 +0000 Received: from smtp1.mailbox.org (smtp1.mailbox.org [IPv6:2001:67c:2050:b231:465::1]) (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-201.mailbox.org (Postfix) with ESMTPS id 4h8Ydn6CNLzMlKT; Tue, 28 Jul 2026 13:49:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unstable.cc; s=MBO0001; t=1785239341; 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=tRaDtzA/BJj2zwxV9t0k38HHdjtHPPreMlLZlmWrfj4=; b=Fg4PMUavj9XbqjgTlU4KvyycExXg2eGInSsBBohkLacnXA3tW1Md3sdU0+RsfHEFNe5sIw 7lVnYap7Djg+QJci0YZta0yJZWPZwgRvrHTCBZ70wfPpf0qf/rzZ5fVK2ueYnxcq/XlKTF KQvkMz2fHwzxaiSmuaWftcf1A85lQSbBSafwmye30hRJKcOlVsKtFBwr7QX/ZouqPpf4DA ejx/8IeXJ/HaUNeLCKbWCSMQJzquVekh+snVq5ACAJtp8w5sRrBUTECA8kYYnkIzWpWdXy WioOWl1fS3YyCXWHVHf1gTMNTxfcN1DuvfVnrXgKaFI3w8MylvG0kqFjLwMfeA== Authentication-Results: outgoing_mbo_mout; dkim=none; spf=pass (outgoing_mbo_mout: domain of a@unstable.cc designates 2001:67c:2050:b231:465::1 as permitted sender) smtp.mailfrom=a@unstable.cc From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 28 Jul 2026 13:48:47 +0200 Message-ID: <20260728114855.1323861-2-a@unstable.cc> In-Reply-To: <20260728114855.1323861-1-a@unstable.cc> References: <20260728114855.1323861-1-a@unstable.cc> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4h8Ydn6CNLzMlKT 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 ovpn_nl_peer_set_doit() resolves the target peer via ovpn_peer_get_by_id() before taking ovpn->lock. In the window between the lookup (which only takes a refcount) and the subsequent spin_lock_bh(&ovp [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.0 RCVD_IN_MSPIKE_H5 RBL: Excellent reputation (+5) [80.241.56.171 listed in wl.mailspike.net] 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-Headers-End: 1wogJ7-0003Bi-7X Subject: [Openvpn-devel] [PATCH ovpn net v4 1/9] ovpn: skip rehash for peers already removed from by_id 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: 1871959144773960165 X-GMAIL-MSGID: 1871959144773960165 From: Antonio Quartulli ovpn_nl_peer_set_doit() resolves the target peer via ovpn_peer_get_by_id() before taking ovpn->lock. In the window between the lookup (which only takes a refcount) and the subsequent spin_lock_bh(&ovpn->lock), a concurrent OVPN_CMD_PEER_DEL, keepalive expiry, or socket teardown can take ovpn->lock first, run ovpn_peer_remove() to unhash the peer from all four tables (by_id, by_vpn_addr4/6, by_transp_addr) and release the lock. set_doit then acquires ovpn->lock and calls ovpn_peer_hash_vpn_ip(), which re-inserts the now-removed peer back into the rehashing tables. The same race affects the float path: ovpn_peer_endpoints_update() holds only a refcount and acquires ovpn->lock very late (after async AEAD decrypt and a netlink notification), then rehashes the peer in the by_transp_addr table. The resurrected peer becomes reachable again from the RX lookup (ovpn_peer_get_by_transp_addr) and the TX VPN-IP lookup, even though userspace believes it is gone. Once the data-path refcount drops the peer is freed via call_rcu while the hash entries embedded in it remain linked, opening a UAF window. Bail out of the rehash when hash_entry_id is unhashed, mirroring the sentinel already used by ovpn_peer_remove() to detect the already-removed state. The check is safe under ovpn->lock, which serializes every mutation of hash_entry_id, and is a no-op for the add path because ovpn_peer_add_mp() inserts hash_entry_id before calling ovpn_peer_hash_vpn_ip(). Fixes: 1d36a36f6d53 ("ovpn: implement peer add/get/dump/delete via netlink") Signed-off-by: Antonio Quartulli --- Changes since v1: * simplified flow in ovpn_peer_endpoints_update() and introduced new unlock2 label --- drivers/net/ovpn/peer.c | 73 ++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c index a21d02ac715e..68021c0c1783 100644 --- a/drivers/net/ovpn/peer.c +++ b/drivers/net/ovpn/peer.c @@ -297,40 +297,46 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb) /* rehashing is required only in MP mode as P2P has one peer * only and thus there is no hashtable */ - if (peer->ovpn->mode == OVPN_MODE_MP) { - spin_lock_bh(&peer->ovpn->lock); - spin_lock_bh(&peer->lock); - bind = rcu_dereference_protected(peer->bind, - lockdep_is_held(&peer->lock)); - if (unlikely(!bind)) { - spin_unlock_bh(&peer->lock); - spin_unlock_bh(&peer->ovpn->lock); - return; - } + if (peer->ovpn->mode != OVPN_MODE_MP) + return; - /* This function may be invoked concurrently, therefore another - * float may have happened in parallel: perform rehashing - * using the peer->bind->remote directly as key - */ + spin_lock_bh(&peer->ovpn->lock); + spin_lock_bh(&peer->lock); + bind = rcu_dereference_protected(peer->bind, + lockdep_is_held(&peer->lock)); + if (unlikely(!bind)) + goto unlock2; - switch (bind->remote.in4.sin_family) { - case AF_INET: - salen = sizeof(*sa); - break; - case AF_INET6: - salen = sizeof(*sa6); - break; - } + /* peer may have been concurrently removed between the caller's + * initial lookup and our acquisition of ovpn->lock; skip the + * rehash so we don't re-insert a removed peer + */ + if (unlikely(hlist_unhashed(&peer->hash_entry_id))) + goto unlock2; - /* remove old hashing */ - hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr); - /* re-add with new transport address */ - nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr, - &bind->remote, salen); - hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead); - spin_unlock_bh(&peer->lock); - spin_unlock_bh(&peer->ovpn->lock); + /* This function may be invoked concurrently, therefore another + * float may have happened in parallel: perform rehashing + * using the peer->bind->remote directly as key + */ + + switch (bind->remote.in4.sin_family) { + case AF_INET: + salen = sizeof(*sa); + break; + case AF_INET6: + salen = sizeof(*sa6); + break; } + + /* remove old hashing */ + hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr); + /* re-add with new transport address */ + nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr, + &bind->remote, salen); + hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead); +unlock2: + spin_unlock_bh(&peer->lock); + spin_unlock_bh(&peer->ovpn->lock); return; unlock: spin_unlock_bh(&peer->lock); @@ -906,6 +912,13 @@ void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer) if (peer->ovpn->mode != OVPN_MODE_MP) return; + /* peer may have been concurrently removed between the caller's + * initial lookup and our acquisition of ovpn->lock; skip the + * rehash so we don't re-insert a removed peer + */ + if (hlist_unhashed(&peer->hash_entry_id)) + return; + if (peer->vpn_addrs.ipv4.s_addr != htonl(INADDR_ANY)) { /* remove potential old hashing */ hlist_nulls_del_init_rcu(&peer->hash_entry_addr4); From patchwork Tue Jul 28 11:48:48 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 5145 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:fd0b:b0:87d:ab56:3700 with SMTP id cw11csp485534mac; Tue, 28 Jul 2026 04:49:19 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+RpOLfojxc36WSqsM82fnwKqiytBqmJXpWAijvHICncGGiXeJMCxE2jlRwf99U482CVmu4cJ8UQbDRA=@openvpn.net X-Received: by 2002:a05:6808:14c9:b0:497:d0ea:7dad with SMTP id 5614622812f47-4ad5bb47759mr1487143b6e.22.1785239359517; Tue, 28 Jul 2026 04:49:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1785239359; cv=none; d=google.com; s=arc-20260327; b=ppnS0chbBjYzI8B3Ra7grkYE62adHLnIUkpe0vtQ3EjVfNxzDvD40XZ5moYyNGeWu9 G7GE55DA+BEZAoTC9iBxISeIHzeHuLlkN4y7EhkRetTPXC6p+KSRPsaGL9A5DZry840z Z+nz6QfJVg7WU30eGIE2N0J0IKoqqiIFz7Iuk65mcUSLcTesZCcN59Q9HljCM/drLRGX ACvmRzT0MjGDqUEWBQsRfNu82veOi9Qn7Gj99gQ1VG7RguS2IsQovebxtjzNKBCG2c+x TG8uqWDBmqWRFIXO6as13xNOmHprnWXvCj5H+TUcxBB0zhHIN+ycggq9en9sQ9foC1+i yRZw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; 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=z5GgYCQ51eyqREAMH1U7IE5jnb0HCmRV0DVGN0Y6nQk=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=ZAmpOQrn1v9JpNgrUWwxwpXesmsLH9HXPww5eQhtZSdnMKmEd/hmdU3Y9Xaqfz2CCx rstXM9p1XDcPWm2E3uG5T4DxgbQHCpej1z346mB60GsA+Xy0oKvzuvmyuO7vLL9Obokd 55hZvL9lhd/aiC/JFFb5okb8dTmCuYd7opoeGNWUU7f8+OCj6VzYPsNaYrTsLpep5a7j h5jBZXQBEMUkBF4KRymqnHUPloHyH1dRCQDGK3I/3VzzuRiz7L12EWxZAZPwshwUZYSv sgMPyWYVRessaIbmrXMQT+HUCRZmRFUTZ1MPOB42ENMM4+gIJfRebGMRkbKwBICoteJ5 E9yQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=atbQxYt8; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=QIC5fWtu; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=eNhxYvBZ; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=Ksbx8ebw; 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 5614622812f47-4ab4b063c79si10794275b6e.16.2026.07.28.04.49.19 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jul 2026 04:49:19 -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=atbQxYt8; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=QIC5fWtu; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=eNhxYvBZ; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=Ksbx8ebw; 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=z5GgYCQ51eyqREAMH1U7IE5jnb0HCmRV0DVGN0Y6nQk=; b=atbQxYt8fssEm9u5S3aIKxs/pG vVEY8c3VMTq1vVPcCgSwTxufgsneGdxU4FNhzZcq1Tp0ghGtgw7uQDGz6y//TZay1Y4BFYdKCG83T G962+tRrTk/W8gIEY/Bex5Ja0pyrMN3QKZ+K0BzXY+S8D3ddiprXVKdSdUfop2SMrSHc=; 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 1wogJ9-0003Gc-Mc; Tue, 28 Jul 2026 11:49:16 +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 1wogJ7-0003GB-TS for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:14 +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=oj93ZxyY5w0ozartbYOt5zHsxh+gzD1zzN/FHy8ef28=; b=QIC5fWtu5DbCsC2TLpRTDknI9N Z808R8SlFosbkiXU6b9oZJSPt8lNyDgYM60gg9uHUiDolM/tol7gkQC9vko0a11h30zd0D+FdWR8/ tp7ar6aHhzZTqdS+ty2AWYfQk4H+si1zEjqjrTPneczIc6Q161cXpNj8nGluIDuCKSKQ=; 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=oj93ZxyY5w0ozartbYOt5zHsxh+gzD1zzN/FHy8ef28=; b=eNhxYvBZ2w/uoNE7leFaVOVPWq vVFIDUXtRFk3Fmuufw3PU3fO4oi0bpFqrj+88bAdhzFsAsJ1PsucT2QUeaWiyT17iIM4DrAwY4D0g GR0UFK99+WcdChMe6IaQKhFfgjRRvYSlXn6H0cObETuzsDS6z0UQtzJc08hA0SG3UIvY=; Received: from mout-p-103.mailbox.org ([80.241.56.161]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wogJ4-0002uj-6u for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:14 +0000 Received: from smtp1.mailbox.org (smtp1.mailbox.org [IPv6:2001:67c:2050:b231:465::1]) (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-103.mailbox.org (Postfix) with ESMTPS id 4h8Ydp3q8WzKnD6; Tue, 28 Jul 2026 13:49:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unstable.cc; s=MBO0001; t=1785239342; 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=oj93ZxyY5w0ozartbYOt5zHsxh+gzD1zzN/FHy8ef28=; b=Ksbx8ebwxcohmlhaNlUrdp8k1K0OPEPvKcYj/IIugBydZvWPCFtX+C9lQ9EQLb1YZvDf9M Taaj4C+jotMujUMsY+TYZMDmRpUl/ys/kXm0CiIGP0CpRY/KLc0DdsQUdDSxCcPB26O2wV nmeBU104/HotZIv2Ge9qCq77NbTtlxC7TfcolkhGa8g+WtaaV7sUtnj5CsEGA1PKV5tyUY g4ShDyQT2EWLnvyX/8/lkPd3/INRSyb9KJwJ18HI2eCNpM5EZ3kNNoNE02am2l3fvdrIcC HyI7rbhRQLywTdfxFukSzMtvMB0g5hoU0tKFMyqwQuGJavP+lkhI05wpcSTV/A== Authentication-Results: outgoing_mbo_mout; dkim=none; spf=pass (outgoing_mbo_mout: domain of a@unstable.cc designates 2001:67c:2050:b231:465::1 as permitted sender) smtp.mailfrom=a@unstable.cc From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 28 Jul 2026 13:48:48 +0200 Message-ID: <20260728114855.1323861-3-a@unstable.cc> In-Reply-To: <20260728114855.1323861-1-a@unstable.cc> References: <20260728114855.1323861-1-a@unstable.cc> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4h8Ydp3q8WzKnD6 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: From: Antonio Quartulli When userspace updates a peer's remote endpoint via OVPN_CMD_PEER_SET, ovpn_nl_peer_modify() installs a new ovpn_bind through ovpn_peer_reset_sockaddr(), but ovpn_nl_peer_set_doit() only calls ovpn_pe [...] 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_AU Message has a valid DKIM or DK signature from author's domain -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.0 RCVD_IN_MSPIKE_H5 RBL: Excellent reputation (+5) [80.241.56.161 listed in wl.mailspike.net] 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-Headers-End: 1wogJ4-0002uj-6u Subject: [Openvpn-devel] [PATCH ovpn net v4 2/9] ovpn: rehash peer in by_transp_addr table on CMD_PEER_SET 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: 1871959146985097477 X-GMAIL-MSGID: 1871959146985097477 From: Antonio Quartulli When userspace updates a peer's remote endpoint via OVPN_CMD_PEER_SET, ovpn_nl_peer_modify() installs a new ovpn_bind through ovpn_peer_reset_sockaddr(), but ovpn_nl_peer_set_doit() only calls ovpn_peer_hash_vpn_ip() to refresh the VPN-IP hashtables. The peer is left in the bucket of peers->by_transp_addr corresponding to its old remote address. As a consequence, datagrams arriving at the UDP RX path from the newly configured remote hash to a different slot and the lockless lookup in ovpn_peer_get_by_transp_addr() (called from ovpn_udp_encap_recv()) does not find the peer, until either a float event or a peer re-add fixes the bucket. Introduce ovpn_peer_hash_transp_addr() (modeled after ovpn_peer_hash_vpn_ip()) and invoke it from ovpn_nl_peer_set_doit() whenever the request carried a new remote address. The helper bails out in P2P mode and on peers without a bind (TCP), and relies on hlist_nulls_del_init_rcu()'s pprev==NULL short-circuit to handle the case of an entry not currently linked in the table. Fixes: 1d36a36f6d53 ("ovpn: implement peer add/get/dump/delete via netlink") Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/netlink.c | 6 +++ drivers/net/ovpn/peer.c | 105 +++++++++++++++++++++++++------------ drivers/net/ovpn/peer.h | 1 + 3 files changed, 79 insertions(+), 33 deletions(-) diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c index 4c66c1ec497e..4dad85294198 100644 --- a/drivers/net/ovpn/netlink.c +++ b/drivers/net/ovpn/netlink.c @@ -534,6 +534,12 @@ int ovpn_nl_peer_set_doit(struct sk_buff *skb, struct genl_info *info) */ if (ret > 0) ovpn_peer_hash_vpn_ip(peer); + /* if the remote endpoint was updated, the by_transp_addr hash bucket + * also needs to be refreshed, otherwise incoming packets from the new + * remote address would fail the lockless lookup + */ + if (attrs[OVPN_A_PEER_REMOTE_IPV4] || attrs[OVPN_A_PEER_REMOTE_IPV6]) + ovpn_peer_hash_transp_addr(peer); spin_unlock_bh(&ovpn->lock); ovpn_peer_put(peer); diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c index 68021c0c1783..a330892e82bf 100644 --- a/drivers/net/ovpn/peer.c +++ b/drivers/net/ovpn/peer.c @@ -189,6 +189,9 @@ int ovpn_peer_reset_sockaddr(struct ovpn_peer *peer, &(*__tbl1)[ovpn_get_hash_slot(*__tbl1, _key, _key_len)];\ }) +static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer, + const struct ovpn_bind *bind); + /** * ovpn_peer_endpoints_update - update remote or local endpoint for peer * @peer: peer to update the remote endpoint for @@ -196,7 +199,6 @@ int ovpn_peer_reset_sockaddr(struct ovpn_peer *peer, */ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb) { - struct hlist_nulls_head *nhead; struct sockaddr_storage ss; struct sockaddr_in6 *sa6; bool reset_cache = false; @@ -295,46 +297,23 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb) ovpn_nl_peer_float_notify(peer, &ss); /* rehashing is required only in MP mode as P2P has one peer - * only and thus there is no hashtable + * only and thus there is no hashtable. + * + * This function may be invoked concurrently, so re-read peer->bind + * under the proper locks and rehash against its current value. */ if (peer->ovpn->mode != OVPN_MODE_MP) return; + /* This function may be invoked concurrently, therefore another + * float may have happened in parallel: re-acquire the locks and + * rehash using the peer->bind->remote directly as key + */ spin_lock_bh(&peer->ovpn->lock); spin_lock_bh(&peer->lock); bind = rcu_dereference_protected(peer->bind, lockdep_is_held(&peer->lock)); - if (unlikely(!bind)) - goto unlock2; - - /* peer may have been concurrently removed between the caller's - * initial lookup and our acquisition of ovpn->lock; skip the - * rehash so we don't re-insert a removed peer - */ - if (unlikely(hlist_unhashed(&peer->hash_entry_id))) - goto unlock2; - - /* This function may be invoked concurrently, therefore another - * float may have happened in parallel: perform rehashing - * using the peer->bind->remote directly as key - */ - - switch (bind->remote.in4.sin_family) { - case AF_INET: - salen = sizeof(*sa); - break; - case AF_INET6: - salen = sizeof(*sa6); - break; - } - - /* remove old hashing */ - hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr); - /* re-add with new transport address */ - nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr, - &bind->remote, salen); - hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead); -unlock2: + __ovpn_peer_hash_transp_addr(peer, bind); spin_unlock_bh(&peer->lock); spin_unlock_bh(&peer->ovpn->lock); return; @@ -902,6 +881,66 @@ bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb, return match; } +/* Move @peer to the by_transp_addr bucket matching its current bind. + * + * Caller must hold both peer->ovpn->lock and peer->lock, and must have + * already dereferenced a valid (non-NULL) peer->bind, passed in as @bind. + */ +static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer, + const struct ovpn_bind *bind) +{ + struct hlist_nulls_head *nhead; + size_t salen; + + lockdep_assert_held(&peer->ovpn->lock); + lockdep_assert_held(&peer->lock); + + if (WARN_ON_ONCE(!bind)) + return; + + /* peer may have been concurrently removed between the caller's + * initial lookup and our acquisition of ovpn->lock; skip the + * rehash so we don't re-insert a removed peer + */ + if (unlikely(hlist_unhashed(&peer->hash_entry_id))) + return; + + switch (bind->remote.in4.sin_family) { + case AF_INET: + salen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + salen = sizeof(struct sockaddr_in6); + break; + default: + return; + } + + /* remove old hashing (no-op if entry is not currently linked) */ + hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr); + /* re-add with current transport address */ + nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr, + &bind->remote, salen); + hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead); +} + +void ovpn_peer_hash_transp_addr(struct ovpn_peer *peer) +{ + struct ovpn_bind *bind; + + lockdep_assert_held(&peer->ovpn->lock); + + /* rehashing makes sense only in multipeer mode */ + if (peer->ovpn->mode != OVPN_MODE_MP) + return; + + spin_lock_bh(&peer->lock); + bind = rcu_dereference_protected(peer->bind, + lockdep_is_held(&peer->lock)); + __ovpn_peer_hash_transp_addr(peer, bind); + spin_unlock_bh(&peer->lock); +} + void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer) { struct hlist_nulls_head *nhead; diff --git a/drivers/net/ovpn/peer.h b/drivers/net/ovpn/peer.h index 86c8cffada6d..dfa5c0037e02 100644 --- a/drivers/net/ovpn/peer.h +++ b/drivers/net/ovpn/peer.h @@ -150,6 +150,7 @@ struct ovpn_peer *ovpn_peer_get_by_id(struct ovpn_priv *ovpn, u32 peer_id); struct ovpn_peer *ovpn_peer_get_by_dst(struct ovpn_priv *ovpn, struct sk_buff *skb); void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer); +void ovpn_peer_hash_transp_addr(struct ovpn_peer *peer); bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb, struct ovpn_peer *peer); From patchwork Tue Jul 28 11:48:49 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 5141 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:fd0b:b0:87d:ab56:3700 with SMTP id cw11csp485501mac; Tue, 28 Jul 2026 04:49:17 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+RoGOGxeM0yncJHVjE84p7ABQRBSEUBpah9Sl+rpfpS22x7e/jclWS+/L/8qZMyAP1C3NBeCbY3NZo0=@openvpn.net X-Received: by 2002:a05:6870:718f:b0:455:ac39:9909 with SMTP id 586e51a60fabf-4586cb4a436mr1192246fac.37.1785239357518; Tue, 28 Jul 2026 04:49:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1785239357; cv=none; d=google.com; s=arc-20260327; b=aYg+yPC9pnE6wGzxcC0QYrq3H59Urjf+21ZPCltWf30jIYRfDR0zSgp968NMGjfwFT vUxvOGzd1+VpnP/j9g2Rj3vwsgAyjqC/J3MH5xgR/KGaI0uz1rhPMju0W/4A1+gWi7Qy k+oLeBDuojB4P0TXzSW3Yk5tT4UnV2LWffuI5tE9S48L3qofVXGdfunjJaPKGXENa1M2 nHoDKTDg2f4EqyvWhQgRS4mHrewOlUdj46qjVAiuOc9fOfEq4vAN5/uDRsNlSnQ9ZvmT R0IreTmtFjAAu5EZDsPnCII0qfGAmAej5aNcyqAioK5VQAHvaTpN1Ptw21MAapP5UPSQ s5cw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; 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=fU92+gKt4yApHpIwY37R1b5J7gHtzpyeXo1Ak2efZCE=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=RduaCgLDkNsTAmK+UQhplOw0O/SdB14v/DReP2YeZb0PjRFgCH6DhZBEdEkUiX8QDA 2vYilc8zp5kg8iCwwm7e6IytVbE4YhZ6lwiWPV7OoKSZWtXEsNrou7VUWPg/58tOovp4 6mPNd06s+1waCqNV/pSaC1qj4pBE9DDHDpeBCuDgx6PdHf2fz/RV3IuqXyw4+rorvOQS lwujYg1afE1jfeQwOsR9EKm89qWKbfWCKFe+p1vYSLSyHDTJHhVOQl9k8uF4WxwKl7LD CkEVeyiFDZgXrUGI32NrD0+tVjbOSWxHukQGzRenR9XVB6v0dqcy/ir+X8P0My+hw1Ur Nhtw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=XbwLAUfs; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="B/t2AhNx"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="Cu/gypxE"; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=qLu2lLQq; 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 586e51a60fabf-457aaa0bb80si14550370fac.368.2026.07.28.04.49.17 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jul 2026 04:49:17 -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=XbwLAUfs; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="B/t2AhNx"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="Cu/gypxE"; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=qLu2lLQq; 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=fU92+gKt4yApHpIwY37R1b5J7gHtzpyeXo1Ak2efZCE=; b=XbwLAUfs7QwdKFYNF29gGflsEF NlhD0tbDXu+gmkhuow14N9MVejLv4q/8gkPsoFWZx6b+Hf1hkNGdNqYcEzX3cwKTTIjEvkQLI/ExO AZWcg24X/euyFJDrsmGQHWGXWzUYtEhgKxdjEyO937rs9QoncNd0g+PdROAfJujqpDFY=; 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 1wogJ7-0003Fx-2k; Tue, 28 Jul 2026 11:49: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 1wogJ5-0003Fk-S2 for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:12 +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=Q5s+IliVCAtSxSuO/VpXlFTI87izFQhZPPXqXBnI1qQ=; b=B/t2AhNx4AwZhdD64FAKs0RSYu HUXNmRLvtte4lsImbNwIcRuSuCFgfh3poDYawnDeRKT9FKG/TkqVHO9/A9DqvCH2baEgrkloWWtKe YTe7Jq0JYSxq0f3k1Hs/bb33g9HMhKZlq0MqH11kJugoS0td70eABk3/Auk7BOWrsA44=; 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=Q5s+IliVCAtSxSuO/VpXlFTI87izFQhZPPXqXBnI1qQ=; b=Cu/gypxEWnLXy2BJFRIEjrrhf9 xVLMSPnle6vwpF+72upjLT9LCZhG0+zlBxELUOAGp5DyDT2IxzR3deNrGtONTcouYNp7OrozRQdl/ Ox4AQLjzlD1eX/k8m1r2BLmlq5Pqp8X83vqg8isfwTAB7g6R+d6MAw3wOqWXH76C2goA=; 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 1wogJ5-0002um-0H for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:12 +0000 Received: from smtp1.mailbox.org (unknown [10.196.197.1]) (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 4h8Ydq1Hr3z8v0H; Tue, 28 Jul 2026 13:49:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unstable.cc; s=MBO0001; t=1785239343; 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=Q5s+IliVCAtSxSuO/VpXlFTI87izFQhZPPXqXBnI1qQ=; b=qLu2lLQqcFJMQEcJ4bsza6Ojqrj5Z/lRxWprggB0G58fmNcWIYfIYs4IXiL77VLTfHU/qH VLQeJ/o+I4xwVUnUNaany4+R1Qg/4x/7cHYekbNKImfUSp1q6tO2g+P/YtWQ6LBd+8FRvW 9/8gR/FSCjU8QXQhlB1n1tE4OZAf7NswgEmnnIf1J2i0y7HNpPDCo0PFBBjfHd5RfzfJHk QF8tGN7dZfstYhX1Oc/cDDLTY1pYPqebwzGHgTC80EwDr4s3JoK/XC1N6KYRj/XRxZqx2Z r2A2q/1muYloYqcBA+2/w5SzN0YWmAH8lQfbukN8Q3J/3U6Ebv3+QONxjosQ+w== From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 28 Jul 2026 13:48:49 +0200 Message-ID: <20260728114855.1323861-4-a@unstable.cc> In-Reply-To: <20260728114855.1323861-1-a@unstable.cc> References: <20260728114855.1323861-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-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: From: Antonio Quartulli The cached local source address bind->local is updated in place on a live, RCU-published ovpn_bind while holding peer->lock: the UDP output error paths reset it (ovpn_udp4_output()/ovpn_udp6_output()) [...] 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_AU Message has a valid DKIM or DK signature from author's domain -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.0 RCVD_IN_MSPIKE_H5 RBL: Excellent reputation (+5) [80.241.56.151 listed in wl.mailspike.net] 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-Headers-End: 1wogJ5-0002um-0H Subject: [Openvpn-devel] [PATCH ovpn net v4 3/9] ovpn: fix data race reading cached local endpoint on TX path 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: 1871959144999625757 X-GMAIL-MSGID: 1871959144999625757 From: Antonio Quartulli The cached local source address bind->local is updated in place on a live, RCU-published ovpn_bind while holding peer->lock: the UDP output error paths reset it (ovpn_udp4_output()/ovpn_udp6_output()) and the RX float path learns it (ovpn_peer_endpoints_update()). The UDP TX fast path and the netlink dump, however, read bind->local holding only rcu_read_lock(), never peer->lock. For bind->local.ipv6 this is a torn read: struct in6_addr is 128 bit and is copied as multiple words, so a concurrent in-place update can make a reader observe a mix of the old and new address. The mangled source address then feeds ip6_dst_lookup_flow() and udp_tunnel6_xmit_skb(). For bind->local.ipv4 (a single aligned word) it is a data race without tearing. A spinlock on the per-packet TX path is not acceptable, and READ_ONCE()/WRITE_ONCE() cannot atomically access the 128-bit IPv6 address (the >8-byte access is rejected at build time and per-word accesses still can't yield a consistent snapshot). Serialize the IPv6 field with a per-peer seqcount_spinlock_t tied to the existing peer->lock: the in-place writers (already under peer->lock) bump it, and readers take a lock-free read_seqcount_begin()/retry() snapshot via the new ovpn_peer_local_ipv6() helper. The single-word IPv4 field is handled with plain READ_ONCE()/WRITE_ONCE(). bind->remote is untouched: it is immutable for a given bind object (only swapped via whole-bind RCU replacement), so reading it locklessly remains safe. Fixes: 08857b5ec5d9 ("ovpn: implement basic TX path (UDP)") Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/netlink.c | 13 +++++++++++-- drivers/net/ovpn/peer.c | 26 +++++++++++++++++++++++++- drivers/net/ovpn/peer.h | 6 ++++++ drivers/net/ovpn/udp.c | 17 +++++++++++++---- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c index 4dad85294198..8e21fa3e7822 100644 --- a/drivers/net/ovpn/netlink.c +++ b/drivers/net/ovpn/netlink.c @@ -610,14 +610,23 @@ static int ovpn_nl_send_peer(struct sk_buff *skb, const struct genl_info *info, bind = rcu_dereference(peer->bind); if (bind) { if (bind->remote.in4.sin_family == AF_INET) { + /* bind->local is updated in place under peer->lock; + * READ_ONCE() pairs with the WRITE_ONCE() updaters + */ if (nla_put_in_addr(skb, OVPN_A_PEER_REMOTE_IPV4, bind->remote.in4.sin_addr.s_addr) || nla_put_net16(skb, OVPN_A_PEER_REMOTE_PORT, bind->remote.in4.sin_port) || nla_put_in_addr(skb, OVPN_A_PEER_LOCAL_IPV4, - bind->local.ipv4.s_addr)) + READ_ONCE(bind->local.ipv4.s_addr))) goto err_unlock; } else if (bind->remote.in4.sin_family == AF_INET6) { + struct in6_addr local_ipv6; + + /* read the 128-bit local address under the peer + * seqcount to avoid a torn read + */ + ovpn_peer_local_ipv6(peer, bind, &local_ipv6); if (nla_put_in6_addr(skb, OVPN_A_PEER_REMOTE_IPV6, &bind->remote.in6.sin6_addr) || nla_put_u32(skb, OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID, @@ -625,7 +634,7 @@ static int ovpn_nl_send_peer(struct sk_buff *skb, const struct genl_info *info, nla_put_net16(skb, OVPN_A_PEER_REMOTE_PORT, bind->remote.in6.sin6_port) || nla_put_in6_addr(skb, OVPN_A_PEER_LOCAL_IPV6, - &bind->local.ipv6)) + &local_ipv6)) goto err_unlock; } } diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c index a330892e82bf..3554da01e406 100644 --- a/drivers/net/ovpn/peer.c +++ b/drivers/net/ovpn/peer.c @@ -113,6 +113,7 @@ struct ovpn_peer *ovpn_peer_new(struct ovpn_priv *ovpn, u32 id) RCU_INIT_POINTER(peer->bind, NULL); ovpn_crypto_state_init(&peer->crypto); spin_lock_init(&peer->lock); + seqcount_spinlock_init(&peer->bind_local_seq, &peer->lock); kref_init(&peer->refcount); ovpn_peer_stats_init(&peer->vpn_stats); ovpn_peer_stats_init(&peer->link_stats); @@ -176,6 +177,27 @@ int ovpn_peer_reset_sockaddr(struct ovpn_peer *peer, return 0; } +/** + * ovpn_peer_local_ipv6 - read the cached local IPv6 endpoint of a peer + * @peer: the peer owning the binding + * @bind: the binding to read the local address from + * @dst: where the local IPv6 address is copied to + * + * bind->local is updated in place under peer->lock (TX error path and RX + * float path). Read the 128-bit address under the peer seqcount so that + * lockless readers never observe a torn value. + */ +void ovpn_peer_local_ipv6(const struct ovpn_peer *peer, + const struct ovpn_bind *bind, struct in6_addr *dst) +{ + unsigned int seq; + + do { + seq = read_seqcount_begin(&peer->bind_local_seq); + *dst = bind->local.ipv6; + } while (read_seqcount_retry(&peer->bind_local_seq, seq)); +} + /* variable name __tbl2 needs to be different from __tbl1 * in the macro below to avoid confusing clang */ @@ -238,7 +260,7 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb) netdev_name(peer->ovpn->dev), peer->id, &bind->local.ipv4.s_addr, &ip_hdr(skb)->daddr); - bind->local.ipv4.s_addr = ip_hdr(skb)->daddr; + WRITE_ONCE(bind->local.ipv4.s_addr, ip_hdr(skb)->daddr); reset_cache = true; } break; @@ -269,7 +291,9 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb) netdev_name(peer->ovpn->dev), peer->id, &bind->local.ipv6, &ipv6_hdr(skb)->daddr); + write_seqcount_begin(&peer->bind_local_seq); bind->local.ipv6 = ipv6_hdr(skb)->daddr; + write_seqcount_end(&peer->bind_local_seq); reset_cache = true; } break; diff --git a/drivers/net/ovpn/peer.h b/drivers/net/ovpn/peer.h index dfa5c0037e02..c0994c606554 100644 --- a/drivers/net/ovpn/peer.h +++ b/drivers/net/ovpn/peer.h @@ -10,6 +10,7 @@ #ifndef _NET_OVPN_OVPNPEER_H_ #define _NET_OVPN_OVPNPEER_H_ +#include #include #include @@ -56,6 +57,8 @@ * @link_stats: per-peer link/transport TX/RX stats * @delete_reason: why peer was deleted (i.e. timeout, transport error, ..) * @lock: protects binding to peer (bind) and keepalive* fields + * @bind_local_seq: seqcount serializing in-place updates of bind->local + * (done under @lock) against lockless readers on the TX path * @refcount: reference counter * @rcu: used to free peer in an RCU safe way * @release_entry: entry for the socket release list @@ -110,6 +113,7 @@ struct ovpn_peer { struct ovpn_peer_stats link_stats; enum ovpn_del_peer_reason delete_reason; spinlock_t lock; /* protects bind and keepalive* */ + seqcount_spinlock_t bind_local_seq; /* protects bind->local */ struct kref refcount; struct rcu_head rcu; struct llist_node release_entry; @@ -151,6 +155,8 @@ struct ovpn_peer *ovpn_peer_get_by_dst(struct ovpn_priv *ovpn, struct sk_buff *skb); void ovpn_peer_hash_vpn_ip(struct ovpn_peer *peer); void ovpn_peer_hash_transp_addr(struct ovpn_peer *peer); +void ovpn_peer_local_ipv6(const struct ovpn_peer *peer, + const struct ovpn_bind *bind, struct in6_addr *dst); bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb, struct ovpn_peer *peer); diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c index 7f69e8890b5b..17d65d1595ed 100644 --- a/drivers/net/ovpn/udp.c +++ b/drivers/net/ovpn/udp.c @@ -147,7 +147,10 @@ static int ovpn_udp4_output(struct ovpn_peer *peer, struct ovpn_bind *bind, { struct rtable *rt; struct flowi4 fl = { - .saddr = bind->local.ipv4.s_addr, + /* bind->local is updated in place under peer->lock; a single + * aligned word is read/written atomically via {READ,WRITE}_ONCE + */ + .saddr = READ_ONCE(bind->local.ipv4.s_addr), .daddr = bind->remote.in4.sin_addr.s_addr, .fl4_sport = inet_sk(sk)->inet_sport, .fl4_dport = bind->remote.in4.sin_port, @@ -169,7 +172,7 @@ static int ovpn_udp4_output(struct ovpn_peer *peer, struct ovpn_bind *bind, */ fl.saddr = 0; spin_lock_bh(&peer->lock); - bind->local.ipv4.s_addr = 0; + WRITE_ONCE(bind->local.ipv4.s_addr, 0); spin_unlock_bh(&peer->lock); dst_cache_reset(cache); } @@ -178,7 +181,7 @@ static int ovpn_udp4_output(struct ovpn_peer *peer, struct ovpn_bind *bind, if (IS_ERR(rt) && PTR_ERR(rt) == -EINVAL) { fl.saddr = 0; spin_lock_bh(&peer->lock); - bind->local.ipv4.s_addr = 0; + WRITE_ONCE(bind->local.ipv4.s_addr, 0); spin_unlock_bh(&peer->lock); dst_cache_reset(cache); @@ -224,7 +227,6 @@ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind, int ret; struct flowi6 fl = { - .saddr = bind->local.ipv6, .daddr = bind->remote.in6.sin6_addr, .fl6_sport = inet_sk(sk)->inet_sport, .fl6_dport = bind->remote.in6.sin6_port, @@ -233,6 +235,11 @@ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind, .flowi6_oif = bind->remote.in6.sin6_scope_id, }; + /* bind->local is updated in place under peer->lock; read the 128-bit + * address under the peer seqcount to avoid a torn read + */ + ovpn_peer_local_ipv6(peer, bind, &fl.saddr); + local_bh_disable(); dst = dst_cache_get_ip6(cache, &fl.saddr); if (dst) @@ -245,7 +252,9 @@ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind, */ fl.saddr = in6addr_any; spin_lock_bh(&peer->lock); + write_seqcount_begin(&peer->bind_local_seq); bind->local.ipv6 = in6addr_any; + write_seqcount_end(&peer->bind_local_seq); spin_unlock_bh(&peer->lock); dst_cache_reset(cache); } From patchwork Tue Jul 28 11:48:50 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 5148 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:fd0b:b0:87d:ab56:3700 with SMTP id cw11csp485564mac; Tue, 28 Jul 2026 04:49:20 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+Rq/1MgU9l5zXaau+b7ihIwOUVfG3LtwZmI0dCvDi+kCIkQS0Iq6Z0gP8W/Eu+h2IVIktt9U4tHIbFE=@openvpn.net X-Received: by 2002:a05:6870:a1a5:b0:451:cba2:10ad with SMTP id 586e51a60fabf-4586cacca31mr1001245fac.20.1785239360685; Tue, 28 Jul 2026 04:49:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1785239360; cv=none; d=google.com; s=arc-20260327; b=HE7tszRHp4ybTj16ni3w2bmLDu6+YAjqm8vBjewkIJmctU8qimDcBNm8IZ90Ltkyt1 SpgBYlGAIEC6OVTtfvIBWszbj/AsjFN4iLRCGWcSpYy4PrgE/TSC6n1eNDEgP2iHNOdt Zg5b+k7EJtV2H4Eil1B9uTNnuqIvggB66ZT5JLUxfmrE5evNSoceXWxtkhY5o0ei4h5y 8QZRgEPhFYMqXwIsiX+fdS7+Ui8lfCQuGFtsNFYo9AKnrfzPYZp/io7Lpn1O0xCNwuK4 DgIVBHNup/P9EBmdJOhDTdZa8DMHGlTIVIzvwqL5F4rUxx0EYzfW2h1ADd1Tvvp4lNH+ 6CTg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; 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=Oj8Z5EuLMRxrE2iZMLlUC+4BrcJM5h7LPIlkZgChsak=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=qGlvYi5Tua0EU90SKWckBpoebVg7fUWGiHrJBt3BufvarznPnR0giAmmTPC71/20Pi 4zQHi5TOqh1ofd1CYuwYUCeJadsxCaKQWLKE6qTsDY2AJxyYcrD8A0Z+5ZEJ+V1B1zsn GNwS6y9IBKRHgrG8jYv6DzRQWn6lq4mK2HQcuoYgW9/n7/TsN8QgSdaRXqDPp3XBUpTP emcPQoWEMw7+F5FN6HbRVOBb4ZaKgEWKo658erNf8w9QfwfAZ49IkcYl8tX1ZiPLDYlW 8+PjrEqEjKl4Wa+OJmDc8KhWr//54rn2TwXZEPfgHgxFLKzMPAzRmMHCUQse8dBR1LOe TLFw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=Z9ASxpMo; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="RfR/lFoE"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="c/nMSEP1"; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=innx1MXg; 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 586e51a60fabf-457aa1916c0si14722864fac.23.2026.07.28.04.49.20 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jul 2026 04:49:20 -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=Z9ASxpMo; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b="RfR/lFoE"; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="c/nMSEP1"; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=innx1MXg; 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=Oj8Z5EuLMRxrE2iZMLlUC+4BrcJM5h7LPIlkZgChsak=; b=Z9ASxpMo+VhFi/W9NAu9+ZBP6V 0fMwymfJVM0RXBKKWxhZX8CCTMjUt71uM/IdEyMqA5AiRoJSDgdDTPLyUELuP2ZrbSURbmDmY+phB KY3LZdjVQfun6S3WaZ9azKGGpXqri79V2cmAbOiENQPi1GaeqWM+m/CUh1TcJ+EDNpPY=; Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1wogJE-0005u1-MR; Tue, 28 Jul 2026 11:49:18 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1wogJC-0005tm-Kz for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:16 +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=ixElgIOpjex/L7zdwx7lUWOiWK5w4EbBc2Uvh57Z4fI=; b=RfR/lFoExguXPt5pDF1Q2td/Qi KXwTsYRt0Jd0eV8G3fUiSI4hQsJS7KoXEFkpISs9YoMJP3Kun0udLtk6rvcqEOnG6JmgtTd1ROLDL o0yI9KkcRgkXBVNbbWGgARSgO+AY6MRR9zICObKyscZQffIwKVbjgEW4CatofjuqYIwA=; 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=ixElgIOpjex/L7zdwx7lUWOiWK5w4EbBc2Uvh57Z4fI=; b=c/nMSEP1+ykwDqu/hqhwdbj4dv FlwYidV1RDpkGlynJnbwLZbbWdCQtA3vjQ1FpnwqyVCKBPMO4QXrtgNUT6APwEANK1I6HWMyGO3Vo /4Kt/S7hn3DlXActe+aCWtq96CAKSSGFS8IgLEVeivLzA44WiT7xGIppWboVp+gfBhsE=; Received: from mout-p-103.mailbox.org ([80.241.56.161]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wogJ8-0003Bm-OM for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:16 +0000 Received: from smtp1.mailbox.org (smtp1.mailbox.org [IPv6:2001:67c:2050:b231:465::1]) (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-103.mailbox.org (Postfix) with ESMTPS id 4h8Ydq5DD0zKnVJ; Tue, 28 Jul 2026 13:49:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unstable.cc; s=MBO0001; t=1785239343; 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=ixElgIOpjex/L7zdwx7lUWOiWK5w4EbBc2Uvh57Z4fI=; b=innx1MXgJawRmiOXavFrlkBE5FebLjSyZKJY4RAsQkqB98DHfAecbvYD+M6xw2ingIfiDr yuV34c/XEj2xPeEXMLjqi5xcqDpQ0+KaDnjicLkLdvUq8nY4Fe5m/HHvoLD9BHmPv4klHV cooyMUrhbQdsqyaf0y2LvaHkN1PO4RiW10Vy470VDGTkms8ZtWJewHt47n+a4HD9wEUAmB dhi4kZ8HVBvBFqZDx9jbQrGK/othnHKJUxPTxO3grByEpH3E41Ou+IHc4SnWhqZeqbkRmR nhsU3G2vHa15NB/3dpctLWNxBdGGIQyRbJMKwKDiatae6B9rJK6qm+g5kAlGsA== Authentication-Results: outgoing_mbo_mout; dkim=none; spf=pass (outgoing_mbo_mout: domain of a@unstable.cc designates 2001:67c:2050:b231:465::1 as permitted sender) smtp.mailfrom=a@unstable.cc From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 28 Jul 2026 13:48:50 +0200 Message-ID: <20260728114855.1323861-5-a@unstable.cc> In-Reply-To: <20260728114855.1323861-1-a@unstable.cc> References: <20260728114855.1323861-1-a@unstable.cc> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4h8Ydq5DD0zKnVJ 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: From: Antonio Quartulli Some subsystems, like BPF SOCKMAP, set sk_user_data without actually setting the encap_type. For this reason, we must make sure that the type is the one ovpn expects before dereferencing sk_user_data. Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_MSPIKE_H5 RBL: Excellent reputation (+5) [80.241.56.161 listed in wl.mailspike.net] 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -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.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-Headers-End: 1wogJ8-0003Bm-OM Subject: [Openvpn-devel] [PATCH ovpn net v4 4/9] ovpn: ensure socket is owned by ovpn before deref sk_user_data 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: 1871959147759548193 X-GMAIL-MSGID: 1871959147759548193 From: Antonio Quartulli Some subsystems, like BPF SOCKMAP, set sk_user_data without actually setting the encap_type. For this reason, we must make sure that the type is the one ovpn expects before dereferencing sk_user_data. Failing to do so may lead to out-of-bounds reads. Fixes: f6226ae7a0cd ("ovpn: introduce the ovpn_socket object") Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/socket.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/ovpn/socket.c b/drivers/net/ovpn/socket.c index 517caa64a4fe..6cbeb2caaeec 100644 --- a/drivers/net/ovpn/socket.c +++ b/drivers/net/ovpn/socket.c @@ -162,6 +162,15 @@ struct ovpn_socket *ovpn_socket_new(struct socket *sock, struct ovpn_peer *peer) rcu_read_lock(); ovpn_sock = rcu_dereference_sk_user_data(sk); if (ovpn_sock) { + /* something else filled the sk_user_data without + * setting the encap_type. Reject the socket. + */ + if (!type) { + ovpn_sock = ERR_PTR(-EBUSY); + rcu_read_unlock(); + goto sock_release; + } + /* socket owned by another ovpn instance, we can't use it */ if (ovpn_sock->ovpn != peer->ovpn) { ovpn_sock = ERR_PTR(-EBUSY); From patchwork Tue Jul 28 11:48:51 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 5143 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:fd0b:b0:87d:ab56:3700 with SMTP id cw11csp485521mac; Tue, 28 Jul 2026 04:49:18 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+RrTc+Yf+7BXkaiYf2uUz8GwuudMOYNLWQT/YYUbhoZbdBpId/SqAICqy4/ikyt1sIaaLgD8WVBYL9Y=@openvpn.net X-Received: by 2002:a05:6820:1788:b0:6a1:7895:658f with SMTP id 006d021491bc7-6ac96c974d7mr758585eaf.41.1785239358605; Tue, 28 Jul 2026 04:49:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1785239358; cv=none; d=google.com; s=arc-20260327; b=kodYkmo+eaJPbpKYRHfL4b/GYnyGvyu2hSuykhT4+ykNGZQTXhyNUQofnlP5Efn+jX 4LE3NgleizOBEt6VhSjmzdOsegoi+xQsaFEAaSiR/h8T/LhkHXiOpCCdm8MLTeo4E4Ky Ns0rp/27BPGwxgImeqbzTGwZzNvgHpiq+MBCtgs+EwQJnYLJpFmvH76cLpDrEwO4zjIz QHstMz7zO/HvnC0TccWW+DIcB59rGVSuRsJUWxsfwMJYt9gSlx5ccivOG6K9dCO6rqqz JaVNB9JXPLyrfgn/3Ch1KDQL/3mYGrXuOdGJKahdOKq+1pPxz4i5D+JcSF3LDk1m7jHt q+uQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; 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=LO4FpBapn/kWixcblzlYC0Q9G/fM1QaDvR/ssXqDM0s=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=UE/ZU9kjUpiK9ASc821NEjWhrbwC08C0mVL46vmcMxbJnHTQBIcVv2lN/3yNro7YOq 8LviltjlDjPnIt9itS0z831fEksxBhrg9aDagY2+aGukMaB53fDGWXNyf44vd5O5Vkpl qOVfJ8j6cdeT1dgYb2KLpoJjlWF49GeCMbYIyyyz2u5xdchyX7WnAXEUMBuWnUbeu7eb 4mn8kwEg2xXmzA4PJkoAthQgaQ3ZMxG/o1+GfcoI9EFTa3oHtIvq4N5jAqQ53K0HIfxw 0xyF47jN/CIj1hV9p+lbzrFICNJ+rMIYf37grJsCKRfkNqhVvSi6/yRHaEpm2NfMigsO SUGg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=AD6MjVZp; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=bDvHygDW; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=Z6AbPy8i; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=zOfUB+ps; 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 586e51a60fabf-457aa9759e7si14984098fac.292.2026.07.28.04.49.18 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jul 2026 04:49:18 -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=AD6MjVZp; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=bDvHygDW; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=Z6AbPy8i; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=zOfUB+ps; 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=LO4FpBapn/kWixcblzlYC0Q9G/fM1QaDvR/ssXqDM0s=; b=AD6MjVZp66Ob3RTHZ6xXlIqZp7 RP6GjBn5ed8a7uCYx+f2Bh8kAEBqu9ozxqzv7nTSbOBqp4MNtlvQdY4GRzuSLZQSVNOMvJ9ozvm9+ CMShUyeOD1H0nw8VUTYw60MCShMO53F0R9BrKq4KCtrrLMJQmj3wsULgUOXmXAtc+BH4=; Received: from [127.0.0.1] (helo=sfs-ml-3.v29.lw.sourceforge.com) by sfs-ml-3.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1wogJ8-000663-T7; Tue, 28 Jul 2026 11:49:15 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-3.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1wogJ6-00065p-1W for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:12 +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=OB1wJIkO3dO6uhO/DiOC9lTI+DvWuIBap7OwdXV6sls=; b=bDvHygDWhEXS6TGKB0mr6ZeJJg uqMXxB7Y5CM0+YXzGZ5JBzPB7MLnW/QcsRomeE3biHU0SBVRhC42SuQMiriMSRGowpfVJHWMTPFP9 cBBl6Qoc7nHfqhENw6h7GS7qh07YTIPpKDO2Sseb5VBijG8f0W3EcQ2Yc854ZEEOpx/o=; 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=OB1wJIkO3dO6uhO/DiOC9lTI+DvWuIBap7OwdXV6sls=; b=Z6AbPy8iXtNmNF5aIEyVSmCWpx yVLGC7taDX/mDDOKeR19AWkHC+bpyFzWQcXAULCKpd8tTKojru7zqB66V/FsEskiUjVYrL/0MLMc5 fl8IVCOQxv5bj28QR9dbyHHzp4K7cCyltIfC1J0TLPriWuhwkmwX8YCJ15MVX9M9H3E0=; Received: from mout-p-202.mailbox.org ([80.241.56.172]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wogJ9-0003Bo-Lg for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:12 +0000 Received: from smtp1.mailbox.org (unknown [10.196.197.1]) (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-202.mailbox.org (Postfix) with ESMTPS id 4h8Ydr1ry5zMlHV; Tue, 28 Jul 2026 13:49:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unstable.cc; s=MBO0001; t=1785239344; 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=OB1wJIkO3dO6uhO/DiOC9lTI+DvWuIBap7OwdXV6sls=; b=zOfUB+psEc+MJbKKKU8ikmPhfeug5oDd1yxrlZYp92x/+Ij9hEsa5iui6VWQhT9K+M6s5X sRwq3hgqPv+0mVvJ/ujGWP/+SfHENRzFquzvD2Y/CHML8KR2ZTak55iUjENWwsLdYM+zEF 4EffhKKa4KZ9UA3BIZTtfHg36VRwhQdC6tAOUz1hB7AutOrmSxz6SIY8pn9d6AgSCL4aLQ lAhgoX8ty2Lv2crOoFzMvuWGs0pv7KIMJFJo/c5oMoHzjydXKr5xTQ9oTmwznIR3M5KjzF 1M9hDw/+F4lBoU/RzdsFuC//Qf0DyvBMFAmYUeqmW77OQqE2VHFyp9WMBID+WQ== From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 28 Jul 2026 13:48:51 +0200 Message-ID: <20260728114855.1323861-6-a@unstable.cc> In-Reply-To: <20260728114855.1323861-1-a@unstable.cc> References: <20260728114855.1323861-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 ovpn_peer_endpoints_update() builds the new remote endpoint in an on-stack struct sockaddr_storage that is left uninitialized. For IPv4 only sin_family/sin_addr/sin_port are written, leaving the 8-byt [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_MSPIKE_H5 RBL: Excellent reputation (+5) [80.241.56.172 listed in wl.mailspike.net] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-Headers-End: 1wogJ9-0003Bo-Lg Subject: [Openvpn-devel] [PATCH ovpn net v4 5/9] ovpn: zero-initialize sockaddr before learning a floated endpoint 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: 1871959145578695868 X-GMAIL-MSGID: 1871959145578695868 From: Antonio Quartulli ovpn_peer_endpoints_update() builds the new remote endpoint in an on-stack struct sockaddr_storage that is left uninitialized. For IPv4 only sin_family/sin_addr/sin_port are written, leaving the 8-byte sin_zero padding as stack garbage (for IPv6, sin6_flowinfo is left uninitialized likewise). ovpn_peer_reset_sockaddr() -> ovpn_bind_from_sockaddr() then memcpy()s sizeof(struct sockaddr_in)/sizeof(struct sockaddr_in6) bytes - padding included - into bind->remote. That buffer is later hashed with jhash() over the same length to place the peer in the by_transp_addr table, so the garbage padding lands the floated peer in an essentially random bucket. Lockless lookups in ovpn_peer_get_by_transp_addr() build their key from a zero-initialized sockaddr_storage, compute a different bucket and fail to find the peer. This is also a plain use of uninitialized stack memory in jhash(). Build the floated endpoint with a designated initializer so the padding (sin_zero for IPv4, sin6_flowinfo for IPv6) is zeroed as part of the assignment. This keeps the padding out of the by_transp_addr hash key without memset-ing the whole sockaddr_storage on every received packet. Fixes: f0281c1d3732 ("ovpn: add support for updating local or remote UDP endpoint") Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/peer.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c index 3554da01e406..00971bbd3dcf 100644 --- a/drivers/net/ovpn/peer.c +++ b/drivers/net/ovpn/peer.c @@ -244,9 +244,16 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb) */ local_ip = &ip_hdr(skb)->daddr; sa = (struct sockaddr_in *)&ss; - sa->sin_family = AF_INET; - sa->sin_addr.s_addr = ip_hdr(skb)->saddr; - sa->sin_port = udp_hdr(skb)->source; + /* use a designated initializer so the sin_zero padding + * is zeroed (it ends up in the by_transp_addr hash key) + * without memset-ing the whole sockaddr_storage on the + * RX fast path + */ + *sa = (struct sockaddr_in) { + .sin_family = AF_INET, + .sin_addr.s_addr = ip_hdr(skb)->saddr, + .sin_port = udp_hdr(skb)->source, + }; salen = sizeof(*sa); reset_cache = true; break; @@ -272,11 +279,19 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb) */ local_ip = &ipv6_hdr(skb)->daddr; sa6 = (struct sockaddr_in6 *)&ss; - sa6->sin6_family = AF_INET6; - sa6->sin6_addr = ipv6_hdr(skb)->saddr; - sa6->sin6_port = udp_hdr(skb)->source; - sa6->sin6_scope_id = ipv6_iface_scope_id(&ipv6_hdr(skb)->saddr, - skb->skb_iif); + /* use a designated initializer so the sin6_flowinfo + * padding is zeroed (it ends up in the by_transp_addr + * hash key) without memset-ing the whole + * sockaddr_storage on the RX fast path + */ + *sa6 = (struct sockaddr_in6) { + .sin6_family = AF_INET6, + .sin6_addr = ipv6_hdr(skb)->saddr, + .sin6_port = udp_hdr(skb)->source, + .sin6_scope_id = + ipv6_iface_scope_id(&ipv6_hdr(skb)->saddr, + skb->skb_iif), + }; salen = sizeof(*sa6); reset_cache = true; break; From patchwork Tue Jul 28 11:48:52 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 5147 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:fd0b:b0:87d:ab56:3700 with SMTP id cw11csp485553mac; Tue, 28 Jul 2026 04:49:20 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+Rre4dARW2xpzghX8ZhQSvroeX5mJIKOodV5D+7k8LKPZGFDbjh26aGa5U1j6Re12/E6BqP8f/4wgHA=@openvpn.net X-Received: by 2002:a05:6820:88f:b0:6aa:e99d:7f7b with SMTP id 006d021491bc7-6ac96c69291mr990909eaf.18.1785239360117; Tue, 28 Jul 2026 04:49:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1785239360; cv=none; d=google.com; s=arc-20260327; b=C2HUtaRa5ZahU0aeuvWpHrXKfcSVOTiY4ybk54ur7ZGcc+pNB07Eb3omg6Mye7osp9 q6XKQPXM7l56cVWdEgnC4CMvZnNjwUWpjf57OSpq+6H6HCyPtvH8xKFClPBVuLECj055 OH+Sh69uECP9UQ5CU9ZaOi4BckEmtGBagq2FGfasyN3lHehvLewr6RYsvdUnsQBexKqv 07jKDWZSOZc7JUGFmMTn3jReHU/wLb5U7ipHEScgmHIelcpvMTDsKduktPvyhfi8MgZs YyQJiDw1G3wV+ZCTMj5zcQTiFcC/E2R08ExV4h8vL7ekZ+jDyNJVtNnkTmmwF7nG84xl n0fw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; 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=gtPZ7qfVPtVPN64G95SuUKdyKRa/JTdzuD0ywsZWjTg=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=jEFb25ZB12FXQwlbU4eEaRJPF/8cmD3Y6IRlNeLgS1p7avbLPhAWzcc6NA8tKhH8pA OCGY5TKD59LuQKiOG/hZLADSR+AlRo5Vcl3FuQ6xq6kHcei/+/FfFFP1GlJ38deccbnO iPrwTRhy68psMEmIelsdmkHo138IetT8OE4fAvRbIH/Jb67lyAxOaPsHpECcLNRA0cbl yuiXifK8Ktcc9fbw7ugPdhWUt+XBSVtPH77+MQC6EvqK/54dhEJ2Z6Wt/1rMoL6hFGy6 YdDHCOBnNKUKluoJfZvpmrk76F/Amc5utrIOQm06Ba66Uq8oTk6NNwa562zdq56nbWt3 597g==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=C4eIXGVY; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=iPPBWx8R; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=ZB+6niBG; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=THsTy+vK; 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 46e09a7af769-7ee49bef0b1si13045945a34.38.2026.07.28.04.49.19 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jul 2026 04:49:20 -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=C4eIXGVY; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=iPPBWx8R; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=ZB+6niBG; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=THsTy+vK; 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=gtPZ7qfVPtVPN64G95SuUKdyKRa/JTdzuD0ywsZWjTg=; b=C4eIXGVYjjO3OjzUVe9GMpeZho TEbg3/4e8jgmmZDElNHWIMugC4XCxcJiFc+g9wtBQi1Gm5PEt2Qz9kr5G64umeFOXWNeskXhuRwoB 3KJhgFtHgnAz89CRd3d2ujAMyHa2Ti5xIGCdERhGEEAyCA9m6NjBIXS0DVmuyLnbwPkE=; Received: from [127.0.0.1] (helo=sfs-ml-3.v29.lw.sourceforge.com) by sfs-ml-3.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1wogJA-00066H-6m; Tue, 28 Jul 2026 11:49:16 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-3.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1wogJ8-00065w-IK for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:15 +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=vHx0ao4c0cWDp76L5UI+a1UoZuOzW2Z88UtcUEGyHmQ=; b=iPPBWx8RpNZ//dfwbDx6Be1gb9 2xiIvM7Tn3LCB8jv9mrjJxEpjGYbQdUCtItdVuJNtWYGG+MR0xzI374aG+eMBXC827Ub06QXvaoaS zTokn0G6ePmCEj0VTAi6oghk01EcNaNc6MEGaswi/T2b5WKyXwBzeP24BjE82sA32FBY=; 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=vHx0ao4c0cWDp76L5UI+a1UoZuOzW2Z88UtcUEGyHmQ=; b=ZB+6niBG5rfwB+zqGXdDYjk/Ei GC8haBc10S5l0a3kRY4nfOR3esRqNPJld1WgZmNFyFXF90NobNiK3TphKiMgchRoi475aYVBt1i1X m49jnDfUzkaO2mFP+0U1TY+N8s/dvxo/Vcd78aaDDSJ1ZjTQYLMssUVqufJbFslADcqo=; Received: from mout-p-201.mailbox.org ([80.241.56.171]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wogJA-0003Bp-28 for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:15 +0000 Received: from smtp1.mailbox.org (unknown [10.196.197.1]) (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-201.mailbox.org (Postfix) with ESMTPS id 4h8Ydr6NBPzMlD1; Tue, 28 Jul 2026 13:49:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unstable.cc; s=MBO0001; t=1785239344; 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=vHx0ao4c0cWDp76L5UI+a1UoZuOzW2Z88UtcUEGyHmQ=; b=THsTy+vKevb59/QMrtusm+I1LbkdXWRAykDunU/ukrnqiHoEOjw6AJcxNMad3Sz0V9YNsC ZSNV0c+/tA0dEwQ471P7hUTOoyZZ+rthDHXfYbkMIXmGObOInRE6Osyh1afeoTZX1sQdaM OLYg9fJCDQ5d2f+tdXDHlZRD2Egc4IlOLIQN0iB8Lw6uIkdLmoSc4HiAuTT1xB0AfvWo4c b3liBrnxUEm3d66HeN288vRjUwr+tVFcZ4On9NKd8tHdfhQSLsO5PsCfi+FVY2Hy1LUr2M yKNx9DufKpNwojrii3E8rGiLwErOvo5PeLRPOpGRQbuJT59Axu1tyFFFi6QSIw== From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 28 Jul 2026 13:48:52 +0200 Message-ID: <20260728114855.1323861-7-a@unstable.cc> In-Reply-To: <20260728114855.1323861-1-a@unstable.cc> References: <20260728114855.1323861-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-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: From: Antonio Quartulli The by_transp_addr table is keyed on the peer's remote transport address, but the float rehash hashed bind->remote directly, while the two other sites that touch the table build a clean key first: ovp [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_MSPIKE_H5 RBL: Excellent reputation (+5) [80.241.56.171 listed in wl.mailspike.net] 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -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.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-Headers-End: 1wogJA-0003Bp-28 Subject: [Openvpn-devel] [PATCH ovpn net v4 6/9] ovpn: hash floated peer by transport identity only 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: 1871959147299112284 X-GMAIL-MSGID: 1871959147299112284 From: Antonio Quartulli The by_transp_addr table is keyed on the peer's remote transport address, but the float rehash hashed bind->remote directly, while the two other sites that touch the table build a clean key first: ovpn_peer_add_mp() and the lookup in ovpn_peer_get_by_transp_addr() both hash a sockaddr holding only family/address/port. For a link-local IPv6 peer, bind->remote carries sin6_scope_id (set from ipv6_iface_scope_id() when the endpoint is learned), and that field is folded into the jhash() over sizeof(struct sockaddr_in6). The lookup never sets sin6_scope_id, so after such a peer floats it is rehashed into a scope_id-dependent bucket that lookups (scope_id 0) never visit, making the peer unreachable through the by_transp_addr fallback. ovpn_peer_transp_match() only compares address and port, so the hash was keying on a field the match ignores. sin6_scope_id must stay in bind->remote because the TX path uses it as flowi6_oif, so it cannot just be cleared there. Instead build the hash key from family/address/port only, exactly like ovpn_peer_add_mp() and the lookup, so all three sites agree on the bucket. Fixes: f0281c1d3732 ("ovpn: add support for updating local or remote UDP endpoint") Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/peer.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c index 00971bbd3dcf..27fcc917c657 100644 --- a/drivers/net/ovpn/peer.c +++ b/drivers/net/ovpn/peer.c @@ -928,7 +928,10 @@ bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb, static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer, const struct ovpn_bind *bind) { + struct sockaddr_storage sa = {}; struct hlist_nulls_head *nhead; + struct sockaddr_in6 *sa6; + struct sockaddr_in *sa4; size_t salen; lockdep_assert_held(&peer->ovpn->lock); @@ -944,12 +947,26 @@ static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer, if (unlikely(hlist_unhashed(&peer->hash_entry_id))) return; + /* Build the hash key from the transport identity only + * (family/address/port), matching ovpn_peer_add_mp() and the lookup + * in ovpn_peer_get_by_transp_addr(). Hashing bind->remote directly + * would fold in sin6_scope_id (set on the float path but never by the + * lookup), scattering the peer into a bucket lookups cannot reach. + */ switch (bind->remote.in4.sin_family) { case AF_INET: - salen = sizeof(struct sockaddr_in); + sa4 = (struct sockaddr_in *)&sa; + sa4->sin_family = AF_INET; + sa4->sin_addr.s_addr = bind->remote.in4.sin_addr.s_addr; + sa4->sin_port = bind->remote.in4.sin_port; + salen = sizeof(*sa4); break; case AF_INET6: - salen = sizeof(struct sockaddr_in6); + sa6 = (struct sockaddr_in6 *)&sa; + sa6->sin6_family = AF_INET6; + sa6->sin6_addr = bind->remote.in6.sin6_addr; + sa6->sin6_port = bind->remote.in6.sin6_port; + salen = sizeof(*sa6); break; default: return; @@ -958,8 +975,8 @@ static void __ovpn_peer_hash_transp_addr(struct ovpn_peer *peer, /* remove old hashing (no-op if entry is not currently linked) */ hlist_nulls_del_init_rcu(&peer->hash_entry_transp_addr); /* re-add with current transport address */ - nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr, - &bind->remote, salen); + nhead = ovpn_get_hash_head(peer->ovpn->peers->by_transp_addr, &sa, + salen); hlist_nulls_add_head_rcu(&peer->hash_entry_transp_addr, nhead); } From patchwork Tue Jul 28 11:48:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 5142 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:fd0b:b0:87d:ab56:3700 with SMTP id cw11csp485514mac; Tue, 28 Jul 2026 04:49:18 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+RppMWOdF+j23Qxag2wNHc+Xwu7yXh9qUQ4ugunxTrOTi0cysFWiuWURzTlv+ngo21lsNWQ82/elw5U=@openvpn.net X-Received: by 2002:a05:6870:8985:b0:448:89e3:4c58 with SMTP id 586e51a60fabf-4586cd63ca7mr1188748fac.18.1785239358085; Tue, 28 Jul 2026 04:49:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1785239358; cv=none; d=google.com; s=arc-20260327; b=iNnb8D4Tud0GQUMHbomPP/TFHpO3ukR0nR+XWGvAxp2wdRkQpF7UaHQQDcXTtWiIhq Vqf02hNCxqHkGcog8d11o9tbKpdz3Siwl89DjcO8FMmlLbkL06Wyx/r+uhYThlN6146c /GE95aIIfXWZ3P3jM+kWu0IGJTNWgHmpMGWpPkisckJQtR9ITTcJfSQmawhl8kubhtjE nH/g1XlXQc9DU6jEea3uN+FbIYIIOPxbvYs0qfKBnv7toXku/ghYBJXLm9+uRd0FxLB9 MzPTn+oFk7ll4aCt9870n/tiyQXu5KWNJt1jDi0zT8a8tEQ/jrgGdg9+uV8uOQwnNcz9 BClQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; 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=WVBJxS8hJ21PO9M0cCVGQ3NZ//jvWPqSrDtCfNWize0=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=BJICJ6mpcEwB84jKAkBuy7ztka9vqOsbZchPhNqDXpaCZGxwHvAR8+t0WO46IiHtFg bzPoN0rEqacHjrdn7hYEVOYD7OhCufLX2mFR3fxS7iOOrS5pcJqZnt4urGmnjzO9gPjC CHpAFbpf9ff7wGeIKNU93KuRjOFsLhnYz8JhVbyXk6WWBz3CeAf9fIDOru5i9zWaFdLw +UgkOlI9p4cRtu1aKxeMHQ0z2+krOCkl+wQfJvPQfqoqQ4UURMv86oCtlAIHQZsdVw29 DO+vBQ5O+8x68X3rpxGKJ88rr9nnxfb74FIrU56YqoC9ZNrAW286j5MVN/JMI9rxKhjC s9+w==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=gxdjU3No; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=CGHYsTMn; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=VFGMH8Nc; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=opeNHN9f; 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 586e51a60fabf-457aa9fcab6si15007004fac.324.2026.07.28.04.49.17 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jul 2026 04:49:18 -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=gxdjU3No; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=CGHYsTMn; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=VFGMH8Nc; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=opeNHN9f; 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=WVBJxS8hJ21PO9M0cCVGQ3NZ//jvWPqSrDtCfNWize0=; b=gxdjU3NomUzanX9SBiJ/9mTz4m Z57o82MdYe8r+brHPPpYB5pXMs0P/Zbwud8FhCrByjXqA8I1BUlxiWIfLvlxXQw9wFKM0ZQ/LFv0O SGxuPcXcFkdVtADINIWHsDBOtVo+8SbZvZSF3O4FM+ZOQHn+0+Z895zl5a6QhRmFF6io=; 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 1wogJ9-0002oV-5Z; Tue, 28 Jul 2026 11:49:15 +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 1wogJ8-0002oL-0f for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:14 +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=YJuazhbGH4Gvwf2Gu6aH9UhNU90q2oiwbgb+HRB7nF8=; b=CGHYsTMnsJerZS8PFblKm0dp2L uSJn2ZqRS5UuYFMjaSPOBwPyk9Nm6IPhCFxtBmnX3eyNABAoGS/0j8Te7j0fLaZ8+h2u58YqP6Tc1 BJHk6vK9MfzI7elnluuo0iFMTivv0jsz0uSU4IkWRpci25HDS6jSkq86u+EuUi6TQYN4=; 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=YJuazhbGH4Gvwf2Gu6aH9UhNU90q2oiwbgb+HRB7nF8=; b=VFGMH8Nc6HsBtnD8HwAyWP99GY 5nlCvhi03OJuG6ruflrHRxH76tAyWIGaVLKlZI8fwXapRVNbsbiDdJ+TgLbge9I0nifcW0z7aPd8A vIITA6dYsy2UC9HeZs4W4sdOUGORjm+l5SFqAJWsZDzOMjCXRMlhf+R/nFCcc2fTVd5k=; 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 1wogJ6-0002uq-IZ for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:13 +0000 Received: from smtp1.mailbox.org (smtp1.mailbox.org [IPv6:2001:67c:2050:b231:465::1]) (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 4h8Yds2z0bz8tYs; Tue, 28 Jul 2026 13:49:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unstable.cc; s=MBO0001; t=1785239345; 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=YJuazhbGH4Gvwf2Gu6aH9UhNU90q2oiwbgb+HRB7nF8=; b=opeNHN9fVF9oJhtWvO/hI0x6yz2DB0qTnJbQI7cLKmlxqhSeIkOIQbhWjfMff9O4xcsokw fJbQlrwp1t15fHhVXkHlFQ9c+upZNkJh+mmKJ6GFo25yv3cut06pyS7UW2uhOd16+o43l7 E4CAtz2p9tkAU118JGCZ89o1+QotwmXEmO+HfySE3twwfWNtEd8iOkCXYdrS6z6FJVTB0S hUoeBsCeuPtSLaeVXa8y9XUw+SIR5nOdQNtKYzmjp2cWdngTNu+nfe3At0wozdesqo201W 65g4F5+8JMERrSCMlGtaKELIgx0QZZbOVcIoBz4meFCzROTrgCpRwkrY/UkJ6A== Authentication-Results: outgoing_mbo_mout; dkim=none; spf=pass (outgoing_mbo_mout: domain of a@unstable.cc designates 2001:67c:2050:b231:465::1 as permitted sender) smtp.mailfrom=a@unstable.cc From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 28 Jul 2026 13:48:53 +0200 Message-ID: <20260728114855.1323861-8-a@unstable.cc> In-Reply-To: <20260728114855.1323861-1-a@unstable.cc> References: <20260728114855.1323861-1-a@unstable.cc> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4h8Yds2z0bz8tYs 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 ovpn_mp_alloc() tried to disable SEND_REDIRECTS on a multipeer interface, but it runs from ovpn_net_init() (->ndo_init), which register_netdevice() invokes before the NETDEV_REGISTER notifier chain. T [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_MSPIKE_H5 RBL: Excellent reputation (+5) [80.241.56.151 listed in wl.mailspike.net] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-Headers-End: 1wogJ6-0002uq-IZ Subject: [Openvpn-devel] [PATCH ovpn net v4 7/9] ovpn: disable IPv4 redirects on MP interfaces 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: 1871959145153086554 X-GMAIL-MSGID: 1871959145153086554 From: Antonio Quartulli ovpn_mp_alloc() tried to disable SEND_REDIRECTS on a multipeer interface, but it runs from ovpn_net_init() (->ndo_init), which register_netdevice() invokes before the NETDEV_REGISTER notifier chain. The IPv4 in_device is only created when that notifier reaches inetdev_event() -> inetdev_init(), so __in_dev_get_rtnl() always returned NULL at ndo_init time and the whole redirect-disabling block (both the per-device and the per-netns IPV4_DEVCONF_ALL write) was dead. MP interfaces therefore kept emitting ICMP redirects. Disabling redirects only once is not enough either: the IPv4 in_device is destroyed and recreated when the interface is moved to a different network namespace (NETDEV_UNREGISTER/NETDEV_REGISTER), and the newly created in_device inherits the destination namespace defaults, silently re-enabling SEND_REDIRECTS. Disable redirects from ovpn_net_open() (->ndo_open) instead: it runs every time the interface is brought up, including after the in_device has been recreated, so the setting is always re-applied. This mirrors what wireguard does in wg_open(). RTNL is held on the ndo_open() path, so __in_dev_get_rtnl() is safe. Fixes: 05003b408c20 ("ovpn: implement multi-peer support") Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/main.c | 50 ++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/drivers/net/ovpn/main.c b/drivers/net/ovpn/main.c index 9993c1dfe471..c4e775250727 100644 --- a/drivers/net/ovpn/main.c +++ b/drivers/net/ovpn/main.c @@ -35,25 +35,11 @@ static void ovpn_priv_free(struct net_device *net) static int ovpn_mp_alloc(struct ovpn_priv *ovpn) { - struct in_device *dev_v4; int i; if (ovpn->mode != OVPN_MODE_MP) return 0; - dev_v4 = __in_dev_get_rtnl(ovpn->dev); - if (dev_v4) { - /* disable redirects as Linux gets confused by ovpn - * handling same-LAN routing. - * This happens because a multipeer interface is used as - * relay point between hosts in the same subnet, while - * in a classic LAN this would not be needed because the - * two hosts would be able to talk directly. - */ - IN_DEV_CONF_SET(dev_v4, SEND_REDIRECTS, false); - IPV4_DEVCONF_ALL(dev_net(ovpn->dev), SEND_REDIRECTS) = false; - } - /* the peer container is fairly large, therefore we allocate it only in * MP mode */ @@ -97,9 +83,38 @@ static void ovpn_net_uninit(struct net_device *dev) gro_cells_destroy(&ovpn->gro_cells); } +static int ovpn_net_open(struct net_device *dev) +{ + struct ovpn_priv *ovpn = netdev_priv(dev); + struct in_device *dev_v4; + + /* the IPv4 in_device (and thus its config) is recreated whenever the + * interface is moved to a new netns, so redirects must be disabled on + * every bring-up rather than once at creation time, otherwise the + * setting is silently lost after such a move + */ + if (ovpn->mode == OVPN_MODE_MP) { + dev_v4 = __in_dev_get_rtnl(dev); + if (dev_v4) { + /* disable redirects as Linux gets confused by ovpn + * handling same-LAN routing. + * This happens because a multipeer interface is used as + * relay point between hosts in the same subnet, while + * in a classic LAN this would not be needed because the + * two hosts would be able to talk directly. + */ + IN_DEV_CONF_SET(dev_v4, SEND_REDIRECTS, false); + IPV4_DEVCONF_ALL(dev_net(dev), SEND_REDIRECTS) = false; + } + } + + return 0; +} + static const struct net_device_ops ovpn_netdev_ops = { .ndo_init = ovpn_net_init, .ndo_uninit = ovpn_net_uninit, + .ndo_open = ovpn_net_open, .ndo_start_xmit = ovpn_net_xmit, }; @@ -183,6 +198,7 @@ static int ovpn_newlink(struct net_device *dev, struct ovpn_priv *ovpn = netdev_priv(dev); struct nlattr **data = params->data; enum ovpn_mode mode = OVPN_MODE_P2P; + int ret; if (data && data[IFLA_OVPN_MODE]) { mode = nla_get_u8(data[IFLA_OVPN_MODE]); @@ -207,7 +223,11 @@ static int ovpn_newlink(struct net_device *dev, else netif_carrier_off(dev); - return register_netdevice(dev); + ret = register_netdevice(dev); + if (ret < 0) + return ret; + + return 0; } static int ovpn_fill_info(struct sk_buff *skb, const struct net_device *dev) From patchwork Tue Jul 28 11:48:54 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 5144 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:fd0b:b0:87d:ab56:3700 with SMTP id cw11csp485524mac; Tue, 28 Jul 2026 04:49:19 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+Rpk43CJ4LC/IzJVTsuvga4QljEVtRRCSh7Y5PCDDygV2/JcgZeb12JEZh4UjZPzQS9/myGJKNmvMEI=@openvpn.net X-Received: by 2002:a05:6808:228e:b0:497:8b9:bdc7 with SMTP id 5614622812f47-4ad5b9ca9e3mr1305254b6e.15.1785239358932; Tue, 28 Jul 2026 04:49:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1785239358; cv=none; d=google.com; s=arc-20260327; b=MaMZel6c3Km7XGohZSmacEJU+C3t0qeEn7Dl9j6C9mZkg2UT2bHJHye9jk+u3hXSgZ dpn3mHnDVxcNGNwHHp6aOyxBI6iWgmi66BUi5mMHYQhH8NM3GJz4vGECSP+4eC3bubxz Aabq5lbsdEWU9YKphEpYaFV7bksIWhPtoeIM/b0rIyjpQVrYgVMdjpxsXDZxNY1UP8AR LvmPb3b2RlCG4dV82KVCZ+l2L4jnazT4HZvvgVDRaOVIJZeT61Sp1vGdO69wMMb55bhJ ROhsuLrPDvuRuyVqmmJrHB3DV0hS+yzSns4vmsoNsvD87EntJz0bIJau/21Iaxcb92St ju2w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; 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=MwQgd9got00wHlhrV53CT4w4al0uuUpnTo79rg8BRDw=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=K7uPa0Q1mQpiugwmXPpWRDz2b8XlNNd76W/WhCxarpcumlmJQe4thUqB+arjhfLx9e BrAPrT+s01H7hLRFXB/mLUQ98g/Dkm5WZQfmuTEBswRqUr+KoKLE+giDLnvBudKbIqrU WJZzxjGzGZ/mItrARjI3ovXSUQyHXHCYQjHVphK2wIB+Y7xFlG/h7XxDJCFsHefuvkgJ rgLb2Vk98m3/JZmexhHCXKalU+g2XoFL4n4cj5MI1IvvwLvc1ZDMbbA/wspAQ3JwI0aQ wAc3yLmle8RfSclAEeWwuII+FVpANfysEgaPPy2gRysX1k0KYvSF1PKbe9shLygec9Gi +ORQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=CYTi3rBu; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Iwtaj1ej; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="B5W/Xr43"; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=C+d8hzx2; 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 5614622812f47-4ab4b3faac3si10618183b6e.66.2026.07.28.04.49.18 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jul 2026 04:49:18 -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=CYTi3rBu; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=Iwtaj1ej; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="B5W/Xr43"; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=C+d8hzx2; 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=MwQgd9got00wHlhrV53CT4w4al0uuUpnTo79rg8BRDw=; b=CYTi3rBuXu/0pK2FTQYA2uYif7 lrKg6tukfXvfWUEKqykqYtlzv8I6jR2dQYhhgTUAC1sDNik9vZtBIrjre71sNlXt0snOdFAhLCo5m lVsu3l/nJVsnRLi3BeqgVvw3QGVoUX6uf8+XEark5yh5LJhq2FWKYHHnqZJVhFUdgjCM=; Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1wogJC-0005td-C9; Tue, 28 Jul 2026 11:49:15 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1wogJA-0005tQ-LV for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:14 +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=j4K0CryDDnvcfv4cinY40LKzzK/Yzm1HDYN5nMvZdnA=; b=Iwtaj1ej5ZXhMy6nmNfwp2qPii zpL5w4YVPCncQNri3IU2pj8KglZSr589sMFwmXTBhji0QQPBC5pNzO/eqtueML3Q9bfGJCe6SEiYb /KQN7g7qmvOU/mRfUq3yVKyG5miBlVsTOkjWcuHm3oPQmskO0zmjAVjYNe7mdDaCXOr4=; 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=j4K0CryDDnvcfv4cinY40LKzzK/Yzm1HDYN5nMvZdnA=; b=B5W/Xr433YQK+UdKEHA4CFmmmm VdtkGGsKlchaPJYl4BtWesgVmO4nTfJVT42qwy4Kjzk8SwetHNZT3Fn5ZvKoEcc4yBvOqATQs29Oe Pg7Kmvc6+OyKlx3QTtuo+H0GnDH3N3LLJN72ybJAAnFU4pqbWBTC3JSjYeaZZ/TZAkIA=; Received: from mout-p-202.mailbox.org ([80.241.56.172]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wogJ7-0002v1-Jj for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:14 +0000 Received: from smtp1.mailbox.org (smtp1.mailbox.org [IPv6:2001:67c:2050:b231:465::1]) (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-202.mailbox.org (Postfix) with ESMTPS id 4h8Yds6wRwzMlK5; Tue, 28 Jul 2026 13:49:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unstable.cc; s=MBO0001; t=1785239345; 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=j4K0CryDDnvcfv4cinY40LKzzK/Yzm1HDYN5nMvZdnA=; b=C+d8hzx2amUKvJC+3mCNuzpbl81zptRIlteIlerx011raepKGqYsPsZJhaoHymh15aeXRv KywapRm4PVW/LHiEqU3ompG9qQkxIEAxn9zEgK8b0KCgvjJLXKWNQwEGyo0+lBRp5GkS1N YQKYu5J7RsaN6HMk6AlKLfi0sYS6ywL0JMMYI34wJwbYoVrkZ9GW8nkdsF3aq3VzrcNvlX xKGTOJfOVjM0nzzK0GU2Q8F6aatqHMHBUTAIRusT2j5+9Lp2W/6XrpVVG1MpSmliupkJ1E 8FFAOKCWvJhZ/Y9O4jY3PdeJLLpgpVLxBv4d1fLuZn6b9r2S7DzQYmeW1qBy6Q== Authentication-Results: outgoing_mbo_mout; dkim=none; spf=pass (outgoing_mbo_mout: domain of a@unstable.cc designates 2001:67c:2050:b231:465::1 as permitted sender) smtp.mailfrom=a@unstable.cc From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 28 Jul 2026 13:48:54 +0200 Message-ID: <20260728114855.1323861-9-a@unstable.cc> In-Reply-To: <20260728114855.1323861-1-a@unstable.cc> References: <20260728114855.1323861-1-a@unstable.cc> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4h8Yds6wRwzMlK5 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 Netlink calls may access TCP global vars (i.e. when attaching a TCP socket), therefore we need to make sure the latters are initialized beforehand. For this reason move the global TCP initialization at the top of the module init function. Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_MSPIKE_H5 RBL: Excellent reputation (+5) [80.241.56.172 listed in wl.mailspike.net] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-Headers-End: 1wogJ7-0002v1-Jj Subject: [Openvpn-devel] [PATCH ovpn net v4 8/9] ovpn: ensure TCP vars are initialized first 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: 1871959145681427795 X-GMAIL-MSGID: 1871959145681427795 From: Antonio Quartulli Netlink calls may access TCP global vars (i.e. when attaching a TCP socket), therefore we need to make sure the latters are initialized beforehand. For this reason move the global TCP initialization at the top of the module init function. Fixes: 11851cbd60ea ("ovpn: implement TCP transport") Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/ovpn/main.c b/drivers/net/ovpn/main.c index c4e775250727..f8ae64612951 100644 --- a/drivers/net/ovpn/main.c +++ b/drivers/net/ovpn/main.c @@ -253,8 +253,14 @@ static struct rtnl_link_ops ovpn_link_ops = { static int __init ovpn_init(void) { - int err = rtnl_link_register(&ovpn_link_ops); + int err; + /* init TCP first so that any subsequent netlink operation + * is ensured to access initialized TCP global vars + */ + ovpn_tcp_init(); + + err = rtnl_link_register(&ovpn_link_ops); if (err) { pr_err("ovpn: can't register rtnl link ops: %d\n", err); return err; @@ -266,8 +272,6 @@ static int __init ovpn_init(void) goto unreg_rtnl; } - ovpn_tcp_init(); - return 0; unreg_rtnl: From patchwork Tue Jul 28 11:48:55 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 5146 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:fd0b:b0:87d:ab56:3700 with SMTP id cw11csp485544mac; Tue, 28 Jul 2026 04:49:20 -0700 (PDT) X-Forwarded-Encrypted: i=2; AHgh+Ro25bHgF5j9rpbpDg433iHKx29eQ5wbfxPg61xPoip65YB/PN+XeICjpr9CxWAlodjI2o1cNz9mAmY=@openvpn.net X-Received: by 2002:a05:6871:740e:b0:43b:5268:b7a0 with SMTP id 586e51a60fabf-4586cf08defmr1194928fac.26.1785239359965; Tue, 28 Jul 2026 04:49:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1785239359; cv=none; d=google.com; s=arc-20260327; b=DoTmof41W6c9UJXLSkfRkOdgWfhwJOcZtvjzpCBpmzR1E1SnN4jWbFOJdHaPvO0DCd Tag2hUbcCoalqwQJLy9qv1poY3Hh9/yC5ZYxSLB1OBfgKFIxcSOIMo0t7DlppPSWQ1vX BpXcdR5hIVQFnbElkZ/BHbETDHM/SvrNlnNJhU37cL5F7DhvpHYhiUme5KyxMEoK0mhY uXsWIKfCAWsPA9RZFrkJeqBpW61ph0D6qZ8Wlf1UbWblngx408cRttIg/4LmzHBf68s0 JkaEQqVnrGTugcJUxPidXtjm4U+ok1hIdVPC9f6tEzIhM8Ju9QO5G01SoIvDx0whAPFz NhhQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; 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=BmObCGVUYDmiGhAK/avuIXvOiABjKr8EvGr7fTGKyts=; fh=BsMg/B0Yb/hS/rzP5Npz4luh0IleZm8REk1XWiWRt2A=; b=OQrGNQIj9RzhmHh2Pq/nQghhJnKu+E05XiWnkWskpuc2mCTBbsUrzVDk+kyUDgzpUg 6FJpUEQvsJX4ISOcS/8S+UVYUcxqQRdMWEyH/GyzX3JWfeDTlbPiTKJWZ86+fthaBsCf wgvg/81stDqZpQ1ONMpH1GE6CQ6taXTY/7eBX5STuS+L0JEAIZyVy20PRfYZuPkgdPVI 23Wk0vypBm1N4YHJiClgrj2gA2a4s307W6DoXai0/knfP0yTERGharRl4uDJOu8GW4li Wyr+r5MqpU2RQCZ7mqAzKg3E7wQK2WXWGX/vUSk2Rw3/k39k3ITgQkTFfqY+MBO7E0yZ 0SZQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=JOTsJkW4; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=LRBa0vTK; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=jG1EkRP0; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=JiN4gEt0; 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 586e51a60fabf-457aa194c2dsi14784675fac.46.2026.07.28.04.49.19 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jul 2026 04:49:19 -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=JOTsJkW4; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=LRBa0vTK; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=jG1EkRP0; dkim=neutral (body hash did not verify) header.i=@unstable.cc header.s=MBO0001 header.b=JiN4gEt0; 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=BmObCGVUYDmiGhAK/avuIXvOiABjKr8EvGr7fTGKyts=; b=JOTsJkW4Q0b4IyuyrPyWxluQaI K+JVWIkXh4MfJCav5jteQUvn2hDme4zT1DBKN76go+5JalqwpxTCoRDLTMOaIljENvOroLunQ39b/ aDCqZevRbjcucYYZ4KMgh209pZ0PTJduN1r6VojUIY+QJyeAcLSmIkuUK8scpp5iQoF4=; 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 1wogJA-0002os-HD; Tue, 28 Jul 2026 11:49:16 +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 1wogJ9-0002oe-CW for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:15 +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=Yg5CoNDMDrOG6jpu826kHHRn6bPkRuc1+5tmPj7qUS4=; b=LRBa0vTK1le5a3xXoSpElqSzV0 DQgN9HyxgJ0smZhr9IelKJuecLdinXdQj4eUNo3CJsOvr8fyzawWvcSlfazI4czast8P52bZUYRna zr9icp4RDB8DJbeWdQnDZUNjlGbtJN14TXqVaTCJ390YRng7yiNCzEYmezVxAvmnbXKE=; 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=Yg5CoNDMDrOG6jpu826kHHRn6bPkRuc1+5tmPj7qUS4=; b=jG1EkRP08i62VVf0KwbsJwst7y fKmBV6pLJxWH6ABtudL9cFOgn1m3jQWO/PtkGJK3F+RPuI2BKhWHksy4Mn6sIYMvhRnRs1KrCFsu4 Z1fk5EqZdKvNoXK+e6tO/KayeE1/mj3l8YIv61OZwqk/88HBIlIlApGDeuSUediR04XM=; Received: from mout-p-101.mailbox.org ([80.241.56.151]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1wogJB-0003C7-SY for openvpn-devel@lists.sourceforge.net; Tue, 28 Jul 2026 11:49:15 +0000 Received: from smtp1.mailbox.org (unknown [10.196.197.1]) (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 4h8Ydt3lCgz8v0r; Tue, 28 Jul 2026 13:49:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unstable.cc; s=MBO0001; t=1785239346; 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=Yg5CoNDMDrOG6jpu826kHHRn6bPkRuc1+5tmPj7qUS4=; b=JiN4gEt04iu5R5Pb+me7Qj/olFlLcXhRGF8xxmFSauLdM8xiXigKQ1etNAV0wzZstVtYBA CH1pzvXiXDm4RUWYpEL227DIoDuN9ZnnAHmSHH3A0X027qNvlTtzUXspggBPI2PIhBj065 zb7AD017dDSEFpLBRGVIK8/LVNt2PCwG7NHliUDQ0FqldKtH+fweEVp8hSziF5N5KEF3Bi v9WSMjHcXksHyoS/Q3GFqlP0z5bfjpSjtqnxzqD/URZxsJ7NIchFdBtBcZ89Sz2rc8q2IU 0ETQCVCdZR8zHAxbAZEZr2QLaA7unQesmKskxLw6fJYEt3CJRF+Gi7ohMKN/MQ== From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 28 Jul 2026 13:48:55 +0200 Message-ID: <20260728114855.1323861-10-a@unstable.cc> In-Reply-To: <20260728114855.1323861-1-a@unstable.cc> References: <20260728114855.1323861-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 ovpn_udp{4, 6}_output() resolve a route from a flow key sampled from the peer binding and the transport socket, then cache the result in the per-peer dst_cache. Several of those sources may change conc [...] Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_MSPIKE_H5 RBL: Excellent reputation (+5) [80.241.56.151 listed in wl.mailspike.net] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-Headers-End: 1wogJB-0003C7-SY Subject: [Openvpn-devel] [PATCH ovpn net v4 9/9] ovpn: invalidate the UDP TX dst_cache when the flow key changes 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: 1871959147087025884 X-GMAIL-MSGID: 1871959147087025884 From: Antonio Quartulli ovpn_udp{4,6}_output() resolve a route from a flow key sampled from the peer binding and the transport socket, then cache the result in the per-peer dst_cache. Several of those sources may change concurrently with TX, and the dst_cache epoch (reset_ts vs the per-CPU refresh_ts stamped at get-miss time) only neutralizes the common ordering. Three issues remain: - ovpn_peer_endpoints_update() may either update bind->local in place or replace the whole bind via RCU (float -> new remote, hence new daddr/dport/oif). It already dst_cache_reset()s, but the TX path can still cache a dst it resolved with the pre-update values if its dst_cache_get-miss lands a strictly later jiffy than the reset. - inet_sk(sk)->inet_sport can be reset to 0 by __udp_disconnect() (connect() with AF_UNSPEC) on a socket without SOCK_BINDPORT_LOCK, and sk->sk_mark can change any time via setsockopt(SO_MARK). Neither triggers an ovpn cache reset, so a previously-cached entry resolved with the old value persists until dst obsolescence. Both fields are also read locklessly into the flow key (data race). - A sport of 0 means the transport socket has been disconnected and unhashed; sending a UDP packet from source port 0 is nonsense. In the common dispatcher ovpn_udp_output() (so every TX, including cache hits, runs the check): - Sample inet_sport with READ_ONCE(). If it is 0, emit a one-time netdev_warn_once() and return -EIO so ovpn_udp_send_skb() drops the skb. - Sample sk_mark with READ_ONCE(). - Compare both against the values stored when the dst_cache was last (re-)populated (new per-peer fields dst_cache_sport/dst_cache_mark, zero-initialised by kzalloc_obj() in ovpn_peer_new()). On mismatch dst_cache_reset() the cache and WRITE_ONCE() the new values, so the subsequent dst_cache_get() misses and the lookup re-resolves with the current sport/mark. - Pass sport/mark down to ovpn_udp{4,6}_output(); they use those in the flowi initializer and skip the per-function sampling. The post-lookup re-check in the v4/v6 paths covers both the bind/local race the original commit addressed (rcu_access_pointer on peer->bind and READ_ONCE/ovpn_peer_local_ipv6 on bind->local) and sport/mark: the TX-entry check alone is not enough, because a slow resolver can finish its route lookup after another CPU has already re-tagged the cache with a different sport/mark, so it must re-verify both before populating the cache. sk_protocol is immutable post-creation and is intentionally read plain. The in-flight packet is still transmitted with the resolved parameters; only the cache is guarded. No fast-path lock is added. Fixes: 08857b5ec5d9 ("ovpn: implement basic TX path (UDP)") Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/peer.h | 8 ++++ drivers/net/ovpn/udp.c | 101 ++++++++++++++++++++++++++++++++++------ 2 files changed, 94 insertions(+), 15 deletions(-) diff --git a/drivers/net/ovpn/peer.h b/drivers/net/ovpn/peer.h index c0994c606554..17d57b12fa5e 100644 --- a/drivers/net/ovpn/peer.h +++ b/drivers/net/ovpn/peer.h @@ -46,6 +46,12 @@ * @tcp.sk_cb.ops: pointer to the original prot_ops object (TCP only) * @crypto: the crypto configuration (ciphers, keys, etc..) * @dst_cache: cache for dst_entry used to send to peer + * @dst_cache_sport: inet_sport observed when the dst_cache was last + * (re-)populated; compared on every TX to detect changes + * (e.g. connect(AF_UNSPEC)) and invalidate the cache + * @dst_cache_mark: sk_mark observed when the dst_cache was last + * (re-)populated; compared on every TX to detect changes + * via setsockopt(SO_MARK) and invalidate the cache * @bind: remote peer binding * @keepalive_interval: seconds after which a new keepalive should be sent * @keepalive_xmit_exp: future timestamp when next keepalive should be sent @@ -102,6 +108,8 @@ struct ovpn_peer { } tcp; struct ovpn_crypto_state crypto; struct dst_cache dst_cache; + __be16 dst_cache_sport; + u32 dst_cache_mark; struct ovpn_bind __rcu *bind; unsigned long keepalive_interval; unsigned long keepalive_xmit_exp; diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c index 17d65d1595ed..fc5ef77d17b0 100644 --- a/drivers/net/ovpn/udp.c +++ b/drivers/net/ovpn/udp.c @@ -143,19 +143,24 @@ static int ovpn_udp_encap_recv(struct sock *sk, struct sk_buff *skb) */ static int ovpn_udp4_output(struct ovpn_peer *peer, struct ovpn_bind *bind, struct dst_cache *cache, struct sock *sk, - struct sk_buff *skb) + struct sk_buff *skb, __be16 sport, u32 mark) { + /* bind->local is updated in place under peer->lock; a single aligned + * word is read/written atomically via {READ,WRITE}_ONCE. Snapshot it + * so the post-lookup validity check can compare against the value we + * actually resolved with: fl.saddr may be overwritten by the FIB when + * the local address is unset, and comparing bind->local against that + * would spuriously skip caching. + */ + __be32 saddr = READ_ONCE(bind->local.ipv4.s_addr); struct rtable *rt; struct flowi4 fl = { - /* bind->local is updated in place under peer->lock; a single - * aligned word is read/written atomically via {READ,WRITE}_ONCE - */ - .saddr = READ_ONCE(bind->local.ipv4.s_addr), + .saddr = saddr, .daddr = bind->remote.in4.sin_addr.s_addr, - .fl4_sport = inet_sk(sk)->inet_sport, + .fl4_sport = sport, .fl4_dport = bind->remote.in4.sin_port, .flowi4_proto = sk->sk_protocol, - .flowi4_mark = sk->sk_mark, + .flowi4_mark = mark, }; int ret; @@ -171,6 +176,7 @@ static int ovpn_udp4_output(struct ovpn_peer *peer, struct ovpn_bind *bind, * new look up */ fl.saddr = 0; + saddr = 0; spin_lock_bh(&peer->lock); WRITE_ONCE(bind->local.ipv4.s_addr, 0); spin_unlock_bh(&peer->lock); @@ -180,6 +186,7 @@ static int ovpn_udp4_output(struct ovpn_peer *peer, struct ovpn_bind *bind, rt = ip_route_output_flow(sock_net(sk), &fl, sk); if (IS_ERR(rt) && PTR_ERR(rt) == -EINVAL) { fl.saddr = 0; + saddr = 0; spin_lock_bh(&peer->lock); WRITE_ONCE(bind->local.ipv4.s_addr, 0); spin_unlock_bh(&peer->lock); @@ -196,7 +203,21 @@ static int ovpn_udp4_output(struct ovpn_peer *peer, struct ovpn_bind *bind, ret); goto err; } - dst_cache_set_ip4(cache, &rt->dst, fl.saddr); + /* only cache the result if the parameters we resolved with are still + * current: a concurrent ovpn_peer_endpoints_update() may have replaced + * the bind (float) or updated bind->local in place, and a concurrent + * ovpn_udp_output() may have re-tagged the cache with a different + * sport/mark after we sampled them. In any of these cases the cache was + * already reset and re-caching a route resolved with the stale values + * would poison it, so bail out and reset instead. + */ + if (rcu_access_pointer(peer->bind) == bind && + READ_ONCE(bind->local.ipv4.s_addr) == saddr && + READ_ONCE(peer->dst_cache_sport) == sport && + READ_ONCE(peer->dst_cache_mark) == mark) + dst_cache_set_ip4(cache, &rt->dst, fl.saddr); + else + dst_cache_reset(cache); transmit: udp_tunnel_xmit_skb(rt, sk, skb, fl.saddr, fl.daddr, 0, @@ -221,24 +242,30 @@ static int ovpn_udp4_output(struct ovpn_peer *peer, struct ovpn_bind *bind, */ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind, struct dst_cache *cache, struct sock *sk, - struct sk_buff *skb) + struct sk_buff *skb, __be16 sport, u32 mark) { struct dst_entry *dst; + struct in6_addr local, saddr; int ret; struct flowi6 fl = { .daddr = bind->remote.in6.sin6_addr, - .fl6_sport = inet_sk(sk)->inet_sport, + .fl6_sport = sport, .fl6_dport = bind->remote.in6.sin6_port, .flowi6_proto = sk->sk_protocol, - .flowi6_mark = sk->sk_mark, + .flowi6_mark = mark, .flowi6_oif = bind->remote.in6.sin6_scope_id, }; /* bind->local is updated in place under peer->lock; read the 128-bit - * address under the peer seqcount to avoid a torn read + * address under the peer seqcount to avoid a torn read. Snapshot it so + * the post-lookup validity check can compare against the value we + * actually resolved with: fl.saddr may be overwritten by the FIB when + * the local address is unset, and comparing bind->local against that + * would spuriously skip caching. */ ovpn_peer_local_ipv6(peer, bind, &fl.saddr); + saddr = fl.saddr; local_bh_disable(); dst = dst_cache_get_ip6(cache, &fl.saddr); @@ -251,6 +278,7 @@ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind, * new look up */ fl.saddr = in6addr_any; + saddr = in6addr_any; spin_lock_bh(&peer->lock); write_seqcount_begin(&peer->bind_local_seq); bind->local.ipv6 = in6addr_any; @@ -267,7 +295,22 @@ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind, &bind->remote.in6, ret); goto err; } - dst_cache_set_ip6(cache, dst, &fl.saddr); + /* only cache the result if the parameters we resolved with are still + * current: a concurrent ovpn_peer_endpoints_update() may have replaced + * the bind (float) or updated bind->local in place, and a concurrent + * ovpn_udp_output() may have re-tagged the cache with a different + * sport/mark after we sampled them. In any of these cases the cache was + * already reset and re-caching a route resolved with the stale values + * would poison it, so bail out and reset instead. + */ + ovpn_peer_local_ipv6(peer, bind, &local); + if (rcu_access_pointer(peer->bind) == bind && + ipv6_addr_equal(&local, &saddr) && + READ_ONCE(peer->dst_cache_sport) == sport && + READ_ONCE(peer->dst_cache_mark) == mark) + dst_cache_set_ip6(cache, dst, &fl.saddr); + else + dst_cache_reset(cache); transmit: /* user IPv6 packets may be larger than the transport interface @@ -306,12 +349,40 @@ static int ovpn_udp_output(struct ovpn_peer *peer, struct dst_cache *cache, struct sock *sk, struct sk_buff *skb) { struct ovpn_bind *bind; + __be16 sport; + u32 mark; int ret; /* set sk to null if skb is already orphaned */ if (!skb->destructor) skb->sk = NULL; + sport = READ_ONCE(inet_sk(sk)->inet_sport); + if (unlikely(!sport)) { + /* the transport UDP socket has been disconnected (e.g. via + * connect(AF_UNSPEC)): inet_sport == 0 means the socket has + * been unhashed and sending from source port 0 is nonsense; + * refuse and tell the operator + */ + netdev_warn_once(peer->ovpn->dev, + "UDP transport socket has no source port; was it disconnected?\n"); + return -EIO; + } + mark = READ_ONCE(sk->sk_mark); + + /* userspace can change sk_mark (via setsockopt(SO_MARK)) and + * inet_sport (via connect(AF_UNSPEC)) at any time without notifying + * ovpn; if either differs from what the dst_cache was last populated + * with, invalidate the cache now so a hit doesn't return a dst + * resolved with the old value + */ + if (READ_ONCE(peer->dst_cache_sport) != sport || + READ_ONCE(peer->dst_cache_mark) != mark) { + dst_cache_reset(cache); + WRITE_ONCE(peer->dst_cache_sport, sport); + WRITE_ONCE(peer->dst_cache_mark, mark); + } + rcu_read_lock(); bind = rcu_dereference(peer->bind); if (unlikely(!bind)) { @@ -323,11 +394,11 @@ static int ovpn_udp_output(struct ovpn_peer *peer, struct dst_cache *cache, switch (bind->remote.in4.sin_family) { case AF_INET: - ret = ovpn_udp4_output(peer, bind, cache, sk, skb); + ret = ovpn_udp4_output(peer, bind, cache, sk, skb, sport, mark); break; #if IS_ENABLED(CONFIG_IPV6) case AF_INET6: - ret = ovpn_udp6_output(peer, bind, cache, sk, skb); + ret = ovpn_udp6_output(peer, bind, cache, sk, skb, sport, mark); break; #endif default: