From f75251f7e301bfbdb0f77005110449f6f3190a64 Mon Sep 17 00:00:00 2001 From: Abhishek Mishra Date: Wed, 19 Aug 2026 08:07:17 +0000 Subject: [PATCH] nshlib: close extra fds before jailed execvp chroot closes non-stdio, non-O_CLOEXEC descriptors before execvp so inherited host fds cannot bypass the jail. Signed-off-by: Abhishek Mishra --- 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 #include #include +#include #include #include @@ -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;