This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit f75251f7e301bfbdb0f77005110449f6f3190a64 Author: Abhishek Mishra <[email protected]> AuthorDate: Wed Aug 19 08:07:17 2026 +0000 nshlib: close extra fds before jailed execvp chroot <newroot> <command> closes non-stdio, non-O_CLOEXEC descriptors before execvp so inherited host fds cannot bypass the jail. Signed-off-by: Abhishek Mishra <[email protected]> --- nshlib/nsh_envcmds.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/nshlib/nsh_envcmds.c b/nshlib/nsh_envcmds.c index e8b0d0473..740c1fe19 100644 --- a/nshlib/nsh_envcmds.c +++ b/nshlib/nsh_envcmds.c @@ -30,6 +30,7 @@ #include <unistd.h> #include <string.h> #include <ctype.h> +#include <fcntl.h> #include <libgen.h> #include <errno.h> @@ -324,6 +325,40 @@ errout: } #endif +/**************************************************************************** + * Name: nsh_chroot_closefds + * + * Description: + * Close descriptors above stderr that are not already O_CLOEXEC so a + * jailed execvp() child cannot inherit host file descriptors. + * + ****************************************************************************/ + +#if defined(CONFIG_FS_CHROOT) && !defined(CONFIG_NSH_DISABLE_CHROOT) && \ + defined(CONFIG_LIBC_EXECFUNCS) +static void nsh_chroot_closefds(void) +{ + int fdmax; + int fd; + int flags; + + fdmax = sysconf(_SC_OPEN_MAX); + if (fdmax <= STDERR_FILENO) + { + return; + } + + for (fd = STDERR_FILENO + 1; fd < fdmax; fd++) + { + flags = fcntl(fd, F_GETFD); + if (flags >= 0 && (flags & FD_CLOEXEC) == 0) + { + close(fd); + } + } +} +#endif + /**************************************************************************** * Name: cmd_chroot ****************************************************************************/ @@ -366,6 +401,7 @@ int cmd_chroot(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv) #ifdef CONFIG_LIBC_EXECFUNCS if (argc > 2) { + nsh_chroot_closefds(); execvp(argv[2], &argv[2]); nsh_error(vtbl, g_fmtcmdfailed, argv[0], "execvp", NSH_ERRNO); return ERROR;
