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 | 33 ++++++++++++++++++++++++++++-----
 3 files changed, 53 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..09d15bfec 100644
--- a/libbb/executable.c
+++ b/libbb/executable.c
@@ -7,6 +7,7 @@
  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 #include "libbb.h"
+#include "busybox.h" /* for APPLET_IS_NOEXEC */
 
 /* check if path points to an executable file;
  * return 1 if found;
@@ -78,15 +79,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

Reply via email to