| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <memory> | 5 #include <memory> |
| 6 #include <string> | 6 #include <string> |
| 7 | 7 |
| 8 #include "base/string16.h" |
| 8 #include "base/sys_string_conversions.h" | 9 #include "base/sys_string_conversions.h" |
| 9 #include "base/win/scoped_handle.h" | 10 #include "base/win/scoped_handle.h" |
| 10 #include "base/win/scoped_process_information.h" | 11 #include "base/win/scoped_process_information.h" |
| 12 #include "base/win/windows_version.h" |
| 11 #include "sandbox/win/src/sandbox.h" | 13 #include "sandbox/win/src/sandbox.h" |
| 12 #include "sandbox/win/src/sandbox_policy.h" | 14 #include "sandbox/win/src/sandbox_policy.h" |
| 13 #include "sandbox/win/src/sandbox_factory.h" | 15 #include "sandbox/win/src/sandbox_factory.h" |
| 14 #include "sandbox/win/tests/common/controller.h" | 16 #include "sandbox/win/tests/common/controller.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 18 |
| 17 namespace { | 19 namespace { |
| 18 | 20 |
| 19 // While the shell API provides better calls than this home brew function | 21 // While the shell API provides better calls than this home brew function |
| 20 // we use GetSystemWindowsDirectoryW which does not query the registry so | 22 // we use GetSystemWindowsDirectoryW which does not query the registry so |
| 21 // it is safe to use after revert. | 23 // it is safe to use after revert. |
| 22 std::wstring MakeFullPathToSystem32(const wchar_t* name) { | 24 string16 MakeFullPathToSystem32(const wchar_t* name) { |
| 23 wchar_t windows_path[MAX_PATH] = {0}; | 25 wchar_t windows_path[MAX_PATH] = {0}; |
| 24 ::GetSystemWindowsDirectoryW(windows_path, MAX_PATH); | 26 ::GetSystemWindowsDirectoryW(windows_path, MAX_PATH); |
| 25 std::wstring full_path(windows_path); | 27 string16 full_path(windows_path); |
| 26 if (full_path.empty()) { | 28 if (full_path.empty()) { |
| 27 return full_path; | 29 return full_path; |
| 28 } | 30 } |
| 29 full_path += L"\\system32\\"; | 31 full_path += L"\\system32\\"; |
| 30 full_path += name; | 32 full_path += name; |
| 31 return full_path; | 33 return full_path; |
| 32 } | 34 } |
| 33 | 35 |
| 34 // Creates a process with the |exe| and |command| parameter using the | 36 // Creates a process with the |exe| and |command| parameter using the |
| 35 // unicode and ascii version of the api. | 37 // unicode and ascii version of the api. |
| 36 sandbox::SboxTestResult CreateProcessHelper(const std::wstring &exe, | 38 sandbox::SboxTestResult CreateProcessHelper(const string16& exe, |
| 37 const std::wstring &command) { | 39 const string16& command) { |
| 38 base::win::ScopedProcessInformation pi; | 40 base::win::ScopedProcessInformation pi; |
| 39 STARTUPINFOW si = {sizeof(si)}; | 41 STARTUPINFOW si = {sizeof(si)}; |
| 40 | 42 |
| 41 const wchar_t *exe_name = NULL; | 43 const wchar_t *exe_name = NULL; |
| 42 if (!exe.empty()) | 44 if (!exe.empty()) |
| 43 exe_name = exe.c_str(); | 45 exe_name = exe.c_str(); |
| 44 | 46 |
| 45 const wchar_t *cmd_line = NULL; | 47 const wchar_t *cmd_line = NULL; |
| 46 if (!command.empty()) | 48 if (!command.empty()) |
| 47 cmd_line = command.c_str(); | 49 cmd_line = command.c_str(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 if (ret1 == ret2) | 92 if (ret1 == ret2) |
| 91 return ret1; | 93 return ret1; |
| 92 | 94 |
| 93 return sandbox::SBOX_TEST_FAILED; | 95 return sandbox::SBOX_TEST_FAILED; |
| 94 } | 96 } |
| 95 | 97 |
| 96 } // namespace | 98 } // namespace |
| 97 | 99 |
| 98 namespace sandbox { | 100 namespace sandbox { |
| 99 | 101 |
| 100 // Tries to create the process in argv[0] using 7 different ways. | 102 SBOX_TESTS_COMMAND int Process_RunApp1(int argc, wchar_t **argv) { |
| 101 // Since we also try the Ansi and Unicode version of the CreateProcess API, | |
| 102 // The process referenced by argv[0] will be spawned 14 times. | |
| 103 SBOX_TESTS_COMMAND int Process_RunApp(int argc, wchar_t **argv) { | |
| 104 if (argc != 1) { | 103 if (argc != 1) { |
| 105 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | 104 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 106 } | 105 } |
| 107 if ((NULL == argv) || (NULL == argv[0])) { | 106 if ((NULL == argv) || (NULL == argv[0])) { |
| 108 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | 107 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 109 } | 108 } |
| 110 std::wstring path = MakeFullPathToSystem32(argv[0]); | 109 string16 path = MakeFullPathToSystem32(argv[0]); |
| 111 | 110 |
| 112 // TEST 1: Try with the path in the app_name. | 111 // TEST 1: Try with the path in the app_name. |
| 113 int result1 = CreateProcessHelper(path, std::wstring()); | 112 return CreateProcessHelper(path, string16()); |
| 113 } |
| 114 |
| 115 SBOX_TESTS_COMMAND int Process_RunApp2(int argc, wchar_t **argv) { |
| 116 if (argc != 1) { |
| 117 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 118 } |
| 119 if ((NULL == argv) || (NULL == argv[0])) { |
| 120 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 121 } |
| 122 string16 path = MakeFullPathToSystem32(argv[0]); |
| 114 | 123 |
| 115 // TEST 2: Try with the path in the cmd_line. | 124 // TEST 2: Try with the path in the cmd_line. |
| 116 std::wstring cmd_line = L"\""; | 125 string16 cmd_line = L"\""; |
| 117 cmd_line += path; | 126 cmd_line += path; |
| 118 cmd_line += L"\""; | 127 cmd_line += L"\""; |
| 119 int result2 = CreateProcessHelper(std::wstring(), cmd_line); | 128 return CreateProcessHelper(string16(), cmd_line); |
| 129 } |
| 130 |
| 131 SBOX_TESTS_COMMAND int Process_RunApp3(int argc, wchar_t **argv) { |
| 132 if (argc != 1) { |
| 133 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 134 } |
| 135 if ((NULL == argv) || (NULL == argv[0])) { |
| 136 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 137 } |
| 120 | 138 |
| 121 // TEST 3: Try file name in the cmd_line. | 139 // TEST 3: Try file name in the cmd_line. |
| 122 int result3 = CreateProcessHelper(std::wstring(), argv[0]); | 140 return CreateProcessHelper(string16(), argv[0]); |
| 141 } |
| 142 |
| 143 SBOX_TESTS_COMMAND int Process_RunApp4(int argc, wchar_t **argv) { |
| 144 if (argc != 1) { |
| 145 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 146 } |
| 147 if ((NULL == argv) || (NULL == argv[0])) { |
| 148 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 149 } |
| 123 | 150 |
| 124 // TEST 4: Try file name in the app_name and current directory sets correctly. | 151 // TEST 4: Try file name in the app_name and current directory sets correctly. |
| 125 std::wstring system32 = MakeFullPathToSystem32(L""); | 152 string16 system32 = MakeFullPathToSystem32(L""); |
| 126 wchar_t current_directory[MAX_PATH + 1]; | 153 wchar_t current_directory[MAX_PATH + 1]; |
| 127 int result4; | 154 int result4; |
| 128 bool test_succeeded = false; | 155 bool test_succeeded = false; |
| 129 DWORD ret = ::GetCurrentDirectory(MAX_PATH, current_directory); | 156 DWORD ret = ::GetCurrentDirectory(MAX_PATH, current_directory); |
| 130 if (0 != ret && ret < MAX_PATH) { | 157 if (!ret) |
| 158 return SBOX_TEST_FIRST_ERROR; |
| 159 |
| 160 if (ret < MAX_PATH) { |
| 131 current_directory[ret] = L'\\'; | 161 current_directory[ret] = L'\\'; |
| 132 current_directory[ret+1] = L'\0'; | 162 current_directory[ret+1] = L'\0'; |
| 133 if (::SetCurrentDirectory(system32.c_str())) { | 163 if (::SetCurrentDirectory(system32.c_str())) { |
| 134 result4 = CreateProcessHelper(argv[0], std::wstring()); | 164 result4 = CreateProcessHelper(argv[0], string16()); |
| 135 if (::SetCurrentDirectory(current_directory)) { | 165 if (::SetCurrentDirectory(current_directory)) { |
| 136 test_succeeded = true; | 166 test_succeeded = true; |
| 137 } | 167 } |
| 168 } else { |
| 169 return SBOX_TEST_SECOND_ERROR; |
| 138 } | 170 } |
| 139 } | 171 } |
| 140 if (!test_succeeded) | 172 if (!test_succeeded) |
| 141 result4 = SBOX_TEST_FAILED; | 173 result4 = SBOX_TEST_FAILED; |
| 142 | 174 |
| 175 return result4; |
| 176 } |
| 177 |
| 178 SBOX_TESTS_COMMAND int Process_RunApp5(int argc, wchar_t **argv) { |
| 179 if (argc != 1) { |
| 180 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 181 } |
| 182 if ((NULL == argv) || (NULL == argv[0])) { |
| 183 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 184 } |
| 185 string16 path = MakeFullPathToSystem32(argv[0]); |
| 186 |
| 143 // TEST 5: Try with the path in the cmd_line and arguments. | 187 // TEST 5: Try with the path in the cmd_line and arguments. |
| 144 cmd_line = L"\""; | 188 string16 cmd_line = L"\""; |
| 145 cmd_line += path; | 189 cmd_line += path; |
| 146 cmd_line += L"\" /INSERT"; | 190 cmd_line += L"\" /I"; |
| 147 int result5 = CreateProcessHelper(std::wstring(), cmd_line); | 191 return CreateProcessHelper(string16(), cmd_line); |
| 192 } |
| 193 |
| 194 SBOX_TESTS_COMMAND int Process_RunApp6(int argc, wchar_t **argv) { |
| 195 if (argc != 1) { |
| 196 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 197 } |
| 198 if ((NULL == argv) || (NULL == argv[0])) { |
| 199 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 200 } |
| 148 | 201 |
| 149 // TEST 6: Try with the file_name in the cmd_line and arguments. | 202 // TEST 6: Try with the file_name in the cmd_line and arguments. |
| 150 cmd_line = argv[0]; | 203 string16 cmd_line = argv[0]; |
| 151 cmd_line += L" /INSERT"; | 204 cmd_line += L" /I"; |
| 152 int result6 = CreateProcessHelper(std::wstring(), cmd_line); | 205 return CreateProcessHelper(string16(), cmd_line); |
| 153 | |
| 154 // TEST 7: Try with the path without the drive. | |
| 155 cmd_line = path.substr(path.find(L'\\')); | |
| 156 int result7 = CreateProcessHelper(std::wstring(), cmd_line); | |
| 157 | |
| 158 // Check if they all returned the same thing. | |
| 159 if ((result1 == result2) && (result2 == result3) && (result3 == result4) && | |
| 160 (result4 == result5) && (result5 == result6) && (result6 == result7)) | |
| 161 return result1; | |
| 162 | |
| 163 return SBOX_TEST_FAILED; | |
| 164 } | 206 } |
| 165 | 207 |
| 166 // Creates a process and checks if it's possible to get a handle to it's token. | 208 // Creates a process and checks if it's possible to get a handle to it's token. |
| 167 SBOX_TESTS_COMMAND int Process_GetChildProcessToken(int argc, wchar_t **argv) { | 209 SBOX_TESTS_COMMAND int Process_GetChildProcessToken(int argc, wchar_t **argv) { |
| 168 if (argc != 1) | 210 if (argc != 1) |
| 169 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | 211 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 170 | 212 |
| 171 if ((NULL == argv) || (NULL == argv[0])) | 213 if ((NULL == argv) || (NULL == argv[0])) |
| 172 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; | 214 return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; |
| 173 | 215 |
| 174 std::wstring path = MakeFullPathToSystem32(argv[0]); | 216 string16 path = MakeFullPathToSystem32(argv[0]); |
| 175 | 217 |
| 176 base::win::ScopedProcessInformation pi; | 218 base::win::ScopedProcessInformation pi; |
| 177 STARTUPINFOW si = {sizeof(si)}; | 219 STARTUPINFOW si = {sizeof(si)}; |
| 178 | 220 |
| 179 if (!::CreateProcessW(path.c_str(), NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, | 221 if (!::CreateProcessW(path.c_str(), NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, |
| 180 NULL, NULL, &si, pi.Receive())) { | 222 NULL, NULL, &si, pi.Receive())) { |
| 181 return SBOX_TEST_FAILED; | 223 return SBOX_TEST_FAILED; |
| 182 } | 224 } |
| 183 | 225 |
| 184 HANDLE token = NULL; | 226 HANDLE token = NULL; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 | 271 |
| 230 // Check the working case. | 272 // Check the working case. |
| 231 runner.GetPolicy()->SetTokenLevel(USER_INTERACTIVE, USER_INTERACTIVE); | 273 runner.GetPolicy()->SetTokenLevel(USER_INTERACTIVE, USER_INTERACTIVE); |
| 232 | 274 |
| 233 EXPECT_EQ(SBOX_ALL_OK, | 275 EXPECT_EQ(SBOX_ALL_OK, |
| 234 runner.GetPolicy()->AddRule(TargetPolicy::SUBSYS_PROCESS, | 276 runner.GetPolicy()->AddRule(TargetPolicy::SUBSYS_PROCESS, |
| 235 TargetPolicy::PROCESS_ALL_EXEC, | 277 TargetPolicy::PROCESS_ALL_EXEC, |
| 236 L"this is not important")); | 278 L"this is not important")); |
| 237 } | 279 } |
| 238 | 280 |
| 239 // This test is disabled. See bug 1305476. | 281 TEST(ProcessPolicyTest, CreateProcessAW) { |
| 240 TEST(ProcessPolicyTest, DISABLED_RunFindstrExe) { | |
| 241 TestRunner runner; | 282 TestRunner runner; |
| 242 std::wstring exe_path = MakeFullPathToSystem32(L"findstr.exe"); | 283 string16 exe_path = MakeFullPathToSystem32(L"findstr.exe"); |
| 243 std::wstring system32 = MakeFullPathToSystem32(L""); | 284 string16 system32 = MakeFullPathToSystem32(L""); |
| 244 ASSERT_TRUE(!exe_path.empty()); | 285 ASSERT_TRUE(!exe_path.empty()); |
| 245 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, | 286 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, |
| 246 TargetPolicy::PROCESS_MIN_EXEC, | 287 TargetPolicy::PROCESS_MIN_EXEC, |
| 247 exe_path.c_str())); | 288 exe_path.c_str())); |
| 248 | 289 |
| 249 // Need to add directory rules for the directories that we use in | 290 // Need to add directory rules for the directories that we use in |
| 250 // SetCurrentDirectory. | 291 // SetCurrentDirectory. |
| 251 EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_DIR_ANY, | 292 EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_DIR_ANY, |
| 252 system32.c_str())); | 293 system32.c_str())); |
| 253 | 294 |
| 254 wchar_t current_directory[MAX_PATH]; | 295 wchar_t current_directory[MAX_PATH]; |
| 255 DWORD ret = ::GetCurrentDirectory(MAX_PATH, current_directory); | 296 DWORD ret = ::GetCurrentDirectory(MAX_PATH, current_directory); |
| 256 ASSERT_TRUE(0 != ret && ret < MAX_PATH); | 297 ASSERT_TRUE(0 != ret && ret < MAX_PATH); |
| 257 | 298 |
| 258 wcscat_s(current_directory, MAX_PATH, L"\\"); | 299 wcscat_s(current_directory, MAX_PATH, L"\\"); |
| 259 EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_DIR_ANY, | 300 EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_DIR_ANY, |
| 260 current_directory)); | 301 current_directory)); |
| 261 | 302 |
| 262 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Process_RunApp findstr.exe")); | 303 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp1 calc.exe")); |
| 263 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp calc.exe")); | 304 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp2 calc.exe")); |
| 305 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp3 calc.exe")); |
| 306 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp5 calc.exe")); |
| 307 EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Process_RunApp6 calc.exe")); |
| 308 |
| 309 EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
| 310 runner.RunTest(L"Process_RunApp1 findstr.exe")); |
| 311 EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
| 312 runner.RunTest(L"Process_RunApp2 findstr.exe")); |
| 313 EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
| 314 runner.RunTest(L"Process_RunApp3 findstr.exe")); |
| 315 EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
| 316 runner.RunTest(L"Process_RunApp5 findstr.exe")); |
| 317 EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
| 318 runner.RunTest(L"Process_RunApp6 findstr.exe")); |
| 319 |
| 320 if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { |
| 321 // WinXP results are not reliable. |
| 322 EXPECT_EQ(SBOX_TEST_SECOND_ERROR, |
| 323 runner.RunTest(L"Process_RunApp4 calc.exe")); |
| 324 EXPECT_EQ(SBOX_TEST_SECOND_ERROR, |
| 325 runner.RunTest(L"Process_RunApp4 findstr.exe")); |
| 326 } |
| 264 } | 327 } |
| 265 | 328 |
| 266 TEST(ProcessPolicyTest, OpenToken) { | 329 TEST(ProcessPolicyTest, OpenToken) { |
| 267 TestRunner runner; | 330 TestRunner runner; |
| 268 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Process_OpenToken")); | 331 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"Process_OpenToken")); |
| 269 } | 332 } |
| 270 | 333 |
| 271 TEST(ProcessPolicyTest, TestGetProcessTokenMinAccess) { | 334 TEST(ProcessPolicyTest, TestGetProcessTokenMinAccess) { |
| 272 TestRunner runner; | 335 TestRunner runner; |
| 273 std::wstring exe_path = MakeFullPathToSystem32(L"findstr.exe"); | 336 string16 exe_path = MakeFullPathToSystem32(L"findstr.exe"); |
| 274 ASSERT_TRUE(!exe_path.empty()); | 337 ASSERT_TRUE(!exe_path.empty()); |
| 275 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, | 338 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, |
| 276 TargetPolicy::PROCESS_MIN_EXEC, | 339 TargetPolicy::PROCESS_MIN_EXEC, |
| 277 exe_path.c_str())); | 340 exe_path.c_str())); |
| 278 | 341 |
| 279 EXPECT_EQ(SBOX_TEST_DENIED, | 342 EXPECT_EQ(SBOX_TEST_DENIED, |
| 280 runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); | 343 runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); |
| 281 } | 344 } |
| 282 | 345 |
| 283 TEST(ProcessPolicyTest, TestGetProcessTokenMaxAccess) { | 346 TEST(ProcessPolicyTest, TestGetProcessTokenMaxAccess) { |
| 284 TestRunner runner(JOB_UNPROTECTED, USER_INTERACTIVE, USER_INTERACTIVE); | 347 TestRunner runner(JOB_UNPROTECTED, USER_INTERACTIVE, USER_INTERACTIVE); |
| 285 std::wstring exe_path = MakeFullPathToSystem32(L"findstr.exe"); | 348 string16 exe_path = MakeFullPathToSystem32(L"findstr.exe"); |
| 286 ASSERT_TRUE(!exe_path.empty()); | 349 ASSERT_TRUE(!exe_path.empty()); |
| 287 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, | 350 EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_PROCESS, |
| 288 TargetPolicy::PROCESS_ALL_EXEC, | 351 TargetPolicy::PROCESS_ALL_EXEC, |
| 289 exe_path.c_str())); | 352 exe_path.c_str())); |
| 290 | 353 |
| 291 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | 354 EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
| 292 runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); | 355 runner.RunTest(L"Process_GetChildProcessToken findstr.exe")); |
| 293 } | 356 } |
| 294 | 357 |
| 295 } // namespace sandbox | 358 } // namespace sandbox |
| OLD | NEW |