Have ReExec read environment from /proc/self/environ
authorPeter Collingbourne <peter@pcc.me.uk>
Thu, 17 Jan 2013 19:50:42 +0000 (19:50 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Thu, 17 Jan 2013 19:50:42 +0000 (19:50 +0000)
It is possible for ReExec to be called before the C standard library
has initialised itself sufficiently for execv to work properly.
Fix this by parsing the environment ourselves and using execve.

Differential Revision: http://llvm-reviews.chandlerc.com/D304

llvm-svn: 172748

compiler-rt/lib/sanitizer_common/sanitizer_linux.cc

index 0ba80d4..8b9ba38 100644 (file)
@@ -201,24 +201,31 @@ const char *GetEnv(const char *name) {
   return 0;  // Not found.
 }
 
-void ReExec() {
-  static const int kMaxArgv = 100;
-  InternalScopedBuffer<char*> argv(kMaxArgv + 1);
-  static char *buff;
+static void ReadNullSepFileToArray(const char *path, char ***arr,
+                                   int arr_size) {
+  char *buff;
   uptr buff_size = 0;
-  ReadFileToBuffer("/proc/self/cmdline", &buff, &buff_size, 1024 * 1024);
-  argv[0] = buff;
-  int argc, i;
-  for (argc = 1, i = 1; ; i++) {
+  *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
+  ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024);
+  (*arr)[0] = buff;
+  int count, i;
+  for (count = 1, i = 1; ; i++) {
     if (buff[i] == 0) {
       if (buff[i+1] == 0) break;
-      argv[argc] = &buff[i+1];
-      CHECK_LE(argc, kMaxArgv);  // FIXME: make this more flexible.
-      argc++;
+      (*arr)[count] = &buff[i+1];
+      CHECK_LE(count, arr_size - 1);  // FIXME: make this more flexible.
+      count++;
     }
   }
-  argv[argc] = 0;
-  execv(argv[0], argv.data());
+  (*arr)[count] = 0;
+}
+
+void ReExec() {
+  static const int kMaxArgv = 100, kMaxEnvp = 1000;
+  char **argv, **envp;
+  ReadNullSepFileToArray("/proc/self/cmdline", &argv, kMaxArgv);
+  ReadNullSepFileToArray("/proc/self/environ", &envp, kMaxEnvp);
+  execve(argv[0], argv, envp);
 }
 
 void PrepareForSandboxing() {