| 0c0dddc0 | 13-May-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: disable BHs when updating device stats
ovpn updates dev->dstats from both process and softirq contexts. In particular, TCP paths may run from socket callbacks, workqueues or strparser work, wh
ovpn: disable BHs when updating device stats
ovpn updates dev->dstats from both process and softirq contexts. In particular, TCP paths may run from socket callbacks, workqueues or strparser work, while UDP receive and ovpn's ndo_start_xmit path may update the same per-device dstats from BH context.
Add ovpn device drop-stat helpers that disable BHs around dev_dstats_rx_dropped() and dev_dstats_tx_dropped(), and use them for drop accounting.
The successful RX dev_dstats_rx_add() update is already covered by the BH-disabled section around gro_cells_receive(). For the successful TCP TX dev_dstats_tx_add() update, replace the existing preempt-disabled section with a BH-disabled one.
Fixes: 11851cbd60ea ("ovpn: implement TCP transport") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| 982422b1 | 17-Mar-2026 |
Antonio Quartulli <antonio@openvpn.net> |
ovpn: fix race between deleting interface and adding new peer
While deleting an existing ovpn interface, there is a very narrow window where adding a new peer via netlink may cause the netdevice to
ovpn: fix race between deleting interface and adding new peer
While deleting an existing ovpn interface, there is a very narrow window where adding a new peer via netlink may cause the netdevice to hang and prevent its unregistration.
It may happen during ovpn_dellink(), when all existing peers are freed and the device is queued for deregistration, but a CMD_PEER_NEW message comes in adding a new peer that takes again a reference to the netdev.
At this point there is no way to release the device because we are under the assumption that all peers were already released.
Fix the race condition by releasing all peers in ndo_uninit(), when the netdevice has already been removed from the netdev list.
Also ovpn_peer_add() has now an extra check that forces the function to bail out if the device reg_state is not REGISTERED. This way any incoming CMD_PEER_NEW racing with the interface deletion routine will simply stop before adding the peer.
Note that the above check happens while holding the netdev_lock to prevent racing netdev state changes.
ovpn_dellink() is now empty and can be removed.
Reported-by: Hyunwoo Kim <imv4bel@gmail.com> Closes: https://lore.kernel.org/netdev/aaVgJ16edTfQkYbx@v4bel/ Suggested-by: Sabrina Dubroca <sd@queasysnail.net> Fixes: 80747caef33d ("ovpn: introduce the ovpn_peer object") Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| 1fef6614 | 13-May-2026 |
David Carlier <devnexen@gmail.com> |
ovpn: respect peer refcount in CMD_NEW_PEER error path
ovpn_nl_peer_new_doit()'s error path calls ovpn_peer_release() directly rather than ovpn_peer_put(), bypassing the kref. The accompanying comme
ovpn: respect peer refcount in CMD_NEW_PEER error path
ovpn_nl_peer_new_doit()'s error path calls ovpn_peer_release() directly rather than ovpn_peer_put(), bypassing the kref. The accompanying comment ("peer was not yet hashed, thus it is not used in any context") holds for UDP but not for TCP.
For UDP, the ovpn_socket union uses the .ovpn arm and never points back at a peer; UDP encap_recv looks up peers via the not-yet-populated hashtables, so the new peer is unreachable until ovpn_peer_add() publishes it.
For TCP, ovpn_socket_new() sets ovpn_sock->peer and ovpn_tcp_socket_attach() publishes ovpn_sock via rcu_assign_sk_user_data(). From that moment until ovpn_socket_release() detaches in the error path, the TCP fd is fully wired: userspace recvmsg / sendmsg / close / poll on the fd, as well as the strparser-driven ovpn_tcp_rcv() path, can reach the peer through sk_user_data -> ovpn_sock->peer and bump its refcount via ovpn_peer_hold().
ovpn_tcp_socket_wait_finish() (called inside ovpn_socket_release()) drains strparser and the tx work, but does not synchronize with userspace syscall callers that already hold a peer reference. If ovpn_nl_peer_modify() or ovpn_peer_add() returns an error while such a caller is in flight - notably an ovpn_tcp_recvmsg() blocked in __skb_recv_datagram() on peer->tcp.user_queue - the direct ovpn_peer_release() destroys the peer while the caller still holds the reference, and the eventual ovpn_peer_put() from that caller operates on freed memory.
Replace the direct destructor call with ovpn_peer_put() so the kref correctly defers destruction until the last reference is dropped. In the common case where no concurrent user is present, behaviour is unchanged: the kref hits zero immediately and ovpn_peer_release_kref() runs the same destructor.
With this conversion ovpn_peer_release() has no callers outside peer.c - ovpn_peer_release_kref() in the same translation unit is the only remaining user - so make it static and drop its declaration from peer.h.
Fixes: 11851cbd60ea ("ovpn: implement TCP transport") Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Assisted-by: Claude:claude-opus-4-7 Signed-off-by: David Carlier <devnexen@gmail.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| c539cb30 | 25-Mar-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: ensure packet delivery happens with BH disabled
ovpn injects decrypted packets into the netdev RX path through ovpn_netdev_write() which invokes gro_cells_receive() and dev_dstats_rx_add().
o
ovpn: ensure packet delivery happens with BH disabled
ovpn injects decrypted packets into the netdev RX path through ovpn_netdev_write() which invokes gro_cells_receive() and dev_dstats_rx_add().
ovpn_netdev_write() is normally called in softirq context, however, in case of TCP connections it may also be invoked process context.
When this happens gro_cells_receive() will throw a warning:
[ 230.183747][ T12] WARNING: net/core/gro_cells.c:30 at gro_cells_receive+0x708/0xaa0, CPU#1: kworker/u16:0/12
and lockdep will also report a potential inconsistent lock state:
WARNING: inconsistent lock state 7.0.0-rc4+ #246 Tainted: G W -------------------------------- inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
because attempts to acquire gro_cells->bh_lock by both contexts may lead to a deadlock.
At the same time, dev_dstats_rx_add() does not expect to race with a softirq (which may happen when invoked in process context), because the latter may access its per-cpu state and corrupt it.
Fix all this by invoking local_bh_disable/enable() around gro_cells_receive() and dev_dstats_rx_add() to ensure that bottom halves are always disabled before calling both of them.
Fixes: 11851cbd60ea ("ovpn: implement TCP transport") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| c841b676 | 14-Nov-2025 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: notify userspace on client float event
Send a netlink notification when a client updates its remote UDP endpoint. The notification includes the new IP address, port, and scope ID (for IPv6).
ovpn: notify userspace on client float event
Send a netlink notification when a client updates its remote UDP endpoint. The notification includes the new IP address, port, and scope ID (for IPv6).
Cc: linux-kselftest@vger.kernel.org Cc: horms@kernel.org Cc: shuah@kernel.org Cc: donald.hunter@gmail.com Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net> Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
show more ...
|
| 4a648059 | 28-May-2025 |
Qingfang Deng <dqfext@gmail.com> |
ovpn: pktid: use bitops.h API
Use bitops.h for replay window to simplify code.
Signed-off-by: Qingfang Deng <dqfext@gmail.com> [antonio@openvpn.net: extended commit message] Signed-off-by: Antonio
ovpn: pktid: use bitops.h API
Use bitops.h for replay window to simplify code.
Signed-off-by: Qingfang Deng <dqfext@gmail.com> [antonio@openvpn.net: extended commit message] Signed-off-by: Antonio Quartulli <antonio@openvpn.net> Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
show more ...
|
| 94560267 | 12-Feb-2026 |
Antonio Quartulli <antonio@openvpn.net> |
ovpn: tcp - don't deref NULL sk_socket member after tcp_close()
When deleting a peer in case of keepalive expiration, the peer is removed from the OpenVPN hashtable and is temporary inserted in a "r
ovpn: tcp - don't deref NULL sk_socket member after tcp_close()
When deleting a peer in case of keepalive expiration, the peer is removed from the OpenVPN hashtable and is temporary inserted in a "release list" for further processing.
This happens in: ovpn_peer_keepalive_work() unlock_ovpn(release_list)
This processing includes detaching from the socket being used to talk to this peer, by restoring its original proto and socket ops/callbacks.
In case of TCP it may happen that, while the peer is sitting in the release list, userspace decides to close the socket. This will result in a concurrent execution of:
tcp_close(sk) __tcp_close(sk) sock_orphan(sk) sk_set_socket(sk, NULL)
The last function call will set sk->sk_socket to NULL.
When the releasing routine is resumed, ovpn_tcp_socket_detach() will attempt to dereference sk->sk_socket to restore its original ops member. This operation will crash due to sk->sk_socket being NULL.
Fix this race condition by testing-and-accessing sk->sk_socket atomically under sk->sk_callback_lock.
Link: https://lore.kernel.org/netdev/176996279620.3109699.15382994681575380467@eldamar.lan/ Link: https://github.com/OpenVPN/ovpn-net-next/issues/29 Signed-off-by: Antonio Quartulli <antonio@openvpn.net> Fixes: 11851cbd60ea ("ovpn: implement TCP transport") Link: https://patch.msgid.link/20260212213130.11497-1-antonio@openvpn.net Signed-off-by: Paolo Abeni <pabeni@redhat.com>
show more ...
|
| b660b13d | 30-Jan-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: fix VPN TX bytes counting
In ovpn_net_xmit, after GSO segmentation and segment processing, the first segment on the list is used to increment VPN TX statistics, which fails to account for any
ovpn: fix VPN TX bytes counting
In ovpn_net_xmit, after GSO segmentation and segment processing, the first segment on the list is used to increment VPN TX statistics, which fails to account for any subsequent segments in the chain.
Fix this by accumulating the length of every segment that successfully passes skb_share_check into a tx_bytes variable. This ensures the peer statistics accurately reflect the total data volume sent, regardless of whether the original packet was segmented.
Fixes: 04ca14955f9a ("ovpn: store tunnel and transport statistics") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| a5ec7baa | 30-Jan-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: fix possible use-after-free in ovpn_net_xmit
When building the skb_list in ovpn_net_xmit, skb_share_check will free the original skb if it is shared. The current implementation continues to us
ovpn: fix possible use-after-free in ovpn_net_xmit
When building the skb_list in ovpn_net_xmit, skb_share_check will free the original skb if it is shared. The current implementation continues to use the stale skb pointer for subsequent operations: - peer lookup, - skb_dst_drop (even though all segments produced by skb_gso_segment will have a dst attached), - ovpn_peer_stats_increment_tx.
Fix this by moving the peer lookup and skb_dst_drop before segmentation so that the original skb is still valid when used. Return early if all segments fail skb_share_check and the list ends up empty. Also switch ovpn_peer_stats_increment_tx to use skb_list.next; the next patch fixes the stats logic.
Fixes: 08857b5ec5d9 ("ovpn: implement basic TX path (UDP)") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|