Make a small change to the API. Instead of passing in a file
descriptor to /proc/self/maps, we now pass in a file descriptor
to /proc/self and open "maps" ourselves. This is a more generic
API that will make it easier to add other features in the future
(e.g. merge the setuid sandbox into the seccomp sandbox, if the
kernel allow unprivileged calls to chroot).

BUG=none
TEST=make test
Review URL: https://chromiumcodereview.appspot.com/10178029

git-svn-id: http://seccompsandbox.googlecode.com/svn/trunk@180 55e79e8e-603c-11de-8c10-5fe6993ea61f
diff --git a/sandbox.cc b/sandbox.cc
index e952457..204c140 100644
--- a/sandbox.cc
+++ b/sandbox.cc
@@ -11,6 +11,7 @@
 namespace playground {
 
 // Global variables
+int                                 Sandbox::proc_self_ = -1;
 int                                 Sandbox::proc_self_maps_ = -1;
 enum Sandbox::SandboxStatus         Sandbox::status_ = STATUS_UNKNOWN;
 int                                 Sandbox::pid_;
@@ -193,7 +194,7 @@
   }
 }
 
-int Sandbox::supportsSeccompSandbox(int proc_fd) {
+int Sandbox::supportsSeccompSandbox(int proc_self) {
   if (status_ != STATUS_UNKNOWN) {
     return status_ != STATUS_UNSUPPORTED;
   }
@@ -216,8 +217,8 @@
         sys.dup2(devnull, 2);
         sys.close(devnull);
       }
-      if (proc_fd >= 0) {
-        setProcSelfMaps(sys.openat(proc_fd, "self/maps", O_RDONLY, 0));
+      if (proc_self >= 0) {
+        setProcSelf(sys.dup(proc_self));
       }
       startSandbox();
       write(sys, fds[1], "", 1);
@@ -250,8 +251,8 @@
   }
 }
 
-void Sandbox::setProcSelfMaps(int proc_self_maps) {
-  proc_self_maps_ = proc_self_maps;
+void Sandbox::setProcSelf(int proc_self) {
+  proc_self_ = proc_self;
 }
 
 void Sandbox::startSandbox() {
@@ -262,6 +263,13 @@
   }
 
   SysCalls sys;
+  if (proc_self_ >= 0) {
+    proc_self_maps_ = sys.openat(proc_self_, "maps", O_RDONLY, 0);
+    if (NOINTR_SYS(sys.close(proc_self_))) {
+      die("Failed to close proc_self_");
+    }
+    proc_self_ = -1;
+  }
   if (proc_self_maps_ < 0) {
     proc_self_maps_        = sys.open("/proc/self/maps", O_RDONLY, 0);
     if (proc_self_maps_ < 0) {
diff --git a/sandbox.h b/sandbox.h
index 8f49575..26ff782 100644
--- a/sandbox.h
+++ b/sandbox.h
@@ -5,8 +5,9 @@
 #ifndef SANDBOX_H__
 #define SANDBOX_H__
 
-extern "C" int  SupportsSeccompSandbox(int proc_fd);
-extern "C" void SeccompSandboxSetProcSelfMaps(int proc_self_maps);
+// See sandbox_impl.h for detailed comments on this API
+extern "C" int  SupportsSeccompSandbox(int proc_self);
+extern "C" void SeccompSandboxSetProcSelf(int proc_self);
 extern "C" void StartSeccompSandbox();
 
 #endif // SANDBOX_H__
diff --git a/sandbox_impl.h b/sandbox_impl.h
index 81b9bf8..5efa884 100644
--- a/sandbox_impl.h
+++ b/sandbox_impl.h
@@ -72,18 +72,19 @@
   // This could be because the kernel does not support Seccomp mode, or it
   // could be because we fail to successfully rewrite all system call entry
   // points.
-  // "proc_fd" should be a file descriptor for "/proc", or -1 if not provided
-  // by the caller.
-  static int supportsSeccompSandbox(int proc_fd)
+  // "proc_self" should be a file descriptor for "/proc/self", or -1 if not
+  // provided by the caller.
+  static int supportsSeccompSandbox(int proc_self)
                                          asm("SupportsSeccompSandbox");
 
   // The sandbox needs to be able to access "/proc/self/maps". If this file
   // is not accessible when "startSandbox()" gets called, the caller can
-  // provide an already opened file descriptor by calling "setProcSelfMaps()".
+  // provide an already opened file descriptor by calling "setProcSelf()".
   // The sandbox becomes the newer owner of this file descriptor and will
-  // eventually close it when "startSandbox()" executes.
-  static void setProcSelfMaps(int proc_self_maps)
-                                         asm("SeccompSandboxSetProcSelfMaps");
+  // eventually close it when "startSandbox()" executes. But if the caller
+  // never ends up calling startSandbox(), then the caller must close the
+  // file descriptor.
+  static void setProcSelf(int proc_self) asm("SeccompSandboxSetProcSelf");
 
   // This is the main public entry point. It finds all system calls that
   // need rewriting, sets up the resources needed by the sandbox, and
@@ -642,6 +643,7 @@
   // Seccomp mode.
   static void  createTrustedThread(SecureMem::Args* secureMem);
 
+  static int   proc_self_;
   static int   proc_self_maps_;
   static enum SandboxStatus {
     STATUS_UNKNOWN, STATUS_UNSUPPORTED, STATUS_AVAILABLE, STATUS_ENABLED