Index: chrome_elf/blacklist/blacklist.cc |
diff --git a/chrome_elf/blacklist/blacklist.cc b/chrome_elf/blacklist/blacklist.cc |
index 8107ffcab39abeaebde41f90c73a90beefc36ac4..055b0abfc4cc172e609775bbedafe71c4191a5f7 100644 |
--- a/chrome_elf/blacklist/blacklist.cc |
+++ b/chrome_elf/blacklist/blacklist.cc |
@@ -59,20 +59,54 @@ namespace { |
// determine if the blacklist is enabled for them. |
bool g_blacklist_initialized = false; |
-// Record that the thunk setup completed succesfully and close the registry |
-// key handle since it is no longer needed. |
-void RecordSuccessfulThunkSetup(HKEY* key) { |
- if (key != NULL) { |
- DWORD blacklist_state = blacklist::BLACKLIST_SETUP_RUNNING; |
- ::RegSetValueEx(*key, |
- blacklist::kBeaconState, |
- 0, |
- REG_DWORD, |
- reinterpret_cast<LPBYTE>(&blacklist_state), |
- sizeof(blacklist_state)); |
- ::RegCloseKey(*key); |
- key = NULL; |
+// Helper to set DWORD registry values. |
+DWORD SetDWValue(HKEY* key, const wchar_t* property, DWORD value) { |
+ return ::RegSetValueEx(*key, |
+ property, |
+ 0, |
+ REG_DWORD, |
+ reinterpret_cast<LPBYTE>(&value), |
+ sizeof(value)); |
+} |
+ |
+bool GenerateStateFromBeaconAndAttemptCount(HKEY* key, DWORD blacklist_state) { |
+ LONG result = 0; |
+ if (blacklist_state == blacklist::BLACKLIST_SETUP_RUNNING) { |
+ // Some part of the blacklist setup failed last time. If this has occured |
+ // blacklist::kBeaconMaxAttempts times in a row we switch the state to |
+ // failed and skip setting up the blacklist. |
+ DWORD attempt_count = 0; |
+ DWORD attempt_count_size = sizeof(attempt_count); |
+ result = ::RegQueryValueEx(*key, |
+ blacklist::kBeaconAttemptCount, |
+ 0, |
+ NULL, |
+ reinterpret_cast<LPBYTE>(&attempt_count), |
+ &attempt_count_size); |
+ |
+ if (result == ERROR_FILE_NOT_FOUND) |
+ attempt_count = 0; |
+ else if (result != ERROR_SUCCESS) |
+ return false; |
+ |
+ ++attempt_count; |
+ SetDWValue(key, blacklist::kBeaconAttemptCount, attempt_count); |
+ |
+ if (attempt_count >= blacklist::kBeaconMaxAttempts) { |
+ blacklist_state = blacklist::BLACKLIST_SETUP_FAILED; |
+ SetDWValue(key, blacklist::kBeaconState, blacklist_state); |
+ return false; |
+ } |
+ } else if (blacklist_state == blacklist::BLACKLIST_ENABLED) { |
+ // If the blacklist succeeded on the previous run reset the failure |
+ // counter. |
+ result = |
+ SetDWValue(key, blacklist::kBeaconAttemptCount, static_cast<DWORD>(0)); |
+ if (result != ERROR_SUCCESS) { |
+ return false; |
+ } |
} |
+ return true; |
} |
} // namespace |
@@ -102,7 +136,7 @@ bool LeaveSetupBeacon() { |
return false; |
// Retrieve the current blacklist state. |
- DWORD blacklist_state = BLACKLIST_DISABLED; |
+ DWORD blacklist_state = BLACKLIST_STATE_MAX; |
DWORD blacklist_state_size = sizeof(blacklist_state); |
DWORD type = 0; |
result = ::RegQueryValueEx(key, |
@@ -112,21 +146,18 @@ bool LeaveSetupBeacon() { |
reinterpret_cast<LPBYTE>(&blacklist_state), |
&blacklist_state_size); |
- if (blacklist_state != BLACKLIST_ENABLED || |
- result != ERROR_SUCCESS || type != REG_DWORD) { |
+ if (blacklist_state == BLACKLIST_DISABLED || result != ERROR_SUCCESS || |
+ type != REG_DWORD) { |
+ ::RegCloseKey(key); |
+ return false; |
+ } |
+ |
+ if (!GenerateStateFromBeaconAndAttemptCount(&key, blacklist_state)) { |
::RegCloseKey(key); |
return false; |
} |
- // Mark the blacklist setup code as running so if it crashes the blacklist |
- // won't be enabled for the next run. |
- blacklist_state = BLACKLIST_SETUP_RUNNING; |
- result = ::RegSetValueEx(key, |
- kBeaconState, |
- 0, |
- REG_DWORD, |
- reinterpret_cast<LPBYTE>(&blacklist_state), |
- sizeof(blacklist_state)); |
+ result = SetDWValue(&key, kBeaconState, BLACKLIST_SETUP_RUNNING); |
::RegCloseKey(key); |
return (result == ERROR_SUCCESS); |
@@ -147,15 +178,28 @@ bool ResetBeacon() { |
if (result != ERROR_SUCCESS) |
return false; |
- DWORD blacklist_state = BLACKLIST_ENABLED; |
- result = ::RegSetValueEx(key, |
- kBeaconState, |
- 0, |
- REG_DWORD, |
- reinterpret_cast<LPBYTE>(&blacklist_state), |
- sizeof(blacklist_state)); |
- ::RegCloseKey(key); |
+ DWORD blacklist_state = BLACKLIST_STATE_MAX; |
+ DWORD blacklist_state_size = sizeof(blacklist_state); |
+ DWORD type = 0; |
+ result = ::RegQueryValueEx(key, |
+ kBeaconState, |
+ 0, |
+ &type, |
+ reinterpret_cast<LPBYTE>(&blacklist_state), |
+ &blacklist_state_size); |
+ if (result != ERROR_SUCCESS || type != REG_DWORD) { |
+ ::RegCloseKey(key); |
+ return false; |
+ } |
+ |
+ // Reaching this point with the setup running state means the setup |
+ // succeeded and so we reset to enabled. Any other state indicates that setup |
+ // was skipped; in that case we leave the state alone for later recording. |
+ if (blacklist_state == BLACKLIST_SETUP_RUNNING) |
+ result = SetDWValue(&key, kBeaconState, BLACKLIST_ENABLED); |
+ |
+ ::RegCloseKey(key); |
return (result == ERROR_SUCCESS); |
} |
@@ -253,7 +297,8 @@ bool Initialize(bool force) { |
if (IsNonBrowserProcess()) |
return false; |
- // Check to see if a beacon is present, abort if so. |
+ // Check to see if the blacklist beacon is still set to running (indicating a |
+ // failure) or disabled, and abort if so. |
if (!force && !LeaveSetupBeacon()) |
return false; |
@@ -268,30 +313,6 @@ bool Initialize(bool force) { |
if (!thunk) |
return false; |
- // Record that we are starting the thunk setup code. |
- HKEY key = NULL; |
- DWORD disposition = 0; |
- LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, |
- kRegistryBeaconPath, |
- 0, |
- NULL, |
- REG_OPTION_NON_VOLATILE, |
- KEY_QUERY_VALUE | KEY_SET_VALUE, |
- NULL, |
- &key, |
- &disposition); |
- if (result == ERROR_SUCCESS) { |
- DWORD blacklist_state = BLACKLIST_THUNK_SETUP; |
- ::RegSetValueEx(key, |
- kBeaconState, |
- 0, |
- REG_DWORD, |
- reinterpret_cast<LPBYTE>(&blacklist_state), |
- sizeof(blacklist_state)); |
- } else { |
- key = NULL; |
- } |
- |
BYTE* thunk_storage = reinterpret_cast<BYTE*>(&g_thunk_storage); |
// Mark the thunk storage as readable and writeable, since we |
@@ -301,7 +322,6 @@ bool Initialize(bool force) { |
sizeof(g_thunk_storage), |
PAGE_EXECUTE_READWRITE, |
&old_protect)) { |
- RecordSuccessfulThunkSetup(&key); |
return false; |
} |
@@ -353,8 +373,6 @@ bool Initialize(bool force) { |
PAGE_EXECUTE_READ, |
&old_protect); |
- RecordSuccessfulThunkSetup(&key); |
- |
AddDllsFromRegistryToBlacklist(); |
return NT_SUCCESS(ret) && page_executable; |