| Index: content/common/sandbox_win.cc
|
| ===================================================================
|
| --- content/common/sandbox_win.cc (revision 188735)
|
| +++ content/common/sandbox_win.cc (working copy)
|
| @@ -2,7 +2,7 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "content/common/sandbox_policy.h"
|
| +#include "content/common/sandbox_win.h"
|
|
|
| #include <string>
|
|
|
| @@ -10,8 +10,6 @@
|
| #include "base/debug/debugger.h"
|
| #include "base/debug/trace_event.h"
|
| #include "base/file_util.h"
|
| -#include "base/lazy_instance.h"
|
| -#include "base/logging.h"
|
| #include "base/path_service.h"
|
| #include "base/process_util.h"
|
| #include "base/string_util.h"
|
| @@ -25,15 +23,16 @@
|
| #include "content/public/common/content_switches.h"
|
| #include "content/public/common/process_type.h"
|
| #include "content/public/common/sandbox_init.h"
|
| +#include "content/public/common/sandboxed_process_launcher_delegate.h"
|
| #include "sandbox/win/src/process_mitigations.h"
|
| #include "sandbox/win/src/sandbox.h"
|
| #include "sandbox/win/src/sandbox_nt_util.h"
|
| #include "sandbox/win/src/win_utils.h"
|
| -#include "ui/gl/gl_switches.h"
|
|
|
| static sandbox::BrokerServices* g_broker_services = NULL;
|
| static sandbox::TargetServices* g_target_services = NULL;
|
|
|
| +namespace content {
|
| namespace {
|
|
|
| // The DLLs listed here are known (or under strong suspicion) of causing crashes
|
| @@ -111,12 +110,6 @@
|
| L"winstylerthemehelper.dll" // Tuneup utilities 2006.
|
| };
|
|
|
| -// The DLLs listed here are known (or under strong suspicion) of causing crashes
|
| -// when they are loaded in the GPU process.
|
| -const wchar_t* const kTroublesomeGpuDlls[] = {
|
| - L"cmsetac.dll", // Unknown (suspected malware).
|
| -};
|
| -
|
| // Adds the policy rules for the path and path\ with the semantic |access|.
|
| // If |children| is set to true, we need to add the wildcard rules to also
|
| // apply the rule to the subfiles and subfolders.
|
| @@ -232,14 +225,6 @@
|
| BlacklistAddOneDll(kTroublesomeDlls[ix], true, policy);
|
| }
|
|
|
| -// Same as AddGenericDllEvictionPolicy but specifically for the GPU process.
|
| -// In this we add the blacklisted dlls even if they are not loaded in this
|
| -// process.
|
| -void AddGpuDllEvictionPolicy(sandbox::TargetPolicy* policy) {
|
| - for (int ix = 0; ix != arraysize(kTroublesomeGpuDlls); ++ix)
|
| - BlacklistAddOneDll(kTroublesomeGpuDlls[ix], false, policy);
|
| -}
|
| -
|
| // Returns the object path prepended with the current logon session.
|
| string16 PrependWindowsSessionPath(const char16* object) {
|
| // Cache this because it can't change after process creation.
|
| @@ -291,30 +276,18 @@
|
| return false;
|
| }
|
|
|
| -void SetJobLevel(const CommandLine& cmd_line,
|
| - sandbox::JobLevel job_level,
|
| - uint32 ui_exceptions,
|
| - sandbox::TargetPolicy* policy) {
|
| - if (ShouldSetJobLevel(cmd_line))
|
| - policy->SetJobLevel(job_level, ui_exceptions);
|
| - else
|
| - policy->SetJobLevel(sandbox::JOB_NONE, 0);
|
| -}
|
| -
|
| -// Closes handles that are opened at process creation and initialization.
|
| -void AddBaseHandleClosePolicy(sandbox::TargetPolicy* policy) {
|
| - // Being able to manipulate anything BaseNamedObjects is bad.
|
| - string16 object_path = PrependWindowsSessionPath(L"\\BaseNamedObjects");
|
| - policy->AddKernelObjectToClose(L"Directory", object_path.data());
|
| - object_path = PrependWindowsSessionPath(
|
| - L"\\BaseNamedObjects\\windows_shell_global_counters");
|
| - policy->AddKernelObjectToClose(L"Section", object_path.data());
|
| -}
|
| -
|
| // Adds the generic policy rules to a sandbox TargetPolicy.
|
| bool AddGenericPolicy(sandbox::TargetPolicy* policy) {
|
| sandbox::ResultCode result;
|
|
|
| + // Renderers need to copy sections for plugin DIBs and GPU.
|
| + // GPU needs to copy sections to renderers.
|
| + result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
|
| + sandbox::TargetPolicy::HANDLES_DUP_ANY,
|
| + L"Section");
|
| + if (result != sandbox::SBOX_ALL_OK)
|
| + return false;
|
| +
|
| // Add the policy for the client side of a pipe. It is just a file
|
| // in the \pipe\ namespace. We restrict it to pipes that start with
|
| // "chrome." so the sandboxed process cannot connect to system services.
|
| @@ -323,14 +296,7 @@
|
| L"\\??\\pipe\\chrome.*");
|
| if (result != sandbox::SBOX_ALL_OK)
|
| return false;
|
| - // Allow the server side of a pipe restricted to the "chrome.nacl."
|
| - // namespace so that it cannot impersonate other system or other chrome
|
| - // service pipes.
|
| - result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
|
| - sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY,
|
| - L"\\\\.\\pipe\\chrome.nacl.*");
|
| - if (result != sandbox::SBOX_ALL_OK)
|
| - return false;
|
| +
|
| // Allow the server side of sync sockets, which are pipes that have
|
| // the "chrome.sync" namespace and a randomly generated suffix.
|
| result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
|
| @@ -360,116 +326,14 @@
|
| if (result != sandbox::SBOX_ALL_OK)
|
| return false;
|
| #endif // NDEBUG
|
| - return true;
|
| -}
|
|
|
| -// For the GPU process we gotten as far as USER_LIMITED. The next level
|
| -// which is USER_RESTRICTED breaks both the DirectX backend and the OpenGL
|
| -// backend. Note that the GPU process is connected to the interactive
|
| -// desktop.
|
| -// TODO(cpu): Lock down the sandbox more if possible.
|
| -bool AddPolicyForGPU(CommandLine* cmd_line, sandbox::TargetPolicy* policy) {
|
| -#if !defined(NACL_WIN64) // We don't need this code on win nacl64.
|
| - if (base::win::GetVersion() > base::win::VERSION_XP) {
|
| - if (cmd_line->GetSwitchValueASCII(switches::kUseGL) ==
|
| - gfx::kGLImplementationDesktopName) {
|
| - // Open GL path.
|
| - policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
|
| - sandbox::USER_LIMITED);
|
| - SetJobLevel(*cmd_line, sandbox::JOB_UNPROTECTED, 0, policy);
|
| - policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
|
| - } else {
|
| - if (cmd_line->GetSwitchValueASCII(switches::kUseGL) ==
|
| - gfx::kGLImplementationSwiftShaderName ||
|
| - cmd_line->HasSwitch(switches::kReduceGpuSandbox) ||
|
| - cmd_line->HasSwitch(switches::kDisableImageTransportSurface)) {
|
| - // Swiftshader path.
|
| - policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
|
| - sandbox::USER_LIMITED);
|
| - } else {
|
| - // Angle + DirectX path.
|
| - policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
|
| - sandbox::USER_RESTRICTED);
|
| - // This is a trick to keep the GPU out of low-integrity processes. It
|
| - // starts at low-integrity for UIPI to work, then drops below
|
| - // low-integrity after warm-up.
|
| - policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
|
| - }
|
| -
|
| - // UI restrictions break when we access Windows from outside our job.
|
| - // However, we don't want a proxy window in this process because it can
|
| - // introduce deadlocks where the renderer blocks on the gpu, which in
|
| - // turn blocks on the browser UI thread. So, instead we forgo a window
|
| - // message pump entirely and just add job restrictions to prevent child
|
| - // processes.
|
| - SetJobLevel(*cmd_line,
|
| - sandbox::JOB_LIMITED_USER,
|
| - JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS |
|
| - JOB_OBJECT_UILIMIT_DESKTOP |
|
| - JOB_OBJECT_UILIMIT_EXITWINDOWS |
|
| - JOB_OBJECT_UILIMIT_DISPLAYSETTINGS,
|
| - policy);
|
| -
|
| - policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
|
| - }
|
| - } else {
|
| - SetJobLevel(*cmd_line, sandbox::JOB_UNPROTECTED, 0, policy);
|
| - policy->SetTokenLevel(sandbox::USER_UNPROTECTED,
|
| - sandbox::USER_LIMITED);
|
| - }
|
| -
|
| - // Allow the server side of GPU sockets, which are pipes that have
|
| - // the "chrome.gpu" namespace and an arbitrary suffix.
|
| - sandbox::ResultCode result = policy->AddRule(
|
| - sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
|
| - sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY,
|
| - L"\\\\.\\pipe\\chrome.gpu.*");
|
| - if (result != sandbox::SBOX_ALL_OK)
|
| - return false;
|
| -
|
| - // GPU needs to copy sections to renderers.
|
| - result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
|
| - sandbox::TargetPolicy::HANDLES_DUP_ANY,
|
| - L"Section");
|
| - if (result != sandbox::SBOX_ALL_OK)
|
| - return false;
|
| -
|
| -#ifdef USE_AURA
|
| - // GPU also needs to add sections to the browser for aura
|
| - // TODO(jschuh): refactor the GPU channel to remove this. crbug.com/128786
|
| - result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
|
| - sandbox::TargetPolicy::HANDLES_DUP_BROKER,
|
| - L"Section");
|
| - if (result != sandbox::SBOX_ALL_OK)
|
| - return false;
|
| -#endif
|
| -
|
| AddGenericDllEvictionPolicy(policy);
|
| - AddGpuDllEvictionPolicy(policy);
|
|
|
| - if (cmd_line->HasSwitch(switches::kEnableLogging)) {
|
| - string16 log_file_path = logging::GetLogFileFullPath();
|
| - if (!log_file_path.empty()) {
|
| - result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
|
| - sandbox::TargetPolicy::FILES_ALLOW_ANY,
|
| - log_file_path.c_str());
|
| - if (result != sandbox::SBOX_ALL_OK)
|
| - return false;
|
| - }
|
| - }
|
| -#endif
|
| return true;
|
| }
|
|
|
| -bool AddPolicyForRenderer(sandbox::TargetPolicy* policy) {
|
| - // Renderers need to copy sections for plugin DIBs and GPU.
|
| +bool AddPolicyForSandboxedProcess(sandbox::TargetPolicy* policy) {
|
| sandbox::ResultCode result;
|
| - result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
|
| - sandbox::TargetPolicy::HANDLES_DUP_ANY,
|
| - L"Section");
|
| - if (result != sandbox::SBOX_ALL_OK)
|
| - return false;
|
| -
|
| // Renderers need to share events with plugins.
|
| result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
|
| sandbox::TargetPolicy::HANDLES_DUP_ANY,
|
| @@ -477,14 +341,6 @@
|
| if (result != sandbox::SBOX_ALL_OK)
|
| return false;
|
|
|
| - // Renderers need to send named pipe handles and shared memory
|
| - // segment handles to NaCl loader processes.
|
| - result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
|
| - sandbox::TargetPolicy::HANDLES_DUP_ANY,
|
| - L"File");
|
| - if (result != sandbox::SBOX_ALL_OK)
|
| - return false;
|
| -
|
| sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED;
|
| if (base::win::GetVersion() > base::win::VERSION_XP) {
|
| // On 2003/Vista the initial token has to be restricted if the main
|
| @@ -503,21 +359,9 @@
|
| DLOG(WARNING) << "Failed to apply desktop security to the renderer";
|
| }
|
|
|
| - AddGenericDllEvictionPolicy(policy);
|
| -
|
| return true;
|
| }
|
|
|
| -// The Pepper process as locked-down as a renderer execpt that it can
|
| -// create the server side of chrome pipes.
|
| -bool AddPolicyForPepperPlugin(sandbox::TargetPolicy* policy) {
|
| - sandbox::ResultCode result;
|
| - result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
|
| - sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY,
|
| - L"\\\\.\\pipe\\chrome.*");
|
| - return result == sandbox::SBOX_ALL_OK;
|
| -}
|
| -
|
| // This code is test only, and attempts to catch unsafe uses of
|
| // DuplicateHandle() that copy privileged handles into sandboxed processes.
|
| #ifndef OFFICIAL_BUILD
|
| @@ -618,8 +462,27 @@
|
|
|
| } // namespace
|
|
|
| -namespace content {
|
| +void SetJobLevel(const CommandLine& cmd_line,
|
| + sandbox::JobLevel job_level,
|
| + uint32 ui_exceptions,
|
| + sandbox::TargetPolicy* policy) {
|
| + if (ShouldSetJobLevel(cmd_line))
|
| + policy->SetJobLevel(job_level, ui_exceptions);
|
| + else
|
| + policy->SetJobLevel(sandbox::JOB_NONE, 0);
|
| +}
|
|
|
| +// TODO(jschuh): Need get these restrictions applied to NaCl and Pepper.
|
| +// Just have to figure out what needs to be warmed up first.
|
| +void AddBaseHandleClosePolicy(sandbox::TargetPolicy* policy) {
|
| + // Being able to manipulate anything BaseNamedObjects is bad.
|
| + string16 object_path = PrependWindowsSessionPath(L"\\BaseNamedObjects");
|
| + policy->AddKernelObjectToClose(L"Directory", object_path.data());
|
| + object_path = PrependWindowsSessionPath(
|
| + L"\\BaseNamedObjects\\windows_shell_global_counters");
|
| + policy->AddKernelObjectToClose(L"Section", object_path.data());
|
| +}
|
| +
|
| bool InitBrokerServices(sandbox::BrokerServices* broker_services) {
|
| // TODO(abarth): DCHECK(CalledOnValidThread());
|
| // See <http://b/1287166>.
|
| @@ -628,7 +491,7 @@
|
| sandbox::ResultCode result = broker_services->Init();
|
| g_broker_services = broker_services;
|
|
|
| -// In non-official builds warn about dangerous uses of DuplicateHandle.
|
| + // In non-official builds warn about dangerous uses of DuplicateHandle.
|
| BOOL is_in_job = FALSE;
|
| #ifdef NACL_WIN64
|
| CHECK(::IsProcessInJob(::GetCurrentProcess(), NULL, &is_in_job));
|
| @@ -662,8 +525,9 @@
|
| return sandbox::SBOX_ALL_OK == result;
|
| }
|
|
|
| -base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
|
| - const base::FilePath& exposed_dir) {
|
| +base::ProcessHandle StartSandboxedProcess(
|
| + SandboxedProcessLauncherDelegate* delegate,
|
| + CommandLine* cmd_line) {
|
| const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
|
| ProcessType type;
|
| std::string type_str = cmd_line->GetSwitchValueASCII(switches::kProcessType);
|
| @@ -773,30 +637,19 @@
|
|
|
| SetJobLevel(*cmd_line, sandbox::JOB_LOCKDOWN, 0, policy);
|
|
|
| - if (type == PROCESS_TYPE_GPU) {
|
| - if (!AddPolicyForGPU(cmd_line, policy))
|
| - return 0;
|
| - } else {
|
| - if (!AddPolicyForRenderer(policy))
|
| - return 0;
|
| - // TODO(jschuh): Need get these restrictions applied to NaCl and Pepper.
|
| - // Just have to figure out what needs to be warmed up first.
|
| - if (type == PROCESS_TYPE_RENDERER ||
|
| - type == PROCESS_TYPE_WORKER) {
|
| - AddBaseHandleClosePolicy(policy);
|
| - // Pepper uses the renderer's policy, whith some tweaks.
|
| - } else if (type == PROCESS_TYPE_PPAPI_PLUGIN) {
|
| - if (!AddPolicyForPepperPlugin(policy))
|
| - return 0;
|
| - }
|
| + bool disable_default_policy = false;
|
| + base::FilePath exposed_dir;
|
| + if (delegate)
|
| + delegate->PreSandbox(&disable_default_policy, &exposed_dir);
|
|
|
| + if (!disable_default_policy && !AddPolicyForSandboxedProcess(policy))
|
| + return 0;
|
|
|
| - if (type_str != switches::kRendererProcess) {
|
| - // Hack for Google Desktop crash. Trick GD into not injecting its DLL into
|
| - // this subprocess. See
|
| - // http://code.google.com/p/chromium/issues/detail?id=25580
|
| - cmd_line->AppendSwitchASCII("ignored", " --type=renderer ");
|
| - }
|
| + if (type_str != switches::kRendererProcess) {
|
| + // Hack for Google Desktop crash. Trick GD into not injecting its DLL into
|
| + // this subprocess. See
|
| + // http://code.google.com/p/chromium/issues/detail?id=25580
|
| + cmd_line->AppendSwitchASCII("ignored", " --type=renderer ");
|
| }
|
|
|
| sandbox::ResultCode result;
|
| @@ -827,6 +680,13 @@
|
| policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE));
|
| }
|
|
|
| + if (delegate) {
|
| + bool success = true;
|
| + delegate->PreSpawnTarget(policy, &success);
|
| + if (!success)
|
| + return 0;
|
| + }
|
| +
|
| TRACE_EVENT_BEGIN_ETW("StartProcessWithAccess::LAUNCHPROCESS", 0, 0);
|
|
|
| result = g_broker_services->SpawnTarget(
|
| @@ -842,26 +702,10 @@
|
| return 0;
|
| }
|
|
|
| -#if !defined(NACL_WIN64)
|
| - // For Native Client sel_ldr processes on 32-bit Windows, reserve 1 GB of
|
| - // address space to prevent later failure due to address space fragmentation
|
| - // from .dll loading. The NaCl process will attempt to locate this space by
|
| - // scanning the address space using VirtualQuery.
|
| - // TODO(bbudge) Handle the --no-sandbox case.
|
| - // http://code.google.com/p/nativeclient/issues/detail?id=2131
|
| - if (type == PROCESS_TYPE_NACL_LOADER) {
|
| - const SIZE_T kOneGigabyte = 1 << 30;
|
| - void* nacl_mem = VirtualAllocEx(target.process_handle(),
|
| - NULL,
|
| - kOneGigabyte,
|
| - MEM_RESERVE,
|
| - PAGE_NOACCESS);
|
| - if (!nacl_mem) {
|
| - DLOG(WARNING) << "Failed to reserve address space for Native Client";
|
| - }
|
| - }
|
| -#endif // !defined(NACL_WIN64)
|
| + if (delegate)
|
| + delegate->PostSpawnTarget(target.process_handle());
|
|
|
| +
|
| ResumeThread(target.thread_handle());
|
|
|
| // Help the process a little. It can't start the debugger by itself if
|
|
|