Ticket #8 (closed defect)
Opened 6 years ago
Last modified 5 years ago
infinite loop on socket shutdown
| Reported by: | hillerj | Owned by: | |
|---|---|---|---|
| Priority: | normal | Milestone: | |
| Component: | Version: | ||
| Keywords: | Cc: | hillerj, sshattered, mwbourgeois, bagder | |
| Blocked By: | Blocks: |
Description
The problem I am having shows up when I hit the
MaxStartups? configuration limit in sshd. The program I
wrote spins up multiple threads that each connect to a
unix box using libssh2, executes a couple commands and
then exit. Let's say the MaxStartups? parameter for
sshd is 4 and I spin up 5 threads. Since the fifth
thread hits the MaxStartups? limit, sshd closes the
socket, which then causes that thread to go into an
infinite loop in the function libssh2_banner_receive.
The infinite loop is due to the socket function recv
returning 0. Line 111 of session.c is the culprit.
Now, I am running on Windows but I checked the
documentation for recv on Windows and Unix and they
both state that when recv returns 0 it means the peer
has shutdown the socket. It seems like line 111 in
session.c should be changed to something like "if(ret
0) return 1;". I also looked at other places that
the function recv is used and it looks like the
function libssh2_blocking_read could have the same
infinite loop problem due to line 688 of packet.c. I
am not sure if my research is correct so please let me
know. Thanks.
Change History
comment:1 Changed 6 years ago by sshattered
comment:2 Changed 6 years ago by sshattered
Actually, if you want it to function normally again:
"if (ret > 0){bytes_read+=ret;continue;}if (ret == 0) break;"
at the beginning of line 688 will allow normal usage.
comment:3 Changed 5 years ago by mwbourgeois
I've had this problem with both of the mentioned instances of the recv causing an infinite loop when the remote host closes the connection. I wrote a patch against the current CVS which should fix this problem which I will attempt to attach to this report and submit for inclusion in CVS.
comment:4 Changed 5 years ago by mwbourgeois
diff -Naur libssh2/src/packet.c libssh2-uwhousing20061221/src/packet.c
--- libssh2/src/packet.c 2006-12-21 08:29:50.349858448 -0600
+++ libssh2-uwhousing20061221/src/packet.c 2006-12-21 09:47:27.499864032 -0600
@@ -702,7 +702,7 @@
}
return -1;
}
- if (ret == 0) continue;
+ if (ret == 0) break;
bytes_read += ret;
}
diff -Naur libssh2/src/session.c libssh2-uwhousing20061221/src/session.c
--- libssh2/src/session.c 2006-12-21 08:29:50.524831848 -0600
+++ libssh2-uwhousing20061221/src/session.c 2006-12-21 08:32:12.775206504 -0600
@@ -125,9 +125,10 @@
/* Some kinda error, but don't break for non-blocking issues */
return 1;
}
+ continue;
}
- if (ret <= 0) continue;
+ if (ret == 0) return 1;
if (c == '\0') {
/* NULLs are not allowed in SSH banners */
comment:5 Changed 5 years ago by bagder
This is addressed in current CVS, if still present please open a new bug report

I have seen a similar problem in packet.c where the packet
'count' to be achieved is 782254606 and the received bytes
are always zero. The socket I use in this case is
non-blocking as passed in to libssh2. The read produces a
zero return each time in the loop and continues forever with
a cooresponding cpu spike.
The packet capture shows a steady stream of resets by the
remote host, "administratively prohibited" with a code 10.
To continue locally for debugging purposes, inserting:
"if (ret > 0) continue;if (ret == 0) break;"
at line 688 in fn libssh2_blocking_read() will allow a reset
socket to exit with an error of -5 from the statrup function
and return control of the client to you.