[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