[PATCH] channels: fix ChannelTimeout deadline for global= and xctype refinement

Bhagavathiyappan Shanmugam via openssh-unix-dev <[email protected]>
Newsgroups gmane.network.openssh.devel
Message-ID <[email protected]>
Hi,

This patch fixes two issues with ChannelTimeout in channels.c.

Bug 1 — Functional: session= timeout never fires
-------------------------------------------------
When ChannelTimeout session=5s is configured, the timeout is correctly
set in channel_new() but silently destroyed by channel_set_xtype() when
the channel is refined from "session" to "session:shell" or
"session:command". lookup_timeout("session:shell") returns 0 because the
pattern "session" does not match "session:shell", and the old code
unconditionally overwrote inactive_deadline with 0.

Steps to reproduce:
  ssh -o ChannelTimeout="session=5s" user@host "sleep 8"

Expected: connection killed after 5 seconds of inactivity
Actual:   sleep 8 completes after 8 seconds, timeout never fires

Debug evidence:
  debug1: channel 0: new session [client-session] (inactive timeout: 5)
  debug2: channel_set_xtype: labeled channel 0 as session:command (inactive timeout 0)
  [session runs for full 8 seconds, no timeout]
  debug1: Exit status 0


Bug 2 — Display: global= shows 0 in three debug messages
---------------------------------------------------------
When ChannelTimeout global=10s is configured, three debug messages
incorrectly print 0 instead of 10. The global deadline is stored in
sc->global_deadline, not c->inactive_deadline, but the messages only
read c->inactive_deadline.

Steps to reproduce:
  ssh -vvv -o ChannelTimeout="global=10s" user@host

Expected:
  channel 0: new session [client-session] (inactive timeout: 10)
  channel_set_xtype: labeled channel 0 as session:shell (inactive timeout 10)
  channel 0: closing after 10 seconds of inactivity

Actual:
  channel 0: new session [client-session] (inactive timeout: 0)
  channel_set_xtype: labeled channel 0 as session:shell (inactive timeout 0)
  channel 0: closing after 0 seconds of inactivity


Fix
---
Fix 1: In channel_set_xtype(), only overwrite inactive_deadline when
the xctype lookup actually finds a match — preserving the ctype-level
deadline otherwise.

Fix 2: In three debug messages, fall back to sc->global_deadline when
c->inactive_deadline is 0.

Tested on OpenSSH_10.5p1 (macOS).
---


From 36d9a7920055b5306bd4f49e2aa92832c9b84b91 Mon Sep 17 00:00:00 2001

From: Bhagavathiyappan Shanmugam <[email protected]<mailto:[email protected]>>

Date: Fri, 21 Aug 2026 12:32:29 +0530

Subject: [PATCH] channels: fix ChannelTimeout deadline for global= and xctype

 refinement


channel_set_xtype() is called after channel_new() to refine the channel

type (e.g. "session" -> "session:shell"). When ChannelTimeout session=5s

is configured, lookup_timeout("session:shell") returns 0 because the

pattern "session" does not match "session:shell". The previous code

unconditionally overwrote inactive_deadline with 0, destroying the value

set by channel_new() and preventing the timeout from ever firing.


Fix: only update inactive_deadline when the xctype lookup finds a

configured match, so a more specific xctype pattern can still override

the ctype-level deadline but an unmatched xctype never erases it.


Also fix three debug messages that printed 0 instead of the configured

value when ChannelTimeout global=Xs is used. The global deadline is

stored in sc->global_deadline, not c->inactive_deadline, so the log

messages now fall back to sc->global_deadline when inactive_deadline

is 0.

---

 channels.c | 21 +++++++++++++++------

 1 file changed, 15 insertions(+), 6 deletions(-)


diff --git a/channels.c b/channels.c

index fcd80288f..9b9936558 100644

--- a/channels.c

+++ b/channels.c

@@ -378,6 +378,7 @@ channel_classify(struct ssh *ssh, Channel *c)

 void

 channel_set_xtype(struct ssh *ssh, int id, const char *xctype)

 {

+ struct ssh_channels *sc = ssh->chanctxt;

  Channel *c;



  if ((c = channel_by_id(ssh, id)) == NULL)

@@ -385,11 +386,15 @@ channel_set_xtype(struct ssh *ssh, int id, const char *xctype)

  if (c->xctype != NULL)

  free(c->xctype);

  c->xctype = xstrdup(xctype);

- /* Type has changed, so look up inactivity deadline again */

- c->inactive_deadline = lookup_timeout(ssh, c->xctype);

+ /* Only override deadline if xctype has a more specific match. */

+ int 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 %u)", id, xctype,

-     c->inactive_deadline);

+     c->inactive_deadline != 0 ? c->inactive_deadline

+     : (u_int)sc->global_deadline);

 }



 /*

@@ -560,7 +565,9 @@ channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd,

  TAILQ_INIT(&c->status_confirms);

  channel_classify(ssh, c);

  debug("channel %d: new %s [%s] (inactive timeout: %u)",

-     found, c->ctype, remote_name, c->inactive_deadline);

+     found, c->ctype, remote_name,

+     c->inactive_deadline != 0 ? c->inactive_deadline

+     : (u_int)sc->global_deadline);

  return c;

 }



@@ -2708,9 +2715,11 @@ 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 */

+ u_int fired_deadline = c->inactive_deadline != 0

+     ? c->inactive_deadline

+     : (u_int)sc->global_deadline;

  verbose("channel %d: closing after %u seconds "

-     "of inactivity", c->self,

-     c->inactive_deadline);

+     "of inactivity", c->self, fired_deadline);

  channel_force_close(ssh, c, 1);

  } else if (c->notbefore <= now) {

  /* Run handlers that are not paused. */

--

2.50.1 (Apple Git-155)


———
Reported a issue in Bugzilla as well, please find the attached link to it,
https://bugzilla.mindrot.org/show_bug.cgi?id=3994

Thank You,
Bhagavathiyappan


Get Outlook for Mac<https://aka.ms/GetOutlookForMac>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.