summaryrefslogtreecommitdiffstats
path: root/sandbox/win/tests
diff options
context:
space:
mode:
authorjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-13 20:05:09 +0000
committerjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-13 20:05:09 +0000
commit4bcf1c120956613b5f899fb1d6f677961ea8806d (patch)
tree90bcbbab2dcfdb98a676ce7c689f2b6c0f79e383 /sandbox/win/tests
parenta5e451505f3e2a4120473b451d49d7ea3b289f78 (diff)
downloadchromium_src-4bcf1c120956613b5f899fb1d6f677961ea8806d.zip
chromium_src-4bcf1c120956613b5f899fb1d6f677961ea8806d.tar.gz
chromium_src-4bcf1c120956613b5f899fb1d6f677961ea8806d.tar.bz2
Move Windows sandbox
- Move Windows sandbox to sandbox/win - Update sandbox_win.gypi git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146625 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox/win/tests')
-rw-r--r--sandbox/win/tests/common/controller.cc338
-rw-r--r--sandbox/win/tests/common/controller.h145
-rw-r--r--sandbox/win/tests/common/test_utils.cc72
-rw-r--r--sandbox/win/tests/common/test_utils.h19
-rw-r--r--sandbox/win/tests/integration_tests/integration_tests.cc18
-rw-r--r--sandbox/win/tests/integration_tests/integration_tests_test.cc94
-rw-r--r--sandbox/win/tests/integration_tests/sbox_integration_tests.vcproj242
-rw-r--r--sandbox/win/tests/unit_tests/sbox_unittests.vcproj258
-rw-r--r--sandbox/win/tests/unit_tests/unit_tests.cc16
-rw-r--r--sandbox/win/tests/validation_tests/commands.cc262
-rw-r--r--sandbox/win/tests/validation_tests/commands.h37
-rw-r--r--sandbox/win/tests/validation_tests/sbox_validation_tests.vcproj216
-rw-r--r--sandbox/win/tests/validation_tests/suite.cc200
-rw-r--r--sandbox/win/tests/validation_tests/unit_tests.cc16
14 files changed, 1933 insertions, 0 deletions
diff --git a/sandbox/win/tests/common/controller.cc b/sandbox/win/tests/common/controller.cc
new file mode 100644
index 0000000..6c73c2d
--- /dev/null
+++ b/sandbox/win/tests/common/controller.cc
@@ -0,0 +1,338 @@
+// Copyright (c) 2012 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/tests/common/controller.h"
+
+#include <string>
+
+#include "base/process.h"
+#include "base/process_util.h"
+#include "base/sys_string_conversions.h"
+#include "base/win/windows_version.h"
+#include "sandbox/src/sandbox_factory.h"
+#include "sandbox/src/sandbox_utils.h"
+
+namespace {
+
+static const int kDefaultTimeout = 3000;
+
+// Constructs a full path to a file inside the system32 folder.
+std::wstring MakePathToSys32(const wchar_t* name, bool is_obj_man_path) {
+ wchar_t windows_path[MAX_PATH] = {0};
+ if (0 == ::GetSystemWindowsDirectoryW(windows_path, MAX_PATH))
+ return std::wstring();
+
+ std::wstring full_path(windows_path);
+ if (full_path.empty())
+ return full_path;
+
+ if (is_obj_man_path)
+ full_path.insert(0, L"\\??\\");
+
+ full_path += L"\\system32\\";
+ full_path += name;
+ return full_path;
+}
+
+// Constructs a full path to a file inside the syswow64 folder.
+std::wstring MakePathToSysWow64(const wchar_t* name, bool is_obj_man_path) {
+ wchar_t windows_path[MAX_PATH] = {0};
+ if (0 == ::GetSystemWindowsDirectoryW(windows_path, MAX_PATH))
+ return std::wstring();
+
+ std::wstring full_path(windows_path);
+ if (full_path.empty())
+ return full_path;
+
+ if (is_obj_man_path)
+ full_path.insert(0, L"\\??\\");
+
+ full_path += L"\\SysWOW64\\";
+ full_path += name;
+ return full_path;
+}
+
+bool IsProcessRunning(HANDLE process) {
+ DWORD exit_code = 0;
+ if (::GetExitCodeProcess(process, &exit_code))
+ return exit_code == STILL_ACTIVE;
+ return false;
+}
+
+} // namespace
+
+namespace sandbox {
+
+std::wstring MakePathToSys(const wchar_t* name, bool is_obj_man_path) {
+ return (base::win::OSInfo::GetInstance()->wow64_status() ==
+ base::win::OSInfo::WOW64_ENABLED) ?
+ MakePathToSysWow64(name, is_obj_man_path) :
+ MakePathToSys32(name, is_obj_man_path);
+}
+
+BrokerServices* GetBroker() {
+ static BrokerServices* broker = SandboxFactory::GetBrokerServices();
+ static bool is_initialized = false;
+
+ if (!broker) {
+ return NULL;
+ }
+
+ if (!is_initialized) {
+ if (SBOX_ALL_OK != broker->Init())
+ return NULL;
+
+ is_initialized = true;
+ }
+
+ return broker;
+}
+
+TestRunner::TestRunner(JobLevel job_level, TokenLevel startup_token,
+ TokenLevel main_token)
+ : is_init_(false), is_async_(false), no_sandbox_(false),
+ target_process_id_(0) {
+ Init(job_level, startup_token, main_token);
+}
+
+TestRunner::TestRunner()
+ : is_init_(false), is_async_(false), no_sandbox_(false),
+ target_process_id_(0) {
+ Init(JOB_LOCKDOWN, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
+}
+
+void TestRunner::Init(JobLevel job_level, TokenLevel startup_token,
+ TokenLevel main_token) {
+ broker_ = NULL;
+ policy_ = NULL;
+ timeout_ = kDefaultTimeout;
+ state_ = AFTER_REVERT;
+ is_async_= false;
+ target_process_id_ = 0;
+
+ broker_ = GetBroker();
+ if (!broker_)
+ return;
+
+ policy_ = broker_->CreatePolicy();
+ if (!policy_)
+ return;
+
+ policy_->SetJobLevel(job_level, 0);
+ policy_->SetTokenLevel(startup_token, main_token);
+
+ is_init_ = true;
+}
+
+TargetPolicy* TestRunner::GetPolicy() {
+ return policy_;
+}
+
+TestRunner::~TestRunner() {
+ if (target_process_)
+ ::TerminateProcess(target_process_, 0);
+
+ if (policy_)
+ policy_->Release();
+}
+
+bool TestRunner::AddRule(TargetPolicy::SubSystem subsystem,
+ TargetPolicy::Semantics semantics,
+ const wchar_t* pattern) {
+ if (!is_init_)
+ return false;
+
+ return (SBOX_ALL_OK == policy_->AddRule(subsystem, semantics, pattern));
+}
+
+bool TestRunner::AddRuleSys32(TargetPolicy::Semantics semantics,
+ const wchar_t* pattern) {
+ if (!is_init_)
+ return false;
+
+ std::wstring win32_path = MakePathToSys32(pattern, false);
+ if (win32_path.empty())
+ return false;
+
+ if (!AddRule(TargetPolicy::SUBSYS_FILES, semantics, win32_path.c_str()))
+ return false;
+
+ if (base::win::OSInfo::GetInstance()->wow64_status() !=
+ base::win::OSInfo::WOW64_ENABLED)
+ return true;
+
+ win32_path = MakePathToSysWow64(pattern, false);
+ if (win32_path.empty())
+ return false;
+
+ return AddRule(TargetPolicy::SUBSYS_FILES, semantics, win32_path.c_str());
+}
+
+bool TestRunner::AddFsRule(TargetPolicy::Semantics semantics,
+ const wchar_t* pattern) {
+ if (!is_init_)
+ return false;
+
+ return AddRule(TargetPolicy::SUBSYS_FILES, semantics, pattern);
+}
+
+int TestRunner::RunTest(const wchar_t* command) {
+ if (MAX_STATE > 10)
+ return SBOX_TEST_INVALID_PARAMETER;
+
+ wchar_t state_number[2];
+ state_number[0] = L'0' + state_;
+ state_number[1] = L'\0';
+ std::wstring full_command(state_number);
+ full_command += L" ";
+ full_command += command;
+
+ return InternalRunTest(full_command.c_str());
+}
+
+int TestRunner::InternalRunTest(const wchar_t* command) {
+ if (!is_init_)
+ return SBOX_TEST_FAILED_TO_RUN_TEST;
+
+ // For simplicity TestRunner supports only one process per instance.
+ if (target_process_) {
+ if (IsProcessRunning(target_process_))
+ return SBOX_TEST_FAILED_TO_RUN_TEST;
+ target_process_.Close();
+ target_process_id_ = 0;
+ }
+
+ // Get the path to the sandboxed process.
+ wchar_t prog_name[MAX_PATH];
+ GetModuleFileNameW(NULL, prog_name, MAX_PATH);
+
+ // Launch the sandboxed process.
+ ResultCode result = SBOX_ALL_OK;
+ PROCESS_INFORMATION target = {0};
+
+ std::wstring arguments(L"\"");
+ arguments += prog_name;
+ arguments += L"\" -child";
+ arguments += no_sandbox_ ? L"-no-sandbox " : L" ";
+ arguments += command;
+
+ if (no_sandbox_) {
+ STARTUPINFO startup_info = {sizeof(STARTUPINFO)};
+ if (!::CreateProcessW(prog_name, &arguments[0], NULL, NULL, FALSE, 0,
+ NULL, NULL, &startup_info, &target)) {
+ return SBOX_ERROR_GENERIC;
+ }
+ broker_->AddTargetPeer(target.hProcess);
+ } else {
+ result = broker_->SpawnTarget(prog_name, arguments.c_str(), policy_,
+ &target);
+ }
+
+ if (SBOX_ALL_OK != result)
+ return SBOX_TEST_FAILED_TO_RUN_TEST;
+
+ ::ResumeThread(target.hThread);
+
+ // For an asynchronous run we don't bother waiting.
+ if (is_async_) {
+ target_process_.Set(target.hProcess);
+ target_process_id_ = target.dwProcessId;
+ ::CloseHandle(target.hThread);
+ return SBOX_TEST_SUCCEEDED;
+ }
+
+ if (::IsDebuggerPresent()) {
+ // Don't kill the target process on a time-out while we are debugging.
+ timeout_ = INFINITE;
+ }
+
+ if (WAIT_TIMEOUT == ::WaitForSingleObject(target.hProcess, timeout_)) {
+ ::TerminateProcess(target.hProcess, SBOX_TEST_TIMED_OUT);
+ ::CloseHandle(target.hProcess);
+ ::CloseHandle(target.hThread);
+ return SBOX_TEST_TIMED_OUT;
+ }
+
+ DWORD exit_code = SBOX_TEST_LAST_RESULT;
+ if (!::GetExitCodeProcess(target.hProcess, &exit_code)) {
+ ::CloseHandle(target.hProcess);
+ ::CloseHandle(target.hThread);
+ return SBOX_TEST_FAILED_TO_RUN_TEST;
+ }
+
+ ::CloseHandle(target.hProcess);
+ ::CloseHandle(target.hThread);
+
+ return exit_code;
+}
+
+void TestRunner::SetTimeout(DWORD timeout_ms) {
+ timeout_ = timeout_ms;
+}
+
+void TestRunner::SetTestState(SboxTestsState desired_state) {
+ state_ = desired_state;
+}
+
+// This is the main procedure for the target (child) application. We'll find out
+// the target test and call it.
+// We expect the arguments to be:
+// argv[1] = "-child"
+// argv[2] = SboxTestsState when to run the command
+// argv[3] = command to run
+// argv[4...] = command arguments.
+int DispatchCall(int argc, wchar_t **argv) {
+ if (argc < 4)
+ return SBOX_TEST_INVALID_PARAMETER;
+
+ // We hard code two tests to avoid dispatch failures.
+ if (0 == _wcsicmp(argv[3], L"wait")) {
+ Sleep(INFINITE);
+ return SBOX_TEST_TIMED_OUT;
+ }
+
+ if (0 == _wcsicmp(argv[3], L"ping"))
+ return SBOX_TEST_PING_OK;
+
+ SboxTestsState state = static_cast<SboxTestsState>(_wtoi(argv[2]));
+ if ((state <= MIN_STATE) || (state >= MAX_STATE))
+ return SBOX_TEST_INVALID_PARAMETER;
+
+ HMODULE module;
+ if (!GetModuleHandleHelper(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
+ GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ reinterpret_cast<wchar_t*>(&DispatchCall),
+ &module))
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ std::string command_name = base::SysWideToMultiByte(argv[3], CP_UTF8);
+ CommandFunction command = reinterpret_cast<CommandFunction>(
+ ::GetProcAddress(module, command_name.c_str()));
+ if (!command)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ if (BEFORE_INIT == state)
+ return command(argc - 4, argv + 4);
+ else if (EVERY_STATE == state)
+ command(argc - 4, argv + 4);
+
+ TargetServices* target = SandboxFactory::GetTargetServices();
+ if (target) {
+ if (SBOX_ALL_OK != target->Init())
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ if (BEFORE_REVERT == state)
+ return command(argc - 4, argv + 4);
+ else if (EVERY_STATE == state)
+ command(argc - 4, argv + 4);
+
+ target->LowerToken();
+ } else if (0 != _wcsicmp(argv[1], L"-child-no-sandbox")) {
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+ }
+
+ return command(argc - 4, argv + 4);
+}
+
+} // namespace sandbox
diff --git a/sandbox/win/tests/common/controller.h b/sandbox/win/tests/common/controller.h
new file mode 100644
index 0000000..5c2a471
--- /dev/null
+++ b/sandbox/win/tests/common/controller.h
@@ -0,0 +1,145 @@
+// Copyright (c) 2012 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_COMMON_CONTROLLER_H_
+#define SANDBOX_TESTS_COMMON_CONTROLLER_H__
+
+#include <windows.h>
+#include <string>
+
+#include "base/win/scoped_handle.h"
+#include "sandbox/src/sandbox.h"
+
+namespace sandbox {
+
+// See winerror.h for details.
+#define SEVERITY_INFO_FLAGS 0x40000000
+#define SEVERITY_ERROR_FLAGS 0xC0000000
+#define CUSTOMER_CODE 0x20000000
+#define SBOX_TESTS_FACILITY 0x05B10000
+
+// All the possible error codes returned by the child process in
+// the sandbox.
+enum SboxTestResult {
+ SBOX_TEST_FIRST_RESULT = CUSTOMER_CODE | SBOX_TESTS_FACILITY,
+ SBOX_TEST_SUCCEEDED,
+ SBOX_TEST_PING_OK,
+ SBOX_TEST_FIRST_INFO = SBOX_TEST_FIRST_RESULT | SEVERITY_INFO_FLAGS,
+ SBOX_TEST_DENIED, // Access was denied.
+ SBOX_TEST_NOT_FOUND, // The resource was not found.
+ SBOX_TEST_FIRST_ERROR = SBOX_TEST_FIRST_RESULT | SEVERITY_ERROR_FLAGS,
+ SBOX_TEST_INVALID_PARAMETER,
+ SBOX_TEST_FAILED_TO_RUN_TEST,
+ SBOX_TEST_FAILED_TO_EXECUTE_COMMAND,
+ SBOX_TEST_TIMED_OUT,
+ SBOX_TEST_FAILED,
+ SBOX_TEST_LAST_RESULT
+};
+
+inline bool IsSboxTestsResult(SboxTestResult result) {
+ unsigned int code = static_cast<unsigned int>(result);
+ unsigned int first = static_cast<unsigned int>(SBOX_TEST_FIRST_RESULT);
+ unsigned int last = static_cast<unsigned int>(SBOX_TEST_LAST_RESULT);
+ return (code > first) && (code < last);
+}
+
+enum SboxTestsState {
+ MIN_STATE = 1,
+ BEFORE_INIT,
+ BEFORE_REVERT,
+ AFTER_REVERT,
+ EVERY_STATE,
+ MAX_STATE
+};
+
+#define SBOX_TESTS_API __declspec(dllexport)
+#define SBOX_TESTS_COMMAND extern "C" SBOX_TESTS_API
+
+extern "C" {
+typedef int (*CommandFunction)(int argc, wchar_t **argv);
+}
+
+// Class to facilitate the launch of a test inside the sandbox.
+class TestRunner {
+ public:
+ TestRunner(JobLevel job_level, TokenLevel startup_token,
+ TokenLevel main_token);
+
+ TestRunner();
+
+ ~TestRunner();
+
+ // Adds a rule to the policy. The parameters are the same as the AddRule
+ // function in the sandbox.
+ bool AddRule(TargetPolicy::SubSystem subsystem,
+ TargetPolicy::Semantics semantics,
+ const wchar_t* pattern);
+
+ // Adds a filesystem rules with the path of a file in system32. The function
+ // appends "pattern" to "system32" and then call AddRule. Return true if the
+ // function succeeds.
+ bool AddRuleSys32(TargetPolicy::Semantics semantics, const wchar_t* pattern);
+
+ // Adds a filesystem rules to the policy. Returns true if the functions
+ // succeeds.
+ bool AddFsRule(TargetPolicy::Semantics semantics, const wchar_t* pattern);
+
+ // Starts a child process in the sandbox and ask it to run |command|. Returns
+ // a SboxTestResult. By default, the test runs AFTER_REVERT.
+ int RunTest(const wchar_t* command);
+
+ // Sets the timeout value for the child to run the command and return.
+ void SetTimeout(DWORD timeout_ms);
+
+ // Sets TestRunner to return without waiting for the process to exit.
+ void SetAsynchronous(bool is_async) { is_async_ = is_async; }
+
+ // Sets TestRunner to return without waiting for the process to exit.
+ void SetUnsandboxed(bool is_no_sandbox) { no_sandbox_ = is_no_sandbox; }
+
+ // Sets the desired state for the test to run.
+ void SetTestState(SboxTestsState desired_state);
+
+ // Returns the pointers to the policy object. It can be used to modify
+ // the policy manually.
+ TargetPolicy* GetPolicy();
+
+ // Return the process handle for an asynchronous test.
+ HANDLE process() { return target_process_; }
+
+ // Return the process ID for an asynchronous test.
+ DWORD process_id() { return target_process_id_; }
+
+ private:
+ // Initializes the data in the object. Sets is_init_ to tree if the
+ // function succeeds. This is meant to be called from the constructor.
+ void Init(JobLevel job_level, TokenLevel startup_token,
+ TokenLevel main_token);
+
+ // The actual runner.
+ int InternalRunTest(const wchar_t* command);
+
+ BrokerServices* broker_;
+ TargetPolicy* policy_;
+ DWORD timeout_;
+ SboxTestsState state_;
+ bool is_init_;
+ bool is_async_;
+ bool no_sandbox_;
+ base::win::ScopedHandle target_process_;
+ DWORD target_process_id_;
+};
+
+// Returns the broker services.
+BrokerServices* GetBroker();
+
+// Constructs a full path to a file inside the system32 (or syswow64) folder.
+std::wstring MakePathToSys(const wchar_t* name, bool is_obj_man_path);
+
+// Runs the given test on the target process.
+int DispatchCall(int argc, wchar_t **argv);
+
+} // namespace sandbox
+
+#endif // SANDBOX_TESTS_COMMON_CONTROLLER_H_
diff --git a/sandbox/win/tests/common/test_utils.cc b/sandbox/win/tests/common/test_utils.cc
new file mode 100644
index 0000000..929c322
--- /dev/null
+++ b/sandbox/win/tests/common/test_utils.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2006-2010 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/tests/common/test_utils.h"
+
+#include <winioctl.h>
+
+typedef struct _REPARSE_DATA_BUFFER {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ };
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+
+// Sets a reparse point. |source| will now point to |target|. Returns true if
+// the call succeeds, false otherwise.
+bool SetReparsePoint(HANDLE source, const wchar_t* target) {
+ USHORT size_target = static_cast<USHORT>(wcslen(target)) * sizeof(target[0]);
+
+ char buffer[2000] = {0};
+ DWORD returned;
+
+ REPARSE_DATA_BUFFER* data = reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer);
+
+ data->ReparseTag = 0xa0000003;
+ memcpy(data->MountPointReparseBuffer.PathBuffer, target, size_target + 2);
+ data->MountPointReparseBuffer.SubstituteNameLength = size_target;
+ data->MountPointReparseBuffer.PrintNameOffset = size_target + 2;
+ data->ReparseDataLength = size_target + 4 + 8;
+
+ int data_size = data->ReparseDataLength + 8;
+
+ if (!DeviceIoControl(source, FSCTL_SET_REPARSE_POINT, &buffer, data_size,
+ NULL, 0, &returned, NULL)) {
+ return false;
+ }
+ return true;
+}
+
+// Delete the reparse point referenced by |source|. Returns true if the call
+// succeeds, false otherwise.
+bool DeleteReparsePoint(HANDLE source) {
+ DWORD returned;
+ REPARSE_DATA_BUFFER data = {0};
+ data.ReparseTag = 0xa0000003;
+ if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0,
+ &returned, NULL)) {
+ return false;
+ }
+
+ return true;
+}
diff --git a/sandbox/win/tests/common/test_utils.h b/sandbox/win/tests/common/test_utils.h
new file mode 100644
index 0000000..9e17660
--- /dev/null
+++ b/sandbox/win/tests/common/test_utils.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2006-2010 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_COMMON_TEST_UTILS_H_
+#define SANDBOX_TESTS_COMMON_TEST_UTILS_H_
+
+#include <windows.h>
+
+// Sets a reparse point. |source| will now point to |target|. Returns true if
+// the call succeeds, false otherwise.
+bool SetReparsePoint(HANDLE source, const wchar_t* target);
+
+// Delete the reparse point referenced by |source|. Returns true if the call
+// succeeds, false otherwise.
+bool DeleteReparsePoint(HANDLE source);
+
+#endif // SANDBOX_TESTS_COMMON_TEST_UTILS_H_
+
diff --git a/sandbox/win/tests/integration_tests/integration_tests.cc b/sandbox/win/tests/integration_tests/integration_tests.cc
new file mode 100644
index 0000000..5096abb
--- /dev/null
+++ b/sandbox/win/tests/integration_tests/integration_tests.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 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 "testing/gtest/include/gtest/gtest.h"
+#include "sandbox/tests/common/controller.h"
+
+int wmain(int argc, wchar_t **argv) {
+ if (argc >= 2) {
+ if (0 == _wcsicmp(argv[1], L"-child") ||
+ 0 == _wcsicmp(argv[1], L"-child-no-sandbox"))
+ // This instance is a child, not the test.
+ return sandbox::DispatchCall(argc, argv);
+ }
+
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/sandbox/win/tests/integration_tests/integration_tests_test.cc b/sandbox/win/tests/integration_tests/integration_tests_test.cc
new file mode 100644
index 0000000..b610681
--- /dev/null
+++ b/sandbox/win/tests/integration_tests/integration_tests_test.cc
@@ -0,0 +1,94 @@
+// Copyright (c) 2006-2008 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.
+
+// Some tests for the framework itself.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "sandbox/src/sandbox.h"
+#include "sandbox/src/target_services.h"
+#include "sandbox/src/sandbox_factory.h"
+#include "sandbox/tests/common/controller.h"
+
+namespace sandbox {
+
+// Returns the current process state.
+SBOX_TESTS_COMMAND int IntegrationTestsTest_state(int argc, wchar_t **argv) {
+ if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
+ return BEFORE_INIT;
+
+ if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf())
+ return BEFORE_REVERT;
+
+ return AFTER_REVERT;
+}
+
+// Returns the current process state, keeping track of it.
+SBOX_TESTS_COMMAND int IntegrationTestsTest_state2(int argc, wchar_t **argv) {
+ static SboxTestsState state = MIN_STATE;
+ if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) {
+ if (MIN_STATE == state)
+ state = BEFORE_INIT;
+ return state;
+ }
+
+ if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) {
+ if (BEFORE_INIT == state)
+ state = BEFORE_REVERT;
+ return state;
+ }
+
+ if (BEFORE_REVERT == state)
+ state = AFTER_REVERT;
+ return state;
+}
+
+// Returns the number of arguments
+SBOX_TESTS_COMMAND int IntegrationTestsTest_args(int argc, wchar_t **argv) {
+ for (int i = 0; i < argc; i++) {
+ wchar_t argument[20];
+ size_t argument_bytes = wcslen(argv[i]) * sizeof(wchar_t);
+ memcpy(argument, argv[i], __min(sizeof(argument), argument_bytes));
+ }
+
+ return argc;
+}
+
+TEST(IntegrationTestsTest, CallsBeforeInit) {
+ TestRunner runner;
+ runner.SetTimeout(2000);
+ runner.SetTestState(BEFORE_INIT);
+ ASSERT_EQ(BEFORE_INIT, runner.RunTest(L"IntegrationTestsTest_state"));
+}
+
+TEST(IntegrationTestsTest, CallsBeforeRevert) {
+ TestRunner runner;
+ runner.SetTimeout(2000);
+ runner.SetTestState(BEFORE_REVERT);
+ ASSERT_EQ(BEFORE_REVERT, runner.RunTest(L"IntegrationTestsTest_state"));
+}
+
+TEST(IntegrationTestsTest, CallsAfterRevert) {
+ TestRunner runner;
+ runner.SetTimeout(2000);
+ runner.SetTestState(AFTER_REVERT);
+ ASSERT_EQ(AFTER_REVERT, runner.RunTest(L"IntegrationTestsTest_state"));
+}
+
+TEST(IntegrationTestsTest, CallsEveryState) {
+ TestRunner runner;
+ runner.SetTimeout(2000);
+ runner.SetTestState(EVERY_STATE);
+ ASSERT_EQ(AFTER_REVERT, runner.RunTest(L"IntegrationTestsTest_state2"));
+}
+
+TEST(IntegrationTestsTest, ForwardsArguments) {
+ TestRunner runner;
+ runner.SetTimeout(2000);
+ runner.SetTestState(BEFORE_INIT);
+ ASSERT_EQ(1, runner.RunTest(L"IntegrationTestsTest_args first"));
+ ASSERT_EQ(4, runner.RunTest(L"IntegrationTestsTest_args first second third "
+ L"fourth"));
+}
+
+} // namespace sandbox
diff --git a/sandbox/win/tests/integration_tests/sbox_integration_tests.vcproj b/sandbox/win/tests/integration_tests/sbox_integration_tests.vcproj
new file mode 100644
index 0000000..53816e7
--- /dev/null
+++ b/sandbox/win/tests/integration_tests/sbox_integration_tests.vcproj
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="sbox_integration_tests"
+ ProjectGUID="{542D4B3B-98D4-4233-B68D-0103891508C6}"
+ RootNamespace="unit_tests"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE"
+ UsePrecompiledHeader="2"
+ ForcedIncludeFiles="stdafx.h"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/safeseh /dynamicbase /ignore:4199 $(NoInherit)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE"
+ UsePrecompiledHeader="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/safeseh /dynamicbase /ignore:4199 $(NoInherit)"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Common"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{49F2D231-E141-4455-B241-7D37C09B6EEB}"
+ >
+ <File
+ RelativePath="..\common\controller.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\common\controller.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\testing\gtest\src\gtest.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\integration_tests.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\..\src\dep_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\file_policy_test.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\integration_tests_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\integrity_level_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ipc_ping_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\named_pipe_policy_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\policy_target_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\process_policy_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\registry_policy_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\sync_policy_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\unload_dll_test.cc"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sandbox/win/tests/unit_tests/sbox_unittests.vcproj b/sandbox/win/tests/unit_tests/sbox_unittests.vcproj
new file mode 100644
index 0000000..a2df792
--- /dev/null
+++ b/sandbox/win/tests/unit_tests/sbox_unittests.vcproj
@@ -0,0 +1,258 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="sbox_unittests"
+ ProjectGUID="{883553BE-2A9D-418C-A121-61FE1DFBC562}"
+ RootNamespace="unit_tests"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ ForcedIncludeFiles="stdafx.h"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Common"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\testing\gtest\src\gtest.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\unit_tests.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestInterception"
+ >
+ <File
+ RelativePath="..\..\src\interception_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\pe_image_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\service_resolver_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestRestrictedToken"
+ >
+ <File
+ RelativePath="..\..\src\restricted_token_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="TestJob"
+ >
+ <File
+ RelativePath="..\..\src\job_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Sid"
+ >
+ <File
+ RelativePath="..\..\src\sid_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Policy"
+ >
+ <File
+ RelativePath="..\..\src\policy_engine_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\policy_low_level_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\policy_opcodes_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="IPC"
+ >
+ <File
+ RelativePath="..\..\src\ipc_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\threadpool_unittest.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sandbox/win/tests/unit_tests/unit_tests.cc b/sandbox/win/tests/unit_tests/unit_tests.cc
new file mode 100644
index 0000000..a9623db
--- /dev/null
+++ b/sandbox/win/tests/unit_tests/unit_tests.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 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 "testing/gtest/include/gtest/gtest.h"
+
+int wmain(int argc, wchar_t **argv) {
+ if (argc >= 2) {
+ if (0 == _wcsicmp(argv[1], L"-child"))
+ // This instance is a child, not the test.
+ return 0;
+ }
+
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/sandbox/win/tests/validation_tests/commands.cc b/sandbox/win/tests/validation_tests/commands.cc
new file mode 100644
index 0000000..d99451f
--- /dev/null
+++ b/sandbox/win/tests/validation_tests/commands.cc
@@ -0,0 +1,262 @@
+// Copyright (c) 2012 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 <windows.h>
+#include <string>
+
+#include "sandbox/tests/validation_tests/commands.h"
+
+#include "sandbox/tests/common/controller.h"
+
+namespace {
+
+// Returns the HKEY corresponding to name. If there is no HKEY corresponding
+// to the name it returns NULL.
+HKEY GetHKEYFromString(const std::wstring &name) {
+ if (L"HKLM" == name)
+ return HKEY_LOCAL_MACHINE;
+ else if (L"HKCR" == name)
+ return HKEY_CLASSES_ROOT;
+ else if (L"HKCC" == name)
+ return HKEY_CURRENT_CONFIG;
+ else if (L"HKCU" == name)
+ return HKEY_CURRENT_USER;
+ else if (L"HKU" == name)
+ return HKEY_USERS;
+
+ return NULL;
+}
+
+// Modifies string to remove the leading and trailing quotes.
+void trim_quote(std::wstring* string) {
+ std::wstring::size_type pos1 = string->find_first_not_of(L'"');
+ std::wstring::size_type pos2 = string->find_last_not_of(L'"');
+
+ if (std::wstring::npos == pos1 || std::wstring::npos == pos2)
+ (*string) = L"";
+ else
+ (*string) = string->substr(pos1, pos2 + 1);
+}
+
+int TestOpenFile(std::wstring path, bool for_write) {
+ wchar_t path_expanded[MAX_PATH + 1] = {0};
+ DWORD size = ::ExpandEnvironmentStrings(path.c_str(), path_expanded,
+ MAX_PATH);
+ if (!size)
+ return sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ HANDLE file;
+ file = ::CreateFile(path_expanded,
+ for_write ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, // No security attributes.
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL); // No template.
+
+ if (INVALID_HANDLE_VALUE != file) {
+ ::CloseHandle(file);
+ return sandbox::SBOX_TEST_SUCCEEDED;
+ } else {
+ if (ERROR_ACCESS_DENIED == ::GetLastError()) {
+ return sandbox::SBOX_TEST_DENIED;
+ } else {
+ return sandbox::SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+ }
+ }
+}
+
+} // namespace
+
+namespace sandbox {
+
+SBOX_TESTS_COMMAND int ValidWindow(int argc, wchar_t **argv) {
+ if (1 != argc)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ HWND window = reinterpret_cast<HWND>(static_cast<ULONG_PTR>(_wtoi(argv[0])));
+
+ return TestValidWindow(window);
+}
+
+int TestValidWindow(HWND window) {
+ if (::IsWindow(window))
+ return SBOX_TEST_SUCCEEDED;
+
+ return SBOX_TEST_DENIED;
+}
+
+SBOX_TESTS_COMMAND int OpenProcessCmd(int argc, wchar_t **argv) {
+ if (2 != argc)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ DWORD process_id = _wtol(argv[0]);
+ DWORD access_mask = _wtol(argv[1]);
+ return TestOpenProcess(process_id, access_mask);
+}
+
+int TestOpenProcess(DWORD process_id, DWORD access_mask) {
+ HANDLE process = ::OpenProcess(access_mask,
+ FALSE, // Do not inherit handle.
+ process_id);
+ if (NULL == process) {
+ if (ERROR_ACCESS_DENIED == ::GetLastError()) {
+ return SBOX_TEST_DENIED;
+ } else {
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+ }
+ } else {
+ ::CloseHandle(process);
+ return SBOX_TEST_SUCCEEDED;
+ }
+}
+
+SBOX_TESTS_COMMAND int OpenThreadCmd(int argc, wchar_t **argv) {
+ if (1 != argc)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ DWORD thread_id = _wtoi(argv[0]);
+ return TestOpenThread(thread_id);
+}
+
+int TestOpenThread(DWORD thread_id) {
+
+ HANDLE thread = ::OpenThread(THREAD_QUERY_INFORMATION,
+ FALSE, // Do not inherit handles.
+ thread_id);
+
+ if (NULL == thread) {
+ if (ERROR_ACCESS_DENIED == ::GetLastError()) {
+ return SBOX_TEST_DENIED;
+ } else {
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+ }
+ } else {
+ ::CloseHandle(thread);
+ return SBOX_TEST_SUCCEEDED;
+ }
+}
+
+SBOX_TESTS_COMMAND int OpenFile(int argc, wchar_t **argv) {
+ if (1 != argc)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ std::wstring path = argv[0];
+ trim_quote(&path);
+
+ return TestOpenReadFile(path);
+}
+
+int TestOpenReadFile(const std::wstring& path) {
+ return TestOpenFile(path, false);
+}
+
+int TestOpenWriteFile(int argc, wchar_t **argv) {
+ if (1 != argc)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ std::wstring path = argv[0];
+ trim_quote(&path);
+
+ return TestOpenWriteFile(path);
+ }
+
+int TestOpenWriteFile(const std::wstring& path) {
+ return TestOpenFile(path, true);
+}
+
+SBOX_TESTS_COMMAND int OpenKey(int argc, wchar_t **argv) {
+ if (0 == argc || argc > 2)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ // Get the hive.
+ HKEY base_key = GetHKEYFromString(argv[0]);
+
+ // Get the subkey.
+ std::wstring subkey;
+ if (2 == argc) {
+ subkey = argv[1];
+ trim_quote(&subkey);
+ }
+
+ return TestOpenKey(base_key, subkey);
+}
+
+int TestOpenKey(HKEY base_key, std::wstring subkey) {
+ HKEY key;
+ LONG err_code = ::RegOpenKeyEx(base_key,
+ subkey.c_str(),
+ 0, // Reserved, must be 0.
+ MAXIMUM_ALLOWED,
+ &key);
+ if (ERROR_SUCCESS == err_code) {
+ ::RegCloseKey(key);
+ return SBOX_TEST_SUCCEEDED;
+ } else if (ERROR_INVALID_HANDLE == err_code ||
+ ERROR_ACCESS_DENIED == err_code) {
+ return SBOX_TEST_DENIED;
+ } else {
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+ }
+}
+
+// Returns true if the current's thread desktop is the interactive desktop.
+// In Vista there is a more direct test but for XP and w2k we need to check
+// the object name.
+bool IsInteractiveDesktop(bool* is_interactive) {
+ HDESK current_desk = ::GetThreadDesktop(::GetCurrentThreadId());
+ if (NULL == current_desk) {
+ return false;
+ }
+ wchar_t current_desk_name[256] = {0};
+ if (!::GetUserObjectInformationW(current_desk, UOI_NAME, current_desk_name,
+ sizeof(current_desk_name), NULL)) {
+ return false;
+ }
+ *is_interactive = (0 == _wcsicmp(L"default", current_desk_name));
+ return true;
+}
+
+SBOX_TESTS_COMMAND int OpenInteractiveDesktop(int, wchar_t **) {
+ return TestOpenInputDesktop();
+}
+
+int TestOpenInputDesktop() {
+ bool is_interactive = false;
+ if (IsInteractiveDesktop(&is_interactive) && is_interactive) {
+ return SBOX_TEST_SUCCEEDED;
+ }
+ HDESK desk = ::OpenInputDesktop(0, FALSE, DESKTOP_CREATEWINDOW);
+ if (desk) {
+ ::CloseDesktop(desk);
+ return SBOX_TEST_SUCCEEDED;
+ }
+ return SBOX_TEST_DENIED;
+}
+
+SBOX_TESTS_COMMAND int SwitchToSboxDesktop(int, wchar_t **) {
+ return TestSwitchDesktop();
+}
+
+int TestSwitchDesktop() {
+ HDESK sbox_desk = ::GetThreadDesktop(::GetCurrentThreadId());
+ if (NULL == sbox_desk) {
+ return SBOX_TEST_FAILED;
+ }
+ if (::SwitchDesktop(sbox_desk)) {
+ return SBOX_TEST_SUCCEEDED;
+ }
+ return SBOX_TEST_DENIED;
+}
+
+SBOX_TESTS_COMMAND int SleepCmd(int argc, wchar_t **argv) {
+ if (1 != argc)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+
+ ::Sleep(_wtoi(argv[0]));
+ return SBOX_TEST_SUCCEEDED;
+}
+
+
+} // namespace sandbox
diff --git a/sandbox/win/tests/validation_tests/commands.h b/sandbox/win/tests/validation_tests/commands.h
new file mode 100644
index 0000000..9b797a5
--- /dev/null
+++ b/sandbox/win/tests/validation_tests/commands.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 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_VALIDATION_TESTS_COMMANDS_H__
+#define SANDBOX_TESTS_VALIDATION_TESTS_COMMANDS_H__
+
+namespace sandbox {
+
+// Checks if window is a real window. Returns a SboxTestResult.
+int TestValidWindow(HWND window);
+
+// Tries to open the process_id. Returns a SboxTestResult.
+int TestOpenProcess(DWORD process_id, DWORD access_mask);
+
+// Tries to open thread_id. Returns a SboxTestResult.
+int TestOpenThread(DWORD thread_id);
+
+// Tries to open path for read access. Returns a SboxTestResult.
+int TestOpenReadFile(const std::wstring& path);
+
+// Tries to open path for write access. Returns a SboxTestResult.
+int TestOpenWriteFile(const std::wstring& path);
+
+// Tries to open a registry key.
+int TestOpenKey(HKEY base_key, std::wstring subkey);
+
+// Tries to open the workstation's input desktop as long as the
+// current desktop is not the interactive one. Returns a SboxTestResult.
+int TestOpenInputDesktop();
+
+// Tries to switch the interactive desktop. Returns a SboxTestResult.
+int TestSwitchDesktop();
+
+} // namespace sandbox
+
+#endif // SANDBOX_TESTS_VALIDATION_TESTS_COMMANDS_H__
diff --git a/sandbox/win/tests/validation_tests/sbox_validation_tests.vcproj b/sandbox/win/tests/validation_tests/sbox_validation_tests.vcproj
new file mode 100644
index 0000000..9b7b599
--- /dev/null
+++ b/sandbox/win/tests/validation_tests/sbox_validation_tests.vcproj
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="sbox_validation_tests"
+ ProjectGUID="{B9CC7B0D-145A-49C2-B887-84E43CFA0F27}"
+ RootNamespace="unit_tests"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\debug.vsprops;$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ ForcedIncludeFiles="stdafx.h"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="shlwapi.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\testing\using_gtest.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="_CONSOLE"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="shlwapi.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Common"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{2E6C7E35-7538-4883-B80C-C89961A80D66}"
+ >
+ <File
+ RelativePath="..\common\controller.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\common\controller.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\testing\gtest\src\gtest.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ <File
+ RelativePath=".\unit_tests.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Suite"
+ >
+ <File
+ RelativePath=".\commands.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\commands.h"
+ >
+ </File>
+ <File
+ RelativePath=".\suite.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/sandbox/win/tests/validation_tests/suite.cc b/sandbox/win/tests/validation_tests/suite.cc
new file mode 100644
index 0000000..3147f70
--- /dev/null
+++ b/sandbox/win/tests/validation_tests/suite.cc
@@ -0,0 +1,200 @@
+// Copyright (c) 2012 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.
+
+// This file contains the validation tests for the sandbox.
+// It includes the tests that need to be performed inside the
+// sandbox.
+
+#include <shlwapi.h>
+
+#include "base/win/windows_version.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "sandbox/tests/common/controller.h"
+
+#pragma comment(lib, "shlwapi.lib")
+
+namespace {
+
+void TestProcessAccess(sandbox::TestRunner* runner, DWORD target) {
+ const wchar_t *kCommandTemplate = L"OpenProcessCmd %d %d";
+ wchar_t command[1024] = {0};
+
+ // Test all the scary process permissions.
+ wsprintf(command, kCommandTemplate, target, PROCESS_CREATE_THREAD);
+ EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+ wsprintf(command, kCommandTemplate, target, PROCESS_DUP_HANDLE);
+ EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+ wsprintf(command, kCommandTemplate, target, PROCESS_SET_INFORMATION);
+ EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+ wsprintf(command, kCommandTemplate, target, PROCESS_VM_OPERATION);
+ EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+ wsprintf(command, kCommandTemplate, target, PROCESS_VM_READ);
+ EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+ wsprintf(command, kCommandTemplate, target, PROCESS_VM_WRITE);
+ EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+ wsprintf(command, kCommandTemplate, target, PROCESS_QUERY_INFORMATION);
+ EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+ wsprintf(command, kCommandTemplate, target, WRITE_DAC);
+ EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+ wsprintf(command, kCommandTemplate, target, WRITE_OWNER);
+ EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+ wsprintf(command, kCommandTemplate, target, READ_CONTROL);
+ EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command));
+}
+
+} // namespace
+
+namespace sandbox {
+
+// Returns true if the volume that contains any_path supports ACL security. The
+// input path can contain unexpanded environment strings. Returns false on any
+// failure or if the file system does not support file security (such as FAT).
+bool VolumeSupportsACLs(const wchar_t* any_path) {
+ wchar_t expand[MAX_PATH +1];
+ DWORD len =::ExpandEnvironmentStringsW(any_path, expand, _countof(expand));
+ if (0 == len) return false;
+ if (len > _countof(expand)) return false;
+ if (!::PathStripToRootW(expand)) return false;
+ DWORD fs_flags = 0;
+ if (!::GetVolumeInformationW(expand, NULL, 0, 0, NULL, &fs_flags, NULL, 0))
+ return false;
+ if (fs_flags & FILE_PERSISTENT_ACLS) return true;
+ return false;
+}
+
+// Tests if the suite is working properly.
+TEST(ValidationSuite, TestSuite) {
+ TestRunner runner;
+ ASSERT_EQ(SBOX_TEST_PING_OK, runner.RunTest(L"ping"));
+}
+
+// Tests if the file system is correctly protected by the sandbox.
+TEST(ValidationSuite, TestFileSystem) {
+ // Do not perform the test if the system is using FAT or any other
+ // file system that does not have file security.
+ ASSERT_TRUE(VolumeSupportsACLs(L"%SystemDrive%\\"));
+ ASSERT_TRUE(VolumeSupportsACLs(L"%SystemRoot%\\"));
+ ASSERT_TRUE(VolumeSupportsACLs(L"%ProgramFiles%\\"));
+ ASSERT_TRUE(VolumeSupportsACLs(L"%Temp%\\"));
+ ASSERT_TRUE(VolumeSupportsACLs(L"%AppData%\\"));
+
+ TestRunner runner;
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFile %SystemDrive%"));
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFile %SystemRoot%"));
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFile %ProgramFiles%"));
+ EXPECT_EQ(SBOX_TEST_DENIED,
+ runner.RunTest(L"OpenFile %SystemRoot%\\System32"));
+ EXPECT_EQ(SBOX_TEST_DENIED,
+ runner.RunTest(L"OpenFile %SystemRoot%\\explorer.exe"));
+ EXPECT_EQ(SBOX_TEST_DENIED,
+ runner.RunTest(L"OpenFile %SystemRoot%\\Cursors\\arrow_i.cur"));
+ EXPECT_EQ(SBOX_TEST_DENIED,
+ runner.RunTest(L"OpenFile %AllUsersProfile%"));
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFile %Temp%"));
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFile %AppData%"));
+}
+
+// Tests if the registry is correctly protected by the sandbox.
+TEST(ValidationSuite, TestRegistry) {
+ TestRunner runner;
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKLM"));
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKCU"));
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKU"));
+ EXPECT_EQ(SBOX_TEST_DENIED,
+ runner.RunTest(
+ L"OpenKey HKLM "
+ L"\"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon\""));
+}
+
+// Tests that the permissions on the Windowstation does not allow the sandbox
+// to get to the interactive desktop or to make the sbox desktop interactive.
+TEST(ValidationSuite, TestDesktop) {
+ TestRunner runner;
+ runner.GetPolicy()->SetAlternateDesktop(false);
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenInteractiveDesktop NULL"));
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"SwitchToSboxDesktop NULL"));
+}
+
+// Tests if the windows are correctly protected by the sandbox.
+TEST(ValidationSuite, TestWindows) {
+ TestRunner runner;
+ wchar_t command[1024] = {0};
+
+ wsprintf(command, L"ValidWindow %d", ::GetDesktopWindow());
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
+
+ wsprintf(command, L"ValidWindow %d", ::FindWindow(NULL, NULL));
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
+}
+
+// Tests that a locked-down process cannot open another locked-down process.
+TEST(ValidationSuite, TestProcessDenyLockdown) {
+ TestRunner runner;
+ TestRunner target;
+ wchar_t command[1024] = {0};
+
+ target.SetAsynchronous(true);
+
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000"));
+
+ TestProcessAccess(&runner, target.process_id());
+}
+
+// Tests that a low-integrity process cannot open a locked-down process (due
+// to the integrity label changing after startup via SetDelayedIntegrityLevel).
+TEST(ValidationSuite, TestProcessDenyLowIntegrity) {
+ // This test applies only to Vista and above.
+ if (base::win::Version() < base::win::VERSION_VISTA)
+ return;
+
+ TestRunner runner;
+ TestRunner target;
+ wchar_t command[1024] = {0};
+
+ target.SetAsynchronous(true);
+ target.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW);
+
+ runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
+ runner.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS,
+ USER_INTERACTIVE);
+
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000"));
+
+ TestProcessAccess(&runner, target.process_id());
+}
+
+// Tests that a locked-down process cannot open a low-integrity process.
+TEST(ValidationSuite, TestProcessDenyBelowLowIntegrity) {
+ // This test applies only to Vista and above.
+ if (base::win::Version() < base::win::VERSION_VISTA)
+ return;
+
+ TestRunner runner;
+ TestRunner target;
+ wchar_t command[1024] = {0};
+
+ target.SetAsynchronous(true);
+ target.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
+ target.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS,
+ USER_INTERACTIVE);
+
+ runner.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_UNTRUSTED);
+ runner.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS,
+ USER_INTERACTIVE);
+
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000"));
+
+ TestProcessAccess(&runner, target.process_id());
+}
+
+// Tests if the threads are correctly protected by the sandbox.
+TEST(ValidationSuite, TestThread) {
+ TestRunner runner;
+ wchar_t command[1024] = {0};
+
+ wsprintf(command, L"OpenThreadCmd %d", ::GetCurrentThreadId());
+ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
+}
+
+} // namespace sandbox
diff --git a/sandbox/win/tests/validation_tests/unit_tests.cc b/sandbox/win/tests/validation_tests/unit_tests.cc
new file mode 100644
index 0000000..490f7ec
--- /dev/null
+++ b/sandbox/win/tests/validation_tests/unit_tests.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 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 "testing/gtest/include/gtest/gtest.h"
+#include "sandbox/tests/common/controller.h"
+
+int wmain(int argc, wchar_t **argv) {
+ if (argc >= 2) {
+ if (0 == _wcsicmp(argv[1], L"-child"))
+ return sandbox::DispatchCall(argc, argv);
+ }
+
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}