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, |
jam
2013/03/19 16:06:27
this same code was in AddPolicyForGPU and AddPolic
|
+ 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) { |
jam
2013/03/19 16:06:27
(I renamed this to something more generic since it
|
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 |