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 3 // found in the LICENSE file. 4 5 #include "content/browser/frame_host/debug_urls.h" 6 7 #include <vector> 8 9 #include "base/command_line.h" 10 #include "base/debug/asan_invalid_access.h" 11 #include "base/debug/profiler.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "cc/base/switches.h" 14 #include "content/browser/gpu/gpu_process_host_ui_shim.h" 15 #include "content/public/browser/browser_thread.h" 16 #include "content/public/common/content_constants.h" 17 #include "content/public/common/url_constants.h" 18 #include "ppapi/proxy/ppapi_messages.h" 19 #include "url/gurl.h" 20 21 #if defined(ENABLE_PLUGINS) 22 #include "content/browser/ppapi_plugin_process_host.h" 23 #endif 24 25 namespace content { 26 27 namespace { 28 29 // Define the Asan debug URLs. 30 const char kAsanCrashDomain[] = "crash"; 31 const char kAsanHeapOverflow[] = "/browser-heap-overflow"; 32 const char kAsanHeapUnderflow[] = "/browser-heap-underflow"; 33 const char kAsanUseAfterFree[] = "/browser-use-after-free"; 34 #if defined(SYZYASAN) 35 const char kAsanCorruptHeapBlock[] = "/browser-corrupt-heap-block"; 36 const char kAsanCorruptHeap[] = "/browser-corrupt-heap"; 37 #endif 38 HandlePpapiFlashDebugURL(const GURL & url)39void HandlePpapiFlashDebugURL(const GURL& url) { 40 #if defined(ENABLE_PLUGINS) 41 bool crash = url == GURL(kChromeUIPpapiFlashCrashURL); 42 43 std::vector<PpapiPluginProcessHost*> hosts; 44 PpapiPluginProcessHost::FindByName( 45 base::UTF8ToUTF16(kFlashPluginName), &hosts); 46 for (std::vector<PpapiPluginProcessHost*>::iterator iter = hosts.begin(); 47 iter != hosts.end(); ++iter) { 48 if (crash) 49 (*iter)->Send(new PpapiMsg_Crash()); 50 else 51 (*iter)->Send(new PpapiMsg_Hang()); 52 } 53 #endif 54 } 55 IsAsanDebugURL(const GURL & url)56bool IsAsanDebugURL(const GURL& url) { 57 #if defined(SYZYASAN) 58 if (!base::debug::IsBinaryInstrumented()) 59 return false; 60 #endif 61 62 if (!(url.is_valid() && url.SchemeIs(kChromeUIScheme) && 63 url.DomainIs(kAsanCrashDomain, sizeof(kAsanCrashDomain) - 1) && 64 url.has_path())) { 65 return false; 66 } 67 68 if (url.path() == kAsanHeapOverflow || url.path() == kAsanHeapUnderflow || 69 url.path() == kAsanUseAfterFree) { 70 return true; 71 } 72 73 #if defined(SYZYASAN) 74 if (url.path() == kAsanCorruptHeapBlock || url.path() == kAsanCorruptHeap) 75 return true; 76 #endif 77 78 return false; 79 } 80 HandleAsanDebugURL(const GURL & url)81bool HandleAsanDebugURL(const GURL& url) { 82 #if defined(SYZYASAN) 83 if (!base::debug::IsBinaryInstrumented()) 84 return false; 85 86 if (url.path() == kAsanCorruptHeapBlock) { 87 base::debug::AsanCorruptHeapBlock(); 88 return true; 89 } else if (url.path() == kAsanCorruptHeap) { 90 base::debug::AsanCorruptHeap(); 91 return true; 92 } 93 #endif 94 95 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN) 96 if (url.path() == kAsanHeapOverflow) { 97 base::debug::AsanHeapOverflow(); 98 } else if (url.path() == kAsanHeapUnderflow) { 99 base::debug::AsanHeapUnderflow(); 100 } else if (url.path() == kAsanUseAfterFree) { 101 base::debug::AsanHeapUseAfterFree(); 102 } else { 103 return false; 104 } 105 #endif 106 107 return true; 108 } 109 110 111 } // namespace 112 HandleDebugURL(const GURL & url,ui::PageTransition transition)113bool HandleDebugURL(const GURL& url, ui::PageTransition transition) { 114 // Ensure that the user explicitly navigated to this URL, unless 115 // kEnableGpuBenchmarking is enabled by Telemetry. 116 bool is_telemetry_navigation = 117 base::CommandLine::ForCurrentProcess()->HasSwitch( 118 cc::switches::kEnableGpuBenchmarking) && 119 (transition & ui::PAGE_TRANSITION_TYPED); 120 121 if (!(transition & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR) && 122 !is_telemetry_navigation) 123 return false; 124 125 if (IsAsanDebugURL(url)) 126 return HandleAsanDebugURL(url); 127 128 if (url == GURL(kChromeUIBrowserCrashURL)) { 129 // Induce an intentional crash in the browser process. 130 CHECK(false); 131 return true; 132 } 133 134 if (url == GURL(kChromeUIGpuCleanURL)) { 135 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance(); 136 if (shim) 137 shim->SimulateRemoveAllContext(); 138 return true; 139 } 140 141 if (url == GURL(kChromeUIGpuCrashURL)) { 142 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance(); 143 if (shim) 144 shim->SimulateCrash(); 145 return true; 146 } 147 148 if (url == GURL(kChromeUIGpuHangURL)) { 149 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance(); 150 if (shim) 151 shim->SimulateHang(); 152 return true; 153 } 154 155 if (url == GURL(kChromeUIPpapiFlashCrashURL) || 156 url == GURL(kChromeUIPpapiFlashHangURL)) { 157 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 158 base::Bind(&HandlePpapiFlashDebugURL, url)); 159 return true; 160 } 161 162 return false; 163 } 164 IsRendererDebugURL(const GURL & url)165bool IsRendererDebugURL(const GURL& url) { 166 if (!url.is_valid()) 167 return false; 168 169 if (url.SchemeIs(url::kJavaScriptScheme)) 170 return true; 171 172 return url == GURL(kChromeUICrashURL) || 173 url == GURL(kChromeUIDumpURL) || 174 url == GURL(kChromeUIKillURL) || 175 url == GURL(kChromeUIHangURL) || 176 url == GURL(kChromeUIShorthangURL); 177 } 178 179 } // namespace content 180