This patch makes BB_EXECVP the gateway to the exec syscall family. When called, it first looks for a matching applet, and executes it directly of indirectly by re-executing the binary. This new behaviour is configurable by the new FEATURE_FORCE_NOEXEC option.
When FEATURE_FORCE_APPLETS is enabled, BB_EXECVP will fail when trying to execute things that are not busybox applets. This allows more control over the executed processes. Signed-off-by: Nadav Tasher <[email protected]> --- Config.in | 22 ++++++++++++++++++++++ include/libbb.h | 16 +++------------- libbb/executable.c | 32 +++++++++++++++++++++++++++----- 3 files changed, 52 insertions(+), 18 deletions(-) diff --git a/Config.in b/Config.in index dfab102bb..e5d08b33f 100644 --- a/Config.in +++ b/Config.in @@ -311,6 +311,28 @@ config FEATURE_PREFER_APPLETS problems in chroot jails without mounted /proc and with ps/top (command name can be shown as 'exe' for applets started this way). +config FEATURE_FORCE_NOEXEC + bool "call applets without exec" + default n + depends on FEATURE_PREFER_APPLETS + help + This is an experimental option which allows calling applets directly + and bypassing NOEXEC restrictions, instead of exec'ing /proc/self/exe. + This reduces the amount of exec syscalls used when running applets, + especially in shells. + + This feature extends the "exec prefers applets" feature. + +config FEATURE_FORCE_APPLETS + bool "only use applets" + default n + depends on FEATURE_PREFER_APPLETS + help + This is an experimental option which makes exec calls fail when trying + to execute external binaries that are not part of busybox. + + This feature extends the "exec prefers applets" feature. + config BUSYBOX_EXEC_PATH string "Path to busybox executable" default "/proc/self/exe" diff --git a/include/libbb.h b/include/libbb.h index 4d6193795..af33d94b6 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1230,21 +1230,11 @@ int file_is_executable(const char *name) FAST_FUNC; char *find_executable(const char *filename, const char **PATHp) FAST_FUNC; int executable_exists(const char *filename) FAST_FUNC; -/* BB_EXECxx always execs (it's not doing NOFORK/NOEXEC stuff), - * but it may exec busybox and call applet instead of searching PATH. +/* BB_EXECxx are called instead of using execXX directly, to allow + * implementation of NOFORK/NOEXEC applet logic if required. */ -#if ENABLE_FEATURE_PREFER_APPLETS int BB_EXECVP(const char *file, char *const argv[]) FAST_FUNC; -#define BB_EXECLP(prog,cmd,...) \ - do { \ - if (find_applet_by_name(prog) >= 0) \ - execlp(bb_busybox_exec_path, cmd, __VA_ARGS__); \ - execlp(prog, cmd, __VA_ARGS__); \ - } while (0) -#else -#define BB_EXECVP(prog,cmd) execvp(prog,cmd) -#define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__) -#endif +int BB_EXECVPE(const char *file, char *const argv[], char *const envp[]) FAST_FUNC; void BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC; /* xvfork() can't be a _function_, return after vfork in child mangles stack diff --git a/libbb/executable.c b/libbb/executable.c index 09bed1eaf..8b4b59ef3 100644 --- a/libbb/executable.c +++ b/libbb/executable.c @@ -78,15 +78,37 @@ int FAST_FUNC executable_exists(const char *name) return ret != NULL; } -#if ENABLE_FEATURE_PREFER_APPLETS -/* just like the real execvp, but try to launch an applet named 'file' first */ +/* just like the real execvp, but we might try to launch an applet named 'file' first */ int FAST_FUNC BB_EXECVP(const char *file, char *const argv[]) { - if (find_applet_by_name(file) >= 0) - execvp(bb_busybox_exec_path, argv); +#if ENABLE_FEATURE_PREFER_APPLETS + int applet = find_applet_by_name(file); + if (applet >= 0) { + if (ENABLE_FEATURE_FORCE_NOEXEC || APPLET_IS_NOEXEC(applet)) + run_noexec_applet_and_exit(applet, file, (char **) argv); + else + execvp(bb_busybox_exec_path, argv); + } +# if ENABLE_FEATURE_FORCE_APPLETS + else { + /* set errno accordingly */ + errno = ENOENT; + return -1; + } +# endif +#endif + return execvp(file, argv); } -#endif + +int FAST_FUNC BB_EXECVPE(const char *file, char *const argv[], char *const envp[]) +{ + clearenv(); + while (*envp) + putenv(*envp++); + + return BB_EXECVP(file, argv); +} void FAST_FUNC BB_EXECVP_or_die(char **argv) { -- 2.43.0 _______________________________________________ busybox mailing list [email protected] https://lists.busybox.net/mailman/listinfo/busybox
