Commit 661bc439 authored by pennymac's avatar pennymac Committed by Commit Bot

[Windows Sandbox Tests] Re-format process mitigation tests.

- Rename process_mitigations_test.cc -> process_mitigations_unittest.cc
- Pull large chunks out of process_mitigations_unittest.cc into unittest
files of their own.  The size was getting way out of hand.
- New files for existing tests: extensionpoints, imageload, win32k.
- NO new functionality tests in this CL - only re-organized things:
  - Note: the existing tests for every process mitigation that just check policy
	enabling have been centralized into one single test target function
	(SBOX_TESTS_COMMAND) called CheckPolicy.  Any new mitigation checks
	should be added here as well.
  - Note: The individual mitigation TESTs that trigger "CheckPolicy" have been
	adjusted to ensure we test both pre and post child-process startup wherever
	they are supported.

TEST= sbox_integration_tests.exe, ProcessMitigationsTest.*
BUG=733739
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.win:win10_chromium_x64_rel_ng
TBR=forshaw,wfh

Review-Url: https://codereview.chromium.org/2944493002
Cr-Commit-Position: refs/heads/master@{#485387}
parent 39242679
...@@ -182,7 +182,10 @@ test("sbox_integration_tests") { ...@@ -182,7 +182,10 @@ test("sbox_integration_tests") {
"src/lpc_policy_test.cc", "src/lpc_policy_test.cc",
"src/named_pipe_policy_test.cc", "src/named_pipe_policy_test.cc",
"src/policy_target_test.cc", "src/policy_target_test.cc",
"src/process_mitigations_test.cc", "src/process_mitigations_extensionpoints_unittest.cc",
"src/process_mitigations_imageload_unittest.cc",
"src/process_mitigations_unittest.cc",
"src/process_mitigations_win32k_unittest.cc",
"src/process_policy_test.cc", "src/process_policy_test.cc",
"src/registry_policy_test.cc", "src/registry_policy_test.cc",
"src/restricted_token_test.cc", "src/restricted_token_test.cc",
...@@ -228,14 +231,14 @@ executable("cfi_unittest_exe") { ...@@ -228,14 +231,14 @@ executable("cfi_unittest_exe") {
loadable_module("sbox_integration_test_hook_dll") { loadable_module("sbox_integration_test_hook_dll") {
sources = [ sources = [
"tests/integration_tests/hooking_dll.cc", "tests/integration_tests/hooking_dll.cc",
"tests/integration_tests/integration_tests_common.h", "tests/integration_tests/hooking_dll.h",
] ]
} }
executable("sbox_integration_test_win_proc") { executable("sbox_integration_test_win_proc") {
sources = [ sources = [
"tests/integration_tests/hooking_win_proc.cc", "tests/integration_tests/hooking_win_proc.cc",
"tests/integration_tests/integration_tests_common.h", "tests/integration_tests/hooking_win_proc.h",
] ]
configs -= [ "//build/config/win:console" ] configs -= [ "//build/config/win:console" ]
......
// Copyright 2017 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.h"
#include <windows.h>
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
#include "base/scoped_native_library.h"
#include "base/strings/stringprintf.h"
#include "base/test/test_timeouts.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/target_services.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 {
//------------------------------------------------------------------------------
// Internal Defines & Functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// ImageLoadRemote test helper function.
//
// Trigger test child process (with or without mitigation enabled).
//------------------------------------------------------------------------------
void TestWin10ImageLoadRemote(bool is_success_test) {
// ***Insert a manual testing share UNC path here!
// E.g.: \\\\hostname\\sharename\\calc.exe
base::string16 unc = L"\"\\\\hostname\\sharename\\calc.exe\"";
sandbox::TestRunner runner;
sandbox::TargetPolicy* policy = runner.GetPolicy();
// Set a policy that would normally allow for process creation.
policy->SetJobLevel(sandbox::JOB_NONE, 0);
policy->SetTokenLevel(sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED);
runner.SetDisableCsrss(false);
if (!is_success_test) {
// Enable the NoRemote mitigation.
EXPECT_EQ(policy->SetDelayedProcessMitigations(
sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE),
sandbox::SBOX_ALL_OK);
}
base::string16 test = L"TestChildProcess ";
test += unc.c_str();
EXPECT_EQ((is_success_test ? sandbox::SBOX_TEST_SUCCEEDED
: sandbox::SBOX_TEST_FAILED),
runner.RunTest(test.c_str()));
}
//------------------------------------------------------------------------------
// ImageLoadLow test helper function.
//
// 1. Set up a copy of calc, using icacls to make it low integrity.
// 2. Trigger test child process (with or without mitigation enabled).
//------------------------------------------------------------------------------
void TestWin10ImageLoadLowLabel(bool is_success_test) {
// Setup a mandatory low executable for this test (calc.exe).
// If anything fails during setup, ASSERT to end test.
base::FilePath orig_path;
ASSERT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &orig_path));
orig_path = orig_path.Append(L"calc.exe");
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath new_path = temp_dir.GetPath();
new_path = new_path.Append(L"lowIL_calc.exe");
// Test file will be cleaned up by the ScopedTempDir.
ASSERT_TRUE(base::CopyFileW(orig_path, new_path));
base::string16 cmd_line = L"icacls \"";
cmd_line += new_path.value().c_str();
cmd_line += L"\" /setintegritylevel Low";
base::LaunchOptions options = base::LaunchOptionsForTest();
base::Process setup_proc = base::LaunchProcess(cmd_line.c_str(), options);
ASSERT_TRUE(setup_proc.IsValid());
int exit_code = 1;
if (!setup_proc.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
&exit_code)) {
// Might have timed out, or might have failed.
// Terminate to make sure we clean up any mess.
setup_proc.Terminate(0, false);
ASSERT_TRUE(false);
}
// Make sure icacls was successful.
ASSERT_EQ(0, exit_code);
sandbox::TestRunner runner;
sandbox::TargetPolicy* policy = runner.GetPolicy();
// Set a policy that would normally allow for process creation.
policy->SetJobLevel(sandbox::JOB_NONE, 0);
policy->SetTokenLevel(sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED);
runner.SetDisableCsrss(false);
if (!is_success_test) {
// Enable the NoLowLabel mitigation.
EXPECT_EQ(policy->SetDelayedProcessMitigations(
sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL),
sandbox::SBOX_ALL_OK);
}
base::string16 test = L"TestChildProcess \"";
test += new_path.value().c_str();
test += L"\" false";
EXPECT_EQ((is_success_test ? sandbox::SBOX_TEST_SUCCEEDED
: sandbox::SBOX_TEST_FAILED),
runner.RunTest(test.c_str()));
}
} // namespace
namespace sandbox {
//------------------------------------------------------------------------------
// Exported Image Load Tests
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Disable image load from remote devices (MITIGATION_IMAGE_LOAD_NO_REMOTE).
// >= Win10_TH2
//------------------------------------------------------------------------------
// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE
// mitigation enables the setting on a process.
TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoRemotePolicySuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
return;
base::string16 test_command = L"CheckPolicy ";
test_command += std::to_wstring(TESTPOLICY_LOADNOREMOTE);
//---------------------------------
// 1) Test setting pre-startup.
//---------------------------------
TestRunner runner;
sandbox::TargetPolicy* policy = runner.GetPolicy();
EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE),
SBOX_ALL_OK);
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str()));
//---------------------------------
// 2) Test setting post-startup.
//---------------------------------
TestRunner runner2;
sandbox::TargetPolicy* policy2 = runner2.GetPolicy();
EXPECT_EQ(
policy2->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE),
SBOX_ALL_OK);
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str()));
}
// This test validates that we CAN create a new process from
// a remote UNC device, if the MITIGATION_IMAGE_LOAD_NO_REMOTE
// mitigation is NOT set.
//
// MANUAL testing only.
TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
return;
TestWin10ImageLoadRemote(true);
}
// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE
// mitigation prevents creating a new process from a remote
// UNC device.
//
// MANUAL testing only.
TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteFailure) {
if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
return;
TestWin10ImageLoadRemote(false);
}
//------------------------------------------------------------------------------
// Disable image load when "mandatory low label" (integrity level).
// (MITIGATION_IMAGE_LOAD_NO_LOW_LABEL)
// >= Win10_TH2
//------------------------------------------------------------------------------
// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL
// mitigation enables the setting on a process.
TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelPolicySuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
return;
base::string16 test_command = L"CheckPolicy ";
test_command += std::to_wstring(TESTPOLICY_LOADNOLOW);
//---------------------------------
// 1) Test setting pre-startup.
//---------------------------------
TestRunner runner;
sandbox::TargetPolicy* policy = runner.GetPolicy();
EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_IMAGE_LOAD_NO_LOW_LABEL),
SBOX_ALL_OK);
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str()));
//---------------------------------
// 2) Test setting post-startup.
//---------------------------------
TestRunner runner2;
sandbox::TargetPolicy* policy2 = runner2.GetPolicy();
EXPECT_EQ(
policy2->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_LOW_LABEL),
SBOX_ALL_OK);
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str()));
}
// This test validates that we CAN create a new process with
// low mandatory label (IL), if the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL
// mitigation is NOT set.
TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
return;
TestWin10ImageLoadLowLabel(true);
}
// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL
// mitigation prevents creating a new process with low mandatory label (IL).
TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelFailure) {
if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
return;
TestWin10ImageLoadLowLabel(false);
}
} // namespace sandbox
This diff is collapsed.
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
#include <stdio.h> #include <stdio.h>
#include <windows.h> #include <windows.h>
#define _DLL_EXPORTING #define BUILDING_DLL
#include "integration_tests_common.h" #include "hooking_dll.h"
// This data section creates a common area that is accessible // This data section creates a common area that is accessible
// to all instances of the DLL (in every process). They map to // to all instances of the DLL (in every process). They map to
...@@ -24,10 +24,11 @@ bool hook_called = false; ...@@ -24,10 +24,11 @@ bool hook_called = false;
#pragma comment(linker, "/SECTION:.hook,RWS") #pragma comment(linker, "/SECTION:.hook,RWS")
namespace { namespace {
HANDLE event = NULL; HANDLE event = NULL;
} }
namespace hooking_dll {
void SetHook(HHOOK hook_handle) { void SetHook(HHOOK hook_handle) {
hook = hook_handle; hook = hook_handle;
...@@ -50,14 +51,16 @@ LRESULT HookProc(int code, WPARAM w_param, LPARAM l_param) { ...@@ -50,14 +51,16 @@ LRESULT HookProc(int code, WPARAM w_param, LPARAM l_param) {
return CallNextHookEx(hook, code, w_param, l_param); return CallNextHookEx(hook, code, w_param, l_param);
} }
} // namespace hooking_dll
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) { if (reason == DLL_PROCESS_ATTACH) {
// The testing process should have set up this named event already // The testing process should have set up this named event already
// (if the test needs this event to be signaled). // (if the test needs this event to be signaled).
event = ::OpenEventW(EVENT_MODIFY_STATE, FALSE, g_hook_event); event = ::OpenEventW(EVENT_MODIFY_STATE, FALSE, hooking_dll::g_hook_event);
} }
if (reason == DLL_PROCESS_DETACH) if (reason == DLL_PROCESS_DETACH && event != nullptr)
::CloseHandle(event); ::CloseHandle(event);
return TRUE; return TRUE;
......
// Copyright 2016 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_TESTS_INTEGRATION_TESTS_HOOKING_DLL_H_
#define SANDBOX_TESTS_INTEGRATION_TESTS_HOOKING_DLL_H_
#include <windows.h>
#ifdef BUILDING_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
namespace hooking_dll {
constexpr wchar_t g_hook_dll_file[] = L"sbox_integration_test_hook_dll.dll";
constexpr wchar_t g_hook_event[] = L"ChromeExtensionTestHookEvent";
DLL_EXPORT void SetHook(HHOOK hook_handle);
DLL_EXPORT bool WasHookCalled();
DLL_EXPORT LRESULT HookProc(int code, WPARAM w_param, LPARAM l_param);
} // namespace hooking_dll
#endif // SANDBOX_TESTS_INTEGRATION_TESTS_HOOKING_DLL_H_
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "integration_tests_common.h"
#include <windows.h> #include <windows.h>
#include "hooking_win_proc.h"
LRESULT CALLBACK WndProc(HWND window, LRESULT CALLBACK WndProc(HWND window,
UINT message, UINT message,
WPARAM w_param, WPARAM w_param,
...@@ -33,8 +33,12 @@ int WINAPI WinMain(HINSTANCE instance, ...@@ -33,8 +33,12 @@ int WINAPI WinMain(HINSTANCE instance,
HINSTANCE prev_instance, HINSTANCE prev_instance,
LPSTR cmd_line, LPSTR cmd_line,
int cmd_show) { int cmd_show) {
constexpr wchar_t winproc_class_name[] = L"myWindowClass";
constexpr wchar_t winproc_window_name[] = L"ChromeMitigationTests";
// The parent process should have set up this named event already. // The parent process should have set up this named event already.
HANDLE event = ::OpenEventW(EVENT_MODIFY_STATE, FALSE, g_winproc_event); HANDLE event = ::OpenEventW(EVENT_MODIFY_STATE, FALSE,
hooking_win_proc::g_winproc_event);
if (event == NULL || event == INVALID_HANDLE_VALUE) if (event == NULL || event == INVALID_HANDLE_VALUE)
return 1; return 1;
...@@ -50,17 +54,17 @@ int WINAPI WinMain(HINSTANCE instance, ...@@ -50,17 +54,17 @@ int WINAPI WinMain(HINSTANCE instance,
window_class.hCursor = ::LoadCursor(NULL, IDC_ARROW); window_class.hCursor = ::LoadCursor(NULL, IDC_ARROW);
window_class.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOWFRAME); window_class.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOWFRAME);
window_class.lpszMenuName = NULL; window_class.lpszMenuName = NULL;
window_class.lpszClassName = g_winproc_class_name; window_class.lpszClassName = winproc_class_name;
window_class.hIconSm = ::LoadIcon(NULL, IDI_APPLICATION); window_class.hIconSm = ::LoadIcon(NULL, IDI_APPLICATION);
if (!::RegisterClassEx(&window_class)) if (!::RegisterClassEx(&window_class))
return 1; return 1;
// Step 2: Create the Window. // Step 2: Create the Window.
HWND window = ::CreateWindowExW(WS_EX_CLIENTEDGE, g_winproc_class_name, HWND window =
g_winproc_window_name, WS_OVERLAPPEDWINDOW, ::CreateWindowExW(WS_EX_CLIENTEDGE, winproc_class_name,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, winproc_window_name, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
NULL, instance, NULL); CW_USEDEFAULT, 240, 120, NULL, NULL, instance, NULL);
if (window == NULL) if (window == NULL)
return 1; return 1;
......
// Copyright 2016 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_TESTS_INTEGRATION_TESTS_HOOKING_WIN_PROC_H_
#define SANDBOX_TESTS_INTEGRATION_TESTS_HOOKING_WIN_PROC_H_
#include <windows.h>
namespace hooking_win_proc {
constexpr wchar_t g_winproc_file[] = L"sbox_integration_test_win_proc.exe ";
constexpr wchar_t g_winproc_event[] = L"ChromeExtensionTestEvent";
} // namespace hooking_win_proc
#endif // SANDBOX_TESTS_INTEGRATION_TESTS_HOOKING_WIN_PROC_H_
...@@ -5,8 +5,20 @@ ...@@ -5,8 +5,20 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/test/launcher/unit_test_launcher.h" #include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_suite.h" #include "base/test/test_suite.h"
#include "testing/gtest/include/gtest/gtest.h" #include "base/test/test_timeouts.h"
#include "sandbox/win/tests/common/controller.h" #include "sandbox/win/tests/common/controller.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace sandbox {
// Common function used for timeout with Win APIs like ::WaitForSingleObject().
DWORD SboxTestEventTimeout() {
if (::IsDebuggerPresent())
return INFINITE;
return static_cast<DWORD>(
(TestTimeouts::action_timeout()).InMillisecondsRoundedUp());
}
}
int wmain(int argc, wchar_t **argv) { int wmain(int argc, wchar_t **argv) {
if (argc >= 2) { if (argc >= 2) {
......
...@@ -7,37 +7,25 @@ ...@@ -7,37 +7,25 @@
#include <windows.h> #include <windows.h>
// Use the same header file for DLL and importers. namespace sandbox {
#ifdef _DLL_EXPORTING
#define DECLSPEC extern "C" __declspec(dllexport)
#else
#define DECLSPEC extern "C" __declspec(dllimport)
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Tests // Common - for sharing between source files.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
const wchar_t* g_extension_point_test_mutex = L"ChromeExtensionTestMutex"; enum TestPolicy {
TESTPOLICY_DEP = 1,
//------------------------------------------------------------------------------ TESTPOLICY_ASLR,
// Hooking WinProc exe. TESTPOLICY_STRICTHANDLE,
//------------------------------------------------------------------------------ TESTPOLICY_WIN32K,
const wchar_t* g_winproc_file = L"sbox_integration_test_win_proc.exe "; TESTPOLICY_EXTENSIONPOINT,
const wchar_t* g_winproc_class_name = L"myWindowClass"; TESTPOLICY_NONSYSFONT,
const wchar_t* g_winproc_window_name = L"ChromeMitigationTests"; TESTPOLICY_LOADNOREMOTE,
const wchar_t* g_winproc_event = L"ChromeExtensionTestEvent"; TESTPOLICY_LOADNOLOW,
};
//------------------------------------------------------------------------------
// Hooking dll. // Timeout for ::WaitForSingleObject synchronization.
//------------------------------------------------------------------------------ DWORD SboxTestEventTimeout();
const wchar_t* g_hook_dll_file = L"sbox_integration_test_hook_dll.dll";
const wchar_t* g_hook_event = L"ChromeExtensionTestHookEvent"; } // namespace sandbox
const char* g_hook_handler_func = "HookProc";
const char* g_was_hook_called_func = "WasHookCalled";
const char* g_set_hook_func = "SetHook";
DECLSPEC LRESULT HookProc(int code, WPARAM wParam, LPARAM lParam);
DECLSPEC bool WasHookCalled();
DECLSPEC void SetHook(HHOOK hook_handle);
#endif // SANDBOX_TESTS_INTEGRATION_TESTS_COMMON_H_ #endif // SANDBOX_TESTS_INTEGRATION_TESTS_COMMON_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment