From bcf2cd1795cfcc6068b9ecfd6dcee001e58dbdb4 Mon Sep 17 00:00:00 2001 From: Abhishek Mishra Date: Wed, 19 Aug 2026 08:07:17 +0000 Subject: [PATCH] nshlib: add chroot command chdir into the new root, call chroot("."), then chdir("/") so relative paths stay in the jail. With a command, execvp() after the jail is set. Signed-off-by: Abhishek Mishra --- nshlib/Kconfig | 5 ++++ nshlib/nsh.h | 3 +++ nshlib/nsh_command.c | 5 ++++ nshlib/nsh_envcmds.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+) diff --git a/nshlib/Kconfig b/nshlib/Kconfig index e0259a2ac..0de85924b 100644 --- a/nshlib/Kconfig +++ b/nshlib/Kconfig @@ -361,6 +361,11 @@ config NSH_DISABLE_CD bool "Disable cd" default DEFAULT_SMALL +config NSH_DISABLE_CHROOT + bool "Disable chroot" + default DEFAULT_SMALL + depends on FS_CHROOT + config NSH_DISABLE_CHMOD bool "Disable chmod" default DEFAULT_SMALL diff --git a/nshlib/nsh.h b/nshlib/nsh.h index 295f11b94..4183fab55 100644 --- a/nshlib/nsh.h +++ b/nshlib/nsh.h @@ -1084,6 +1084,9 @@ int cmd_irqinfo(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); #ifndef CONFIG_NSH_DISABLE_CD int cmd_cd(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); #endif +#if defined(CONFIG_FS_CHROOT) && !defined(CONFIG_NSH_DISABLE_CHROOT) + int cmd_chroot(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); +#endif #ifndef CONFIG_NSH_DISABLE_PWD int cmd_pwd(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); #endif diff --git a/nshlib/nsh_command.c b/nshlib/nsh_command.c index 988e4792d..22e43b4f4 100644 --- a/nshlib/nsh_command.c +++ b/nshlib/nsh_command.c @@ -168,6 +168,11 @@ static const struct cmdmap_s g_cmdmap[] = CMD_MAP("cd", cmd_cd, 1, 2, "[|-|~|..]"), #endif +#if defined(CONFIG_FS_CHROOT) && !defined(CONFIG_NSH_DISABLE_CHROOT) + CMD_MAP("chroot", cmd_chroot, 2, CONFIG_NSH_MAXARGUMENTS, + " [ [args...]]"), +#endif + #if defined(CONFIG_FS_PERMISSION) && !defined(CONFIG_NSH_DISABLE_CHMOD) CMD_MAP("chmod", cmd_chmod, 3, 3, " "), #endif diff --git a/nshlib/nsh_envcmds.c b/nshlib/nsh_envcmds.c index 52be0e96c..e8b0d0473 100644 --- a/nshlib/nsh_envcmds.c +++ b/nshlib/nsh_envcmds.c @@ -324,6 +324,64 @@ errout: } #endif +/**************************************************************************** + * Name: cmd_chroot + ****************************************************************************/ + +#if defined(CONFIG_FS_CHROOT) && !defined(CONFIG_NSH_DISABLE_CHROOT) +int cmd_chroot(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv) +{ + FAR char *fullpath; + int ret; + + fullpath = nsh_getfullpath(vtbl, argv[1]); + if (fullpath == NULL) + { + nsh_error(vtbl, g_fmtcmdoutofmemory, argv[0]); + return ERROR; + } + + ret = chdir(fullpath); + nsh_freefullpath(fullpath); + if (ret < 0) + { + nsh_error(vtbl, g_fmtcmdfailed, argv[0], "chdir", NSH_ERRNO); + return ERROR; + } + + ret = chroot("."); + if (ret < 0) + { + nsh_error(vtbl, g_fmtcmdfailed, argv[0], "chroot", NSH_ERRNO); + return ERROR; + } + + ret = chdir("/"); + if (ret < 0) + { + nsh_error(vtbl, g_fmtcmdfailed, argv[0], "chdir", NSH_ERRNO); + return ERROR; + } + +#ifdef CONFIG_LIBC_EXECFUNCS + if (argc > 2) + { + execvp(argv[2], &argv[2]); + nsh_error(vtbl, g_fmtcmdfailed, argv[0], "execvp", NSH_ERRNO); + return ERROR; + } +#else + if (argc > 2) + { + nsh_error(vtbl, g_fmtcmdfailed, argv[0], "execvp", NSH_ERRNO); + return ERROR; + } +#endif + + return OK; +} +#endif /* CONFIG_FS_CHROOT && !CONFIG_NSH_DISABLE_CHROOT */ + /**************************************************************************** * Name: cmd_echo ****************************************************************************/