Commit eb4a6ff5 authored by Will Harris's avatar Will Harris Committed by Commit Bot

Add Heap corruption chrome URLs.

chrome://heapcorruptioncrash/ to crash a child renderer process.
chrome://inducebrowserheapcorruption/ to crash a browser process.

BUG=865632

Change-Id: I69caa1c80cd1775f416d656312222b9b4856f682
Reviewed-on: https://chromium-review.googlesource.com/1129628
Commit-Queue: Will Harris <wfh@chromium.org>
Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577989}
parent 4b7e2572
......@@ -319,6 +319,8 @@ jumbo_component("base") {
"debug/dump_without_crashing.h",
"debug/gdi_debug_util_win.cc",
"debug/gdi_debug_util_win.h",
"debug/invalid_access_win.cc",
"debug/invalid_access_win.h",
"debug/leak_annotations.h",
"debug/leak_tracker.h",
"debug/proc_maps_linux.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/debug/invalid_access_win.h"
#include <stdlib.h>
#include <windows.h>
#include "base/logging.h"
#include "base/win/windows_version.h"
namespace base {
namespace debug {
namespace win {
namespace {
void CreateSyntheticHeapCorruption() {
EXCEPTION_RECORD record = {};
record.ExceptionCode = STATUS_HEAP_CORRUPTION;
RaiseFailFastException(&record, nullptr,
FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
}
} // namespace
void TerminateWithHeapCorruption() {
__try {
// Pre-Windows 10, it's hard to trigger a heap corruption fast fail, so
// artificially create one instead.
if (base::win::GetVersion() < base::win::VERSION_WIN10)
CreateSyntheticHeapCorruption();
HANDLE heap = ::HeapCreate(0, 0, 0);
CHECK(heap);
CHECK(HeapSetInformation(heap, HeapEnableTerminationOnCorruption, nullptr,
0));
void* addr = ::HeapAlloc(heap, 0, 0x1000);
CHECK(addr);
// Corrupt heap header.
char* addr_mutable = reinterpret_cast<char*>(addr);
memset(addr_mutable - sizeof(addr), 0xCC, sizeof(addr));
HeapFree(heap, 0, addr);
HeapDestroy(heap);
} __except (EXCEPTION_EXECUTE_HANDLER) {
// Heap corruption exception should never be caught.
CHECK(false);
}
// Should never reach here.
abort();
}
} // namespace win
} // namespace debug
} // namespace base
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_DEBUG_INVALID_ACCESS_WIN_H_
#define BASE_DEBUG_INVALID_ACCESS_WIN_H_
#include "base/base_export.h"
namespace base {
namespace debug {
namespace win {
// Creates a synthetic heap corruption that causes the current process to
// terminate immediately with a fast fail exception.
[[noreturn]] BASE_EXPORT void TerminateWithHeapCorruption();
} // namespace win
} // namespace debug
} // namespace base
#endif // BASE_DEBUG_INVALID_ACCESS_WIN_H_
......@@ -7,6 +7,7 @@
#include <utility>
#include "base/at_exit.h"
#include "base/debug/invalid_access_win.h"
#include "base/process/kill.h"
#include "base/test/multiprocess_test.h"
#include "base/test/test_timeouts.h"
......@@ -299,6 +300,13 @@ TEST_F(ProcessTest, PredefinedProcessIsRunning) {
}
#endif
#if defined(OS_WIN)
TEST_F(ProcessTest, HeapCorruption) {
EXPECT_EXIT(base::debug::win::TerminateWithHeapCorruption(),
::testing::ExitedWithCode(STATUS_HEAP_CORRUPTION), "");
}
#endif
TEST_F(ProcessTest, ChildProcessIsRunning) {
Process process(SpawnChild("SleepyChildProcess"));
EXPECT_FALSE(process.WaitForExitWithTimeout(
......
......@@ -179,6 +179,27 @@ IN_PROC_BROWSER_TEST_F(MetricsServiceBrowserTest, MAYBE_CrashRenderers) {
histogram_tester.ExpectUniqueSample("Tabs.SadTab.CrashCreated", 1, 1);
}
#if defined(OS_WIN)
IN_PROC_BROWSER_TEST_F(MetricsServiceBrowserTest, HeapCorruptionInRenderer) {
base::HistogramTester histogram_tester;
OpenTabsAndNavigateToCrashyUrl(content::kChromeUIHeapCorruptionCrashURL);
// Verify that the expected stability metrics were recorded.
const PrefService* prefs = g_browser_process->local_state();
EXPECT_EQ(1, prefs->GetInteger(metrics::prefs::kStabilityLaunchCount));
// The three tabs from OpenTabs() and the one tab to open chrome://crash/.
EXPECT_EQ(4, prefs->GetInteger(metrics::prefs::kStabilityPageLoadCount));
EXPECT_EQ(1, prefs->GetInteger(metrics::prefs::kStabilityRendererCrashCount));
histogram_tester.ExpectUniqueSample(
"CrashExitCodes.Renderer",
std::abs(static_cast<int32_t>(STATUS_HEAP_CORRUPTION)), 1);
histogram_tester.ExpectUniqueSample("Tabs.SadTab.CrashCreated", 1, 1);
LOG(INFO) << histogram_tester.GetAllHistogramsRecorded();
}
#endif // OS_WIN
IN_PROC_BROWSER_TEST_F(MetricsServiceBrowserTest, MAYBE_CheckCrashRenderers) {
base::HistogramTester histogram_tester;
......
......@@ -425,25 +425,30 @@ const char* const kChromeHostURLs[] = {
};
const size_t kNumberOfChromeHostURLs = arraysize(kChromeHostURLs);
const char* const kChromeDebugURLs[] = {content::kChromeUIBadCastCrashURL,
content::kChromeUIBrowserCrashURL,
content::kChromeUICrashURL,
content::kChromeUIDumpURL,
content::kChromeUIKillURL,
content::kChromeUIHangURL,
content::kChromeUIShorthangURL,
content::kChromeUIGpuCleanURL,
content::kChromeUIGpuCrashURL,
content::kChromeUIGpuHangURL,
content::kChromeUIMemoryExhaustURL,
content::kChromeUIPpapiFlashCrashURL,
content::kChromeUIPpapiFlashHangURL,
const char* const kChromeDebugURLs[] = {
content::kChromeUIBadCastCrashURL,
content::kChromeUIBrowserCrashURL,
content::kChromeUICrashURL,
content::kChromeUIDumpURL,
content::kChromeUIKillURL,
content::kChromeUIHangURL,
content::kChromeUIShorthangURL,
content::kChromeUIGpuCleanURL,
content::kChromeUIGpuCrashURL,
content::kChromeUIGpuHangURL,
content::kChromeUIMemoryExhaustURL,
content::kChromeUIPpapiFlashCrashURL,
content::kChromeUIPpapiFlashHangURL,
#if defined(OS_WIN)
content::kChromeUIBrowserHeapCorruptionURL,
content::kChromeUIHeapCorruptionCrashURL,
#endif
#if defined(OS_ANDROID)
content::kChromeUIGpuJavaCrashURL,
kChromeUIJavaCrashURL,
content::kChromeUIGpuJavaCrashURL,
kChromeUIJavaCrashURL,
#endif
kChromeUIQuitURL,
kChromeUIRestartURL};
kChromeUIQuitURL,
kChromeUIRestartURL};
const size_t kNumberOfChromeDebugURLs = arraysize(kChromeDebugURLs);
} // namespace chrome
......@@ -26,6 +26,10 @@
#include "ppapi/proxy/ppapi_messages.h" // nogncheck
#endif
#if defined(OS_WIN)
#include "base/debug/invalid_access_win.h"
#endif
namespace content {
class ScopedAllowWaitForDebugURL {
......@@ -142,6 +146,14 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
return true;
}
#if defined(OS_WIN)
if (url == kChromeUIBrowserHeapCorruptionURL) {
// Induce an intentional heap corruption in the browser process.
base::debug::win::TerminateWithHeapCorruption();
return true;
}
#endif
if (url == kChromeUIBrowserUIHang) {
HangCurrentThread();
return true;
......
......@@ -58,6 +58,11 @@ const char kChromeUIProcessInternalsURL[] = "chrome://process-internals";
#if defined(OS_ANDROID)
const char kChromeUIGpuJavaCrashURL[] = "chrome://gpu-java-crash/";
#endif
#if defined(OS_WIN)
const char kChromeUIBrowserHeapCorruptionURL[] =
"chrome://inducebrowserheapcorruption/";
const char kChromeUIHeapCorruptionCrashURL[] = "chrome://heapcorruptioncrash/";
#endif
#if defined(ADDRESS_SANITIZER)
const char kChromeUICrashHeapOverflowURL[] = "chrome://crash/heap-overflow";
const char kChromeUICrashHeapUnderflowURL[] = "chrome://crash/heap-underflow";
......
......@@ -69,6 +69,10 @@ CONTENT_EXPORT extern const char kChromeUIProcessInternalsURL[];
#if defined(OS_ANDROID)
CONTENT_EXPORT extern const char kChromeUIGpuJavaCrashURL[];
#endif
#if defined(OS_WIN)
CONTENT_EXPORT extern const char kChromeUIBrowserHeapCorruptionURL[];
CONTENT_EXPORT extern const char kChromeUIHeapCorruptionCrashURL[];
#endif
#if defined(ADDRESS_SANITIZER)
CONTENT_EXPORT extern const char kChromeUICrashHeapOverflowURL[];
CONTENT_EXPORT extern const char kChromeUICrashHeapUnderflowURL[];
......
......@@ -90,6 +90,11 @@ bool IsRendererDebugURL(const GURL& url) {
}
#endif
#if defined(OS_WIN)
if (url == kChromeUIHeapCorruptionCrashURL)
return true;
#endif
#if DCHECK_IS_ON()
if (url == kChromeUICrashDcheckURL)
return true;
......
......@@ -239,6 +239,7 @@
#endif
#if defined(OS_WIN)
#include "base/debug/invalid_access_win.h"
#include "base/process/kill.h"
#elif defined(OS_POSIX)
#include <signal.h>
......@@ -1063,6 +1064,15 @@ void HandleChromeDebugURL(const GURL& url) {
CHECK(false);
}
#if defined(OS_WIN)
if (url == kChromeUIHeapCorruptionCrashURL) {
LOG(ERROR)
<< "Intentionally causing heap corruption because user navigated to "
<< url.spec();
base::debug::win::TerminateWithHeapCorruption();
}
#endif
#if DCHECK_IS_ON()
if (url == kChromeUICrashDcheckURL) {
LOG(ERROR) << "Intentionally causing DCHECK because user navigated to "
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment