Merge from Chromium at DEPS revision 269336

This commit was generated by merge_to_master.py.

Change-Id: I8b9c77f10eccd2a8b4c7ce373ffda18568af54ff
diff --git a/sandbox/linux/suid/client/DEPS b/sandbox/linux/suid/client/DEPS
new file mode 100644
index 0000000..99a337d
--- /dev/null
+++ b/sandbox/linux/suid/client/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+sandbox/linux/services",
+]
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.cc b/sandbox/linux/suid/client/setuid_sandbox_client.cc
index 3300cb4..fc03cdd 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_client.cc
+++ b/sandbox/linux/suid/client/setuid_sandbox_client.cc
@@ -5,6 +5,8 @@
 #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
 
 #include <fcntl.h>
+#include <stdlib.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -136,7 +138,7 @@
 
 SetuidSandboxClient* SetuidSandboxClient::Create() {
   base::Environment* environment(base::Environment::Create());
-  SetuidSandboxClient* sandbox_client(new(SetuidSandboxClient));
+  SetuidSandboxClient* sandbox_client(new SetuidSandboxClient);
 
   CHECK(environment);
   sandbox_client->env_ = environment;
@@ -152,6 +154,21 @@
   delete env_;
 }
 
+void SetuidSandboxClient::CloseDummyFile() {
+  // When we're launched through the setuid sandbox, SetupLaunchOptions
+  // arranges for kZygoteIdFd to be a dummy file descriptor to satisfy an
+  // ancient setuid sandbox ABI requirement. However, the descriptor is no
+  // longer needed, so we can simply close it right away now.
+  CHECK(IsSuidSandboxChild());
+
+  // Sanity check that kZygoteIdFd refers to a pipe.
+  struct stat st;
+  PCHECK(0 == fstat(kZygoteIdFd, &st));
+  CHECK(S_ISFIFO(st.st_mode));
+
+  PCHECK(0 == IGNORE_EINTR(close(kZygoteIdFd)));
+}
+
 bool SetuidSandboxClient::ChrootMe() {
   int ipc_fd = GetIPCDescriptor(env_);
 
@@ -226,12 +243,6 @@
   return false;
 }
 
-int SetuidSandboxClient::GetUniqueToChildFileDescriptor() {
-  // The setuid binary is hard-wired to close this in the helper process it
-  // creates.
-  return kZygoteIdFd;
-}
-
 base::FilePath SetuidSandboxClient::GetSandboxBinaryPath() {
   base::FilePath sandbox_binary;
   base::FilePath exe_dir;
@@ -256,8 +267,7 @@
   return sandbox_binary;
 }
 
-void SetuidSandboxClient::PrependWrapper(base::CommandLine* cmd_line,
-                                         base::LaunchOptions* options) {
+void SetuidSandboxClient::PrependWrapper(base::CommandLine* cmd_line) {
   std::string sandbox_binary(GetSandboxBinaryPath().value());
   struct stat st;
   if (sandbox_binary.empty() || stat(sandbox_binary.c_str(), &st) != 0) {
@@ -275,15 +285,30 @@
                << sandbox_binary << " is owned by root and has mode 4755.";
   }
 
-  if (cmd_line) {
-    cmd_line->PrependWrapper(sandbox_binary);
-  }
+  cmd_line->PrependWrapper(sandbox_binary);
+}
 
-  if (options) {
-    // Launching a setuid binary requires PR_SET_NO_NEW_PRIVS to not be used.
-    options->allow_new_privs = true;
-    UnsetExpectedEnvironmentVariables(&options->environ);
-  }
+void SetuidSandboxClient::SetupLaunchOptions(
+    base::LaunchOptions* options,
+    base::FileHandleMappingVector* fds_to_remap,
+    base::ScopedFD* dummy_fd) {
+  DCHECK(options);
+  DCHECK(fds_to_remap);
+
+  // Launching a setuid binary requires PR_SET_NO_NEW_PRIVS to not be used.
+  options->allow_new_privs = true;
+  UnsetExpectedEnvironmentVariables(&options->environ);
+
+  // Set dummy_fd to the reading end of a closed pipe.
+  int pipe_fds[2];
+  PCHECK(0 == pipe(pipe_fds));
+  PCHECK(0 == IGNORE_EINTR(close(pipe_fds[1])));
+  dummy_fd->reset(pipe_fds[0]);
+
+  // We no longer need a dummy socket for discovering the child's PID,
+  // but the sandbox is still hard-coded to expect a file descriptor at
+  // kZygoteIdFd. Fixing this requires a sandbox API change. :(
+  fds_to_remap->push_back(std::make_pair(dummy_fd->get(), kZygoteIdFd));
 }
 
 void SetuidSandboxClient::SetupLaunchEnvironment() {
diff --git a/sandbox/linux/suid/client/setuid_sandbox_client.h b/sandbox/linux/suid/client/setuid_sandbox_client.h
index 332c63b..2bbad7a 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_client.h
+++ b/sandbox/linux/suid/client/setuid_sandbox_client.h
@@ -8,14 +8,10 @@
 #include "base/basictypes.h"
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
+#include "base/files/scoped_file.h"
+#include "base/process/launch.h"
 #include "sandbox/linux/sandbox_export.h"
 
-namespace base {
-class CommandLine;
-class Environment;
-struct LaunchOptions;
-}
-
 namespace sandbox {
 
 // Helper class to use the setuid sandbox. This class is to be used both
@@ -28,23 +24,21 @@
 // 1. A calls SetupLaunchEnvironment()
 // 2. A sets up a CommandLine and then amends it with
 //    PrependWrapper() (or manually, by relying on GetSandboxBinaryPath()).
-// 3. A makes sure that GetUniqueToChildFileDescriptor() is an existing file
-//    descriptor that can be closed by the helper process created by the
-//    setuid sandbox. (This is the right file descriptor to use for magic
-//    "must-be-unique" sockets that are use to identify processes across
-//    pid namespaces.)
+// 3. A uses SetupLaunchOptions() to arrange for a dummy descriptor for the
+//    setuid sandbox ABI.
 // 4. A launches B with base::LaunchProcess, using the amended CommandLine.
-// 5. B performs various initializations that require access to the file
+// 5. B uses CloseDummyFile() to close the dummy file descriptor.
+// 6. B performs various initializations that require access to the file
 //    system.
-// 5.b (optional) B uses sandbox::Credentials::HasOpenDirectory() to verify
+// 6.b (optional) B uses sandbox::Credentials::HasOpenDirectory() to verify
 //    that no directory is kept open (which would allow bypassing the setuid
 //    sandbox).
-// 6. B should be prepared to assume the role of init(1). In particular, B
+// 7. B should be prepared to assume the role of init(1). In particular, B
 //    cannot receive any signal from any other process, excluding SIGKILL.
 //    If B dies, all the processes in the namespace will die.
 //    B can fork() and the parent can assume the role of init(1), by using
 //    CreateInitProcessReaper().
-// 7. B requests being chroot-ed through ChrootMe() and
+// 8. B requests being chroot-ed through ChrootMe() and
 //    requests other sandboxing status via the status functions.
 class SANDBOX_EXPORT SetuidSandboxClient {
  public:
@@ -52,6 +46,8 @@
   static class SetuidSandboxClient* Create();
   ~SetuidSandboxClient();
 
+  // Close the dummy file descriptor leftover from the sandbox ABI.
+  void CloseDummyFile();
   // Ask the setuid helper over the setuid sandbox IPC channel to chroot() us
   // to an empty directory.
   // Will only work if we have been launched through the setuid helper.
@@ -76,22 +72,21 @@
   // The setuid sandbox may still be disabled via the environment.
   // This is tracked in crbug.com/245376.
   bool IsDisabledViaEnvironment();
-  // When using the setuid sandbox, an extra helper process is created.
-  // Unfortunately, this helper process is hard-wired to close a specific file
-  // descriptor.
-  // The caller must make sure that GetUniqueToChildFileDescriptor() is an
-  // existing file descriptor that can be closed by the helper process. It's ok
-  // to make it a dummy, useless file descriptor if needed.
-  int GetUniqueToChildFileDescriptor();
   // Get the sandbox binary path. This method knows about the
   // CHROME_DEVEL_SANDBOX environment variable used for user-managed builds. If
   // the sandbox binary cannot be found, it will return an empty FilePath.
   base::FilePath GetSandboxBinaryPath();
-  // Modify |cmd_line| and |options| to launch via the setuid sandbox. Crash if
-  // the setuid sandbox binary cannot be found. Either can be NULL if the caller
-  // needs additional control.
-  void PrependWrapper(base::CommandLine* cmd_line,
-                      base::LaunchOptions* options);
+  // Modify |cmd_line| to launch via the setuid sandbox. Crash if the setuid
+  // sandbox binary cannot be found.  |cmd_line| must not be NULL.
+  void PrependWrapper(base::CommandLine* cmd_line);
+  // Set-up the launch options for launching via the setuid sandbox.  Caller is
+  // responsible for keeping |dummy_fd| alive until LaunchProcess() completes.
+  // |options| and |fds_to_remap| must not be NULL.
+  // (Keeping |dummy_fd| alive is an unfortunate historical artifact of the
+  // chrome-sandbox ABI.)
+  void SetupLaunchOptions(base::LaunchOptions* options,
+                          base::FileHandleMappingVector* fds_to_remap,
+                          base::ScopedFD* dummy_fd);
   // Set-up the environment. This should be done prior to launching the setuid
   // helper.
   void SetupLaunchEnvironment();
@@ -106,4 +101,3 @@
 }  // namespace sandbox
 
 #endif  // SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_
-