fail the session when a packet handler records a fatal error - #12
Open
precla wants to merge 1 commit into
Open
Conversation
libssh's channel_rcv_data frees a whole CHANNEL_DATA payload and returns SSH_PACKET_USED when it exceeds the channel's local window. The session keeps running minus those bytes, so the application sees a stream missing its head, and ssh_event_dopoll cannot report it. session_event_poll now compares the session error code across the poll and fails the session if a fatal error appeared during it. The snapshot avoids tripping on a stale error. this narrows the race rather than closing it: dopoll runs the data callbacks inline. Measured 6 of 12 and 7 of 11 blocked, versus none unguarded. added storm regression test and a harness that forces a real discard Signed-off-by: Antonio Prcela <antonio.prcela@sartura.hr>
precla
force-pushed
the
ssh_leading_bytes_dropped
branch
from
August 27, 2026 11:28
0431850 to
7d18439
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
libssh's channel_rcv_data frees a whole CHANNEL_DATA payload and returns SSH_PACKET_USED when it exceeds the channel's local window. The session keeps running minus those bytes, so the application sees a stream missing its head, and ssh_event_dopoll cannot report it.
session_event_poll now compares the session error code across the poll and fails the session if a fatal error appeared during it. The snapshot avoids tripping on a stale error.
this narrows the race rather than closing it: dopoll runs the data callbacks inline. Measured 6 of 12 and 7 of 11 blocked, versus none unguarded.
added storm regression test and a harness that forces a real discard
related to #7
this does not fully fix the issue, it's just a minor improvement
you can see in src/test_ssh_hello_storm.sh that the libssh is in one case run patched. which might be the proper fix. but it is questionable if upstream would allow/merge that change.
More details regarding the libssh behavior that causes this issue:
What RFC 4254 says:
what the libssh patch does and does not fix:
It does not stop data loss. When this branch is reached, bytes beyond the
window are gone either way — the clamp only delivers the portion that was within
the window instead of nothing. The wins are that a partially-overrunning peer no
longer costs a whole packet, and that the session's error state is no longer incorrect.
Note the interaction with the mitigation in
session_event_poll: that checkexists solely because the discard is silent. Clamping removes the bogus
SSH_FATAL, so with this patch the guard no longer fires for this branch — andany residual loss becomes silent again. Keep the guard for the
CLOSED_REMOTEbranch and for any future handler that records a fatal without acting on it, but
do not expect the two changes to compose into a guarantee.
The underlying question is still open: why
len > local_windowoccurs inthe field. Whether the peer overshoots the advertised window or libssh's own
accounting drifts decides whether this patch is the remedy or merely makes a
peer bug less damaging.
ACTON_SSH_LIBSSH_LOG=warnprintsData packet too big for our window(N vs M); comparingMagainst what thepeer should have believed the window to be identifies which side drifted.