diff options
-rw-r--r-- | content/common/sandbox_win.cc | 10 | ||||
-rw-r--r-- | sandbox/win/sandbox_win.gypi | 6 | ||||
-rw-r--r-- | sandbox/win/src/interceptors.h | 4 | ||||
-rw-r--r-- | sandbox/win/src/interceptors_64.cc | 24 | ||||
-rw-r--r-- | sandbox/win/src/interceptors_64.h | 14 | ||||
-rw-r--r-- | sandbox/win/src/ipc_tags.h | 3 | ||||
-rw-r--r-- | sandbox/win/src/process_mitigations_test.cc | 51 | ||||
-rw-r--r-- | sandbox/win/src/process_mitigations_win32k_dispatcher.cc | 57 | ||||
-rw-r--r-- | sandbox/win/src/process_mitigations_win32k_dispatcher.h | 31 | ||||
-rw-r--r-- | sandbox/win/src/process_mitigations_win32k_interception.cc | 29 | ||||
-rw-r--r-- | sandbox/win/src/process_mitigations_win32k_interception.h | 46 | ||||
-rw-r--r-- | sandbox/win/src/process_mitigations_win32k_policy.cc | 24 | ||||
-rw-r--r-- | sandbox/win/src/process_mitigations_win32k_policy.h | 35 | ||||
-rw-r--r-- | sandbox/win/src/sandbox_policy.h | 8 | ||||
-rw-r--r-- | sandbox/win/src/sandbox_policy_base.cc | 17 |
15 files changed, 350 insertions, 9 deletions
diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc index 9432d24..18b30e2 100644 --- a/content/common/sandbox_win.cc +++ b/content/common/sandbox_win.cc @@ -333,7 +333,6 @@ bool AddGenericPolicy(sandbox::TargetPolicy* policy) { #endif // NDEBUG AddGenericDllEvictionPolicy(policy); - return true; } @@ -614,8 +613,13 @@ base::ProcessHandle StartSandboxedProcess( type_str == switches::kRendererProcess && browser_command_line.HasSwitch( switches::kEnableWin32kRendererLockDown)) { - mitigations |= sandbox::MITIGATION_WIN32K_DISABLE; - } + if (policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, + sandbox::TargetPolicy::FAKE_USER_GDI_INIT, + NULL) != sandbox::SBOX_ALL_OK) { + return 0; + } + mitigations |= sandbox::MITIGATION_WIN32K_DISABLE; + } if (policy->SetProcessMitigations(mitigations) != sandbox::SBOX_ALL_OK) return 0; diff --git a/sandbox/win/sandbox_win.gypi b/sandbox/win/sandbox_win.gypi index 01d3f12..7d9cf94 100644 --- a/sandbox/win/sandbox_win.gypi +++ b/sandbox/win/sandbox_win.gypi @@ -74,6 +74,12 @@ 'src/policy_target.h', 'src/process_mitigations.cc', 'src/process_mitigations.h', + 'src/process_mitigations_win32k_dispatcher.cc', + 'src/process_mitigations_win32k_dispatcher.h', + 'src/process_mitigations_win32k_interception.cc', + 'src/process_mitigations_win32k_interception.h', + 'src/process_mitigations_win32k_policy.cc', + 'src/process_mitigations_win32k_policy.h', 'src/process_thread_dispatcher.cc', 'src/process_thread_dispatcher.h', 'src/process_thread_interception.cc', diff --git a/sandbox/win/src/interceptors.h b/sandbox/win/src/interceptors.h index ae3ecc6..a17447a 100644 --- a/sandbox/win/src/interceptors.h +++ b/sandbox/win/src/interceptors.h @@ -41,6 +41,10 @@ enum InterceptorId { // Sync dispatcher: CREATE_EVENT_ID, OPEN_EVENT_ID, + // Process mitigations Win32k dispatcher: + GDIINITIALIZE_ID, + GETSTOCKOBJECT_ID, + REGISTERCLASSW_ID, INTERCEPTOR_MAX_ID }; diff --git a/sandbox/win/src/interceptors_64.cc b/sandbox/win/src/interceptors_64.cc index f279b16..ef0b5f0 100644 --- a/sandbox/win/src/interceptors_64.cc +++ b/sandbox/win/src/interceptors_64.cc @@ -8,6 +8,7 @@ #include "sandbox/win/src/filesystem_interception.h" #include "sandbox/win/src/named_pipe_interception.h" #include "sandbox/win/src/policy_target.h" +#include "sandbox/win/src/process_mitigations_win32k_interception.h" #include "sandbox/win/src/process_thread_interception.h" #include "sandbox/win/src/registry_interception.h" #include "sandbox/win/src/sandbox_nt_types.h" @@ -251,4 +252,27 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenEvent64( object_attributes); } +// ----------------------------------------------------------------------- + +SANDBOX_INTERCEPT BOOL WINAPI TargetGdiDllInitialize64( + HANDLE dll, + DWORD reason) { + GdiDllInitializeFunction orig_fn = reinterpret_cast< + GdiDllInitializeFunction>(g_originals[GDIINITIALIZE_ID]); + return TargetGdiDllInitialize(orig_fn, dll, reason); +} + +SANDBOX_INTERCEPT HGDIOBJ WINAPI TargetGetStockObject64(int object) { + GetStockObjectFunction orig_fn = reinterpret_cast< + GetStockObjectFunction>(g_originals[GETSTOCKOBJECT_ID]); + return TargetGetStockObject(orig_fn, object); +} + +SANDBOX_INTERCEPT ATOM WINAPI TargetRegisterClassW64( + const WNDCLASS* wnd_class) { + RegisterClassWFunction orig_fn = reinterpret_cast< + RegisterClassWFunction>(g_originals[REGISTERCLASSW_ID]); + return TargetRegisterClassW(orig_fn, wnd_class); +} + } // namespace sandbox diff --git a/sandbox/win/src/interceptors_64.h b/sandbox/win/src/interceptors_64.h index 2ff31a8..7368ceb 100644 --- a/sandbox/win/src/interceptors_64.h +++ b/sandbox/win/src/interceptors_64.h @@ -154,6 +154,20 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenEvent64( PHANDLE event_handle, ACCESS_MASK desired_access, POBJECT_ATTRIBUTES object_attributes); +// ----------------------------------------------------------------------- +// Interceptors handled by the process mitigations win32k lockdown code. + +// Interceptor for the GdiDllInitialize function. +SANDBOX_INTERCEPT BOOL WINAPI TargetGdiDllInitialize64( + HANDLE dll, + DWORD reason); + +// Interceptor for the GetStockObject function. +SANDBOX_INTERCEPT HGDIOBJ WINAPI TargetGetStockObject64(int object); + +// Interceptor for the RegisterClassW function. +SANDBOX_INTERCEPT ATOM WINAPI TargetRegisterClassW64(const WNDCLASS* wnd_class); + } // extern "C" } // namespace sandbox diff --git a/sandbox/win/src/ipc_tags.h b/sandbox/win/src/ipc_tags.h index 4e3a806..d680411 100644 --- a/sandbox/win/src/ipc_tags.h +++ b/sandbox/win/src/ipc_tags.h @@ -29,6 +29,9 @@ enum { IPC_NTCREATEKEY_TAG, IPC_NTOPENKEY_TAG, IPC_DUPLICATEHANDLEPROXY_TAG, + IPC_GDI_GDIDLLINITIALIZE_TAG, + IPC_GDI_GETSTOCKOBJECT_TAG, + IPC_USER_REGISTERCLASSW_TAG, IPC_LAST_TAG }; diff --git a/sandbox/win/src/process_mitigations_test.cc b/sandbox/win/src/process_mitigations_test.cc index 19e55ba..e606256 100644 --- a/sandbox/win/src/process_mitigations_test.cc +++ b/sandbox/win/src/process_mitigations_test.cc @@ -88,7 +88,6 @@ SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { reinterpret_cast<GetProcessMitigationPolicyFunction>( ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); - if (!get_process_mitigation_policy) return SBOX_TEST_NOT_FOUND; @@ -103,9 +102,6 @@ SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { if (!CheckWin8StrictHandlePolicy()) return SBOX_TEST_THIRD_ERROR; - if (!CheckWin8Win32CallPolicy()) - return SBOX_TEST_FOURTH_ERROR; - if (!CheckWin8DllExtensionPolicy()) return SBOX_TEST_FIFTH_ERROR; @@ -201,5 +197,52 @@ TEST(ProcessMitigationsTest, CheckDep) { } #endif +SBOX_TESTS_COMMAND int CheckWin8Lockdown(int argc, wchar_t **argv) { + get_process_mitigation_policy = + reinterpret_cast<GetProcessMitigationPolicyFunction>( + ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), + "GetProcessMitigationPolicy")); + if (!get_process_mitigation_policy) + return SBOX_TEST_NOT_FOUND; + + if (!CheckWin8Win32CallPolicy()) + return SBOX_TEST_FIRST_ERROR; + return SBOX_TEST_SUCCEEDED; +} + +// This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation on +// the target process causes the launch to fail in process initialization. +// The test process itself links against user32/gdi32. +TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownFailure) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + TestRunner runner; + sandbox::TargetPolicy* policy = runner.GetPolicy(); + + EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), + SBOX_ALL_OK); + EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); +} + +// This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation +// along with the policy to fake user32 and gdi32 initialization successfully +// launches the target process. +// The test process itself links against user32/gdi32. +TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownSuccess) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + TestRunner runner; + sandbox::TargetPolicy* policy = runner.GetPolicy(); + + EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), + SBOX_ALL_OK); + EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, + sandbox::TargetPolicy::FAKE_USER_GDI_INIT, NULL), + sandbox::SBOX_ALL_OK); + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); +} + } // namespace sandbox diff --git a/sandbox/win/src/process_mitigations_win32k_dispatcher.cc b/sandbox/win/src/process_mitigations_win32k_dispatcher.cc new file mode 100644 index 0000000..e426084 --- /dev/null +++ b/sandbox/win/src/process_mitigations_win32k_dispatcher.cc @@ -0,0 +1,57 @@ +// 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 "sandbox/win/src/process_mitigations_win32k_dispatcher.h" +#include "sandbox/win/src/interception.h" +#include "sandbox/win/src/interceptors.h" +#include "sandbox/win/src/ipc_tags.h" +#include "sandbox/win/src/process_mitigations_win32k_interception.h" + +namespace sandbox { + +ProcessMitigationsWin32KDispatcher::ProcessMitigationsWin32KDispatcher( + PolicyBase* policy_base) + : policy_base_(policy_base) { +} + +bool ProcessMitigationsWin32KDispatcher::SetupService( + InterceptionManager* manager, int service) { + if (!(policy_base_->GetProcessMitigations() & + sandbox::MITIGATION_WIN32K_DISABLE)) { + return false; + } + + switch (service) { + case IPC_GDI_GDIDLLINITIALIZE_TAG: { + if (!INTERCEPT_EAT(manager, L"gdi32.dll", GdiDllInitialize, + GDIINITIALIZE_ID, 12)) { + return false; + } + return true; + } + + case IPC_GDI_GETSTOCKOBJECT_TAG: { + if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetStockObject, + GETSTOCKOBJECT_ID, 8)) { + return false; + } + return true; + } + + case IPC_USER_REGISTERCLASSW_TAG: { + if (!INTERCEPT_EAT(manager, L"user32.dll", RegisterClassW, + REGISTERCLASSW_ID, 8)) { + return false; + } + return true; + } + + default: + break; + } + return false; +} + +} // namespace sandbox + diff --git a/sandbox/win/src/process_mitigations_win32k_dispatcher.h b/sandbox/win/src/process_mitigations_win32k_dispatcher.h new file mode 100644 index 0000000..65c9f77 --- /dev/null +++ b/sandbox/win/src/process_mitigations_win32k_dispatcher.h @@ -0,0 +1,31 @@ +// 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 SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_DISPATCHER_H_ +#define SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_DISPATCHER_H_ + +#include "base/basictypes.h" +#include "sandbox/win/src/sandbox_policy_base.h" + +namespace sandbox { + +// This class sets up intercepts for the Win32K lockdown policy which is set +// on Windows 8 and beyond. +class ProcessMitigationsWin32KDispatcher : public Dispatcher { + public: + explicit ProcessMitigationsWin32KDispatcher(PolicyBase* policy_base); + ~ProcessMitigationsWin32KDispatcher() {} + + // Dispatcher interface. + virtual bool SetupService(InterceptionManager* manager, int service); + + private: + PolicyBase* policy_base_; + + DISALLOW_COPY_AND_ASSIGN(ProcessMitigationsWin32KDispatcher); +}; + +} // namespace sandbox + +#endif // SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_DISPATCHER_H_ diff --git a/sandbox/win/src/process_mitigations_win32k_interception.cc b/sandbox/win/src/process_mitigations_win32k_interception.cc new file mode 100644 index 0000000..ee24fbf --- /dev/null +++ b/sandbox/win/src/process_mitigations_win32k_interception.cc @@ -0,0 +1,29 @@ +// 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 "sandbox/win/src/process_mitigations_win32k_interception.h" + +namespace sandbox { + +BOOL WINAPI TargetGdiDllInitialize( + GdiDllInitializeFunction orig_gdi_dll_initialize, + HANDLE dll, + DWORD reason) { + return TRUE; +} + +HGDIOBJ WINAPI TargetGetStockObject( + GetStockObjectFunction orig_get_stock_object, + int object) { + return reinterpret_cast<HGDIOBJ>(NULL); +} + +ATOM WINAPI TargetRegisterClassW( + RegisterClassWFunction orig_register_class_function, + const WNDCLASS* wnd_class) { + return TRUE; +} + +} // namespace sandbox + diff --git a/sandbox/win/src/process_mitigations_win32k_interception.h b/sandbox/win/src/process_mitigations_win32k_interception.h new file mode 100644 index 0000000..bf7b551 --- /dev/null +++ b/sandbox/win/src/process_mitigations_win32k_interception.h @@ -0,0 +1,46 @@ +// 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 SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_INTERCEPTION_H_ +#define SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_INTERCEPTION_H_ + +#include <windows.h> +#include "base/basictypes.h" +#include "sandbox/win/src/sandbox_types.h" + +namespace sandbox { + +extern "C" { + +typedef BOOL (WINAPI* GdiDllInitializeFunction) ( + HANDLE dll, + DWORD reason, + LPVOID reserved); + +typedef HGDIOBJ (WINAPI *GetStockObjectFunction) (int object); + +typedef ATOM (WINAPI *RegisterClassWFunction) (const WNDCLASS* wnd_class); + +// Interceptor for the GdiDllInitialize function. +SANDBOX_INTERCEPT BOOL WINAPI TargetGdiDllInitialize( + GdiDllInitializeFunction orig_gdi_dll_initialize, + HANDLE dll, + DWORD reason); + +// Interceptor for the GetStockObject function. +SANDBOX_INTERCEPT HGDIOBJ WINAPI TargetGetStockObject( + GetStockObjectFunction orig_get_stock_object, + int object); + +// Interceptor for the RegisterClassW function. +SANDBOX_INTERCEPT ATOM WINAPI TargetRegisterClassW( + RegisterClassWFunction orig_register_class_function, + const WNDCLASS* wnd_class); + +} // extern "C" + +} // namespace sandbox + +#endif // SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_INTERCEPTION_H_ + diff --git a/sandbox/win/src/process_mitigations_win32k_policy.cc b/sandbox/win/src/process_mitigations_win32k_policy.cc new file mode 100644 index 0000000..af18c54 --- /dev/null +++ b/sandbox/win/src/process_mitigations_win32k_policy.cc @@ -0,0 +1,24 @@ +// 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 "sandbox/win/src/process_mitigations_win32k_policy.h" + +namespace sandbox { + +bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules( + const wchar_t* name, + TargetPolicy::Semantics semantics, + LowLevelPolicy* policy) { + PolicyRule rule(FAKE_SUCCESS); + if (!policy->AddRule(IPC_GDI_GDIDLLINITIALIZE_TAG, &rule)) + return false; + if (!policy->AddRule(IPC_GDI_GETSTOCKOBJECT_TAG, &rule)) + return false; + if (!policy->AddRule(IPC_USER_REGISTERCLASSW_TAG, &rule)) + return false; + return true; +} + +} // namespace sandbox + diff --git a/sandbox/win/src/process_mitigations_win32k_policy.h b/sandbox/win/src/process_mitigations_win32k_policy.h new file mode 100644 index 0000000..078ed2b --- /dev/null +++ b/sandbox/win/src/process_mitigations_win32k_policy.h @@ -0,0 +1,35 @@ +// 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 SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_POLICY_H_ +#define SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_POLICY_H_ + +#include "base/basictypes.h" +#include "sandbox/win/src/crosscall_server.h" +#include "sandbox/win/src/policy_low_level.h" +#include "sandbox/win/src/sandbox_policy.h" + +namespace sandbox { + +enum EvalResult; + +// This class centralizes most of the knowledge related to the process +// mitigations Win32K lockdown policy. +class ProcessMitigationsWin32KLockdownPolicy { + public: + // Creates the required low-level policy rules to evaluate a high-level + // policy rule for the Win32K process mitigation policy. + // name is the object name, semantics is the desired semantics for the + // open or create and policy is the policy generator to which the rules are + // going to be added. + static bool GenerateRules(const wchar_t* name, + TargetPolicy::Semantics semantics, + LowLevelPolicy* policy); +}; + +} // namespace sandbox + +#endif // SANDBOX_SRC_PROCESS_MITIGATIONS_WIN32K_POLICY_H_ + + diff --git a/sandbox/win/src/sandbox_policy.h b/sandbox/win/src/sandbox_policy.h index 9379d45..22a2049 100644 --- a/sandbox/win/src/sandbox_policy.h +++ b/sandbox/win/src/sandbox_policy.h @@ -26,7 +26,8 @@ class TargetPolicy { SUBSYS_PROCESS, // Creation of child processes. SUBSYS_REGISTRY, // Creation and opening of registry keys. SUBSYS_SYNC, // Creation of named sync objects. - SUBSYS_HANDLES // Duplication of handles to other processes. + SUBSYS_HANDLES, // Duplication of handles to other processes. + SUBSYS_WIN32K_LOCKDOWN // Win32K Lockdown related policy. }; // Allowable semantics when a rule is matched. @@ -52,7 +53,10 @@ class TargetPolicy { EVENTS_ALLOW_ANY, // Allows the creation of an event with full access. EVENTS_ALLOW_READONLY, // Allows opening an even with synchronize access. REG_ALLOW_READONLY, // Allows readonly access to a registry key. - REG_ALLOW_ANY // Allows read and write access to a registry key. + REG_ALLOW_ANY, // Allows read and write access to a registry key. + FAKE_USER_GDI_INIT // Fakes user32 and gdi32 initialization. This can + // be used to allow the DLLs to load and initialize + // even if the process cannot access that subsystem. }; // Increments the reference count of this object. The reference count must diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc index ca946a4..711fafc 100644 --- a/sandbox/win/src/sandbox_policy_base.cc +++ b/sandbox/win/src/sandbox_policy_base.cc @@ -21,6 +21,8 @@ #include "sandbox/win/src/policy_broker.h" #include "sandbox/win/src/policy_engine_processor.h" #include "sandbox/win/src/policy_low_level.h" +#include "sandbox/win/src/process_mitigations_win32k_dispatcher.h" +#include "sandbox/win/src/process_mitigations_win32k_policy.h" #include "sandbox/win/src/process_thread_dispatcher.h" #include "sandbox/win/src/process_thread_policy.h" #include "sandbox/win/src/registry_dispatcher.h" @@ -125,6 +127,11 @@ PolicyBase::PolicyBase() dispatcher = new HandleDispatcher(this); ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG] = dispatcher; + + dispatcher = new ProcessMitigationsWin32KDispatcher(this); + ipc_targets_[IPC_GDI_GDIDLLINITIALIZE_TAG] = dispatcher; + ipc_targets_[IPC_GDI_GETSTOCKOBJECT_TAG] = dispatcher; + ipc_targets_[IPC_USER_REGISTERCLASSW_TAG] = dispatcher; } PolicyBase::~PolicyBase() { @@ -425,6 +432,16 @@ ResultCode PolicyBase::AddRule(SubSystem subsystem, Semantics semantics, } break; } + + case SUBSYS_WIN32K_LOCKDOWN: { + if (!ProcessMitigationsWin32KLockdownPolicy::GenerateRules( + pattern, semantics,policy_maker_)) { + NOTREACHED(); + return SBOX_ERROR_BAD_PARAMS; + } + break; + } + default: { return SBOX_ERROR_UNSUPPORTED; } |