Chromium Code Reviews| 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 |