Bug 1818 - SSH2_MSG_CHANNEL_FAILURE on closed channel
Summary: SSH2_MSG_CHANNEL_FAILURE on closed channel
Status: CLOSED FIXED
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: sshd (show other bugs)
Version: 5.1p1
Hardware: All All
: P2 normal
Assignee: Assigned to nobody
URL:
Keywords:
Depends on:
Blocks: V_6_7
  Show dependency treegraph
 
Reported: 2010-09-14 04:03 AEST by Simon Tatham
Modified: 2021-10-14 01:40 AEDT (History)
3 users (show)

See Also:


Attachments
putty.log : SSH packet log of failing connection (redacted) (174.94 KB, application/octet-stream)
2010-09-14 04:08 AEST, Simon Tatham
no flags Details
openssh-channel-failure.diff : proposed patch (529 bytes, patch)
2010-09-14 04:13 AEST, Simon Tatham
no flags Details | Diff
improved fix handling both client and server (1.18 KB, patch)
2014-04-19 20:21 AEST, Simon Tatham
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Simon Tatham 2010-09-14 04:03:45 AEST
When I connect to an OpenSSH server using PuTTY with X11 forwarding, and run a makefile I use which invokes a large number of X applications in rapid succession, I find PuTTY terminates the session with a message along the lines of "Disconnected: Received SSH2_MSG_CHANNEL_FAILURE for nonexistent channel 257" (the channel number may vary).

I told PuTTY to produce a full session log, which I attach here. (Sorry it's a bit large.) You can indeed see that PuTTY receives the final SSH2_MSG_CHANNEL_FAILURE at a point when it has both sent and received SSH2_MSG_CHANNEL_CLOSE on that channel. RFC 4254 section 5.3 states that when a party has both sent and received SSH2_MSG_CHANNEL_CLOSE for a channel, that channel is considered closed for that party and it may reuse the channel number; PuTTY's indignation at receiving the CHANNEL_FAILURE at that time therefore seems reasonable to me.

I think what must have happened is that OpenSSHD sent its CHANNEL_CLOSE before it received the CHANNEL_REQUEST and CHANNEL_CLOSE from PuTTY; so when _it_ received the CHANNEL_REQUEST, it had sent but not received CHANNEL_CLOSE, and hence it did not yet consider the channel closed and felt free to respond to the request.

However, although that sounds reasonable, I think it is in fact wrong behaviour. I think a direct logical consequence of section 5.3 is that after sending CHANNEL_CLOSE on a channel a party MUST NOT send any subsequent responses to channel events - because it can't be sure the other party hasn't just sent its own CHANNEL_CLOSE, causing exactly this circumstance. Conversely, on receiving CHANNEL_CLOSE, a party must discard any outstanding channel requests for which it was expecting to receive responses, and assume those requests were not received by the server until after it sent its close. I can't think of any other interpretation of RFC 4254 devoid of race conditions.

(The channel request type is "winadj@putty.projects.tartarus.org": a phony channel request designed to elicit a CHANNEL_FAILURE which PuTTY uses to tune its window adjustment policy. I don't think that detail is important except inasmuch as it has the want_reply flag set.)

I report this bug against 5.1p1, because that's the version in Debian stable. However, I have reproduced the same behaviour with openssh-SNAP-20100914 downloaded by following the links from http://www.openssh.com/portable.html, so I don't think this is an already-fixed issue.
Comment 1 Simon Tatham 2010-09-14 04:08:37 AEST
Created attachment 1925 [details]
putty.log : SSH packet log of failing connection (redacted)
Comment 2 Simon Tatham 2010-09-14 04:10:07 AEST
Sorry about that; my packet log was apparently too big for Bugzilla to accept. I've attached a redacted version, produced using the Perl one-liner

perl -ne 'if (/^\S/) { splice @lines, 2, $#lines-3, "  ...\n" if $#lines >= 5; print @lines; @lines = (); print; } else { push @lines, $_; }'

and hopefully that still shows the sequence of events (from PuTTY's viewpoint) and all important numbers and details without the huge wodges of irrelevant channel data.
Comment 3 Simon Tatham 2010-09-14 04:13:15 AEST
Created attachment 1926 [details]
openssh-channel-failure.diff : proposed patch

Here's a trivial patch which seems to work for me: after I apply this (against last month's snapshot, not 5.1p1) my complex makefile runs to completion without any issues at the SSH level. As I discussed in my comments earlier, it simply suppresses generation of SSH2_MSG_CHANNEL_{SUCCESS,FAILURE} for channels on which SSH2_MSG_CHANNEL_CLOSE has already been sent. (It lacks comments and rationale, though; it's merely a proof of concept.)
Comment 4 Damien Miller 2010-09-14 10:51:45 AEST
Thanks for the detailed report.

I don't see anything in RFC 4254 section 5.3 indicating that a channel shouldn't send notifications while it is half-closed. Could you explain how you arrived at this interpretation?
Comment 5 Simon Tatham 2010-09-14 17:37:42 AEST
Because if you send anything that arrives at the other side when _it_ thinks the channel is fully closed, that's definitely in violation of 5.3. So if you send stuff after you've sent CLOSE, then it _might_ cross in transit with the other side's CLOSE, in which case it would arrive at the other side when that side had already both sent and received CLOSE.

I discussed this last night with a friend, and he pointed out that there is an alternative protocol fix which also works, but it's more clearly contradictory of explicit text in the RFC. Instead of ruling that requests received after we send CLOSE may not be responded to, we could instead rule that all requests are responded to and modify section 5.3 to state that a channel number may be reused after you have both sent and received CLOSE _and_ received replies to all outstanding channel requests.

However, it's clear that the current situation leads to a problem, so _something_ needs fixing one way or the other. If you don't agree with my analysis, should we take this to ietf-secsh and see if we can get a consensus?
Comment 6 Damien Miller 2011-01-24 12:30:44 AEDT
Retarget unclosed bugs from 5.7=>5.8
Comment 7 Damien Miller 2011-09-06 10:34:08 AEST
Retarget unresolved bugs/features to 6.0 release
Comment 8 Damien Miller 2011-09-06 10:36:23 AEST
Retarget unresolved bugs/features to 6.0 release
Comment 9 Damien Miller 2011-09-06 10:38:56 AEST
Retarget unresolved bugs/features to 6.0 release

(try again - bugzilla's "change several" isn't)
Comment 10 Damien Miller 2012-02-24 10:34:16 AEDT
Retarget from 6.0 to 6.1
Comment 11 Damien Miller 2012-02-24 10:37:54 AEDT
Retarget 6.0 => 6.1
Comment 12 Simon Tatham 2012-02-24 20:13:11 AEDT
I've now worked around this issue on the PuTTY side (at least on the current development trunk), by implementing a more robust handling of SSH2_MSG_CHANNEL_CLOSE: _we_ now do not send CHANNEL_CLOSE until we have seen replies to all our outstanding channel requests, and therefore the question of which order the server's close and the request replies appear in is moot.
Comment 13 Damien Miller 2012-09-07 11:37:36 AEST
Retarget uncompleted bugs from 6.1 => 6.2
Comment 14 Damien Miller 2012-09-07 11:40:02 AEST
Retarget bugs from 6.1 => 6.2
Comment 15 Damien Miller 2013-03-08 10:23:10 AEDT
retarget to openssh-6.3
Comment 16 Damien Miller 2013-07-25 12:17:11 AEST
Retarget to openssh-6.4
Comment 17 Damien Miller 2013-07-25 12:19:59 AEST
Retarget 6.3 -> 6.4
Comment 18 Damien Miller 2014-02-06 10:17:26 AEDT
Retarget incomplete bugs / feature requests to 6.6 release
Comment 19 Damien Miller 2014-02-06 10:19:14 AEDT
Retarget incomplete bugs / feature requests to 6.6 release
Comment 20 Damien Miller 2014-04-12 14:48:19 AEST
Retarget to 6.7 release, since 6.6 was mostly bugfixing.
Comment 21 Damien Miller 2014-04-12 14:54:13 AEST
Remove from 6.6 tracking bug
Comment 22 Simon Tatham 2014-04-19 20:21:01 AEST
Created attachment 2431 [details]
improved fix handling both client and server

This issue has come up again recently and is currently under discussion on ietf-ssh. The general consensus seems to be that RFC 4254 has an ambiguity in it and that we should issue a clarification saying that responses to any outstanding or future channel requests should be implied by CHANNEL_CLOSE, and hence no actual reply messages should be sent after sending CHANNEL_CLOSE.

OpenSSH is the only implementation I know of which does not do this (and PuTTY's window size tuning mechanism does cause us to notice...), so could I request higher priority on fixing it, please? I've attached a patch that I think is right.

(I notice that I've attached a patch before, but it only dealt with the server side; this does the same thing on the client side too. I've only been able to test the server-side fix, but the client-side fix matches it as far as I can see so it should be right.)
Comment 23 Damien Miller 2014-04-29 23:10:46 AEST
Patch applied - this will be in OpenSSH 6.7
Comment 24 Damien Miller 2014-10-08 08:00:49 AEDT
Close all bugs left open from 6.6 and 6.7 releases.
Comment 25 Ahmed Sayeed 2021-10-14 01:40:09 AEDT
[spam removed]