diff options
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[]; |