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

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: Made csharp's changes. 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
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,
58 reinterpret_cast<LPBYTE>(&blacklist_state),
59 sizeof(blacklist_state));
60 ::RegCloseKey(*key);
61 key = NULL;
62 }
63 } 57 }
64 58
65 } // namespace 59 } // namespace
66 60
67 namespace blacklist { 61 namespace blacklist {
68 62
69 #if defined(_WIN64) 63 #if defined(_WIN64)
70 // Allocate storage for the pointer to the old NtMapViewOfSectionFunction. 64 // Allocate storage for the pointer to the old NtMapViewOfSectionFunction.
71 #pragma section(".oldntmap",write,read) 65 #pragma section(".oldntmap",write,read)
72 __declspec(allocate(".oldntmap")) 66 __declspec(allocate(".oldntmap"))
73 NtMapViewOfSectionFunction g_nt_map_view_of_section_func = NULL; 67 NtMapViewOfSectionFunction g_nt_map_view_of_section_func = NULL;
74 #endif 68 #endif
75 69
70 bool HandlePreviousBeacon(HKEY* key, DWORD blacklist_state) {
csharp 2014/06/11 13:34:43 This function shouldn't be indented and can be mov
krstnmnlsn 2014/06/11 16:35:27 Done.
71 LONG result;
72 if (blacklist_state == BLACKLIST_SETUP_RUNNING) {
73 // Some part of the blacklist setup failed last time. If this has occured
74 // some minimum number of times in a row we switch the state to failed and
75 // skip setting up the blacklist.
76 DWORD attempt_count = 0;
77 DWORD attempt_count_size = sizeof(attempt_count);
78 DWORD attempt_count_type = 0;
79 result = ::RegQueryValueEx(*key,
80 kBeaconAttemptCount,
81 0,
82 &attempt_count_type,
83 reinterpret_cast<LPBYTE>(&attempt_count),
84 &attempt_count_size);
85
86 if (result == ERROR_FILE_NOT_FOUND) {
csharp 2014/06/11 13:34:43 I'm not sure we need lines 88->95. It just sets th
krstnmnlsn 2014/06/11 16:35:27 Done.
87 attempt_count = 0;
88 attempt_count_type = REG_DWORD;
89 result = SetDWValue(key, kBeaconAttemptCount, attempt_count);
90 }
91
92 if (result != ERROR_SUCCESS || attempt_count_type != REG_DWORD) {
93 ::RegCloseKey(*key);
csharp 2014/06/11 13:34:43 It probably is cleaner to move all the ::RegCloseK
krstnmnlsn 2014/06/11 16:35:27 Yea I realized after that might be better. Done.
94 return false;
95 }
96
97 attempt_count = attempt_count + 1;
csharp 2014/06/11 13:34:43 ++attempt_count instead?
krstnmnlsn 2014/06/11 16:35:27 Done.
98 result = SetDWValue(key, kBeaconAttemptCount, attempt_count);
99 if (result != ERROR_SUCCESS) {
csharp 2014/06/11 13:34:43 I wonder if we shouldn't try to abort here. If we
krstnmnlsn 2014/06/11 16:35:27 Yeah, I don't think taking it out even introduces
100 ::RegCloseKey(*key);
101 return false;
102 }
103
104 if (attempt_count >= blacklist::kBeaconMaxAttempts) {
105 blacklist_state = BLACKLIST_SETUP_FAILED;
106 SetDWValue(key, kBeaconState, blacklist_state);
107 ::RegCloseKey(*key);
108 return false;
109 }
110 } else if (blacklist_state == BLACKLIST_ENABLED) {
111 // If the blacklist succeeded on the previous run reset the failure
112 // counter.
113 result = SetDWValue(key, kBeaconAttemptCount, static_cast<DWORD>(0));
114 if (result != ERROR_SUCCESS) {
115 ::RegCloseKey(*key);
116 return false;
117 }
118 }
119 return true;
120 }
121
76 bool LeaveSetupBeacon() { 122 bool LeaveSetupBeacon() {
77 HKEY key = NULL; 123 HKEY key = NULL;
78 DWORD disposition = 0; 124 DWORD disposition = 0;
79 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, 125 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER,
80 kRegistryBeaconPath, 126 kRegistryBeaconPath,
81 0, 127 0,
82 NULL, 128 NULL,
83 REG_OPTION_NON_VOLATILE, 129 REG_OPTION_NON_VOLATILE,
84 KEY_QUERY_VALUE | KEY_SET_VALUE, 130 KEY_QUERY_VALUE | KEY_SET_VALUE,
85 NULL, 131 NULL,
86 &key, 132 &key,
87 &disposition); 133 &disposition);
88 if (result != ERROR_SUCCESS) 134 if (result != ERROR_SUCCESS)
89 return false; 135 return false;
90 136
91 // Retrieve the current blacklist state. 137 // Retrieve the current blacklist state.
92 DWORD blacklist_state = BLACKLIST_DISABLED; 138 DWORD blacklist_state = BLACKLIST_STATE_MAX;
93 DWORD blacklist_state_size = sizeof(blacklist_state); 139 DWORD blacklist_state_size = sizeof(blacklist_state);
94 DWORD type = 0; 140 DWORD type = 0;
95 result = ::RegQueryValueEx(key, 141 result = ::RegQueryValueEx(key,
96 kBeaconState, 142 kBeaconState,
97 0, 143 0,
98 &type, 144 &type,
99 reinterpret_cast<LPBYTE>(&blacklist_state), 145 reinterpret_cast<LPBYTE>(&blacklist_state),
100 &blacklist_state_size); 146 &blacklist_state_size);
101 147
102 if (blacklist_state != BLACKLIST_ENABLED || 148 if (blacklist_state == BLACKLIST_DISABLED || result != ERROR_SUCCESS ||
103 result != ERROR_SUCCESS || type != REG_DWORD) { 149 type != REG_DWORD) {
104 ::RegCloseKey(key); 150 ::RegCloseKey(key);
105 return false; 151 return false;
106 } 152 }
107 153
108 // Mark the blacklist setup code as running so if it crashes the blacklist 154 if (!HandlePreviousBeacon(&key, blacklist_state))
csharp 2014/06/11 13:34:43 This name seems a bit vague, I don't really have a
krstnmnlsn 2014/06/11 16:35:27 Yea I couldn't think of a reasonably short but als
109 // won't be enabled for the next run. 155 return false;
110 blacklist_state = BLACKLIST_SETUP_RUNNING; 156
111 result = ::RegSetValueEx(key, 157 result = SetDWValue(&key, kBeaconState, BLACKLIST_SETUP_RUNNING);
112 kBeaconState,
113 0,
114 REG_DWORD,
115 reinterpret_cast<LPBYTE>(&blacklist_state),
116 sizeof(blacklist_state));
117 ::RegCloseKey(key); 158 ::RegCloseKey(key);
118 159
119 return (result == ERROR_SUCCESS); 160 return (result == ERROR_SUCCESS);
120 } 161 }
121 162
122 bool ResetBeacon() { 163 bool ResetBeacon() {
123 HKEY key = NULL; 164 HKEY key = NULL;
124 DWORD disposition = 0; 165 DWORD disposition = 0;
125 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, 166 LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER,
126 kRegistryBeaconPath, 167 kRegistryBeaconPath,
127 0, 168 0,
128 NULL, 169 NULL,
129 REG_OPTION_NON_VOLATILE, 170 REG_OPTION_NON_VOLATILE,
130 KEY_QUERY_VALUE | KEY_SET_VALUE, 171 KEY_QUERY_VALUE | KEY_SET_VALUE,
131 NULL, 172 NULL,
132 &key, 173 &key,
133 &disposition); 174 &disposition);
134 if (result != ERROR_SUCCESS) 175 if (result != ERROR_SUCCESS)
135 return false; 176 return false;
136 177
137 DWORD blacklist_state = BLACKLIST_ENABLED; 178 DWORD blacklist_state = BLACKLIST_STATE_MAX;
138 result = ::RegSetValueEx(key, 179 DWORD blacklist_state_size = sizeof(blacklist_state);
139 kBeaconState, 180 DWORD type = 0;
140 0, 181 result = ::RegQueryValueEx(key,
141 REG_DWORD, 182 kBeaconState,
142 reinterpret_cast<LPBYTE>(&blacklist_state), 183 0,
143 sizeof(blacklist_state)); 184 &type,
185 reinterpret_cast<LPBYTE>(&blacklist_state),
186 &blacklist_state_size);
187
188 if (result != ERROR_SUCCESS || type != REG_DWORD) {
189 ::RegCloseKey(key);
190 return false;
191 }
192
193 // Reaching this point with the setup running state means the setup
194 // succeeded and so we reset to enabled. Any other state indicates that setup
195 // was skipped; in that case we leave the state alone for later recording.
196 if (blacklist_state == BLACKLIST_SETUP_RUNNING)
197 result = SetDWValue(&key, kBeaconState, BLACKLIST_ENABLED);
198
144 ::RegCloseKey(key); 199 ::RegCloseKey(key);
145
146 return (result == ERROR_SUCCESS); 200 return (result == ERROR_SUCCESS);
147 } 201 }
148 202
149 int BlacklistSize() { 203 int BlacklistSize() {
150 int size = -1; 204 int size = -1;
151 while (blacklist::g_troublesome_dlls[++size] != NULL) {} 205 while (blacklist::g_troublesome_dlls[++size] != NULL) {}
152 206
153 return size; 207 return size;
154 } 208 }
155 209
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 287
234 bool Initialize(bool force) { 288 bool Initialize(bool force) {
235 // Check to see that we found the functions we need in ntdll. 289 // Check to see that we found the functions we need in ntdll.
236 if (!InitializeInterceptImports()) 290 if (!InitializeInterceptImports())
237 return false; 291 return false;
238 292
239 // Check to see if this is a non-browser process, abort if so. 293 // Check to see if this is a non-browser process, abort if so.
240 if (IsNonBrowserProcess()) 294 if (IsNonBrowserProcess())
241 return false; 295 return false;
242 296
243 // Check to see if a beacon is present, abort if so. 297 // Check to see if the blacklist beacon is still set to running (indicating a
298 // failure) or disabled, and abort if so.
244 if (!force && !LeaveSetupBeacon()) 299 if (!force && !LeaveSetupBeacon())
245 return false; 300 return false;
246 301
247 // It is possible for other dlls to have already patched code by now and 302 // It is possible for other dlls to have already patched code by now and
248 // attempting to patch their code might result in crashes. 303 // attempting to patch their code might result in crashes.
249 const bool kRelaxed = false; 304 const bool kRelaxed = false;
250 305
251 // Create a thunk via the appropriate ServiceResolver instance. 306 // Create a thunk via the appropriate ServiceResolver instance.
252 sandbox::ServiceResolverThunk* thunk = GetThunk(kRelaxed); 307 sandbox::ServiceResolverThunk* thunk = GetThunk(kRelaxed);
253 308
254 // Don't try blacklisting on unsupported OS versions. 309 // Don't try blacklisting on unsupported OS versions.
255 if (!thunk) 310 if (!thunk)
256 return false; 311 return false;
257 312
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); 313 BYTE* thunk_storage = reinterpret_cast<BYTE*>(&g_thunk_storage);
283 314
284 // Mark the thunk storage as readable and writeable, since we 315 // Mark the thunk storage as readable and writeable, since we
285 // ready to write to it. 316 // ready to write to it.
286 DWORD old_protect = 0; 317 DWORD old_protect = 0;
287 if (!VirtualProtect(&g_thunk_storage, 318 if (!VirtualProtect(&g_thunk_storage,
288 sizeof(g_thunk_storage), 319 sizeof(g_thunk_storage),
289 PAGE_EXECUTE_READWRITE, 320 PAGE_EXECUTE_READWRITE,
290 &old_protect)) { 321 &old_protect)) {
291 RecordSuccessfulThunkSetup(&key);
292 return false; 322 return false;
293 } 323 }
294 324
295 thunk->AllowLocalPatches(); 325 thunk->AllowLocalPatches();
296 326
297 // We declare this early so it can be used in the 64-bit block below and 327 // 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. 328 // still work on 32-bit build when referenced at the end of the function.
299 BOOL page_executable = false; 329 BOOL page_executable = false;
300 330
301 // Replace the default NtMapViewOfSection with our patched version. 331 // Replace the default NtMapViewOfSection with our patched version.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 363
334 // Record if we have initialized the blacklist. 364 // Record if we have initialized the blacklist.
335 g_blacklist_initialized = NT_SUCCESS(ret); 365 g_blacklist_initialized = NT_SUCCESS(ret);
336 366
337 // Mark the thunk storage as executable and prevent any future writes to it. 367 // Mark the thunk storage as executable and prevent any future writes to it.
338 page_executable = page_executable && VirtualProtect(&g_thunk_storage, 368 page_executable = page_executable && VirtualProtect(&g_thunk_storage,
339 sizeof(g_thunk_storage), 369 sizeof(g_thunk_storage),
340 PAGE_EXECUTE_READ, 370 PAGE_EXECUTE_READ,
341 &old_protect); 371 &old_protect);
342 372
343 RecordSuccessfulThunkSetup(&key);
344
345 return NT_SUCCESS(ret) && page_executable; 373 return NT_SUCCESS(ret) && page_executable;
346 } 374 }
347 375
348 } // namespace blacklist 376 } // namespace blacklist
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698