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.
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 "testing/gtest/include/gtest/gtest.h"
19 #include "version.h" // NOLINT
21 const wchar_t kTestDllName1[] = L"blacklist_test_dll_1.dll";
22 const wchar_t kTestDllName2[] = L"blacklist_test_dll_2.dll";
23 const wchar_t kTestDllName3[] = L"blacklist_test_dll_3.dll";
25 const wchar_t kDll2Beacon[] = L"{F70A0100-2889-4629-9B44-610FE5C73231}";
26 const wchar_t kDll3Beacon[] = L"{9E056AEC-169E-400c-B2D0-5A07E3ACE2EB}";
28 extern const wchar_t* kEnvVars[];
31 // When modifying the blacklist in the test process, use the exported test dll
32 // functions on the test blacklist dll, not the ones linked into the test
34 __declspec(dllimport) bool TestDll_AddDllToBlacklist(const wchar_t* dll_name);
35 __declspec(dllimport) bool TestDLL_IsBlacklistInitialized();
36 __declspec(dllimport) bool TestDll_RemoveDllFromBlacklist(
37 const wchar_t* dll_name);
40 class BlacklistTest : public testing::Test {
41 virtual void SetUp() {
42 // Force an import from blacklist_test_main_dll.
43 InitBlacklistTestDll();
46 virtual void TearDown() {
47 TestDll_RemoveDllFromBlacklist(kTestDllName1);
48 TestDll_RemoveDllFromBlacklist(kTestDllName2);
49 TestDll_RemoveDllFromBlacklist(kTestDllName3);
53 TEST_F(BlacklistTest, Beacon) {
54 registry_util::RegistryOverrideManager override_manager;
55 override_manager.OverrideRegistry(HKEY_CURRENT_USER, L"beacon_test");
57 base::win::RegKey blacklist_registry_key(HKEY_CURRENT_USER,
58 blacklist::kRegistryBeaconPath,
59 KEY_QUERY_VALUE | KEY_SET_VALUE);
61 // Ensure that the beacon state starts off enabled for this version.
62 LONG result = blacklist_registry_key.WriteValue(blacklist::kBeaconState,
63 blacklist::BLACKLIST_ENABLED);
64 EXPECT_EQ(ERROR_SUCCESS, result);
66 result = blacklist_registry_key.WriteValue(blacklist::kBeaconVersion,
67 TEXT(CHROME_VERSION_STRING));
68 EXPECT_EQ(ERROR_SUCCESS, result);
70 // First call should find the beacon and reset it.
71 EXPECT_TRUE(blacklist::ResetBeacon());
73 // First call should succeed as the beacon is enabled.
74 EXPECT_TRUE(blacklist::LeaveSetupBeacon());
76 // Second call should fail indicating the beacon wasn't set as enabled.
77 EXPECT_FALSE(blacklist::LeaveSetupBeacon());
79 // Resetting the beacon should work when setup beacon is present.
80 EXPECT_TRUE(blacklist::ResetBeacon());
82 // Change the version and ensure that the setup fails due to the version
84 base::string16 different_version(L"other_version");
85 ASSERT_NE(different_version, TEXT(CHROME_VERSION_STRING));
87 result = blacklist_registry_key.WriteValue(blacklist::kBeaconVersion,
88 different_version.c_str());
89 EXPECT_EQ(ERROR_SUCCESS, result);
91 EXPECT_FALSE(blacklist::LeaveSetupBeacon());
94 TEST_F(BlacklistTest, AddAndRemoveModules) {
95 EXPECT_TRUE(blacklist::AddDllToBlacklist(L"foo.dll"));
96 // Adding the same item twice should be idempotent.
97 EXPECT_TRUE(blacklist::AddDllToBlacklist(L"foo.dll"));
98 EXPECT_TRUE(blacklist::RemoveDllFromBlacklist(L"foo.dll"));
99 EXPECT_FALSE(blacklist::RemoveDllFromBlacklist(L"foo.dll"));
101 // Increase the blacklist size by 1 to include the NULL pointer
102 // that marks the end.
103 int empty_spaces = blacklist::kTroublesomeDllsMaxCount - (
104 blacklist::BlacklistSize() + 1);
105 std::vector<base::string16> added_dlls;
106 added_dlls.reserve(empty_spaces);
107 for (int i = 0; i < empty_spaces; ++i) {
108 added_dlls.push_back(base::IntToString16(i) + L".dll");
109 EXPECT_TRUE(blacklist::AddDllToBlacklist(added_dlls[i].c_str())) << i;
111 EXPECT_FALSE(blacklist::AddDllToBlacklist(L"overflow.dll"));
112 for (int i = 0; i < empty_spaces; ++i) {
113 EXPECT_TRUE(blacklist::RemoveDllFromBlacklist(added_dlls[i].c_str())) << i;
115 EXPECT_FALSE(blacklist::RemoveDllFromBlacklist(added_dlls[0].c_str()));
116 EXPECT_FALSE(blacklist::RemoveDllFromBlacklist(
117 added_dlls[empty_spaces - 1].c_str()));
120 TEST_F(BlacklistTest, LoadBlacklistedLibrary) {
121 base::FilePath current_dir;
122 ASSERT_TRUE(PathService::Get(base::DIR_EXE, ¤t_dir));
124 // Ensure that the blacklist is loaded.
125 ASSERT_TRUE(TestDLL_IsBlacklistInitialized());
127 // Test that an un-blacklisted DLL can load correctly.
128 base::ScopedNativeLibrary dll1(current_dir.Append(kTestDllName1));
129 EXPECT_TRUE(dll1.is_valid());
133 const wchar_t* dll_name;
134 const wchar_t* dll_beacon;
136 { kTestDllName2, kDll2Beacon },
137 { kTestDllName3, kDll3Beacon }
139 for (int i = 0 ; i < arraysize(test_data); ++i) {
140 // Add the DLL to the blacklist, ensure that it is not loaded both by
141 // inspecting the handle returned by LoadLibrary and by looking for an
142 // environment variable that is set when the DLL's entry point is called.
143 EXPECT_TRUE(TestDll_AddDllToBlacklist(test_data[i].dll_name));
144 base::ScopedNativeLibrary dll_blacklisted(
145 current_dir.Append(test_data[i].dll_name));
146 EXPECT_FALSE(dll_blacklisted.is_valid());
147 EXPECT_EQ(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0));
148 dll_blacklisted.Reset(NULL);
150 // Remove the DLL from the blacklist. Ensure that it loads and that its
151 // entry point was called.
152 EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(test_data[i].dll_name));
153 base::ScopedNativeLibrary dll(current_dir.Append(test_data[i].dll_name));
154 EXPECT_TRUE(dll.is_valid());
155 EXPECT_NE(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0));
158 ::SetEnvironmentVariable(test_data[i].dll_beacon, NULL);
160 // Ensure that the dll won't load even if the name has different
162 base::string16 uppercase_name = base::i18n::ToUpper(test_data[i].dll_name);
163 EXPECT_TRUE(TestDll_AddDllToBlacklist(uppercase_name.c_str()));
164 base::ScopedNativeLibrary dll_blacklisted_different_case(
165 current_dir.Append(test_data[i].dll_name));
166 EXPECT_FALSE(dll_blacklisted_different_case.is_valid());
167 EXPECT_EQ(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0));
168 dll_blacklisted_different_case.Reset(NULL);
170 EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(uppercase_name.c_str()));