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

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

Issue 2683823004: Protect heap metadata in Oilpan. (Closed)
Patch Set: remove unnecessary 4-byte padding. 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) 184 #if CPU(64BIT)
sof 2017/02/11 06:38:10 To the extent that it is still useful, this static
193 static_assert(sizeof(HeapObjectHeader) == 8, 185 static_assert(sizeof(HeapObjectHeader) == 8,
194 "size of HeapObjectHeader must be 8 byte aligned"); 186 "size of HeapObjectHeader must be 8 byte aligned");
195 #endif 187 #endif
196 188
197 ASSERT(gcInfoIndex < GCInfoTable::maxIndex); 189 ASSERT(gcInfoIndex < GCInfoTable::maxIndex);
198 ASSERT(size < nonLargeObjectPageSizeMax); 190 ASSERT(size < nonLargeObjectPageSizeMax);
199 ASSERT(!(size & allocationMask)); 191 ASSERT(!(size & allocationMask));
200 m_encoded = static_cast<uint32_t>( 192 m_encoded = static_cast<uint32_t>(
201 (gcInfoIndex << headerGCInfoIndexShift) | size | 193 (gcInfoIndex << headerGCInfoIndexShift) | size |
202 (gcInfoIndex == gcInfoIndexForFreeListHeader ? headerFreedBitMask : 0)); 194 (gcInfoIndex == gcInfoIndexForFreeListHeader ? headerFreedBitMask : 0));
(...skipping 23 matching lines...) Expand all
226 void markWrapperHeader(); 218 void markWrapperHeader();
227 void unmarkWrapperHeader(); 219 void unmarkWrapperHeader();
228 bool isMarked() const; 220 bool isMarked() const;
229 void mark(); 221 void mark();
230 void unmark(); 222 void unmark();
231 223
232 Address payload(); 224 Address payload();
233 size_t payloadSize(); 225 size_t payloadSize();
234 Address payloadEnd(); 226 Address payloadEnd();
235 227
236 #if DCHECK_IS_ON() 228 // TODO(633030): Make |checkHeader| and |zapMagic| private. This class should
229 // manage its integrity on its own, without requiring outside callers to
230 // explicitly check.
237 bool checkHeader() const; 231 bool checkHeader() const;
238 // Zap magic number with a new magic number that means there was once an 232 // 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 233 // object allocated here, but it was freed because nobody marked it during
240 // GC. 234 // GC.
241 void zapMagic(); 235 void zapMagic();
242 #endif
243 236
244 void finalize(Address, size_t); 237 void finalize(Address, size_t);
245 static HeapObjectHeader* fromPayload(const void*); 238 static HeapObjectHeader* fromPayload(const void*);
246 239
247 static const uint16_t magic = 0xfff1; 240 static const uint32_t zappedMagic = 0xDEAD4321;
248 static const uint16_t zappedMagic = 0x4321;
249 241
250 private: 242 private:
251 uint32_t m_encoded; 243 // Returns a random value.
sof 2017/02/11 06:38:10 Just a syntactic issue -- could you declare getMag
palmer 2017/02/14 22:49:50 Done.
252 #if DCHECK_IS_ON() 244 //
253 uint16_t m_magic; 245 // The implementation gets its randomness from the locations of 2 independent
246 // sources of address space layout randomization: a function in a Chrome
247 // executable image, and a function in an external DLL/so. This implementation
248 // should be fast and small, and should have the benefit of requiring
249 // attackers to discover and use 2 independent weak infoleak bugs, or 1
250 // arbitrary infoleak bug (used twice).
251 uint32_t getMagic() const {
252 const uintptr_t random1 =
253 ~(reinterpret_cast<uintptr_t>(
254 base::trace_event::MemoryAllocatorDump::kNameSize) >>
255 16);
256
257 #if OS(WIN)
258 const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::ReadFile) << 16);
259 #elif OS(POSIX)
260 const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::read) << 16);
261 #else
262 #error OS not supported
254 #endif 263 #endif
255 264
256 // In 64 bit architectures, we intentionally add 4 byte padding immediately 265 #if CPU(64BIT)
257 // after the HeapObjectHeader. This is because: 266 static_assert(sizeof(uintptr_t) == sizeof(uint64_t),
258 // 267 "uintptr_t is not uint64_t");
259 // | HeapObjectHeader (4 byte) | <- 8 byte aligned 268 const uint32_t random = static_cast<uint32_t>(
260 // | padding (4 byte) | 269 (random1 & 0x0FFFFULL) | ((random2 >> 32) & 0x0FFFF0000ULL));
261 // | object payload (8 * n byte) | <- 8 byte aligned 270 #elif CPU(32BIT)
262 // 271 static_assert(sizeof(uintptr_t) == sizeof(uint32_t),
263 // is better than: 272 "uintptr_t is not uint32_t");
264 // 273 const uint32_t random = (random1 & 0x0FFFFUL) | (random2 & 0xFFFF0000UL);
265 // | HeapObjectHeader (4 byte) | <- 4 byte aligned 274 #else
266 // | object payload (8 * n byte) | <- 8 byte aligned 275 #error architecture not supported
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 276 #endif
277
278 return random;
279 }
280
281 uint32_t m_magic;
282 uint32_t m_encoded;
274 }; 283 };
275 284
276 class FreeListEntry final : public HeapObjectHeader { 285 class FreeListEntry final : public HeapObjectHeader {
277 public: 286 public:
278 NO_SANITIZE_ADDRESS 287 NO_SANITIZE_ADDRESS
279 explicit FreeListEntry(size_t size) 288 explicit FreeListEntry(size_t size)
280 : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) { 289 : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) {
281 #if DCHECK_IS_ON() 290 #if DCHECK_IS_ON()
282 ASSERT(size >= sizeof(HeapObjectHeader)); 291 ASSERT(size >= sizeof(HeapObjectHeader));
283 zapMagic(); 292 zapMagic();
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const { 858 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const {
850 size_t result = m_encoded & headerSizeMask; 859 size_t result = m_encoded & headerSizeMask;
851 // Large objects should not refer to header->size(). 860 // Large objects should not refer to header->size().
852 // The actual size of a large object is stored in 861 // The actual size of a large object is stored in
853 // LargeObjectPage::m_payloadSize. 862 // LargeObjectPage::m_payloadSize.
854 ASSERT(result != largeObjectSizeInHeader); 863 ASSERT(result != largeObjectSizeInHeader);
855 ASSERT(!pageFromObject(this)->isLargeObjectPage()); 864 ASSERT(!pageFromObject(this)->isLargeObjectPage());
856 return result; 865 return result;
857 } 866 }
858 867
859 #if DCHECK_IS_ON()
860 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::checkHeader() const { 868 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::checkHeader() const {
861 return m_magic == magic; 869 return m_magic == getMagic();
862 } 870 }
863 #endif
864 871
865 inline Address HeapObjectHeader::payload() { 872 inline Address HeapObjectHeader::payload() {
866 return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); 873 return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader);
867 } 874 }
868 875
869 inline Address HeapObjectHeader::payloadEnd() { 876 inline Address HeapObjectHeader::payloadEnd() {
870 return reinterpret_cast<Address>(this) + size(); 877 return reinterpret_cast<Address>(this) + size();
871 } 878 }
872 879
873 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() { 880 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() {
(...skipping 67 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