Skip to content

Commit c4b3242

Browse files
committed
portfwd: stop double-closing the forwarded socket
The LOCAL_CLEANUP handler closes the target socket, and portfwd_worker() closed its own copy of the same descriptor again at teardown. That was unreachable while the library never emitted the action, which is why the report against it was set aside; it is reachable now. - record the cleanup in the forwarding state and skip the second close - reset the record when a fresh forward's socket is adopted, or one left by an earlier refused open skips closing a live socket at exit - drop the handler comment saying the action is never emitted
1 parent 04128a7 commit c4b3242

1 file changed

Lines changed: 15 additions & 4 deletions

File tree

examples/portfwd/portfwd.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ typedef struct PortfwdState {
249249
SOCKET_T appFd; /* socket to the local target, -1 when idle */
250250
word32 channelId; /* id of the inbound forwarded-tcpip channel */
251251
int pending; /* a new channel is waiting to be wired up */
252+
int cleanupRxd; /* LOCAL_CLEANUP closed appFd for us */
252253
int replied; /* peer answered the tcpip-forward request */
253254
int refused; /* ...and the answer was a refusal */
254255
int badPort; /* ...or named a port outside 1..65535 */
@@ -319,15 +320,17 @@ static int portfwdRemoteFwdCb(WS_FwdCbAction action, void* ctx,
319320
st->pending = 1;
320321
break;
321322
case WOLFSSH_FWD_LOCAL_CLEANUP:
322-
/* The library does not currently emit this action, so this branch
323-
* never runs. The target socket is closed when portfwd_worker()
324-
* leaves its loop. Kept so the handler is right if that changes. */
323+
/* Paired with the LOCAL_SETUP that opened the target socket.
324+
* portfwd_worker() keeps its own copy of the descriptor, so tell
325+
* it not to close what has already been closed. The closing
326+
* channel's id arrives in the port argument. */
325327
(void)address;
326328
(void)port;
327329
if (st->appFd != (SOCKET_T)-1) {
328330
WCLOSESOCKET(st->appFd);
329331
st->appFd = (SOCKET_T)-1;
330332
}
333+
st->cleanupRxd = 1;
331334
break;
332335
case WOLFSSH_FWD_REMOTE_SETUP:
333336
case WOLFSSH_FWD_REMOTE_CLEANUP:
@@ -746,6 +749,9 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args)
746749
WS_CHANNEL_ID_SELF);
747750
if (fwdState.appFd != (SOCKET_T)-1 && newChannel != NULL) {
748751
appFd = fwdState.appFd;
752+
/* The latch describes this descriptor now, not one an
753+
* earlier failed open already cleaned up. */
754+
fwdState.cleanupRxd = 0;
749755
fwdChannel = newChannel;
750756
fwdChannelId = fwdState.channelId;
751757
FD_SET(appFd, &templateFds);
@@ -885,7 +891,12 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args)
885891
WCLOSESOCKET(sshFd);
886892
if (listenFd != (SOCKET_T)-1)
887893
WCLOSESOCKET(listenFd);
888-
WCLOSESOCKET(appFd);
894+
/* Skip a descriptor the cleanup callback already closed; closing it
895+
* twice can take down whatever has been handed the number since. */
896+
if (fwdState.cleanupRxd)
897+
appFd = (SOCKET_T)-1;
898+
if (appFd != (SOCKET_T)-1)
899+
WCLOSESOCKET(appFd);
889900
wolfSSH_free(ssh);
890901
wolfSSH_CTX_free(ctx);
891902
#ifdef WOLFSSH_SMALL_STACK

0 commit comments

Comments
 (0)