1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/debug/invalid_access_win.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <windows.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <intrin.h>
10*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
13*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker namespace base {
16*6777b538SAndroid Build Coastguard Worker namespace debug {
17*6777b538SAndroid Build Coastguard Worker namespace win {
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker namespace {
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_X86_FAMILY)
22*6777b538SAndroid Build Coastguard Worker // On x86/x64 systems, nop instructions are generally 1 byte.
23*6777b538SAndroid Build Coastguard Worker static constexpr int kNopInstructionSize = 1;
24*6777b538SAndroid Build Coastguard Worker #elif defined(ARCH_CPU_ARM64)
25*6777b538SAndroid Build Coastguard Worker // On Arm systems, all instructions are 4 bytes, fixed size.
26*6777b538SAndroid Build Coastguard Worker static constexpr int kNopInstructionSize = 4;
27*6777b538SAndroid Build Coastguard Worker #else
28*6777b538SAndroid Build Coastguard Worker #error "Unsupported architecture"
29*6777b538SAndroid Build Coastguard Worker #endif
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker // Function that can be jumped midway into safely.
nop_sled()32*6777b538SAndroid Build Coastguard Worker __attribute__((naked)) int nop_sled() {
33*6777b538SAndroid Build Coastguard Worker asm("nop\n"
34*6777b538SAndroid Build Coastguard Worker "nop\n"
35*6777b538SAndroid Build Coastguard Worker "ret\n");
36*6777b538SAndroid Build Coastguard Worker }
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker using FuncType = decltype(&nop_sled);
39*6777b538SAndroid Build Coastguard Worker
IndirectCall(FuncType * func)40*6777b538SAndroid Build Coastguard Worker void IndirectCall(FuncType* func) {
41*6777b538SAndroid Build Coastguard Worker // This code always generates CFG guards.
42*6777b538SAndroid Build Coastguard Worker (*func)();
43*6777b538SAndroid Build Coastguard Worker }
44*6777b538SAndroid Build Coastguard Worker
45*6777b538SAndroid Build Coastguard Worker } // namespace
46*6777b538SAndroid Build Coastguard Worker
TerminateWithHeapCorruption()47*6777b538SAndroid Build Coastguard Worker void TerminateWithHeapCorruption() {
48*6777b538SAndroid Build Coastguard Worker __try {
49*6777b538SAndroid Build Coastguard Worker HANDLE heap = ::HeapCreate(0, 0, 0);
50*6777b538SAndroid Build Coastguard Worker CHECK(heap);
51*6777b538SAndroid Build Coastguard Worker CHECK(HeapSetInformation(heap, HeapEnableTerminationOnCorruption, nullptr,
52*6777b538SAndroid Build Coastguard Worker 0));
53*6777b538SAndroid Build Coastguard Worker void* addr = ::HeapAlloc(heap, 0, 0x1000);
54*6777b538SAndroid Build Coastguard Worker CHECK(addr);
55*6777b538SAndroid Build Coastguard Worker // Corrupt heap header.
56*6777b538SAndroid Build Coastguard Worker char* addr_mutable = reinterpret_cast<char*>(addr);
57*6777b538SAndroid Build Coastguard Worker memset(addr_mutable - sizeof(addr), 0xCC, sizeof(addr));
58*6777b538SAndroid Build Coastguard Worker
59*6777b538SAndroid Build Coastguard Worker HeapFree(heap, 0, addr);
60*6777b538SAndroid Build Coastguard Worker HeapDestroy(heap);
61*6777b538SAndroid Build Coastguard Worker } __except (EXCEPTION_EXECUTE_HANDLER) {
62*6777b538SAndroid Build Coastguard Worker // Heap corruption exception should never be caught.
63*6777b538SAndroid Build Coastguard Worker CHECK(false);
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker // Should never reach here.
66*6777b538SAndroid Build Coastguard Worker abort();
67*6777b538SAndroid Build Coastguard Worker }
68*6777b538SAndroid Build Coastguard Worker
TerminateWithControlFlowViolation()69*6777b538SAndroid Build Coastguard Worker void TerminateWithControlFlowViolation() {
70*6777b538SAndroid Build Coastguard Worker // Call into the middle of the NOP sled.
71*6777b538SAndroid Build Coastguard Worker FuncType func = reinterpret_cast<FuncType>(
72*6777b538SAndroid Build Coastguard Worker (reinterpret_cast<uintptr_t>(nop_sled)) + kNopInstructionSize);
73*6777b538SAndroid Build Coastguard Worker __try {
74*6777b538SAndroid Build Coastguard Worker // Generates a STATUS_STACK_BUFFER_OVERRUN exception if CFG triggers.
75*6777b538SAndroid Build Coastguard Worker IndirectCall(&func);
76*6777b538SAndroid Build Coastguard Worker } __except (EXCEPTION_EXECUTE_HANDLER) {
77*6777b538SAndroid Build Coastguard Worker // CFG fast fail should never be caught.
78*6777b538SAndroid Build Coastguard Worker CHECK(false);
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker // Should only reach here if CFG is disabled.
81*6777b538SAndroid Build Coastguard Worker abort();
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker
84*6777b538SAndroid Build Coastguard Worker } // namespace win
85*6777b538SAndroid Build Coastguard Worker } // namespace debug
86*6777b538SAndroid Build Coastguard Worker } // namespace base
87