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

Side by Side Diff: third_party/WebKit/Source/platform/heap/HeapPage.h

Issue 2683823004: Protect heap metadata in Oilpan. (Closed)
Patch Set: Unconditionally assert 8-byte HOH size. Created 3 years, 10 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 | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 13 matching lines...) Expand all
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #ifndef HeapPage_h 31 #ifndef HeapPage_h
32 #define HeapPage_h 32 #define HeapPage_h
33 33
34 #include <stdint.h>
34 #include "base/trace_event/memory_allocator_dump.h" 35 #include "base/trace_event/memory_allocator_dump.h"
35 #include "platform/PlatformExport.h" 36 #include "platform/PlatformExport.h"
36 #include "platform/heap/BlinkGC.h" 37 #include "platform/heap/BlinkGC.h"
37 #include "platform/heap/GCInfo.h" 38 #include "platform/heap/GCInfo.h"
38 #include "platform/heap/ThreadState.h" 39 #include "platform/heap/ThreadState.h"
39 #include "platform/heap/Visitor.h" 40 #include "platform/heap/Visitor.h"
40 #include "wtf/AddressSanitizer.h" 41 #include "wtf/AddressSanitizer.h"
41 #include "wtf/Allocator.h" 42 #include "wtf/Allocator.h"
42 #include "wtf/Assertions.h" 43 #include "wtf/Assertions.h"
43 #include "wtf/ContainerAnnotations.h" 44 #include "wtf/ContainerAnnotations.h"
44 #include "wtf/Forward.h" 45 #include "wtf/Forward.h"
45 #include "wtf/allocator/Partitions.h" 46 #include "wtf/allocator/Partitions.h"
46 #include <stdint.h>
47 47
48 namespace blink { 48 namespace blink {
49 49
50 const size_t blinkPageSizeLog2 = 17; 50 const size_t blinkPageSizeLog2 = 17;
51 const size_t blinkPageSize = 1 << blinkPageSizeLog2; 51 const size_t blinkPageSize = 1 << blinkPageSizeLog2;
52 const size_t blinkPageOffsetMask = blinkPageSize - 1; 52 const size_t blinkPageOffsetMask = blinkPageSize - 1;
53 const size_t blinkPageBaseMask = ~blinkPageOffsetMask; 53 const size_t blinkPageBaseMask = ~blinkPageOffsetMask;
54 54
55 // We allocate pages at random addresses but in groups of 55 // We allocate pages at random addresses but in groups of
56 // blinkPagesPerRegion at a given random address. We group pages to 56 // blinkPagesPerRegion at a given random address. We group pages to
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 #else 117 #else
118 #define SET_MEMORY_INACCESSIBLE(address, size) memset((address), 0, (size)) 118 #define SET_MEMORY_INACCESSIBLE(address, size) memset((address), 0, (size))
119 #define SET_MEMORY_ACCESSIBLE(address, size) \ 119 #define SET_MEMORY_ACCESSIBLE(address, size) \
120 do { \ 120 do { \
121 } while (false) 121 } while (false)
122 #define CHECK_MEMORY_INACCESSIBLE(address, size) \ 122 #define CHECK_MEMORY_INACCESSIBLE(address, size) \
123 do { \ 123 do { \
124 } while (false) 124 } while (false)
125 #endif 125 #endif
126 126
127 #if !DCHECK_IS_ON() && CPU(64BIT)
128 #define USE_4BYTE_HEADER_PADDING 1
129 #else
130 #define USE_4BYTE_HEADER_PADDING 0
131 #endif
132
133 class NormalPageArena; 127 class NormalPageArena;
134 class PageMemory; 128 class PageMemory;
135 129
136 // HeapObjectHeader is 4 byte (32 bit) that has the following layout: 130 // HeapObjectHeader is 4 byte (32 bit) that has the following layout:
137 // 131 //
138 // | gcInfoIndex (14 bit) | 132 // | gcInfoIndex (14 bit) |
139 // | DOM mark bit (1 bit) | 133 // | DOM mark bit (1 bit) |
140 // | size (14 bit) | 134 // | size (14 bit) |
141 // | dead bit (1 bit) | 135 // | dead bit (1 bit) |
142 // | freed bit (1 bit) | 136 // | freed bit (1 bit) |
(...skipping 29 matching lines...) Expand all
172 nonLargeObjectPageSizeMax >= blinkPageSize, 166 nonLargeObjectPageSizeMax >= blinkPageSize,
173 "max size supported by HeapObjectHeader must at least be blinkPageSize"); 167 "max size supported by HeapObjectHeader must at least be blinkPageSize");
174 168
175 class PLATFORM_EXPORT HeapObjectHeader { 169 class PLATFORM_EXPORT HeapObjectHeader {
176 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); 170 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
177 171
178 public: 172 public:
179 // If gcInfoIndex is 0, this header is interpreted as a free list header. 173 // If gcInfoIndex is 0, this header is interpreted as a free list header.
180 NO_SANITIZE_ADDRESS 174 NO_SANITIZE_ADDRESS
181 HeapObjectHeader(size_t size, size_t gcInfoIndex) { 175 HeapObjectHeader(size_t size, size_t gcInfoIndex) {
182 #if DCHECK_IS_ON() 176 m_magic = getMagic();
183 m_magic = magic;
184 #endif
185 // sizeof(HeapObjectHeader) must be equal to or smaller than 177 // sizeof(HeapObjectHeader) must be equal to or smaller than
186 // allocationGranurarity, because HeapObjectHeader is used as a header 178 // allocationGranurarity, because HeapObjectHeader is used as a header
187 // for an freed entry. Given that the smallest entry size is 179 // for an freed entry. Given that the smallest entry size is
188 // allocationGranurarity, HeapObjectHeader must fit into the size. 180 // allocationGranurarity, HeapObjectHeader must fit into the size.
189 static_assert( 181 static_assert(
190 sizeof(HeapObjectHeader) <= allocationGranularity, 182 sizeof(HeapObjectHeader) <= allocationGranularity,
191 "size of HeapObjectHeader must be smaller than allocationGranularity"); 183 "size of HeapObjectHeader must be smaller than allocationGranularity");
192 #if CPU(64BIT)
193 static_assert(sizeof(HeapObjectHeader) == 8, 184 static_assert(sizeof(HeapObjectHeader) == 8,
194 "size of HeapObjectHeader must be 8 byte aligned"); 185 "sizeof(HeapObjectHeader) must be 8 bytes");
195 #endif
196 186
197 ASSERT(gcInfoIndex < GCInfoTable::maxIndex); 187 ASSERT(gcInfoIndex < GCInfoTable::maxIndex);
198 ASSERT(size < nonLargeObjectPageSizeMax); 188 ASSERT(size < nonLargeObjectPageSizeMax);
199 ASSERT(!(size & allocationMask)); 189 ASSERT(!(size & allocationMask));
200 m_encoded = static_cast<uint32_t>( 190 m_encoded = static_cast<uint32_t>(
201 (gcInfoIndex << headerGCInfoIndexShift) | size | 191 (gcInfoIndex << headerGCInfoIndexShift) | size |
202 (gcInfoIndex == gcInfoIndexForFreeListHeader ? headerFreedBitMask : 0)); 192 (gcInfoIndex == gcInfoIndexForFreeListHeader ? headerFreedBitMask : 0));
203 } 193 }
204 194
205 NO_SANITIZE_ADDRESS 195 NO_SANITIZE_ADDRESS
(...skipping 20 matching lines...) Expand all
226 void markWrapperHeader(); 216 void markWrapperHeader();
227 void unmarkWrapperHeader(); 217 void unmarkWrapperHeader();
228 bool isMarked() const; 218 bool isMarked() const;
229 void mark(); 219 void mark();
230 void unmark(); 220 void unmark();
231 221
232 Address payload(); 222 Address payload();
233 size_t payloadSize(); 223 size_t payloadSize();
234 Address payloadEnd(); 224 Address payloadEnd();
235 225
236 #if DCHECK_IS_ON() 226 // TODO(633030): Make |checkHeader| and |zapMagic| private. This class should
227 // manage its integrity on its own, without requiring outside callers to
228 // explicitly check.
237 bool checkHeader() const; 229 bool checkHeader() const;
238 // Zap magic number with a new magic number that means there was once an 230 // Zap magic number with a new magic number that means there was once an
239 // object allocated here, but it was freed because nobody marked it during 231 // object allocated here, but it was freed because nobody marked it during
240 // GC. 232 // GC.
241 void zapMagic(); 233 void zapMagic();
242 #endif
243 234
244 void finalize(Address, size_t); 235 void finalize(Address, size_t);
245 static HeapObjectHeader* fromPayload(const void*); 236 static HeapObjectHeader* fromPayload(const void*);
246 237
247 static const uint16_t magic = 0xfff1; 238 static const uint32_t zappedMagic = 0xDEAD4321;
248 static const uint16_t zappedMagic = 0x4321;
249 239
250 private: 240 private:
241 // Returns a random value.
242 //
243 // The implementation gets its randomness from the locations of 2 independent
244 // sources of address space layout randomization: a function in a Chrome
245 // executable image, and a function in an external DLL/so. This implementation
246 // should be fast and small, and should have the benefit of requiring
247 // attackers to discover and use 2 independent weak infoleak bugs, or 1
248 // arbitrary infoleak bug (used twice).
249 uint32_t getMagic() const;
250
251 uint32_t m_magic;
251 uint32_t m_encoded; 252 uint32_t m_encoded;
252 #if DCHECK_IS_ON()
253 uint16_t m_magic;
254 #endif
255
256 // In 64 bit architectures, we intentionally add 4 byte padding immediately
257 // after the HeapObjectHeader. This is because:
258 //
259 // | HeapObjectHeader (4 byte) | <- 8 byte aligned
260 // | padding (4 byte) |
261 // | object payload (8 * n byte) | <- 8 byte aligned
262 //
263 // is better than:
264 //
265 // | HeapObjectHeader (4 byte) | <- 4 byte aligned
266 // | object payload (8 * n byte) | <- 8 byte aligned
267 // | padding (4 byte) | <- 4 byte aligned
268 //
269 // since the former layout aligns both header and payload to 8 byte.
270 #if USE_4BYTE_HEADER_PADDING
271 public:
272 uint32_t m_padding;
273 #endif
274 }; 253 };
275 254
276 class FreeListEntry final : public HeapObjectHeader { 255 class FreeListEntry final : public HeapObjectHeader {
277 public: 256 public:
278 NO_SANITIZE_ADDRESS 257 NO_SANITIZE_ADDRESS
279 explicit FreeListEntry(size_t size) 258 explicit FreeListEntry(size_t size)
280 : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) { 259 : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) {
281 #if DCHECK_IS_ON() 260 #if DCHECK_IS_ON()
282 ASSERT(size >= sizeof(HeapObjectHeader)); 261 ASSERT(size >= sizeof(HeapObjectHeader));
283 zapMagic(); 262 zapMagic();
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const { 828 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const {
850 size_t result = m_encoded & headerSizeMask; 829 size_t result = m_encoded & headerSizeMask;
851 // Large objects should not refer to header->size(). 830 // Large objects should not refer to header->size().
852 // The actual size of a large object is stored in 831 // The actual size of a large object is stored in
853 // LargeObjectPage::m_payloadSize. 832 // LargeObjectPage::m_payloadSize.
854 ASSERT(result != largeObjectSizeInHeader); 833 ASSERT(result != largeObjectSizeInHeader);
855 ASSERT(!pageFromObject(this)->isLargeObjectPage()); 834 ASSERT(!pageFromObject(this)->isLargeObjectPage());
856 return result; 835 return result;
857 } 836 }
858 837
859 #if DCHECK_IS_ON()
860 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::checkHeader() const { 838 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::checkHeader() const {
861 return m_magic == magic; 839 return m_magic == getMagic();
862 } 840 }
863 #endif
864 841
865 inline Address HeapObjectHeader::payload() { 842 inline Address HeapObjectHeader::payload() {
866 return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); 843 return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader);
867 } 844 }
868 845
869 inline Address HeapObjectHeader::payloadEnd() { 846 inline Address HeapObjectHeader::payloadEnd() {
870 return reinterpret_cast<Address>(this) + size(); 847 return reinterpret_cast<Address>(this) + size();
871 } 848 }
872 849
873 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() { 850 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() {
874 size_t size = m_encoded & headerSizeMask; 851 size_t size = m_encoded & headerSizeMask;
875 if (UNLIKELY(size == largeObjectSizeInHeader)) { 852 if (UNLIKELY(size == largeObjectSizeInHeader)) {
876 ASSERT(pageFromObject(this)->isLargeObjectPage()); 853 ASSERT(pageFromObject(this)->isLargeObjectPage());
877 return static_cast<LargeObjectPage*>(pageFromObject(this))->payloadSize(); 854 return static_cast<LargeObjectPage*>(pageFromObject(this))->payloadSize();
878 } 855 }
879 ASSERT(!pageFromObject(this)->isLargeObjectPage()); 856 ASSERT(!pageFromObject(this)->isLargeObjectPage());
880 return size - sizeof(HeapObjectHeader); 857 return size - sizeof(HeapObjectHeader);
881 } 858 }
882 859
883 inline HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) { 860 inline HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) {
884 Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); 861 Address addr = reinterpret_cast<Address>(const_cast<void*>(payload));
885 HeapObjectHeader* header = 862 HeapObjectHeader* header =
886 reinterpret_cast<HeapObjectHeader*>(addr - sizeof(HeapObjectHeader)); 863 reinterpret_cast<HeapObjectHeader*>(addr - sizeof(HeapObjectHeader));
887 ASSERT(header->checkHeader()); 864 ASSERT(header->checkHeader());
888 return header; 865 return header;
889 } 866 }
890 867
868 inline uint32_t HeapObjectHeader::getMagic() const {
869 const uintptr_t random1 =
870 ~(reinterpret_cast<uintptr_t>(
871 base::trace_event::MemoryAllocatorDump::kNameSize) >>
872 16);
873
874 #if OS(WIN)
875 const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::ReadFile) << 16);
876 #elif OS(POSIX)
877 const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::read) << 16);
878 #else
879 #error OS not supported
880 #endif
881
882 #if CPU(64BIT)
883 static_assert(sizeof(uintptr_t) == sizeof(uint64_t),
884 "uintptr_t is not uint64_t");
885 const uint32_t random = static_cast<uint32_t>(
886 (random1 & 0x0FFFFULL) | ((random2 >> 32) & 0x0FFFF0000ULL));
887 #elif CPU(32BIT)
888 static_assert(sizeof(uintptr_t) == sizeof(uint32_t),
889 "uintptr_t is not uint32_t");
890 const uint32_t random = (random1 & 0x0FFFFUL) | (random2 & 0xFFFF0000UL);
891 #else
892 #error architecture not supported
893 #endif
894
895 return random;
896 }
897
891 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::isWrapperHeaderMarked() 898 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::isWrapperHeaderMarked()
892 const { 899 const {
893 ASSERT(checkHeader()); 900 ASSERT(checkHeader());
894 return m_encoded & headerWrapperMarkBitMask; 901 return m_encoded & headerWrapperMarkBitMask;
895 } 902 }
896 903
897 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::markWrapperHeader() { 904 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::markWrapperHeader() {
898 ASSERT(checkHeader()); 905 ASSERT(checkHeader());
899 ASSERT(!isWrapperHeaderMarked()); 906 ASSERT(!isWrapperHeaderMarked());
900 m_encoded |= headerWrapperMarkBitMask; 907 m_encoded |= headerWrapperMarkBitMask;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
941 return outOfLineAllocate(allocationSize, gcInfoIndex); 948 return outOfLineAllocate(allocationSize, gcInfoIndex);
942 } 949 }
943 950
944 inline NormalPageArena* NormalPage::arenaForNormalPage() const { 951 inline NormalPageArena* NormalPage::arenaForNormalPage() const {
945 return static_cast<NormalPageArena*>(arena()); 952 return static_cast<NormalPageArena*>(arena());
946 } 953 }
947 954
948 } // namespace blink 955 } // namespace blink
949 956
950 #endif // HeapPage_h 957 #endif // HeapPage_h
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698