Fix echoserver remote-forward listener accept

- ssh_worker() cached fwdCtx.listenFd at entry, while still -1
- The listener is only made later, from WOLFSSH_FWD_REMOTE_SETUP
- FD_SET() and accept() then got a bogus fd, failing with EBADF,
  which broke the worker loop and dropped the session
- Read listenFd from the context at each use, guarded on validity
- agentListenFd has the same shape but is set up before ssh_worker()

Issue: ZD-21867
pull/1088/head
John Safranek 2026-07-22 14:06:56 -07:00 committed by JacobBarthelmeh
parent 9382811225
commit 4caf4558f4
1 changed files with 24 additions and 8 deletions

View File

@ -531,6 +531,19 @@ static int wolfSSH_FwdDefaultActions(WS_FwdCbAction action, void* vCtx,
ret = -1;
}
#ifndef USE_WINDOWS_API
if (ret == 0) {
/* A forward torn down with a connection open leaves this port in
* TIME_WAIT, which would fail the next bind. tcp_listen() sets
* this for the other listeners; do the same here. */
int on = 1;
if (setsockopt(appCtx->listenFd, SOL_SOCKET, SO_REUSEADDR,
&on, (socklen_t)sizeof(on)) < 0) {
ret = -1;
}
}
#endif
if (ret == 0) {
WMEMSET(&addr, 0, sizeof addr);
@ -873,7 +886,6 @@ static int ssh_worker(thread_ctx_t* threadCtx)
#endif
#ifdef WOLFSSH_FWD
WS_SOCKET_T fwdFd = -1;
WS_SOCKET_T fwdListenFd = threadCtx->fwdCtx.listenFd;
word32 fwdBufferIdx = 0;
#endif
@ -955,10 +967,13 @@ static int ssh_worker(thread_ctx_t* threadCtx)
}
#endif /* WOLFSSH_AGENT */
#ifdef WOLFSSH_FWD
if (threadCtx->fwdCtx.state == APP_STATE_LISTEN) {
FD_SET(fwdListenFd, &readFds);
if (fwdListenFd > maxFd)
maxFd = fwdListenFd;
/* The fwd callback creates this listener mid-loop; re-read it
* each pass rather than caching it. */
if (threadCtx->fwdCtx.state == APP_STATE_LISTEN
&& threadCtx->fwdCtx.listenFd >= 0) {
FD_SET(threadCtx->fwdCtx.listenFd, &readFds);
if (threadCtx->fwdCtx.listenFd > maxFd)
maxFd = threadCtx->fwdCtx.listenFd;
}
if (fwdFd >= 0
&& threadCtx->fwdCtx.state == APP_STATE_CONNECTED) {
@ -1250,12 +1265,13 @@ static int ssh_worker(thread_ctx_t* threadCtx)
}
}
}
if (threadCtx->fwdCtx.state == APP_STATE_LISTEN) {
if (FD_ISSET(fwdListenFd, &readFds)) {
if (threadCtx->fwdCtx.state == APP_STATE_LISTEN
&& threadCtx->fwdCtx.listenFd >= 0) {
if (FD_ISSET(threadCtx->fwdCtx.listenFd, &readFds)) {
#ifdef SHELL_DEBUG
printf("accepting fwd connection\n");
#endif
fwdFd = accept(fwdListenFd, NULL, NULL);
fwdFd = accept(threadCtx->fwdCtx.listenFd, NULL, NULL);
if (fwdFd == -1) {
rc = errno;
if (rc != SOCKET_EWOULDBLOCK) {