OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <windows.h> | 5 #include <windows.h> |
| 6 #include <psapi.h> |
6 | 7 |
| 8 #include <vector> |
| 9 |
| 10 #include "base/numerics/safe_conversions.h" |
7 #include "base/win/scoped_handle.h" | 11 #include "base/win/scoped_handle.h" |
| 12 #include "base/win/scoped_process_information.h" |
8 #include "sandbox/win/src/nt_internals.h" | 13 #include "sandbox/win/src/nt_internals.h" |
9 #include "sandbox/win/src/win_utils.h" | 14 #include "sandbox/win/src/win_utils.h" |
10 #include "sandbox/win/tests/common/test_utils.h" | 15 #include "sandbox/win/tests/common/test_utils.h" |
11 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
12 | 17 |
| 18 namespace { |
| 19 |
| 20 class ScopedTerminateProcess { |
| 21 public: |
| 22 ScopedTerminateProcess(HANDLE process) : process_(process) {} |
| 23 |
| 24 ~ScopedTerminateProcess() { ::TerminateProcess(process_, 0); } |
| 25 |
| 26 private: |
| 27 HANDLE process_; |
| 28 }; |
| 29 |
| 30 bool GetModuleList(HANDLE process, std::vector<HMODULE>* result) { |
| 31 std::vector<HMODULE> modules(256); |
| 32 DWORD size_needed = 0; |
| 33 if (EnumProcessModules( |
| 34 process, &modules[0], |
| 35 base::checked_cast<DWORD>(modules.size() * sizeof(HMODULE)), |
| 36 &size_needed)) { |
| 37 result->assign(modules.begin(), |
| 38 modules.begin() + (size_needed / sizeof(HMODULE))); |
| 39 return true; |
| 40 } |
| 41 modules.resize(size_needed / sizeof(HMODULE)); |
| 42 if (EnumProcessModules( |
| 43 process, &modules[0], |
| 44 base::checked_cast<DWORD>(modules.size() * sizeof(HMODULE)), |
| 45 &size_needed)) { |
| 46 result->assign(modules.begin(), |
| 47 modules.begin() + (size_needed / sizeof(HMODULE))); |
| 48 return true; |
| 49 } |
| 50 return false; |
| 51 } |
| 52 |
| 53 } // namespace |
| 54 |
13 TEST(WinUtils, IsReparsePoint) { | 55 TEST(WinUtils, IsReparsePoint) { |
14 using sandbox::IsReparsePoint; | 56 using sandbox::IsReparsePoint; |
15 | 57 |
16 // Create a temp file because we need write access to it. | 58 // Create a temp file because we need write access to it. |
17 wchar_t temp_directory[MAX_PATH]; | 59 wchar_t temp_directory[MAX_PATH]; |
18 wchar_t my_folder[MAX_PATH]; | 60 wchar_t my_folder[MAX_PATH]; |
19 ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u); | 61 ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u); |
20 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, my_folder), 0u); | 62 ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, my_folder), 0u); |
21 | 63 |
22 // Delete the file and create a directory instead. | 64 // Delete the file and create a directory instead. |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 using sandbox::GetLastErrorFromNtStatus; | 157 using sandbox::GetLastErrorFromNtStatus; |
116 EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), | 158 EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), |
117 GetLastErrorFromNtStatus(STATUS_SUCCESS)); | 159 GetLastErrorFromNtStatus(STATUS_SUCCESS)); |
118 EXPECT_EQ(static_cast<DWORD>(ERROR_NOT_SUPPORTED), | 160 EXPECT_EQ(static_cast<DWORD>(ERROR_NOT_SUPPORTED), |
119 GetLastErrorFromNtStatus(STATUS_NOT_SUPPORTED)); | 161 GetLastErrorFromNtStatus(STATUS_NOT_SUPPORTED)); |
120 EXPECT_EQ(static_cast<DWORD>(ERROR_ALREADY_EXISTS), | 162 EXPECT_EQ(static_cast<DWORD>(ERROR_ALREADY_EXISTS), |
121 GetLastErrorFromNtStatus(STATUS_OBJECT_NAME_COLLISION)); | 163 GetLastErrorFromNtStatus(STATUS_OBJECT_NAME_COLLISION)); |
122 EXPECT_EQ(static_cast<DWORD>(ERROR_ACCESS_DENIED), | 164 EXPECT_EQ(static_cast<DWORD>(ERROR_ACCESS_DENIED), |
123 GetLastErrorFromNtStatus(STATUS_ACCESS_DENIED)); | 165 GetLastErrorFromNtStatus(STATUS_ACCESS_DENIED)); |
124 } | 166 } |
| 167 |
| 168 TEST(WinUtils, GetProcessBaseAddress) { |
| 169 using sandbox::GetProcessBaseAddress; |
| 170 STARTUPINFO start_info = {}; |
| 171 PROCESS_INFORMATION proc_info = {}; |
| 172 WCHAR command_line[] = L"notepad"; |
| 173 start_info.cb = sizeof(start_info); |
| 174 start_info.dwFlags = STARTF_USESHOWWINDOW; |
| 175 start_info.wShowWindow = SW_HIDE; |
| 176 EXPECT_TRUE(::CreateProcessW(nullptr, command_line, nullptr, nullptr, FALSE, |
| 177 CREATE_SUSPENDED, nullptr, nullptr, &start_info, |
| 178 &proc_info)); |
| 179 base::win::ScopedProcessInformation scoped_proc_info(proc_info); |
| 180 ScopedTerminateProcess process_terminate(scoped_proc_info.process_handle()); |
| 181 void* base_address = GetProcessBaseAddress(scoped_proc_info.process_handle()); |
| 182 EXPECT_NE(nullptr, base_address); |
| 183 EXPECT_NE(static_cast<DWORD>(-1), |
| 184 ::ResumeThread(scoped_proc_info.thread_handle())); |
| 185 ::WaitForInputIdle(scoped_proc_info.process_handle(), 1000); |
| 186 EXPECT_NE(static_cast<DWORD>(-1), |
| 187 ::SuspendThread(scoped_proc_info.thread_handle())); |
| 188 // Check again, the process will have done some more memory initialization. |
| 189 EXPECT_EQ(base_address, |
| 190 GetProcessBaseAddress(scoped_proc_info.process_handle())); |
| 191 |
| 192 std::vector<HMODULE> modules; |
| 193 // Compare against the loader's module list (which should now be initialized). |
| 194 // GetModuleList could fail if the target process hasn't fully initialized. |
| 195 // If so skip this check and log it as a warning. |
| 196 if (GetModuleList(scoped_proc_info.process_handle(), &modules) && |
| 197 modules.size() > 0) { |
| 198 // First module should be the main executable. |
| 199 EXPECT_EQ(base_address, modules[0]); |
| 200 } else { |
| 201 LOG(WARNING) << "Couldn't test base address against module list"; |
| 202 } |
| 203 // Fill in some of the virtual memory with 10MiB chunks and try again. |
| 204 for (int count = 0; count < 100; ++count) { |
| 205 EXPECT_NE(nullptr, |
| 206 ::VirtualAllocEx(scoped_proc_info.process_handle(), nullptr, |
| 207 10 * 1024 * 1024, MEM_RESERVE, PAGE_NOACCESS)); |
| 208 } |
| 209 EXPECT_EQ(base_address, |
| 210 GetProcessBaseAddress(scoped_proc_info.process_handle())); |
| 211 } |
OLD | NEW |