Subject: data overflowing the window

From: der Mouse <[email-masked]>
Date: Sun, 14 Dec 2003 23:59:32 -0500 (EST)

I note that data flowing over channels is flow-controlled with a window
mechanism somewhat similar to TCP's (connect-18, section 5.2 et al).
However, since (unlike TCP) there are no sequence numbers, I think I
see a problem.

connect-18 excerpt:

   Data transfer is done with messages of the following type.

     byte      SSH_MSG_CHANNEL_DATA
     uint32    recipient channel
     string    data

   The maximum amount of data allowed is the current window size.  The
   window size is decremented by the amount of data sent. Both parties
   MAY ignore all extra data sent after the allowed window is empty.

But I think I see a race.  If a CHANNEL_DATA and a WINDOW_ADJUST cross
in transit, the two ends' idea of how much window space is available
can get permanently out of sync.  For example:

A                                                                B

Suppose the connection is idle and B's receive window is 1000 bytes.

--> CHANNEL_DATA, 1500 bytes -->

A now thinks B's receive window is zero, with the last 500 bytes of
data being possibly ignored.

                                <-- WINDOW_ADJUST, 1000 bytes <--

B now thinks its receive window is 2000 bytes.

                                --> CHANNEL_DATA, 1500 bytes -->

B now thinks its receive window is 500 bytes.

<-- WINDOW_ADJUST, 1000 bytes <--

A now thinks B's receive window is 1000 bytes.

At this point, the two ends are 500 bytes out of sync, and A could (for
example) send 750 bytes thinking B won't ignore any of it whereas B is
actually likely to ignore the last 250 bytes of it.

Without sequence numbers, I can't see any way to fix this short of
making it a protocol error to send out-of-window data; if anyone is
ever allowed to send beyond the end of the peer's receive window, this
situation can arise.  Is there some more compelling reason why
connect-18 doesn't make it a protocol error to send out-of-window data?

(Actually, it's also fixable if you allow window space to go negative.
But that amounts to throwing away the window mechanism entirely.)

/~\ The ASCII				der Mouse
\ / Ribbon Campaign
 X  Against HTML	       [email-masked]
/ \ Email!	     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B

---

From: Nicolas Williams <[email-masked]>
Date: Mon, 15 Dec 2003 11:55:25 -0800

> --> CHANNEL_DATA, 1500 bytes -->

Why would A do this?

> B now thinks its receive window is 2000 bytes.

Er, why?  B first thought it was 1000, then zero (because A consumed
1000 bytes of the window), then 1000 (because the sink on B's side for
that channel consumed the 1000 bytes that A sent, so B grew the window
back to 1000) -- not 2000.

And A first thought the windows was 1000 octets (though it stubbornly
sent 1500 octets), then it knew it would fall to zero (because its
CHANNEL_DATA consumed the window), then it learned that the window went
back to 1000 octets when B sent the WINDOW_ADJUST message.

> B now thinks its receive window is 500 bytes.

See above -- B would now think its window is 0 and would discard the
last 500 bytes that A sent.

> A now thinks B's receive window is 1000 bytes.

As does B.

What's the problem?

> actually likely to ignore the last 250 bytes of it.

See above

Cheers,

Nico
--

---

From: der Mouse <[email-masked]>
Date: Mon, 15 Dec 2003 15:07:55 -0500 (EST)

>> --> CHANNEL_DATA, 1500 bytes -->

I don't know.  Since it's not forbidden, I see no particular reason for
A not to.  Maybe it's easier.

> 1000 bytes of the window),

No, because B hasn't received that packet yet.  Remember, I was
postulating that the two packets cross in transit.  Thus these...

>> <-- WINDOW_ADJUST, 1000 bytes <--

...are the same two packets as above, just as seen by their receivers
rather than their senders.

/~\ The ASCII				der Mouse
\ / Ribbon Campaign

---

From: Bill Sommerfeld <[email-masked]>
Date: Mon, 15 Dec 2003 15:47:32 -0500

this looks like a corner case.

the spec says:

   "No data may be sent to a channel until
   a message is received to indicate that window space is available."

and:

   "'initial window size' specifies how many bytes of channel data can be
   sent to the sender of this message without adjusting the window."

> Is there some more compelling reason why

in addition, the spec says:

   Both parties MAY ignore all extra data sent after the allowed
   window is empty.

which clearly implies that clients which wish reliable transport MUST
NOT send more than allowed by the current window.

						- Bill

---

From: [email-masked] (Niels Möller)
Date: 15 Dec 2003 22:07:30 +0100

> data being possibly ignored.

Then A is not behaving properly, and he should be happy that B doesn't
just hangup on him. The spec allows B to operate in a sloppy mode and
just ignore the extra data and go on as if nothing happened, but
that's not supposed to be the normal way to operate.

Your own quoting of the spec says this fairly clearly: "The maximum
amount of data allowed is the current window size" Period. Sending
more should be considered a protocol violation.

Also note the final paragraph in section 3, "Channels are
flow-controlled. No data may be sent to a channel until a message is
received to indicate that window space is available."

(I think most implementations ignore the extra data and display a
warning message, but I wouldn't be surprised if some respond with a
SSH_MSG_DISCONNECT, SSH_DISCONNECT_PROTOCOL_ERROR, and some silently
accept the data. That's fine. However, any implementation that *sends*
more data than the current window size is broken. This is just an
example of the "be conservative in what you send, and liberal in what
you accept" attitude).

/Niels

---

From: Markus Friedl <[email-masked]>
Date: Tue, 16 Dec 2003 10:21:16 +0100

> data being possibly ignored.

B _must_ not send more than 1000 bytes in this case.