This change makes the standalone shell use the BB_EXECVE utility. BB_EXECVE calls BB_APPLET_EXECVE which has NOEXEC and applets only logic.
This allows for better control of the executed processes. Signed-off-by: Nadav Tasher <tasherna...@gmail.com> --- shell/ash.c | 72 +++++++++++++++++++---------------------------------- 1 file changed, 26 insertions(+), 46 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 9173b8608..1d8a39077 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8271,34 +8271,23 @@ static int builtinloc = -1; /* index in path of %builtin, or -1 */ static void -tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp) +tryexec(const char *cmd, char **argv, char **envp) { -#if ENABLE_FEATURE_SH_STANDALONE - if (applet_no >= 0) { - if (APPLET_IS_NOEXEC(applet_no)) { - clearenv(); - while (*envp) - putenv(*envp++); - popredir(/*drop:*/ 1); - run_noexec_applet_and_exit(applet_no, cmd, argv); - } - /* re-exec ourselves with the new arguments */ - execve(bb_busybox_exec_path, argv, envp); - /* If they called chroot or otherwise made the binary no longer - * executable, fall through */ - } -#endif + /* because we might not actually exec, redirected fds + * might not close, since they have the CLOEXEC flag. + * this ensures they are closed. */ + popredir(/*drop:*/ 1); repeat: #ifdef SYSV do { - execve(cmd, argv, envp); + BB_EXECVE(cmd, argv, envp); } while (errno == EINTR); #else - execve(cmd, argv, envp); + BB_EXECVE(cmd, argv, envp); #endif - if (cmd != bb_busybox_exec_path && errno == ENOEXEC) { + if (strcmp(cmd, "ash") != 0 && errno == ENOEXEC) { /* Run "cmd" as a shell script: * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html * "If the execve() function fails with ENOEXEC, the shell @@ -8316,12 +8305,15 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c * to interpret foreign ELF binaries as shell scripts. */ argv[0] = (char*) cmd; - cmd = bb_busybox_exec_path; + /* NB: this is only possible because all callers of shellexec() * ensure that the argv[-1] slot exists! - */ + * it is also required, as ash expects args to start at argv[1]. */ argv--; argv[0] = (char*) "ash"; + + /* this makes the following repeat execute ash by re-exec or NOEXEC */ + cmd = (char*) "ash"; goto repeat; } } @@ -8338,33 +8330,21 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) int e; char **envp; int exerrno; - int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */ envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL); - if (strchr(prog, '/') != NULL -#if ENABLE_FEATURE_SH_STANDALONE - || (applet_no = find_applet_by_name(prog)) >= 0 -#endif - ) { - tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); - if (applet_no >= 0) { - /* We tried execing ourself, but it didn't work. - * Maybe /proc/self/exe doesn't exist? - * Try $PATH search. - */ - goto try_PATH; - } - e = errno; - } else { - try_PATH: - e = ENOENT; - while (padvance(&path, argv[0]) >= 0) { - cmdname = stackblock(); - if (--idx < 0 && pathopt == NULL) { - tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp); - if (errno != ENOENT && errno != ENOTDIR) - e = errno; - } + /* try executing using tryexec, which might execute applets + * using NOEXEC logic, and might execute a matching binary. + */ + tryexec(prog, argv, envp); + e = errno; + + /* fallback to PATH search and try executing using tryexec */ + while (padvance(&path, argv[0]) >= 0) { + cmdname = stackblock(); + if (--idx < 0 && pathopt == NULL) { + tryexec(cmdname, argv, envp); + if (errno != ENOENT && errno != ENOTDIR) + e = errno; } } -- 2.43.0 _______________________________________________ busybox mailing list busybox@busybox.net https://lists.busybox.net/mailman/listinfo/busybox