[bug][sshd][security] ClientAliveInterval multiplied twice
Dawid Majchrzak (Nokia)
dawid.majchrzak at nokia.com
Mon Jun 5 20:36:58 AEST 2023
Hello,
My team discovered that starting from openssh v9.2 a ClientAliveInterval param from /etc/ssh/sshd_config
is interpreted as multiplied twice value.
----
Component: sshd
Version: 9.2p1 and higher
Hardware: ARM64
OS:Linux
----
sshd_config
----
ClientAliveInterval 5
ClientAliveCountMax 3
---
Debug logs
----
[2023-05-29 12:00:16] debug1: client_input_channel_req: channel 0 rtype keepalive at openssh.com reply 1
[2023-05-29 12:00:26] debug1: client_input_channel_req: channel 0 rtype keepalive at openssh.com reply 1
[2023-05-29 12:00:36] debug1: client_input_channel_req: channel 0 rtype keepalive at openssh.com reply 1
[2023-05-29 12:00:46] debug1: client_input_channel_req: channel 0 rtype keepalive at openssh.com reply 1
----
Looks like the problem was introduced with commit d478cdc7ad6edd4b1bcd1e86fb2f23194ff33d5a
With a new ptimeout api sshd server can double a client probing interval time.
commit d478cdc7ad6edd4b1bcd1e86fb2f23194ff33d5a
Author: djm at openbsd.org <djm at openbsd.org>
Date: Fri Jan 6 02:38:23 2023 +0000
upstream: replace manual poll/ppoll timeout math with ptimeout API
feedback markus / ok markus dtucker
OpenBSD-Commit-ID: c5ec4f2d52684cdb788cd9cbc1bcf89464014be2
@@ -251,19 +237,18 @@ wait_until_can_do_something(struct ssh *ssh,
*conn_in_readyp = (*pfdp)[0].revents != 0;
*conn_out_readyp = (*pfdp)[1].revents != 0;
+ /* ClientAliveInterval probing */
if (client_alive_scheduled) {
time_t now = monotime();
-
- /*
- * If the ppoll timed out, or returned for some other reason
- * but we haven't heard from the client in time, send keepalive.
- */
- if (ret == 0 || (last_client_time != 0 && last_client_time +
- options.client_alive_interval <= now)) {
+ if (ret == 0 &&
+ now > last_client_time + options.client_alive_interval) {
+ /* ppoll timed out and we're due to probe */
client_alive_check(ssh);
last_client_time = now;
- } else if (*conn_in_readyp)
+ } else if (ret != 0 && *conn_in_readyp) {
+ /* Data from peer; reset probe timer. */
last_client_time = now;
+ }
}
}
This bug can be easily fixed by changing client_alive_check() condition.
Proposed soulution/Fix:
>From 6cf45ca16c51cc99b5210dea708e22e4dec8b2b0 Mon Sep 17 00:00:00 2001
From: Dawid Majchrzak <dawid.majchrzak at nokia.com>
Date: Wed, 31 May 2023 18:51:53 +0200
Subject: [PATCH] serverloop: Fix ClientAliveInterval probing condition
Commit d478cdc7ad6edd4b1bcd1e86fb2f23194ff33d5a introduced
ClientAliveInterval parameter regression that can double a probing
interval time.
Signed-off-by: Dawid Majchrzak <dawid.majchrzak at nokia.com>
---
serverloop.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/serverloop.c b/serverloop.c
index de5fa2e3..f160550e 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -253,7 +253,7 @@ wait_until_can_do_something(struct ssh *ssh,
/* ClientAliveInterval probing */
if (client_alive_scheduled) {
if (ret == 0 &&
- now > last_client_time + options.client_alive_interval) {
+ now >= last_client_time + options.client_alive_interval) {
/* ppoll timed out and we're due to probe */
client_alive_check(ssh);
last_client_time = now;
--
2.25.1
BR, Dawid
More information about the openssh-unix-dev
mailing list