[Openvpn-devel,ovpn,net] ovpn: use monotonic clock for peer keepalive timeouts

Message ID 20260608140642.546546-1-marco@mandelbit.com
State New
Headers
Series [Openvpn-devel,ovpn,net] ovpn: use monotonic clock for peer keepalive timeouts |

Commit Message

Marco Baffo June 8, 2026, 2:06 p.m. UTC
  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).

Signed-off-by: Marco Baffo <marco@mandelbit.com>
---
 drivers/net/ovpn/io.c   | 4 ++--
 drivers/net/ovpn/peer.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
  

Comments

Antonio Quartulli June 8, 2026, 2:19 p.m. UTC | #1
From: Antonio Quartulli <antonio@openvpn.net>


On Mon, 08 Jun 2026 16:06:42 +0200, Marco Baffo wrote:
> 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'.
> 
> [...]

Applied, thanks!

[1/1] ovpn: use monotonic clock for peer keepalive timeouts
      commit: 573bb65040d2b815888f56e8c96f58659fdfee9c

Best regards,
  

Patch

diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c
index 22c555dd962e..802d39ef38e5 100644
--- a/drivers/net/ovpn/io.c
+++ b/drivers/net/ovpn/io.c
@@ -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:
diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index c02dfab51a6e..ef1da9e03b5a 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -44,7 +44,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",
@@ -1342,7 +1342,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);