| 5940f340 | 28-Aug-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: reject invalid peer VPN addresses
In MP mode, ovpn uses peer VPN addresses as lookup keys for selecting the peer that should receive outgoing tunnel packets. The netlink configuration path cur
ovpn: reject invalid peer VPN addresses
In MP mode, ovpn uses peer VPN addresses as lookup keys for selecting the peer that should receive outgoing tunnel packets. The netlink configuration path currently accepts address values that cannot sensibly identify a VPN peer, such as multicast, broadcast or loopback addresses.
Reject invalid peer VPN addresses when creating or updating an MP peer. Keep accepting the unspecified address as the internal unset value, provided that at least one VPN address family remains configured.
Fixes: 1d36a36f6d53 ("ovpn: implement peer add/get/dump/delete via netlink") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| 025af3a0 | 28-Aug-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: reject multipeer peers without VPN addresses
In MP mode, ovpn uses the peer VPN addresses to select the peer for outgoing tunnel packets. Peer creation currently requires a VPN IPv4 or IPv6 at
ovpn: reject multipeer peers without VPN addresses
In MP mode, ovpn uses the peer VPN addresses to select the peer for outgoing tunnel packets. Peer creation currently requires a VPN IPv4 or IPv6 attribute, but it only checks for the presence of the attribute and not for a usable address value.
This allows userspace to create an MP peer with only unspecified VPN addresses, or to update an existing peer so that both VPN address families become unspecified. Such a peer cannot be selected through the VPN address hash tables.
Reject MP peer creation or update when the resulting peer would not have at least one VPN address configured.
This changes such configurations from being accepted to being rejected, but they have never been usable because the peer cannot be selected through the VPN address hash tables.
Fixes: 1d36a36f6d53 ("ovpn: implement peer add/get/dump/delete via netlink") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| d25e885b | 28-Aug-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: reject duplicate peer VPN addresses
In MP mode, ovpn uses the peer VPN addresses as lookup keys for selecting the peer that should receive an outgoing tunnel packet. However, the netlink peer
ovpn: reject duplicate peer VPN addresses
In MP mode, ovpn uses the peer VPN addresses as lookup keys for selecting the peer that should receive an outgoing tunnel packet. However, the netlink peer configuration path does not currently reject duplicate VPN addresses.
If two peers are configured with the same VPN address, both can be inserted in the VPN address hash table and lookups return whichever peer is found first. This makes peer selection ambiguous and dependent on hash insertion order.
Reject peer creation or update when the resulting VPN address is already assigned to another peer. Ignore unspecified addresses because those are not inserted in the VPN address hash tables.
This changes such configurations from being accepted to being rejected, but they have never worked reliably because peer selection is ambiguous.
Fixes: 1d36a36f6d53 ("ovpn: implement peer add/get/dump/delete via netlink") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| b43beccb | 28-Aug-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: always unhash old VPN addresses before rehashing
ovpn_peer_hash_vpn_ip updates the per-peer VPN address hash entries after userspace changes a peer VPN address. The current code removes an old
ovpn: always unhash old VPN addresses before rehashing
ovpn_peer_hash_vpn_ip updates the per-peer VPN address hash entries after userspace changes a peer VPN address. The current code removes an old hash entry only when the new address for that family is not the unspecified address.
When an address is cleared to 0.0.0.0 or ::, its hash node therefore remains linked in the bucket selected by the old address. The address comparison performed during lookup prevents the old address from matching, but the table retains a stale entry until the peer is removed or another address is configured for that family.
Always remove both old VPN address hash entries before conditionally adding the currently configured addresses back. This ensures that a cleared address leaves its hash node unhashed.
Fixes: 1d36a36f6d53 ("ovpn: implement peer add/get/dump/delete via netlink") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| 7d810498 | 28-Aug-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: replace bind when clearing stale local source
The UDP output fallback clears bind->local in place when the remembered source address is no longer usable. The bind is RCU-published and read loc
ovpn: replace bind when clearing stale local source
The UDP output fallback clears bind->local in place when the remembered source address is no longer usable. The bind is RCU-published and read locklessly by concurrent TX, so an IPv6 reader can observe a torn address.
Retry the route lookup with source address autoselection without modifying the bind. After a successful lookup, revalidate the bind and route key under peer->lock, reset the dst cache, and best-effort publish a replacement bind with a wildcard local address.
Do not cache the resolved dst when clearing the local source. Replacing the source invalidates all per-CPU cache entries, while dst_cache_set_ip4 and dst_cache_set_ip6 update only the current CPU slot. The current packet can still use the resolved route; if bind allocation fails, a later cache miss retries the repair.
Fixes: 08857b5ec5d9 ("ovpn: implement basic TX path (UDP)") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| aea934a2 | 28-Aug-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: replace bind when learning local endpoint
struct ovpn_bind is published through peer->bind with RCU, but local endpoint learning updates bind->local in place under peer->lock. UDP TX reads the
ovpn: replace bind when learning local endpoint
struct ovpn_bind is published through peer->bind with RCU, but local endpoint learning updates bind->local in place under peer->lock. UDP TX reads the field without that lock. In particular, a concurrent IPv6 update can therefore result in a torn address read.
Use ovpn_peer_reset_sockaddr to publish a replacement bind when learning a new local endpoint, just as a remote endpoint change does. Preserve the current remote address and reset the dst cache only after the new bind has been published successfully.
Track remote endpoint changes separately so that float notification and transport-address rehashing remain limited to actual peer floats.
Fixes: f0281c1d3732 ("ovpn: add support for updating local or remote UDP endpoint") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| fa603710 | 28-Aug-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: validate peer state before caching UDP dst
UDP route lookup runs without peer->lock while the bind is protected by RCU. The route key is snapshotted separately. Either can change while the loo
ovpn: validate peer state before caching UDP dst
UDP route lookup runs without peer->lock while the bind is protected by RCU. The route key is snapshotted separately. Either can change while the lookup is in progress.
The TX path currently checks only the route key before publishing the looked-up dst. If the bind changes but the route key does not, a dst resolved from the old endpoint can be installed in the cache after the bind replacement.
Compare both the bind pointer and the route key under peer->lock before updating the cache. The RCU read-side critical section keeps the old bind alive throughout the lookup, so pointer identity is sufficient to detect a replacement.
Fixes: f0281c1d3732 ("ovpn: add support for updating local or remote UDP endpoint") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| 7c66b7a4 | 28-Aug-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: track UDP socket route key for peer dst cache
ovpn stores the route used to transmit UDP packets in a per-peer dst cache. A cached dst is only valid for the route lookup inputs used when it wa
ovpn: track UDP socket route key for peer dst cache
ovpn stores the route used to transmit UDP packets in a per-peer dst cache. A cached dst is only valid for the route lookup inputs used when it was resolved.
Some of those inputs are mutable while userspace still owns the UDP socket. In particular, changes to the socket mark or UDP source port do not invalidate ovpn's peer dst cache, so ovpn can keep using a route selected with an old socket route key.
Replace the cached mark with a route key containing the socket-owned lookup inputs currently used by ovpn, and reset the peer dst cache when the key changes. Before storing a newly looked-up dst, recheck the route key under the peer lock so a dst resolved for stale socket state is not published.
Fixes: 08857b5ec5d9 ("ovpn: implement basic TX path (UDP)") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| 77393b4d | 28-Aug-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: skip UDP source validation for unspecified addresses
ovpn validates the cached local UDP source address before reusing or refreshing a peer dst cache. This is only meaningful when a concrete s
ovpn: skip UDP source validation for unspecified addresses
ovpn validates the cached local UDP source address before reusing or refreshing a peer dst cache. This is only meaningful when a concrete source address is selected.
For IPv6, calling ipv6_chk_addr with :: checks whether the unspecified address itself is configured on the host. A peer may legitimately have bind->local.ipv6 set to :: when no local endpoint was configured or after a stale learned address was cleared. In that case the source should be left unspecified and selected by ip6_dst_lookup_flow().
For IPv4, inet_confirm_addr(..., local = 0, ...) asks for local address autoselection rather than validating a chosen source. Skip the precheck there as well and let ip_route_output_flow select or reject the source.
Only validate non-zero/non-any source addresses.
Fixes: 08857b5ec5d9 ("ovpn: implement basic TX path (UDP)") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| 2da3dfa1 | 29-Jul-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: defer key slot crypto freeing to workqueue
Key slots are released through a kref and the existing release path frees the AEAD transforms from an RCU callback. That is not safe for all crypto i
ovpn: defer key slot crypto freeing to workqueue
Key slots are released through a kref and the existing release path frees the AEAD transforms from an RCU callback. That is not safe for all crypto implementations: crypto_free_aead can sleep, for example when an async or hardware implementation has teardown work to complete.
Use queue_rcu_work for key-slot release. This keeps the RCU grace period needed by lockless key-slot readers, but runs the actual crypto teardown from workqueue context where sleeping is allowed. Once the rcu_work callback runs, pre-existing RCU readers are gone, and the final kref put already proves that no transform user remains, so the worker can release the AEAD transforms and free the slot directly.
The previous patch drains ovpn_wq during module exit, so queued key-slot teardown work cannot outlive module text.
Fixes: 8534731dbf2d ("ovpn: implement packet processing") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| e9714db8 | 07-Aug-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: run deferred work on a module-owned workqueue
ovpn queues several work items whose callbacks execute module text. These works currently run on the global system workqueues, so module exit has
ovpn: run deferred work on a module-owned workqueue
ovpn queues several work items whose callbacks execute module text. These works currently run on the global system workqueues, so module exit has no driver-owned drain point that guarantees the callbacks have fully returned before the module text can be freed.
Object references protect the objects used by the callbacks, but they do not prove that a workqueue function has returned. In particular, a worker can drop the final reference that unblocks device teardown while it is still executing ovpn code.
Add a module-owned workqueue and queue all ovpn work items on it. During module exit, unregister rtnl and netlink first, flush the workqueue so ordinary ovpn workers finish, run the final RCU barrier, and destroy the workqueue last. This keeps the workqueue available for cleanup work queued from RCU callbacks, while ensuring no ovpn work item can outlive the module text.
The per-device delayed keepalive work remains explicitly disabled during netdev teardown (disable_delayed_work_sync in ndo_uninit), since flush_workqueue does not flush delayed work that is still only pending on its timer.
Fixes: 3ecfd9349f40 ("ovpn: implement keepalive mechanism") Fixes: 11851cbd60ea ("ovpn: implement TCP transport") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| 9e163917 | 29-Jul-2026 |
Ralf Lici <ralf@mandelbit.com> |
ovpn: finish crypto callback cleanup before peer release
Crypto completion callbacks hold both key-slot and peer references. The peer reference pins the netdev, and dropping the last peer reference
ovpn: finish crypto callback cleanup before peer release
Crypto completion callbacks hold both key-slot and peer references. The peer reference pins the netdev, and dropping the last peer reference can let netdev unregistration and module removal make progress.
Do not release that peer reference before the callback has finished its own cleanup. If ovpn_crypto_key_slot_put runs after ovpn_peer_put, it can schedule an RCU callback backed by module text after ovpn_cleanup rcu_barrier has already run. The TX error path also freed the remaining skb after ovpn_peer_put, leaving callback cleanup outside the peer/netdev lifetime window.
Release the key slot and free any remaining skb first, then drop the peer reference as the last callback action.
Fixes: 8534731dbf2d ("ovpn: implement packet processing") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| 26ba17d8 | 24-Jul-2026 |
Qingfang Deng <qingfang.deng@linux.dev> |
ovpn: fix incorrect use of rcu_access_pointer()
rcu_access_pointer() should only be used to test the value of a pointer, not to dereference it. As it's in a spin_lock_bh() critical section, use rcu_
ovpn: fix incorrect use of rcu_access_pointer()
rcu_access_pointer() should only be used to test the value of a pointer, not to dereference it. As it's in a spin_lock_bh() critical section, use rcu_dereference_bh() instead, avoiding an extra rcu_read_lock().
Fixes: f6226ae7a0cd ("ovpn: introduce the ovpn_socket object") Signed-off-by: Qingfang Deng <qingfang.deng@linux.dev> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| 4680c0eb | 28-Jul-2026 |
Antonio Quartulli <antonio@openvpn.net> |
ovpn: ensure TCP vars are initialized first
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 t
ovpn: ensure TCP vars are initialized first
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 <antonio@openvpn.net>
show more ...
|
| 0301aa32 | 28-Jul-2026 |
Antonio Quartulli <antonio@openvpn.net> |
ovpn: disable IPv4 redirects on MP interfaces
ovpn_mp_alloc() tried to disable SEND_REDIRECTS on a multipeer interface, but it runs from ovpn_net_init() (->ndo_init), which register_netdevice() invo
ovpn: disable IPv4 redirects on MP interfaces
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 <antonio@openvpn.net>
show more ...
|
| b47a52dc | 28-Jul-2026 |
Antonio Quartulli <antonio@openvpn.net> |
ovpn: hash floated peer by transport identity only
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 si
ovpn: hash floated peer by transport identity only
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 <antonio@openvpn.net>
show more ...
|
| 3f012bdb | 28-Jul-2026 |
Antonio Quartulli <antonio@openvpn.net> |
ovpn: zero-initialize sockaddr before learning a floated endpoint
ovpn_peer_endpoints_update() builds the new remote endpoint in an on-stack struct sockaddr_storage that is left uninitialized. For I
ovpn: zero-initialize sockaddr before learning a floated endpoint
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 <antonio@openvpn.net>
show more ...
|
| 59aed1eb | 28-Jul-2026 |
Antonio Quartulli <antonio@openvpn.net> |
ovpn: ensure socket is owned by ovpn before deref sk_user_data
Some subsystems, like BPF SOCKMAP, set sk_user_data without actually setting the encap_type.
For this reason, we must make sure that t
ovpn: ensure socket is owned by ovpn before deref sk_user_data
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 <antonio@openvpn.net>
show more ...
|
| cc12f724 | 28-Jul-2026 |
Antonio Quartulli <antonio@openvpn.net> |
ovpn: rehash peer in by_transp_addr table on CMD_PEER_SET
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_rese
ovpn: rehash peer in by_transp_addr table on CMD_PEER_SET
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 <antonio@openvpn.net>
show more ...
|
| 33ec1056 | 28-Jul-2026 |
Antonio Quartulli <antonio@openvpn.net> |
ovpn: skip rehash for peers already removed from by_id
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 on
ovpn: skip rehash for peers already removed from by_id
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 <antonio@openvpn.net>
show more ...
|
| 935dc3bb | 22-Jul-2026 |
Marco Baffo <marco@mandelbit.com> |
ovpn: limit keepalive values to one day
Large keepalive values can overflow the delayed-work delay on 32-bit systems, causing the keepalive worker to be repeatedly scheduled.
A correct configuratio
ovpn: limit keepalive values to one day
Large keepalive values can overflow the delayed-work delay on 32-bit systems, causing the keepalive worker to be repeatedly scheduled.
A correct configuration should not require such large keepalive values, and an upper limit of one day is already generous and unnecessary in practice. Limit both the keepalive interval and timeout to 86400 seconds.
Signed-off-by: Marco Baffo <marco@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|
| f7e6287c | 08-Jun-2026 |
Marco Baffo <marco@mandelbit.com> |
ovpn: use monotonic clock for peer keepalive timeouts
Replace ktime_get_real_seconds() with the monotonic ktime_get_boottime_seconds() to ensure the keepalive mechanism is robust against system cloc
ovpn: use monotonic clock for peer keepalive timeouts
Replace ktime_get_real_seconds() with the monotonic ktime_get_boottime_seconds() to ensure the keepalive mechanism is robust against system clock modifications.
Right now, the driver uses ktime_get_real_seconds() to track peer timeouts, relying on the system wall-clock.
An administrative time adjustment or an NTP sync that steps the clock forward can cause `now' to instantly exceed `last_recv + timeout'.
When this occurs, the driver artificially expires healthy peers. Depending on the OpenVPN user-space configuration, this triggers a premature tunnel restart (if --keepalive or --ping-restart is used) or a complete disconnection of the client (if --ping-exit is used).
Fixes: 3ecfd9349f40 ("ovpn: implement keepalive mechanism") Signed-off-by: Marco Baffo <marco@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
show more ...
|