OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/environment.h" | 9 #include "base/environment.h" |
10 #include "base/files/file.h" | |
10 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
11 #include "base/files/scoped_temp_dir.h" | 12 #include "base/files/scoped_temp_dir.h" |
12 #include "base/i18n/case_conversion.h" | 13 #include "base/i18n/case_conversion.h" |
13 #include "base/macros.h" | 14 #include "base/macros.h" |
14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
15 #include "base/path_service.h" | 16 #include "base/path_service.h" |
16 #include "base/scoped_native_library.h" | 17 #include "base/scoped_native_library.h" |
17 #include "base/strings/string16.h" | 18 #include "base/strings/string16.h" |
18 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
19 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
20 #include "base/test/test_reg_util_win.h" | 21 #include "base/test/test_reg_util_win.h" |
21 #include "base/win/registry.h" | 22 #include "base/win/registry.h" |
22 #include "chrome/common/chrome_version.h" | 23 #include "chrome/common/chrome_version.h" |
23 #include "chrome_elf/blacklist/blacklist.h" | 24 #include "chrome_elf/blacklist/blacklist.h" |
24 #include "chrome_elf/blacklist/test/blacklist_test_main_dll.h" | |
25 #include "chrome_elf/chrome_elf_constants.h" | 25 #include "chrome_elf/chrome_elf_constants.h" |
26 #include "chrome_elf/chrome_elf_reg.h" | |
26 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
27 | 28 |
28 const wchar_t kTestDllName1[] = L"blacklist_test_dll_1.dll"; | 29 const wchar_t kTestDllName1[] = L"blacklist_test_dll_1.dll"; |
29 const wchar_t kTestDllName2[] = L"blacklist_test_dll_2.dll"; | 30 const wchar_t kTestDllName2[] = L"blacklist_test_dll_2.dll"; |
30 const wchar_t kTestDllName3[] = L"blacklist_test_dll_3.dll"; | 31 const wchar_t kTestDllName3[] = L"blacklist_test_dll_3.dll"; |
31 | 32 |
32 const wchar_t kDll2Beacon[] = L"{F70A0100-2889-4629-9B44-610FE5C73231}"; | 33 const wchar_t kDll2Beacon[] = L"{F70A0100-2889-4629-9B44-610FE5C73231}"; |
33 const wchar_t kDll3Beacon[] = L"{9E056AEC-169E-400c-B2D0-5A07E3ACE2EB}"; | 34 const wchar_t kDll3Beacon[] = L"{9E056AEC-169E-400c-B2D0-5A07E3ACE2EB}"; |
34 | 35 |
35 extern const wchar_t* kEnvVars[]; | 36 extern const wchar_t* kEnvVars[]; |
36 | 37 |
37 extern "C" { | 38 namespace { |
38 // When modifying the blacklist in the test process, use the exported test dll | 39 |
39 // functions on the test blacklist dll, not the ones linked into the test | 40 // Functions we need from blacklist_test_main_dll.dll |
40 // executable itself. | 41 typedef void (*TestDll_AddDllsFromRegistryToBlacklistFunction)(); |
41 __declspec(dllimport) void TestDll_AddDllsFromRegistryToBlacklist(); | 42 typedef bool (*TestDll_AddDllToBlacklistFunction)(const wchar_t* dll_name); |
42 __declspec(dllimport) bool TestDll_AddDllToBlacklist(const wchar_t* dll_name); | 43 typedef int (*TestDll_BlacklistSizeFunction)(); |
43 __declspec(dllimport) int TestDll_BlacklistSize(); | 44 typedef void (*TestDll_BlockedDllFunction)(size_t blocked_index); |
44 __declspec(dllimport) void TestDll_BlockedDll(size_t blocked_index); | 45 typedef int (*TestDll_GetBlacklistIndexFunction)(const wchar_t* dll_name); |
45 __declspec(dllimport) int TestDll_GetBlacklistIndex(const wchar_t* dll_name); | 46 typedef bool (*TestDll_IsBlacklistInitializedFunction)(); |
46 __declspec(dllimport) bool TestDll_IsBlacklistInitialized(); | 47 typedef bool (*TestDll_RemoveDllFromBlacklistFunction)(const wchar_t* dll_name); |
47 __declspec(dllimport) bool TestDll_RemoveDllFromBlacklist( | 48 typedef bool (*TestDll_SuccessfullyBlockedFunction)( |
48 const wchar_t* dll_name); | |
49 __declspec(dllimport) bool TestDll_SuccessfullyBlocked( | |
50 const wchar_t** blocked_dlls, | 49 const wchar_t** blocked_dlls, |
51 int* size); | 50 int* size); |
52 } | 51 typedef void (*InitTestDllFunction)(); |
53 | 52 |
54 namespace { | 53 TestDll_AddDllsFromRegistryToBlacklistFunction |
54 TestDll_AddDllsFromRegistryToBlacklist = nullptr; | |
55 TestDll_AddDllToBlacklistFunction TestDll_AddDllToBlacklist = nullptr; | |
56 TestDll_BlacklistSizeFunction TestDll_BlacklistSize = nullptr; | |
57 TestDll_BlockedDllFunction TestDll_BlockedDll = nullptr; | |
58 TestDll_GetBlacklistIndexFunction TestDll_GetBlacklistIndex = nullptr; | |
59 TestDll_IsBlacklistInitializedFunction TestDll_IsBlacklistInitialized = nullptr; | |
60 TestDll_RemoveDllFromBlacklistFunction TestDll_RemoveDllFromBlacklist = nullptr; | |
61 TestDll_SuccessfullyBlockedFunction TestDll_SuccessfullyBlocked = nullptr; | |
62 InitTestDllFunction InitTestDll = nullptr; | |
55 | 63 |
56 struct TestData { | 64 struct TestData { |
57 const wchar_t* dll_name; | 65 const wchar_t* dll_name; |
58 const wchar_t* dll_beacon; | 66 const wchar_t* dll_beacon; |
59 } test_data[] = { | 67 } test_data[] = { |
60 {kTestDllName2, kDll2Beacon}, | 68 {kTestDllName2, kDll2Beacon}, |
61 {kTestDllName3, kDll3Beacon} | 69 {kTestDllName3, kDll3Beacon} |
62 }; | 70 }; |
63 | 71 |
64 class BlacklistTest : public testing::Test { | 72 class BlacklistTest : public testing::Test { |
65 protected: | 73 protected: |
66 BlacklistTest() : override_manager_(), num_initially_blocked_(0) { | 74 BlacklistTest() : override_manager_(), num_initially_blocked_(0) { |
67 override_manager_.OverrideRegistry(HKEY_CURRENT_USER); | |
68 } | 75 } |
69 | 76 |
70 void CheckBlacklistedDllsNotLoaded() { | 77 void CheckBlacklistedDllsNotLoaded() { |
71 base::FilePath current_dir; | 78 base::FilePath current_dir; |
72 ASSERT_TRUE(PathService::Get(base::DIR_EXE, ¤t_dir)); | 79 ASSERT_TRUE(PathService::Get(base::DIR_EXE, ¤t_dir)); |
73 | 80 |
74 for (size_t i = 0; i < arraysize(test_data); ++i) { | 81 for (size_t i = 0; i < arraysize(test_data); ++i) { |
75 // Ensure that the dll has not been loaded both by inspecting the handle | 82 // Ensure that the dll has not been loaded both by inspecting the handle |
76 // returned by LoadLibrary and by looking for an environment variable that | 83 // returned by LoadLibrary and by looking for an environment variable that |
77 // is set when the DLL's entry point is called. | 84 // is set when the DLL's entry point is called. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
119 } | 126 } |
120 } | 127 } |
121 | 128 |
122 std::unique_ptr<base::win::RegKey> blacklist_registry_key_; | 129 std::unique_ptr<base::win::RegKey> blacklist_registry_key_; |
123 registry_util::RegistryOverrideManager override_manager_; | 130 registry_util::RegistryOverrideManager override_manager_; |
124 | 131 |
125 // The number of dlls initially blocked by the blacklist. | 132 // The number of dlls initially blocked by the blacklist. |
126 int num_initially_blocked_; | 133 int num_initially_blocked_; |
127 | 134 |
128 private: | 135 private: |
136 // This function puts registry-key redirection paths into | |
137 // a process-specific temp file, for our test DLLs to access. | |
138 void IpcOverrides() { | |
139 wchar_t* file_name = L"chrome_elf_tests.txt"; | |
robertshield
2016/04/20 05:16:09
static const
penny
2016/05/28 01:34:22
Done.
| |
140 | |
141 wchar_t path[MAX_PATH] = {}; | |
142 ::wsprintf(path, L"chrome_elf_test_%u\\", ::GetCurrentProcessId()); | |
robertshield
2016/04/20 15:45:47
Please also use process creation time when naming
penny
2016/05/28 01:34:22
See main comment in reply.
| |
143 | |
144 base::FilePath temp_dir; | |
145 ASSERT_TRUE(base::PathService::Get(base::DIR_TEMP, &temp_dir)); | |
146 temp_dir = temp_dir.Append(path); | |
147 | |
148 ASSERT_TRUE(reg_override_dir_.Set(temp_dir)); | |
robertshield
2016/04/20 15:45:47
I think this will delete the user's %TEMP% folder,
penny
2016/05/28 01:34:22
It's all good actually - doesn't touch %TEMP%.
re
| |
149 | |
150 temp_dir = temp_dir.Append(file_name); | |
151 // This file will be deleted when the ScopedTempDir is cleaned up. | |
152 base::File file(temp_dir, | |
153 base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE); | |
154 ASSERT_TRUE(file.IsValid()); | |
155 | |
156 std::wstring content; | |
157 if (!nt::HKCU_override.empty()) { | |
158 content.append(L"hkcu=\""); | |
159 content.append(nt::HKCU_override.c_str()); | |
160 content.append(L"\"\n"); | |
161 } | |
162 if (!nt::HKLM_override.empty()) { | |
163 content.append(L"hklm=\""); | |
164 content.append(nt::HKLM_override.c_str()); | |
165 content.append(L"\"\n"); | |
166 } | |
167 ASSERT_NE(-1, file.Write(0, (char*)content.c_str(), | |
168 (int)(content.length() * sizeof(wchar_t)))); | |
169 } | |
170 | |
129 void SetUp() override { | 171 void SetUp() override { |
130 // Force an import from blacklist_test_main_dll. | 172 override_manager_.OverrideRegistry(HKEY_CURRENT_USER, &nt::HKCU_override); |
131 InitBlacklistTestDll(); | 173 |
174 // Make the override path available to our test DLL. | |
175 IpcOverrides(); | |
176 | |
177 // Load the main test Dll now. | |
178 // Note: this has to happen after we set up the registry overrides. | |
179 HMODULE dll = nullptr; | |
180 dll = ::LoadLibraryW(L"blacklist_test_main_dll.dll"); | |
181 if (!dll) | |
182 return; | |
183 TestDll_AddDllsFromRegistryToBlacklist = | |
184 reinterpret_cast<TestDll_AddDllsFromRegistryToBlacklistFunction>( | |
185 ::GetProcAddress(dll, "TestDll_AddDllsFromRegistryToBlacklist")); | |
186 TestDll_AddDllToBlacklist = | |
187 reinterpret_cast<TestDll_AddDllToBlacklistFunction>( | |
188 ::GetProcAddress(dll, "TestDll_AddDllToBlacklist")); | |
189 TestDll_BlacklistSize = reinterpret_cast<TestDll_BlacklistSizeFunction>( | |
190 ::GetProcAddress(dll, "TestDll_BlacklistSize")); | |
191 TestDll_BlockedDll = reinterpret_cast<TestDll_BlockedDllFunction>( | |
192 ::GetProcAddress(dll, "TestDll_BlockedDll")); | |
193 TestDll_GetBlacklistIndex = | |
194 reinterpret_cast<TestDll_GetBlacklistIndexFunction>( | |
195 ::GetProcAddress(dll, "TestDll_GetBlacklistIndex")); | |
196 TestDll_IsBlacklistInitialized = | |
197 reinterpret_cast<TestDll_IsBlacklistInitializedFunction>( | |
198 ::GetProcAddress(dll, "TestDll_IsBlacklistInitialized")); | |
199 TestDll_RemoveDllFromBlacklist = | |
200 reinterpret_cast<TestDll_RemoveDllFromBlacklistFunction>( | |
201 ::GetProcAddress(dll, "TestDll_RemoveDllFromBlacklist")); | |
202 TestDll_SuccessfullyBlocked = | |
203 reinterpret_cast<TestDll_SuccessfullyBlockedFunction>( | |
204 ::GetProcAddress(dll, "TestDll_SuccessfullyBlocked")); | |
205 InitTestDll = reinterpret_cast<InitTestDllFunction>( | |
206 ::GetProcAddress(dll, "InitTestDll")); | |
207 if (!TestDll_AddDllsFromRegistryToBlacklist || !TestDll_AddDllToBlacklist || | |
208 !TestDll_BlacklistSize || !TestDll_BlockedDll || | |
209 !TestDll_GetBlacklistIndex || !TestDll_IsBlacklistInitialized || | |
210 !TestDll_RemoveDllFromBlacklist || !TestDll_SuccessfullyBlocked || | |
211 !InitTestDll) | |
212 return; | |
213 | |
214 // We have to call this exported function every time this test setup runs. | |
215 // If the tests are running in single process mode, the test DLL does not | |
216 // get reloaded everytime - but we need to make sure it updates | |
217 // appropriately. | |
218 InitTestDll(); | |
219 | |
132 blacklist_registry_key_.reset( | 220 blacklist_registry_key_.reset( |
133 new base::win::RegKey(HKEY_CURRENT_USER, | 221 new base::win::RegKey(HKEY_CURRENT_USER, |
134 blacklist::kRegistryBeaconPath, | 222 blacklist::kRegistryBeaconPath, |
135 KEY_QUERY_VALUE | KEY_SET_VALUE)); | 223 KEY_QUERY_VALUE | KEY_SET_VALUE)); |
136 | 224 |
137 // Find out how many dlls were blocked before the test starts. | 225 // Find out how many dlls were blocked before the test starts. |
138 TestDll_SuccessfullyBlocked(NULL, &num_initially_blocked_); | 226 TestDll_SuccessfullyBlocked(NULL, &num_initially_blocked_); |
139 } | 227 } |
140 | 228 |
141 void TearDown() override { | 229 void TearDown() override { |
142 TestDll_RemoveDllFromBlacklist(kTestDllName1); | 230 TestDll_RemoveDllFromBlacklist(kTestDllName1); |
143 TestDll_RemoveDllFromBlacklist(kTestDllName2); | 231 TestDll_RemoveDllFromBlacklist(kTestDllName2); |
144 TestDll_RemoveDllFromBlacklist(kTestDllName3); | 232 TestDll_RemoveDllFromBlacklist(kTestDllName3); |
145 } | 233 } |
234 | |
235 // A scoped temporary directory to be destroyed with this test. | |
236 base::ScopedTempDir reg_override_dir_; | |
146 }; | 237 }; |
147 | 238 |
148 TEST_F(BlacklistTest, Beacon) { | 239 TEST_F(BlacklistTest, Beacon) { |
149 // Ensure that the beacon state starts off 'running' for this version. | 240 // Ensure that the beacon state starts off 'running' for this version. |
150 LONG result = blacklist_registry_key_->WriteValue( | 241 LONG result = blacklist_registry_key_->WriteValue( |
151 blacklist::kBeaconState, blacklist::BLACKLIST_SETUP_RUNNING); | 242 blacklist::kBeaconState, blacklist::BLACKLIST_SETUP_RUNNING); |
152 EXPECT_EQ(ERROR_SUCCESS, result); | 243 EXPECT_EQ(ERROR_SUCCESS, result); |
153 | 244 |
154 result = blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion, | 245 result = blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion, |
155 TEXT(CHROME_VERSION_STRING)); | 246 TEXT(CHROME_VERSION_STRING)); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
248 TEST_F(BlacklistTest, AddDllsFromRegistryToBlacklist) { | 339 TEST_F(BlacklistTest, AddDllsFromRegistryToBlacklist) { |
249 // Ensure that the blacklist is loaded. | 340 // Ensure that the blacklist is loaded. |
250 ASSERT_TRUE(TestDll_IsBlacklistInitialized()); | 341 ASSERT_TRUE(TestDll_IsBlacklistInitialized()); |
251 | 342 |
252 // Delete the finch registry key to clear its values. | 343 // Delete the finch registry key to clear its values. |
253 base::win::RegKey key(HKEY_CURRENT_USER, | 344 base::win::RegKey key(HKEY_CURRENT_USER, |
254 blacklist::kRegistryFinchListPath, | 345 blacklist::kRegistryFinchListPath, |
255 KEY_QUERY_VALUE | KEY_SET_VALUE); | 346 KEY_QUERY_VALUE | KEY_SET_VALUE); |
256 key.DeleteKey(L""); | 347 key.DeleteKey(L""); |
257 | 348 |
258 // Add the test dlls to the registry (with their name as both key and value). | 349 // Add the test dlls to the registry. |
350 // (REG_MULTI_SZ: eos separated, double null terminated.) | |
259 base::win::RegKey finch_blacklist_registry_key( | 351 base::win::RegKey finch_blacklist_registry_key( |
260 HKEY_CURRENT_USER, | 352 HKEY_CURRENT_USER, |
261 blacklist::kRegistryFinchListPath, | 353 blacklist::kRegistryFinchListPath, |
262 KEY_QUERY_VALUE | KEY_SET_VALUE); | 354 KEY_QUERY_VALUE | KEY_SET_VALUE); |
355 | |
356 std::vector<wchar_t>(reg_buffer); | |
263 for (size_t i = 0; i < arraysize(test_data); ++i) { | 357 for (size_t i = 0; i < arraysize(test_data); ++i) { |
264 finch_blacklist_registry_key.WriteValue(test_data[i].dll_name, | 358 if (reg_buffer.size() > 0) |
265 test_data[i].dll_name); | 359 reg_buffer.push_back(L'\0'); |
360 const wchar_t* dll = test_data[i].dll_name; | |
361 // Append the name, not including terminator. | |
362 reg_buffer.insert(reg_buffer.end(), dll, dll + ::wcslen(dll)); | |
266 } | 363 } |
364 reg_buffer.push_back(L'\0'); | |
365 reg_buffer.push_back(L'\0'); | |
366 | |
367 finch_blacklist_registry_key.WriteValue( | |
368 blacklist::kRegistryFinchListValueName, reg_buffer.data(), | |
369 (DWORD)(reg_buffer.size() * sizeof(wchar_t)), REG_MULTI_SZ); | |
267 | 370 |
268 TestDll_AddDllsFromRegistryToBlacklist(); | 371 TestDll_AddDllsFromRegistryToBlacklist(); |
269 CheckBlacklistedDllsNotLoaded(); | 372 CheckBlacklistedDllsNotLoaded(); |
270 } | 373 } |
271 | 374 |
272 void TestResetBeacon(std::unique_ptr<base::win::RegKey>& key, | 375 void TestResetBeacon(std::unique_ptr<base::win::RegKey>& key, |
273 DWORD input_state, | 376 DWORD input_state, |
274 DWORD expected_output_state) { | 377 DWORD expected_output_state) { |
275 LONG result = key->WriteValue(blacklist::kBeaconState, input_state); | 378 LONG result = key->WriteValue(blacklist::kBeaconState, input_state); |
276 EXPECT_EQ(ERROR_SUCCESS, result); | 379 EXPECT_EQ(ERROR_SUCCESS, result); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 &blacklist_state); | 445 &blacklist_state); |
343 EXPECT_EQ(blacklist_state, blacklist::BLACKLIST_SETUP_RUNNING); | 446 EXPECT_EQ(blacklist_state, blacklist::BLACKLIST_SETUP_RUNNING); |
344 | 447 |
345 DWORD attempt_count = blacklist::kBeaconMaxAttempts; | 448 DWORD attempt_count = blacklist::kBeaconMaxAttempts; |
346 blacklist_registry_key_->ReadValueDW(blacklist::kBeaconAttemptCount, | 449 blacklist_registry_key_->ReadValueDW(blacklist::kBeaconAttemptCount, |
347 &attempt_count); | 450 &attempt_count); |
348 EXPECT_EQ(static_cast<DWORD>(0), attempt_count); | 451 EXPECT_EQ(static_cast<DWORD>(0), attempt_count); |
349 } | 452 } |
350 | 453 |
351 } // namespace | 454 } // namespace |
OLD | NEW |