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 : // Poison the first 64k of the memory as they're not addressable.
28 E : Poison(0, 0x10000, kInvalidAddress);
29 E : }
30 :
31 E : void Shadow::TearDown() {
32 : // Unpoison the shadow memory.
33 E : Unpoison(shadow_, kShadowSize);
34 : // Unpoison the first 64k of the memory.
35 E : Unpoison(0, 0x10000);
36 E : }
37 :
38 E : void Shadow::Reset() {
39 E : memset(shadow_, 0, kShadowSize);
40 E : }
41 :
42 E : void Shadow::Poison(const void* addr, size_t size, ShadowMarker shadow_val) {
43 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
44 E : uintptr_t start = index & 0x7;
45 E : DCHECK_EQ(0U, (index + size) & 0x7);
46 :
47 E : index >>= 3;
48 E : if (start)
49 E : shadow_[index++] = start;
50 :
51 E : size >>= 3;
52 E : DCHECK_GT(arraysize(shadow_), index + size);
53 E : memset(shadow_ + index, shadow_val, size);
54 E : }
55 :
56 E : void Shadow::Unpoison(const void* addr, size_t size) {
57 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
58 E : DCHECK_EQ(0U, index & 0x7);
59 :
60 E : uint8 remainder = size & 0x7;
61 E : index >>= 3;
62 E : size >>= 3;
63 E : DCHECK_GT(arraysize(shadow_), index + size);
64 E : memset(shadow_ + index, kHeapAddressableByte, size);
65 :
66 E : if (remainder != 0)
67 E : shadow_[index + size] = remainder;
68 E : }
69 :
70 E : void Shadow::MarkAsFreed(const void* addr, size_t size) {
71 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
72 E : uintptr_t start = index & 0x7;
73 :
74 E : index >>= 3;
75 E : if (start)
76 i : shadow_[index++] = kHeapFreedByte;
77 :
78 E : size_t size_shadow = size >> 3;
79 E : DCHECK_GT(arraysize(shadow_), index + size_shadow);
80 E : memset(shadow_ + index, kHeapFreedByte, size_shadow);
81 E : if ((size & 0x7) != 0)
82 E : shadow_[index + size_shadow] = kHeapFreedByte;
83 E : }
84 :
85 E : bool Shadow::IsAccessible(const void* addr) {
86 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
87 E : uintptr_t start = index & 0x7;
88 :
89 E : index >>= 3;
90 :
91 E : DCHECK_GT(arraysize(shadow_), index);
92 E : uint8 shadow = shadow_[index];
93 E : if (shadow == 0)
94 E : return true;
95 :
96 E : if ((shadow & kHeapNonAccessibleByteMask) != 0)
97 E : return false;
98 :
99 E : return start < shadow;
100 E : }
101 :
102 E : Shadow::ShadowMarker Shadow::GetShadowMarkerForAddress(const void* addr) {
103 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
104 E : index >>= 3;
105 :
106 E : DCHECK_GT(arraysize(shadow_), index);
107 E : return static_cast<ShadowMarker>(shadow_[index]);
108 E : }
109 :
110 : void Shadow::CloneShadowRange(const void* src_pointer,
111 : void* dst_pointer,
112 E : size_t size) {
113 E : DCHECK_EQ(0U, size & 0x7);
114 :
115 E : uintptr_t src_index = reinterpret_cast<uintptr_t>(src_pointer);
116 E : DCHECK_EQ(0U, src_index & 0x7);
117 E : src_index >>= 3;
118 :
119 E : uintptr_t dst_index = reinterpret_cast<uintptr_t>(dst_pointer);
120 E : DCHECK_EQ(0U, dst_index & 0x7);
121 E : dst_index >>= 3;
122 :
123 E : size_t size_shadow = size >> 3;
124 :
125 E : memcpy(shadow_ + dst_index, shadow_ + src_index, size_shadow);
126 E : }
127 :
128 : void Shadow::AppendShadowByteText(const char *prefix,
129 : uintptr_t index,
130 : std::string* output,
131 E : size_t bug_index) {
132 : base::StringAppendF(
133 E : output, "%s0x%08x:", prefix, reinterpret_cast<void*>(index << 3));
134 E : char separator = ' ';
135 E : for (uint32 i = 0; i < 8; i++) {
136 E : if (index + i == bug_index)
137 E : separator = '[';
138 E : uint8 shadow_value = shadow_[index + i];
139 : base::StringAppendF(
140 E : output, "%c%x%x", separator, shadow_value >> 4, shadow_value & 15);
141 E : if (separator == '[')
142 E : separator = ']';
143 E : else if (separator == ']')
144 E : separator = ' ';
145 E : }
146 E : if (separator == ']')
147 E : base::StringAppendF(output, "]");
148 E : base::StringAppendF(output, "\n");
149 E : }
150 :
151 E : void Shadow::AppendShadowArrayText(const void* addr, std::string* output) {
152 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
153 E : index >>= 3;
154 E : size_t index_start = index;
155 E : index_start &= ~0x7;
156 E : for (int i = -4; i <= 4; i++) {
157 E : const char * const prefix = (i == 0) ? "=>" : " ";
158 E : AppendShadowByteText(prefix, (index_start + i * 8), output, index);
159 E : }
160 E : }
161 :
162 E : void Shadow::AppendShadowMemoryText(const void* addr, std::string* output) {
163 E : base::StringAppendF(output, "Shadow bytes around the buggy address:\n");
164 E : AppendShadowArrayText(addr, output);
165 : base::StringAppendF(output,
166 E : "Shadow byte legend (one shadow byte represents 8 application bytes):\n");
167 : base::StringAppendF(output, " Addressable: %x%x\n",
168 E : kHeapAddressableByte >> 4, kHeapAddressableByte & 15);
169 : base::StringAppendF(output,
170 E : " Partially addressable: 01 02 03 04 05 06 07\n");
171 : base::StringAppendF(output, " Heap left redzone: %x%x\n",
172 E : kHeapLeftRedzone >> 4, kHeapLeftRedzone & 15);
173 : base::StringAppendF(output, " Heap righ redzone: %x%x\n",
174 E : kHeapRightRedzone >> 4, kHeapRightRedzone & 15);
175 : base::StringAppendF(output, " Freed Heap region: %x%x\n",
176 E : kHeapFreedByte >> 4, kHeapFreedByte & 15);
177 E : }
178 :
179 : bool Shadow::GetNullTerminatedArraySize(const void* addr,
180 : size_t* size,
181 E : size_t max_size) {
182 E : DCHECK(addr != NULL);
183 E : DCHECK(size != NULL);
184 :
185 E : uintptr_t index = reinterpret_cast<uintptr_t>(addr);
186 E : const uint8* addr_value = reinterpret_cast<const uint8*>(addr);
187 E : index >>= 3;
188 E : *size = 0;
189 :
190 : // Scan the input array 8 bytes at a time until we've found a NULL value or
191 : // we've reached the end of an accessible memory block.
192 : // TODO(sebmarchand): Look into doing this more efficiently.
193 E : while (true) {
194 E : uint8 shadow = shadow_[index++];
195 E : if ((shadow & kHeapNonAccessibleByteMask) != 0)
196 E : return false;
197 :
198 E : uint8 max_index = shadow ? shadow : 8;
199 E : while (max_index-- > 0) {
200 E : (*size)++;
201 E : if (*size == max_size || *addr_value == 0)
202 E : return true;
203 E : addr_value++;
204 E : }
205 :
206 E : if (shadow != 0)
207 E : return false;
208 E : }
209 E : }
210 :
211 : } // namespace asan
212 : } // namespace agent
|