Bug 1253575 - Fallback to DuplicateHandle() when base::OpenPrivilegedProcessHandle() fails when starting a child process. r=krizsa
authorCervantes Yu <cyu@mozilla.com>
Thu, 23 Jun 2016 17:50:37 +0800
changeset 333700 b214bedbeab67525c7c4526318808d46d400e47e
parent 333699 fe5d0a5fa8fe7447abcd1e2e0dfd1cb478479682
child 333701 c77f60f1fef906a3f4f80eedae06588fec001259
push id10033
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:50:26 +0000
treeherdermozilla-aurora@5dddbefdf759 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskrizsa
bugs1253575
milestone51.0a1
Bug 1253575 - Fallback to DuplicateHandle() when base::OpenPrivilegedProcessHandle() fails when starting a child process. r=krizsa MozReview-Commit-ID: 2nglWFJgfja
ipc/chromium/src/base/process_util.h
ipc/chromium/src/base/process_util_posix.cc
ipc/chromium/src/base/process_util_win.cc
ipc/glue/GeckoChildProcessHost.cpp
ipc/glue/GeckoChildProcessHost.h
--- a/ipc/chromium/src/base/process_util.h
+++ b/ipc/chromium/src/base/process_util.h
@@ -109,23 +109,20 @@ ProcessId GetCurrentProcId();
 // Returns the ProcessHandle of the current process.
 ProcessHandle GetCurrentProcessHandle();
 
 // Converts a PID to a process handle. This handle must be closed by
 // CloseProcessHandle when you are done with it. Returns true on success.
 bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle);
 
 // Converts a PID to a process handle. On Windows the handle is opened
-// with more access rights and must only be used by trusted code. Parameter
-// error can be used to get the error code in opening the process handle.
+// with more access rights and must only be used by trusted code.
 // You have to close returned handle using CloseProcessHandle. Returns true
 // on success.
-bool OpenPrivilegedProcessHandle(ProcessId pid,
-                                 ProcessHandle* handle,
-                                 int64_t* error = nullptr);
+bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle);
 
 // Closes the process handle opened by OpenProcessHandle.
 void CloseProcessHandle(ProcessHandle process);
 
 // Returns the unique ID for the specified process. This is functionally the
 // same as Windows' GetProcessId(), but works on versions of Windows before
 // Win XP SP1 as well.
 ProcessId GetProcId(ProcessHandle process);
--- a/ipc/chromium/src/base/process_util_posix.cc
+++ b/ipc/chromium/src/base/process_util_posix.cc
@@ -44,24 +44,19 @@ ProcessHandle GetCurrentProcessHandle() 
 
 bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
   // On Posix platforms, process handles are the same as PIDs, so we
   // don't need to do anything.
   *handle = pid;
   return true;
 }
 
-bool OpenPrivilegedProcessHandle(ProcessId pid,
-                                 ProcessHandle* handle,
-                                 int64_t* error) {
+bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) {
   // On POSIX permissions are checked for each operation on process,
   // not when opening a "handle".
-  if (error) {
-    *error = 0;
-  }
   return OpenProcessHandle(pid, handle);
 }
 
 void CloseProcessHandle(ProcessHandle process) {
   // See OpenProcessHandle, nothing to do.
   return;
 }
 
--- a/ipc/chromium/src/base/process_util_win.cc
+++ b/ipc/chromium/src/base/process_util_win.cc
@@ -81,30 +81,25 @@ bool OpenProcessHandle(ProcessId pid, Pr
   if (result == NULL) {
     return false;
   }
 
   *handle = result;
   return true;
 }
 
-bool OpenPrivilegedProcessHandle(ProcessId pid,
-                                 ProcessHandle* handle,
-                                 int64_t* error) {
+bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) {
   ProcessHandle result = OpenProcess(PROCESS_DUP_HANDLE |
                                          PROCESS_TERMINATE |
                                          PROCESS_QUERY_INFORMATION |
                                          PROCESS_VM_READ |
                                          SYNCHRONIZE,
                                      FALSE, pid);
 
   if (result == NULL) {
-    if (error) {
-      *error = GetLastError();
-    }
     return false;
   }
 
   *handle = result;
   return true;
 }
 
 void CloseProcessHandle(ProcessHandle process) {
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -1146,53 +1146,57 @@ GeckoChildProcessHost::PerformAsyncLaunc
   }
   // NB: on OS X, we block much longer than we need to in order to
   // reach this call, waiting for the child process's task_t.  The
   // best way to fix that is to refactor this file, hard.
 #if defined(MOZ_WIDGET_COCOA)
   mChildTask = child_task;
 #endif
 
-  OpenPrivilegedHandle(base::GetProcId(process));
-  {
-    MonitorAutoLock lock(mMonitor);
-    mProcessState = PROCESS_CREATED;
-    lock.Notify();
+  if (!OpenPrivilegedHandle(base::GetProcId(process))
+#ifdef XP_WIN
+      // If we failed in opening the process handle, try harder by duplicating
+      // one.
+      && !::DuplicateHandle(::GetCurrentProcess(), process,
+                            ::GetCurrentProcess(), &mChildProcessHandle,
+                            PROCESS_DUP_HANDLE | PROCESS_TERMINATE |
+                            PROCESS_QUERY_INFORMATION | PROCESS_VM_READ |
+                            SYNCHRONIZE,
+                            FALSE, 0)
+#endif
+     ) {
+    NS_RUNTIMEABORT("cannot open handle to child process");
   }
+  MonitorAutoLock lock(mMonitor);
+  mProcessState = PROCESS_CREATED;
+  lock.Notify();
 
   return true;
 }
 
-void
+bool
 GeckoChildProcessHost::OpenPrivilegedHandle(base::ProcessId aPid)
 {
   if (mChildProcessHandle) {
     MOZ_ASSERT(aPid == base::GetProcId(mChildProcessHandle));
-    return;
+    return true;
   }
-  int64_t error = 0;
-  if (!base::OpenPrivilegedProcessHandle(aPid, &mChildProcessHandle, &error)) {
-#ifdef MOZ_CRASHREPORTER
-    CrashReporter::
-      AnnotateCrashReport(NS_LITERAL_CSTRING("LastError"),
-                          nsPrintfCString ("%lld", error));
-#endif
-    NS_RUNTIMEABORT("can't open handle to child process");
-  }
+
+  return base::OpenPrivilegedProcessHandle(aPid, &mChildProcessHandle);
 }
 
 void
 GeckoChildProcessHost::OnChannelConnected(int32_t peer_pid)
 {
-  OpenPrivilegedHandle(peer_pid);
-  {
-    MonitorAutoLock lock(mMonitor);
-    mProcessState = PROCESS_CONNECTED;
-    lock.Notify();
+  if (!OpenPrivilegedHandle(peer_pid)) {
+    NS_RUNTIMEABORT("can't open handle to child process");
   }
+  MonitorAutoLock lock(mMonitor);
+  mProcessState = PROCESS_CONNECTED;
+  lock.Notify();
 }
 
 void
 GeckoChildProcessHost::OnMessageReceived(IPC::Message&& aMsg)
 {
   // We never process messages ourself, just save them up for the next
   // listener.
   mQueue.push(Move(aMsg));
@@ -1249,17 +1253,19 @@ GeckoExistingProcessHost::~GeckoExisting
   // will happen.
   SetAlreadyDead();
 }
 
 bool
 GeckoExistingProcessHost::PerformAsyncLaunch(StringVector aExtraOpts,
                                              base::ProcessArchitecture aArch)
 {
-  OpenPrivilegedHandle(base::GetProcId(mExistingProcessHandle));
+  if (!OpenPrivilegedHandle(base::GetProcId(mExistingProcessHandle))) {
+    NS_RUNTIMEABORT("can't open handle to child process");
+  }
 
   MonitorAutoLock lock(mMonitor);
   mProcessState = PROCESS_CREATED;
   lock.Notify();
 
   return true;
 }
 
--- a/ipc/glue/GeckoChildProcessHost.h
+++ b/ipc/glue/GeckoChildProcessHost.h
@@ -168,17 +168,17 @@ protected:
   base::file_handle_mapping_vector mFileMap;
 #endif
 
   ProcessHandle mChildProcessHandle;
 #if defined(OS_MACOSX)
   task_t mChildTask;
 #endif
 
-  void OpenPrivilegedHandle(base::ProcessId aPid);
+  bool OpenPrivilegedHandle(base::ProcessId aPid);
 
 private:
   DISALLOW_EVIL_CONSTRUCTORS(GeckoChildProcessHost);
 
   // Does the actual work for AsyncLaunch, on the IO thread.
   bool PerformAsyncLaunchInternal(std::vector<std::string>& aExtraOpts,
                                   base::ProcessArchitecture arch);