Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(328)

Side by Side Diff: chrome_elf/blacklist/blacklist.cc

Issue 311893005: Can now adjust the number of retries before the blacklist is disabled. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Mostly clarifying comments. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome_elf/blacklist/blacklist.h ('k') | chrome_elf/blacklist/test/blacklist_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 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 "chrome_elf/blacklist/blacklist.h" 5 #include "chrome_elf/blacklist/blacklist.h"
6 6
7 #include <assert.h> 7 #include <assert.h>
8 #include <string.h> 8 #include <string.h>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 28 matching lines...) Expand all
39 // an extra allocation at run time. 39 // an extra allocation at run time.
40 #pragma section(".crthunk",read,execute) 40 #pragma section(".crthunk",read,execute)
41 __declspec(allocate(".crthunk")) sandbox::ThunkData g_thunk_storage; 41 __declspec(allocate(".crthunk")) sandbox::ThunkData g_thunk_storage;
42 42
43 namespace { 43 namespace {
44 44
45 // Record if the blacklist was successfully initialized so processes can easily 45 // Record if the blacklist was successfully initialized so processes can easily
46 // determine if the blacklist is enabled for them. 46 // determine if the blacklist is enabled for them.
47 bool g_blacklist_initialized = false; 47 bool g_blacklist_initialized = false;
48 48
49 // Record that the thunk setup completed succesfully and close the registry 49 // Helper to set DWORD registry values.
50 // key handle since it is no longer needed. 50 DWORD SetDWValue(HKEY* key, const wchar_t* property, DWORD value) {
51 void RecordSuccessfulThunkSetup(HKEY* key) { 51 return ::RegSetValueEx(*key,
52 if (key != NULL) { 52 property,
53 DWORD blacklist_state = blacklist::BLACKLIST_SETUP_RUNNING; 53 0,
54 ::RegSetValueEx(*key, 54 REG_DWORD,
55 blacklist::kBeaconState, 55 reinterpret_cast<LPBYTE>(&value),
56 0, 56 sizeof(value));
57 REG_DWORD, 57 }
58 reinterpret_cast<LPBYTE>(&blacklist_state), 58
59 sizeof(blacklist_state)); 59 bool HandlePreviousBeacon(HKEY* key, DWORD blacklist_state) {
csharp 2014/06/11 17:07:13 GenerateStateFromBeaconAndAttemptCount?
krstnmnlsn 2014/06/11 17:55:19 Done.
60 ::RegCloseKey(*key); 60 LONG result;
61 key = NULL; 61 if (blacklist_state == blacklist::BLACKLIST_SETUP_RUNNING) {
62 // Some part of the blacklist setup failed last time. If this has occured
63 // some minimum number of times in a row we switch the state to failed and
csharp 2014/06/11 17:07:13 "some minimum number of "-> "blacklist::kBeaconMax
krstnmnlsn 2014/06/11 17:55:19 Done.
64 // skip setting up the blacklist.
65 DWORD attempt_count = 0;
66 DWORD attempt_count_size = sizeof(attempt_count);
67 DWORD attempt_count_type = 0;
68 result = ::RegQueryValueEx(*key,
69 blacklist::kBeaconAttemptCount,
70 0,
csharp 2014/06/11 17:07:13 Please use NULL instead of 0
krstnmnlsn 2014/06/11 17:55:19 Leaving this until we decide to change all of them
71 &attempt_count_type,
csharp 2014/06/11 17:07:13 Since we don't examine this value anymore can we g
krstnmnlsn 2014/06/11 17:55:19 Done.
72 reinterpret_cast<LPBYTE>(&attempt_count),
73 &attempt_count_size);
74
75 if (result == ERROR_FILE_NOT_FOUND)
76 attempt_count = 0;
77 else if (result != ERROR_SUCCESS)
78 return false;
79
80 ++attempt_count;
81 SetDWValue(key, blacklist::kBeaconAttemptCount, attempt_count);
82
83 if (attempt_count >= blacklist::kBeaconMaxAttempts) {
84 blacklist_state = blacklist::BLACKLIST_SETUP_FAILED;
85 SetDWValue(key, blacklist::kBeaconState, blacklist_state);
86 return false;
87 }
88 } else if (blacklist_state == blacklist::BLACKLIST_ENABLED) {
89 // If the blacklist succeeded on the previous run reset the failure
90 // counter.
91 result =
92 SetDWValue(key, blacklist::kBeaconAttemptCount, static_cast<DWORD>(0));
93 if (result != ERROR_SUCCESS) {
94 return false;
95 }
62 } 96 }
97 return true;
63 } 98 }
64 99
65 } // namespace 100 } // namespace
66 101
67 namespace blacklist { 102 namespace blacklist {
68 103
69 #if defined(_WIN64) 104 #if defined(_WIN64)
70 // Allocate storage for the pointer to the old NtMapViewOfSectionFunction. 105 // Allocate storage for the pointer to the old NtMapViewOfSectionFunction.
71 #pragma section(".oldntmap",write,read) 106 #pragma section(".oldntmap",write,read)
72 __declspec(allocate(".oldntmap")) 107 __declspec(allocate(".oldntmap"))
73 NtMapViewOfSectionFunction g_nt_map_view_of_section_func = NULL; 108 NtMapViewOfSectionFunction g_nt_map_view_of_section_func = NULL;
74 #endif 109 #endif
75 110
76 bool LeaveSetupBeacon() { 111 bool LeaveSetupBeacon() {
77 HKEY key = NULL; 112 HKEY key = NULL;
78 DWORD disposition = 0; 113 DWORD disposition = 0;
79 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, 114 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER,
80 kRegistryBeaconPath, 115 kRegistryBeaconPath,
81 0, 116 0,
82 NULL, 117 NULL,
83 REG_OPTION_NON_VOLATILE, 118 REG_OPTION_NON_VOLATILE,
84 KEY_QUERY_VALUE | KEY_SET_VALUE, 119 KEY_QUERY_VALUE | KEY_SET_VALUE,
85 NULL, 120 NULL,
86 &key, 121 &key,
87 &disposition); 122 &disposition);
88 if (result != ERROR_SUCCESS) 123 if (result != ERROR_SUCCESS)
89 return false; 124 return false;
90 125
91 // Retrieve the current blacklist state. 126 // Retrieve the current blacklist state.
92 DWORD blacklist_state = BLACKLIST_DISABLED; 127 DWORD blacklist_state = BLACKLIST_STATE_MAX;
93 DWORD blacklist_state_size = sizeof(blacklist_state); 128 DWORD blacklist_state_size = sizeof(blacklist_state);
94 DWORD type = 0; 129 DWORD type = 0;
95 result = ::RegQueryValueEx(key, 130 result = ::RegQueryValueEx(key,
96 kBeaconState, 131 kBeaconState,
97 0, 132 0,
98 &type, 133 &type,
99 reinterpret_cast<LPBYTE>(&blacklist_state), 134 reinterpret_cast<LPBYTE>(&blacklist_state),
100 &blacklist_state_size); 135 &blacklist_state_size);
101 136
102 if (blacklist_state != BLACKLIST_ENABLED || 137 if (blacklist_state == BLACKLIST_DISABLED || result != ERROR_SUCCESS ||
103 result != ERROR_SUCCESS || type != REG_DWORD) { 138 type != REG_DWORD) {
104 ::RegCloseKey(key); 139 ::RegCloseKey(key);
105 return false; 140 return false;
106 } 141 }
107 142
108 // Mark the blacklist setup code as running so if it crashes the blacklist 143 if (!HandlePreviousBeacon(&key, blacklist_state)) {
109 // won't be enabled for the next run. 144 ::RegCloseKey(key);
110 blacklist_state = BLACKLIST_SETUP_RUNNING; 145 return false;
111 result = ::RegSetValueEx(key, 146 }
112 kBeaconState, 147
113 0, 148 result = SetDWValue(&key, kBeaconState, BLACKLIST_SETUP_RUNNING);
114 REG_DWORD,
115 reinterpret_cast<LPBYTE>(&blacklist_state),
116 sizeof(blacklist_state));
117 ::RegCloseKey(key); 149 ::RegCloseKey(key);
118 150
119 return (result == ERROR_SUCCESS); 151 return (result == ERROR_SUCCESS);
120 } 152 }
121 153
122 bool ResetBeacon() { 154 bool ResetBeacon() {
123 HKEY key = NULL; 155 HKEY key = NULL;
124 DWORD disposition = 0; 156 DWORD disposition = 0;
125 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, 157 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER,
126 kRegistryBeaconPath, 158 kRegistryBeaconPath,
127 0, 159 0,
128 NULL, 160 NULL,
129 REG_OPTION_NON_VOLATILE, 161 REG_OPTION_NON_VOLATILE,
130 KEY_QUERY_VALUE | KEY_SET_VALUE, 162 KEY_QUERY_VALUE | KEY_SET_VALUE,
131 NULL, 163 NULL,
132 &key, 164 &key,
133 &disposition); 165 &disposition);
134 if (result != ERROR_SUCCESS) 166 if (result != ERROR_SUCCESS)
135 return false; 167 return false;
136 168
137 DWORD blacklist_state = BLACKLIST_ENABLED; 169 DWORD blacklist_state = BLACKLIST_STATE_MAX;
138 result = ::RegSetValueEx(key, 170 DWORD blacklist_state_size = sizeof(blacklist_state);
139 kBeaconState, 171 DWORD type = 0;
140 0, 172 result = ::RegQueryValueEx(key,
141 REG_DWORD, 173 kBeaconState,
142 reinterpret_cast<LPBYTE>(&blacklist_state), 174 0,
143 sizeof(blacklist_state)); 175 &type,
176 reinterpret_cast<LPBYTE>(&blacklist_state),
177 &blacklist_state_size);
178
179 if (result != ERROR_SUCCESS || type != REG_DWORD) {
180 ::RegCloseKey(key);
181 return false;
182 }
183
184 // Reaching this point with the setup running state means the setup
185 // succeeded and so we reset to enabled. Any other state indicates that setup
186 // was skipped; in that case we leave the state alone for later recording.
187 if (blacklist_state == BLACKLIST_SETUP_RUNNING)
188 result = SetDWValue(&key, kBeaconState, BLACKLIST_ENABLED);
189
144 ::RegCloseKey(key); 190 ::RegCloseKey(key);
145
146 return (result == ERROR_SUCCESS); 191 return (result == ERROR_SUCCESS);
147 } 192 }
148 193
149 int BlacklistSize() { 194 int BlacklistSize() {
150 int size = -1; 195 int size = -1;
151 while (blacklist::g_troublesome_dlls[++size] != NULL) {} 196 while (blacklist::g_troublesome_dlls[++size] != NULL) {}
152 197
153 return size; 198 return size;
154 } 199 }
155 200
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 278
234 bool Initialize(bool force) { 279 bool Initialize(bool force) {
235 // Check to see that we found the functions we need in ntdll. 280 // Check to see that we found the functions we need in ntdll.
236 if (!InitializeInterceptImports()) 281 if (!InitializeInterceptImports())
237 return false; 282 return false;
238 283
239 // Check to see if this is a non-browser process, abort if so. 284 // Check to see if this is a non-browser process, abort if so.
240 if (IsNonBrowserProcess()) 285 if (IsNonBrowserProcess())
241 return false; 286 return false;
242 287
243 // Check to see if a beacon is present, abort if so. 288 // Check to see if the blacklist beacon is still set to running (indicating a
289 // failure) or disabled, and abort if so.
244 if (!force && !LeaveSetupBeacon()) 290 if (!force && !LeaveSetupBeacon())
245 return false; 291 return false;
246 292
247 // It is possible for other dlls to have already patched code by now and 293 // It is possible for other dlls to have already patched code by now and
248 // attempting to patch their code might result in crashes. 294 // attempting to patch their code might result in crashes.
249 const bool kRelaxed = false; 295 const bool kRelaxed = false;
250 296
251 // Create a thunk via the appropriate ServiceResolver instance. 297 // Create a thunk via the appropriate ServiceResolver instance.
252 sandbox::ServiceResolverThunk* thunk = GetThunk(kRelaxed); 298 sandbox::ServiceResolverThunk* thunk = GetThunk(kRelaxed);
253 299
254 // Don't try blacklisting on unsupported OS versions. 300 // Don't try blacklisting on unsupported OS versions.
255 if (!thunk) 301 if (!thunk)
256 return false; 302 return false;
257 303
258 // Record that we are starting the thunk setup code.
259 HKEY key = NULL;
260 DWORD disposition = 0;
261 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER,
262 kRegistryBeaconPath,
263 0,
264 NULL,
265 REG_OPTION_NON_VOLATILE,
266 KEY_QUERY_VALUE | KEY_SET_VALUE,
267 NULL,
268 &key,
269 &disposition);
270 if (result == ERROR_SUCCESS) {
271 DWORD blacklist_state = BLACKLIST_THUNK_SETUP;
272 ::RegSetValueEx(key,
273 kBeaconState,
274 0,
275 REG_DWORD,
276 reinterpret_cast<LPBYTE>(&blacklist_state),
277 sizeof(blacklist_state));
278 } else {
279 key = NULL;
280 }
281
282 BYTE* thunk_storage = reinterpret_cast<BYTE*>(&g_thunk_storage); 304 BYTE* thunk_storage = reinterpret_cast<BYTE*>(&g_thunk_storage);
283 305
284 // Mark the thunk storage as readable and writeable, since we 306 // Mark the thunk storage as readable and writeable, since we
285 // ready to write to it. 307 // ready to write to it.
286 DWORD old_protect = 0; 308 DWORD old_protect = 0;
287 if (!VirtualProtect(&g_thunk_storage, 309 if (!VirtualProtect(&g_thunk_storage,
288 sizeof(g_thunk_storage), 310 sizeof(g_thunk_storage),
289 PAGE_EXECUTE_READWRITE, 311 PAGE_EXECUTE_READWRITE,
290 &old_protect)) { 312 &old_protect)) {
291 RecordSuccessfulThunkSetup(&key);
292 return false; 313 return false;
293 } 314 }
294 315
295 thunk->AllowLocalPatches(); 316 thunk->AllowLocalPatches();
296 317
297 // We declare this early so it can be used in the 64-bit block below and 318 // We declare this early so it can be used in the 64-bit block below and
298 // still work on 32-bit build when referenced at the end of the function. 319 // still work on 32-bit build when referenced at the end of the function.
299 BOOL page_executable = false; 320 BOOL page_executable = false;
300 321
301 // Replace the default NtMapViewOfSection with our patched version. 322 // Replace the default NtMapViewOfSection with our patched version.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 354
334 // Record if we have initialized the blacklist. 355 // Record if we have initialized the blacklist.
335 g_blacklist_initialized = NT_SUCCESS(ret); 356 g_blacklist_initialized = NT_SUCCESS(ret);
336 357
337 // Mark the thunk storage as executable and prevent any future writes to it. 358 // Mark the thunk storage as executable and prevent any future writes to it.
338 page_executable = page_executable && VirtualProtect(&g_thunk_storage, 359 page_executable = page_executable && VirtualProtect(&g_thunk_storage,
339 sizeof(g_thunk_storage), 360 sizeof(g_thunk_storage),
340 PAGE_EXECUTE_READ, 361 PAGE_EXECUTE_READ,
341 &old_protect); 362 &old_protect);
342 363
343 RecordSuccessfulThunkSetup(&key);
344
345 return NT_SUCCESS(ret) && page_executable; 364 return NT_SUCCESS(ret) && page_executable;
346 } 365 }
347 366
348 } // namespace blacklist 367 } // namespace blacklist
OLDNEW
« no previous file with comments | « chrome_elf/blacklist/blacklist.h ('k') | chrome_elf/blacklist/test/blacklist_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698