1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : #include "syzygy/agent/asan/asan_shadow.h"
15 :
16 : #include "base/logging.h"
17 : #include "base/stringprintf.h"
18 :
19 : namespace agent {
20 : namespace asan {
21 :
22 : uint8 Shadow::shadow_[kShadowSize];
23 :
24 E : void Shadow::SetUp() {
25 : // Poison the shadow memory.
26 E : Poison(shadow_, kShadowSize, kAsanMemoryByte);
27 E : }
28 :
29 E : void Shadow::TearDown() {
30 : // Unpoison the shadow memory.
31 E : Unpoison(shadow_, kShadowSize);
32 E : }
33 :
34 E : void Shadow::Reset() {
35 E : memset(shadow_, 0, kShadowSize);
36 E : }
37 :
38 E : void Shadow::Poison(const void* addr, size_t size, ShadowMarker shadow_val) {
39 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
40 E : uintptr_t start = index & 0x7;
41 E : DCHECK_EQ(0U, (index + size) & 0x7);
42 :
43 E : index >>= 3;
44 E : if (start)
45 E : shadow_[index++] = start;
46 :
47 E : size >>= 3;
48 E : DCHECK_GT(arraysize(shadow_), index + size);
49 E : memset(shadow_ + index, shadow_val, size);
50 E : }
51 :
52 E : void Shadow::Unpoison(const void* addr, size_t size) {
53 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
54 E : DCHECK_EQ(0U, index & 0x7);
55 :
56 E : uint8 remainder = size & 0x7;
57 E : index >>= 3;
58 E : size >>= 3;
59 E : DCHECK_GT(arraysize(shadow_), index + size);
60 E : memset(shadow_ + index, kHeapAddressableByte, size);
61 :
62 E : if (remainder != 0)
63 i : shadow_[index + size] = remainder;
64 E : }
65 :
66 E : void Shadow::MarkAsFreed(const void* addr, size_t size) {
67 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
68 E : uintptr_t start = index & 0x7;
69 :
70 E : index >>= 3;
71 E : if (start)
72 i : shadow_[index++] = kHeapFreedByte;
73 :
74 E : size_t size_shadow = size >> 3;
75 E : DCHECK_GT(arraysize(shadow_), index + size_shadow);
76 E : memset(shadow_ + index, kHeapFreedByte, size_shadow);
77 E : if ((size & 0x7) != 0)
78 E : shadow_[index + size_shadow] = kHeapFreedByte;
79 E : }
80 :
81 E : bool Shadow::IsAccessible(const void* addr) {
82 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
83 E : uintptr_t start = index & 0x7;
84 :
85 E : index >>= 3;
86 :
87 E : DCHECK_GT(arraysize(shadow_), index);
88 E : uint8 shadow = shadow_[index];
89 E : if (shadow == 0)
90 E : return true;
91 :
92 E : if ((shadow & kHeapNonAccessibleByteMask) != 0)
93 E : return false;
94 :
95 E : return start < shadow;
96 E : }
97 :
98 E : Shadow::ShadowMarker Shadow::GetShadowMarkerForAddress(const void* addr) {
99 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
100 E : index >>= 3;
101 :
102 E : DCHECK_GT(arraysize(shadow_), index);
103 E : return static_cast<ShadowMarker>(shadow_[index]);
104 E : }
105 :
106 : void Shadow::AppendShadowByteText(const char *prefix,
107 : uintptr_t index,
108 : std::string* output,
109 E : size_t bug_index) {
110 : base::StringAppendF(
111 E : output, "%s0x%08x:", prefix, reinterpret_cast<void*>(index << 3));
112 E : char separator = ' ';
113 E : for (uint32 i = 0; i < 8; i++) {
114 E : if (index + i == bug_index)
115 E : separator = '[';
116 E : uint8 shadow_value = shadow_[index + i];
117 : base::StringAppendF(
118 E : output, "%c%x%x", separator, shadow_value >> 4, shadow_value & 15);
119 E : if (separator == '[')
120 E : separator = ']';
121 E : else if (separator == ']')
122 E : separator = ' ';
123 E : }
124 E : if (separator == ']')
125 E : base::StringAppendF(output, "]");
126 E : base::StringAppendF(output, "\n");
127 E : }
128 :
129 : void Shadow::AppendShadowMemoryText(const void* addr,
130 E : std::string* output) {
131 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
132 E : index >>= 3;
133 E : base::StringAppendF(output, "Shadow bytes around the buggy address:\n");
134 E : size_t index_start = index;
135 E : index_start &= ~0x7;
136 E : for (int i = -4; i <= 4; i++) {
137 E : const char * const prefix = (i == 0) ? "=>" : " ";
138 E : AppendShadowByteText(prefix, (index_start + i * 8), output, index);
139 E : }
140 : base::StringAppendF(output,
141 E : "Shadow byte legend (one shadow byte represents 8 application bytes):\n");
142 : base::StringAppendF(output, " Addressable: %x%x\n",
143 E : kHeapAddressableByte >> 4, kHeapAddressableByte & 15);
144 : base::StringAppendF(output,
145 E : " Partially addressable: 01 02 03 04 05 06 07\n");
146 : base::StringAppendF(output, " Heap left redzone: %x%x\n",
147 E : kHeapLeftRedzone >> 4, kHeapLeftRedzone & 15);
148 : base::StringAppendF(output, " Heap righ redzone: %x%x\n",
149 E : kHeapRightRedzone >> 4, kHeapRightRedzone & 15);
150 : base::StringAppendF(output, " Freed Heap region: %x%x\n",
151 E : kHeapFreedByte >> 4, kHeapFreedByte & 15);
152 E : }
153 :
154 : } // namespace asan
155 : } // namespace agent
|