From 033646ce0a826290147c267d7a5d80910e1ea1ed Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 28 Aug 2026 12:47:02 -0700 Subject: [PATCH] Re-resolve the forwarded channel before the half-close check A refused channel open frees the channel and surfaces as a fatal error rather than a close, so the guard that clears fwdChannel never runs and the half-close check read freed memory on every refused -L forward. - Stash the channel id wherever the channel is created or adopted - Look the channel up by id each pass and stop once it is gone --- examples/portfwd/portfwd.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/examples/portfwd/portfwd.c b/examples/portfwd/portfwd.c index e562ac4c..e406368d 100644 --- a/examples/portfwd/portfwd.c +++ b/examples/portfwd/portfwd.c @@ -438,6 +438,7 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args) int replyTries; struct timeval to; WOLFSSH_CHANNEL* fwdChannel = NULL; + word32 fwdChannelId = 0; byte* appBuffer = NULL; byte* sshBuffer = NULL; word32 appBufferSz = 0; @@ -746,6 +747,7 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args) if (fwdState.appFd != (SOCKET_T)-1 && newChannel != NULL) { appFd = fwdState.appFd; fwdChannel = newChannel; + fwdChannelId = fwdState.channelId; FD_SET(appFd, &templateFds); nFds = findMax((int)sshFd, (int)appFd) + 1; appFdSet = 1; @@ -767,6 +769,16 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args) break; } + /* A refused open frees the channel and reports a fatal + * error, not a close, so the guard above does not run. + * Re-resolve by id rather than trust the pointer. */ + if (fwdChannel != NULL) { + fwdChannel = wolfSSH_ChannelFind(ssh, fwdChannelId, + WS_CHANNEL_ID_SELF); + if (fwdChannel == NULL) + break; + } + /* Relay the half-close so a local reader waiting on end-of-input * returns; nothing else relays it. Driven off the latched channel * state, not the WS_EOF status: the flush inside wolfSSH_worker() @@ -836,6 +848,10 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args) appFdSet = 1; fwdChannel = wolfSSH_ChannelFwdNew(ssh, fwdToHost, fwdToPort, fwdFromHost, fwdFromPort); + if (fwdChannel != NULL + && wolfSSH_ChannelGetId(fwdChannel, &fwdChannelId, + WS_CHANNEL_ID_SELF) != WS_SUCCESS) + fwdChannel = NULL; continue; } if (appBufferUsed > 0) {