about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-02-08 02:27:03 +0000
committerEric Wong <normalperson@yhbt.net>2013-02-08 02:33:02 +0000
commitbd37ad7bfae8c9b25a9eef1e1ce9b7c17d1f5257 (patch)
treed1e0fdc2d918cc49dd250cea603bdc1f336911d2
parent117a11e9e2b8a365df90336ae78b61f6562b7bd3 (diff)
downloadcmogstored-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.h1
-rw-r--r--m4/.gitignore3
-rw-r--r--m4/gnulib-cache.m43
-rw-r--r--upgrade.c31
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
diff --git a/upgrade.c b/upgrade.c
index 98de363..8d96060 100644
--- a/upgrade.c
+++ b/upgrade.c
@@ -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;