[openssh-commits] [openssh] 03/03: upstream: convert channel timeouts to use floating points, allows
git+noreply at mindrot.org
git+noreply at mindrot.org
Wed Sep 16 16:29:26 AEST 2026
This is an automated email from the git hooks/post-receive script.
djm pushed a commit to branch master
in repository openssh.
commit a253258c6d9ed991d7390f0d5569f83f189eab75
Author: djm at openbsd.org <djm at openbsd.org>
AuthorDate: Wed Sep 16 06:23:15 2026 +0000
upstream: convert channel timeouts to use floating points, allows
fractional and subsecond timeouts; ok markus, deraadt
OpenBSD-Commit-ID: f25665fc4e734ade36f6cb631dc28c6c54bb9e76
---
channels.c | 64 +++++++++++++++++++++++++++++-----------------------------
channels.h | 12 +++++------
misc.c | 31 ++++++++++++++++++++++++----
misc.h | 6 ++++--
monitor_wrap.c | 5 +++--
ssh.c | 8 +++++---
6 files changed, 77 insertions(+), 49 deletions(-)
diff --git a/channels.c b/channels.c
index e1c98d756..ad380dbe4 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.469 2026/09/16 05:00:51 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.470 2026/09/16 06:23:15 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo at cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -147,7 +147,7 @@ struct permission_set {
/* Used to record timeouts per channel type */
struct ssh_channel_timeout {
char *type_pattern;
- int timeout_secs;
+ double timeout_secs;
};
/* Master structure for channels state */
@@ -191,7 +191,7 @@ struct ssh_channels {
u_int x11_saved_data_len;
/* Deadline after which all X11 connections are refused */
- time_t x11_refuse_time;
+ double x11_refuse_time;
/*
* Fake X11 authentication data. This is what the server will be
@@ -211,8 +211,8 @@ struct ssh_channels {
struct ssh_channel_timeout *timeouts;
size_t ntimeouts;
/* Global timeout for all OPEN channels */
- int global_deadline;
- time_t lastused;
+ double global_deadline;
+ double lastused;
/* pattern-lists used to classify channels as bulk */
char *bulk_classifier_tty, *bulk_classifier_notty;
/* Number of active bulk channels (set by channel_handler) */
@@ -346,16 +346,16 @@ channel_set_tcp_keepalives(struct ssh *ssh, int on)
*/
void
channel_add_timeout(struct ssh *ssh, const char *type_pattern,
- int timeout_secs)
+ double timeout_secs)
{
struct ssh_channels *sc = ssh->chanctxt;
if (strcmp(type_pattern, "global") == 0) {
- debug2_f("global channel timeout %d seconds", timeout_secs);
+ debug2_f("global channel timeout %f seconds", timeout_secs);
sc->global_deadline = timeout_secs;
return;
}
- debug2_f("channel type \"%s\" timeout %d seconds",
+ debug2_f("channel type \"%s\" timeout %f seconds",
type_pattern, timeout_secs);
sc->timeouts = xrecallocarray(sc->timeouts, sc->ntimeouts,
sc->ntimeouts + 1, sizeof(*sc->timeouts));
@@ -379,7 +379,7 @@ channel_clear_timeouts(struct ssh *ssh)
sc->ntimeouts = 0;
}
-static int
+static double
lookup_timeout(struct ssh *ssh, const char *type)
{
struct ssh_channels *sc = ssh->chanctxt;
@@ -426,13 +426,13 @@ channel_set_xtype(struct ssh *ssh, int id, const char *xctype)
free(c->xctype);
c->xctype = xstrdup(xctype);
/* Only override deadline if xctype has a more specific match. */
- int xtype_deadline = lookup_timeout(ssh, c->xctype);
+ double xtype_deadline = lookup_timeout(ssh, c->xctype);
if (xtype_deadline != 0)
c->inactive_deadline = xtype_deadline;
channel_classify(ssh, c);
/* report effective timeout: per-channel if set, else global */
- debug2_f("labeled channel %d as %s (inactive timeout %d)", id, xctype,
- c->inactive_deadline != 0 ?
+ debug2_f("labeled channel %d as %s (inactive timeout %f)", id, xctype,
+ c->inactive_deadline != 0.0 ?
c->inactive_deadline : sc->global_deadline);
}
@@ -443,7 +443,7 @@ channel_set_xtype(struct ssh *ssh, int id, const char *xctype)
static void
channel_set_used_time(struct ssh *ssh, Channel *c)
{
- ssh->chanctxt->lastused = monotime();
+ ssh->chanctxt->lastused = monotime_double();
if (c != NULL)
c->lastused = ssh->chanctxt->lastused;
}
@@ -452,11 +452,11 @@ channel_set_used_time(struct ssh *ssh, Channel *c)
* Get the time at which a channel is due to time out for inactivity.
* Returns 0 if the channel is not due to time out ever.
*/
-static time_t
+static double
channel_get_expiry(struct ssh *ssh, Channel *c)
{
struct ssh_channels *sc = ssh->chanctxt;
- time_t expiry = 0, channel_expiry;
+ double expiry = 0, channel_expiry;
if (sc->lastused != 0 && sc->global_deadline != 0)
expiry = sc->lastused + sc->global_deadline;
@@ -603,8 +603,8 @@ channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd,
c->inactive_deadline = lookup_timeout(ssh, c->ctype);
TAILQ_INIT(&c->status_confirms);
channel_classify(ssh, c);
- debug("channel %d: new %s [%s] (inactive timeout: %d)",
- found, c->ctype, remote_name, c->inactive_deadline != 0 ?
+ debug("channel %d: new %s [%s] (inactive timeout: %f)",
+ found, c->ctype, remote_name, c->inactive_deadline != 0.0 ?
c->inactive_deadline : sc->global_deadline);
return c;
}
@@ -1432,8 +1432,8 @@ x11_open_helper(struct ssh *ssh, struct sshbuf *b)
}
/* Is this being called after the refusal deadline? */
- if (sc->x11_refuse_time != 0 &&
- monotime() >= sc->x11_refuse_time) {
+ if (sc->x11_refuse_time != 0.0 &&
+ monotime_double() >= sc->x11_refuse_time) {
verbose("Rejected X11 connection after ForwardX11Timeout "
"expired");
return -1;
@@ -1980,7 +1980,7 @@ channel_post_x11_listener(struct ssh *ssh, Channel *c)
errno != ECONNABORTED)
error("accept: %.100s", strerror(errno));
if (errno == EMFILE || errno == ENFILE)
- c->notbefore = monotime() + 1;
+ c->notbefore = monotime_double() + 1.0;
return;
}
set_nodelay(newsock);
@@ -2064,7 +2064,7 @@ port_open_helper(struct ssh *ssh, Channel *c, char *rtype)
}
void
-channel_set_x11_refuse_time(struct ssh *ssh, time_t refuse_time)
+channel_set_x11_refuse_time(struct ssh *ssh, double refuse_time)
{
ssh->chanctxt->x11_refuse_time = refuse_time;
}
@@ -2111,7 +2111,7 @@ channel_post_port_listener(struct ssh *ssh, Channel *c)
errno != ECONNABORTED)
error("accept: %.100s", strerror(errno));
if (errno == EMFILE || errno == ENFILE)
- c->notbefore = monotime() + 1;
+ c->notbefore = monotime_double() + 1.0;
return;
}
if (addr.ss_family == AF_INET || addr.ss_family == AF_INET6) {
@@ -2150,7 +2150,7 @@ channel_post_auth_listener(struct ssh *ssh, Channel *c)
if (newsock == -1) {
error("accept from auth socket: %.100s", strerror(errno));
if (errno == EMFILE || errno == ENFILE)
- c->notbefore = monotime() + 1;
+ c->notbefore = monotime_double() + 1.0;
return;
}
nc = channel_new(ssh, "agent-connection",
@@ -2640,7 +2640,7 @@ channel_post_mux_listener(struct ssh *ssh, Channel *c)
&addrlen)) == -1) {
error_f("accept: %s", strerror(errno));
if (errno == EMFILE || errno == ENFILE)
- c->notbefore = monotime() + 1;
+ c->notbefore = monotime_double() + 1.0;
return;
}
@@ -2738,9 +2738,9 @@ channel_handler(struct ssh *ssh, int table, struct timespec *timeout)
chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post;
u_int i, oalloc;
Channel *c;
- time_t now;
+ double now;
- now = monotime();
+ now = monotime_double();
for (sc->nbulk = i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) {
c = sc->channels[i];
if (c == NULL)
@@ -2762,10 +2762,10 @@ channel_handler(struct ssh *ssh, int table, struct timespec *timeout)
channel_get_expiry(ssh, c) != 0 &&
now >= channel_get_expiry(ssh, c)) {
/* channel closed for inactivity */
- int fired_deadline = c->inactive_deadline != 0 ?
+ double deadline = c->inactive_deadline != 0.0 ?
c->inactive_deadline : sc->global_deadline;
- verbose("channel %d: closing after %d seconds "
- "of inactivity", c->self, fired_deadline);
+ verbose("channel %d: closing after %f seconds "
+ "of inactivity", c->self, deadline);
channel_force_close(ssh, c, 1);
} else if (c->notbefore <= now) {
/* Run handlers that are not paused. */
@@ -5485,15 +5485,15 @@ int
x11_channel_used_recently(struct ssh *ssh) {
u_int i;
Channel *c;
- time_t lastused = 0;
+ double lastused = 0;
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
c = ssh->chanctxt->channels[i];
- if (c == NULL || c->ctype == NULL || c->lastused == 0 ||
+ if (c == NULL || c->ctype == NULL || c->lastused == 0.0 ||
strcmp(c->ctype, "x11-connection") != 0)
continue;
if (c->lastused > lastused)
lastused = c->lastused;
}
- return lastused != 0 && monotime() <= lastused + 1;
+ return lastused != 0.0 && monotime_double() <= lastused + 1.0;
}
diff --git a/channels.h b/channels.h
index 8311749e2..cc520ba13 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.168 2026/09/16 00:13:58 djm Exp $ */
+/* $OpenBSD: channels.h,v 1.169 2026/09/16 06:23:15 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo at cs.hut.fi>
@@ -147,7 +147,7 @@ struct Channel {
#endif
int client_tty; /* (client) TTY has been requested */
int force_drain; /* force close on iEOF */
- time_t notbefore; /* Pause IO until deadline (time_t) */
+ double notbefore; /* Pause IO until deadline (time_t) */
int delayed; /* post-IO handlers for newly created
* channels are delayed until the first call
* to a matching pre-IO handler.
@@ -211,9 +211,9 @@ struct Channel {
/* Inactivity timeouts */
/* Last traffic seen for OPEN channels */
- time_t lastused;
+ double lastused;
/* Inactivity timeout deadline in seconds (0 = no timeout) */
- int inactive_deadline;
+ double inactive_deadline;
};
#define CHAN_EXTENDED_IGNORE 0
@@ -315,7 +315,7 @@ int channel_has_bulk(struct ssh *);
void channel_set_tcp_keepalives(struct ssh *, int);
/* channel inactivity timeouts */
-void channel_add_timeout(struct ssh *, const char *, int);
+void channel_add_timeout(struct ssh *, const char *, double);
void channel_clear_timeouts(struct ssh *);
/* mux proxy support */
@@ -383,7 +383,7 @@ int permitopen_port(const char *);
/* x11 forwarding */
-void channel_set_x11_refuse_time(struct ssh *, time_t);
+void channel_set_x11_refuse_time(struct ssh *, double);
int x11_connect_display(struct ssh *);
int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **);
void x11_request_forwarding_with_spoofing(struct ssh *, int,
diff --git a/misc.c b/misc.c
index b6e05461b..33d9d7061 100644
--- a/misc.c
+++ b/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.219 2026/09/16 00:13:58 djm Exp $ */
+/* $OpenBSD: misc.c,v 1.220 2026/09/16 06:23:15 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005-2020 Damien Miller. All rights reserved.
@@ -2633,10 +2633,10 @@ format_absolute_time(uint64_t t, char *buf, size_t len)
* Caller must free *typep.
*/
int
-parse_pattern_interval(const char *s, char **typep, int *secsp)
+parse_pattern_interval(const char *s, char **typep, double *secsp)
{
char *cp, *sdup;
- int secs;
+ double secs;
if (typep != NULL)
*typep = NULL;
@@ -2651,7 +2651,7 @@ parse_pattern_interval(const char *s, char **typep, int *secsp)
return -1;
}
*cp++ = '\0';
- if ((secs = convtime(cp)) < 0) {
+ if ((secs = convtime_double(cp)) < 0.0) {
free(sdup);
return -1;
}
@@ -3085,6 +3085,22 @@ ptimeout_deadline_ms(struct timespec *pt, long ms)
ptimeout_deadline_tsp(pt, &p);
}
+/* Specify a poll/ppoll deadline of at most 'sec' seconds (double) */
+void
+ptimeout_deadline_sec_double(struct timespec *pt, double sec)
+{
+ struct timespec t;
+
+ memset(&t, 0, sizeof(t));
+ if ((int64_t)sec > SSH_TIME_T_MAX)
+ t.tv_sec = SSH_TIME_T_MAX;
+ else if (sec > 0) {
+ t.tv_sec = sec;
+ t.tv_nsec = (sec - (double)t.tv_sec) * 1000000000.0;
+ }
+ ptimeout_deadline_tsp(pt, &t);
+}
+
/* Specify a poll/ppoll deadline at wall clock monotime 'when' (timespec) */
void
ptimeout_deadline_monotime_tsp(struct timespec *pt, struct timespec *when)
@@ -3103,6 +3119,13 @@ ptimeout_deadline_monotime_tsp(struct timespec *pt, struct timespec *when)
}
}
+/* Specify a poll/ppoll deadline at wall clock monotime 'when' (double) */
+void
+ptimeout_deadline_monotime_double(struct timespec *pt, double when)
+{
+ ptimeout_deadline_sec_double(pt, when - monotime_double());
+}
+
/* Specify a poll/ppoll deadline at wall clock monotime 'when' */
void
ptimeout_deadline_monotime(struct timespec *pt, time_t when)
diff --git a/misc.h b/misc.h
index 589213f21..0784f379b 100644
--- a/misc.h
+++ b/misc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.119 2026/09/16 00:25:50 djm Exp $ */
+/* $OpenBSD: misc.h,v 1.120 2026/09/16 06:23:16 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo at cs.hut.fi>
@@ -109,7 +109,7 @@ int valid_env_name(const char *);
const char *atoi_err(const char *, int *);
int parse_absolute_time(const char *, uint64_t *);
void format_absolute_time(uint64_t, char *, size_t);
-int parse_pattern_interval(const char *, char **, int *);
+int parse_pattern_interval(const char *, char **, double *);
int path_absolute(const char *);
int stdfd_devnull(int, int, int);
int lib_contains_symbol(const char *, const char *);
@@ -234,8 +234,10 @@ struct timespec;
void ptimeout_init(struct timespec *pt);
void ptimeout_deadline_sec(struct timespec *pt, long sec);
void ptimeout_deadline_ms(struct timespec *pt, long ms);
+void ptimeout_deadline_sec_double(struct timespec *pt, double sec);
void ptimeout_deadline_monotime_tsp(struct timespec *pt, struct timespec *when);
void ptimeout_deadline_monotime(struct timespec *pt, time_t when);
+void ptimeout_deadline_monotime_double(struct timespec *pt, double when);
int ptimeout_get_ms(struct timespec *pt);
struct timespec *ptimeout_get_tsp(struct timespec *pt);
int ptimeout_isset(struct timespec *pt);
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 3d68f804f..c828fce04 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.c,v 1.150 2026/09/16 00:29:44 djm Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.151 2026/09/16 06:23:16 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos at citi.umich.edu>
* Copyright 2002 Markus Friedl <markus at openbsd.org>
@@ -1171,7 +1171,8 @@ server_process_permitopen(struct ssh *ssh)
void
server_process_channel_timeouts(struct ssh *ssh)
{
- u_int i, secs;
+ u_int i;
+ double secs;
char *type;
debug3_f("setting %u timeouts", options.num_channel_timeouts);
diff --git a/ssh.c b/ssh.c
index b87d4c1cc..3eb721211 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.638 2026/09/16 00:13:58 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.639 2026/09/16 06:23:16 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo at cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -1693,14 +1693,16 @@ main(int ac, char **av)
/* Apply channels timeouts, if set */
channel_clear_timeouts(ssh);
for (j = 0; j < options.num_channel_timeouts; j++) {
+ double timeout;
+
debug3("applying channel timeout %s",
options.channel_timeouts[j]);
if (parse_pattern_interval(options.channel_timeouts[j],
- &cp, &i) != 0) {
+ &cp, &timeout) != 0) {
fatal_f("internal error: bad timeout %s",
options.channel_timeouts[j]);
}
- channel_add_timeout(ssh, cp, i);
+ channel_add_timeout(ssh, cp, timeout);
free(cp);
}
channel_set_tcp_keepalives(ssh,
--
To stop receiving notification emails like this one, please contact
djm at mindrot.org.
More information about the openssh-commits
mailing list