Index: third_party/WebKit/Source/platform/heap/HeapPage.h |
diff --git a/third_party/WebKit/Source/platform/heap/HeapPage.h b/third_party/WebKit/Source/platform/heap/HeapPage.h |
index 65ef346b238fcd31c712558828713a9334b340cb..ed6582cb0b2c2e19968b467aa4967ca9f3e14692 100644 |
--- a/third_party/WebKit/Source/platform/heap/HeapPage.h |
+++ b/third_party/WebKit/Source/platform/heap/HeapPage.h |
@@ -31,6 +31,7 @@ |
#ifndef HeapPage_h |
#define HeapPage_h |
+#include <stdint.h> |
#include "base/trace_event/memory_allocator_dump.h" |
#include "platform/PlatformExport.h" |
#include "platform/heap/BlinkGC.h" |
@@ -43,7 +44,6 @@ |
#include "wtf/ContainerAnnotations.h" |
#include "wtf/Forward.h" |
#include "wtf/allocator/Partitions.h" |
-#include <stdint.h> |
namespace blink { |
@@ -124,12 +124,6 @@ const uint8_t reuseForbiddenZapValue = 0x2c; |
} while (false) |
#endif |
-#if !DCHECK_IS_ON() && CPU(64BIT) |
-#define USE_4BYTE_HEADER_PADDING 1 |
-#else |
-#define USE_4BYTE_HEADER_PADDING 0 |
-#endif |
- |
class NormalPageArena; |
class PageMemory; |
@@ -179,9 +173,7 @@ class PLATFORM_EXPORT HeapObjectHeader { |
// If gcInfoIndex is 0, this header is interpreted as a free list header. |
NO_SANITIZE_ADDRESS |
HeapObjectHeader(size_t size, size_t gcInfoIndex) { |
-#if DCHECK_IS_ON() |
- m_magic = magic; |
-#endif |
+ m_magic = getMagic(); |
// sizeof(HeapObjectHeader) must be equal to or smaller than |
// allocationGranurarity, because HeapObjectHeader is used as a header |
// for an freed entry. Given that the smallest entry size is |
@@ -189,10 +181,8 @@ class PLATFORM_EXPORT HeapObjectHeader { |
static_assert( |
sizeof(HeapObjectHeader) <= allocationGranularity, |
"size of HeapObjectHeader must be smaller than allocationGranularity"); |
-#if CPU(64BIT) |
static_assert(sizeof(HeapObjectHeader) == 8, |
- "size of HeapObjectHeader must be 8 byte aligned"); |
-#endif |
+ "sizeof(HeapObjectHeader) must be 8 bytes"); |
ASSERT(gcInfoIndex < GCInfoTable::maxIndex); |
ASSERT(size < nonLargeObjectPageSizeMax); |
@@ -233,44 +223,33 @@ class PLATFORM_EXPORT HeapObjectHeader { |
size_t payloadSize(); |
Address payloadEnd(); |
-#if DCHECK_IS_ON() |
+ // TODO(633030): Make |checkHeader| and |zapMagic| private. This class should |
+ // manage its integrity on its own, without requiring outside callers to |
+ // explicitly check. |
bool checkHeader() const; |
// Zap magic number with a new magic number that means there was once an |
// object allocated here, but it was freed because nobody marked it during |
// GC. |
void zapMagic(); |
-#endif |
void finalize(Address, size_t); |
static HeapObjectHeader* fromPayload(const void*); |
- static const uint16_t magic = 0xfff1; |
- static const uint16_t zappedMagic = 0x4321; |
+ static const uint32_t zappedMagic = 0xDEAD4321; |
private: |
+ // Returns a random value. |
+ // |
+ // The implementation gets its randomness from the locations of 2 independent |
+ // sources of address space layout randomization: a function in a Chrome |
+ // executable image, and a function in an external DLL/so. This implementation |
+ // should be fast and small, and should have the benefit of requiring |
+ // attackers to discover and use 2 independent weak infoleak bugs, or 1 |
+ // arbitrary infoleak bug (used twice). |
+ uint32_t getMagic() const; |
+ |
+ uint32_t m_magic; |
uint32_t m_encoded; |
-#if DCHECK_IS_ON() |
- uint16_t m_magic; |
-#endif |
- |
-// In 64 bit architectures, we intentionally add 4 byte padding immediately |
-// after the HeapObjectHeader. This is because: |
-// |
-// | HeapObjectHeader (4 byte) | <- 8 byte aligned |
-// | padding (4 byte) | |
-// | object payload (8 * n byte) | <- 8 byte aligned |
-// |
-// is better than: |
-// |
-// | HeapObjectHeader (4 byte) | <- 4 byte aligned |
-// | object payload (8 * n byte) | <- 8 byte aligned |
-// | padding (4 byte) | <- 4 byte aligned |
-// |
-// since the former layout aligns both header and payload to 8 byte. |
-#if USE_4BYTE_HEADER_PADDING |
- public: |
- uint32_t m_padding; |
-#endif |
}; |
class FreeListEntry final : public HeapObjectHeader { |
@@ -856,11 +835,9 @@ NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const { |
return result; |
} |
-#if DCHECK_IS_ON() |
NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::checkHeader() const { |
- return m_magic == magic; |
+ return m_magic == getMagic(); |
} |
-#endif |
inline Address HeapObjectHeader::payload() { |
return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); |
@@ -888,6 +865,36 @@ inline HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) { |
return header; |
} |
+inline uint32_t HeapObjectHeader::getMagic() const { |
+ const uintptr_t random1 = |
+ ~(reinterpret_cast<uintptr_t>( |
+ base::trace_event::MemoryAllocatorDump::kNameSize) >> |
+ 16); |
+ |
+#if OS(WIN) |
+ const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::ReadFile) << 16); |
+#elif OS(POSIX) |
+ const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::read) << 16); |
+#else |
+#error OS not supported |
+#endif |
+ |
+#if CPU(64BIT) |
+ static_assert(sizeof(uintptr_t) == sizeof(uint64_t), |
+ "uintptr_t is not uint64_t"); |
+ const uint32_t random = static_cast<uint32_t>( |
+ (random1 & 0x0FFFFULL) | ((random2 >> 32) & 0x0FFFF0000ULL)); |
+#elif CPU(32BIT) |
+ static_assert(sizeof(uintptr_t) == sizeof(uint32_t), |
+ "uintptr_t is not uint32_t"); |
+ const uint32_t random = (random1 & 0x0FFFFUL) | (random2 & 0xFFFF0000UL); |
+#else |
+#error architecture not supported |
+#endif |
+ |
+ return random; |
+} |
+ |
NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::isWrapperHeaderMarked() |
const { |
ASSERT(checkHeader()); |