[PATCH v3 15/27] BB_EXECVP: make BB_EXECVP do NOEXEC logic and allow it to to force applet execution
d+busybox at adaptive-enterprises.com
d+busybox at adaptive-enterprises.com
Mon Jan 27 07:46:56 UTC 2025
On Mon, 27 Jan 2025, Nadav Tasher wrote:
> 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.
I'm pretty sure that applets not marked NOEXEC won't work well
unless you use an exec syscall, so this FORCE_NOEXEC seems pretty
dubious. Can you separate this feature from this series?
> 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.
This is more of a restriction, than a force. Good names are hard,
but something like FEATURE_EXEC_ONLY_APPLETS would be clearer?
> BB_EXECVPE is introduced to support passing seperate
> environment to a BB_EXECVP call, and uses the new
> copy_terminated_string_array function to backup the
> current environ. This mimics the behaviour of execvpe.
[...]
> +char** copy_terminated_string_array(char **array) {
Ah, I was thinking that you could avoid any string copying of environ[] by
committing to use the envp argument only when you know the applet is known
and is NOEXEC. The relevant equivalence I think is:
BB_EXECVP(p,a) === BB_EXECVPE(p,a,environ)
Because the only error you expect from BB_EXECVPE on an applet is ENOENT,
then you can try find_applet_by_name() early, and return -1 without ever
touching environ. Also, since you expect the BB_EXEC* not to return on
success, there's no need to save the environ.
The sketch looks like this:
extern char **environ;
BB_EXECVP(file, argv)
{
/* passing environ indicates we're not changing it */
return BB_EXECVPE(file, argv, environ);
}
BB_EXECVPE(file, argv, envp)
{
applet = -1;
if (ENABLE_FEATURE_PREFER_APPLETS &&
(applet = find_applet_by_name(file)) > 0 &&
!APPLET_IS_NOEXEC(applet))
{
if (env != environ) {
clearenv();
for (e in envp) putenv(e);
}
exec_applet(...); /* noreturn */
} else {
if (ENABLE_FEATURE_FORCE_APPLETS) {
errno = applet < 0 ? ENOENT : ENOEXEC;
return -1;
}
if (envp == environ)
return execv(file, argv);
else
return execve(file, argv, envp);
}
}
More information about the busybox
mailing list