| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "base/bind.h" |
| 6 #include "base/md5.h" |
| 5 #include "base/metrics/field_trial.h" | 7 #include "base/metrics/field_trial.h" |
| 6 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "base/metrics/sparse_histogram.h" |
| 7 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| 8 #include "base/win/registry.h" | 11 #include "base/win/registry.h" |
| 9 #include "chrome/browser/chrome_elf_init_win.h" | 12 #include "chrome/browser/chrome_elf_init_win.h" |
| 10 #include "chrome_elf/blacklist/blacklist.h" | 13 #include "chrome_elf/blacklist/blacklist.h" |
| 14 #include "content/public/browser/browser_thread.h" |
| 11 #include "version.h" // NOLINT | 15 #include "version.h" // NOLINT |
| 12 | 16 |
| 13 namespace { | 17 namespace { |
| 14 | 18 |
| 15 const char kBrowserBlacklistTrialName[] = "BrowserBlacklist"; | 19 const char kBrowserBlacklistTrialName[] = "BrowserBlacklist"; |
| 16 const char kBrowserBlacklistTrialEnabledGroupName[] = "Enabled"; | 20 const char kBrowserBlacklistTrialEnabledGroupName[] = "Enabled"; |
| 17 | 21 |
| 22 // How long to wait, in seconds, before reporting for the second (and last |
| 23 // time), what dlls were blocked from the browser process. |
| 24 const int kBlacklistReportingDelaySec = 600; |
| 25 |
| 18 // This enum is used to define the buckets for an enumerated UMA histogram. | 26 // This enum is used to define the buckets for an enumerated UMA histogram. |
| 19 // Hence, | 27 // Hence, |
| 20 // (a) existing enumerated constants should never be deleted or reordered, and | 28 // (a) existing enumerated constants should never be deleted or reordered, and |
| 21 // (b) new constants should only be appended in front of | 29 // (b) new constants should only be appended in front of |
| 22 // BLACKLIST_SETUP_EVENT_MAX. | 30 // BLACKLIST_SETUP_EVENT_MAX. |
| 23 enum BlacklistSetupEventType { | 31 enum BlacklistSetupEventType { |
| 24 // The blacklist beacon has placed to enable the browser blacklisting. | 32 // The blacklist beacon has placed to enable the browser blacklisting. |
| 25 BLACKLIST_SETUP_ENABLED = 0, | 33 BLACKLIST_SETUP_ENABLED = 0, |
| 26 | 34 |
| 27 // The blacklist was successfully enabled. | 35 // The blacklist was successfully enabled. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 39 // Always keep this at the end. | 47 // Always keep this at the end. |
| 40 BLACKLIST_SETUP_EVENT_MAX, | 48 BLACKLIST_SETUP_EVENT_MAX, |
| 41 }; | 49 }; |
| 42 | 50 |
| 43 void RecordBlacklistSetupEvent(BlacklistSetupEventType blacklist_setup_event) { | 51 void RecordBlacklistSetupEvent(BlacklistSetupEventType blacklist_setup_event) { |
| 44 UMA_HISTOGRAM_ENUMERATION("Blacklist.Setup", | 52 UMA_HISTOGRAM_ENUMERATION("Blacklist.Setup", |
| 45 blacklist_setup_event, | 53 blacklist_setup_event, |
| 46 BLACKLIST_SETUP_EVENT_MAX); | 54 BLACKLIST_SETUP_EVENT_MAX); |
| 47 } | 55 } |
| 48 | 56 |
| 57 // Report which DLLs were prevented from being loaded. |
| 58 void ReportSuccessfulBlocks() { |
| 59 typedef void (*SuccessfullyBlockedPtr)(const wchar_t**, int*); |
| 60 SuccessfullyBlockedPtr successfully_blocked = |
| 61 reinterpret_cast<SuccessfullyBlockedPtr>(GetProcAddress( |
| 62 GetModuleHandle(L"chrome_elf.dll"), "SuccessfullyBlocked")); |
| 63 |
| 64 if (!successfully_blocked) |
| 65 return; |
| 66 |
| 67 // Figure out how many dlls were blocked. |
| 68 int num_blocked_dlls = 0; |
| 69 successfully_blocked(NULL, &num_blocked_dlls); |
| 70 |
| 71 if (num_blocked_dlls == 0) |
| 72 return; |
| 73 |
| 74 // Now retrieve the list of blocked dlls. |
| 75 std::vector<const wchar_t*> blocked_dlls(num_blocked_dlls); |
| 76 successfully_blocked(&blocked_dlls[0], &num_blocked_dlls); |
| 77 |
| 78 // Send up the hashes of the blocked dlls via UMA. |
| 79 for (size_t i = 0; i < blocked_dlls.size(); ++i) { |
| 80 base::MD5Digest hash; |
| 81 base::MD5Sum(blocked_dlls[i], wcslen(blocked_dlls[i]), &hash); |
| 82 |
| 83 // Convert the md5 hash to an integer. Strip off the signed bit because |
| 84 // UMA doesn't support negative values, but takes a signed int as input. |
| 85 uint32 uma_hash = |
| 86 static_cast<int>(hash.a[0] + (hash.a[1] << 8) + (hash.a[2] << 12) + |
| 87 ((hash.a[3] * 0x7f) << 16)); |
| 88 |
| 89 UMA_HISTOGRAM_SPARSE_SLOWLY("Blacklist.Blocked", uma_hash); |
| 90 } |
| 91 } |
| 92 |
| 49 } // namespace | 93 } // namespace |
| 50 | 94 |
| 51 void InitializeChromeElf() { | 95 void InitializeChromeElf() { |
| 52 if (base::FieldTrialList::FindFullName(kBrowserBlacklistTrialName) == | 96 if (base::FieldTrialList::FindFullName(kBrowserBlacklistTrialName) == |
| 53 kBrowserBlacklistTrialEnabledGroupName) { | 97 kBrowserBlacklistTrialEnabledGroupName) { |
| 54 BrowserBlacklistBeaconSetup(); | 98 BrowserBlacklistBeaconSetup(); |
| 55 } else { | 99 } else { |
| 56 // Disable the blacklist for all future runs by removing the beacon. | 100 // Disable the blacklist for all future runs by removing the beacon. |
| 57 base::win::RegKey blacklist_registry_key(HKEY_CURRENT_USER); | 101 base::win::RegKey blacklist_registry_key(HKEY_CURRENT_USER); |
| 58 blacklist_registry_key.DeleteKey(blacklist::kRegistryBeaconPath); | 102 blacklist_registry_key.DeleteKey(blacklist::kRegistryBeaconPath); |
| 59 } | 103 } |
| 104 |
| 105 // Report all successful blacklist interceptions. |
| 106 ReportSuccessfulBlocks(); |
| 107 |
| 108 // Schedule another task to report all sucessful interceptions later. |
| 109 // This time delay should be long enough to catch any dlls that attempt to |
| 110 // inject after Chrome has started up. |
| 111 content::BrowserThread::PostDelayedTask( |
| 112 content::BrowserThread::UI, |
| 113 FROM_HERE, |
| 114 base::Bind(&ReportSuccessfulBlocks), |
| 115 base::TimeDelta::FromSeconds(kBlacklistReportingDelaySec)); |
| 60 } | 116 } |
| 61 | 117 |
| 62 void BrowserBlacklistBeaconSetup() { | 118 void BrowserBlacklistBeaconSetup() { |
| 63 base::win::RegKey blacklist_registry_key(HKEY_CURRENT_USER, | 119 base::win::RegKey blacklist_registry_key(HKEY_CURRENT_USER, |
| 64 blacklist::kRegistryBeaconPath, | 120 blacklist::kRegistryBeaconPath, |
| 65 KEY_QUERY_VALUE | KEY_SET_VALUE); | 121 KEY_QUERY_VALUE | KEY_SET_VALUE); |
| 66 | 122 |
| 67 // Find the last recorded blacklist version. | 123 // Find the last recorded blacklist version. |
| 68 base::string16 blacklist_version; | 124 base::string16 blacklist_version; |
| 69 blacklist_registry_key.ReadValue(blacklist::kBeaconVersion, | 125 blacklist_registry_key.ReadValue(blacklist::kBeaconVersion, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 | 168 |
| 113 // Since some part of the blacklist failed, ensure it is now disabled | 169 // Since some part of the blacklist failed, ensure it is now disabled |
| 114 // for this version. | 170 // for this version. |
| 115 if (blacklist_state != blacklist::BLACKLIST_DISABLED) { | 171 if (blacklist_state != blacklist::BLACKLIST_DISABLED) { |
| 116 blacklist_registry_key.WriteValue(blacklist::kBeaconState, | 172 blacklist_registry_key.WriteValue(blacklist::kBeaconState, |
| 117 blacklist::BLACKLIST_DISABLED); | 173 blacklist::BLACKLIST_DISABLED); |
| 118 } | 174 } |
| 119 } | 175 } |
| 120 } | 176 } |
| 121 } | 177 } |
| OLD | NEW |