From ac73e41fc3db8c2dc049dcca3ec3e635bd5fadc8 Mon Sep 17 00:00:00 2001 From: Ricard Rosson Date: Thu, 23 Jul 2026 18:59:54 +0100 Subject: [PATCH] netutils/telnetd: keep the listen socket out of the standard-stream range When telnetd_daemon() starts without open standard streams - exactly what happens when nsh_telnetstart() spawns "telnetd &" before the console device exists (e.g. CONFIG_NSH_USBCONSOLE boards, where nsh_initialize() runs before the USB console is connected) - socket() returns a descriptor in the 0..2 range. The accept loop's own "go silent" close(0)..close(2) then destroys the listen socket on the first iteration: every subsequent accept4() fails with EBADF and the daemon serves nothing. Observed on hardware (RP2350, CDC-ACM console + CDC-NCM composite): the daemon task was alive but port 23 refused every connection; the thread list showed it looping on the failed accept. Duplicate the descriptor above the standard-stream range before using it. Assisted-by: Claude Fable 5 Signed-off-by: Ricard Rosson --- netutils/telnetd/telnetd_daemon.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/netutils/telnetd/telnetd_daemon.c b/netutils/telnetd/telnetd_daemon.c index c1512113c..a4c1e74fe 100644 --- a/netutils/telnetd/telnetd_daemon.c +++ b/netutils/telnetd/telnetd_daemon.c @@ -125,6 +125,28 @@ int telnetd_daemon(FAR const struct telnetd_config_s *config) goto errout; } + /* If the daemon was started without standard streams (e.g. spawned by + * nsh_telnetstart() before a USB console device exists), socket() may + * have returned a descriptor in 0..2. The "go silent" + * close(0)..close(2) at the top of the accept loop below would then + * destroy the listen socket: every subsequent accept4() fails and the + * daemon serves nothing. Move the descriptor above the + * standard-stream range. + */ + + if (listensd <= 2) + { + int highsd = fcntl(listensd, F_DUPFD_CLOEXEC, 3); + if (highsd < 0) + { + nerr("ERROR: F_DUPFD_CLOEXEC failed: %d\n", errno); + goto errout_with_socket; + } + + close(listensd); + listensd = highsd; + } + #ifdef CONFIG_NET_SOCKOPTS /* Set socket to reuse address */