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

Side by Side Diff: Source/bindings/v8/ScriptWrappable.h

Issue 14623025: Revert "Revert "Replace ScriptWrappable pointer masking with back-pointer check in DOMDataStore."" (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « Source/bindings/v8/DOMDataStore.h ('k') | 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) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 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 24 matching lines...) Expand all
35 #include "bindings/v8/V8Utilities.h" 35 #include "bindings/v8/V8Utilities.h"
36 #include "bindings/v8/WrapperTypeInfo.h" 36 #include "bindings/v8/WrapperTypeInfo.h"
37 #include "core/dom/WebCoreMemoryInstrumentation.h" 37 #include "core/dom/WebCoreMemoryInstrumentation.h"
38 #include <v8.h> 38 #include <v8.h>
39 39
40 namespace WebCore { 40 namespace WebCore {
41 41
42 class ScriptWrappable : public MemoryReporterTag { 42 class ScriptWrappable : public MemoryReporterTag {
43 friend class WeakHandleListener<ScriptWrappable>; 43 friend class WeakHandleListener<ScriptWrappable>;
44 public: 44 public:
45 ScriptWrappable() : m_maskedStorage(0) { } 45 ScriptWrappable() : m_wrapperOrTypeInfo(0) { }
46 46
47 // Wrappables need to be initialized with their most derrived type for which 47 // Wrappables need to be initialized with their most derrived type for which
48 // bindings exist, in much the same way that certain other types need to be 48 // bindings exist, in much the same way that certain other types need to be
49 // adopted and so forth. The overloaded initializeScriptWrappableForInterfac e() 49 // adopted and so forth. The overloaded initializeScriptWrappableForInterfac e()
50 // functions are implemented by the generated V8 bindings code. Declaring th e 50 // functions are implemented by the generated V8 bindings code. Declaring th e
51 // extern function in the template avoids making a centralized header of all 51 // extern function in the template avoids making a centralized header of all
52 // the bindings in the universe. C++11's extern template feature may provide 52 // the bindings in the universe. C++11's extern template feature may provide
53 // a cleaner solution someday. 53 // a cleaner solution someday.
54 template <class C> static void init(C* object) 54 template <class C> static void init(C* object)
55 { 55 {
56 void initializeScriptWrappableForInterface(C*); 56 void initializeScriptWrappableForInterface(C*);
57 initializeScriptWrappableForInterface(object); 57 initializeScriptWrappableForInterface(object);
58 } 58 }
59 59
60 void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration) 60 void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
61 { 61 {
62 ASSERT(!containsWrapper()); 62 ASSERT(!containsWrapper());
63 if (!*wrapper) { 63 if (!*wrapper) {
64 m_maskedStorage = 0; 64 m_wrapperOrTypeInfo = 0;
65 return; 65 return;
66 } 66 }
67 v8::Persistent<v8::Object> persistent(isolate, wrapper); 67 v8::Persistent<v8::Object> persistent(isolate, wrapper);
68 configuration.configureWrapper(persistent, isolate); 68 configuration.configureWrapper(persistent, isolate);
69 WeakHandleListener<ScriptWrappable>::makeWeak(isolate, persistent, this) ; 69 WeakHandleListener<ScriptWrappable>::makeWeak(isolate, persistent, this) ;
70 m_maskedStorage = maskOrUnmaskValue(reinterpret_cast<uintptr_t>(*persist ent)); 70 m_wrapperOrTypeInfo = reinterpret_cast<uintptr_t>(*persistent) | 1;
71 ASSERT(containsWrapper()); 71 ASSERT(containsWrapper());
72 } 72 }
73 73
74 const WrapperTypeInfo* typeInfo() 74 const WrapperTypeInfo* typeInfo()
75 { 75 {
76 if (containsTypeInfo()) 76 if (containsTypeInfo())
77 return reinterpret_cast<const WrapperTypeInfo*>(m_maskedStorage); 77 return reinterpret_cast<const WrapperTypeInfo*>(m_wrapperOrTypeInfo) ;
78 78
79 if (containsWrapper()) { 79 if (containsWrapper()) {
80 v8::Persistent<v8::Object> unsafeWrapper; 80 v8::Persistent<v8::Object> unsafeWrapper;
81 unsafePersistent().copyTo(&unsafeWrapper); 81 unsafePersistent().copyTo(&unsafeWrapper);
82 return toWrapperTypeInfo(unsafeWrapper); 82 return toWrapperTypeInfo(unsafeWrapper);
83 } 83 }
84 84
85 return 0; 85 return 0;
86 } 86 }
87 87
88 void setTypeInfo(const WrapperTypeInfo* info) 88 void setTypeInfo(const WrapperTypeInfo* info)
89 { 89 {
90 m_maskedStorage = reinterpret_cast<uintptr_t>(info); 90 m_wrapperOrTypeInfo = reinterpret_cast<uintptr_t>(info);
91 ASSERT(containsTypeInfo()); 91 ASSERT(containsTypeInfo());
92 } 92 }
93 93
94 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const 94 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
95 { 95 {
96 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); 96 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
97 info.ignoreMember(m_maskedStorage); 97 info.ignoreMember(m_wrapperOrTypeInfo);
98 } 98 }
99 99
100 static bool wrapperCanBeStoredInObject(const void*) { return false; } 100 static bool wrapperCanBeStoredInObject(const void*) { return false; }
101 static bool wrapperCanBeStoredInObject(const ScriptWrappable*) { return true ; } 101 static bool wrapperCanBeStoredInObject(const ScriptWrappable*) { return true ; }
102 102
103 static void setWrapperInObject(void*, v8::Handle<v8::Object>, v8::Isolate*, const WrapperConfiguration&) 103 static void setWrapperInObject(void*, v8::Handle<v8::Object>, v8::Isolate*, const WrapperConfiguration&)
104 { 104 {
105 ASSERT_NOT_REACHED(); 105 ASSERT_NOT_REACHED();
106 } 106 }
107 107
(...skipping 19 matching lines...) Expand all
127 } 127 }
128 128
129 static void setTypeInfoInObject(ScriptWrappable* object, const WrapperTypeIn fo* info) 129 static void setTypeInfoInObject(ScriptWrappable* object, const WrapperTypeIn fo* info)
130 { 130 {
131 object->setTypeInfo(info); 131 object->setTypeInfo(info);
132 } 132 }
133 133
134 protected: 134 protected:
135 ~ScriptWrappable() 135 ~ScriptWrappable()
136 { 136 {
137 ASSERT(m_maskedStorage); // Assert initialization via init() even if no t subsequently wrapped. 137 ASSERT(m_wrapperOrTypeInfo); // Assert initialization via init() even i f not subsequently wrapped.
138 m_maskedStorage = 0; // Break UAF attempts to wrap. 138 m_wrapperOrTypeInfo = 0; // Break UAF attempts to wrap.
139 } 139 }
140 140
141 private: 141 private:
142 // For calling unsafePersistent and getWrapperFromObject. 142 // For calling unsafePersistent and getWrapperFromObject.
143 friend class MinorGCWrapperVisitor; 143 friend class MinorGCWrapperVisitor;
144 friend class DOMDataStore; 144 friend class DOMDataStore;
145 145
146 UnsafePersistent<v8::Object> unsafePersistent() const 146 UnsafePersistent<v8::Object> unsafePersistent() const
147 { 147 {
148 v8::Object* object = containsWrapper() ? reinterpret_cast<v8::Object*>(m askOrUnmaskValue(m_maskedStorage)) : 0; 148 v8::Object* object = containsWrapper() ? reinterpret_cast<v8::Object*>(m _wrapperOrTypeInfo & ~1) : 0;
149 return UnsafePersistent<v8::Object>(object); 149 return UnsafePersistent<v8::Object>(object);
150 } 150 }
151 151
152 static UnsafePersistent<v8::Object> getUnsafeWrapperFromObject(void*) 152 static UnsafePersistent<v8::Object> getUnsafeWrapperFromObject(void*)
153 { 153 {
154 ASSERT_NOT_REACHED(); 154 ASSERT_NOT_REACHED();
155 return UnsafePersistent<v8::Object>(); 155 return UnsafePersistent<v8::Object>();
156 } 156 }
157 157
158 static UnsafePersistent<v8::Object> getUnsafeWrapperFromObject(ScriptWrappab le* object) 158 static UnsafePersistent<v8::Object> getUnsafeWrapperFromObject(ScriptWrappab le* object)
159 { 159 {
160 return object->unsafePersistent(); 160 return object->unsafePersistent();
161 } 161 }
162 162
163 inline bool containsWrapper() const { return (m_maskedStorage & 1) == 1; } 163 inline bool containsWrapper() const { return (m_wrapperOrTypeInfo & 1) == 1; }
164 inline bool containsTypeInfo() const { return m_maskedStorage && ((m_maskedS torage & 1) == 0); } 164 inline bool containsTypeInfo() const { return m_wrapperOrTypeInfo && (m_wrap perOrTypeInfo & 1) == 0; }
165
166 static inline uintptr_t maskOrUnmaskValue(uintptr_t value)
167 {
168 // Entropy via ASLR, bottom bit set to always toggle the bottom bit in t he result. Since masking is only
169 // applied to wrappers, not wrapper type infos, and these are aligned po itners with zeros in the bottom
170 // bit(s), this automatically set the wrapper flag in the bottom bit upo n encoding. Simiarlry,this
171 // automatically zeros out the bit upon decoding. Additionally, since se tWrapper() now performs an explicit
172 // null test, and wrapper() requires the bottom bit to be set, there is no need to preserve null here.
173 const uintptr_t randomMask = ~((reinterpret_cast<uintptr_t>(&WebCoreMemo ryTypes::DOM) >> 13)) | 1;
174 return value ^ randomMask;
175 }
176 165
177 inline void disposeWrapper(v8::Persistent<v8::Value> value, v8::Isolate* iso late, const WrapperTypeInfo* info) 166 inline void disposeWrapper(v8::Persistent<v8::Value> value, v8::Isolate* iso late, const WrapperTypeInfo* info)
178 { 167 {
179 ASSERT(containsWrapper()); 168 ASSERT(containsWrapper());
180 ASSERT(reinterpret_cast<uintptr_t>(*value) == maskOrUnmaskValue(m_masked Storage)); 169 ASSERT(reinterpret_cast<uintptr_t>(*value) == (m_wrapperOrTypeInfo & ~1) );
181 value.Dispose(isolate); 170 value.Dispose(isolate);
182 setTypeInfo(info); 171 setTypeInfo(info);
183 } 172 }
184 173
185 // If zero, then this contains nothing, otherwise: 174 // If zero, then this contains nothing, otherwise:
186 // If the bottom bit it set, then this contains a masked pointer to a wrap per object in the remainging bits. 175 // If the bottom bit it set, then this contains a pointer to a wrapper obj ect in the remainging bits.
187 // If the bottom bit is clear, then this contains a pointer to the wrapper type info in the remaining bits. 176 // If the bottom bit is clear, then this contains a pointer to the wrapper type info in the remaining bits.
188 // Masking wrappers prevents attackers from overwriting this field with poin ters to sprayed data. 177 uintptr_t m_wrapperOrTypeInfo;
189 // Pointers to (and inside) WrapperTypeInfo are already protected by ASLR.
190 uintptr_t m_maskedStorage;
191 }; 178 };
192 179
193 template<> 180 template<>
194 inline void WeakHandleListener<ScriptWrappable>::callback(v8::Isolate* isolate, v8::Persistent<v8::Value> value, ScriptWrappable* key) 181 inline void WeakHandleListener<ScriptWrappable>::callback(v8::Isolate* isolate, v8::Persistent<v8::Value> value, ScriptWrappable* key)
195 { 182 {
196 ASSERT(value->IsObject()); 183 ASSERT(value->IsObject());
197 v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value) ; 184 v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value) ;
198 ASSERT(key->unsafePersistent().handle() == wrapper); 185 ASSERT(key->unsafePersistent().handle() == wrapper);
199 186
200 // Note: |object| might not be equal to |key|, e.g., if ScriptWrappable isn' t a left-most base class. 187 // Note: |object| might not be equal to |key|, e.g., if ScriptWrappable isn' t a left-most base class.
201 void* object = toNative(wrapper); 188 void* object = toNative(wrapper);
202 WrapperTypeInfo* info = toWrapperTypeInfo(wrapper); 189 WrapperTypeInfo* info = toWrapperTypeInfo(wrapper);
203 ASSERT(info->derefObjectFunction); 190 ASSERT(info->derefObjectFunction);
204 191
205 key->disposeWrapper(value, isolate, info); 192 key->disposeWrapper(value, isolate, info);
206 // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed 193 // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed
207 // inside key->deref(), which causes Node destructions. We should 194 // inside key->deref(), which causes Node destructions. We should
208 // make Node destructions incremental. 195 // make Node destructions incremental.
209 info->derefObject(object); 196 info->derefObject(object);
210 } 197 }
211 198
212 } // namespace WebCore 199 } // namespace WebCore
213 200
214 #endif // ScriptWrappable_h 201 #endif // ScriptWrappable_h
OLDNEW
« no previous file with comments | « Source/bindings/v8/DOMDataStore.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698