summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcsharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-03 17:01:41 +0000
committercsharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-03 17:01:41 +0000
commitc80b3502ba5dda8c0fa8f712f585aa1aad45f385 (patch)
treebd4ff65796243c61e215dfb2bb0eedc1602369aa
parent12cc5113da4e1b49cb7c88d56f7c1599365ee3ce (diff)
downloadchromium_src-c80b3502ba5dda8c0fa8f712f585aa1aad45f385.zip
chromium_src-c80b3502ba5dda8c0fa8f712f585aa1aad45f385.tar.gz
chromium_src-c80b3502ba5dda8c0fa8f712f585aa1aad45f385.tar.bz2
Add UMA stats to record when DLLs are successfully blocked in the Browser.
BUG=345287 Review URL: https://codereview.chromium.org/174013007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@254480 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--PRESUBMIT.py1
-rw-r--r--chrome/browser/DEPS2
-rw-r--r--chrome/browser/chrome_elf_init_unittest_win.cc67
-rw-r--r--chrome/browser/chrome_elf_init_win.cc44
-rw-r--r--chrome/chrome_browser.gypi1
-rw-r--r--chrome_elf/blacklist/blacklist.cc45
-rw-r--r--chrome_elf/blacklist/blacklist.h15
-rw-r--r--chrome_elf/blacklist/blacklist_interceptions.cc19
-rw-r--r--chrome_elf/blacklist/test/blacklist_test.cc51
-rw-r--r--chrome_elf/blacklist/test/blacklist_test_main_dll.def3
-rw-r--r--chrome_elf/chrome_elf.def1
-rw-r--r--chrome_elf/chrome_elf.gyp1
-rw-r--r--chrome_elf/chrome_elf_main.cc3
-rw-r--r--chrome_elf/dll_hash.gypi31
-rw-r--r--chrome_elf/dll_hash/dll_hash.cc14
-rw-r--r--chrome_elf/dll_hash/dll_hash.h13
-rw-r--r--chrome_elf/dll_hash/dll_hash_main.cc28
-rw-r--r--tools/metrics/histograms/histograms.xml16
18 files changed, 312 insertions, 43 deletions
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index d9f21b9..e2b8507 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -894,6 +894,7 @@ def _CheckSpamLogging(input_api, output_api):
(r"^base[\\\/]logging\.h$",
r"^base[\\\/]logging\.cc$",
r"^cloud_print[\\\/]",
+ r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 313c8ce..b214bfb 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -3,8 +3,10 @@ include_rules = [
"+ash",
"+chrome/app",
"+chrome/installer",
+ "+chrome_elf/blacklist",
"+chrome_elf/chrome_elf_constants.h",
"+chrome_elf/create_file",
+ "+chrome_elf/dll_hash",
"+chromeos",
"+components/autofill/content/browser",
"+components/autofill/content/common",
diff --git a/chrome/browser/chrome_elf_init_unittest_win.cc b/chrome/browser/chrome_elf_init_unittest_win.cc
index 513b96b..b7cee8a 100644
--- a/chrome/browser/chrome_elf_init_unittest_win.cc
+++ b/chrome/browser/chrome_elf_init_unittest_win.cc
@@ -5,47 +5,50 @@
#include "chrome/browser/chrome_elf_init_win.h"
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_reg_util_win.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome_elf/chrome_elf_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "version.h" // NOLINT
class ChromeBlacklistTrialTest : public testing::Test {
protected:
- ChromeBlacklistTrialTest() :
- blacklist_registry_key_(HKEY_CURRENT_USER,
- blacklist::kRegistryBeaconPath,
- KEY_QUERY_VALUE | KEY_SET_VALUE) {}
+ ChromeBlacklistTrialTest() {}
+ virtual ~ChromeBlacklistTrialTest() {}
virtual void SetUp() OVERRIDE {
testing::Test::SetUp();
- registry_util::RegistryOverrideManager override_manager;
- override_manager.OverrideRegistry(HKEY_CURRENT_USER,
- L"browser_blacklist_test");
-
+ override_manager_.OverrideRegistry(HKEY_CURRENT_USER,
+ L"browser_blacklist_test");
+ blacklist_registry_key_.reset(
+ new base::win::RegKey(HKEY_CURRENT_USER,
+ blacklist::kRegistryBeaconPath,
+ KEY_QUERY_VALUE | KEY_SET_VALUE));
}
DWORD GetBlacklistState() {
DWORD blacklist_state = blacklist::BLACKLIST_STATE_MAX;
- blacklist_registry_key_.ReadValueDW(blacklist::kBeaconState,
- &blacklist_state);
+ blacklist_registry_key_->ReadValueDW(blacklist::kBeaconState,
+ &blacklist_state);
return blacklist_state;
}
base::string16 GetBlacklistVersion() {
base::string16 blacklist_version;
- blacklist_registry_key_.ReadValue(blacklist::kBeaconVersion,
- &blacklist_version);
+ blacklist_registry_key_->ReadValue(blacklist::kBeaconVersion,
+ &blacklist_version);
return blacklist_version;
}
- base::win::RegKey blacklist_registry_key_;
+ scoped_ptr<base::win::RegKey> blacklist_registry_key_;
+ registry_util::RegistryOverrideManager override_manager_;
private:
DISALLOW_COPY_AND_ASSIGN(ChromeBlacklistTrialTest);
@@ -55,9 +58,9 @@ class ChromeBlacklistTrialTest : public testing::Test {
// Ensure that the default trial deletes any existing blacklist beacons.
TEST_F(ChromeBlacklistTrialTest, DefaultRun) {
// Set some dummy values as beacons.
- blacklist_registry_key_.WriteValue(blacklist::kBeaconState,
- blacklist::BLACKLIST_ENABLED);
- blacklist_registry_key_.WriteValue(blacklist::kBeaconVersion, L"Data");
+ blacklist_registry_key_->WriteValue(blacklist::kBeaconState,
+ blacklist::BLACKLIST_ENABLED);
+ blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion, L"Data");
// This setup code should result in the default group, which should remove
// all the beacon values.
@@ -82,9 +85,11 @@ TEST_F(ChromeBlacklistTrialTest, VerifyFirstRun) {
TEST_F(ChromeBlacklistTrialTest, SetupFailed) {
// Set the registry to indicate that the blacklist setup is running,
- // which means it failed to run correctly last time.
- blacklist_registry_key_.WriteValue(blacklist::kBeaconState,
- blacklist::BLACKLIST_SETUP_RUNNING);
+ // which means it failed to run correctly last time for this version.
+ blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion,
+ TEXT(CHROME_VERSION_STRING));
+ blacklist_registry_key_->WriteValue(blacklist::kBeaconState,
+ blacklist::BLACKLIST_SETUP_RUNNING);
BrowserBlacklistBeaconSetup();
@@ -94,9 +99,11 @@ TEST_F(ChromeBlacklistTrialTest, SetupFailed) {
TEST_F(ChromeBlacklistTrialTest, ThunkSetupFailed) {
// Set the registry to indicate that the blacklist thunk setup is running,
- // which means it failed to run correctly last time.
- blacklist_registry_key_.WriteValue(blacklist::kBeaconState,
- blacklist::BLACKLIST_THUNK_SETUP);
+ // which means it failed to run correctly last time for this version.
+ blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion,
+ TEXT(CHROME_VERSION_STRING));
+ blacklist_registry_key_->WriteValue(blacklist::kBeaconState,
+ blacklist::BLACKLIST_THUNK_SETUP);
BrowserBlacklistBeaconSetup();
@@ -106,9 +113,11 @@ TEST_F(ChromeBlacklistTrialTest, ThunkSetupFailed) {
TEST_F(ChromeBlacklistTrialTest, InterceptionFailed) {
// Set the registry to indicate that an interception is running,
- // which means it failed to run correctly last time.
- blacklist_registry_key_.WriteValue(blacklist::kBeaconState,
- blacklist::BLACKLIST_INTERCEPTING);
+ // which means it failed to run correctly last time for this version.
+ blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion,
+ TEXT(CHROME_VERSION_STRING));
+ blacklist_registry_key_->WriteValue(blacklist::kBeaconState,
+ blacklist::BLACKLIST_INTERCEPTING);
BrowserBlacklistBeaconSetup();
@@ -119,10 +128,10 @@ TEST_F(ChromeBlacklistTrialTest, InterceptionFailed) {
TEST_F(ChromeBlacklistTrialTest, VersionChanged) {
// Mark the blacklist as disabled for an older version, so it should
// get enabled for this new version.
- blacklist_registry_key_.WriteValue(blacklist::kBeaconVersion,
- L"old_version");
- blacklist_registry_key_.WriteValue(blacklist::kBeaconState,
- blacklist::BLACKLIST_DISABLED);
+ blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion,
+ L"old_version");
+ blacklist_registry_key_->WriteValue(blacklist::kBeaconState,
+ blacklist::BLACKLIST_DISABLED);
BrowserBlacklistBeaconSetup();
diff --git a/chrome/browser/chrome_elf_init_win.cc b/chrome/browser/chrome_elf_init_win.cc
index aa74c46..0ea4e0d 100644
--- a/chrome/browser/chrome_elf_init_win.cc
+++ b/chrome/browser/chrome_elf_init_win.cc
@@ -2,12 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/registry.h"
#include "chrome/browser/chrome_elf_init_win.h"
+#include "chrome_elf/blacklist/blacklist.h"
#include "chrome_elf/chrome_elf_constants.h"
+#include "chrome_elf/dll_hash/dll_hash.h"
+#include "content/public/browser/browser_thread.h"
#include "version.h" // NOLINT
namespace {
@@ -15,6 +20,10 @@ namespace {
const char kBrowserBlacklistTrialName[] = "BrowserBlacklist";
const char kBrowserBlacklistTrialEnabledGroupName[] = "Enabled";
+// How long to wait, in seconds, before reporting for the second (and last
+// time), what dlls were blocked from the browser process.
+const int kBlacklistReportingDelaySec = 600;
+
// This enum is used to define the buckets for an enumerated UMA histogram.
// Hence,
// (a) existing enumerated constants should never be deleted or reordered, and
@@ -46,6 +55,29 @@ void RecordBlacklistSetupEvent(BlacklistSetupEventType blacklist_setup_event) {
BLACKLIST_SETUP_EVENT_MAX);
}
+// Report which DLLs were prevented from being loaded.
+void ReportSuccessfulBlocks() {
+ // Figure out how many dlls were blocked.
+ int num_blocked_dlls = 0;
+ blacklist::SuccessfullyBlocked(NULL, &num_blocked_dlls);
+
+ if (num_blocked_dlls == 0)
+ return;
+
+ // Now retrieve the list of blocked dlls.
+ std::vector<const wchar_t*> blocked_dlls(num_blocked_dlls);
+ blacklist::SuccessfullyBlocked(&blocked_dlls[0], &num_blocked_dlls);
+
+ // Send up the hashes of the blocked dlls via UMA.
+ for (size_t i = 0; i < blocked_dlls.size(); ++i) {
+ std::string dll_name_utf8;
+ base::WideToUTF8(blocked_dlls[i], wcslen(blocked_dlls[i]), &dll_name_utf8);
+ int uma_hash = DllNameToHash(dll_name_utf8);
+
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Blacklist.Blocked", uma_hash);
+ }
+}
+
} // namespace
void InitializeChromeElf() {
@@ -57,6 +89,18 @@ void InitializeChromeElf() {
base::win::RegKey blacklist_registry_key(HKEY_CURRENT_USER);
blacklist_registry_key.DeleteKey(blacklist::kRegistryBeaconPath);
}
+
+ // Report all successful blacklist interceptions.
+ ReportSuccessfulBlocks();
+
+ // Schedule another task to report all sucessful interceptions later.
+ // This time delay should be long enough to catch any dlls that attempt to
+ // inject after Chrome has started up.
+ content::BrowserThread::PostDelayedTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&ReportSuccessfulBlocks),
+ base::TimeDelta::FromSeconds(kBlacklistReportingDelaySec));
}
void BrowserBlacklistBeaconSetup() {
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 5aa3933..02f9c04 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -3413,6 +3413,7 @@
'../chrome/chrome.gyp:chrome_version_header',
'../chrome_elf/chrome_elf.gyp:chrome_elf',
'../chrome_elf/chrome_elf.gyp:chrome_elf_constants',
+ '../chrome_elf/chrome_elf.gyp:dll_hash',
'../google_update/google_update.gyp:google_update',
'../third_party/iaccessible2/iaccessible2.gyp:iaccessible2',
'../third_party/isimpledom/isimpledom.gyp:isimpledom',
diff --git a/chrome_elf/blacklist/blacklist.cc b/chrome_elf/blacklist/blacklist.cc
index 5ce3773..681427a 100644
--- a/chrome_elf/blacklist/blacklist.cc
+++ b/chrome_elf/blacklist/blacklist.cc
@@ -4,6 +4,7 @@
#include "chrome_elf/blacklist/blacklist.h"
+#include <assert.h>
#include <string.h>
#include "base/basictypes.h"
@@ -30,6 +31,9 @@ const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount] = {
NULL,
};
+bool g_blocked_dlls[kTroublesomeDllsMaxCount] = {};
+int g_num_blocked_dlls = 0;
+
} // namespace blacklist
// Allocate storage for thunks in a page of this module to save on doing
@@ -285,6 +289,7 @@ bool AddDllToBlacklist(const wchar_t* dll_name) {
wcscpy(str_buffer, dll_name);
g_troublesome_dlls[blacklist_size] = str_buffer;
+ g_blocked_dlls[blacklist_size] = false;
return true;
}
@@ -297,12 +302,52 @@ bool RemoveDllFromBlacklist(const wchar_t* dll_name) {
delete[] g_troublesome_dlls[i];
g_troublesome_dlls[i] = g_troublesome_dlls[blacklist_size - 1];
g_troublesome_dlls[blacklist_size - 1] = NULL;
+
+ // Also update the stats recording if we have blocked this dll or not.
+ if (g_blocked_dlls[i])
+ --g_num_blocked_dlls;
+ g_blocked_dlls[i] = g_blocked_dlls[blacklist_size - 1];
return true;
}
}
return false;
}
+// TODO(csharp): Maybe store these values in the registry so we can
+// still report them if Chrome crashes early.
+void SuccessfullyBlocked(const wchar_t** blocked_dlls, int* size) {
+ if (size == NULL)
+ return;
+
+ // If the array isn't valid or big enough, just report the size it needs to
+ // be and return.
+ if (blocked_dlls == NULL && *size < g_num_blocked_dlls) {
+ *size = g_num_blocked_dlls;
+ return;
+ }
+
+ *size = g_num_blocked_dlls;
+
+ int strings_to_fill = 0;
+ for (int i = 0; strings_to_fill < g_num_blocked_dlls && g_troublesome_dlls[i];
+ ++i) {
+ if (g_blocked_dlls[i]) {
+ blocked_dlls[strings_to_fill] = g_troublesome_dlls[i];
+ ++strings_to_fill;
+ }
+ }
+}
+
+void BlockedDll(size_t blocked_index) {
+ assert(blocked_index < kTroublesomeDllsMaxCount);
+
+ if (!g_blocked_dlls[blocked_index] &&
+ blocked_index < kTroublesomeDllsMaxCount) {
+ ++g_num_blocked_dlls;
+ g_blocked_dlls[blocked_index] = true;
+ }
+}
+
bool Initialize(bool force) {
// Check to see that we found the functions we need in ntdll.
if (!InitializeInterceptImports())
diff --git a/chrome_elf/blacklist/blacklist.h b/chrome_elf/blacklist/blacklist.h
index 779525f..9877c29 100644
--- a/chrome_elf/blacklist/blacklist.h
+++ b/chrome_elf/blacklist/blacklist.h
@@ -12,7 +12,7 @@
namespace blacklist {
// Max size of the DLL blacklist.
-const int kTroublesomeDllsMaxCount = 64;
+const size_t kTroublesomeDllsMaxCount = 64;
// The DLL blacklist.
extern const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount];
@@ -44,12 +44,25 @@ extern "C" bool IsBlacklistInitialized();
// the blacklist when this returns, false on error. Note that this will copy
// |dll_name| and will leak it on exit if the string is not subsequently removed
// using RemoveDllFromBlacklist.
+// Exposed for testing only, this shouldn't be exported from chrome_elf.dll.
extern "C" bool AddDllToBlacklist(const wchar_t* dll_name);
// Removes the given dll name from the blacklist. Returns true if it was
// removed, false on error.
+// Exposed for testing only, this shouldn't be exported from chrome_elf.dll.
extern "C" bool RemoveDllFromBlacklist(const wchar_t* dll_name);
+// Returns a list of all the dlls that have been successfully blocked by the
+// blacklist via blocked_dlls, if there is enough space (according to |size|).
+// |size| will always be modified to be the number of dlls that were blocked.
+// The caller doesn't own the strings and isn't expected to free them. These
+// strings won't be hanging unless RemoveDllFromBlacklist is called, but it
+// is only exposed in tests (and should stay that way).
+extern "C" void SuccessfullyBlocked(const wchar_t** blocked_dlls, int* size);
+
+// Record that the dll at the given index was blocked.
+void BlockedDll(size_t blocked_index);
+
// Initializes the DLL blacklist in the current process. This should be called
// before any undesirable DLLs might be loaded. If |force| is set to true, then
// initialization will take place even if a beacon is present. This is useful
diff --git a/chrome_elf/blacklist/blacklist_interceptions.cc b/chrome_elf/blacklist/blacklist_interceptions.cc
index b3f3d82..8496c48 100644
--- a/chrome_elf/blacklist/blacklist_interceptions.cc
+++ b/chrome_elf/blacklist/blacklist_interceptions.cc
@@ -35,12 +35,12 @@ FARPROC GetNtDllExportByName(const char* export_name) {
return ::GetProcAddress(ntdll, export_name);
}
-bool DllMatch(const base::string16& module_name) {
+int DllMatch(const base::string16& module_name) {
for (int i = 0; blacklist::g_troublesome_dlls[i] != NULL; ++i) {
if (_wcsicmp(module_name.c_str(), blacklist::g_troublesome_dlls[i]) == 0)
- return true;
+ return i;
}
- return false;
+ return -1;
}
// TODO(robertshield): Some of the helper functions below overlap somewhat with
@@ -203,10 +203,15 @@ NTSTATUS BlNtMapViewOfSectionImpl(
module_name = ExtractLoadedModuleName(file_name);
}
- if (!module_name.empty() && DllMatch(module_name)) {
- DCHECK_NT(g_nt_unmap_view_of_section_func);
- g_nt_unmap_view_of_section_func(process, *base);
- ret = STATUS_UNSUCCESSFUL;
+ if (!module_name.empty()) {
+ int blocked_index = DllMatch(module_name);
+ if (blocked_index != -1) {
+ DCHECK_NT(g_nt_unmap_view_of_section_func);
+ g_nt_unmap_view_of_section_func(process, *base);
+ ret = STATUS_UNSUCCESSFUL;
+
+ blacklist::BlockedDll(blocked_index);
+ }
}
}
diff --git a/chrome_elf/blacklist/test/blacklist_test.cc b/chrome_elf/blacklist/test/blacklist_test.cc
index 096502d..e507446 100644
--- a/chrome_elf/blacklist/test/blacklist_test.cc
+++ b/chrome_elf/blacklist/test/blacklist_test.cc
@@ -33,9 +33,12 @@ extern "C" {
// functions on the test blacklist dll, not the ones linked into the test
// executable itself.
__declspec(dllimport) bool TestDll_AddDllToBlacklist(const wchar_t* dll_name);
-__declspec(dllimport) bool TestDLL_IsBlacklistInitialized();
+__declspec(dllimport) bool TestDll_IsBlacklistInitialized();
__declspec(dllimport) bool TestDll_RemoveDllFromBlacklist(
const wchar_t* dll_name);
+__declspec(dllimport) bool TestDll_SuccessfullyBlocked(
+ const wchar_t** blocked_dlls,
+ int* size);
}
class BlacklistTest : public testing::Test {
@@ -118,18 +121,50 @@ TEST_F(BlacklistTest, AddAndRemoveModules) {
added_dlls[empty_spaces - 1].c_str()));
}
+TEST_F(BlacklistTest, SuccessfullyBlocked) {
+ // Ensure that we have at least 5 dlls to blacklist.
+ int blacklist_size = blacklist::BlacklistSize();
+ const int kDesiredBlacklistSize = 5;
+ for (int i = blacklist_size; i < kDesiredBlacklistSize; ++i) {
+ base::string16 new_dll_name(base::IntToString16(i) + L".dll");
+ EXPECT_TRUE(blacklist::AddDllToBlacklist(new_dll_name.c_str()));
+ }
+
+ // Block 5 dlls, one at a time, starting from the end of the list, and
+ // ensuring SuccesfullyBlocked correctly passes the list of blocked dlls.
+ for (int i = 0; i < kDesiredBlacklistSize; ++i) {
+ blacklist::BlockedDll(i);
+
+ int size = 0;
+ blacklist::SuccessfullyBlocked(NULL, &size);
+ EXPECT_EQ(i + 1, size);
+
+ std::vector<const wchar_t*> blocked_dlls(size);
+ blacklist::SuccessfullyBlocked(&(blocked_dlls[0]), &size);
+ EXPECT_EQ(i + 1, size);
+
+ for (size_t j = 0; j < blocked_dlls.size(); ++j) {
+ EXPECT_EQ(blocked_dlls[j], blacklist::g_troublesome_dlls[j]);
+ }
+ }
+}
+
TEST_F(BlacklistTest, LoadBlacklistedLibrary) {
base::FilePath current_dir;
ASSERT_TRUE(PathService::Get(base::DIR_EXE, &current_dir));
// Ensure that the blacklist is loaded.
- ASSERT_TRUE(TestDLL_IsBlacklistInitialized());
+ ASSERT_TRUE(TestDll_IsBlacklistInitialized());
// Test that an un-blacklisted DLL can load correctly.
base::ScopedNativeLibrary dll1(current_dir.Append(kTestDllName1));
EXPECT_TRUE(dll1.is_valid());
dll1.Reset(NULL);
+ int num_blocked_dlls = 0;
+ TestDll_SuccessfullyBlocked(NULL, &num_blocked_dlls);
+ EXPECT_EQ(0, num_blocked_dlls);
+
struct TestData {
const wchar_t* dll_name;
const wchar_t* dll_beacon;
@@ -148,6 +183,13 @@ TEST_F(BlacklistTest, LoadBlacklistedLibrary) {
EXPECT_EQ(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0));
dll_blacklisted.Reset(NULL);
+ // Ensure that the dll is recorded as blocked.
+ int array_size = 1;
+ const wchar_t* blocked_dll = NULL;
+ TestDll_SuccessfullyBlocked(&blocked_dll, &array_size);
+ EXPECT_EQ(1, array_size);
+ EXPECT_EQ(test_data[i].dll_name, base::string16(blocked_dll));
+
// Remove the DLL from the blacklist. Ensure that it loads and that its
// entry point was called.
EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(test_data[i].dll_name));
@@ -169,5 +211,10 @@ TEST_F(BlacklistTest, LoadBlacklistedLibrary) {
dll_blacklisted_different_case.Reset(NULL);
EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(uppercase_name.c_str()));
+
+ // The blocked dll was removed, so we shouldn't get anything returned
+ // here.
+ TestDll_SuccessfullyBlocked(NULL, &num_blocked_dlls);
+ EXPECT_EQ(0, num_blocked_dlls);
}
}
diff --git a/chrome_elf/blacklist/test/blacklist_test_main_dll.def b/chrome_elf/blacklist/test/blacklist_test_main_dll.def
index 82e0f0e..920dc6c 100644
--- a/chrome_elf/blacklist/test/blacklist_test_main_dll.def
+++ b/chrome_elf/blacklist/test/blacklist_test_main_dll.def
@@ -6,6 +6,7 @@ LIBRARY "blacklist_test_main_dll.dll"
EXPORTS
TestDll_AddDllToBlacklist=AddDllToBlacklist
- TestDLL_IsBlacklistInitialized=IsBlacklistInitialized
+ TestDll_IsBlacklistInitialized=IsBlacklistInitialized
+ TestDll_SuccessfullyBlocked=SuccessfullyBlocked
TestDll_RemoveDllFromBlacklist=RemoveDllFromBlacklist
InitBlacklistTestDll \ No newline at end of file
diff --git a/chrome_elf/chrome_elf.def b/chrome_elf/chrome_elf.def
index 026f9c6..566a8fb 100644
--- a/chrome_elf/chrome_elf.def
+++ b/chrome_elf/chrome_elf.def
@@ -9,3 +9,4 @@ EXPORTS
GetRedirectCount
IsBlacklistInitialized
SignalChromeElf
+ SuccessfullyBlocked
diff --git a/chrome_elf/chrome_elf.gyp b/chrome_elf/chrome_elf.gyp
index e564aa76..1534dbf 100644
--- a/chrome_elf/chrome_elf.gyp
+++ b/chrome_elf/chrome_elf.gyp
@@ -9,6 +9,7 @@
'../build/util/version.gypi',
'../build/win_precompile.gypi',
'blacklist.gypi',
+ 'dll_hash.gypi',
],
'targets': [
{
diff --git a/chrome_elf/chrome_elf_main.cc b/chrome_elf/chrome_elf_main.cc
index de64375..989493a 100644
--- a/chrome_elf/chrome_elf_main.cc
+++ b/chrome_elf/chrome_elf_main.cc
@@ -23,9 +23,6 @@ BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) {
blacklist::Initialize(false); // Don't force, abort if beacon is present.
} __except(GenerateCrashDump(GetExceptionInformation())) {
}
-
- // TODO(csharp): Move additions to the DLL blacklist to a sane place.
- // blacklist::AddDllToBlacklist(L"foo.dll");
}
return TRUE;
diff --git a/chrome_elf/dll_hash.gypi b/chrome_elf/dll_hash.gypi
new file mode 100644
index 0000000..9e89a24
--- /dev/null
+++ b/chrome_elf/dll_hash.gypi
@@ -0,0 +1,31 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'dll_hash',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ ],
+ 'sources': [
+ 'dll_hash/dll_hash.cc',
+ 'dll_hash/dll_hash.h',
+ ],
+ },
+ {
+ 'target_name': 'dll_hash_main',
+ 'type': 'executable',
+ 'dependencies': [
+ 'dll_hash',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'dll_hash/dll_hash_main.cc',
+ ],
+ }
+ ]
+} \ No newline at end of file
diff --git a/chrome_elf/dll_hash/dll_hash.cc b/chrome_elf/dll_hash/dll_hash.cc
new file mode 100644
index 0000000..ecd1491
--- /dev/null
+++ b/chrome_elf/dll_hash/dll_hash.cc
@@ -0,0 +1,14 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/hash.h"
+#include "chrome_elf/dll_hash/dll_hash.h"
+
+int DllNameToHash(std::string dll_name) {
+ uint32 data = base::Hash(dll_name);
+
+ // Strip off the signed bit because UMA doesn't support negative values,
+ // but takes a signed int as input.
+ return static_cast<int>(data & 0x7fffffff);
+}
diff --git a/chrome_elf/dll_hash/dll_hash.h b/chrome_elf/dll_hash/dll_hash.h
new file mode 100644
index 0000000..82bec8a
--- /dev/null
+++ b/chrome_elf/dll_hash/dll_hash.h
@@ -0,0 +1,13 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_ELF_DLL_HASH_DLL_HASH_H_
+#define CHROME_ELF_DLL_HASH_DLL_HASH_H_
+
+#include <string>
+
+// Convert a dll name to a hash that can be sent via UMA.
+int DllNameToHash(std::string dll_name);
+
+#endif // CHROME_ELF_DLL_HASH_DLL_HASH_H_
diff --git a/chrome_elf/dll_hash/dll_hash_main.cc b/chrome_elf/dll_hash/dll_hash_main.cc
new file mode 100644
index 0000000..a360263
--- /dev/null
+++ b/chrome_elf/dll_hash/dll_hash_main.cc
@@ -0,0 +1,28 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This is a utility executable used for generating hashes for dll names
+// for inclusion in tools/metrics/histograms/histograms.xml. Every
+// dll name must have a corresponding entry in the enum there.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "chrome_elf/dll_hash/dll_hash.h"
+
+int main(int argc, char** argv) {
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <dll name> <dll name> <...>\n", argv[0]);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Prints hashes for dll names.\n");
+ fprintf(stderr, "Example: %s \"my_dll.dll\" \"user32.dll\"\n", argv[0]);
+ return 1;
+ }
+ for (int i = 1; i < argc; i++) {
+ int hash = DllNameToHash(std::string(argv[i]));
+ printf("<int value=\"%d\" label=\"%s\"/>\n", hash, argv[i]);
+ }
+ return 0;
+}
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 2060650..f69beeb 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -1376,6 +1376,13 @@ other types of suffix sets.
</summary>
</histogram>
+<histogram name="Blacklist.Blocked" units="DllHash">
+ <summary>
+ Records the name hashes of all the dlls that are blocked from the browser
+ process.
+ </summary>
+</histogram>
+
<histogram name="Blacklist.PatchedInRenderer" enum="BooleanHit">
<summary>
Counts the number of times a renderer process is started with the browser
@@ -25468,6 +25475,15 @@ other types of suffix sets.
<int value="20" label="SQLite Integrity Web Data Test"/>
</enum>
+<enum name="DllHash" type="int">
+<!-- Generated by chrome_elf/dll_hash_for_uma/dll_hash_for_uma_main.cc -->
+
+ <int value="803283353" label="lmrn.dll"/>
+ <int value="989714890" label="datamngr.dll"/>
+ <int value="1270622879" label="hk.dll"/>
+ <int value="2132270559" label="libsvn_tsvn32.dll"/>
+</enum>
+
<enum name="DNSEmptyAddressListAndNoError" type="int">
<int value="0" label="Error reported or Address List is not empty"/>
<int value="1" label="Success reported but Address List is empty"/>