Re: [PATCH ovpn net 3/9] ovpn: fix data race reading cached local endpoint on TX path

Antonio Quartulli <[email protected]>
Newsgroups gmane.network.openvpn.devel
Message-ID <[email protected]>
On 27/05/2026 01:18, Antonio Quartulli wrote:
> From: Antonio Quartulli <[email protected]>
> 
> 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 <[email protected]>

Using seqcount_spinlock may be a bit overkill and complicated.

Ralf is attempting a fix by turning the ovpn_bind object to an RCU 
protected pointer.

This way any modification will be made by creating a new bind object and 
purging the old one, rather than modifying the current one.

We'll see how large the patch happens to be and possibly replace this one.

Regards,


-- 
Antonio Quartulli
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.