diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-08-01 12:59:39 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2016-08-04 12:40:43 +0000 |
commit | 28b1110370900897ab652cb420c371fab8857ad4 (patch) | |
tree | 41b32127d23b0df4f2add2a27e12dc87bddb260e /chromium/sandbox | |
parent | 399c965b6064c440ddcf4015f5f8e9d131c7a0a6 (diff) | |
download | qtwebengine-chromium-28b1110370900897ab652cb420c371fab8857ad4.tar.gz |
BASELINE: Update Chromium to 53.0.2785.41
Also adds a few extra files for extensions.
Change-Id: Iccdd55d98660903331cf8b7b29188da781830af4
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/sandbox')
15 files changed, 623 insertions, 113 deletions
diff --git a/chromium/sandbox/linux/BUILD.gn b/chromium/sandbox/linux/BUILD.gn index bf243cda91c..76eef666ac1 100644 --- a/chromium/sandbox/linux/BUILD.gn +++ b/chromium/sandbox/linux/BUILD.gn @@ -304,6 +304,19 @@ if (is_linux) { "-Wno-sign-compare", ] + import("//build/config/compiler/compiler.gni") + import("//build/config/sanitizers/sanitizers.gni") + if (is_component_build && !using_sanitizer) { + # WARNING! We remove this config so that we don't accidentally + # pick up the //build/config:rpath_for_built_shared_libraries + # sub-config. However, this means that we need to duplicate any + # other flags that executable_config might have. + configs -= [ "//build/config:executable_config" ] + if (!use_gold) { + ldflags = [ "-Wl,--disable-new-dtags" ] + } + } + deps = [ "//build/config/sanitizers:deps", ] diff --git a/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc b/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc index 0a3dadb715c..ae35677de2b 100644 --- a/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc +++ b/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc @@ -2135,7 +2135,8 @@ SANDBOX_TEST(SandboxBPF, Tsync) { return; } - base::WaitableEvent event(true, false); + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); // Create a thread on which to invoke the blocked syscall. pthread_t thread; diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc index 9daeedc901f..804a8fea1e7 100644 --- a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc +++ b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc @@ -157,7 +157,9 @@ void SchedGetParamThread(base::WaitableEvent* thread_run) { BPF_TEST_C(ParameterRestrictions, sched_getparam_allowed, RestrictSchedPolicy) { - base::WaitableEvent thread_run(true, false); + base::WaitableEvent thread_run( + base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); // Run the actual test in a new thread so that the current pid and tid are // different. base::Thread getparam_thread("sched_getparam_thread"); diff --git a/chromium/sandbox/linux/suid/client/setuid_sandbox_client.cc b/chromium/sandbox/linux/suid/client/setuid_sandbox_client.cc index 12ef7f9f40a..ca73d46444e 100644 --- a/chromium/sandbox/linux/suid/client/setuid_sandbox_client.cc +++ b/chromium/sandbox/linux/suid/client/setuid_sandbox_client.cc @@ -10,6 +10,7 @@ #include <unistd.h> #include <string> +#include <utility> #include "base/environment.h" #include "base/files/scoped_file.h" @@ -62,13 +63,12 @@ int GetIPCDescriptor(base::Environment* env) { namespace sandbox { SetuidSandboxClient* SetuidSandboxClient::Create() { - base::Environment* environment(base::Environment::Create()); - CHECK(environment); - return new SetuidSandboxClient(environment); + return new SetuidSandboxClient(base::Environment::Create()); } -SetuidSandboxClient::SetuidSandboxClient(base::Environment* env) - : env_(env), sandboxed_(false) { +SetuidSandboxClient::SetuidSandboxClient(std::unique_ptr<base::Environment> env) + : env_(std::move(env)), sandboxed_(false) { + DCHECK(env_); } SetuidSandboxClient::~SetuidSandboxClient() { diff --git a/chromium/sandbox/linux/suid/client/setuid_sandbox_client.h b/chromium/sandbox/linux/suid/client/setuid_sandbox_client.h index d1cff4256aa..21ddab69767 100644 --- a/chromium/sandbox/linux/suid/client/setuid_sandbox_client.h +++ b/chromium/sandbox/linux/suid/client/setuid_sandbox_client.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_ -#define SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_ +#ifndef SANDBOX_LINUX_SUID_CLIENT_SETUID_SANDBOX_CLIENT_H_ +#define SANDBOX_LINUX_SUID_CLIENT_SETUID_SANDBOX_CLIENT_H_ #include <memory> @@ -58,7 +58,7 @@ class SANDBOX_EXPORT SetuidSandboxClient { bool IsSandboxed() const; private: - explicit SetuidSandboxClient(base::Environment* env); + explicit SetuidSandboxClient(std::unique_ptr<base::Environment> env); // Holds the environment. Will never be NULL. std::unique_ptr<base::Environment> env_; @@ -69,4 +69,4 @@ class SANDBOX_EXPORT SetuidSandboxClient { } // namespace sandbox -#endif // SANDBOX_LINUX_SUID_SETUID_SANDBOX_CLIENT_H_ +#endif // SANDBOX_LINUX_SUID_CLIENT_SETUID_SANDBOX_CLIENT_H_ diff --git a/chromium/sandbox/linux/suid/client/setuid_sandbox_host.cc b/chromium/sandbox/linux/suid/client/setuid_sandbox_host.cc index 278f1d2b42e..24608ecf6ee 100644 --- a/chromium/sandbox/linux/suid/client/setuid_sandbox_host.cc +++ b/chromium/sandbox/linux/suid/client/setuid_sandbox_host.cc @@ -29,13 +29,15 @@ #include "sandbox/linux/suid/common/sandbox.h" #include "sandbox/linux/suid/common/suid_unsafe_environment_variables.h" +namespace sandbox { + namespace { // Set an environment variable that reflects the API version we expect from the // setuid sandbox. Old versions of the sandbox will ignore this. void SetSandboxAPIEnvironmentVariable(base::Environment* env) { - env->SetVar(sandbox::kSandboxEnvironmentApiRequest, - base::IntToString(sandbox::kSUIDSandboxApiNumber)); + env->SetVar(kSandboxEnvironmentApiRequest, + base::IntToString(kSUIDSandboxApiNumber)); } // Unset environment variables that are expected to be set by the setuid @@ -44,11 +46,9 @@ void SetSandboxAPIEnvironmentVariable(base::Environment* env) { void UnsetExpectedEnvironmentVariables(base::EnvironmentMap* env_map) { DCHECK(env_map); const base::NativeEnvironmentString environment_vars[] = { - sandbox::kSandboxDescriptorEnvironmentVarName, - sandbox::kSandboxHelperPidEnvironmentVarName, - sandbox::kSandboxEnvironmentApiProvides, - sandbox::kSandboxPIDNSEnvironmentVarName, - sandbox::kSandboxNETNSEnvironmentVarName, + kSandboxDescriptorEnvironmentVarName, kSandboxHelperPidEnvironmentVarName, + kSandboxEnvironmentApiProvides, kSandboxPIDNSEnvironmentVarName, + kSandboxNETNSEnvironmentVarName, }; for (size_t i = 0; i < arraysize(environment_vars); ++i) { @@ -64,7 +64,7 @@ void UnsetExpectedEnvironmentVariables(base::EnvironmentMap* env_map) { std::string* CreateSavedVariableName(const char* env_var) { char* const saved_env_var = SandboxSavedEnvironmentVariable(env_var); if (!saved_env_var) - return NULL; + return nullptr; std::string* saved_env_var_copy = new std::string(saved_env_var); // SandboxSavedEnvironmentVariable is the C function that we wrap and uses // malloc() to allocate memory. @@ -81,7 +81,7 @@ void SaveSUIDUnsafeEnvironmentVariables(base::Environment* env) { // Get the saved environment variable corresponding to envvar. std::unique_ptr<std::string> saved_env_var( CreateSavedVariableName(env_var)); - if (saved_env_var == NULL) + if (!saved_env_var) continue; std::string value; @@ -98,15 +98,13 @@ const char* GetDevelSandboxPath() { } // namespace -namespace sandbox { - SetuidSandboxHost* SetuidSandboxHost::Create() { - base::Environment* environment(base::Environment::Create()); - CHECK(environment); - return new SetuidSandboxHost(environment); + return new SetuidSandboxHost(base::Environment::Create()); } -SetuidSandboxHost::SetuidSandboxHost(base::Environment* env) : env_(env) { +SetuidSandboxHost::SetuidSandboxHost(std::unique_ptr<base::Environment> env) + : env_(std::move(env)) { + DCHECK(env_); } SetuidSandboxHost::~SetuidSandboxHost() { @@ -116,10 +114,7 @@ SetuidSandboxHost::~SetuidSandboxHost() { // the setuid sandbox. TODO(jln): fix this (crbug.com/245376). bool SetuidSandboxHost::IsDisabledViaEnvironment() { const char* devel_sandbox_path = GetDevelSandboxPath(); - if (devel_sandbox_path && '\0' == *devel_sandbox_path) { - return true; - } - return false; + return devel_sandbox_path && (*devel_sandbox_path == '\0'); } base::FilePath SetuidSandboxHost::GetSandboxBinaryPath() { diff --git a/chromium/sandbox/linux/suid/client/setuid_sandbox_host.h b/chromium/sandbox/linux/suid/client/setuid_sandbox_host.h index c69c2c0c4f0..b36480187b1 100644 --- a/chromium/sandbox/linux/suid/client/setuid_sandbox_host.h +++ b/chromium/sandbox/linux/suid/client/setuid_sandbox_host.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SANDBOX_LINUX_SUID_SETUID_SANDBOX_HOST_H_ -#define SANDBOX_LINUX_SUID_SETUID_SANDBOX_HOST_H_ +#ifndef SANDBOX_LINUX_SUID_CLIENT_SETUID_SANDBOX_HOST_H_ +#define SANDBOX_LINUX_SUID_CLIENT_SETUID_SANDBOX_HOST_H_ #include <memory> @@ -38,13 +38,16 @@ class SANDBOX_EXPORT SetuidSandboxHost { // The setuid sandbox may still be disabled via the environment. // This is tracked in crbug.com/245376. bool IsDisabledViaEnvironment(); + // Get the sandbox binary path. This method knows about the // CHROME_DEVEL_SANDBOX environment variable used for user-managed builds. If // the sandbox binary cannot be found, it will return an empty FilePath. base::FilePath GetSandboxBinaryPath(); + // Modify |cmd_line| to launch via the setuid sandbox. Crash if the setuid // sandbox binary cannot be found. |cmd_line| must not be NULL. void PrependWrapper(base::CommandLine* cmd_line); + // Set-up the launch options for launching via the setuid sandbox. Caller is // responsible for keeping |dummy_fd| alive until LaunchProcess() completes. // |options| and |fds_to_remap| must not be NULL. @@ -53,12 +56,13 @@ class SANDBOX_EXPORT SetuidSandboxHost { void SetupLaunchOptions(base::LaunchOptions* options, base::FileHandleMappingVector* fds_to_remap, base::ScopedFD* dummy_fd); + // Set-up the environment. This should be done prior to launching the setuid // helper. void SetupLaunchEnvironment(); private: - explicit SetuidSandboxHost(base::Environment* env); + explicit SetuidSandboxHost(std::unique_ptr<base::Environment> env); // Holds the environment. Will never be NULL. std::unique_ptr<base::Environment> env_; @@ -68,4 +72,4 @@ class SANDBOX_EXPORT SetuidSandboxHost { } // namespace sandbox -#endif // SANDBOX_LINUX_SUID_SETUID_SANDBOX_HOST_H_ +#endif // SANDBOX_LINUX_SUID_CLIENT_SETUID_SANDBOX_HOST_H_ diff --git a/chromium/sandbox/mac/os_compatibility.cc b/chromium/sandbox/mac/os_compatibility.cc index 42abe293d04..0e8d08f5d75 100644 --- a/chromium/sandbox/mac/os_compatibility.cc +++ b/chromium/sandbox/mac/os_compatibility.cc @@ -181,7 +181,7 @@ class OSCompatibility_10_10 : public OSCompatibility { // static std::unique_ptr<OSCompatibility> OSCompatibility::CreateForPlatform() { - if (base::mac::IsOSMavericksOrEarlier()) + if (base::mac::IsOSMavericks()) return base::WrapUnique(new OSCompatibility_10_7()); else return base::WrapUnique(new OSCompatibility_10_10()); diff --git a/chromium/sandbox/mac/xpc_message_server_unittest.cc b/chromium/sandbox/mac/xpc_message_server_unittest.cc index 16872901993..0feaac975e4 100644 --- a/chromium/sandbox/mac/xpc_message_server_unittest.cc +++ b/chromium/sandbox/mac/xpc_message_server_unittest.cc @@ -21,18 +21,6 @@ namespace sandbox { -class XPCMessageServerTest : public testing::Test { - public: - void SetUp() override { - if (!RunXPCTest()) - return; - } - - bool RunXPCTest() { - return base::mac::IsOSMountainLionOrLater(); - } -}; - // A MessageDemuxer that manages a test server and executes a block for every // message. class BlockDemuxer : public MessageDemuxer { @@ -86,11 +74,7 @@ class BlockDemuxer : public MessageDemuxer { xpc_pipe_t pipe_; }; -#define XPC_TEST_F(name) TEST_F(XPCMessageServerTest, name) { \ - if (!RunXPCTest()) \ - return; \ - -XPC_TEST_F(ReceiveMessage) // { +TEST(XPCMessageServerTest, ReceiveMessage) { BlockDemuxer fixture; XPCMessageServer* server = fixture.server(); @@ -112,7 +96,7 @@ XPC_TEST_F(ReceiveMessage) // { xpc_release(reply); } -XPC_TEST_F(RejectMessage) // { +TEST(XPCMessageServerTest, RejectMessage) { BlockDemuxer fixture; XPCMessageServer* server = fixture.server(); ASSERT_TRUE(fixture.Initialize(^(IPCMessage request) { @@ -129,7 +113,7 @@ XPC_TEST_F(RejectMessage) // { xpc_release(reply); } -XPC_TEST_F(RejectMessageSimpleRoutine) // { +TEST(XPCMessageServerTest, RejectMessageSimpleRoutine) { BlockDemuxer fixture; XPCMessageServer* server = fixture.server(); ASSERT_TRUE(fixture.Initialize(^(IPCMessage request) { @@ -145,7 +129,7 @@ XPC_TEST_F(RejectMessageSimpleRoutine) // { char kGetSenderPID[] = "org.chromium.sandbox.test.GetSenderPID"; -XPC_TEST_F(GetSenderPID) // { +TEST(XPCMessageServerTest, GetSenderPID) { BlockDemuxer fixture; XPCMessageServer* server = fixture.server(); @@ -196,7 +180,7 @@ MULTIPROCESS_TEST_MAIN(GetSenderPID) { return 0; } -XPC_TEST_F(ForwardMessage) // { +TEST(XPCMessageServerTest, ForwardMessage) { BlockDemuxer first; XPCMessageServer* first_server = first.server(); diff --git a/chromium/sandbox/win/BUILD.gn b/chromium/sandbox/win/BUILD.gn index 89eaaed703d..60bb499af3d 100644 --- a/chromium/sandbox/win/BUILD.gn +++ b/chromium/sandbox/win/BUILD.gn @@ -205,11 +205,14 @@ test("sbox_integration_tests") { "tests/common/test_utils.cc", "tests/common/test_utils.h", "tests/integration_tests/integration_tests.cc", + "tests/integration_tests/integration_tests_common.h", "tests/integration_tests/integration_tests_test.cc", ] deps = [ ":sandbox", + ":sbox_integration_test_hook_dll", + ":sbox_integration_test_win_proc", "//base/test:test_support", "//testing/gtest", ] @@ -217,6 +220,23 @@ test("sbox_integration_tests") { libs = [ "dxva2.lib" ] } +loadable_module("sbox_integration_test_hook_dll") { + sources = [ + "tests/integration_tests/hooking_dll.cc", + "tests/integration_tests/integration_tests_common.h", + ] +} + +executable("sbox_integration_test_win_proc") { + sources = [ + "tests/integration_tests/hooking_win_proc.cc", + "tests/integration_tests/integration_tests_common.h", + ] + + configs -= [ "//build/config/win:console" ] + configs += [ "//build/config/win:windowed" ] +} + test("sbox_validation_tests") { sources = [ "tests/common/controller.cc", diff --git a/chromium/sandbox/win/sandbox_win.gypi b/chromium/sandbox/win/sandbox_win.gypi index 8ac9e5909a9..e9673aa9a1b 100644 --- a/chromium/sandbox/win/sandbox_win.gypi +++ b/chromium/sandbox/win/sandbox_win.gypi @@ -197,6 +197,8 @@ 'type': 'executable', 'dependencies': [ 'sandbox', + 'sbox_integration_test_hook_dll', + 'sbox_integration_test_win_proc', '../base/base.gyp:test_support_base', '../testing/gtest.gyp:gtest', ], @@ -224,6 +226,7 @@ 'tests/common/test_utils.cc', 'tests/common/test_utils.h', 'tests/integration_tests/integration_tests.cc', + 'tests/integration_tests/integration_tests_common.h', ], 'link_settings': { 'libraries': [ @@ -232,6 +235,31 @@ }, }, { + 'target_name': 'sbox_integration_test_hook_dll', + 'type': 'shared_library', + 'dependencies': [ + ], + 'sources': [ + 'tests/integration_tests/hooking_dll.cc', + 'tests/integration_tests/integration_tests_common.h', + ], + }, + { + 'target_name': 'sbox_integration_test_win_proc', + 'type': 'executable', + 'dependencies': [ + ], + 'sources': [ + 'tests/integration_tests/hooking_win_proc.cc', + 'tests/integration_tests/integration_tests_common.h', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS + }, + }, + }, + { 'target_name': 'sbox_validation_tests', 'type': 'executable', 'dependencies': [ diff --git a/chromium/sandbox/win/src/address_sanitizer_test.cc b/chromium/sandbox/win/src/address_sanitizer_test.cc index f845ad8b325..75fb0eb6431 100644 --- a/chromium/sandbox/win/src/address_sanitizer_test.cc +++ b/chromium/sandbox/win/src/address_sanitizer_test.cc @@ -21,7 +21,7 @@ namespace sandbox { class AddressSanitizerTests : public ::testing::Test { public: void SetUp() override { - env_.reset(base::Environment::Create()); + env_ = base::Environment::Create(); had_asan_options_ = env_->GetVar("ASAN_OPTIONS", &old_asan_options_); } @@ -42,7 +42,7 @@ SBOX_TESTS_COMMAND int AddressSanitizerTests_Report(int argc, wchar_t** argv) { // AddressSanitizer should detect an out of bounds write (heap buffer // overflow) in this code. volatile int idx = 42; - int *volatile blah = new int[42]; + int* volatile blah = new int[42]; blah[idx] = 42; delete [] blah; return SBOX_TEST_FAILED; @@ -79,7 +79,7 @@ TEST_F(AddressSanitizerTests, TestAddressSanitizer) { base::FilePath exe; ASSERT_TRUE(PathService::Get(base::FILE_EXE, &exe)); base::FilePath pdb_path = exe.DirName().Append(L"*.pdb"); - ASSERT_TRUE(runner.AddFsRule(sandbox::TargetPolicy::FILES_ALLOW_READONLY, + ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, pdb_path.value().c_str())); env_->SetVar("ASAN_OPTIONS", "exitcode=123"); @@ -105,4 +105,4 @@ TEST_F(AddressSanitizerTests, TestAddressSanitizer) { } } -} +} // namespace sandbox diff --git a/chromium/sandbox/win/src/process_mitigations.cc b/chromium/sandbox/win/src/process_mitigations.cc index adcc17c9af9..1fa52094039 100644 --- a/chromium/sandbox/win/src/process_mitigations.cc +++ b/chromium/sandbox/win/src/process_mitigations.cc @@ -137,8 +137,8 @@ bool ApplyProcessMitigationsToCurrentProcess(MitigationFlags flags) { } } - // Enable dll extension policies. - if (flags & MITIGATION_EXTENSION_DLL_DISABLE) { + // Enable extension point policies. + if (flags & MITIGATION_EXTENSION_POINT_DISABLE) { PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {}; policy.DisableExtensionPoints = true; @@ -254,7 +254,7 @@ void ConvertProcessMitigationsToPolicy(MitigationFlags flags, PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON; } - if (flags & MITIGATION_EXTENSION_DLL_DISABLE) { + if (flags & MITIGATION_EXTENSION_POINT_DISABLE) { *policy_flags |= PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; } @@ -333,7 +333,7 @@ bool CanSetProcessMitigationsPostStartup(MitigationFlags flags) { MITIGATION_RELOCATE_IMAGE_REQUIRED | MITIGATION_BOTTOM_UP_ASLR | MITIGATION_STRICT_HANDLE_CHECKS | - MITIGATION_EXTENSION_DLL_DISABLE | + MITIGATION_EXTENSION_POINT_DISABLE | MITIGATION_DLL_SEARCH_ORDER | MITIGATION_HARDEN_TOKEN_IL_POLICY | MITIGATION_WIN32K_DISABLE | diff --git a/chromium/sandbox/win/src/process_mitigations_test.cc b/chromium/sandbox/win/src/process_mitigations_test.cc index 97636bcd84d..bf89a9ad987 100644 --- a/chromium/sandbox/win/src/process_mitigations_test.cc +++ b/chromium/sandbox/win/src/process_mitigations_test.cc @@ -1,36 +1,48 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright 2011 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 <initguid.h> +#include "sandbox/win/src/process_mitigations.h" + #include <d3d9.h> -#include <Opmapi.h> +#include <initguid.h> +#include <opmapi.h> +#include <psapi.h> #include <windows.h> #include <map> #include <string> +#include "base/command_line.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ref_counted.h" #include "base/path_service.h" #include "base/process/launch.h" +#include "base/scoped_native_library.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/test_timeouts.h" +#include "base/win/registry.h" #include "base/win/scoped_handle.h" +#include "base/win/startup_information.h" +#include "base/win/win_util.h" #include "base/win/windows_version.h" #include "sandbox/win/src/nt_internals.h" -#include "sandbox/win/src/process_mitigations.h" #include "sandbox/win/src/process_mitigations_win32k_policy.h" #include "sandbox/win/src/sandbox.h" #include "sandbox/win/src/sandbox_factory.h" #include "sandbox/win/src/target_services.h" -#include "sandbox/win/src/win_utils.h" #include "sandbox/win/tests/common/controller.h" +#include "sandbox/win/tests/integration_tests/integration_tests_common.h" #include "testing/gtest/include/gtest/gtest.h" namespace { +// Timeouts for synchronization. +#define event_timeout \ + static_cast<DWORD>((TestTimeouts::action_timeout()).InMillisecondsRoundedUp()) + // API defined in winbase.h. typedef decltype(GetProcessDEPPolicy)* GetProcessDEPPolicyFunction; @@ -43,6 +55,10 @@ GetProcessMitigationPolicyFunction get_process_mitigation_policy; typedef decltype(AddFontMemResourceEx)* AddFontMemResourceExFunction; typedef decltype(RemoveFontMemResourceEx)* RemoveFontMemResourceExFunction; +// APIs defined in integration_tests_common.h +typedef decltype(WasHookCalled)* WasHookCalledFunction; +typedef decltype(SetHook)* SetHookFunction; + #if !defined(_WIN64) bool CheckWin8DepPolicy() { PROCESS_MITIGATION_DEP_POLICY policy = {}; @@ -59,7 +75,7 @@ bool CheckWin8AslrPolicy() { PROCESS_MITIGATION_ASLR_POLICY policy = {}; if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessASLRPolicy, &policy, sizeof(policy))) { - return false; + return false; } return policy.EnableForceRelocateImages && policy.DisallowStrippedImages; } @@ -68,9 +84,9 @@ bool CheckWin8AslrPolicy() { bool CheckWin8StrictHandlePolicy() { PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy = {}; if (!get_process_mitigation_policy(::GetCurrentProcess(), - ProcessStrictHandleCheckPolicy, - &policy, sizeof(policy))) { - return false; + ProcessStrictHandleCheckPolicy, &policy, + sizeof(policy))) { + return false; } return policy.RaiseExceptionOnInvalidHandleReference && policy.HandleExceptionsPermanentlyEnabled; @@ -79,19 +95,19 @@ bool CheckWin8StrictHandlePolicy() { bool CheckWin8Win32CallPolicy() { PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {}; if (!get_process_mitigation_policy(::GetCurrentProcess(), - ProcessSystemCallDisablePolicy, - &policy, sizeof(policy))) { - return false; + ProcessSystemCallDisablePolicy, &policy, + sizeof(policy))) { + return false; } return policy.DisallowWin32kSystemCalls; } -bool CheckWin8DllExtensionPolicy() { +bool CheckWin8ExtensionPointPolicy() { PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {}; if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessExtensionPointDisablePolicy, &policy, sizeof(policy))) { - return false; + return false; } return policy.DisableExtensionPoints; } @@ -116,8 +132,309 @@ bool CheckWin10ImageLoadNoRemotePolicy() { return policy.NoRemoteImages; } +// Spawn Windows process (with or without mitigation enabled). +bool SpawnWinProc(PROCESS_INFORMATION* pi, bool success_test, HANDLE* event) { + base::win::StartupInformation startup_info; + DWORD creation_flags = 0; + + if (!success_test) { + DWORD64 flags = + PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; + // This test only runs on >= Win8, so don't have to handle + // illegal 64-bit flags on 32-bit <= Win7. + size_t flags_size = sizeof(flags); + + if (!startup_info.InitializeProcThreadAttributeList(1) || + !startup_info.UpdateProcThreadAttribute( + PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &flags, flags_size)) { + ADD_FAILURE(); + return false; + } + creation_flags = EXTENDED_STARTUPINFO_PRESENT; + } + + // Command line must be writable. + base::string16 cmd_writeable(g_winproc_file); + + if (!::CreateProcessW(NULL, &cmd_writeable[0], NULL, NULL, FALSE, + creation_flags, NULL, NULL, startup_info.startup_info(), + pi)) { + ADD_FAILURE(); + return false; + } + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(*event, event_timeout)); + + return true; +} + +//------------------------------------------------------------------------------ +// 1. Spawn a Windows process (with or without mitigation enabled). +// 2. Load the hook Dll locally. +// 3. Create a global named event for the hook to trigger. +// 4. Start the hook (for the specific WinProc or globally). +// 5. Send a keystroke event. +// 6. Ask the hook Dll if it received a hook callback. +// 7. Cleanup the hooking. +// 8. Signal the Windows process to shutdown. +// +// Do NOT use any ASSERTs in this function. Cleanup required. +//------------------------------------------------------------------------------ +void TestWin8ExtensionPointHookWrapper(bool is_success_test, bool global_hook) { + // Set up a couple global events that this test will use. + HANDLE winproc_event = ::CreateEventW(NULL, FALSE, FALSE, g_winproc_event); + if (winproc_event == NULL || winproc_event == INVALID_HANDLE_VALUE) { + ADD_FAILURE(); + return; + } + base::win::ScopedHandle scoped_winproc_event(winproc_event); + + HANDLE hook_event = ::CreateEventW(NULL, FALSE, FALSE, g_hook_event); + if (hook_event == NULL || hook_event == INVALID_HANDLE_VALUE) { + ADD_FAILURE(); + return; + } + base::win::ScopedHandle scoped_hook_event(hook_event); + + // 1. Spawn WinProc. + PROCESS_INFORMATION proc_info = {}; + if (!SpawnWinProc(&proc_info, is_success_test, &winproc_event)) + return; + + // From this point on, no return on failure. Cleanup required. + bool all_good = true; + + // 2. Load the hook DLL. + base::FilePath hook_dll_path(g_hook_dll_file); + base::ScopedNativeLibrary dll(hook_dll_path); + EXPECT_TRUE(dll.is_valid()); + + HOOKPROC hook_proc = + reinterpret_cast<HOOKPROC>(dll.GetFunctionPointer(g_hook_handler_func)); + WasHookCalledFunction was_hook_called = + reinterpret_cast<WasHookCalledFunction>( + dll.GetFunctionPointer(g_was_hook_called_func)); + SetHookFunction set_hook = reinterpret_cast<SetHookFunction>( + dll.GetFunctionPointer(g_set_hook_func)); + if (!hook_proc || !was_hook_called || !set_hook) { + ADD_FAILURE(); + all_good = false; + } + + // 3. Try installing the hook (either on a remote target thread, + // or globally). + HHOOK hook = nullptr; + if (all_good) { + DWORD target = 0; + if (!global_hook) + target = proc_info.dwThreadId; + hook = ::SetWindowsHookExW(WH_KEYBOARD, hook_proc, dll.get(), target); + if (!hook) { + ADD_FAILURE(); + all_good = false; + } else + // Pass the hook DLL the hook handle. + set_hook(hook); + } + + // 4. Inject a keyboard event. + if (all_good) { + // Note: that PostThreadMessage and SendMessage APIs will not deliver + // a keystroke in such a way that triggers a "legitimate" hook. + // Have to use targetless SendInput or keybd_event. The latter is + // less code and easier to work with. + keybd_event(VkKeyScan(L'A'), 0, 0, 0); + keybd_event(VkKeyScan(L'A'), 0, KEYEVENTF_KEYUP, 0); + // Give it a chance to hit the hook handler... + ::WaitForSingleObject(hook_event, event_timeout); + + // 5. Did the hook get hit? Was it expected to? + if (global_hook) + EXPECT_EQ((is_success_test ? true : false), was_hook_called()); + else + // ***IMPORTANT: when targeting a specific thread id, the + // PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE + // mitigation does NOT disable the hook API. It ONLY + // stops global hooks from running in a process. Hence, + // the hook will hit (TRUE) even in the "failure" + // case for a non-global/targeted hook. + EXPECT_EQ((is_success_test ? true : true), was_hook_called()); + } + + // 6. Disable hook. + if (hook) + EXPECT_TRUE(::UnhookWindowsHookEx(hook)); + + // 7. Trigger shutdown of WinProc. + if (proc_info.hProcess) { + if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) { + // Note: The combination/perfect-storm of a Global Hook, in a + // WinProc that has the EXTENSION_POINT_DISABLE mitigation ON, and the + // use of the SendInput or keybd_event API to inject a keystroke, + // results in the target becoming unresponsive. If any one of these + // states are changed, the problem does not occur. This means the WM_QUIT + // message is not handled and the call to WaitForSingleObject times out. + // Therefore not checking the return val. + ::WaitForSingleObject(winproc_event, event_timeout); + } else { + // Ensure no strays. + ::TerminateProcess(proc_info.hProcess, 0); + ADD_FAILURE(); + } + EXPECT_TRUE(::CloseHandle(proc_info.hThread)); + EXPECT_TRUE(::CloseHandle(proc_info.hProcess)); + } +} + +//------------------------------------------------------------------------------ +// 1. Set up the AppInit Dll in registry settings. (Enable) +// 2. Spawn a Windows process (with or without mitigation enabled). +// 3. Check if the AppInit Dll got loaded in the Windows process or not. +// 4. Signal the Windows process to shutdown. +// 5. Restore original reg settings. +// +// Do NOT use any ASSERTs in this function. Cleanup required. +//------------------------------------------------------------------------------ +void TestWin8ExtensionPointAppInitWrapper(bool is_success_test) { + // 0.5 Get path of current module. The appropriate build of the + // AppInit DLL will be in the same directory (and the + // full path is needed for reg). + wchar_t path[MAX_PATH]; + if (!::GetModuleFileNameW(NULL, path, MAX_PATH)) { + ADD_FAILURE(); + return; + } + // Only want the directory. Switch file name for the AppInit DLL. + base::FilePath full_dll_path(path); + full_dll_path = full_dll_path.DirName(); + full_dll_path = full_dll_path.Append(g_hook_dll_file); + wchar_t* non_const = const_cast<wchar_t*>(full_dll_path.value().c_str()); + // Now make sure the path is in "short-name" form for registry. + DWORD length = ::GetShortPathNameW(non_const, NULL, 0); + std::vector<wchar_t> short_name(length); + if (!::GetShortPathNameW(non_const, &short_name[0], length)) { + ADD_FAILURE(); + return; + } + + // 1. Reg setup. + const wchar_t* app_init_reg_path = + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows"; + const wchar_t* dlls_value_name = L"AppInit_DLLs"; + const wchar_t* enabled_value_name = L"LoadAppInit_DLLs"; + const wchar_t* signing_value_name = L"RequireSignedAppInit_DLLs"; + std::wstring orig_dlls; + std::wstring new_dlls; + DWORD orig_enabled_value = 0; + DWORD orig_signing_value = 0; + base::win::RegKey app_init_key(HKEY_LOCAL_MACHINE, app_init_reg_path, + KEY_QUERY_VALUE | KEY_SET_VALUE); + // Backup the existing settings. + if (!app_init_key.Valid() || !app_init_key.HasValue(dlls_value_name) || + !app_init_key.HasValue(enabled_value_name) || + ERROR_SUCCESS != app_init_key.ReadValue(dlls_value_name, &orig_dlls) || + ERROR_SUCCESS != + app_init_key.ReadValueDW(enabled_value_name, &orig_enabled_value)) { + ADD_FAILURE(); + return; + } + if (app_init_key.HasValue(signing_value_name)) { + if (ERROR_SUCCESS != + app_init_key.ReadValueDW(signing_value_name, &orig_signing_value)) { + ADD_FAILURE(); + return; + } + } + + // Set the new settings (obviously requires local admin privileges). + new_dlls = orig_dlls; + if (!orig_dlls.empty()) + new_dlls.append(L","); + new_dlls.append(short_name.data()); + + // From this point on, no return on failure. Cleanup required. + bool all_good = true; + + if (app_init_key.HasValue(signing_value_name)) { + if (ERROR_SUCCESS != + app_init_key.WriteValue(signing_value_name, static_cast<DWORD>(0))) { + ADD_FAILURE(); + all_good = false; + } + } + if (ERROR_SUCCESS != + app_init_key.WriteValue(dlls_value_name, new_dlls.c_str()) || + ERROR_SUCCESS != + app_init_key.WriteValue(enabled_value_name, static_cast<DWORD>(1))) { + ADD_FAILURE(); + all_good = false; + } + + // 2. Spawn WinProc. + HANDLE winproc_event = INVALID_HANDLE_VALUE; + base::win::ScopedHandle scoped_event; + PROCESS_INFORMATION proc_info = {}; + if (all_good) { + winproc_event = ::CreateEventW(NULL, FALSE, FALSE, g_winproc_event); + if (winproc_event == NULL || winproc_event == INVALID_HANDLE_VALUE) { + ADD_FAILURE(); + all_good = false; + } else { + scoped_event.Set(winproc_event); + if (!SpawnWinProc(&proc_info, is_success_test, &winproc_event)) + all_good = false; + } + } + + // 3. Check loaded modules in WinProc to see if the AppInit dll is loaded. + bool dll_loaded = false; + if (all_good) { + std::vector<HMODULE>(modules); + if (!base::win::GetLoadedModulesSnapshot(proc_info.hProcess, &modules)) { + ADD_FAILURE(); + all_good = false; + } else { + for (auto module : modules) { + wchar_t name[MAX_PATH] = {}; + if (::GetModuleFileNameExW(proc_info.hProcess, module, name, + MAX_PATH) && + ::wcsstr(name, g_hook_dll_file)) { + // Found it. + dll_loaded = true; + break; + } + } + } + } + + // Was the test result as expected? + if (all_good) + EXPECT_EQ((is_success_test ? true : false), dll_loaded); + + // 4. Trigger shutdown of WinProc. + if (proc_info.hProcess) { + if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) { + ::WaitForSingleObject(winproc_event, event_timeout); + } else { + // Ensure no strays. + ::TerminateProcess(proc_info.hProcess, 0); + ADD_FAILURE(); + } + EXPECT_TRUE(::CloseHandle(proc_info.hThread)); + EXPECT_TRUE(::CloseHandle(proc_info.hProcess)); + } + + // 5. Reg Restore + EXPECT_EQ(ERROR_SUCCESS, + app_init_key.WriteValue(enabled_value_name, orig_enabled_value)); + if (app_init_key.HasValue(signing_value_name)) + EXPECT_EQ(ERROR_SUCCESS, + app_init_key.WriteValue(signing_value_name, orig_signing_value)); + EXPECT_EQ(ERROR_SUCCESS, + app_init_key.WriteValue(dlls_value_name, orig_dlls.c_str())); +} + void TestWin10ImageLoadRemote(bool is_success_test) { - // ***Insert your manual testing share UNC path here! + // ***Insert a manual testing share UNC path here! // E.g.: \\\\hostname\\sharename\\calc.exe std::wstring unc = L"\"\\\\hostname\\sharename\\calc.exe\""; @@ -526,17 +843,15 @@ SBOX_TESTS_COMMAND int TestChildProcess(int argc, wchar_t** argv) { //------------------------------------------------------------------------------ // Win8 Checks: // MITIGATION_DEP(_NO_ATL_THUNK) -// MITIGATION_EXTENSION_DLL_DISABLE // MITIGATION_RELOCATE_IMAGE(_REQUIRED) - ASLR, release only // MITIGATION_STRICT_HANDLE_CHECKS // >= Win8 //------------------------------------------------------------------------------ -SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { +SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t** argv) { get_process_mitigation_policy = - reinterpret_cast<GetProcessMitigationPolicyFunction>( - ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), - "GetProcessMitigationPolicy")); + reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( + ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); if (!get_process_mitigation_policy) return SBOX_TEST_NOT_FOUND; @@ -553,9 +868,6 @@ SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { if (!CheckWin8StrictHandlePolicy()) return SBOX_TEST_THIRD_ERROR; - if (!CheckWin8DllExtensionPolicy()) - return SBOX_TEST_FIFTH_ERROR; - return SBOX_TEST_SUCCEEDED; } @@ -566,12 +878,10 @@ TEST(ProcessMitigationsTest, CheckWin8) { TestRunner runner; sandbox::TargetPolicy* policy = runner.GetPolicy(); - sandbox::MitigationFlags mitigations = MITIGATION_DEP | - MITIGATION_DEP_NO_ATL_THUNK | - MITIGATION_EXTENSION_DLL_DISABLE; + sandbox::MitigationFlags mitigations = + MITIGATION_DEP | MITIGATION_DEP_NO_ATL_THUNK; #if defined(NDEBUG) // ASLR cannot be forced in debug builds. - mitigations |= MITIGATION_RELOCATE_IMAGE | - MITIGATION_RELOCATE_IMAGE_REQUIRED; + mitigations |= MITIGATION_RELOCATE_IMAGE | MITIGATION_RELOCATE_IMAGE_REQUIRED; #endif EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK); @@ -588,17 +898,16 @@ TEST(ProcessMitigationsTest, CheckWin8) { // < Win8 x86 //------------------------------------------------------------------------------ -SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t **argv) { +SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t** argv) { GetProcessDEPPolicyFunction get_process_dep_policy = - reinterpret_cast<GetProcessDEPPolicyFunction>( - ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), - "GetProcessDEPPolicy")); + reinterpret_cast<GetProcessDEPPolicyFunction>(::GetProcAddress( + ::GetModuleHandleW(L"kernel32.dll"), "GetProcessDEPPolicy")); if (get_process_dep_policy) { BOOL is_permanent = FALSE; DWORD dep_flags = 0; if (!get_process_dep_policy(::GetCurrentProcess(), &dep_flags, - &is_permanent)) { + &is_permanent)) { return SBOX_TEST_FIRST_ERROR; } @@ -608,7 +917,7 @@ SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t **argv) { } else { NtQueryInformationProcessFunction query_information_process = NULL; ResolveNTFunctionPtr("NtQueryInformationProcess", - &query_information_process); + &query_information_process); if (!query_information_process) return SBOX_TEST_NOT_FOUND; @@ -624,8 +933,8 @@ SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t **argv) { static const int MEM_EXECUTE_OPTION_PERMANENT = 8; dep_flags &= 0xff; - if (dep_flags != (MEM_EXECUTE_OPTION_DISABLE | - MEM_EXECUTE_OPTION_PERMANENT)) { + if (dep_flags != + (MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_PERMANENT)) { return SBOX_TEST_FOURTH_ERROR; } } @@ -641,10 +950,9 @@ TEST(ProcessMitigationsTest, CheckDep) { TestRunner runner; sandbox::TargetPolicy* policy = runner.GetPolicy(); - EXPECT_EQ(policy->SetProcessMitigations( - MITIGATION_DEP | - MITIGATION_DEP_NO_ATL_THUNK | - MITIGATION_SEHOP), + EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_DEP | + MITIGATION_DEP_NO_ATL_THUNK | + MITIGATION_SEHOP), SBOX_ALL_OK); EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDep")); } @@ -655,11 +963,10 @@ TEST(ProcessMitigationsTest, CheckDep) { // >= Win8 //------------------------------------------------------------------------------ -SBOX_TESTS_COMMAND int CheckWin8Lockdown(int argc, wchar_t **argv) { +SBOX_TESTS_COMMAND int CheckWin8Lockdown(int argc, wchar_t** argv) { get_process_mitigation_policy = - reinterpret_cast<GetProcessMitigationPolicyFunction>( - ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), - "GetProcessMitigationPolicy")); + reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( + ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); if (!get_process_mitigation_policy) return SBOX_TEST_NOT_FOUND; @@ -1029,6 +1336,158 @@ TEST(ProcessMitigationsTest, CheckWin8Win32KRedirection) { } //------------------------------------------------------------------------------ +// Disable extension points (MITIGATION_EXTENSION_POINT_DISABLE). +// >= Win8 +//------------------------------------------------------------------------------ +SBOX_TESTS_COMMAND int CheckWin8ExtensionPointSetting(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 (!CheckWin8ExtensionPointPolicy()) + return SBOX_TEST_FIRST_ERROR; + return SBOX_TEST_SUCCEEDED; +} + +// This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE +// mitigation enables the setting on a process. +TEST(ProcessMitigationsTest, CheckWin8ExtensionPointPolicySuccess) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + TestRunner runner; + sandbox::TargetPolicy* policy = runner.GetPolicy(); + + EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_EXTENSION_POINT_DISABLE), + SBOX_ALL_OK); + EXPECT_EQ(SBOX_TEST_SUCCEEDED, + runner.RunTest(L"CheckWin8ExtensionPointSetting")); +} + +// This test validates that a "legitimate" global hook CAN be set on the +// sandboxed proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE +// mitigation is not set. +// +// MANUAL testing only. +TEST(ProcessMitigationsTest, + DISABLED_CheckWin8ExtensionPoint_GlobalHook_Success) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + // (is_success_test, global_hook) + TestWin8ExtensionPointHookWrapper(true, true); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +// This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE +// mitigation prevents a global hook on WinProc. +// +// MANUAL testing only. +TEST(ProcessMitigationsTest, + DISABLED_CheckWin8ExtensionPoint_GlobalHook_Failure) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + // (is_success_test, global_hook) + TestWin8ExtensionPointHookWrapper(false, true); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +// This test validates that a "legitimate" hook CAN be set on the sandboxed +// proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. +// +// MANUAL testing only. +TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_Hook_Success) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + // (is_success_test, global_hook) + TestWin8ExtensionPointHookWrapper(true, false); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +// *** Important: MITIGATION_EXTENSION_POINT_DISABLE does NOT prevent +// hooks targetted at a specific thread id. It only prevents +// global hooks. So this test does NOT actually expect the hook +// to fail (see TestWin8ExtensionPointHookWrapper function) even +// with the mitigation on. +// +// MANUAL testing only. +TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_Hook_Failure) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + // (is_success_test, global_hook) + TestWin8ExtensionPointHookWrapper(false, false); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +// This test validates that an AppInit Dll CAN be added to a target +// WinProc if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. +// +// MANUAL testing only. +// Must run this test as admin/elevated. +TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_AppInit_Success) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + TestWin8ExtensionPointAppInitWrapper(true); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +// This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE +// mitigation prevents the loading of any AppInit Dll into WinProc. +// +// MANUAL testing only. +// Must run this test as admin/elevated. +TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_AppInit_Failure) { + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return; + + HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); + EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); + EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); + + TestWin8ExtensionPointAppInitWrapper(false); + + EXPECT_TRUE(::ReleaseMutex(mutex)); + EXPECT_TRUE(::CloseHandle(mutex)); +} + +//------------------------------------------------------------------------------ // Disable non-system font loads (MITIGATION_NONSYSTEM_FONT_DISABLE) // >= Win10 //------------------------------------------------------------------------------ @@ -1193,7 +1652,7 @@ TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoRemotePolicySuccess) { // a remote UNC device, if the MITIGATION_IMAGE_LOAD_NO_REMOTE // mitigation is NOT set. // -// DISABLED for automated testing bots. Enable for manual testing. +// MANUAL testing only. TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteSuccess) { if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) return; @@ -1205,7 +1664,7 @@ TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteSuccess) { // mitigation prevents creating a new process from a remote // UNC device. // -// DISABLED for automated testing bots. Enable for manual testing. +// MANUAL testing only. TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteFailure) { if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) return; diff --git a/chromium/sandbox/win/src/security_level.h b/chromium/sandbox/win/src/security_level.h index 87abdebad57..d8524c1facc 100644 --- a/chromium/sandbox/win/src/security_level.h +++ b/chromium/sandbox/win/src/security_level.h @@ -187,10 +187,14 @@ const MitigationFlags MITIGATION_STRICT_HANDLE_CHECKS = 0x00000100; // PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON. const MitigationFlags MITIGATION_WIN32K_DISABLE = 0x00000200; -// Disables common DLL injection methods (e.g. window hooks and -// App_InitDLLs). Corresponds to +// Prevents certain built-in third party extension points from being used. +// - App_Init DLLs +// - Winsock Layered Service Providers (LSPs) +// - Global Windows Hooks (NOT thread-targeted hooks) +// - Legacy Input Method Editors (IMEs). +// I.e.: Disable legacy hooking mechanisms. Corresponds to // PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON. -const MitigationFlags MITIGATION_EXTENSION_DLL_DISABLE = 0x00000400; +const MitigationFlags MITIGATION_EXTENSION_POINT_DISABLE = 0x00000400; // Prevents the process from loading non-system fonts into GDI. // Corresponds to |