diff options
author | Eric Wong <normalperson@yhbt.net> | 2013-02-08 02:27:03 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2013-02-08 02:33:02 +0000 |
commit | bd37ad7bfae8c9b25a9eef1e1ce9b7c17d1f5257 (patch) | |
tree | d1e0fdc2d918cc49dd250cea603bdc1f336911d2 | |
parent | 117a11e9e2b8a365df90336ae78b61f6562b7bd3 (diff) | |
download | cmogstored-bd37ad7bfae8c9b25a9eef1e1ce9b7c17d1f5257.tar.gz |
execvp may malloc internally in its path lookup, so use find_in_path to perform this lookup in the parent instead. Additionally, putenv() may not be async-signal-safe either, but execve is, so use execve.
-rw-r--r-- | cmogstored.h | 1 | ||||
-rw-r--r-- | m4/.gitignore | 3 | ||||
-rw-r--r-- | m4/gnulib-cache.m4 | 3 | ||||
-rw-r--r-- | upgrade.c | 31 |
4 files changed, 23 insertions, 15 deletions
diff --git a/cmogstored.h b/cmogstored.h index eafbae6..769825b 100644 --- a/cmogstored.h +++ b/cmogstored.h @@ -60,6 +60,7 @@ #include "minmax.h" #include "gc.h" #include "nproc.h" +#include "findprog.h" #include "gcc.h" #include "util.h" diff --git a/m4/.gitignore b/m4/.gitignore index e2e8b56..391f27d 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -172,3 +172,6 @@ /waitpid.m4 /nproc.m4 /extern-inline.m4 +/eaccess.m4 +/findprog.m4 +/stpcpy.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 9104353..1eeafec 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -27,7 +27,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --with-tests --avoid=accept --avoid=accept4 --avoid=alloca --avoid=fstatat --avoid=getcwd --avoid=ioctl --avoid=openat --avoid=read --avoid=sleep --avoid=write --no-conditional-dependencies --no-libtool --macro-prefix=gl argp base64 canonicalize crypto/gc-md5 crypto/gc-sha1 dprintf error git-version-gen hash mempcpy minmax mountlist nonblocking nproc pipe2 progname random_r verify warnings xvasprintf +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --with-tests --avoid=accept --avoid=accept4 --avoid=alloca --avoid=fstatat --avoid=getcwd --avoid=ioctl --avoid=openat --avoid=read --avoid=sleep --avoid=write --no-conditional-dependencies --no-libtool --macro-prefix=gl argp base64 canonicalize crypto/gc-md5 crypto/gc-sha1 dprintf error findprog git-version-gen hash mempcpy minmax mountlist nonblocking nproc pipe2 progname random_r verify warnings xvasprintf # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -39,6 +39,7 @@ gl_MODULES([ crypto/gc-sha1 dprintf error + findprog git-version-gen hash mempcpy @@ -10,6 +10,8 @@ static struct { char **envp; } start; +#define FD_PFX "CMOGSTORED_FD=" + MOG_NOINLINE static void free_list(char **head) { char **tmp = head; @@ -31,7 +33,7 @@ __attribute__((destructor)) static void upgrade_atexit(void) void mog_upgrade_prepare(int argc, char *argv[], char *envp[]) { int i; - size_t env_count = 1; /* extra for NULL-termination */ + size_t env_count = 2; /* extra for NULL-termination and CMOGSTORED_FD */ char **e; /* duplicate argv */ @@ -47,8 +49,11 @@ void mog_upgrade_prepare(int argc, char *argv[], char *envp[]) /* duplicate envp */ e = start.envp; - while (*envp) - *e++ = xstrdup(*envp++); + *e++ = NULL; /* save this slot for CMOGSTORED_FD */ + for (; *envp; envp++) { + if (strncmp(*envp, FD_PFX, strlen(FD_PFX))) + *e++ = xstrdup(*envp); + } *e = NULL; } @@ -89,6 +94,7 @@ pid_t mog_upgrade_spawn(void) size_t bytes; char *dst = NULL; int rc; + const char *execfile; if (!mog_pidfile_upgrade_prepare()) return pid; @@ -99,8 +105,9 @@ pid_t mog_upgrade_spawn(void) return pid; } + execfile = find_in_path(start.argv[0]); errno = 0; - rc = fputs("CMOGSTORED_FD=", fp); + rc = fputs(FD_PFX, fp); if (rc < 0 || rc == EOF) { if (errno == 0) errno = ferror(fp); @@ -121,18 +128,11 @@ pid_t mog_upgrade_spawn(void) pid = fork(); if (pid == 0) { - char **e = start.envp; - - while (*e) - CHECK(int, 0, putenv(*e++)); - - /* CMOGSTORED_FD= is set here */ - CHECK(int, 0, putenv(dst)); - + start.envp[0] = dst; mog_svc_upgrade_prepare(); mog_intr_enable(); - execvp(start.argv[0], start.argv); - die_errno("execvp %s", start.argv[0]); + execve(execfile, start.argv, start.envp); + die_errno("execve %s", execfile); } else if (pid > 0) { mog_process_register(pid, MOG_PROC_UPGRADE); syslog(LOG_INFO, "upgrade spawned PID:%d", pid); @@ -141,6 +141,9 @@ pid_t mog_upgrade_spawn(void) } out: + /* find_in_path does not malloc if output == input */ + if (execfile != start.argv[0]) + mog_free(execfile); free(dst); return pid; |