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>
}
/* 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);
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:
*/
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",
{
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);