blacklist_test.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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 3// found in the LICENSE file. 4 5#include "base/environment.h" 6#include "base/files/file_path.h" 7#include "base/files/scoped_temp_dir.h" 8#include "base/i18n/case_conversion.h" 9#include "base/path_service.h" 10#include "base/scoped_native_library.h" 11#include "base/strings/string16.h" 12#include "base/strings/string_number_conversions.h" 13#include "base/strings/utf_string_conversions.h" 14#include "base/test/test_reg_util_win.h" 15#include "base/win/registry.h" 16#include "chrome_elf/blacklist/blacklist.h" 17#include "chrome_elf/blacklist/test/blacklist_test_main_dll.h" 18#include "chrome_elf/chrome_elf_constants.h" 19#include "testing/gtest/include/gtest/gtest.h" 20#include "version.h" // NOLINT 21 22const wchar_t kTestDllName1[] = L"blacklist_test_dll_1.dll"; 23const wchar_t kTestDllName2[] = L"blacklist_test_dll_2.dll"; 24const wchar_t kTestDllName3[] = L"blacklist_test_dll_3.dll"; 25 26const wchar_t kDll2Beacon[] = L"{F70A0100-2889-4629-9B44-610FE5C73231}"; 27const wchar_t kDll3Beacon[] = L"{9E056AEC-169E-400c-B2D0-5A07E3ACE2EB}"; 28 29extern const wchar_t* kEnvVars[]; 30 31extern "C" { 32// When modifying the blacklist in the test process, use the exported test dll 33// functions on the test blacklist dll, not the ones linked into the test 34// executable itself. 35__declspec(dllimport) bool TestDll_AddDllToBlacklist(const wchar_t* dll_name); 36__declspec(dllimport) bool TestDll_IsBlacklistInitialized(); 37__declspec(dllimport) bool TestDll_RemoveDllFromBlacklist( 38 const wchar_t* dll_name); 39__declspec(dllimport) bool TestDll_SuccessfullyBlocked( 40 const wchar_t** blocked_dlls, 41 int* size); 42} 43 44class BlacklistTest : public testing::Test { 45 virtual void SetUp() { 46 // Force an import from blacklist_test_main_dll. 47 InitBlacklistTestDll(); 48 } 49 50 virtual void TearDown() { 51 TestDll_RemoveDllFromBlacklist(kTestDllName1); 52 TestDll_RemoveDllFromBlacklist(kTestDllName2); 53 TestDll_RemoveDllFromBlacklist(kTestDllName3); 54 } 55}; 56 57TEST_F(BlacklistTest, Beacon) { 58 registry_util::RegistryOverrideManager override_manager; 59 override_manager.OverrideRegistry(HKEY_CURRENT_USER, L"beacon_test"); 60 61 base::win::RegKey blacklist_registry_key(HKEY_CURRENT_USER, 62 blacklist::kRegistryBeaconPath, 63 KEY_QUERY_VALUE | KEY_SET_VALUE); 64 65 // Ensure that the beacon state starts off enabled for this version. 66 LONG result = blacklist_registry_key.WriteValue(blacklist::kBeaconState, 67 blacklist::BLACKLIST_ENABLED); 68 EXPECT_EQ(ERROR_SUCCESS, result); 69 70 result = blacklist_registry_key.WriteValue(blacklist::kBeaconVersion, 71 TEXT(CHROME_VERSION_STRING)); 72 EXPECT_EQ(ERROR_SUCCESS, result); 73 74 // First call should find the beacon and reset it. 75 EXPECT_TRUE(blacklist::ResetBeacon()); 76 77 // First call should succeed as the beacon is enabled. 78 EXPECT_TRUE(blacklist::LeaveSetupBeacon()); 79 80 // Second call should fail indicating the beacon wasn't set as enabled. 81 EXPECT_FALSE(blacklist::LeaveSetupBeacon()); 82 83 // Resetting the beacon should work when setup beacon is present. 84 EXPECT_TRUE(blacklist::ResetBeacon()); 85} 86 87TEST_F(BlacklistTest, AddAndRemoveModules) { 88 EXPECT_TRUE(blacklist::AddDllToBlacklist(L"foo.dll")); 89 // Adding the same item twice should be idempotent. 90 EXPECT_TRUE(blacklist::AddDllToBlacklist(L"foo.dll")); 91 EXPECT_TRUE(blacklist::RemoveDllFromBlacklist(L"foo.dll")); 92 EXPECT_FALSE(blacklist::RemoveDllFromBlacklist(L"foo.dll")); 93 94 // Increase the blacklist size by 1 to include the NULL pointer 95 // that marks the end. 96 int empty_spaces = blacklist::kTroublesomeDllsMaxCount - ( 97 blacklist::BlacklistSize() + 1); 98 std::vector<base::string16> added_dlls; 99 added_dlls.reserve(empty_spaces); 100 for (int i = 0; i < empty_spaces; ++i) { 101 added_dlls.push_back(base::IntToString16(i) + L".dll"); 102 EXPECT_TRUE(blacklist::AddDllToBlacklist(added_dlls[i].c_str())) << i; 103 } 104 EXPECT_FALSE(blacklist::AddDllToBlacklist(L"overflow.dll")); 105 for (int i = 0; i < empty_spaces; ++i) { 106 EXPECT_TRUE(blacklist::RemoveDllFromBlacklist(added_dlls[i].c_str())) << i; 107 } 108 EXPECT_FALSE(blacklist::RemoveDllFromBlacklist(added_dlls[0].c_str())); 109 EXPECT_FALSE(blacklist::RemoveDllFromBlacklist( 110 added_dlls[empty_spaces - 1].c_str())); 111} 112 113TEST_F(BlacklistTest, SuccessfullyBlocked) { 114 // Ensure that we have at least 5 dlls to blacklist. 115 int blacklist_size = blacklist::BlacklistSize(); 116 const int kDesiredBlacklistSize = 5; 117 for (int i = blacklist_size; i < kDesiredBlacklistSize; ++i) { 118 base::string16 new_dll_name(base::IntToString16(i) + L".dll"); 119 EXPECT_TRUE(blacklist::AddDllToBlacklist(new_dll_name.c_str())); 120 } 121 122 // Block 5 dlls, one at a time, starting from the end of the list, and 123 // ensuring SuccesfullyBlocked correctly passes the list of blocked dlls. 124 for (int i = 0; i < kDesiredBlacklistSize; ++i) { 125 blacklist::BlockedDll(i); 126 127 int size = 0; 128 blacklist::SuccessfullyBlocked(NULL, &size); 129 EXPECT_EQ(i + 1, size); 130 131 std::vector<const wchar_t*> blocked_dlls(size); 132 blacklist::SuccessfullyBlocked(&(blocked_dlls[0]), &size); 133 EXPECT_EQ(i + 1, size); 134 135 for (size_t j = 0; j < blocked_dlls.size(); ++j) { 136 EXPECT_EQ(blocked_dlls[j], blacklist::g_troublesome_dlls[j]); 137 } 138 } 139} 140 141TEST_F(BlacklistTest, LoadBlacklistedLibrary) { 142 base::FilePath current_dir; 143 ASSERT_TRUE(PathService::Get(base::DIR_EXE, ¤t_dir)); 144 145 // Ensure that the blacklist is loaded. 146 ASSERT_TRUE(TestDll_IsBlacklistInitialized()); 147 148 // Test that an un-blacklisted DLL can load correctly. 149 base::ScopedNativeLibrary dll1(current_dir.Append(kTestDllName1)); 150 EXPECT_TRUE(dll1.is_valid()); 151 dll1.Reset(NULL); 152 153 int num_blocked_dlls = 0; 154 TestDll_SuccessfullyBlocked(NULL, &num_blocked_dlls); 155 EXPECT_EQ(0, num_blocked_dlls); 156 157 struct TestData { 158 const wchar_t* dll_name; 159 const wchar_t* dll_beacon; 160 } test_data[] = { 161 { kTestDllName2, kDll2Beacon }, 162 { kTestDllName3, kDll3Beacon } 163 }; 164 for (int i = 0 ; i < arraysize(test_data); ++i) { 165 // Add the DLL to the blacklist, ensure that it is not loaded both by 166 // inspecting the handle returned by LoadLibrary and by looking for an 167 // environment variable that is set when the DLL's entry point is called. 168 EXPECT_TRUE(TestDll_AddDllToBlacklist(test_data[i].dll_name)); 169 base::ScopedNativeLibrary dll_blacklisted( 170 current_dir.Append(test_data[i].dll_name)); 171 EXPECT_FALSE(dll_blacklisted.is_valid()); 172 EXPECT_EQ(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0)); 173 dll_blacklisted.Reset(NULL); 174 175 // Ensure that the dll is recorded as blocked. 176 int array_size = 1; 177 const wchar_t* blocked_dll = NULL; 178 TestDll_SuccessfullyBlocked(&blocked_dll, &array_size); 179 EXPECT_EQ(1, array_size); 180 EXPECT_EQ(test_data[i].dll_name, base::string16(blocked_dll)); 181 182 // Remove the DLL from the blacklist. Ensure that it loads and that its 183 // entry point was called. 184 EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(test_data[i].dll_name)); 185 base::ScopedNativeLibrary dll(current_dir.Append(test_data[i].dll_name)); 186 EXPECT_TRUE(dll.is_valid()); 187 EXPECT_NE(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0)); 188 dll.Reset(NULL); 189 190 ::SetEnvironmentVariable(test_data[i].dll_beacon, NULL); 191 192 // Ensure that the dll won't load even if the name has different 193 // capitalization. 194 base::string16 uppercase_name = base::i18n::ToUpper(test_data[i].dll_name); 195 EXPECT_TRUE(TestDll_AddDllToBlacklist(uppercase_name.c_str())); 196 base::ScopedNativeLibrary dll_blacklisted_different_case( 197 current_dir.Append(test_data[i].dll_name)); 198 EXPECT_FALSE(dll_blacklisted_different_case.is_valid()); 199 EXPECT_EQ(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0)); 200 dll_blacklisted_different_case.Reset(NULL); 201 202 EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(uppercase_name.c_str())); 203 204 // The blocked dll was removed, so we shouldn't get anything returned 205 // here. 206 TestDll_SuccessfullyBlocked(NULL, &num_blocked_dlls); 207 EXPECT_EQ(0, num_blocked_dlls); 208 } 209} 210