[openssh-commits] [openssh] 13/87: upstream: correct timeout accounting for ConnectTimeout and
git+noreply at mindrot.org
git+noreply at mindrot.org
Fri Oct 30 20:20:50 AEDT 2026
This is an automated email from the git hooks/post-receive script.
djm pushed a commit to branch master
in repository openssh.
commit 287415219119341d039793052336b1d63ce15a0a
Author: djm at openbsd.org <djm at openbsd.org>
AuthorDate: Fri Oct 30 01:16:44 2026 +0000
upstream: correct timeout accounting for ConnectTimeout and
banner exchange that was broken in openssh-9.5, which caused the timeout to
be erroneously reset between successful reads.
Anthropic ANT-2026-2UMTJC7S
OpenBSD-Commit-ID: 7bc429b079b89ef82f5902ae40e39bc66debb369
---
kex.c | 17 +++++++++++++++--
misc.c | 27 +++++++++++++++++++++------
2 files changed, 36 insertions(+), 8 deletions(-)
diff --git a/kex.c b/kex.c
index d3015e8af..0e87a9f6a 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.196 2026/09/22 00:24:47 dtucker Exp $ */
+/* $OpenBSD: kex.c,v 1.197 2026/10/30 01:16:44 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@@ -1279,6 +1279,8 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
const char *version_addendum)
{
int remote_major, remote_minor, mismatch, oerrno = 0;
+ int have_timeout = timeout_ms > 0;
+ struct timespec now, remain, deadline;
size_t len, n;
int r, expect_nl;
u_char c;
@@ -1289,6 +1291,13 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
char *our_version_string = NULL, *peer_version_string = NULL;
char *cp, *remote_version = NULL;
+ /* The timeout applies to the whole exchange, not to each read */
+ if (have_timeout) {
+ monotime_ts(&now);
+ ms_to_timespec(&remain, timeout_ms);
+ timespecadd(&now, &remain, &deadline);
+ }
+
/* Prepare and send our banner */
sshbuf_reset(our_version);
if (version_addendum != NULL && *version_addendum == '\0')
@@ -1336,7 +1345,11 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
sshbuf_reset(peer_version);
expect_nl = 0;
for (;;) {
- if (timeout_ms > 0) {
+ if (have_timeout) {
+ ptimeout_init(&remain);
+ ptimeout_deadline_monotime_tsp(&remain,
+ &deadline);
+ timeout_ms = ptimeout_get_ms(&remain);
r = waitrfd(ssh_packet_get_connection_in(ssh),
&timeout_ms, NULL);
if (r == -1 && errno == ETIMEDOUT) {
diff --git a/misc.c b/misc.c
index d49c7100a..bc83e39fc 100644
--- a/misc.c
+++ b/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.221 2026/09/16 17:31:27 dtucker Exp $ */
+/* $OpenBSD: misc.c,v 1.222 2026/10/30 01:16:44 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005-2020 Damien Miller. All rights reserved.
@@ -374,7 +374,7 @@ static int
waitfd(int fd, int *timeoutp, short events, volatile sig_atomic_t *stop)
{
struct pollfd pfd;
- struct timespec timeout;
+ struct timespec timeout, now, deadline;
int oerrno, r;
sigset_t nsigset, osigset;
@@ -382,12 +382,18 @@ waitfd(int fd, int *timeoutp, short events, volatile sig_atomic_t *stop)
timeoutp = NULL;
pfd.fd = fd;
pfd.events = events;
- ptimeout_init(&timeout);
- if (timeoutp != NULL)
- ptimeout_deadline_ms(&timeout, *timeoutp);
+ if (timeoutp != NULL) {
+ /* Turn the relative timeout into an absolute deadline */
+ monotime_ts(&now);
+ ms_to_timespec(&timeout, *timeoutp);
+ timespecadd(&now, &timeout, &deadline);
+ }
if (stop != NULL)
sigfillset(&nsigset);
for (; timeoutp == NULL || *timeoutp >= 0;) {
+ ptimeout_init(&timeout);
+ if (timeoutp != NULL)
+ ptimeout_deadline_monotime_tsp(&timeout, &deadline);
if (stop != NULL) {
sigprocmask(SIG_BLOCK, &nsigset, &osigset);
if (*stop) {
@@ -401,8 +407,17 @@ waitfd(int fd, int *timeoutp, short events, volatile sig_atomic_t *stop)
oerrno = errno;
if (stop != NULL)
sigprocmask(SIG_SETMASK, &osigset, NULL);
- if (timeoutp)
+ if (timeoutp != NULL) {
+ ptimeout_init(&timeout);
+ ptimeout_deadline_monotime_tsp(&timeout, &deadline);
*timeoutp = ptimeout_get_ms(&timeout);
+ /*
+ * Callers treat a timeout <= 0 as "no timeout", so
+ * never report that none remains when fd is ready.
+ */
+ if (r > 0 && *timeoutp == 0)
+ *timeoutp = 1;
+ }
errno = oerrno;
if (r > 0)
return 0;
--
To stop receiving notification emails like this one, please contact
djm at mindrot.org.
More information about the openssh-commits
mailing list