-
-
Notifications
You must be signed in to change notification settings - Fork 128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Channel.window_size can overflow on add #101
Comments
Btw, I can view this issue when running with a single-threaded runtime. I think multithreading masks the issue. |
You're absolutely correct - it was supposed to be an assignment! |
Thanks! I've been looking through this a bit and I think there is at least another issue:
And only drained in these places: In both of these spots, we drain a single In an OpenSSH server, Due to this, many (hundreds to thousands depending on file size) of Since we only care about the last |
Not sure I understand this correctly - almost always, the WINDOW_ADJUST messages are passed down to the Only in the first case, we're unconditionally waiting for a new window size when it's 0 (it might make sense to push this one to the It's important to note that looping over |
Right, this is basically my point (though it is using an unbounded channel rather than a bounded one). Refer to the following example:
|
Right - I think I finally get it - however the Do you think there's any value at all in exposing the |
Consider the following field:
https://github.com/warp-tech/russh/blob/49bf9599637d492f0aa17377b9c66cf953cb0824/russh/src/channels.rs#L113
This field is meant to indicate current
window_size
on theChannel
.However, I've been able to hit a case where the
u32
overflows on add, which doesn't seem correct. Here's the scenario:send_data
loop of the channelwindow_size
will become 0. When it does, we enter this loop to wait for an adjustment and reset thewindow_size
.data
returns, callChannel.wait
in a loop waiting forChannelMsg::Data
to come through from the server.The issue I am seeing is that OpenSSH has sent a large amount of
ChannelMsg::WindowAdjusted
messages during step 4.send_data
, does not attempt to process these, it only takes the first one it finds and leaves the rest in the channel.While waiting for
ChannelMsg::Data
in step 5, the remainingChannelMsg::WindowAdjusted
are read out of the channel first.Each
CHANNEL_WINDOW_ADJUST
coming from the server first goes through here:https://github.com/warp-tech/russh/blob/49bf9599637d492f0aa17377b9c66cf953cb0824/russh/src/client/encrypted.rs#L489-L505
This code takes the existing
Channel.recipient_window_size
and adds the new adjustment amount to it. This resulting value is then passed intowindow_adjusted
where it is used to build a newChannelMsg::WindowAdjusted
here:https://github.com/warp-tech/russh/blob/49bf9599637d492f0aa17377b9c66cf953cb0824/russh/src/client/mod.rs#L1450-L1465
Finally, the
wait
method handles these messages by adding the entireChannel.recipient_window_size
to the existingChannel.window_size
here:https://github.com/warp-tech/russh/blob/49bf9599637d492f0aa17377b9c66cf953cb0824/russh/src/channels.rs#L347-L356
Repeatedly adding the
Channel.recipient_window_size
to theChannel.window_size
can overflow theu32
and cause a panic (in debug mode), or an two's complement wrapping (in release mode). I'm wondering if instead ofself.window_size += new_size
, we should doself.window_size = new_size
since we are really passing in the value ofChannel.recipient_window_size
instead of some amount of byte adjustment fromCHANNEL_WINDOW_ADJUST
.The text was updated successfully, but these errors were encountered: