From: graham.gower Date: Tue, 17 Nov 2009 00:17:55 +0000 (+0000) Subject: Use vfork()/execvp() instead of system(). X-Git-Url: https://git.librecmc.org/?p=oweals%2Fopkg-lede.git;a=commitdiff_plain;h=603bec779ab8f0751bc48b0394aadd261fafdcde;hp=cd3404e22aa9baba2c617ce4d4d7f53e3f54853c Use vfork()/execvp() instead of system(). Parts based on a patch by Mike Westerhof for OpenEmbedded. git-svn-id: http://opkg.googlecode.com/svn/trunk@320 e8e0d7a0-c8d9-11dd-a880-a1081c7ac358 --- diff --git a/libopkg/opkg_cmd.c b/libopkg/opkg_cmd.c index b86e670..a93483f 100644 --- a/libopkg/opkg_cmd.c +++ b/libopkg/opkg_cmd.c @@ -340,7 +340,8 @@ static int opkg_finalize_intercepts(opkg_intercept_t ctx) sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name); if (access (path, X_OK) == 0) { - xsystem (path); + const char *argv[] = {"sh", "-c", path, NULL}; + xsystem (argv); } free (path); } diff --git a/libopkg/opkg_conf.c b/libopkg/opkg_conf.c index bd73317..cade51a 100644 --- a/libopkg/opkg_conf.c +++ b/libopkg/opkg_conf.c @@ -25,7 +25,6 @@ #include "opkg_message.h" #include "file_util.h" #include "str_util.h" -#include "xsystem.h" #include "opkg_defines.h" #include "libbb/libbb.h" diff --git a/libopkg/opkg_download.c b/libopkg/opkg_download.c index be3ae2a..953627b 100644 --- a/libopkg/opkg_download.c +++ b/libopkg/opkg_download.c @@ -147,16 +147,21 @@ int opkg_download(opkg_conf_t *conf, const char *src, #else { int res; - char *wgetcmd; - char *wgetopts; - wgetopts = getenv("OPKG_WGETOPTS"); - sprintf_alloc(&wgetcmd, "wget -q %s%s -O \"%s\" \"%s\"", - (conf->http_proxy || conf->ftp_proxy) ? "-Y on " : "", - (wgetopts!=NULL) ? wgetopts : "", - tmp_file_location, src); - opkg_message(conf, OPKG_INFO, "Executing: %s\n", wgetcmd); - res = xsystem(wgetcmd); - free(wgetcmd); + const char *argv[8]; + int i = 0; + + argv[i++] = "wget"; + argv[i++] = "-q"; + if (conf->http_proxy || conf->ftp_proxy) { + argv[i++] = "-Y"; + argv[i++] = "on"; + } + argv[i++] = "-O"; + argv[i++] = tmp_file_location; + argv[i++] = src; + argv[i++] = NULL; + res = xsystem(argv); + if (res) { opkg_message(conf, OPKG_ERROR, "Failed to download %s, error %d\n", src, res); free(tmp_file_location); diff --git a/libopkg/opkg_install.c b/libopkg/opkg_install.c index 02a2be4..5e8596b 100644 --- a/libopkg/opkg_install.c +++ b/libopkg/opkg_install.c @@ -1610,13 +1610,8 @@ static int user_prefers_old_conffile(const char *file_name, const char *backup) } if (strcmp(response, "d") == 0) { - char *cmd; - - free(response); - /* XXX: BUG rewrite to use exec or busybox's internal diff */ - sprintf_alloc(&cmd, "diff -u %s %s", backup, file_name); - xsystem(cmd); - free(cmd); + const char *argv[] = {"diff", "-u", backup, file_name, NULL}; + xsystem(argv); printf(" [Press ENTER to continue]\n"); response = file_read_line_alloc(stdin); free(response); diff --git a/libopkg/pkg.c b/libopkg/pkg.c index 78b6cad..b0c2b69 100644 --- a/libopkg/pkg.c +++ b/libopkg/pkg.c @@ -1195,8 +1195,10 @@ int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg, sprintf_alloc(&cmd, "%s %s", path, args); free(path); - - err = xsystem(cmd); + { + const char *argv[] = {"sh", "-c", cmd, NULL}; + err = xsystem(argv); + } free(cmd); if (err) { diff --git a/libopkg/xsystem.c b/libopkg/xsystem.c index 267f2f9..123510f 100644 --- a/libopkg/xsystem.c +++ b/libopkg/xsystem.c @@ -19,12 +19,7 @@ #include #include "xsystem.h" - -/* XXX: FEATURE: I shouldn't actually use system(3) at all. I don't - really need the /bin/sh invocation which takes resources and - introduces security problems. I should switch all of this to a sort - of execl() or execv() interface/implementation. -*/ +#include "libbb/libbb.h" /* Like system(3), but with error messages printed if the fork fails or if the child process dies due to an uncaught signal. Also, the @@ -34,31 +29,44 @@ Otherwise, the 8-bit return value of the program ala WEXITSTATUS as defined in . */ -int xsystem(const char *cmd) +int +xsystem(const char *argv[]) { - int err; + int status; + pid_t pid; + + pid = vfork(); - err = system(cmd); + switch (pid) { + case -1: + perror_msg("%s: %s: vfork", __FUNCTION__, argv[0]); + return -1; + case 0: + /* child */ + execvp(argv[0], (char*const*)argv); + _exit(-1); + default: + /* parent */ + break; + } - if (err == -1) { - fprintf(stderr, "%s: ERROR: fork failed before execution: `%s'\n", - __FUNCTION__, cmd); - return -1; - } + if (waitpid(pid, &status, 0) == -1) { + perror_msg("%s: %s: waitpid", __FUNCTION__, argv[0]); + return -1; + } - if (WIFSIGNALED(err)) { - fprintf(stderr, "%s: ERROR: Child process died due to signal %d: `%s'\n", - __FUNCTION__, WTERMSIG(err), cmd); - return -1; - } + if (WIFSIGNALED(status)) { + error_msg("%s: %s: Child killed by signal %d\n", + __FUNCTION__, argv[0], WTERMSIG(status)); + return -1; + } - if (WIFEXITED(err)) { - /* Normal child exit */ - return WEXITSTATUS(err); - } + if (!WIFEXITED(status)) { + /* shouldn't happen */ + error_msg("%s: %s: Your system is broken: got status %d " + "from waitpid\n", __FUNCTION__, argv[0], status); + return -1; + } - fprintf(stderr, "%s: ERROR: Received unintelligible return value from system: %d", - __FUNCTION__, err); - return -1; + return WEXITSTATUS(status); } - diff --git a/libopkg/xsystem.h b/libopkg/xsystem.h index cc1ca2a..3c7a3d2 100644 --- a/libopkg/xsystem.h +++ b/libopkg/xsystem.h @@ -28,7 +28,7 @@ Otherwise, the 8-bit return value of the program ala WEXITSTATUS as defined in . */ -int xsystem(const char *cmd); +int xsystem(const char *argv[]); #endif