Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 404 WTF_EXPORT void partitionPurgeMemory(PartitionRoot*, int); | 404 WTF_EXPORT void partitionPurgeMemory(PartitionRoot*, int); |
| 405 WTF_EXPORT void partitionPurgeMemoryGeneric(PartitionRootGeneric*, int); | 405 WTF_EXPORT void partitionPurgeMemoryGeneric(PartitionRootGeneric*, int); |
| 406 | 406 |
| 407 WTF_EXPORT NEVER_INLINE void* partitionAllocSlowPath(PartitionRootBase*, int, si ze_t, PartitionBucket*); | 407 WTF_EXPORT NEVER_INLINE void* partitionAllocSlowPath(PartitionRootBase*, int, si ze_t, PartitionBucket*); |
| 408 WTF_EXPORT NEVER_INLINE void partitionFreeSlowPath(PartitionPage*); | 408 WTF_EXPORT NEVER_INLINE void partitionFreeSlowPath(PartitionPage*); |
| 409 WTF_EXPORT NEVER_INLINE void* partitionReallocGeneric(PartitionRootGeneric*, voi d*, size_t); | 409 WTF_EXPORT NEVER_INLINE void* partitionReallocGeneric(PartitionRootGeneric*, voi d*, size_t); |
| 410 | 410 |
| 411 WTF_EXPORT void partitionDumpStats(PartitionRoot*, const char* partitionName, bo ol isLightDump, PartitionStatsDumper*); | 411 WTF_EXPORT void partitionDumpStats(PartitionRoot*, const char* partitionName, bo ol isLightDump, PartitionStatsDumper*); |
| 412 WTF_EXPORT void partitionDumpStatsGeneric(PartitionRootGeneric*, const char* par titionName, bool isLightDump, PartitionStatsDumper*); | 412 WTF_EXPORT void partitionDumpStatsGeneric(PartitionRootGeneric*, const char* par titionName, bool isLightDump, PartitionStatsDumper*); |
| 413 | 413 |
| 414 class WTF_EXPORT PartitionAllocHooks { | |
| 415 public: | |
| 416 typedef void AllocationHook(void* address, size_t); | |
| 417 typedef void FreeHook(void* address); | |
| 418 | |
| 419 static void setAllocationHook(AllocationHook* hook) { m_allocationHook = hoo k; } | |
| 420 static void setFreeHook(FreeHook* hook) { m_freeHook = hook; } | |
| 421 | |
| 422 static void maybeInvokeAllocationHook(void* address, size_t size) | |
|
haraken
2015/10/20 00:14:19
I'd rename maybeInvokeAllocationHook() to allocati
Ruud van Asseldonk
2015/10/20 11:43:57
Done.
| |
| 423 { | |
| 424 AllocationHook* hook = m_allocationHook; | |
|
Primiano Tucci (use gerrit)
2015/10/19 21:32:03
probably a bit more readable if you s/hook/allocat
Ruud van Asseldonk
2015/10/20 11:43:57
Done.
| |
| 425 if (UNLIKELY(hook != nullptr)) | |
|
bashi
2015/10/20 00:33:49
nit: UNLIKELY(hook).
We don't use ptr != nullptr
Ruud van Asseldonk
2015/10/20 11:43:57
This is because |UNLIKELY(ptr)| expands to |__buil
| |
| 426 hook(address, size); | |
| 427 } | |
| 428 | |
| 429 static void maybeInvokeFreeHook(void* address) | |
| 430 { | |
| 431 FreeHook* hook = m_freeHook; | |
| 432 if (UNLIKELY(hook != nullptr)) | |
| 433 hook(address); | |
| 434 } | |
| 435 | |
| 436 static void maybeInvokeReallocationHook(void* oldAddress, void* newAddress, size_t size) | |
|
haraken
2015/10/20 00:14:19
You won't need this method if you insert the alloc
Ruud van Asseldonk
2015/10/20 11:43:57
Wouldn't I still need it for |partitionReallocGene
| |
| 437 { | |
| 438 // Report a reallocation as a free followed by an allocation. | |
| 439 AllocationHook* allocHook = m_allocationHook; | |
| 440 FreeHook* freeHook = m_freeHook; | |
| 441 if (UNLIKELY(allocHook && freeHook)) { | |
| 442 freeHook(oldAddress); | |
| 443 allocHook(newAddress, size); | |
| 444 } | |
| 445 } | |
| 446 | |
| 447 private: | |
| 448 // Pointers to hook functions that PartitionAlloc will call on allocation an d | |
| 449 // free if the pointers are non-null. | |
| 450 static AllocationHook* m_allocationHook; | |
| 451 static FreeHook* m_freeHook; | |
| 452 }; | |
| 453 | |
| 414 ALWAYS_INLINE PartitionFreelistEntry* partitionFreelistMask(PartitionFreelistEnt ry* ptr) | 454 ALWAYS_INLINE PartitionFreelistEntry* partitionFreelistMask(PartitionFreelistEnt ry* ptr) |
| 415 { | 455 { |
| 416 // We use bswap on little endian as a fast mask for two reasons: | 456 // We use bswap on little endian as a fast mask for two reasons: |
| 417 // 1) If an object is freed and its vtable used where the attacker doesn't | 457 // 1) If an object is freed and its vtable used where the attacker doesn't |
| 418 // get the chance to run allocations between the free and use, the vtable | 458 // get the chance to run allocations between the free and use, the vtable |
| 419 // dereference is likely to fault. | 459 // dereference is likely to fault. |
| 420 // 2) If the attacker has a linear buffer overflow and elects to try and | 460 // 2) If the attacker has a linear buffer overflow and elects to try and |
| 421 // corrupt a freelist pointer, partial pointer overwrite attacks are | 461 // corrupt a freelist pointer, partial pointer overwrite attacks are |
| 422 // thwarted. | 462 // thwarted. |
| 423 // For big endian, similar guarantees are arrived at with a negation. | 463 // For big endian, similar guarantees are arrived at with a negation. |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 606 slotSize = rawSize; | 646 slotSize = rawSize; |
| 607 } | 647 } |
| 608 size_t noCookieSize = partitionCookieSizeAdjustSubtract(slotSize); | 648 size_t noCookieSize = partitionCookieSizeAdjustSubtract(slotSize); |
| 609 char* charRet = static_cast<char*>(ret); | 649 char* charRet = static_cast<char*>(ret); |
| 610 // The value given to the application is actually just after the cookie. | 650 // The value given to the application is actually just after the cookie. |
| 611 ret = charRet + kCookieSize; | 651 ret = charRet + kCookieSize; |
| 612 memset(ret, kUninitializedByte, noCookieSize); | 652 memset(ret, kUninitializedByte, noCookieSize); |
| 613 partitionCookieWriteValue(charRet); | 653 partitionCookieWriteValue(charRet); |
| 614 partitionCookieWriteValue(charRet + kCookieSize + noCookieSize); | 654 partitionCookieWriteValue(charRet + kCookieSize + noCookieSize); |
| 615 #endif | 655 #endif |
| 656 | |
| 657 PartitionAllocHooks::maybeInvokeAllocationHook(ret, size); | |
|
haraken
2015/10/20 00:14:19
You need to insert the allocation hook to partitio
haraken
2015/10/20 00:14:19
And you need to insert the allocation hook to part
| |
| 658 | |
| 616 return ret; | 659 return ret; |
| 617 } | 660 } |
| 618 | 661 |
| 619 ALWAYS_INLINE void* partitionAlloc(PartitionRoot* root, size_t size) | 662 ALWAYS_INLINE void* partitionAlloc(PartitionRoot* root, size_t size) |
| 620 { | 663 { |
| 621 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) | 664 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) |
| 622 void* result = malloc(size); | 665 void* result = malloc(size); |
| 623 RELEASE_ASSERT(result); | 666 RELEASE_ASSERT(result); |
| 624 return result; | 667 return result; |
| 625 #else | 668 #else |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 638 // If these asserts fire, you probably corrupted memory. | 681 // If these asserts fire, you probably corrupted memory. |
| 639 #if ENABLE(ASSERT) | 682 #if ENABLE(ASSERT) |
| 640 size_t slotSize = page->bucket->slotSize; | 683 size_t slotSize = page->bucket->slotSize; |
| 641 size_t rawSize = partitionPageGetRawSize(page); | 684 size_t rawSize = partitionPageGetRawSize(page); |
| 642 if (rawSize) | 685 if (rawSize) |
| 643 slotSize = rawSize; | 686 slotSize = rawSize; |
| 644 partitionCookieCheckValue(ptr); | 687 partitionCookieCheckValue(ptr); |
| 645 partitionCookieCheckValue(reinterpret_cast<char*>(ptr) + slotSize - kCookieS ize); | 688 partitionCookieCheckValue(reinterpret_cast<char*>(ptr) + slotSize - kCookieS ize); |
| 646 memset(ptr, kFreedByte, slotSize); | 689 memset(ptr, kFreedByte, slotSize); |
| 647 #endif | 690 #endif |
| 691 | |
| 692 PartitionAllocHooks::maybeInvokeFreeHook(ptr); | |
|
haraken
2015/10/20 00:14:19
You need to insert the free hook to partitionDirec
Ruud van Asseldonk
2015/10/20 11:43:57
That makes sense. Fixed. What about |partitionReal
| |
| 693 | |
| 648 ASSERT(page->numAllocatedSlots); | 694 ASSERT(page->numAllocatedSlots); |
| 649 PartitionFreelistEntry* freelistHead = page->freelistHead; | 695 PartitionFreelistEntry* freelistHead = page->freelistHead; |
| 650 ASSERT(!freelistHead || partitionPointerIsValid(freelistHead)); | 696 ASSERT(!freelistHead || partitionPointerIsValid(freelistHead)); |
| 651 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ptr != freelistHead); // Catches an immediate double free. | 697 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ptr != freelistHead); // Catches an immediate double free. |
| 652 ASSERT_WITH_SECURITY_IMPLICATION(!freelistHead || ptr != partitionFreelistMa sk(freelistHead->next)); // Look for double free one level deeper in debug. | 698 ASSERT_WITH_SECURITY_IMPLICATION(!freelistHead || ptr != partitionFreelistMa sk(freelistHead->next)); // Look for double free one level deeper in debug. |
| 653 PartitionFreelistEntry* entry = static_cast<PartitionFreelistEntry*>(ptr); | 699 PartitionFreelistEntry* entry = static_cast<PartitionFreelistEntry*>(ptr); |
| 654 entry->next = partitionFreelistMask(freelistHead); | 700 entry->next = partitionFreelistMask(freelistHead); |
| 655 page->freelistHead = entry; | 701 page->freelistHead = entry; |
| 656 --page->numAllocatedSlots; | 702 --page->numAllocatedSlots; |
| 657 if (UNLIKELY(page->numAllocatedSlots <= 0)) { | 703 if (UNLIKELY(page->numAllocatedSlots <= 0)) { |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 814 using WTF::partitionAlloc; | 860 using WTF::partitionAlloc; |
| 815 using WTF::partitionFree; | 861 using WTF::partitionFree; |
| 816 using WTF::partitionAllocGeneric; | 862 using WTF::partitionAllocGeneric; |
| 817 using WTF::partitionFreeGeneric; | 863 using WTF::partitionFreeGeneric; |
| 818 using WTF::partitionReallocGeneric; | 864 using WTF::partitionReallocGeneric; |
| 819 using WTF::partitionAllocActualSize; | 865 using WTF::partitionAllocActualSize; |
| 820 using WTF::partitionAllocSupportsGetSize; | 866 using WTF::partitionAllocSupportsGetSize; |
| 821 using WTF::partitionAllocGetSize; | 867 using WTF::partitionAllocGetSize; |
| 822 | 868 |
| 823 #endif // WTF_PartitionAlloc_h | 869 #endif // WTF_PartitionAlloc_h |
| OLD | NEW |