]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ovpn: use monotonic clock for peer keepalive timeouts
authorMarco Baffo <marco@mandelbit.com>
Mon, 8 Jun 2026 14:06:42 +0000 (16:06 +0200)
committerAntonio Quartulli <antonio@openvpn.net>
Mon, 20 Jul 2026 14:29:31 +0000 (16:29 +0200)
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>
drivers/net/ovpn/io.c
drivers/net/ovpn/peer.c

index a6b777a9c2d9a248bd00e9a1b89ea19cb2b367b3..9a66d693039a3cf07a82037f98bd4beb0b9fe9dc 100644 (file)
@@ -142,7 +142,7 @@ void ovpn_decrypt_post(void *data, int ret)
        }
 
        /* keep track of last received authenticated packet for keepalive */
-       WRITE_ONCE(peer->last_recv, ktime_get_real_seconds());
+       WRITE_ONCE(peer->last_recv, ktime_get_boottime_seconds());
 
        rcu_read_lock();
        sock = rcu_dereference(peer->sock);
@@ -294,7 +294,7 @@ void ovpn_encrypt_post(void *data, int ret)
 
        ovpn_peer_stats_increment_tx(&peer->link_stats, orig_len);
        /* keep track of last sent packet for keepalive */
-       WRITE_ONCE(peer->last_sent, ktime_get_real_seconds());
+       WRITE_ONCE(peer->last_sent, ktime_get_boottime_seconds());
        /* skb passed down the stack - don't free it */
        skb = NULL;
 err_unlock:
index 8fdbb5050690be23659c7c22939064349596f2ed..a21d02ac715e0e342f9c80f5c0f27100628b938a 100644 (file)
@@ -45,7 +45,7 @@ static void unlock_ovpn(struct ovpn_priv *ovpn,
  */
 void ovpn_peer_keepalive_set(struct ovpn_peer *peer, u32 interval, u32 timeout)
 {
-       time64_t now = ktime_get_real_seconds();
+       time64_t now = ktime_get_boottime_seconds();
 
        netdev_dbg(peer->ovpn->dev,
                   "scheduling keepalive for peer %u: interval=%u timeout=%u\n",
@@ -1359,7 +1359,7 @@ void ovpn_peer_keepalive_work(struct work_struct *work)
 {
        struct ovpn_priv *ovpn = container_of(work, struct ovpn_priv,
                                              keepalive_work.work);
-       time64_t next_run = 0, now = ktime_get_real_seconds();
+       time64_t next_run = 0, now = ktime_get_boottime_seconds();
        LLIST_HEAD(release_list);
 
        spin_lock_bh(&ovpn->lock);