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);
                }
        }



_______________________________________________
busybox mailing list
[email protected]
https://lists.busybox.net/mailman/listinfo/busybox

Reply via email to