[PATCH 15/18] BB_EXECVP: make BB_EXECVP do NOEXEC logic and allow it to to force applet execution
Nadav Tasher
tashernadav at gmail.com
Sun Jan 19 23:10:31 UTC 2025
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 <tashernadav at gmail.com>
---
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
More information about the busybox
mailing list