Bug 1253575 - Fallback to DuplicateHandle() when base::OpenPrivilegedProcessHandle() fails when starting a child process. r=krizsa
MozReview-Commit-ID: 2nglWFJgfja
--- 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);