1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// This file contains the validation tests for the sandbox. 6// It includes the tests that need to be performed inside the 7// sandbox. 8 9#include <shlwapi.h> 10 11#include "base/win/windows_version.h" 12#include "testing/gtest/include/gtest/gtest.h" 13#include "sandbox/win/tests/common/controller.h" 14 15#pragma comment(lib, "shlwapi.lib") 16 17namespace { 18 19void TestProcessAccess(sandbox::TestRunner* runner, DWORD target) { 20 const wchar_t *kCommandTemplate = L"OpenProcessCmd %d %d"; 21 wchar_t command[1024] = {0}; 22 23 // Test all the scary process permissions. 24 wsprintf(command, kCommandTemplate, target, PROCESS_CREATE_THREAD); 25 EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command)); 26 wsprintf(command, kCommandTemplate, target, PROCESS_DUP_HANDLE); 27 EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command)); 28 wsprintf(command, kCommandTemplate, target, PROCESS_SET_INFORMATION); 29 EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command)); 30 wsprintf(command, kCommandTemplate, target, PROCESS_VM_OPERATION); 31 EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command)); 32 wsprintf(command, kCommandTemplate, target, PROCESS_VM_READ); 33 EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command)); 34 wsprintf(command, kCommandTemplate, target, PROCESS_VM_WRITE); 35 EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command)); 36 wsprintf(command, kCommandTemplate, target, PROCESS_QUERY_INFORMATION); 37 EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command)); 38 wsprintf(command, kCommandTemplate, target, WRITE_DAC); 39 EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command)); 40 wsprintf(command, kCommandTemplate, target, WRITE_OWNER); 41 EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command)); 42 wsprintf(command, kCommandTemplate, target, READ_CONTROL); 43 EXPECT_EQ(sandbox::SBOX_TEST_DENIED, runner->RunTest(command)); 44} 45 46} // namespace 47 48namespace sandbox { 49 50// Returns true if the volume that contains any_path supports ACL security. The 51// input path can contain unexpanded environment strings. Returns false on any 52// failure or if the file system does not support file security (such as FAT). 53bool VolumeSupportsACLs(const wchar_t* any_path) { 54 wchar_t expand[MAX_PATH +1]; 55 DWORD len =::ExpandEnvironmentStringsW(any_path, expand, _countof(expand)); 56 if (0 == len) return false; 57 if (len > _countof(expand)) return false; 58 if (!::PathStripToRootW(expand)) return false; 59 DWORD fs_flags = 0; 60 if (!::GetVolumeInformationW(expand, NULL, 0, 0, NULL, &fs_flags, NULL, 0)) 61 return false; 62 if (fs_flags & FILE_PERSISTENT_ACLS) return true; 63 return false; 64} 65 66// Tests if the suite is working properly. 67TEST(ValidationSuite, TestSuite) { 68 TestRunner runner; 69 ASSERT_EQ(SBOX_TEST_PING_OK, runner.RunTest(L"ping")); 70} 71 72// Tests if the file system is correctly protected by the sandbox. 73TEST(ValidationSuite, TestFileSystem) { 74 // Do not perform the test if the system is using FAT or any other 75 // file system that does not have file security. 76 ASSERT_TRUE(VolumeSupportsACLs(L"%SystemDrive%\\")); 77 ASSERT_TRUE(VolumeSupportsACLs(L"%SystemRoot%\\")); 78 ASSERT_TRUE(VolumeSupportsACLs(L"%ProgramFiles%\\")); 79 ASSERT_TRUE(VolumeSupportsACLs(L"%Temp%\\")); 80 ASSERT_TRUE(VolumeSupportsACLs(L"%AppData%\\")); 81 82 TestRunner runner; 83 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %SystemDrive%")); 84 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %SystemRoot%")); 85 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %ProgramFiles%")); 86 EXPECT_EQ(SBOX_TEST_DENIED, 87 runner.RunTest(L"OpenFileCmd %SystemRoot%\\System32")); 88 EXPECT_EQ(SBOX_TEST_DENIED, 89 runner.RunTest(L"OpenFileCmd %SystemRoot%\\explorer.exe")); 90 EXPECT_EQ(SBOX_TEST_DENIED, 91 runner.RunTest(L"OpenFileCmd %SystemRoot%\\Cursors\\arrow_i.cur")); 92 EXPECT_EQ(SBOX_TEST_DENIED, 93 runner.RunTest(L"OpenFileCmd %AllUsersProfile%")); 94 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %Temp%")); 95 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenFileCmd %AppData%")); 96} 97 98// Tests if the registry is correctly protected by the sandbox. 99TEST(ValidationSuite, TestRegistry) { 100 TestRunner runner; 101 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKLM")); 102 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKCU")); 103 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenKey HKU")); 104 EXPECT_EQ(SBOX_TEST_DENIED, 105 runner.RunTest( 106 L"OpenKey HKLM " 107 L"\"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon\"")); 108} 109 110// Tests that the permissions on the Windowstation does not allow the sandbox 111// to get to the interactive desktop or to make the sbox desktop interactive. 112TEST(ValidationSuite, TestDesktop) { 113 TestRunner runner; 114 runner.GetPolicy()->SetAlternateDesktop(true); 115 runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW); 116 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"OpenInteractiveDesktop NULL")); 117 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"SwitchToSboxDesktop NULL")); 118} 119 120// Tests that the permissions on the Windowstation does not allow the sandbox 121// to get to the interactive desktop or to make the sbox desktop interactive. 122TEST(ValidationSuite, TestAlternateDesktop) { 123 base::win::Version version = base::win::GetVersion(); 124 if (version < base::win::VERSION_WIN7) 125 return; 126 127 TestRunner runner; 128 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"EnumAlternateWinsta NULL")); 129 130 wchar_t command[1024] = {0}; 131 runner.SetTimeout(3600000); 132 runner.GetPolicy()->SetAlternateDesktop(true); 133 runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW); 134 base::string16 desktop_name = runner.GetPolicy()->GetAlternateDesktop(); 135 desktop_name = desktop_name.substr(desktop_name.find('\\') + 1); 136 wsprintf(command, L"OpenAlternateDesktop %lS", desktop_name.c_str()); 137 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command)); 138} 139 140// Tests if the windows are correctly protected by the sandbox. 141TEST(ValidationSuite, TestWindows) { 142 TestRunner runner; 143 wchar_t command[1024] = {0}; 144 145 wsprintf(command, L"ValidWindow %d", ::GetDesktopWindow()); 146 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command)); 147 148 wsprintf(command, L"ValidWindow %d", ::FindWindow(NULL, NULL)); 149 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command)); 150} 151 152// Tests that a locked-down process cannot open another locked-down process. 153TEST(ValidationSuite, TestProcessDenyLockdown) { 154 TestRunner runner; 155 TestRunner target; 156 wchar_t command[1024] = {0}; 157 158 target.SetAsynchronous(true); 159 160 EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000")); 161 162 TestProcessAccess(&runner, target.process_id()); 163} 164 165// Tests that a low-integrity process cannot open a locked-down process (due 166// to the integrity label changing after startup via SetDelayedIntegrityLevel). 167TEST(ValidationSuite, TestProcessDenyLowIntegrity) { 168 // This test applies only to Vista and above. 169 if (base::win::Version() < base::win::VERSION_VISTA) 170 return; 171 172 TestRunner runner; 173 TestRunner target; 174 wchar_t command[1024] = {0}; 175 176 target.SetAsynchronous(true); 177 target.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW); 178 179 runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW); 180 runner.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS, 181 USER_INTERACTIVE); 182 183 EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000")); 184 185 TestProcessAccess(&runner, target.process_id()); 186} 187 188// Tests that a locked-down process cannot open a low-integrity process. 189TEST(ValidationSuite, TestProcessDenyBelowLowIntegrity) { 190 // This test applies only to Vista and above. 191 if (base::win::Version() < base::win::VERSION_VISTA) 192 return; 193 194 TestRunner runner; 195 TestRunner target; 196 wchar_t command[1024] = {0}; 197 198 target.SetAsynchronous(true); 199 target.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW); 200 target.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS, 201 USER_INTERACTIVE); 202 203 runner.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_UNTRUSTED); 204 runner.GetPolicy()->SetTokenLevel(USER_RESTRICTED_SAME_ACCESS, 205 USER_INTERACTIVE); 206 207 EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"SleepCmd 30000")); 208 209 TestProcessAccess(&runner, target.process_id()); 210} 211 212// Tests if the threads are correctly protected by the sandbox. 213TEST(ValidationSuite, TestThread) { 214 TestRunner runner; 215 wchar_t command[1024] = {0}; 216 217 wsprintf(command, L"OpenThreadCmd %d", ::GetCurrentThreadId()); 218 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command)); 219} 220 221// Tests if an over-limit allocation will be denied. 222TEST(ValidationSuite, TestMemoryLimit) { 223 TestRunner runner; 224 wchar_t command[1024] = {0}; 225 const int kAllocationSize = 256 * 1024 * 1024; 226 227 wsprintf(command, L"AllocateCmd %d", kAllocationSize); 228 runner.GetPolicy()->SetJobMemoryLimit(kAllocationSize); 229 EXPECT_EQ(SBOX_FATAL_MEMORY_EXCEEDED, runner.RunTest(command)); 230} 231 232// Tests a large allocation will succeed absent limits. 233TEST(ValidationSuite, TestMemoryNoLimit) { 234 TestRunner runner; 235 wchar_t command[1024] = {0}; 236 const int kAllocationSize = 256 * 1024 * 1024; 237 238 wsprintf(command, L"AllocateCmd %d", kAllocationSize); 239 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command)); 240} 241 242} // namespace sandbox 243