summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/process/launch.h10
-rw-r--r--base/process/launch_win.cc36
-rw-r--r--chrome/chrome.gyp2
-rw-r--r--chrome/service/service_utility_process_host.cc4
-rw-r--r--chrome/service/service_utility_process_host.h1
-rw-r--r--chrome/utility/OWNERS13
-rw-r--r--chrome/utility/chrome_content_utility_client.cc18
-rw-r--r--chrome/utility/chrome_content_utility_client.h5
-rw-r--r--chrome/utility/chrome_content_utility_ipc_whitelist.cc12
-rw-r--r--chrome/utility/chrome_content_utility_ipc_whitelist.h21
-rw-r--r--components/nacl/browser/nacl_broker_host_win.cc4
-rw-r--r--components/nacl/browser/nacl_process_host.cc1
-rw-r--r--content/browser/browser_child_process_host_impl.cc7
-rw-r--r--content/browser/browser_child_process_host_impl.h19
-rw-r--r--content/browser/child_process_launcher.cc22
-rw-r--r--content/browser/child_process_launcher.h3
-rw-r--r--content/browser/gpu/gpu_process_host.cc1
-rw-r--r--content/browser/plugin_process_host.cc1
-rw-r--r--content/browser/ppapi_plugin_process_host.cc1
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc1
-rw-r--r--content/browser/utility_process_host_impl.cc24
-rw-r--r--content/browser/utility_process_host_impl.h9
-rw-r--r--content/browser/worker_host/worker_process_host.cc1
-rw-r--r--content/common/child_process_host_impl.cc4
-rw-r--r--content/public/browser/browser_child_process_host.h1
-rw-r--r--content/public/browser/browser_child_process_host_delegate.h4
-rw-r--r--content/public/browser/utility_process_host.h5
-rw-r--r--content/public/browser/utility_process_host_client.h3
-rw-r--r--content/public/common/child_process_host_delegate.h5
-rw-r--r--content/public/common/content_switches.cc2
-rw-r--r--content/public/common/content_switches.h1
31 files changed, 224 insertions, 17 deletions
diff --git a/base/process/launch.h b/base/process/launch.h
index e11d1c0..c25a9be 100644
--- a/base/process/launch.h
+++ b/base/process/launch.h
@@ -159,6 +159,16 @@ BASE_EXPORT bool LaunchProcess(const string16& cmdline,
const LaunchOptions& options,
win::ScopedHandle* process_handle);
+// Launches a process with elevated privileges. This does not behave exactly
+// like LaunchProcess as it uses ShellExecuteEx instead of CreateProcess to
+// create the process. This means the process will have elevated privileges
+// and thus some common operations like OpenProcess will fail. The process will
+// be available through the |process_handle| argument. Currently the only
+// supported LaunchOptions are |start_hidden| and |wait|.
+BASE_EXPORT bool LaunchElevatedProcess(const CommandLine& cmdline,
+ const LaunchOptions& options,
+ ProcessHandle* process_handle);
+
#elif defined(OS_POSIX)
// A POSIX-specific version of LaunchProcess that takes an argv array
// instead of a CommandLine. Useful for situations where you need to
diff --git a/base/process/launch_win.cc b/base/process/launch_win.cc
index 0c831cf..de05255 100644
--- a/base/process/launch_win.cc
+++ b/base/process/launch_win.cc
@@ -6,6 +6,7 @@
#include <fcntl.h>
#include <io.h>
+#include <shellapi.h>
#include <windows.h>
#include <userenv.h>
#include <psapi.h>
@@ -239,6 +240,41 @@ bool LaunchProcess(const CommandLine& cmdline,
return rv;
}
+bool LaunchElevatedProcess(const CommandLine& cmdline,
+ const LaunchOptions& options,
+ ProcessHandle* process_handle) {
+ const string16 file = cmdline.GetProgram().value();
+ const string16 arguments = cmdline.GetArgumentsString();
+
+ SHELLEXECUTEINFO shex_info = {0};
+ shex_info.cbSize = sizeof(shex_info);
+ shex_info.fMask = SEE_MASK_NOCLOSEPROCESS;
+ shex_info.hwnd = GetActiveWindow();
+ shex_info.lpVerb = L"runas";
+ shex_info.lpFile = file.c_str();
+ shex_info.lpParameters = arguments.c_str();
+ shex_info.lpDirectory = NULL;
+ shex_info.nShow = options.start_hidden ? SW_HIDE : SW_SHOW;
+ shex_info.hInstApp = NULL;
+
+ if (!ShellExecuteEx(&shex_info)) {
+ DPLOG(ERROR);
+ return false;
+ }
+
+ if (options.wait)
+ WaitForSingleObject(shex_info.hProcess, INFINITE);
+
+ // If the caller wants the process handle give it to them, otherwise just
+ // close it. Closing it does not terminate the process.
+ if (process_handle)
+ *process_handle = shex_info.hProcess;
+ else
+ CloseHandle(shex_info.hProcess);
+
+ return true;
+}
+
bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags) {
JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {0};
limit_info.BasicLimitInformation.LimitFlags = limit_flags;
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index ed0692d..b3ea39d 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -257,6 +257,8 @@
'sources': [
'utility/chrome_content_utility_client.cc',
'utility/chrome_content_utility_client.h',
+ 'utility/chrome_content_utility_ipc_whitelist.cc',
+ 'utility/chrome_content_utility_ipc_whitelist.h',
'utility/cloud_print/bitmap_image.cc',
'utility/cloud_print/bitmap_image.h',
'utility/cloud_print/pwg_encoder.cc',
diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc
index 3e8ee3d..3054adc 100644
--- a/chrome/service/service_utility_process_host.cc
+++ b/chrome/service/service_utility_process_host.cc
@@ -268,6 +268,10 @@ bool ServiceUtilityProcessHost::OnMessageReceived(const IPC::Message& message) {
return handled;
}
+base::ProcessHandle ServiceUtilityProcessHost::GetHandle() const {
+ return handle_;
+}
+
void ServiceUtilityProcessHost::OnRenderPDFPagesToMetafileSucceeded(
int highest_rendered_page_number,
double scale_factor) {
diff --git a/chrome/service/service_utility_process_host.h b/chrome/service/service_utility_process_host.h
index ab27d20..fd1fad9 100644
--- a/chrome/service/service_utility_process_host.h
+++ b/chrome/service/service_utility_process_host.h
@@ -121,6 +121,7 @@ class ServiceUtilityProcessHost : public content::ChildProcessHostDelegate {
// ChildProcessHostDelegate implementation:
virtual void OnChildDisconnected() OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual base::ProcessHandle GetHandle() const OVERRIDE;
private:
// Starts a process. Returns true iff it succeeded. |exposed_dir| is the
diff --git a/chrome/utility/OWNERS b/chrome/utility/OWNERS
new file mode 100644
index 0000000..fbfb968
--- /dev/null
+++ b/chrome/utility/OWNERS
@@ -0,0 +1,13 @@
+# For security review of utility process message whitelisting
+per-file chrome_content_utility_ipc_whitelist.cc=set noparent
+per-file chrome_content_utility_ipc_whitelist.cc=cdn@chromium.org
+per-file chrome_content_utility_ipc_whitelist.cc=cevans@chromium.org
+per-file chrome_content_utility_ipc_whitelist.cc=dcheng@chromium.org
+per-file chrome_content_utility_ipc_whitelist.cc=inferno@chromium.org
+per-file chrome_content_utility_ipc_whitelist.cc=jln@chromium.org
+per-file chrome_content_utility_ipc_whitelist.cc=jorgelo@chromium.org
+per-file chrome_content_utility_ipc_whitelist.cc=jschuh@chromium.org
+per-file chrome_content_utility_ipc_whitelist.cc=kenrb@chromium.org
+per-file chrome_content_utility_ipc_whitelist.cc=nasko@chromium.org
+per-file chrome_content_utility_ipc_whitelist.cc=palmer@chromium.org
+per-file chrome_content_utility_ipc_whitelist.cc=tsepez@chromium.org
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index e5a689c..c66abcf 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -20,6 +20,7 @@
#include "chrome/common/extensions/extension_l10n_util.h"
#include "chrome/common/extensions/update_manifest.h"
#include "chrome/common/safe_browsing/zip_analyzer.h"
+#include "chrome/utility/chrome_content_utility_ipc_whitelist.h"
#include "chrome/utility/cloud_print/bitmap_image.h"
#include "chrome/utility/cloud_print/pwg_encoder.h"
#include "chrome/utility/extensions/unpacker.h"
@@ -27,6 +28,7 @@
#include "chrome/utility/web_resource_unpacker.h"
#include "content/public/child/image_decoder_utils.h"
#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
#include "content/public/utility/utility_thread.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
@@ -72,7 +74,6 @@
#if defined(ENABLE_MDNS)
#include "chrome/utility/local_discovery/service_discovery_message_handler.h"
-#include "content/public/common/content_switches.h"
#endif // ENABLE_MDNS
namespace chrome {
@@ -305,7 +306,8 @@ static base::LazyInstance<PdfFunctions> g_pdf_lib = LAZY_INSTANCE_INITIALIZER;
} // namespace
-ChromeContentUtilityClient::ChromeContentUtilityClient() {
+ChromeContentUtilityClient::ChromeContentUtilityClient()
+ : filter_messages_(false) {
#if !defined(OS_ANDROID)
handlers_.push_back(new ProfileImportHandler());
#endif // OS_ANDROID
@@ -326,10 +328,22 @@ void ChromeContentUtilityClient::UtilityThreadStarted() {
std::string lang = command_line->GetSwitchValueASCII(switches::kLang);
if (!lang.empty())
extension_l10n_util::SetProcessLocale(lang);
+
+ if (command_line->HasSwitch(switches::kUtilityProcessRunningElevated)) {
+ message_id_whitelist_.insert(kMessageWhitelist,
+ kMessageWhitelist + kMessageWhitelistSize);
+ filter_messages_ = true;
+ }
}
bool ChromeContentUtilityClient::OnMessageReceived(
const IPC::Message& message) {
+ if (filter_messages_ &&
+ (message_id_whitelist_.find(message.type()) ==
+ message_id_whitelist_.end())) {
+ return false;
+ }
+
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ChromeContentUtilityClient, message)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_UnpackExtension, OnUnpackExtension)
diff --git a/chrome/utility/chrome_content_utility_client.h b/chrome/utility/chrome_content_utility_client.h
index 8b914f8..fcc5da9 100644
--- a/chrome/utility/chrome_content_utility_client.h
+++ b/chrome/utility/chrome_content_utility_client.h
@@ -129,6 +129,11 @@ class ChromeContentUtilityClient : public content::ContentUtilityClient {
scoped_ptr<metadata::MediaMetadataParser> media_metadata_parser_;
#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
+ // Flag to enable whitelisting.
+ bool filter_messages_;
+ // A list of message_ids to filter.
+ std::set<int> message_id_whitelist_;
+
DISALLOW_COPY_AND_ASSIGN(ChromeContentUtilityClient);
};
diff --git a/chrome/utility/chrome_content_utility_ipc_whitelist.cc b/chrome/utility/chrome_content_utility_ipc_whitelist.cc
new file mode 100644
index 0000000..5715a9cc
--- /dev/null
+++ b/chrome/utility/chrome_content_utility_ipc_whitelist.cc
@@ -0,0 +1,12 @@
+// Copyright 2014 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.
+
+#include "chrome/utility/chrome_content_utility_ipc_whitelist.h"
+
+namespace chrome {
+
+const uint32 kMessageWhitelist[] = {0};
+const size_t kMessageWhitelistSize = arraysize(kMessageWhitelist);
+
+} // namespace chrome
diff --git a/chrome/utility/chrome_content_utility_ipc_whitelist.h b/chrome/utility/chrome_content_utility_ipc_whitelist.h
new file mode 100644
index 0000000..fcbd36c
--- /dev/null
+++ b/chrome/utility/chrome_content_utility_ipc_whitelist.h
@@ -0,0 +1,21 @@
+// Copyright 2014 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.
+
+#ifndef CHROME_UTILITY_CHROME_CONTENT_UTILITY_IPC_WHITELIST_H_
+#define CHROME_UTILITY_CHROME_CONTENT_UTILITY_IPC_WHITELIST_H_
+
+#include "base/basictypes.h"
+
+namespace chrome {
+
+// This array contains the list of IPC messages that the utility process will
+// accept when running with elevated privileges. When new messages need to run
+// with elevated privileges, add them here and be sure to add a security
+// reviewer.
+extern const uint32 kMessageWhitelist[];
+extern const size_t kMessageWhitelistSize;
+
+} // namespace chrome
+
+#endif // CHROME_UTILITY_CHROME_CONTENT_UTILITY_IPC_WHITELIST_H_
diff --git a/components/nacl/browser/nacl_broker_host_win.cc b/components/nacl/browser/nacl_broker_host_win.cc
index 878ca6e..ca54e67 100644
--- a/components/nacl/browser/nacl_broker_host_win.cc
+++ b/components/nacl/browser/nacl_broker_host_win.cc
@@ -67,7 +67,9 @@ bool NaClBrokerHost::Init() {
if (NaClBrowser::GetDelegate()->DialogsAreSuppressed())
cmd_line->AppendSwitch(switches::kNoErrorDialogs);
- process_->Launch(new NaClBrokerSandboxedProcessLauncherDelegate, cmd_line);
+ process_->Launch(new NaClBrokerSandboxedProcessLauncherDelegate,
+ false,
+ cmd_line);
return true;
}
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc
index cb430eb..a5a1341 100644
--- a/components/nacl/browser/nacl_process_host.cc
+++ b/components/nacl/browser/nacl_process_host.cc
@@ -537,6 +537,7 @@ bool NaClProcessHost::LaunchSelLdr() {
}
} else {
process_->Launch(new NaClSandboxedProcessLauncherDelegate,
+ false,
cmd_line.release());
}
#elif defined(OS_POSIX)
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
index fd1b286..c69e5db 100644
--- a/content/browser/browser_child_process_host_impl.cc
+++ b/content/browser/browser_child_process_host_impl.cc
@@ -131,6 +131,7 @@ void BrowserChildProcessHostImpl::TerminateAll() {
void BrowserChildProcessHostImpl::Launch(
#if defined(OS_WIN)
SandboxedProcessLauncherDelegate* delegate,
+ bool launch_elevated,
#elif defined(OS_POSIX)
bool use_zygote,
const base::EnvironmentMap& environ,
@@ -163,6 +164,7 @@ void BrowserChildProcessHostImpl::Launch(
child_process_.reset(new ChildProcessLauncher(
#if defined(OS_WIN)
delegate,
+ launch_elevated,
#elif defined(OS_POSIX)
use_zygote,
environ,
@@ -318,6 +320,11 @@ bool BrowserChildProcessHostImpl::Send(IPC::Message* message) {
return child_process_host_->Send(message);
}
+void BrowserChildProcessHostImpl::OnProcessLaunchFailed() {
+ delegate_->OnProcessLaunchFailed();
+ delete delegate_; // Will delete us
+}
+
void BrowserChildProcessHostImpl::OnProcessLaunched() {
base::ProcessHandle handle = child_process_->GetHandle();
if (!handle) {
diff --git a/content/browser/browser_child_process_host_impl.h b/content/browser/browser_child_process_host_impl.h
index 67ce9e2..3bcab7c 100644
--- a/content/browser/browser_child_process_host_impl.h
+++ b/content/browser/browser_child_process_host_impl.h
@@ -45,6 +45,7 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
virtual void Launch(
#if defined(OS_WIN)
SandboxedProcessLauncherDelegate* delegate,
+ bool launch_elevated,
#elif defined(OS_POSIX)
bool use_zygote,
const base::EnvironmentMap& environ,
@@ -58,9 +59,13 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
virtual void SetName(const base::string16& name) OVERRIDE;
virtual void SetHandle(base::ProcessHandle handle) OVERRIDE;
- // Returns the handle of the child process. This can be called only after
- // OnProcessLaunched is called or it will be invalid and may crash.
- base::ProcessHandle GetHandle() const;
+ // ChildProcessHostDelegate implementation:
+ virtual bool CanShutdown() OVERRIDE;
+ virtual void OnChildDisconnected() OVERRIDE;
+ virtual base::ProcessHandle GetHandle() const OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
+ virtual void OnChannelError() OVERRIDE;
// Removes this host from the host list. Calls ChildProcessHost::ForceShutdown
void ForceShutdown();
@@ -90,15 +95,9 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
static void AddObserver(BrowserChildProcessObserver* observer);
static void RemoveObserver(BrowserChildProcessObserver* observer);
- // ChildProcessHostDelegate implementation:
- virtual bool CanShutdown() OVERRIDE;
- virtual void OnChildDisconnected() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
-
// ChildProcessLauncher::Client implementation.
virtual void OnProcessLaunched() OVERRIDE;
+ virtual void OnProcessLaunchFailed() OVERRIDE;
#if defined(OS_WIN)
void DeleteProcessWaitableEvent(base::WaitableEvent* event);
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc
index 3a16211..7dfad56 100644
--- a/content/browser/child_process_launcher.cc
+++ b/content/browser/child_process_launcher.cc
@@ -73,6 +73,7 @@ class ChildProcessLauncher::Context
void Launch(
#if defined(OS_WIN)
SandboxedProcessLauncherDelegate* delegate,
+ bool launch_elevated,
#elif defined(OS_ANDROID)
int ipcfd,
#elif defined(OS_POSIX)
@@ -102,6 +103,7 @@ class ChildProcessLauncher::Context
child_process_id,
#if defined(OS_WIN)
delegate,
+ launch_elevated,
#elif defined(OS_ANDROID)
ipcfd,
#elif defined(OS_POSIX)
@@ -185,6 +187,7 @@ class ChildProcessLauncher::Context
int child_process_id,
#if defined(OS_WIN)
SandboxedProcessLauncherDelegate* delegate,
+ bool launch_elevated,
#elif defined(OS_ANDROID)
int ipcfd,
#elif defined(OS_POSIX)
@@ -197,8 +200,15 @@ class ChildProcessLauncher::Context
base::TimeTicks begin_launch_time = base::TimeTicks::Now();
#if defined(OS_WIN)
- scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
- base::ProcessHandle handle = StartSandboxedProcess(delegate, cmd_line);
+ base::ProcessHandle handle = base::kNullProcessHandle;
+ if (launch_elevated) {
+ base::LaunchOptions options;
+ options.start_hidden = true;
+ base::LaunchElevatedProcess(*cmd_line, options, &handle);
+ } else {
+ scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
+ handle = StartSandboxedProcess(delegate, cmd_line);
+ }
#elif defined(OS_POSIX)
std::string process_type =
cmd_line->GetSwitchValueASCII(switches::kProcessType);
@@ -335,7 +345,11 @@ class ChildProcessLauncher::Context
zygote_ = zygote;
#endif
if (client_) {
- client_->OnProcessLaunched();
+ if (handle) {
+ client_->OnProcessLaunched();
+ } else {
+ client_->OnProcessLaunchFailed();
+ }
} else {
Terminate();
}
@@ -418,6 +432,7 @@ class ChildProcessLauncher::Context
ChildProcessLauncher::ChildProcessLauncher(
#if defined(OS_WIN)
SandboxedProcessLauncherDelegate* delegate,
+ bool launch_elevated,
#elif defined(OS_POSIX)
bool use_zygote,
const base::EnvironmentMap& environ,
@@ -430,6 +445,7 @@ ChildProcessLauncher::ChildProcessLauncher(
context_->Launch(
#if defined(OS_WIN)
delegate,
+ launch_elevated,
#elif defined(OS_ANDROID)
ipcfd,
#elif defined(OS_POSIX)
diff --git a/content/browser/child_process_launcher.h b/content/browser/child_process_launcher.h
index 7ce7805..965a914 100644
--- a/content/browser/child_process_launcher.h
+++ b/content/browser/child_process_launcher.h
@@ -27,6 +27,8 @@ class CONTENT_EXPORT ChildProcessLauncher {
// constructed on.
virtual void OnProcessLaunched() = 0;
+ virtual void OnProcessLaunchFailed() {};
+
protected:
virtual ~Client() {}
};
@@ -39,6 +41,7 @@ class CONTENT_EXPORT ChildProcessLauncher {
ChildProcessLauncher(
#if defined(OS_WIN)
SandboxedProcessLauncherDelegate* delegate,
+ bool launch_elevated,
#elif defined(OS_POSIX)
bool use_zygote,
const base::EnvironmentMap& environ,
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index eb0b254..41007d4 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -1144,6 +1144,7 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
process_->Launch(
#if defined(OS_WIN)
new GpuSandboxedProcessLauncherDelegate(cmd_line),
+ false,
#elif defined(OS_POSIX)
false,
base::EnvironmentMap(),
diff --git a/content/browser/plugin_process_host.cc b/content/browser/plugin_process_host.cc
index 068858b..e329dcc 100644
--- a/content/browser/plugin_process_host.cc
+++ b/content/browser/plugin_process_host.cc
@@ -245,6 +245,7 @@ bool PluginProcessHost::Init(const WebPluginInfo& info) {
process_->Launch(
#if defined(OS_WIN)
new PluginSandboxedProcessLauncherDelegate,
+ false,
#elif defined(OS_POSIX)
false,
env,
diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc
index 953f84c..f1a3171 100644
--- a/content/browser/ppapi_plugin_process_host.cc
+++ b/content/browser/ppapi_plugin_process_host.cc
@@ -340,6 +340,7 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
process_->Launch(
#if defined(OS_WIN)
new PpapiPluginSandboxedProcessLauncherDelegate(is_broker_),
+ false,
#elif defined(OS_POSIX)
use_zygote,
base::EnvironmentMap(),
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 03ce20c..f6b4832 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -567,6 +567,7 @@ bool RenderProcessHostImpl::Init() {
child_process_launcher_.reset(new ChildProcessLauncher(
#if defined(OS_WIN)
new RendererSandboxedProcessLauncherDelegate,
+ false,
#elif defined(OS_POSIX)
renderer_prefix.empty(),
base::EnvironmentMap(),
diff --git a/content/browser/utility_process_host_impl.cc b/content/browser/utility_process_host_impl.cc
index e2f45245..013c62a 100644
--- a/content/browser/utility_process_host_impl.cc
+++ b/content/browser/utility_process_host_impl.cc
@@ -73,6 +73,9 @@ UtilityProcessHostImpl::UtilityProcessHostImpl(
is_batch_mode_(false),
is_mdns_enabled_(false),
no_sandbox_(false),
+#if defined(OS_WIN)
+ run_elevated_(false),
+#endif
#if defined(OS_LINUX)
child_flags_(ChildProcessHost::CHILD_ALLOW_SELF),
#else
@@ -119,6 +122,13 @@ void UtilityProcessHostImpl::DisableSandbox() {
no_sandbox_ = true;
}
+#if defined(OS_WIN)
+void UtilityProcessHostImpl::ElevatePrivileges() {
+ no_sandbox_ = true;
+ run_elevated_ = true;
+}
+#endif
+
const ChildProcessData& UtilityProcessHostImpl::GetData() {
return process_->GetData();
}
@@ -210,6 +220,12 @@ bool UtilityProcessHostImpl::StartProcess() {
if (is_mdns_enabled_)
cmd_line->AppendSwitch(switches::kUtilityProcessEnableMDns);
+#if defined(OS_WIN)
+ // Let the utility process know if it is intended to be elevated.
+ if (run_elevated_)
+ cmd_line->AppendSwitch(switches::kUtilityProcessRunningElevated);
+#endif
+
bool use_zygote = false;
#if defined(OS_LINUX)
@@ -221,6 +237,7 @@ bool UtilityProcessHostImpl::StartProcess() {
process_->Launch(
#if defined(OS_WIN)
new UtilitySandboxedProcessLauncherDelegate(exposed_dir_),
+ run_elevated_,
#elif defined(OS_POSIX)
use_zygote,
env_,
@@ -240,6 +257,13 @@ bool UtilityProcessHostImpl::OnMessageReceived(const IPC::Message& message) {
return true;
}
+void UtilityProcessHostImpl::OnProcessLaunchFailed() {
+ client_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&UtilityProcessHostClient::OnProcessLaunchFailed,
+ client_.get()));
+}
+
void UtilityProcessHostImpl::OnProcessCrashed(int exit_code) {
client_task_runner_->PostTask(
FROM_HERE,
diff --git a/content/browser/utility_process_host_impl.h b/content/browser/utility_process_host_impl.h
index 3083b22..dd663dd 100644
--- a/content/browser/utility_process_host_impl.h
+++ b/content/browser/utility_process_host_impl.h
@@ -40,6 +40,9 @@ class CONTENT_EXPORT UtilityProcessHostImpl
virtual void SetExposedDir(const base::FilePath& dir) OVERRIDE;
virtual void EnableMDns() OVERRIDE;
virtual void DisableSandbox() OVERRIDE;
+#if defined(OS_WIN)
+ virtual void ElevatePrivileges() OVERRIDE;
+#endif
virtual const ChildProcessData& GetData() OVERRIDE;
#if defined(OS_POSIX)
virtual void SetEnv(const base::EnvironmentMap& env) OVERRIDE;
@@ -54,6 +57,7 @@ class CONTENT_EXPORT UtilityProcessHostImpl
// BrowserChildProcessHost:
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void OnProcessLaunchFailed() OVERRIDE;
virtual void OnProcessCrashed(int exit_code) OVERRIDE;
// A pointer to our client interface, who will be informed of progress.
@@ -72,6 +76,11 @@ class CONTENT_EXPORT UtilityProcessHostImpl
// Whether to pass switches::kNoSandbox to the child.
bool no_sandbox_;
+#if defined(OS_WIN)
+ // Whether to launch the process with elevated privileges.
+ bool run_elevated_;
+#endif
+
// Flags defined in ChildProcessHost with which to start the process.
int child_flags_;
diff --git a/content/browser/worker_host/worker_process_host.cc b/content/browser/worker_host/worker_process_host.cc
index be50d51..91b7938 100644
--- a/content/browser/worker_host/worker_process_host.cc
+++ b/content/browser/worker_host/worker_process_host.cc
@@ -223,6 +223,7 @@ bool WorkerProcessHost::Init(int render_process_id, int render_frame_id) {
process_->Launch(
#if defined(OS_WIN)
new WorkerSandboxedProcessLauncherDelegate,
+ false,
#elif defined(OS_POSIX)
use_zygote,
base::EnvironmentMap(),
diff --git a/content/common/child_process_host_impl.cc b/content/common/child_process_host_impl.cc
index 4e7b862..efdd925 100644
--- a/content/common/child_process_host_impl.cc
+++ b/content/common/child_process_host_impl.cc
@@ -270,7 +270,9 @@ bool ChildProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
}
void ChildProcessHostImpl::OnChannelConnected(int32 peer_pid) {
- if (!base::OpenPrivilegedProcessHandle(peer_pid, &peer_handle_)) {
+ if (!peer_handle_ &&
+ !base::OpenPrivilegedProcessHandle(peer_pid, &peer_handle_) &&
+ !(peer_handle_ = delegate_->GetHandle())) {
NOTREACHED();
}
opening_channel_ = false;
diff --git a/content/public/browser/browser_child_process_host.h b/content/public/browser/browser_child_process_host.h
index 182dd8d..690a015 100644
--- a/content/public/browser/browser_child_process_host.h
+++ b/content/public/browser/browser_child_process_host.h
@@ -46,6 +46,7 @@ class CONTENT_EXPORT BrowserChildProcessHost : public IPC::Sender {
virtual void Launch(
#if defined(OS_WIN)
SandboxedProcessLauncherDelegate* delegate,
+ bool run_elevated,
#elif defined(OS_POSIX)
bool use_zygote,
const base::EnvironmentMap& environ,
diff --git a/content/public/browser/browser_child_process_host_delegate.h b/content/public/browser/browser_child_process_host_delegate.h
index 2efbeab..25ff00a 100644
--- a/content/public/browser/browser_child_process_host_delegate.h
+++ b/content/public/browser/browser_child_process_host_delegate.h
@@ -24,6 +24,10 @@ class CONTENT_EXPORT BrowserChildProcessHostDelegate : public IPC::Listener {
// Called when the process has been started.
virtual void OnProcessLaunched() {}
+ // Called if the process failed to launch. In this case the process never
+ // started so there is no available exit code.
+ virtual void OnProcessLaunchFailed() {}
+
// Called if the process crashed. |exit_code| is the status returned when the
// process crashed (for posix, as returned from waitpid(), for Windows, as
// returned from GetExitCodeProcess()).
diff --git a/content/public/browser/utility_process_host.h b/content/public/browser/utility_process_host.h
index 1f027a8..c39c76e 100644
--- a/content/public/browser/utility_process_host.h
+++ b/content/public/browser/utility_process_host.h
@@ -61,6 +61,11 @@ class UtilityProcessHost : public IPC::Sender,
// Make the process run without a sandbox.
virtual void DisableSandbox() = 0;
+#if defined(OS_WIN)
+ // Make the process run elevated.
+ virtual void ElevatePrivileges() = 0;
+#endif
+
// Returns information about the utility child process.
virtual const ChildProcessData& GetData() = 0;
diff --git a/content/public/browser/utility_process_host_client.h b/content/public/browser/utility_process_host_client.h
index 73d707b..bd7e89d 100644
--- a/content/public/browser/utility_process_host_client.h
+++ b/content/public/browser/utility_process_host_client.h
@@ -23,6 +23,9 @@ class UtilityProcessHostClient
// Called when the process has crashed.
virtual void OnProcessCrashed(int exit_code) {}
+ // Called when the process fails to launch, i.e. it has no exit code.
+ virtual void OnProcessLaunchFailed() {}
+
// Allow the client to filter IPC messages.
virtual bool OnMessageReceived(const IPC::Message& message) = 0;
diff --git a/content/public/common/child_process_host_delegate.h b/content/public/common/child_process_host_delegate.h
index 89cb70a..06d3093 100644
--- a/content/public/common/child_process_host_delegate.h
+++ b/content/public/common/child_process_host_delegate.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/process/process.h"
#include "content/common/content_export.h"
#include "ipc/ipc_listener.h"
@@ -26,6 +27,10 @@ class ChildProcessHostDelegate : public IPC::Listener {
// Called when the child process unexpected closes the IPC channel. Delegates
// would normally delete the object in this case.
virtual void OnChildDisconnected() {}
+
+ // Returns the handle of the child process. This can be called only after
+ // OnProcessLaunched is called or it will be invalid and may crash.
+ virtual base::ProcessHandle GetHandle() const = 0;
};
}; // namespace content
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 2d73c2b..977ace3 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -957,6 +957,8 @@ const char kUtilityProcessAllowedDir[] = "utility-allowed-dir";
// Allows MDns to access network in sandboxed process.
const char kUtilityProcessEnableMDns[] = "utility-enable-mdns";
+const char kUtilityProcessRunningElevated[] = "utility-run-elevated";
+
// Will add kWaitForDebugger to every child processes. If a value is passed, it
// will be used as a filter to determine if the child process should have the
// kWaitForDebugger flag passed on or not.
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 41ddbe7..c902785 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -269,6 +269,7 @@ extern const char kUtilityCmdPrefix[];
CONTENT_EXPORT extern const char kUtilityProcess[];
extern const char kUtilityProcessAllowedDir[];
CONTENT_EXPORT extern const char kUtilityProcessEnableMDns[];
+CONTENT_EXPORT extern const char kUtilityProcessRunningElevated[];
CONTENT_EXPORT extern const char kWaitForDebuggerChildren[];
CONTENT_EXPORT extern const char kWebGLCommandBufferSizeKb[];
CONTENT_EXPORT extern const char kWorkerProcess[];