michael@0: // Copyright (c) 2011 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "base/strings/stringprintf.h" michael@0: #include "base/win/scoped_handle.h" michael@0: michael@0: #include "base/win/windows_version.h" michael@0: #include "sandbox/win/src/nt_internals.h" michael@0: #include "sandbox/win/src/process_mitigations.h" michael@0: #include "sandbox/win/src/sandbox.h" michael@0: #include "sandbox/win/src/sandbox_factory.h" michael@0: #include "sandbox/win/src/sandbox_utils.h" michael@0: #include "sandbox/win/src/target_services.h" michael@0: #include "sandbox/win/src/win_utils.h" michael@0: #include "sandbox/win/tests/common/controller.h" michael@0: #include "testing/gtest/include/gtest/gtest.h" michael@0: michael@0: namespace { michael@0: michael@0: typedef BOOL (WINAPI *GetProcessDEPPolicyFunction)( michael@0: HANDLE process, michael@0: LPDWORD flags, michael@0: PBOOL permanent); michael@0: michael@0: typedef BOOL (WINAPI *GetProcessMitigationPolicyFunction)( michael@0: HANDLE process, michael@0: PROCESS_MITIGATION_POLICY mitigation_policy, michael@0: PVOID buffer, michael@0: SIZE_T length); michael@0: michael@0: GetProcessMitigationPolicyFunction get_process_mitigation_policy; michael@0: michael@0: bool CheckWin8DepPolicy() { michael@0: PROCESS_MITIGATION_DEP_POLICY policy; michael@0: if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy, michael@0: &policy, sizeof(policy))) { michael@0: return false; michael@0: } michael@0: return policy.Enable && policy.Permanent; michael@0: } michael@0: michael@0: bool CheckWin8AslrPolicy() { michael@0: PROCESS_MITIGATION_ASLR_POLICY policy; michael@0: if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessASLRPolicy, michael@0: &policy, sizeof(policy))) { michael@0: return false; michael@0: } michael@0: return policy.EnableForceRelocateImages && policy.DisallowStrippedImages; michael@0: } michael@0: michael@0: bool CheckWin8StrictHandlePolicy() { michael@0: PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy; michael@0: if (!get_process_mitigation_policy(::GetCurrentProcess(), michael@0: ProcessStrictHandleCheckPolicy, michael@0: &policy, sizeof(policy))) { michael@0: return false; michael@0: } michael@0: return policy.RaiseExceptionOnInvalidHandleReference && michael@0: policy.HandleExceptionsPermanentlyEnabled; michael@0: } michael@0: michael@0: bool CheckWin8Win32CallPolicy() { michael@0: PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy; michael@0: if (!get_process_mitigation_policy(::GetCurrentProcess(), michael@0: ProcessSystemCallDisablePolicy, michael@0: &policy, sizeof(policy))) { michael@0: return false; michael@0: } michael@0: return policy.DisallowWin32kSystemCalls; michael@0: } michael@0: michael@0: bool CheckWin8DllExtensionPolicy() { michael@0: PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy; michael@0: if (!get_process_mitigation_policy(::GetCurrentProcess(), michael@0: ProcessExtensionPointDisablePolicy, michael@0: &policy, sizeof(policy))) { michael@0: return false; michael@0: } michael@0: return policy.DisableExtensionPoints; michael@0: } michael@0: michael@0: } // namespace michael@0: michael@0: namespace sandbox { michael@0: michael@0: SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { michael@0: get_process_mitigation_policy = michael@0: reinterpret_cast( michael@0: ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), michael@0: "GetProcessMitigationPolicy")); michael@0: michael@0: if (!get_process_mitigation_policy) michael@0: return SBOX_TEST_NOT_FOUND; michael@0: michael@0: if (!CheckWin8DepPolicy()) michael@0: return SBOX_TEST_FIRST_ERROR; michael@0: michael@0: #if defined(NDEBUG) // ASLR cannot be forced in debug builds. michael@0: if (!CheckWin8AslrPolicy()) michael@0: return SBOX_TEST_SECOND_ERROR; michael@0: #endif michael@0: michael@0: if (!CheckWin8StrictHandlePolicy()) michael@0: return SBOX_TEST_THIRD_ERROR; michael@0: michael@0: if (!CheckWin8Win32CallPolicy()) michael@0: return SBOX_TEST_FOURTH_ERROR; michael@0: michael@0: if (!CheckWin8DllExtensionPolicy()) michael@0: return SBOX_TEST_FIFTH_ERROR; michael@0: michael@0: return SBOX_TEST_SUCCEEDED; michael@0: } michael@0: michael@0: TEST(ProcessMitigationsTest, CheckWin8) { michael@0: if (base::win::GetVersion() < base::win::VERSION_WIN8) michael@0: return; michael@0: michael@0: TestRunner runner; michael@0: sandbox::TargetPolicy* policy = runner.GetPolicy(); michael@0: michael@0: sandbox::MitigationFlags mitigations = MITIGATION_DEP | michael@0: MITIGATION_DEP_NO_ATL_THUNK | michael@0: MITIGATION_EXTENSION_DLL_DISABLE; michael@0: #if defined(NDEBUG) // ASLR cannot be forced in debug builds. michael@0: mitigations |= MITIGATION_RELOCATE_IMAGE | michael@0: MITIGATION_RELOCATE_IMAGE_REQUIRED; michael@0: #endif michael@0: michael@0: EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK); michael@0: michael@0: mitigations |= MITIGATION_STRICT_HANDLE_CHECKS | michael@0: MITIGATION_WIN32K_DISABLE; michael@0: michael@0: EXPECT_EQ(policy->SetDelayedProcessMitigations(mitigations), SBOX_ALL_OK); michael@0: michael@0: EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8")); michael@0: } michael@0: michael@0: michael@0: SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t **argv) { michael@0: GetProcessDEPPolicyFunction get_process_dep_policy = michael@0: reinterpret_cast( michael@0: ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), michael@0: "GetProcessDEPPolicy")); michael@0: if (get_process_dep_policy) { michael@0: BOOL is_permanent = FALSE; michael@0: DWORD dep_flags = 0; michael@0: michael@0: if (!get_process_dep_policy(::GetCurrentProcess(), &dep_flags, michael@0: &is_permanent)) { michael@0: return SBOX_TEST_FIRST_ERROR; michael@0: } michael@0: michael@0: if (!(dep_flags & PROCESS_DEP_ENABLE) || !is_permanent) michael@0: return SBOX_TEST_SECOND_ERROR; michael@0: michael@0: } else { michael@0: NtQueryInformationProcessFunction query_information_process = NULL; michael@0: ResolveNTFunctionPtr("NtQueryInformationProcess", michael@0: &query_information_process); michael@0: if (!query_information_process) michael@0: return SBOX_TEST_NOT_FOUND; michael@0: michael@0: ULONG size = 0; michael@0: ULONG dep_flags = 0; michael@0: if (!SUCCEEDED(query_information_process(::GetCurrentProcess(), michael@0: ProcessExecuteFlags, &dep_flags, michael@0: sizeof(dep_flags), &size))) { michael@0: return SBOX_TEST_THIRD_ERROR; michael@0: } michael@0: michael@0: const int MEM_EXECUTE_OPTION_ENABLE = 1; michael@0: const int MEM_EXECUTE_OPTION_DISABLE = 2; michael@0: const int MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION = 4; michael@0: const int MEM_EXECUTE_OPTION_PERMANENT = 8; michael@0: dep_flags &= 0xff; michael@0: michael@0: if (dep_flags != (MEM_EXECUTE_OPTION_DISABLE | michael@0: MEM_EXECUTE_OPTION_PERMANENT)) { michael@0: return SBOX_TEST_FOURTH_ERROR; michael@0: } michael@0: } michael@0: michael@0: return SBOX_TEST_SUCCEEDED; michael@0: } michael@0: michael@0: #if !defined(_WIN64) // DEP is always enabled on 64-bit. michael@0: TEST(ProcessMitigationsTest, CheckDep) { michael@0: if (!IsXPSP2OrLater() || base::win::GetVersion() > base::win::VERSION_WIN7) michael@0: return; michael@0: michael@0: TestRunner runner; michael@0: sandbox::TargetPolicy* policy = runner.GetPolicy(); michael@0: michael@0: EXPECT_EQ(policy->SetProcessMitigations( michael@0: MITIGATION_DEP | michael@0: MITIGATION_DEP_NO_ATL_THUNK | michael@0: MITIGATION_SEHOP), michael@0: SBOX_ALL_OK); michael@0: EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDep")); michael@0: } michael@0: #endif michael@0: michael@0: } // namespace sandbox michael@0: