[PATCH v8 11/14] applets: use bb_execXX functions instead of direct exec calls

Nadav Tasher tashernadav at gmail.com
Sun Mar 9 23:55:33 UTC 2025


This replaces all invocations of functions from the exec
family with the equivalent proxy functions.

This change provides better control over executed programs
and allows all applets to seamlessly execute other applets
when FEATURE_PREFER_APPLETS is enabled.

Signed-off-by: Nadav Tasher <tashernadav at gmail.com>
---
 archival/libarchive/data_extract_to_command.c |  9 ++---
 archival/libarchive/open_transformer.c        |  3 +-
 console-tools/openvt.c                        |  2 +-
 console-tools/reset.c                         |  2 +-
 coreutils/chroot.c                            |  2 +-
 coreutils/env.c                               |  2 +-
 coreutils/nice.c                              |  2 +-
 coreutils/nohup.c                             |  2 +-
 coreutils/timeout.c                           |  2 +-
 debianutils/start_stop_daemon.c               |  2 +-
 init/bootchartd.c                             | 19 +++++++---
 init/halt.c                                   |  9 +----
 init/init.c                                   |  4 +-
 libbb/run_shell.c                             |  4 +-
 loginutils/adduser.c                          |  7 +++-
 loginutils/getty.c                            | 19 +++++++++-
 mailutils/mail.c                              |  2 +-
 mailutils/reformime.c                         |  2 +-
 miscutils/conspy.c                            | 11 +++++-
 miscutils/crond.c                             | 38 ++++++++++++++++---
 miscutils/crontab.c                           | 13 ++++++-
 miscutils/time.c                              |  2 +-
 networking/ftpd.c                             |  3 +-
 networking/ifupdown.c                         | 17 ++++++++-
 networking/inetd.c                            |  6 +--
 networking/nc.c                               |  3 +-
 networking/nc_bloaty.c                        |  2 +-
 networking/tcpudp.c                           |  2 +-
 networking/telnetd.c                          |  2 +-
 networking/wget.c                             |  5 +--
 printutils/lpd.c                              |  2 +-
 runit/chpst.c                                 |  2 +-
 runit/runsv.c                                 |  9 ++++-
 runit/runsvdir.c                              | 13 ++++++-
 runit/svlogd.c                                | 15 +++++++-
 selinux/runcon.c                              |  2 +-
 shell/cttyhack.c                              |  2 +-
 util-linux/chrt.c                             |  2 +-
 util-linux/ionice.c                           |  2 +-
 util-linux/script.c                           | 18 ++++++++-
 util-linux/setarch.c                          |  2 +-
 util-linux/setpriv.c                          |  2 +-
 util-linux/setsid.c                           |  2 +-
 util-linux/switch_root.c                      |  2 +-
 util-linux/taskset.c                          |  2 +-
 45 files changed, 195 insertions(+), 80 deletions(-)

diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c
index f8b2ff8d2..f1829a6cc 100644
--- a/archival/libarchive/data_extract_to_command.c
+++ b/archival/libarchive/data_extract_to_command.c
@@ -83,6 +83,8 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
 		xpipe(p);
 		pid = BB_MMU ? xfork() : xvfork();
 		if (pid == 0) {
+			char *shell_arg0 = xstrdup(archive_handle->tar__to_command_shell), shell_arg1[] = "-c", *shell_arg2 = xstrdup(archive_handle->tar__to_command), *shell_argv[4] = {shell_arg0, shell_arg1, shell_arg2, NULL};
+
 			/* Child */
 			/* str2env(tar_env, TAR_FILETYPE, "f"); - parent should do it once */
 			oct2env(tar_env, TAR_MODE, file_header->mode);
@@ -98,12 +100,7 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
 			close(p[1]);
 			xdup2(p[0], STDIN_FILENO);
 			signal(SIGPIPE, SIG_DFL);
-			execl(archive_handle->tar__to_command_shell,
-				archive_handle->tar__to_command_shell,
-				"-c",
-				archive_handle->tar__to_command,
-				(char *)0);
-			bb_perror_msg_and_die("can't execute '%s'", archive_handle->tar__to_command_shell);
+			bb_execvp_or_die(shell_argv);
 		}
 		close(p[0]);
 		/* Our caller is expected to do signal(SIGPIPE, SIG_IGN)
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c
index 44715ef25..28d17ed64 100644
--- a/archival/libarchive/open_transformer.c
+++ b/archival/libarchive/open_transformer.c
@@ -139,8 +139,7 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog)
 			argv[1] = (char*)"-cf";
 			argv[2] = (char*)"-";
 			argv[3] = NULL;
-			BB_EXECVP(transform_prog, argv);
-			bb_perror_msg_and_die("can't execute '%s'", transform_prog);
+			bb_execvp_or_die(argv);
 		}
 #endif
 		/* notreached */
diff --git a/console-tools/openvt.c b/console-tools/openvt.c
index c35617eb8..7015a52cf 100644
--- a/console-tools/openvt.c
+++ b/console-tools/openvt.c
@@ -119,7 +119,7 @@ static NOINLINE void vfork_child(char **argv)
 		//bb_error_msg("our pgrp %d", getpgrp());
 		//bb_error_msg("VT's sid %d", tcgetsid(0));
 		//bb_error_msg("VT's pgrp %d", tcgetpgrp(0));
-		BB_EXECVP_or_die(argv);
+		bb_execvp_or_die(argv);
 	}
 }
 
diff --git a/console-tools/reset.c b/console-tools/reset.c
index 655a5ef7a..4da183b7b 100644
--- a/console-tools/reset.c
+++ b/console-tools/reset.c
@@ -58,7 +58,7 @@ int reset_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
 #else
 		/* Make sure stdout gets drained before we execvp */
 		fflush_all();
-		execvp("stty", (char**)args);
+		bb_execvp("stty", (char**)args);
 #endif
 	}
 	return EXIT_SUCCESS;
diff --git a/coreutils/chroot.c b/coreutils/chroot.c
index 0b45aa80c..8fda2524b 100644
--- a/coreutils/chroot.c
+++ b/coreutils/chroot.c
@@ -51,5 +51,5 @@ int chroot_main(int argc UNUSED_PARAM, char **argv)
 		/*argv[2] = NULL; - already is */
 	}
 
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 }
diff --git a/coreutils/env.c b/coreutils/env.c
index e9d3e883e..2985e776c 100644
--- a/coreutils/env.c
+++ b/coreutils/env.c
@@ -89,7 +89,7 @@ int env_main(int argc UNUSED_PARAM, char **argv)
 	}
 
 	if (argv[0]) {
-		BB_EXECVP_or_die(argv);
+		bb_execvp_or_die(argv);
 	}
 
 	if (environ) { /* clearenv() may set environ == NULL! */
diff --git a/coreutils/nice.c b/coreutils/nice.c
index 0648593ee..3694d0ee7 100644
--- a/coreutils/nice.c
+++ b/coreutils/nice.c
@@ -64,5 +64,5 @@ int nice_main(int argc UNUSED_PARAM, char **argv)
 		}
 	}
 
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 }
diff --git a/coreutils/nohup.c b/coreutils/nohup.c
index 69d8daff9..a8e947d85 100644
--- a/coreutils/nohup.c
+++ b/coreutils/nohup.c
@@ -94,5 +94,5 @@ int nohup_main(int argc UNUSED_PARAM, char **argv)
 	signal(SIGHUP, SIG_IGN);
 
 	argv++;
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 }
diff --git a/coreutils/timeout.c b/coreutils/timeout.c
index 84299a0a5..1275813ac 100644
--- a/coreutils/timeout.c
+++ b/coreutils/timeout.c
@@ -154,5 +154,5 @@ int timeout_main(int argc UNUSED_PARAM, char **argv)
 	argv[0] = sv1;
 	argv[1] = sv2;
 #endif
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 }
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c
index 271bc4edf..e667a1f63 100644
--- a/debianutils/start_stop_daemon.c
+++ b/debianutils/start_stop_daemon.c
@@ -629,6 +629,6 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
 	 * strace -oLOG start-stop-daemon -S -x /bin/usleep -a qwerty 500000
 	 * should exec "/bin/usleep", but argv[0] should be "qwerty":
 	 */
-	execvp(execname, argv);
+	bb_execvp(execname, argv);
 	bb_perror_msg_and_die("can't execute '%s'", startas);
 }
diff --git a/init/bootchartd.c b/init/bootchartd.c
index f23025fbf..9a5d69db3 100644
--- a/init/bootchartd.c
+++ b/init/bootchartd.c
@@ -445,11 +445,20 @@ int bootchartd_main(int argc UNUSED_PARAM, char **argv)
 	}
 
 	if (cmd == CMD_PID1) {
+		char init_arg0[] = "init", *init_argv[2] = {init_arg0, NULL};
+
 		char *bootchart_init = getenv("bootchart_init");
-		if (bootchart_init)
-			execl(bootchart_init, bootchart_init, NULL);
-		execl("/init", "init", NULL);
-		execl("/sbin/init", "init", NULL);
+		if (bootchart_init) {
+			char *bootchart_arg0 = xstrdup(bootchart_init), *bootchart_argv[2] = {bootchart_arg0, NULL};
+			bb_execvp(bootchart_arg0, bootchart_argv);
+
+			/* free copied argument */
+			free(bootchart_arg0);
+		}
+
+		/* fallback, we are calling different init binaries */
+		bb_execvp("/init", init_argv);
+		bb_execvp("/sbin/init", init_argv);
 		bb_perror_msg_and_die("can't execute '%s'", "/sbin/init");
 	}
 
@@ -457,7 +466,7 @@ int bootchartd_main(int argc UNUSED_PARAM, char **argv)
 		pid_t pid = xvfork();
 		if (pid == 0) { /* child */
 			argv += 2;
-			BB_EXECVP_or_die(argv);
+			bb_execvp_or_die(argv);
 		}
 		/* parent */
 		waitpid(pid, NULL, 0);
diff --git a/init/halt.c b/init/halt.c
index 7aea8cfec..76dba6b42 100644
--- a/init/halt.c
+++ b/init/halt.c
@@ -230,13 +230,8 @@ int halt_main(int argc UNUSED_PARAM, char **argv)
 				/* runlevels:
 				 * 0 == shutdown
 				 * 6 == reboot */
-				execlp(CONFIG_TELINIT_PATH,
-						CONFIG_TELINIT_PATH,
-						which == 2 ? "6" : "0",
-						(char *)NULL
-				);
-				bb_perror_msg_and_die("can't execute '%s'",
-						CONFIG_TELINIT_PATH);
+				char telinit_arg0[] = CONFIG_TELINIT_PATH, telinit_arg1_6[] = "6", telinit_arg1_0[] = "0", *telinit_argv[] = {telinit_arg0, which == 2 ? telinit_arg1_6 : telinit_arg1_0, NULL};
+				bb_execvp_or_die(telinit_argv);
 			}
 		}
 	} else {
diff --git a/init/init.c b/init/init.c
index 2ee1e4cde..0b3ce68f1 100644
--- a/init/init.c
+++ b/init/init.c
@@ -470,7 +470,7 @@ static void init_exec(const char *command)
 		ioctl(STDIN_FILENO, TIOCSCTTY, 0 /*only try, don't steal*/);
 	}
 	/* Here command never contains the dash, cmd[0] might */
-	BB_EXECVP(command, cmd);
+	bb_execvp(command, cmd);
 	message(L_LOG | L_CONSOLE, "can't run '%s': "STRERROR_FMT, command STRERROR_ERRNO);
 	/* returns if execvp fails */
 }
@@ -1145,7 +1145,7 @@ int init_main(int argc UNUSED_PARAM, char **argv)
 
 		putenv((char*)"SELINUX_INIT=YES");
 		if (selinux_init_load_policy(&enforce) == 0) {
-			BB_EXECVP(argv[0], argv);
+			bb_execvp(argv[0], argv);
 		} else if (enforce > 0) {
 			/* SELinux in enforcing mode but load_policy failed */
 			message(L_CONSOLE, "can't load SELinux Policy. "
diff --git a/libbb/run_shell.c b/libbb/run_shell.c
index c22bba87b..e326190d9 100644
--- a/libbb/run_shell.c
+++ b/libbb/run_shell.c
@@ -80,7 +80,7 @@ void FAST_FUNC exec_shell(const char *shell, int loginshell, const char **additi
 	if (ENABLE_FEATURE_CLEAN_UP)
 		freecon(current_sid);
 #endif
-	execv(shell, (char **) args);
+	bb_execvp(shell, (char **) args);
 	bb_perror_msg_and_die("can't execute '%s'", shell);
 }
 
@@ -93,7 +93,7 @@ void FAST_FUNC exec_login_shell(const char *shell)
 void FAST_FUNC exec_prog_or_SHELL(char **argv)
 {
 	if (argv[0]) {
-		BB_EXECVP_or_die(argv);
+		bb_execvp_or_die(argv);
 	}
 	/* Both users (nsenter and unshare) do indeed exec
 	 * a _login_ shell (with dash in argv[0])!
diff --git a/loginutils/adduser.c b/loginutils/adduser.c
index d3c795afa..4f8c4715f 100644
--- a/loginutils/adduser.c
+++ b/loginutils/adduser.c
@@ -158,8 +158,11 @@ static void passwd_wrapper(const char *login_name) NORETURN;
 
 static void passwd_wrapper(const char *login_name)
 {
-	BB_EXECLP("passwd", "passwd", "--", login_name, NULL);
-	bb_simple_error_msg_and_die("can't execute passwd, you must set password manually");
+	char passwd_arg0[] = "passwd", passwd_arg1[] = "--", *passwd_arg2 = xstrdup(login_name), *passwd_argv[] = {passwd_arg0, passwd_arg1, passwd_arg2, NULL};
+	bb_execvp_or_die_msg(passwd_argv, "can't execute '%s', you must set password manually");
+
+	/* free copied arguments */
+	free(passwd_arg2);
 }
 
 //FIXME: upstream adduser has no short options! NOT COMPATIBLE!
diff --git a/loginutils/getty.c b/loginutils/getty.c
index 4581cc9f7..babae48d1 100644
--- a/loginutils/getty.c
+++ b/loginutils/getty.c
@@ -552,6 +552,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
 	int n;
 	pid_t pid, tsid;
 	char *logname;
+	char *login_arg0, login_arg1[] = "--", *login_arg2, *login_argv[4];
 
 	INIT_G();
 	G.login = _PATH_LOGIN;    /* default login program */
@@ -732,6 +733,20 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
 	/* We use PATH because we trust that root doesn't set "bad" PATH,
 	 * and getty is not suid-root applet */
 	/* With -n, logname == NULL, and login will ask for username instead */
-	BB_EXECLP(G.login, G.login, "--", logname, (char *)0);
-	bb_error_msg_and_die("can't execute '%s'", G.login);
+
+	/* we need to copy some arguments since bb_execvp 
+	 * might modify the strings */
+	login_arg0 = xstrdup(G.login);
+	login_arg2 = xstrdup(logname);
+
+	login_argv[0] = login_arg0;
+	login_argv[1] = login_arg1;
+	login_argv[2] = login_arg2;
+	login_argv[3] = NULL;
+
+	bb_execvp_or_die(login_argv);
+
+	/* free copied arguments */
+	free(login_arg0);
+	free(login_arg2);
 }
diff --git a/mailutils/mail.c b/mailutils/mail.c
index f48b41bab..031b2738d 100644
--- a/mailutils/mail.c
+++ b/mailutils/mail.c
@@ -71,7 +71,7 @@ void FAST_FUNC launch_helper(const char **argv)
 #endif
 		// try to execute connection helper
 		// NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
-		BB_EXECVP_or_die((char**)argv);
+		bb_execvp_or_die((char **) argv);
 	}
 	G.helper_pid = pid;
 	close(child_out.wr);
diff --git a/mailutils/reformime.c b/mailutils/reformime.c
index 850dfb9cc..d7e2c78c7 100644
--- a/mailutils/reformime.c
+++ b/mailutils/reformime.c
@@ -180,7 +180,7 @@ static int parse(const char *boundary, char **argv)
 					xsetenv("CHARSET", charset);
 					xsetenv("ENCODING", encoding);
 					xsetenv("FILENAME", filename);
-					BB_EXECVP_or_die(argv);
+					bb_execvp_or_die(argv);
 				}
 				/* parent will write to fd[1] */
 				close(fd[0]);
diff --git a/miscutils/conspy.c b/miscutils/conspy.c
index 21a498d0f..b90128314 100644
--- a/miscutils/conspy.c
+++ b/miscutils/conspy.c
@@ -332,6 +332,7 @@ static void create_cdev_if_doesnt_exist(const char* name, dev_t dev)
 
 static NOINLINE void start_shell_in_child(const char* tty_name)
 {
+	char *shell_arg0, shell_arg1[] = "-i", *shell_argv[3];
 	int pid = xvfork();
 	if (pid == 0) {
 		struct termios termchild;
@@ -353,8 +354,14 @@ static NOINLINE void start_shell_in_child(const char* tty_name)
 		termchild.c_iflag |= ICRNL;
 		termchild.c_iflag &= ~IXOFF;
 		tcsetattr_stdin_TCSANOW(&termchild);
-		execl(shell, shell, "-i", (char *) NULL);
-		bb_simple_perror_msg_and_die(shell);
+		// duplicate shell, so it is safe
+		shell_arg0 = xstrdup(shell);
+		shell_argv[0] = shell_arg0;
+		shell_argv[1] = shell_arg1;
+		shell_argv[2] = NULL;
+		bb_execvp_or_die(shell_argv);
+		// free copied argument
+		free(shell_arg0);
 	}
 }
 
diff --git a/miscutils/crond.c b/miscutils/crond.c
index b3762d327..c8b309399 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -699,6 +699,8 @@ fork_job(const char *user, int mailFd, CronLine *line, bool run_sendmail)
 	const char *shell, *prog;
 	smallint sv_logmode;
 	pid_t pid;
+	char *shell_arg0, shell_arg1[] = "-c", *shell_arg2, *shell_argv[4];
+	char sendmail_arg0[] = SENDMAIL, sendmail_arg1[] = SENDMAIL_ARGS, *sendmail_argv[] = {sendmail_arg0, sendmail_arg1, NULL};
 
 	/* prepare things before vfork */
 	pas = getpwnam(user);
@@ -725,10 +727,22 @@ fork_job(const char *user, int mailFd, CronLine *line, bool run_sendmail)
 		}
 		/* crond 3.0pl1-100 puts tasks in separate process groups */
 		bb_setpgrp();
-		if (!run_sendmail)
-			execlp(prog, prog, "-c", line->cl_cmd, (char *) NULL);
-		else
-			execlp(prog, prog, SENDMAIL_ARGS, (char *) NULL);
+		if (!run_sendmail) {
+			shell_arg0 = xstrdup(shell);
+			shell_arg2 = xstrdup(line->cl_cmd);
+
+			shell_argv[0] = shell_arg0;
+			shell_argv[1] = shell_arg1;
+			shell_argv[2] = shell_arg2;
+			shell_argv[3] = NULL;
+
+			bb_execvp(shell_argv[0], shell_argv);
+
+			free(shell_arg0);
+			free(shell_arg2);
+		} else {
+			bb_execvp(sendmail_argv[0], sendmail_argv);
+		}
 		/*
 		 * I want this error message on stderr too,
 		 * even if other messages go only to syslog:
@@ -845,6 +859,7 @@ static pid_t start_one_job(const char *user, CronLine *line)
 	const char *shell;
 	struct passwd *pas;
 	pid_t pid;
+	char *shell_arg0, shell_arg1[] = "-c", *shell_arg2, *shell_argv[4];
 
 	pas = getpwnam(user);
 	if (!pas) {
@@ -865,7 +880,20 @@ static pid_t start_one_job(const char *user, CronLine *line)
 		log5("child running %s", shell);
 		/* crond 3.0pl1-100 puts tasks in separate process groups */
 		bb_setpgrp();
-		execl(shell, shell, "-c", line->cl_cmd, (char *) NULL);
+
+		shell_arg0 = xstrdup(shell);
+		shell_arg2 = xstrdup(line->cl_cmd);
+
+		shell_argv[0] = shell_arg0;
+		shell_argv[1] = shell_arg1;
+		shell_argv[2] = shell_arg2;
+		shell_argv[3] = NULL;
+
+		bb_execvp(shell_argv[0], shell_argv);
+
+		free(shell_arg0);
+		free(shell_arg2);
+
 		bb_error_msg_and_die("can't execute '%s' for user %s", shell, user);
 	}
 	if (pid < 0) {
diff --git a/miscutils/crontab.c b/miscutils/crontab.c
index 1111f4d54..d1e5c6c2c 100644
--- a/miscutils/crontab.c
+++ b/miscutils/crontab.c
@@ -44,6 +44,7 @@ static void edit_file(const struct passwd *pas, const char *file)
 {
 	const char *ptr;
 	pid_t pid;
+	char *edit_arg0, *edit_arg1, *edit_argv[3];
 
 	pid = xvfork();
 	if (pid) { /* parent */
@@ -64,8 +65,16 @@ static void edit_file(const struct passwd *pas, const char *file)
 			ptr = "vi";
 	}
 
-	BB_EXECLP(ptr, ptr, file, NULL);
-	bb_perror_msg_and_die("can't execute '%s'", ptr);
+	edit_arg0 = xstrdup(ptr);
+	edit_arg1 = xstrdup(file);
+	
+	edit_argv[0] = edit_arg0;
+	edit_argv[1] = edit_arg1;
+	edit_argv[2] = NULL;
+	bb_execvp_or_die(edit_argv);
+
+	free(edit_arg0);
+	free(edit_arg1);
 }
 
 int crontab_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
diff --git a/miscutils/time.c b/miscutils/time.c
index 77d35a832..8a8f6b962 100644
--- a/miscutils/time.c
+++ b/miscutils/time.c
@@ -416,7 +416,7 @@ static void run_command(char *const *cmd, resource_t *resp)
 	pid = xvfork();
 	if (pid == 0) {
 		/* Child */
-		BB_EXECVP_or_die((char**)cmd);
+		bb_execvp_or_die((char**)cmd);
 	}
 
 	/* Have signals kill the child but not self (if possible).  */
diff --git a/networking/ftpd.c b/networking/ftpd.c
index 0d6a289c7..e0ad29441 100644
--- a/networking/ftpd.c
+++ b/networking/ftpd.c
@@ -733,8 +733,7 @@ popen_ls(const char *opt)
 		}
 		/* Child expects directory to list on fd #3 */
 		xmove_fd(cur_fd, 3);
-		execv(bb_busybox_exec_path, (char**) argv);
-		_exit(127);
+		bb_execvp_or_die((char **) argv);
 #endif
 	}
 
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 9c3640be7..e747ea368 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -1146,6 +1146,7 @@ static void set_environ(struct interface_defn_t *iface, const char *mode, const
 
 static int doit(char *str)
 {
+	char *shell_arg0, shell_arg1[] = "-c", *shell_arg2, *shell_argv[4];
 	if (option_mask32 & (OPT_no_act|OPT_verbose)) {
 		puts(str);
 	}
@@ -1158,7 +1159,19 @@ static int doit(char *str)
 		if (child < 0) /* failure */
 			return 0;
 		if (child == 0) { /* child */
-			execle(G.shell, G.shell, "-c", str, (char *) NULL, G.my_environ);
+			shell_arg0 = xstrdup(G.shell);
+			shell_arg2 = xstrdup(str);
+
+			shell_argv[0] = shell_arg0;
+			shell_argv[1] = shell_arg1;
+			shell_argv[2] = shell_arg2;
+			shell_argv[3] = NULL;
+
+			bb_execvpe(shell_argv[0], shell_argv, G.my_environ);
+
+			free(shell_arg0);
+			free(shell_arg2);
+
 			_exit(127);
 		}
 		safe_waitpid(child, &status, 0);
@@ -1244,7 +1257,7 @@ static int popen2(FILE **in, FILE **out, char *command, char *param)
 		close(outfd.rd);
 		xmove_fd(infd.rd, 0);
 		xmove_fd(outfd.wr, 1);
-		BB_EXECVP_or_die(argv);
+		bb_execvp_or_die(argv);
 	}
 	/* parent */
 	close(infd.rd);
diff --git a/networking/inetd.c b/networking/inetd.c
index e63edcd9d..2bcb0b312 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -1524,7 +1524,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 			sigaction_set(SIGPIPE, &saved_pipe_handler);
 			restore_sigmask(&omask);
 			dbg("execing:'%s'\n", sep->se_program);
-			BB_EXECVP(sep->se_program, sep->se_argv);
+			bb_execvp(sep->se_program, sep->se_argv);
 			bb_perror_msg("can't execute '%s'", sep->se_program);
  do_exit1:
 			/* eat packet in udp case */
@@ -1565,7 +1565,7 @@ static void FAST_FUNC echo_stream(int s, servtab_t *sep UNUSED_PARAM)
 	/* no error messages please... */
 	close(STDERR_FILENO);
 	xopen(bb_dev_null, O_WRONLY);
-	BB_EXECVP("cat", (char**)cat_args);
+	bb_execvp("cat", (char**)cat_args);
 	/* on failure we return to main, which does exit(EXIT_FAILURE) */
 # endif
 }
@@ -1603,7 +1603,7 @@ static void FAST_FUNC discard_stream(int s, servtab_t *sep UNUSED_PARAM)
 	xopen(bb_dev_null, O_WRONLY);
 	/* no error messages please... */
 	xdup2(STDOUT_FILENO, STDERR_FILENO);
-	BB_EXECVP("cat", (char**)cat_args);
+	bb_execvp("cat", (char**)cat_args);
 	/* on failure we return to main, which does exit(EXIT_FAILURE) */
 # endif
 }
diff --git a/networking/nc.c b/networking/nc.c
index ab1316339..ce5e5e8fa 100644
--- a/networking/nc.c
+++ b/networking/nc.c
@@ -241,8 +241,7 @@ int nc_main(int argc, char **argv)
 		xmove_fd(cfd, 0);
 		xdup2(0, 1);
 		/*xdup2(0, 2); - original nc 1.10 does this, we don't */
-		IF_NC_EXTRA(BB_EXECVP(execparam[0], execparam);)
-		IF_NC_EXTRA(bb_perror_msg_and_die("can't execute '%s'", execparam[0]);)
+		IF_NC_EXTRA(bb_execvp_or_die(execparam);)
 	}
 
 	/* loop copying stdin to cfd, and cfd to stdout */
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c
index d35c9e140..307e4417d 100644
--- a/networking/nc_bloaty.c
+++ b/networking/nc_bloaty.c
@@ -275,7 +275,7 @@ static int doexec(char **proggie)
 	dup2(0, 1);
 	/* dup2(0, 2); - do we *really* want this? NO!
 	 * exec'ed prog can do it yourself, if needed */
-	BB_EXECVP_or_die(proggie);
+	bb_execvp_or_die(proggie);
 }
 
 /* connect_w_timeout:
diff --git a/networking/tcpudp.c b/networking/tcpudp.c
index 708e05c2e..dcbc6315f 100644
--- a/networking/tcpudp.c
+++ b/networking/tcpudp.c
@@ -609,7 +609,7 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv)
 	ssl_io(0, argv);
 	bb_perror_msg_and_die("can't execute '%s'", argv[0]);
 #else
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 #endif
 }
 
diff --git a/networking/telnetd.c b/networking/telnetd.c
index bfeea1400..0f1565e6f 100644
--- a/networking/telnetd.c
+++ b/networking/telnetd.c
@@ -568,7 +568,7 @@ make_new_session(
 	 * NB: sock is either 0 or has CLOEXEC set on it.
 	 * fd has CLOEXEC set on it too. These two fds will be closed here.
 	 */
-	BB_EXECVP(G.loginpath, (char **)login_argv);
+	bb_execvp(G.loginpath, (char **)login_argv);
 	/* _exit is safer with vfork, and we shouldn't send message
 	 * to remote clients anyway */
 	_exit_FAILURE(); /*bb_perror_msg_and_die("execv %s", G.loginpath);*/
diff --git a/networking/wget.c b/networking/wget.c
index ec3767793..a79852054 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -740,7 +740,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
 		}
 		//[12] (or earlier) is NULL terminator
 
-		BB_EXECVP(argv[0], argv);
+		bb_execvp(argv[0], argv);
 		xmove_fd(3, 2);
 # if ENABLE_FEATURE_WGET_HTTPS
 		child_failed = 1;
@@ -809,8 +809,7 @@ static void spawn_ssl_client(const char *host, int network_fd, int flags)
 			argv[3] = servername;
 			argv[4] = (flags & TLSLOOP_EXIT_ON_LOCAL_EOF ? (char*)"-e" : NULL);
 			argv[5] = NULL;
-			BB_EXECVP(argv[0], argv);
-			bb_perror_msg_and_die("can't execute '%s'", argv[0]);
+			bb_execvp_or_die(argv);
 		}
 		/* notreached */
 	}
diff --git a/printutils/lpd.c b/printutils/lpd.c
index c67d54708..42680d18b 100644
--- a/printutils/lpd.c
+++ b/printutils/lpd.c
@@ -202,7 +202,7 @@ int lpd_main(int argc UNUSED_PARAM, char **argv)
 			// helper should not talk over network.
 			// this call reopens stdio fds to "/dev/null".
 			bb_daemon_helper(DAEMON_DEVNULL_STDIO);
-			BB_EXECVP_or_die(argv);
+			bb_execvp_or_die(argv);
 		}
 
 		// validate input.
diff --git a/runit/chpst.c b/runit/chpst.c
index 4e3d613b7..a5635b630 100644
--- a/runit/chpst.c
+++ b/runit/chpst.c
@@ -485,5 +485,5 @@ int chpst_main(int argc UNUSED_PARAM, char **argv)
 	if (opt & OPT_2)
 		close(STDERR_FILENO);
 
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 }
diff --git a/runit/runsv.c b/runit/runsv.c
index 20a445319..45774d31f 100644
--- a/runit/runsv.c
+++ b/runit/runsv.c
@@ -280,6 +280,7 @@ static unsigned custom(struct svdir *s, char c)
 	int w;
 	char a[10];
 	struct stat st;
+	char *exec_argv[2];
 
 	if (s->islog)
 		return 0;
@@ -296,7 +297,11 @@ static unsigned custom(struct svdir *s, char c)
 				/* child */
 				if (haslog && dup2(logpipe.wr, 1) == -1)
 					warn2_cannot("setup stdout for ", a);
-				execl(a, a, (char *) NULL);
+
+				exec_argv[0] = a;
+				exec_argv[1] = NULL;
+
+				bb_execvp(exec_argv[0], exec_argv);
 				fatal2_cannot("run ", a);
 			}
 			/* parent */
@@ -391,7 +396,7 @@ static void startservice(struct svdir *s)
 		signal(SIGTERM, SIG_DFL);
 		sig_unblock(SIGCHLD);
 		sig_unblock(SIGTERM);
-		execv(arg[0], (char**) arg);
+		bb_execvp(arg[0], (char**) arg);
 		fatal2_cannot(s->islog ? "start log/" : "start ", arg[0]);
 	}
 	/* parent */
diff --git a/runit/runsvdir.c b/runit/runsvdir.c
index d6629dedd..ceba9ce0b 100644
--- a/runit/runsvdir.c
+++ b/runit/runsvdir.c
@@ -119,6 +119,7 @@ static void warnx(const char *m1)
 static NOINLINE pid_t runsv(const char *name)
 {
 	pid_t pid;
+	char runsv_arg0[] = "runsv", *runsv_arg1, *runsv_argv[3];
 
 	/* If we got signaled, stop spawning children at once! */
 	if (bb_got_signal)
@@ -143,7 +144,17 @@ static NOINLINE pid_t runsv(const char *name)
 			| (1 << SIGTERM)
 			, SIG_DFL);
 #endif
-		execlp("runsv", "runsv", name, (char *) NULL);
+		/* we have to keep name safe */
+		runsv_arg1 = xstrdup(name);
+		
+		runsv_argv[0] = runsv_arg0;
+		runsv_argv[1] = runsv_arg1;
+		runsv_argv[2] = NULL;
+
+		bb_execvp(runsv_argv[0], runsv_argv);
+		
+		free(runsv_arg1);
+
 		fatal2_cannot("start runsv ", name);
 	}
 	return pid;
diff --git a/runit/svlogd.c b/runit/svlogd.c
index f7576f0fa..dfac94c0a 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -393,6 +393,7 @@ static void processorstart(struct logdir *ld)
 {
 	char sv_ch;
 	int pid;
+	char *shell_arg0, shell_arg1[] = "-c", *shell_arg2, *shell_argv[4];
 
 	if (!ld->processor) return;
 	if (ld->ppid) {
@@ -453,7 +454,19 @@ static void processorstart(struct logdir *ld)
 		fd = xopen("newstate", O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT);
 		xmove_fd(fd, 5);
 
-		execl(G.shell, G.shell, "-c", ld->processor, (char*) NULL);
+		shell_arg0 = xstrdup(G.shell);
+		shell_arg2 = xstrdup(ld->processor);
+
+		shell_argv[0] = shell_arg0;
+		shell_argv[1] = shell_arg1;
+		shell_argv[2] = shell_arg2;
+		shell_argv[3] = NULL;
+
+		bb_execvp(shell_argv[0], shell_argv);
+
+		free(shell_arg0);
+		free(shell_arg2);
+
 		bb_perror_msg_and_die(FATAL"can't %s processor %s", "run", ld->name);
 	}
 	ld->fnsave[26] = sv_ch; /* ...restore */
diff --git a/selinux/runcon.c b/selinux/runcon.c
index bc4fa23e0..ae381dee1 100644
--- a/selinux/runcon.c
+++ b/selinux/runcon.c
@@ -157,5 +157,5 @@ int runcon_main(int argc UNUSED_PARAM, char **argv)
 		bb_error_msg_and_die("can't set up security context '%s'",
 				context_str(con));
 
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 }
diff --git a/shell/cttyhack.c b/shell/cttyhack.c
index 62dfb2bc2..e52168e6f 100644
--- a/shell/cttyhack.c
+++ b/shell/cttyhack.c
@@ -184,5 +184,5 @@ int cttyhack_main(int argc UNUSED_PARAM, char **argv)
 	 */
 	ioctl(0, TIOCSCTTY, 1);
  ret:
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 }
diff --git a/util-linux/chrt.c b/util-linux/chrt.c
index 51d08584e..a2beb4165 100644
--- a/util-linux/chrt.c
+++ b/util-linux/chrt.c
@@ -204,5 +204,5 @@ int chrt_main(int argc UNUSED_PARAM, char **argv)
 	if (!argv[0]) /* "-p PRIO PID [...]" */
 		goto print_rt_info;
 
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 }
diff --git a/util-linux/ionice.c b/util-linux/ionice.c
index b768c8322..cada5e646 100644
--- a/util-linux/ionice.c
+++ b/util-linux/ionice.c
@@ -110,7 +110,7 @@ int ionice_main(int argc UNUSED_PARAM, char **argv)
 			if (!(opt & OPT_t))
 				bb_perror_msg_and_die("ioprio_%cet", 's');
 		if (argv[0]) {
-			BB_EXECVP_or_die(argv);
+			bb_execvp_or_die(argv);
 		}
 	}
 
diff --git a/util-linux/script.c b/util-linux/script.c
index 58b844e77..34cff572c 100644
--- a/util-linux/script.c
+++ b/util-linux/script.c
@@ -60,8 +60,10 @@ int script_main(int argc UNUSED_PARAM, char **argv)
 	const char *str_t = NULL;
 	const char *fname = "typescript";
 	const char *shell;
+	char *shell_copy;
 	char shell_opt[] = "-i";
 	char *shell_arg = NULL;
+	char *shell_argv[4];
 	enum {
 		OPT_a = (1 << 0),
 		OPT_c = (1 << 1),
@@ -235,6 +237,18 @@ int script_main(int argc UNUSED_PARAM, char **argv)
 
 	/* Non-ignored signals revert to SIG_DFL on exec anyway */
 	/*signal(SIGCHLD, SIG_DFL);*/
-	execl(shell, shell, shell_opt, shell_arg, (char *) NULL);
-	bb_simple_perror_msg_and_die(shell);
+
+	/* copy shell argument, we don't want it to be modified. */
+	shell_copy = xstrdup(shell);
+
+	shell_argv[0] = shell_copy;
+	shell_argv[1] = shell_opt;
+	shell_argv[2] = shell_arg;
+	shell_argv[3] = NULL;
+	bb_execvp_or_die(shell_argv);
+
+	/* free copied shell */
+	free(shell_copy);
+
+	return -1;
 }
diff --git a/util-linux/setarch.c b/util-linux/setarch.c
index 68b7c663c..3c950322f 100644
--- a/util-linux/setarch.c
+++ b/util-linux/setarch.c
@@ -98,5 +98,5 @@ int setarch_main(int argc UNUSED_PARAM, char **argv)
 		(--argv)[0] = (char*)"/bin/sh";
 
 	/* Try to execute the program */
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 }
diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c
index ee038516d..da4345934 100644
--- a/util-linux/setpriv.c
+++ b/util-linux/setpriv.c
@@ -331,5 +331,5 @@ int setpriv_main(int argc UNUSED_PARAM, char **argv)
 
 	if (!argv[0])
 		bb_show_usage();
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 }
diff --git a/util-linux/setsid.c b/util-linux/setsid.c
index 24b02a509..9bfca99d4 100644
--- a/util-linux/setsid.c
+++ b/util-linux/setsid.c
@@ -78,5 +78,5 @@ int setsid_main(int argc UNUSED_PARAM, char **argv)
 		ioctl(0, TIOCSCTTY, 1);
 	}
 
-	BB_EXECVP_or_die(argv);
+	bb_execvp_or_die(argv);
 }
diff --git a/util-linux/switch_root.c b/util-linux/switch_root.c
index 14139736e..6b396d3e8 100644
--- a/util-linux/switch_root.c
+++ b/util-linux/switch_root.c
@@ -281,7 +281,7 @@ int switch_root_main(int argc UNUSED_PARAM, char **argv)
 			return 0;
 	} else {
 		// Exec NEW_INIT
-		execv(argv[0], argv);
+		bb_execvp(argv[0], argv);
 	}
 	bb_perror_msg_and_die("can't execute '%s'", argv[0]);
 }
diff --git a/util-linux/taskset.c b/util-linux/taskset.c
index a3aa06119..93f49fede 100644
--- a/util-linux/taskset.c
+++ b/util-linux/taskset.c
@@ -321,7 +321,7 @@ int taskset_main(int argc UNUSED_PARAM, char **argv)
 		if (!*argv)
 			bb_show_usage();
 		process_pid_str(NULL, opts, aff);
-		BB_EXECVP_or_die(argv);
+		bb_execvp_or_die(argv);
 	}
 
 	pid_str = aff;
-- 
2.43.0



More information about the busybox mailing list