Re: [Openvpn-devel] [PATCH ovpn net v2 4/5] ovpn: avoid in-place updates of peer bind local address

Sabrina Dubroca <[email protected]>
Newsgroups net.sourceforge.lists.openvpn-devel
Message-ID <an33BZPh-XSyJ2Ks@krikkit>
Hi Ralf,

2026-07-29, 09:20:35 +0200, Ralf Lici wrote:
> struct ovpn_bind is published through peer->bind with RCU. Remote
> endpoint changes already replace the whole bind object, but local
> endpoint learning and UDP source fallback still updated bind->local in
> place. UDP TX can read it locklessly while another CPU updates it under
> peer->lock. For IPv6, that can produce torn reads of the address field.
> 
> Fix this by making the local endpoint immutable after publication too:
> build a new bind object with the updated local address and publish it
> through peer->bind.
> 
> When UDP TX discovers that the remembered local source is no longer
> usable, retry route lookup with a wildcard source. If the lookup
> succeeds and the bind used for the lookup is still current, invalidate
> the peer dst cache and best-effort publish a replacement bind with
> wildcard local address. The current packet can still be transmitted with
> the resolved route even if that bind replacement fails; a later cache
> miss will retry the repair.
> 
> Only store the resolved dst when the local address did not need to be
> reset. A local address change invalidates all per-CPU dst cache entries,
> while dst_cache_set_ip4 and dst_cache_set_ip6 only update the current
> CPU slot. Avoid the old reset-then-set pattern and let the next TX
> repopulate the cache from the new bind state.

This feels like 2 or 3 different bugs. At least making the endpoint
changes rebuild the bind object seems like a standalone patch.

> Fixes: f0281c1d3732 ("ovpn: add support for updating local or remote UDP endpoint")
> Fixes: 08857b5ec5d9 ("ovpn: implement basic TX path (UDP)")
> Signed-off-by: Ralf Lici <[email protected]>
> ---
> No changes since v1 https://lore.kernel.org/openvpn-devel/082540583b9145d89e1cdd5a74c485ea3a53d285.1785253480.git.ralf@mandelbit.com/
> 
>  drivers/net/ovpn/peer.c |  36 +++++++++-----
>  drivers/net/ovpn/udp.c  | 108 +++++++++++++++++++++++++++++++---------
>  2 files changed, 107 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
> index 4806e942be27..383d712582c9 100644
> --- a/drivers/net/ovpn/peer.c
> +++ b/drivers/net/ovpn/peer.c
[...]
> @@ -267,26 +263,40 @@ 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);
> -			bind->local.ipv6 = ipv6_hdr(skb)->daddr;
> -			reset_cache = true;
> +			local_ip = &ipv6_hdr(skb)->daddr;
>  		}
>  		break;
>  	default:
>  		goto unlock;
>  	}
>  
> -	if (unlikely(reset_cache))
> -		dst_cache_reset(&peer->dst_cache);
> -
> -	/* if the peer did not float, we can bail out now */
> -	if (likely(!salen))
> +	/* if there was no float and the local address is unchanged, bail out */
> +	if (likely(!salen && !local_ip))
>  		goto unlock;

nit: !salen is redundant? local_ip is also set in the float case.

but this whole check could be skipped by adding a "break" in the
"local endpoint changed" case and a "goto unlock" if nothing changed
in both cases of the skb->protocol switch.

>  
> +	/* if only the local address changed, populate ss with the current
> +	 * remote
> +	 */
> +	if (!salen)
> +		memcpy(&ss, &bind->remote,
> +		       bind->remote.in4.sin_family == AF_INET ?
> +			       sizeof(struct sockaddr_in) :
> +			       sizeof(struct sockaddr_in6));

nit: Maybe move that under the "learning local IPv*" blocks to avoid
the sizeof ugliness here?


-- 
Sabrina


_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.