Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(214)

Side by Side Diff: syzygy/agent/asan/shadow.cc

Issue 2421523003: Fix a bug in the shadow walker. (Closed)
Patch Set: nit Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | syzygy/agent/asan/shadow_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 Google Inc. All Rights Reserved. 1 // Copyright 2012 Google Inc. All Rights Reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with 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 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 15 matching lines...) Expand all
26 26
27 namespace { 27 namespace {
28 28
29 #ifdef _WIN64 29 #ifdef _WIN64
30 // A lock under which the shadow instance is modified. 30 // A lock under which the shadow instance is modified.
31 base::Lock shadow_instance_lock; 31 base::Lock shadow_instance_lock;
32 32
33 // The pointer for the exception handler to know what shadow object is 33 // The pointer for the exception handler to know what shadow object is
34 // currently used. Under shadow_instance_lock. 34 // currently used. Under shadow_instance_lock.
35 // TODO(loskutov): eliminate this by enforcing Shadow to be a singleton. 35 // TODO(loskutov): eliminate this by enforcing Shadow to be a singleton.
36 const Shadow* shadow_instance; 36 const Shadow* shadow_instance = nullptr;
37 37
38 // The exception handler, intended to map the pages for shadow and page_bits 38 // The exception handler, intended to map the pages for shadow and page_bits
39 // on demand. When a page fault happens, the operating systems calls 39 // on demand. When a page fault happens, the operating systems calls
40 // this handler, and if the page is inside shadow or page_bits, it gets 40 // this handler, and if the page is inside shadow or page_bits, it gets
41 // commited seamlessly for the caller, and then execution continues. 41 // commited seamlessly for the caller, and then execution continues.
42 // Otherwise, the OS keeps searching for an appropriate handler. 42 // Otherwise, the OS keeps searching for an appropriate handler.
43 LONG NTAPI ShadowExceptionHandler(PEXCEPTION_POINTERS exception_pointers) { 43 LONG NTAPI ShadowExceptionHandler(PEXCEPTION_POINTERS exception_pointers) {
44 DCHECK_NE(static_cast<const Shadow*>(nullptr), shadow_instance);
44 // Only handle access violations. 45 // Only handle access violations.
45 if (exception_pointers->ExceptionRecord->ExceptionCode != 46 if (exception_pointers->ExceptionRecord->ExceptionCode !=
46 EXCEPTION_ACCESS_VIOLATION) { 47 EXCEPTION_ACCESS_VIOLATION) {
47 return EXCEPTION_CONTINUE_SEARCH; 48 return EXCEPTION_CONTINUE_SEARCH;
48 } 49 }
49 50
50 // Only handle access violations that land within the shadow memory 51 // Only handle access violations that land within the shadow memory
51 // or the page bits. 52 // or the page bits.
52 53
53 void* addr = reinterpret_cast<void*>( 54 void* addr = reinterpret_cast<void*>(
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 } 209 }
209 210
210 auto cursor = shadow_ + i; 211 auto cursor = shadow_ + i;
211 MEMORY_BASIC_INFORMATION info = {}; 212 MEMORY_BASIC_INFORMATION info = {};
212 while (i < length_) { 213 while (i < length_) {
213 auto next_cursor = cursor; 214 auto next_cursor = cursor;
214 while (cursor < shadow_ + length_) { 215 while (cursor < shadow_ + length_) {
215 auto ret = ::VirtualQuery(cursor, &info, sizeof(info)); 216 auto ret = ::VirtualQuery(cursor, &info, sizeof(info));
216 DCHECK_GT(ret, 0u); 217 DCHECK_GT(ret, 0u);
217 next_cursor = static_cast<uint8_t*>(info.BaseAddress) + info.RegionSize; 218 next_cursor = static_cast<uint8_t*>(info.BaseAddress) + info.RegionSize;
218 if (info.Type == MEM_COMMIT) 219 if (info.State == MEM_COMMIT)
219 break; 220 break;
220 cursor = next_cursor; 221 cursor = next_cursor;
221 } 222 }
222 i = cursor - shadow_; 223 i = cursor - shadow_;
223 next_cursor = std::min(next_cursor, shadow_ + length_); 224 next_cursor = std::min(next_cursor, shadow_ + length_);
224 auto next_i = next_cursor - shadow_; 225 auto next_i = next_cursor - shadow_;
225 for (; i < next_i; ++i) { 226 for (; i < next_i; ++i) {
226 if ((i >= shadow_begin && i < shadow_end) || 227 if ((i >= shadow_begin && i < shadow_end) ||
227 (i >= page_bits_begin && i < page_bits_end) || 228 (i >= page_bits_begin && i < page_bits_end) ||
228 (i >= this_begin && i < this_end)) { 229 (i >= this_begin && i < this_end)) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 Init(true, mem, length); 278 Init(true, mem, length);
278 } 279 }
279 280
280 void Shadow::Init(bool own_memory, void* shadow, size_t length) { 281 void Shadow::Init(bool own_memory, void* shadow, size_t length) {
281 #ifdef _WIN64 282 #ifdef _WIN64
282 { 283 {
283 base::AutoLock lock(shadow_instance_lock); 284 base::AutoLock lock(shadow_instance_lock);
284 shadow_instance = this; 285 shadow_instance = this;
285 } 286 }
286 exception_handler_ = 287 exception_handler_ =
287 AddVectoredExceptionHandler(TRUE, ShadowExceptionHandler); 288 ::AddVectoredExceptionHandler(TRUE, ShadowExceptionHandler);
288 #endif 289 #endif
289 290
290 // Handle the case of a failed allocation. 291 // Handle the case of a failed allocation.
291 if (shadow == nullptr) { 292 if (shadow == nullptr) {
292 own_memory_ = false; 293 own_memory_ = false;
293 shadow_ = nullptr; 294 shadow_ = nullptr;
294 length = 0; 295 length = 0;
295 return; 296 return;
296 } 297 }
297 298
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 } 878 }
878 879
879 bool Shadow::ScanLeftForBracketingBlockStart( 880 bool Shadow::ScanLeftForBracketingBlockStart(
880 size_t initial_nesting_depth, size_t cursor, size_t* location) const { 881 size_t initial_nesting_depth, size_t cursor, size_t* location) const {
881 DCHECK_NE(static_cast<size_t*>(NULL), location); 882 DCHECK_NE(static_cast<size_t*>(NULL), location);
882 883
883 static const size_t kLowerBound = kAddressLowerBound / kShadowRatio; 884 static const size_t kLowerBound = kAddressLowerBound / kShadowRatio;
884 885
885 size_t left = cursor; 886 size_t left = cursor;
886 int nesting_depth = static_cast<int>(initial_nesting_depth); 887 int nesting_depth = static_cast<int>(initial_nesting_depth);
888
889 MEMORY_BASIC_INFORMATION memory_info = {};
890 SIZE_T ret =
891 ::VirtualQuery(&shadow_[left], &memory_info, sizeof(memory_info));
892 DCHECK_GT(ret, 0u);
893 if (memory_info.State != MEM_COMMIT)
894 return false;
895
887 if (ShadowMarkerHelper::IsBlockEnd(shadow_[left])) 896 if (ShadowMarkerHelper::IsBlockEnd(shadow_[left]))
888 --nesting_depth; 897 --nesting_depth;
889 while (true) { 898 while (true) {
899 if (&shadow_[left] < static_cast<const uint8_t*>(memory_info.BaseAddress)) {
900 ret = ::VirtualQuery(&shadow_[left], &memory_info, sizeof(memory_info));
901 DCHECK_GT(ret, 0u);
902 if (memory_info.State != MEM_COMMIT)
903 return false;
904 }
890 if (ShadowMarkerHelper::IsBlockStart(shadow_[left])) { 905 if (ShadowMarkerHelper::IsBlockStart(shadow_[left])) {
891 if (nesting_depth == 0) { 906 if (nesting_depth == 0) {
892 *location = left; 907 *location = left;
893 return true; 908 return true;
894 } 909 }
895 // If this is not a nested block then there's no hope of finding a 910 // If this is not a nested block then there's no hope of finding a
896 // block containing the original cursor. 911 // block containing the original cursor.
897 if (!ShadowMarkerHelper::IsNestedBlockStart(shadow_[left])) 912 if (!ShadowMarkerHelper::IsNestedBlockStart(shadow_[left]))
898 return false; 913 return false;
899 --nesting_depth; 914 --nesting_depth;
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 // Get the bounds as shadow indices, being careful to deal with overflow 1115 // Get the bounds as shadow indices, being careful to deal with overflow
1101 // of |upper_bound|. 1116 // of |upper_bound|.
1102 lower_index_ = reinterpret_cast<uintptr_t>(lower_bound) >> kShadowRatioLog; 1117 lower_index_ = reinterpret_cast<uintptr_t>(lower_bound) >> kShadowRatioLog;
1103 upper_index_ = reinterpret_cast<size_t>(::common::AlignUp( 1118 upper_index_ = reinterpret_cast<size_t>(::common::AlignUp(
1104 reinterpret_cast<const uint8_t*>(upper_bound), kShadowRatio)); 1119 reinterpret_cast<const uint8_t*>(upper_bound), kShadowRatio));
1105 upper_index_--; 1120 upper_index_--;
1106 upper_index_ >>= kShadowRatioLog; 1121 upper_index_ >>= kShadowRatioLog;
1107 upper_index_++; 1122 upper_index_++;
1108 1123
1109 DCHECK_LE(lower_index_, upper_index_); 1124 DCHECK_LE(lower_index_, upper_index_);
1110 DCHECK_GE(shadow->length(), upper_index_); 1125 DCHECK_GE(shadow->length(), upper_index_ - lower_index_);
1111 1126
1112 Reset(); 1127 Reset();
1113 } 1128 }
1114 1129
1115 void ShadowWalker::Reset() { 1130 void ShadowWalker::Reset() {
1116 nesting_depth_ = -1; 1131 nesting_depth_ = -1;
1117 shadow_cursor_ = shadow_->shadow() + lower_index_; 1132 shadow_cursor_ = shadow_->shadow() + lower_index_;
1118 } 1133 }
1119 1134
1120 bool ShadowWalker::Next(BlockInfo* info) { 1135 bool ShadowWalker::Next(BlockInfo* info) {
(...skipping 13 matching lines...) Expand all
1134 auto end_of_region = start_of_region + memory_info.RegionSize; 1149 auto end_of_region = start_of_region + memory_info.RegionSize;
1135 1150
1136 // If the region isn't committed and readable memory then skip it. 1151 // If the region isn't committed and readable memory then skip it.
1137 if (memory_info.State != MEM_COMMIT) { 1152 if (memory_info.State != MEM_COMMIT) {
1138 // If the next region is beyond the part of the shadow being scanned 1153 // If the next region is beyond the part of the shadow being scanned
1139 // then bail early (be careful to handle overflow here). 1154 // then bail early (be careful to handle overflow here).
1140 if (end_of_region > shadow_upper_bound || end_of_region == nullptr) 1155 if (end_of_region > shadow_upper_bound || end_of_region == nullptr)
1141 return false; 1156 return false;
1142 1157
1143 // Step to the beginning of the next region and try again. 1158 // Step to the beginning of the next region and try again.
1144 shadow_cursor_ = start_of_region; 1159 shadow_cursor_ = end_of_region;
1145 continue; 1160 continue;
1146 } 1161 }
1147 1162
1148 // Getting here then |start_of_region| and |end_of_region| are a part of 1163 // Getting here then |start_of_region| and |end_of_region| are a part of
1149 // the shadow that should be scanned. Calculate where to stop for this 1164 // the shadow that should be scanned. Calculate where to stop for this
1150 // region, taking care to handle overflow. 1165 // region, taking care to handle overflow.
1151 if (!end_of_region) { 1166 if (!end_of_region) {
1152 end_of_region = shadow_upper_bound; 1167 end_of_region = shadow_upper_bound;
1153 } else { 1168 } else {
1154 end_of_region = std::min(shadow_upper_bound, end_of_region); 1169 end_of_region = std::min(shadow_upper_bound, end_of_region);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 // Advance the shadow cursor. 1221 // Advance the shadow cursor.
1207 ++shadow_cursor_; 1222 ++shadow_cursor_;
1208 } // while (shadow_cursor_ < end_of_region) 1223 } // while (shadow_cursor_ < end_of_region)
1209 } 1224 }
1210 1225
1211 return false; 1226 return false;
1212 } 1227 }
1213 1228
1214 } // namespace asan 1229 } // namespace asan
1215 } // namespace agent 1230 } // namespace agent
OLDNEW
« no previous file with comments | « no previous file | syzygy/agent/asan/shadow_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698