| Index: sandbox/linux/suid/init_process.c
 | 
| diff --git a/sandbox/linux/suid/init_process.c b/sandbox/linux/suid/init_process.c
 | 
| deleted file mode 100644
 | 
| index e854202086448a32b4806cfedfac7eeb9733aff7..0000000000000000000000000000000000000000
 | 
| --- a/sandbox/linux/suid/init_process.c
 | 
| +++ /dev/null
 | 
| @@ -1,201 +0,0 @@
 | 
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 | 
| -// Use of this source code is governed by a BSD-style license that can be
 | 
| -// found in the LICENSE file.
 | 
| -
 | 
| -#define _GNU_SOURCE
 | 
| -#include "init_process.h"
 | 
| -
 | 
| -#include <dirent.h>
 | 
| -#include <fcntl.h>
 | 
| -#include <signal.h>
 | 
| -#include <stdbool.h>
 | 
| -#include <stdio.h>
 | 
| -#include <stdlib.h>
 | 
| -#include <string.h>
 | 
| -#include <sys/types.h>
 | 
| -#include <sys/wait.h>
 | 
| -#include <unistd.h>
 | 
| -
 | 
| -
 | 
| -static int getProcessStatus(int proc_fd, const char *process,
 | 
| -                            const char *field) {
 | 
| -  int ret = -1;
 | 
| -
 | 
| -  // Open "/proc/${process}/status"
 | 
| -  char *buf = malloc(strlen(process) + 80);
 | 
| -  sprintf(buf, "%s/status", process);
 | 
| -  int fd = openat(proc_fd, buf, O_RDONLY);
 | 
| -  if (fd >= 0) {
 | 
| -    // Only bother to read the first 4kB. All of the fields that we
 | 
| -    // are interested in will show up much earlier.
 | 
| -    buf = realloc(buf, 4097);
 | 
| -    size_t sz = read(fd, buf, 4096);
 | 
| -    if (sz > 0) {
 | 
| -      // Find a matching "field"
 | 
| -      buf[sz] = '\000';
 | 
| -      char *f = malloc(strlen(field) + 4);
 | 
| -      sprintf(f, "\n%s:\t", field);
 | 
| -      char *ptr = strstr(buf, f);
 | 
| -      if (ptr) {
 | 
| -        // Extract the numerical value of the "field"
 | 
| -        ret = atoi(ptr + strlen(f));
 | 
| -      }
 | 
| -      free(f);
 | 
| -    }
 | 
| -    close(fd);
 | 
| -  }
 | 
| -  free(buf);
 | 
| -  return ret;
 | 
| -}
 | 
| -
 | 
| -static bool hasChildren(int proc_fd, int pid) {
 | 
| -  bool ret = false;
 | 
| -
 | 
| -  // Open "/proc"
 | 
| -  int fd = dup(proc_fd);
 | 
| -  lseek(fd, SEEK_SET, 0);
 | 
| -  DIR *dir = fd >= 0 ? fdopendir(fd) : NULL;
 | 
| -  struct dirent de, *res;
 | 
| -  while (dir && !readdir_r(dir, &de, &res) && res) {
 | 
| -    // Find numerical entries. Those are processes.
 | 
| -    if (res->d_name[0] <= '0' || res->d_name[0] > '9') {
 | 
| -      continue;
 | 
| -    }
 | 
| -
 | 
| -    // For each process, check the parent's pid
 | 
| -    int ppid = getProcessStatus(proc_fd, res->d_name, "PPid");
 | 
| -
 | 
| -    if (ppid == pid) {
 | 
| -      // We found a child process. We can stop searching, now
 | 
| -      ret = true;
 | 
| -      break;
 | 
| -    }
 | 
| -  }
 | 
| -  closedir(dir);
 | 
| -  return ret;
 | 
| -}
 | 
| -
 | 
| -void SystemInitProcess(int init_fd, int child_pid, int proc_fd, int null_fd) {
 | 
| -  int ret = 0;
 | 
| -
 | 
| -  // CLONE_NEWPID doesn't adjust the contents of the "/proc" file system.
 | 
| -  // This is very confusing. And it is even possible the kernel developers
 | 
| -  // will consider this a bug and fix it at some point in the future.
 | 
| -  // So, to be on the safe side, we explicitly retrieve our process id
 | 
| -  // from the "/proc" file system. This should continue to work, even if
 | 
| -  // the kernel eventually gets fixed so that "/proc" shows the view from
 | 
| -  // inside of the new pid namespace.
 | 
| -  pid_t init_pid = getProcessStatus(proc_fd, "self", "Pid");
 | 
| -  if (init_pid <= 0) {
 | 
| -    fprintf(stderr,
 | 
| -            "Failed to determine real process id of new \"init\" process\n");
 | 
| -    _exit(1);
 | 
| -  }
 | 
| -
 | 
| -  // Redirect stdio to /dev/null
 | 
| -  if (null_fd < 0 ||
 | 
| -      dup2(null_fd, 0) != 0 ||
 | 
| -      dup2(null_fd, 1) != 1 ||
 | 
| -      dup2(null_fd, 2) != 2) {
 | 
| -    fprintf(stderr, "Failed to point stdio to a safe place\n");
 | 
| -    _exit(1);
 | 
| -  }
 | 
| -  close(null_fd);
 | 
| -
 | 
| -  // Close all file handles
 | 
| -  int fds_fd = openat(proc_fd, "self/fd", O_RDONLY | O_DIRECTORY);
 | 
| -  DIR *dir = fds_fd >= 0 ? fdopendir(fds_fd) : NULL;
 | 
| -  if (dir == NULL) {
 | 
| -    // If we don't know the list of our open file handles, just try closing
 | 
| -    // all valid ones.
 | 
| -    for (int fd = sysconf(_SC_OPEN_MAX); --fd > 2; ) {
 | 
| -      if (fd != init_fd && fd != proc_fd) {
 | 
| -        close(fd);
 | 
| -      }
 | 
| -    }
 | 
| -  } else {
 | 
| -    // If available, it is much more efficient to just close the file
 | 
| -    // handles that show up in "/proc/self/fd/"
 | 
| -    struct dirent de, *res;
 | 
| -    while (!readdir_r(dir, &de, &res) && res) {
 | 
| -      if (res->d_name[0] < '0')
 | 
| -        continue;
 | 
| -      int fd = atoi(res->d_name);
 | 
| -      if (fd > 2 && fd != init_fd && fd != proc_fd && fd != dirfd(dir)) {
 | 
| -        close(fd);
 | 
| -      }
 | 
| -    }
 | 
| -    closedir(dir);
 | 
| -  }
 | 
| -
 | 
| -  // Set up signal handler to catch SIGCHLD, but mask the signal for now
 | 
| -  sigset_t mask;
 | 
| -  sigemptyset(&mask);
 | 
| -  sigaddset(&mask, SIGCHLD);
 | 
| -  sigprocmask(SIG_BLOCK, &mask, NULL);
 | 
| -
 | 
| -  // Notify other processes that we are done initializing
 | 
| -  if (write(init_fd, " ", 1)) { }
 | 
| -  close(init_fd);
 | 
| -
 | 
| -  // Handle dying processes that have been re-parented to the "init" process
 | 
| -  for (;;) {
 | 
| -    bool retry = false;
 | 
| -    do {
 | 
| -      for (;;) {
 | 
| -        // Reap all exit codes of our child processes. This includes both
 | 
| -        // processes that originally were our immediate children, and processes
 | 
| -        // that have since been re-parented to be our children.
 | 
| -        int status;
 | 
| -        pid_t pid = waitpid(0, &status, __WALL | WNOHANG);
 | 
| -        if (pid <= 0) {
 | 
| -          break;
 | 
| -        } else {
 | 
| -          // We found some newly deceased child processes. Better schedule
 | 
| -          // another very thorough inspection of our state.
 | 
| -          retry = false;
 | 
| -        }
 | 
| -        if (pid == child_pid) {
 | 
| -          // If our first immediate child died, remember its exit code. That's
 | 
| -          // the exit code that we should be reporting to our parent process
 | 
| -          if (WIFEXITED(status)) {
 | 
| -            ret = WEXITSTATUS(status);
 | 
| -          } else if (WIFSIGNALED(status)) {
 | 
| -            ret = -WTERMSIG(status);
 | 
| -          }
 | 
| -        }
 | 
| -      }
 | 
| -      if (hasChildren(proc_fd, init_pid)) {
 | 
| -        // As long as we still have child processes, continue waiting for
 | 
| -        // their ultimate demise.
 | 
| -        retry = false;
 | 
| -      } else {
 | 
| -        if (retry) {
 | 
| -          // No more child processes. We can exit now.
 | 
| -          if (ret < 0) {
 | 
| -            // Try to exit with the same signal that our child terminated with
 | 
| -            signal(-ret, SIG_DFL);
 | 
| -            kill(1, -ret);
 | 
| -            ret = 1;
 | 
| -          }
 | 
| -          // Exit with the same exit code that our child exited with
 | 
| -          _exit(ret);
 | 
| -        } else {
 | 
| -          // There is a little bit of a race condition between getting
 | 
| -          // notifications and scanning the "/proc" file system. This is
 | 
| -          // particularly true, because scanning "/proc" cannot possibly be
 | 
| -          // an atomic operation.
 | 
| -          // If we find that we no longer appear to have any children, we check
 | 
| -          // one more time whether there are any children we can now reap.
 | 
| -          // They might have died while we were scanning "/proc" and if so,
 | 
| -          // they should now show up.
 | 
| -          retry = true;
 | 
| -        }
 | 
| -      }
 | 
| -    } while (retry);
 | 
| -
 | 
| -    // Wait until we receive a SIGCHLD signal. Our signal handler doesn't
 | 
| -    // actually need to do anything, though
 | 
| -    sigwaitinfo(&mask, NULL);
 | 
| -  }
 | 
| -}
 | 
| 
 |