mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-11-26 01:03:15 +03:00
poll: Avoid passing other events to callbacks when called recursively
Some architectures (s390x) provide different poll events such as POLLHUP in case
the remote end closed the connection (and they keep reporting this forever).
This is an issue when the user provided callback registering this event as an
error and tries to send some reply (for example EOF) using
`ssh_channel_send_eof()` which will lead to infinite recursion and sefgaults.
This was not solved by the 30b5a2e33b because the
POLLHUP event is not provided by the poll in events bitfield, but only reported
by the poll in revents bit field thus we need to filter these events later on
when the poll is recursively.
Fixes #202
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
11
src/poll.c
11
src/poll.c
@@ -722,14 +722,21 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout)
|
||||
|
||||
used = ctx->polls_used;
|
||||
for (i = 0; i < used && rc > 0; ) {
|
||||
if (ctx->pollfds[i].revents == 0) {
|
||||
revents = ctx->pollfds[i].revents;
|
||||
/* Do not pass any other events except for POLLOUT to callback when
|
||||
* called recursively more than 2 times. On s390x the poll will be
|
||||
* spammed with POLLHUP events causing infinite recursion when the user
|
||||
* callback issues some write/flush/poll calls. */
|
||||
if (ctx->pollptrs[i]->lock_cnt > 2) {
|
||||
revents &= POLLOUT;
|
||||
}
|
||||
if (revents == 0) {
|
||||
i++;
|
||||
} else {
|
||||
int ret;
|
||||
|
||||
p = ctx->pollptrs[i];
|
||||
fd = ctx->pollfds[i].fd;
|
||||
revents = ctx->pollfds[i].revents;
|
||||
/* avoid having any event caught during callback */
|
||||
ctx->pollfds[i].events = 0;
|
||||
p->lock_cnt++;
|
||||
|
||||
Reference in New Issue
Block a user