Chromium Code Reviews| OLD | NEW |
|---|---|
| 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, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. | 13 // limitations under the License. |
| 14 // | 14 // |
| 15 // Implements a class that manages shadow memory for Asan. | 15 // Implements a class that manages shadow memory for Asan. |
| 16 // | 16 // |
| 17 // The layout of a block is fully encoded in shadow memory, allowing for | 17 // The layout of a block is fully encoded in shadow memory, allowing for |
|
Sigurður Ásgeirsson
2016/11/22 19:15:37
maybe this comment can be relocated to a .md file
Sébastien Marchand
2016/11/22 22:12:23
Maybe, we don't really use .md files (yet) so if w
| |
| 18 // recovery of the block simply by inspecting the shadow memory. This is | 18 // recovery of the block simply by inspecting the shadow memory. This is |
| 19 // accomplished as follows: | 19 // accomplished as follows: |
| 20 // | 20 // |
| 21 // - Blocks are always a multiple of kShadowRatio in size and alignment. | 21 // - Blocks are always a multiple of kShadowRatio in size and alignment. |
| 22 // - Each group of kShadowRatio contiguous bytes is represented by a single | 22 // - Each group of kShadowRatio contiguous bytes is represented by a single |
| 23 // marker in the shadow. | 23 // marker in the shadow. |
| 24 // - The first marker of a block is a single block start marker, and the last | 24 // - The first marker of a block is a single block start marker, and the last |
| 25 // is a single block end marker. This uniquely identifies the beginning | 25 // is a single block end marker. This uniquely identifies the beginning |
| 26 // and end of a block simply by scanning and looking for balanced markers. | 26 // and end of a block simply by scanning and looking for balanced markers. |
| 27 // - The left and right redzones are uniquely identified by distinct markers. | 27 // - The left and right redzones are uniquely identified by distinct markers. |
| 28 // - The location of the header and trailer of a block are always at the | 28 // - The location of the header and trailer of a block are always at the |
| 29 // extremes, thus knowing the locations of the start and end markers | 29 // extremes, thus knowing the locations of the start and end markers |
| 30 // uniquely identifies their positions. | 30 // uniquely identifies their positions. |
| 31 // - The left redzone markers uniquely encodes the length of the header padding | 31 // - The left redzone markers uniquely encodes the length of the header padding |
| 32 // as it must also be a multiple of kShadowRatio in length. | 32 // as it must also be a multiple of kShadowRatio in length. |
| 33 // - The right redzone implies the length of the body of the allocation and | 33 // - The right redzone implies the length of the body of the allocation and |
| 34 // the trailer padding modulo kShadowRatio. The remaining bits are encoded | 34 // the trailer padding modulo kShadowRatio. The remaining bits are encoded |
| 35 // directly in the block start marker. | 35 // directly in the block start marker. |
| 36 // - Nested blocks and regular blocks use differing block start/end markers. | |
| 37 // This allows navigation through allocation hierarchies to terminate | |
| 38 // without necessitating a scan through the entire shadow memory. | |
| 39 // | 36 // |
| 40 // A typical block will look something like the following in shadow memory: | 37 // A typical block will look something like the following in shadow memory: |
| 41 // | 38 // |
| 42 // 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 39 // 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F |
| 43 // E7 FA FA FA 00 00 00 00 00 00 FB FB FB FB FB F4 | 40 // E7 FA FA FA 00 00 00 00 00 00 FB FB FB FB FB F4 |
| 44 // | \______/ \_______________/ \____________/ | | 41 // | \______/ \_______________/ \____________/ | |
| 45 // | : | : +-- Block end. | 42 // | : | : +-- Block end. |
| 46 // | : | + - - - - - Right redzone. | 43 // | : | + - - - - - Right redzone. |
| 47 // | : +--------------------------- Body of allocation. | 44 // | : +--------------------------- Body of allocation. |
| 48 // | +- - - - - - - - - - - - - - - - - - - - - Left redzone. | 45 // | +- - - - - - - - - - - - - - - - - - - - - Left redzone. |
| 49 // +----------------------------------------------- Block start. | 46 // +----------------------------------------------- Block start. |
| 50 // | 47 // |
| 51 // - Both the end marker and the start marker indicate the block | |
| 52 // is not nested. Together they indicate the total length of the | |
| 53 // block is 128 bytes. | |
| 54 // - The start marker indicates that the body length is 7 % 8. | 48 // - The start marker indicates that the body length is 7 % 8. |
| 55 // - The header padding indicates that the 16 byte header is followed | 49 // - The header padding indicates that the 16 byte header is followed |
| 56 // by a further 16 bytes of padding. | 50 // by a further 16 bytes of padding. |
| 57 // - The 6 body markers indicate an allocation size of 41..48 bytes. | 51 // - The 6 body markers indicate an allocation size of 41..48 bytes. |
| 58 // Combined with the start marker bits the allocation size can be | 52 // Combined with the start marker bits the allocation size can be |
| 59 // inferred as being 47 bytes, with the last byte contributing to | 53 // inferred as being 47 bytes, with the last byte contributing to |
| 60 // the trailer padding. | 54 // the trailer padding. |
| 61 // - The 5 right redzone markers indicate that the 20 byte trailer is | 55 // - The 5 right redzone markers indicate that the 20 byte trailer is |
| 62 // preceded by at least 28 trailer padding bytes. The additional | 56 // preceded by at least 28 trailer padding bytes. The additional |
| 63 // padding from the body means that there are in total 29 trailer | 57 // padding from the body means that there are in total 29 trailer |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 // @param size The size of the memory to poison. | 127 // @param size The size of the memory to poison. |
| 134 // @param shadow_val The poison marker value. | 128 // @param shadow_val The poison marker value. |
| 135 void Poison(const void* addr, size_t size, ShadowMarker shadow_val); | 129 void Poison(const void* addr, size_t size, ShadowMarker shadow_val); |
| 136 | 130 |
| 137 // Un-poisons @p size bytes starting at @p addr. | 131 // Un-poisons @p size bytes starting at @p addr. |
| 138 // @pre addr mod 8 == 0 && size mod 8 == 0. | 132 // @pre addr mod 8 == 0 && size mod 8 == 0. |
| 139 // @param addr The starting address. | 133 // @param addr The starting address. |
| 140 // @param size The size of the memory to unpoison. | 134 // @param size The size of the memory to unpoison. |
| 141 void Unpoison(const void* addr, size_t size); | 135 void Unpoison(const void* addr, size_t size); |
| 142 | 136 |
| 143 // Mark @p size bytes starting at @p addr as freed. This will preserve | 137 // Mark @p size bytes starting at @p addr as freed. |
| 144 // nested block headers/trailers/redzones, but mark all contents as freed. | |
| 145 // It is expected that the states of all nested blocks have already been | |
| 146 // marked as freed prior to possibly freeing the parent block. | |
| 147 // @param addr The starting address. | 138 // @param addr The starting address. |
| 148 // @param size The size of the memory to mark as freed. | 139 // @param size The size of the memory to mark as freed. |
| 149 void MarkAsFreed(const void* addr, size_t size); | 140 void MarkAsFreed(const void* addr, size_t size); |
| 150 | 141 |
| 151 // Returns true iff the byte at @p addr is not poisoned. | 142 // Returns true iff the byte at @p addr is not poisoned. |
| 152 // @param addr The address that we want to check. | 143 // @param addr The address that we want to check. |
| 153 // @returns true if this address is accessible, false otherwise. | 144 // @returns true if this address is accessible, false otherwise. |
| 154 bool IsAccessible(const void* addr) const; | 145 bool IsAccessible(const void* addr) const; |
| 155 | 146 |
| 156 // Returns true iff all the bytes from @p addr to @p addrs + size - 1 are | 147 // Returns true iff all the bytes from @p addr to @p addrs + size - 1 are |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 template<typename type> | 212 template<typename type> |
| 222 bool GetNullTerminatedArraySize(const void* addr, | 213 bool GetNullTerminatedArraySize(const void* addr, |
| 223 size_t max_size, | 214 size_t max_size, |
| 224 size_t* size) const; | 215 size_t* size) const; |
| 225 | 216 |
| 226 // Calculate the allocation size of a block by using the shadow memory. | 217 // Calculate the allocation size of a block by using the shadow memory. |
| 227 // @param mem A pointer inside the memory block for which we want to calculate | 218 // @param mem A pointer inside the memory block for which we want to calculate |
| 228 // the underlying allocation size. | 219 // the underlying allocation size. |
| 229 // @returns The underlying allocation size or 0 if it can't find a valid block | 220 // @returns The underlying allocation size or 0 if it can't find a valid block |
| 230 // at this address. | 221 // at this address. |
| 231 // @note This function doesn't work for nested blocks. | |
| 232 // TODO(sebmarchand): Add support for nested blocks. | |
| 233 size_t GetAllocSize(const uint8_t* mem) const; | 222 size_t GetAllocSize(const uint8_t* mem) const; |
| 234 | 223 |
| 235 // Poisons memory for an freshly allocated block. | 224 // Poisons memory for an freshly allocated block. |
| 236 // @param info Info about the block layout. | 225 // @param info Info about the block layout. |
| 237 // @note The block must be readable. | 226 // @note The block must be readable. |
| 238 void PoisonAllocatedBlock(const BlockInfo& info); | 227 void PoisonAllocatedBlock(const BlockInfo& info); |
| 239 | 228 |
| 240 // Determines if the block is nested simply by inspecting shadow memory. | |
| 241 bool BlockIsNested(const BlockInfo& info) const; | |
| 242 | |
| 243 // Inspects shadow memory to determine the layout of a block in memory. | 229 // Inspects shadow memory to determine the layout of a block in memory. |
| 244 // Does not rely on any block content itself, strictly reading from the | 230 // Does not rely on any block content itself, strictly reading from the |
| 245 // shadow memory. In the case of nested blocks this will always return | 231 // shadow memory. |
| 246 // the innermost containing block. | |
| 247 // @param addr An address in the block to be inspected. | 232 // @param addr An address in the block to be inspected. |
| 248 // @param info The block information to be populated. | 233 // @param info The block information to be populated. |
| 249 // @returns true on success, false otherwise. | 234 // @returns true on success, false otherwise. |
| 250 bool BlockInfoFromShadow(const void* addr, CompactBlockInfo* info) const; | 235 bool BlockInfoFromShadow(const void* addr, CompactBlockInfo* info) const; |
| 251 bool BlockInfoFromShadow(const void* addr, BlockInfo* info) const; | 236 bool BlockInfoFromShadow(const void* addr, BlockInfo* info) const; |
| 252 | 237 |
| 253 // Inspects shadow memory to find the block containing a nested block. | |
| 254 // @param nested Information about the nested block. | |
| 255 // @param info The block information to be populated. | |
| 256 // @returns true on success, false otherwise. | |
| 257 bool ParentBlockInfoFromShadow( | |
| 258 const BlockInfo& nested, BlockInfo* info) const; | |
| 259 | |
| 260 // Checks if the address @p addr corresponds to the beginning of a block's | 238 // Checks if the address @p addr corresponds to the beginning of a block's |
| 261 // body, i.e. if it's preceded by a left redzone. | 239 // body, i.e. if it's preceded by a left redzone. |
| 262 // @param addr The address that we want to check. | 240 // @param addr The address that we want to check. |
| 263 // @returns true if the address corresponds to the beginning of a block's | 241 // @returns true if the address corresponds to the beginning of a block's |
| 264 // body, false otherwise. | 242 // body, false otherwise. |
| 265 bool IsBeginningOfBlockBody(const void* addr) const; | 243 bool IsBeginningOfBlockBody(const void* addr) const; |
| 266 | 244 |
| 267 // Queries a given page's protection status. | 245 // Queries a given page's protection status. |
| 268 // @param addr An address in the page to be queried. | 246 // @param addr An address in the page to be queried. |
| 269 // @returns true if the address containing the given page is protected, | 247 // @returns true if the address containing the given page is protected, |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 // shadow_[index] to shadow_[index + 7], prefixed by @p prefix. If the index | 323 // shadow_[index] to shadow_[index + 7], prefixed by @p prefix. If the index |
| 346 // @p bug_index is present in this range then its value will be surrounded by | 324 // @p bug_index is present in this range then its value will be surrounded by |
| 347 // brackets. | 325 // brackets. |
| 348 void AppendShadowByteText(const char *prefix, | 326 void AppendShadowByteText(const char *prefix, |
| 349 uintptr_t index, | 327 uintptr_t index, |
| 350 std::string* output, | 328 std::string* output, |
| 351 size_t bug_index) const; | 329 size_t bug_index) const; |
| 352 | 330 |
| 353 // Scans to the left of the provided cursor, looking for the presence of a | 331 // Scans to the left of the provided cursor, looking for the presence of a |
| 354 // block start marker that brackets the cursor. | 332 // block start marker that brackets the cursor. |
| 355 // @param initial_nesting_depth If zero then this will return the inner | |
| 356 // most block containing the cursor. If 1 then this will find the start of | |
| 357 // the block containing that block, and so on. | |
| 358 // @param cursor The position in shadow memory from which to start the scan. | 333 // @param cursor The position in shadow memory from which to start the scan. |
| 359 // @param location Will be set to the location of the start marker, if found. | 334 // @param location Will be set to the location of the start marker, if found. |
| 360 // @returns true on success, false otherwise. | 335 // @returns true on success, false otherwise. |
| 361 bool ScanLeftForBracketingBlockStart( | 336 bool ScanLeftForBracketingBlockStart(size_t cursor, size_t* location) const; |
| 362 size_t initial_nesting_depth, size_t cursor, size_t* location) const; | |
| 363 | 337 |
| 364 // Scans to the right of the provided cursor, looking for the presence of a | 338 // Scans to the right of the provided cursor, looking for the presence of a |
| 365 // block end marker that brackets the cursor. | 339 // block end marker that brackets the cursor. |
| 366 // @param initial_nesting_depth If zero then this will return the inner | |
| 367 // most block containing the cursor. If 1 then this will find the end of | |
| 368 // the block containing that block, and so on. | |
| 369 // @param cursor The position in shadow memory from which to start the scan. | 340 // @param cursor The position in shadow memory from which to start the scan. |
| 370 // @param location Will be set to the location of the end marker, if found. | 341 // @param location Will be set to the location of the end marker, if found. |
| 371 // @returns true on success, false otherwise. | 342 // @returns true on success, false otherwise. |
| 372 bool ScanRightForBracketingBlockEnd( | 343 bool ScanRightForBracketingBlockEnd(size_t cursor, size_t* location) const; |
| 373 size_t initial_nesting_depth, size_t cursor, size_t* location) const; | |
| 374 | 344 |
| 375 // Inspects shadow memory to determine the layout of a block in memory. | 345 // Inspects shadow memory to determine the layout of a block in memory. |
| 376 // @param initial_nesting_depth If zero then this will return the inner | |
| 377 // most block containing the cursor. If 1 then this will find the end of | |
| 378 // the block containing that block, and so on. | |
| 379 // @param addr An address in the block to be inspected. | 346 // @param addr An address in the block to be inspected. |
| 380 // @param info The block information to be populated. | 347 // @param info The block information to be populated. |
| 381 // @returns true on success, false otherwise. | 348 // @returns true on success, false otherwise. |
| 382 bool BlockInfoFromShadowImpl( | 349 bool BlockInfoFromShadowImpl( |
| 383 size_t initial_nesting_depth, | |
| 384 const void* addr, | 350 const void* addr, |
| 385 CompactBlockInfo* info) const; | 351 CompactBlockInfo* info) const; |
| 386 | 352 |
| 387 // If this is true then this shadow object owns the memory. | 353 // If this is true then this shadow object owns the memory. |
| 388 bool own_memory_; | 354 bool own_memory_; |
| 389 | 355 |
| 390 // The actual shadow that is being referred to. In case of large | 356 // The actual shadow that is being referred to. In case of large |
| 391 // address spaces it's stored as a sparse array | 357 // address spaces it's stored as a sparse array |
| 392 // (see ShadowExceptionHandler in the .cc file). | 358 // (see ShadowExceptionHandler in the .cc file). |
| 393 uint8_t* shadow_; | 359 uint8_t* shadow_; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 412 HANDLE exception_handler_; | 378 HANDLE exception_handler_; |
| 413 #endif | 379 #endif |
| 414 }; | 380 }; |
| 415 | 381 |
| 416 // A helper class to walk over the blocks contained in a given memory region. | 382 // A helper class to walk over the blocks contained in a given memory region. |
| 417 // This uses only the metadata present in the shadow to identify the blocks. | 383 // This uses only the metadata present in the shadow to identify the blocks. |
| 418 class ShadowWalker { | 384 class ShadowWalker { |
| 419 public: | 385 public: |
| 420 // Constructor. | 386 // Constructor. |
| 421 // @param shadow The shadow memory object to walk. | 387 // @param shadow The shadow memory object to walk. |
| 422 // @param recursive If true then this will recursively descend into nested | |
| 423 // blocks. Otherwise it will only return the outermost blocks in the | |
| 424 // provided region. | |
| 425 // @param lower_bound The lower bound of the region that this walker should | 388 // @param lower_bound The lower bound of the region that this walker should |
| 426 // cover in the actual memory. | 389 // cover in the actual memory. |
| 427 // @param upper_bound The upper bound of the region that this walker should | 390 // @param upper_bound The upper bound of the region that this walker should |
| 428 // cover in the actual memory. This can overflow to 0 to indicate walking | 391 // cover in the actual memory. This can overflow to 0 to indicate walking |
| 429 // all of memory. | 392 // all of memory. |
| 430 ShadowWalker(const Shadow* shadow, | 393 ShadowWalker(const Shadow* shadow, |
| 431 bool recursive, | |
| 432 const void* lower_bound, | 394 const void* lower_bound, |
| 433 const void* upper_bound); | 395 const void* upper_bound); |
| 434 | 396 |
| 435 // Return the next block in this memory region. | 397 // Return the next block in this memory region. |
| 436 // @param info The block information to be populated. | 398 // @param info The block information to be populated. |
| 437 // @return true if a block was found, false otherwise. | 399 // @return true if a block was found, false otherwise. |
| 438 bool Next(BlockInfo* info); | 400 bool Next(BlockInfo* info); |
| 439 | 401 |
| 440 // Reset the walker to its initial state. | 402 // Reset the walker to its initial state. |
| 441 void Reset(); | 403 void Reset(); |
| 442 | 404 |
| 443 // @returns the nesting depth of the last returned block. If no blocks have | |
| 444 // been walked then this returns -1. | |
| 445 int nesting_depth() const { return nesting_depth_; } | |
| 446 | |
| 447 private: | 405 private: |
| 448 // The shadow memory being walked. | 406 // The shadow memory being walked. |
| 449 const Shadow* shadow_; | 407 const Shadow* shadow_; |
| 450 | 408 |
| 451 // Indicates whether or not the walker will descend recursively into nested | |
| 452 // blocks. | |
| 453 bool recursive_; | |
| 454 | |
| 455 // The bounds of the memory region for this walker, expressed as pointers in | 409 // The bounds of the memory region for this walker, expressed as pointers in |
| 456 // the shadow memory. This allows walking to occur without worrying about | 410 // the shadow memory. This allows walking to occur without worrying about |
| 457 // overflow. | 411 // overflow. |
| 458 size_t lower_index_; | 412 size_t lower_index_; |
| 459 size_t upper_index_; | 413 size_t upper_index_; |
| 460 | 414 |
| 461 // The shadow cursor. | 415 // The shadow cursor. |
| 462 const uint8_t* shadow_cursor_; | 416 const uint8_t* shadow_cursor_; |
| 463 | 417 |
| 464 // The current nesting depth. Starts at -1. | |
| 465 int nesting_depth_; | |
| 466 | |
| 467 DISALLOW_COPY_AND_ASSIGN(ShadowWalker); | 418 DISALLOW_COPY_AND_ASSIGN(ShadowWalker); |
| 468 }; | 419 }; |
| 469 | 420 |
| 470 // The static shadow memory that is referred to by the memory interceptors. | 421 // The static shadow memory that is referred to by the memory interceptors. |
| 471 // These are provided by one of 'dummy_shadow.cc' or 'static_shadow.cc'. | 422 // These are provided by one of 'dummy_shadow.cc' or 'static_shadow.cc'. |
| 472 extern "C" { | 423 extern "C" { |
| 473 extern const size_t asan_memory_interceptors_shadow_memory_size; | 424 extern const size_t asan_memory_interceptors_shadow_memory_size; |
| 474 extern uint8_t asan_memory_interceptors_shadow_memory[]; | 425 extern uint8_t asan_memory_interceptors_shadow_memory[]; |
| 475 } | 426 } |
| 476 | 427 |
| 477 // Bring in the implementation of the templated functions. | 428 // Bring in the implementation of the templated functions. |
| 478 #include "syzygy/agent/asan/shadow_impl.h" | 429 #include "syzygy/agent/asan/shadow_impl.h" |
| 479 | 430 |
| 480 } // namespace asan | 431 } // namespace asan |
| 481 } // namespace agent | 432 } // namespace agent |
| 482 | 433 |
| 483 #endif // SYZYGY_AGENT_ASAN_SHADOW_H_ | 434 #endif // SYZYGY_AGENT_ASAN_SHADOW_H_ |
| OLD | NEW |