OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "webkit/plugins/npapi/webplugin_delegate_impl.h" | 5 #include "webkit/plugins/npapi/webplugin_delegate_impl.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
141 SIZE_T size, | 141 SIZE_T size, |
142 DWORD new_protect, | 142 DWORD new_protect, |
143 PDWORD old_protect); | 143 PDWORD old_protect); |
144 | 144 |
145 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_virtual_free = | 145 base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_virtual_free = |
146 LAZY_INSTANCE_INITIALIZER; | 146 LAZY_INSTANCE_INITIALIZER; |
147 BOOL (WINAPI *g_iat_orig_virtual_free)(LPVOID address, | 147 BOOL (WINAPI *g_iat_orig_virtual_free)(LPVOID address, |
148 SIZE_T size, | 148 SIZE_T size, |
149 DWORD free_type); | 149 DWORD free_type); |
150 | 150 |
151 const size_t kMaxPluginExecMemSize = 64 * 1024 * 1024; // 64mb. | 151 const size_t kMaxPluginExecMemSize = 16 * 1024 * 1024; // 16mb. |
152 const DWORD kExecPageMask = PAGE_EXECUTE | PAGE_EXECUTE_READ | | 152 const DWORD kExecPageMask = PAGE_EXECUTE | PAGE_EXECUTE_READ | |
153 PAGE_EXECUTE_READWRITE; | 153 PAGE_EXECUTE_READWRITE; |
154 static volatile intptr_t g_max_exec_mem_size; | 154 static volatile intptr_t g_max_exec_mem_size; |
155 static intptr_t g_exec_mem_size = 0; | 155 static intptr_t g_exec_mem_size = 0; |
156 static scoped_ptr<base::Lock> g_exec_mem_lock; | 156 static scoped_ptr<base::Lock> g_exec_mem_lock; |
157 | 157 |
158 size_t UpdateExecMemSize(intptr_t size) { | 158 size_t UpdateExecMemSize(intptr_t size) { |
159 base::AutoLock locked(*g_exec_mem_lock); | 159 base::AutoLock locked(*g_exec_mem_lock); |
160 g_exec_mem_size += size; | 160 g_exec_mem_size += size; |
161 // Floor to zero since shutdown may unmap pages created before our hooks. | 161 // Floor to zero since shutdown may unmap pages created before our hooks. |
162 if (g_exec_mem_size < 0) | 162 if (g_exec_mem_size < 0) |
163 g_exec_mem_size = 0; | 163 g_exec_mem_size = 0; |
164 if (g_exec_mem_size > g_max_exec_mem_size) | 164 if (g_exec_mem_size > g_max_exec_mem_size) |
165 g_max_exec_mem_size = g_exec_mem_size; | 165 g_max_exec_mem_size = g_exec_mem_size; |
166 | 166 |
167 return g_exec_mem_size; | 167 return g_exec_mem_size; |
168 } | 168 } |
169 | 169 |
170 // Throw a unique exception when the JIT limit is hit. | |
171 inline void RaiseJITException() { | |
172 static const ULONG parameters[] = {1, 0xabad1dea /* 2880249322 */ }; | |
173 ::RaiseException(EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, | |
174 2, parameters); | |
cpu_(ooo_6.6-7.5)
2012/02/23 01:06:10
instead of 2 use arraysize of whatever it is calle
| |
175 } | |
176 | |
170 // http://crbug.com/16114 | 177 // http://crbug.com/16114 |
171 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow | 178 // Enforces providing a valid device context in NPWindow, so that NPP_SetWindow |
172 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. | 179 // is never called with NPNWindoTypeDrawable and NPWindow set to NULL. |
173 // Doing so allows removing NPP_SetWindow call during painting a windowless | 180 // Doing so allows removing NPP_SetWindow call during painting a windowless |
174 // plugin, which otherwise could trigger layout change while painting by | 181 // plugin, which otherwise could trigger layout change while painting by |
175 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. | 182 // invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes. |
176 // TODO(dglazkov): If this approach doesn't produce regressions, move class to | 183 // TODO(dglazkov): If this approach doesn't produce regressions, move class to |
177 // webplugin_delegate_impl.h and implement for other platforms. | 184 // webplugin_delegate_impl.h and implement for other platforms. |
178 class DrawableContextEnforcer { | 185 class DrawableContextEnforcer { |
179 public: | 186 public: |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 // We need to track RX memory usage in plugins to prevent JIT spraying attacks. | 357 // We need to track RX memory usage in plugins to prevent JIT spraying attacks. |
351 // This is done by hooking VirtualAlloc, VirtualProtect, and VirtualFree. | 358 // This is done by hooking VirtualAlloc, VirtualProtect, and VirtualFree. |
352 LPVOID WINAPI WebPluginDelegateImpl::VirtualAllocPatch(LPVOID address, | 359 LPVOID WINAPI WebPluginDelegateImpl::VirtualAllocPatch(LPVOID address, |
353 SIZE_T size, | 360 SIZE_T size, |
354 DWORD allocation_type, | 361 DWORD allocation_type, |
355 DWORD protect) { | 362 DWORD protect) { |
356 void* p = g_iat_orig_virtual_alloc(address, size, allocation_type, protect); | 363 void* p = g_iat_orig_virtual_alloc(address, size, allocation_type, protect); |
357 if (size && p && (protect & kExecPageMask)) { | 364 if (size && p && (protect & kExecPageMask)) { |
358 bool limit_exceeded = UpdateExecMemSize(static_cast<intptr_t>(size)) > | 365 bool limit_exceeded = UpdateExecMemSize(static_cast<intptr_t>(size)) > |
359 kMaxPluginExecMemSize; | 366 kMaxPluginExecMemSize; |
360 #ifndef NDEBUG // TODO(jschuh): Do this in release after we get numbers. | |
361 if (limit_exceeded) | 367 if (limit_exceeded) |
362 ::DebugBreak(); | 368 RaiseJITException(); |
363 #endif | |
364 } | 369 } |
365 return p; | 370 return p; |
366 } | 371 } |
367 | 372 |
368 BOOL WINAPI WebPluginDelegateImpl::VirtualProtectPatch(LPVOID address, | 373 BOOL WINAPI WebPluginDelegateImpl::VirtualProtectPatch(LPVOID address, |
369 SIZE_T size, | 374 SIZE_T size, |
370 DWORD new_protect, | 375 DWORD new_protect, |
371 PDWORD old_protect) { | 376 PDWORD old_protect) { |
372 if (g_iat_orig_virtual_protect(address, size, new_protect, old_protect)) { | 377 if (g_iat_orig_virtual_protect(address, size, new_protect, old_protect)) { |
373 bool is_exec = !!(new_protect & kExecPageMask); | 378 bool is_exec = !!(new_protect & kExecPageMask); |
374 bool was_exec = !!(*old_protect & kExecPageMask); | 379 bool was_exec = !!(*old_protect & kExecPageMask); |
375 if (is_exec && !was_exec) { | 380 if (is_exec && !was_exec) { |
376 bool limit_exceeded = UpdateExecMemSize(static_cast<intptr_t>(size)) > | 381 bool limit_exceeded = UpdateExecMemSize(static_cast<intptr_t>(size)) > |
377 kMaxPluginExecMemSize; | 382 kMaxPluginExecMemSize; |
378 #ifndef NDEBUG // TODO(jschuh): Do this in release after we get numbers. | |
379 if (limit_exceeded) | 383 if (limit_exceeded) |
380 ::DebugBreak(); | 384 RaiseJITException(); |
381 #endif | |
382 } else if (!is_exec && was_exec) { | 385 } else if (!is_exec && was_exec) { |
383 UpdateExecMemSize(-(static_cast<intptr_t>(size))); | 386 UpdateExecMemSize(-(static_cast<intptr_t>(size))); |
384 } | 387 } |
385 | 388 |
386 return TRUE; | 389 return TRUE; |
387 } | 390 } |
388 | 391 |
389 return FALSE; | 392 return FALSE; |
390 } | 393 } |
391 | 394 |
(...skipping 1310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1702 ::ReleaseCapture(); | 1705 ::ReleaseCapture(); |
1703 break; | 1706 break; |
1704 | 1707 |
1705 default: | 1708 default: |
1706 break; | 1709 break; |
1707 } | 1710 } |
1708 } | 1711 } |
1709 | 1712 |
1710 } // namespace npapi | 1713 } // namespace npapi |
1711 } // namespace webkit | 1714 } // namespace webkit |
OLD | NEW |