Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors |
[email protected] | 8bf104801 | 2012-02-08 01:22:18 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. | ||||
4 | |||||
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 5 | #include "content/browser/renderer_host/debug_urls.h" |
[email protected] | 8bf104801 | 2012-02-08 01:22:18 | [diff] [blame] | 6 | |
[email protected] | 029bd94 | 2013-01-22 08:30:33 | [diff] [blame] | 7 | #include <vector> |
8 | |||||
[email protected] | 4775298 | 2014-07-29 08:01:43 | [diff] [blame] | 9 | #include "base/command_line.h" |
Bruce Dawson | 5ece13c | 2024-02-29 20:37:34 | [diff] [blame] | 10 | #include "base/compiler_specific.h" |
James Cook | 1e618b603 | 2024-06-21 23:13:37 | [diff] [blame] | 11 | #include "base/debug/alias.h" |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 12 | #include "base/debug/asan_invalid_access.h" |
13 | #include "base/debug/profiler.h" | ||||
Avi Drissman | adac2199 | 2023-01-11 23:46:39 | [diff] [blame] | 14 | #include "base/functional/bind.h" |
Peter Boström | b41d6ee | 2024-11-20 15:49:39 | [diff] [blame] | 15 | #include "base/immediate_crash.h" |
Sebastien Marchand | bb331f59 | 2019-12-04 17:59:03 | [diff] [blame] | 16 | #include "base/memory/memory_pressure_listener.h" |
Peter Collingbourne | 6ce4b21 | 2019-02-15 22:19:50 | [diff] [blame] | 17 | #include "base/sanitizer_buildflags.h" |
[email protected] | 74ebfb1 | 2013-06-07 20:48:00 | [diff] [blame] | 18 | #include "base/strings/utf_string_conversions.h" |
erikwright | 811f1b0 | 2015-04-17 18:58:36 | [diff] [blame] | 19 | #include "base/synchronization/waitable_event.h" |
erikwright | cf61cd79 | 2015-04-23 14:35:20 | [diff] [blame] | 20 | #include "base/threading/thread_restrictions.h" |
Sigurdur Asgeirsson | 69d0bcd | 2018-03-29 21:50:51 | [diff] [blame] | 21 | #include "build/build_config.h" |
[email protected] | 4775298 | 2014-07-29 08:01:43 | [diff] [blame] | 22 | #include "cc/base/switches.h" |
sadrul | b428f6b | 2017-03-03 19:28:32 | [diff] [blame] | 23 | #include "content/browser/gpu/gpu_process_host.h" |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 24 | #include "content/public/browser/browser_task_traits.h" |
[email protected] | 029bd94 | 2013-01-22 08:30:33 | [diff] [blame] | 25 | #include "content/public/browser/browser_thread.h" |
[email protected] | 7327029 | 2013-08-09 03:48:07 | [diff] [blame] | 26 | #include "content/public/common/content_constants.h" |
[email protected] | 8bf104801 | 2012-02-08 01:22:18 | [diff] [blame] | 27 | #include "content/public/common/url_constants.h" |
Gyuyoung Kim | 107c2a0 | 2021-04-13 01:49:30 | [diff] [blame] | 28 | #include "third_party/blink/public/common/chrome_debug_urls.h" |
[email protected] | 707e1c4 | 2013-07-09 21:18:58 | [diff] [blame] | 29 | #include "url/gurl.h" |
[email protected] | 8bf104801 | 2012-02-08 01:22:18 | [diff] [blame] | 30 | |
Xiaohan Wang | 7f8052e0 | 2022-01-14 18:44:28 | [diff] [blame] | 31 | #if BUILDFLAG(IS_WIN) |
Will Harris | eb4a6ff | 2018-07-25 18:36:52 | [diff] [blame] | 32 | #include "base/debug/invalid_access_win.h" |
33 | #endif | ||||
34 | |||||
[email protected] | 8bf104801 | 2012-02-08 01:22:18 | [diff] [blame] | 35 | namespace content { |
36 | |||||
pmonette | 3955a4f | 2016-01-29 22:24:37 | [diff] [blame] | 37 | class ScopedAllowWaitForDebugURL { |
38 | private: | ||||
Etienne Pierre-doray | affab0d | 2018-11-12 15:51:11 | [diff] [blame] | 39 | base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope wait; |
pmonette | 3955a4f | 2016-01-29 22:24:37 | [diff] [blame] | 40 | }; |
41 | |||||
[email protected] | 029bd94 | 2013-01-22 08:30:33 | [diff] [blame] | 42 | namespace { |
43 | |||||
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 44 | // Define the Asan debug URLs. |
45 | const char kAsanCrashDomain[] = "crash"; | ||||
46 | const char kAsanHeapOverflow[] = "/browser-heap-overflow"; | ||||
47 | const char kAsanHeapUnderflow[] = "/browser-heap-underflow"; | ||||
48 | const char kAsanUseAfterFree[] = "/browser-use-after-free"; | ||||
Sigurdur Asgeirsson | 69d0bcd | 2018-03-29 21:50:51 | [diff] [blame] | 49 | |
Xiaohan Wang | 7f8052e0 | 2022-01-14 18:44:28 | [diff] [blame] | 50 | #if BUILDFLAG(IS_WIN) |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 51 | const char kAsanCorruptHeapBlock[] = "/browser-corrupt-heap-block"; |
52 | const char kAsanCorruptHeap[] = "/browser-corrupt-heap"; | ||||
erikwright | 3d48305 | 2015-03-06 13:14:44 | [diff] [blame] | 53 | #endif |
erikwright | 420a090 | 2015-02-26 21:16:17 | [diff] [blame] | 54 | |
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 55 | // The conditions here must stay in sync with |HandleAsanDebugURL|. |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 56 | bool IsAsanDebugURL(const GURL& url) { |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 57 | if (!(url.is_valid() && url.SchemeIs(kChromeUIScheme) && |
Aran Gilman | 37d1163 | 2019-10-08 23:07:15 | [diff] [blame] | 58 | url.DomainIs(kAsanCrashDomain) && url.has_path())) { |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 59 | return false; |
60 | } | ||||
61 | |||||
csharrison | 88b3b71 | 2016-11-14 23:12:35 | [diff] [blame] | 62 | if (url.path_piece() == kAsanHeapOverflow || |
63 | url.path_piece() == kAsanHeapUnderflow || | ||||
64 | url.path_piece() == kAsanUseAfterFree) { | ||||
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 65 | return true; |
66 | } | ||||
67 | |||||
Xiaohan Wang | 7f8052e0 | 2022-01-14 18:44:28 | [diff] [blame] | 68 | #if BUILDFLAG(IS_WIN) |
csharrison | 88b3b71 | 2016-11-14 23:12:35 | [diff] [blame] | 69 | if (url.path_piece() == kAsanCorruptHeapBlock || |
70 | url.path_piece() == kAsanCorruptHeap) { | ||||
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 71 | return true; |
csharrison | 88b3b71 | 2016-11-14 23:12:35 | [diff] [blame] | 72 | } |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 73 | #endif |
74 | |||||
75 | return false; | ||||
76 | } | ||||
77 | |||||
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 78 | // The URLs handled here must exactly match those that return true from |
79 | // |IsAsanDebugURL|. | ||||
80 | void HandleAsanDebugURL(const GURL& url) { | ||||
81 | CHECK(IsAsanDebugURL(url)); | ||||
Peter Collingbourne | 6ce4b21 | 2019-02-15 22:19:50 | [diff] [blame] | 82 | #if defined(ADDRESS_SANITIZER) || BUILDFLAG(IS_HWASAN) |
Xiaohan Wang | 7f8052e0 | 2022-01-14 18:44:28 | [diff] [blame] | 83 | #if BUILDFLAG(IS_WIN) |
csharrison | 88b3b71 | 2016-11-14 23:12:35 | [diff] [blame] | 84 | if (url.path_piece() == kAsanCorruptHeapBlock) { |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 85 | base::debug::AsanCorruptHeapBlock(); |
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 86 | return; |
87 | } | ||||
88 | if (url.path_piece() == kAsanCorruptHeap) { | ||||
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 89 | base::debug::AsanCorruptHeap(); |
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 90 | return; |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 91 | } |
Xiaohan Wang | be7c526a | 2022-01-15 14:34:51 | [diff] [blame] | 92 | #endif // BUILDFLAG(IS_WIN) |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 93 | |
csharrison | 88b3b71 | 2016-11-14 23:12:35 | [diff] [blame] | 94 | if (url.path_piece() == kAsanHeapOverflow) { |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 95 | base::debug::AsanHeapOverflow(); |
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 96 | return; |
97 | } | ||||
98 | if (url.path_piece() == kAsanHeapUnderflow) { | ||||
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 99 | base::debug::AsanHeapUnderflow(); |
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 100 | return; |
101 | } | ||||
102 | if (url.path_piece() == kAsanUseAfterFree) { | ||||
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 103 | base::debug::AsanHeapUseAfterFree(); |
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 104 | return; |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 105 | } |
106 | #endif | ||||
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 107 | } |
108 | |||||
Bruce Dawson | 5ece13c | 2024-02-29 20:37:34 | [diff] [blame] | 109 | NOINLINE void HangCurrentThread() { |
pmonette | 3955a4f | 2016-01-29 22:24:37 | [diff] [blame] | 110 | ScopedAllowWaitForDebugURL allow_wait; |
gab | d6f9bff | 2016-06-02 13:48:20 | [diff] [blame] | 111 | base::WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
112 | base::WaitableEvent::InitialState::NOT_SIGNALED) | ||||
113 | .Wait(); | ||||
pmonette | 3955a4f | 2016-01-29 22:24:37 | [diff] [blame] | 114 | } |
[email protected] | b4b3479 | 2014-06-14 08:29:37 | [diff] [blame] | 115 | |
Bruce Dawson | 5ece13c | 2024-02-29 20:37:34 | [diff] [blame] | 116 | NOINLINE void CrashBrowserProcessIntentionally() { |
James Cook | 1e618b603 | 2024-06-21 23:13:37 | [diff] [blame] | 117 | // Don't fold so that crash reports will clearly show this method. This helps |
118 | // with crash triage. | ||||
119 | NO_CODE_FOLDING(); | ||||
Bruce Dawson | 5ece13c | 2024-02-29 20:37:34 | [diff] [blame] | 120 | // Induce an intentional crash in the browser process. |
Peter Boström | b41d6ee | 2024-11-20 15:49:39 | [diff] [blame] | 121 | base::ImmediateCrash(); |
Bruce Dawson | 5ece13c | 2024-02-29 20:37:34 | [diff] [blame] | 122 | } |
123 | |||||
[email protected] | 029bd94 | 2013-01-22 08:30:33 | [diff] [blame] | 124 | } // namespace |
125 | |||||
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 126 | // The conditions here must stay in sync with |HandleDebugURL|. |
127 | bool IsDebugURL(const GURL& url) { | ||||
128 | if (!(url.is_valid() && url.SchemeIs(kChromeUIScheme))) { | ||||
129 | return false; | ||||
130 | } | ||||
131 | |||||
132 | if (IsAsanDebugURL(url)) { | ||||
133 | return true; | ||||
134 | } | ||||
135 | |||||
136 | if (url == blink::kChromeUIBrowserCrashURL || | ||||
137 | url == blink::kChromeUIBrowserDcheckURL || | ||||
138 | #if BUILDFLAG(IS_WIN) | ||||
139 | url == blink::kChromeUIBrowserHeapCorruptionURL || | ||||
140 | #endif | ||||
141 | url == blink::kChromeUIBrowserUIHang || | ||||
142 | url == blink::kChromeUIDelayedBrowserUIHang || | ||||
143 | url == blink::kChromeUIGpuCleanURL || | ||||
144 | url == blink::kChromeUIGpuCrashURL || | ||||
145 | #if BUILDFLAG(IS_ANDROID) | ||||
146 | url == blink::kChromeUIGpuJavaCrashURL || | ||||
147 | #endif | ||||
148 | url == blink::kChromeUIGpuHangURL || | ||||
149 | url == blink::kChromeUIMemoryPressureCriticalURL || | ||||
150 | url == blink::kChromeUIMemoryPressureModerateURL) { | ||||
151 | return true; | ||||
152 | } | ||||
153 | |||||
154 | return false; | ||||
155 | } | ||||
156 | |||||
157 | // The URLs handled here must exactly match those that return true from | ||||
158 | // |IsDebugURL|. | ||||
159 | void HandleDebugURL(const GURL& url, | ||||
Ian Vollick | 9dda052 | 2019-09-11 02:24:29 | [diff] [blame] | 160 | ui::PageTransition transition, |
161 | bool is_explicit_navigation) { | ||||
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 162 | CHECK(IsDebugURL(url)); |
Ian Vollick | 9dda052 | 2019-09-11 02:24:29 | [diff] [blame] | 163 | // We want to handle the debug URL if the user explicitly navigated to this |
164 | // URL, unless kEnableGpuBenchmarking is enabled by Telemetry. | ||||
[email protected] | 47927870 | 2014-08-11 20:32:09 | [diff] [blame] | 165 | bool is_telemetry_navigation = |
166 | base::CommandLine::ForCurrentProcess()->HasSwitch( | ||||
Peter Kasting | 6e6af3c | 2024-10-15 00:13:18 | [diff] [blame] | 167 | switches::kEnableGpuBenchmarking) && |
vmiura | 20fa51a3 | 2015-10-27 21:39:34 | [diff] [blame] | 168 | (PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED)); |
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 169 | if (!is_explicit_navigation && !is_telemetry_navigation) { |
170 | return; | ||||
[email protected] | 8bf104801 | 2012-02-08 01:22:18 | [diff] [blame] | 171 | } |
172 | |||||
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 173 | if (IsAsanDebugURL(url)) { |
174 | HandleAsanDebugURL(url); | ||||
175 | return; | ||||
176 | } | ||||
177 | if (url == blink::kChromeUIBrowserCrashURL) { | ||||
178 | CrashBrowserProcessIntentionally(); | ||||
179 | return; | ||||
180 | } | ||||
Peter Boström | d032070 | 2022-05-17 19:16:31 | [diff] [blame] | 181 | if (url == blink::kChromeUIBrowserDcheckURL) { |
182 | // Induce an intentional DCHECK in the browser process. This is used to | ||||
183 | // see if a DCHECK will bring down the current process (is FATAL). | ||||
184 | DCHECK(false); | ||||
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 185 | return; |
Peter Boström | d032070 | 2022-05-17 19:16:31 | [diff] [blame] | 186 | } |
Xiaohan Wang | 7f8052e0 | 2022-01-14 18:44:28 | [diff] [blame] | 187 | #if BUILDFLAG(IS_WIN) |
Gyuyoung Kim | 107c2a0 | 2021-04-13 01:49:30 | [diff] [blame] | 188 | if (url == blink::kChromeUIBrowserHeapCorruptionURL) { |
Will Harris | eb4a6ff | 2018-07-25 18:36:52 | [diff] [blame] | 189 | // Induce an intentional heap corruption in the browser process. |
190 | base::debug::win::TerminateWithHeapCorruption(); | ||||
Will Harris | eb4a6ff | 2018-07-25 18:36:52 | [diff] [blame] | 191 | } |
192 | #endif | ||||
Gyuyoung Kim | 107c2a0 | 2021-04-13 01:49:30 | [diff] [blame] | 193 | if (url == blink::kChromeUIBrowserUIHang) { |
pmonette | 3955a4f | 2016-01-29 22:24:37 | [diff] [blame] | 194 | HangCurrentThread(); |
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 195 | return; |
pmonette | 3955a4f | 2016-01-29 22:24:37 | [diff] [blame] | 196 | } |
Gyuyoung Kim | 107c2a0 | 2021-04-13 01:49:30 | [diff] [blame] | 197 | if (url == blink::kChromeUIDelayedBrowserUIHang) { |
pmonette | 3955a4f | 2016-01-29 22:24:37 | [diff] [blame] | 198 | // Webdriver-safe url to hang the ui thread. Webdriver waits for the onload |
199 | // event in javascript which needs a little more time to fire. | ||||
Gabriel Charette | e7cdc5cd | 2020-05-27 23:35:05 | [diff] [blame] | 200 | GetUIThreadTaskRunner({})->PostDelayedTask( |
Peter Kasting | e5a38ed | 2021-10-02 03:06:35 | [diff] [blame] | 201 | FROM_HERE, base::BindOnce(&HangCurrentThread), base::Seconds(2)); |
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 202 | return; |
erikwright | 811f1b0 | 2015-04-17 18:58:36 | [diff] [blame] | 203 | } |
Gyuyoung Kim | 107c2a0 | 2021-04-13 01:49:30 | [diff] [blame] | 204 | if (url == blink::kChromeUIGpuCleanURL) { |
Thiabaud Engelbrecht | e7ed165 | 2023-06-04 21:42:35 | [diff] [blame] | 205 | auto* host = GpuProcessHost::Get(); |
206 | if (host) { | ||||
207 | host->gpu_service()->DestroyAllChannels(); | ||||
208 | } | ||||
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 209 | return; |
[email protected] | 8bf104801 | 2012-02-08 01:22:18 | [diff] [blame] | 210 | } |
Gyuyoung Kim | 107c2a0 | 2021-04-13 01:49:30 | [diff] [blame] | 211 | if (url == blink::kChromeUIGpuCrashURL) { |
Thiabaud Engelbrecht | e7ed165 | 2023-06-04 21:42:35 | [diff] [blame] | 212 | auto* host = GpuProcessHost::Get(); |
213 | if (host) { | ||||
214 | host->gpu_service()->Crash(); | ||||
215 | } | ||||
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 216 | return; |
[email protected] | 8bf104801 | 2012-02-08 01:22:18 | [diff] [blame] | 217 | } |
Xiaohan Wang | 7f8052e0 | 2022-01-14 18:44:28 | [diff] [blame] | 218 | #if BUILDFLAG(IS_ANDROID) |
Gyuyoung Kim | 107c2a0 | 2021-04-13 01:49:30 | [diff] [blame] | 219 | if (url == blink::kChromeUIGpuJavaCrashURL) { |
Thiabaud Engelbrecht | e7ed165 | 2023-06-04 21:42:35 | [diff] [blame] | 220 | auto* host = GpuProcessHost::Get(); |
221 | if (host) { | ||||
222 | host->gpu_service()->ThrowJavaException(); | ||||
223 | } | ||||
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 224 | return; |
boliu | 7a81c252 | 2017-02-03 03:41:04 | [diff] [blame] | 225 | } |
226 | #endif | ||||
Gyuyoung Kim | 107c2a0 | 2021-04-13 01:49:30 | [diff] [blame] | 227 | if (url == blink::kChromeUIGpuHangURL) { |
Thiabaud Engelbrecht | e7ed165 | 2023-06-04 21:42:35 | [diff] [blame] | 228 | auto* host = GpuProcessHost::Get(); |
229 | if (host) { | ||||
230 | host->gpu_service()->Hang(); | ||||
231 | } | ||||
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 232 | return; |
[email protected] | 8bf104801 | 2012-02-08 01:22:18 | [diff] [blame] | 233 | } |
Gyuyoung Kim | 107c2a0 | 2021-04-13 01:49:30 | [diff] [blame] | 234 | if (url == blink::kChromeUIMemoryPressureCriticalURL) { |
Sebastien Marchand | bb331f59 | 2019-12-04 17:59:03 | [diff] [blame] | 235 | base::MemoryPressureListener::NotifyMemoryPressure( |
236 | base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); | ||||
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 237 | return; |
Sebastien Marchand | bb331f59 | 2019-12-04 17:59:03 | [diff] [blame] | 238 | } |
Gyuyoung Kim | 107c2a0 | 2021-04-13 01:49:30 | [diff] [blame] | 239 | if (url == blink::kChromeUIMemoryPressureModerateURL) { |
Sebastien Marchand | bb331f59 | 2019-12-04 17:59:03 | [diff] [blame] | 240 | base::MemoryPressureListener::NotifyMemoryPressure( |
241 | base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); | ||||
Emmanuel Arias Soto | 9e15965 | 2025-05-16 07:53:55 | [diff] [blame] | 242 | return; |
Sebastien Marchand | bb331f59 | 2019-12-04 17:59:03 | [diff] [blame] | 243 | } |
[email protected] | 8bf104801 | 2012-02-08 01:22:18 | [diff] [blame] | 244 | } |
245 | |||||
[email protected] | 8bf104801 | 2012-02-08 01:22:18 | [diff] [blame] | 246 | } // namespace content |