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

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

Issue 13828008: Second part of moving V8 Binding Integrity off of vtables. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Invert meaning of flag to avoid branches in hot path. Created 7 years, 8 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') | Source/bindings/v8/WorkerScriptController.cpp » ('j') | 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 23 matching lines...) Expand all
34 #include "V8Utilities.h" 34 #include "V8Utilities.h"
35 #include "WebCoreMemoryInstrumentation.h" 35 #include "WebCoreMemoryInstrumentation.h"
36 #include "WrapperTypeInfo.h" 36 #include "WrapperTypeInfo.h"
37 #include <v8.h> 37 #include <v8.h>
38 38
39 namespace WebCore { 39 namespace WebCore {
40 40
41 class ScriptWrappable { 41 class ScriptWrappable {
42 friend class WeakHandleListener<ScriptWrappable>; 42 friend class WeakHandleListener<ScriptWrappable>;
43 public: 43 public:
44 ScriptWrappable() 44 ScriptWrappable() : m_maskedStorage(0) { }
45
46 // Wrappables need to be initialized with their most derrived type for which
47 // bindings exist, in much the same way that certain other types need to be
48 // adopted and so forth. The overloaded initializeScriptWrappableForInterfac e()
49 // functions are implemented by the generated V8 bindings code. Declaring th e
50 // extern function in the template avoids making a centralized header of all
51 // the bindings in the universe.
52 template <class C> static void init(C* object)
45 { 53 {
46 #ifndef NDEBUG 54 extern void initializeScriptWrappableForInterface(C*); // Workaround for lack of extern template prior to C++11.
47 m_init = false; 55 initializeScriptWrappableForInterface(object);
48 #endif
49 }
50
51 template <class C> static void init(C *object)
52 {
53 #ifndef NDEBUG
54 object->m_init = true;
55 #endif
56 } 56 }
57 57
58 v8::Handle<v8::Object> wrapper() const 58 v8::Handle<v8::Object> wrapper() const
59 { 59 {
60 return v8::Handle<v8::Object>(maskOrUnmaskPointer(*m_maskedWrapper)); 60 v8::Object* object = containsWrapper() ? reinterpret_cast<v8::Object*>(m askOrUnmaskValue(m_maskedStorage)) : 0;
61 return v8::Handle<v8::Object>(object);
61 } 62 }
62 63
63 void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration) 64 void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
64 { 65 {
65 ASSERT(m_maskedWrapper.IsEmpty()); 66 ASSERT(!containsWrapper());
67 if (!*wrapper) {
68 m_maskedStorage = 0;
69 return;
abarth-chromium 2013/04/12 21:08:14 four-space indent pls
70 }
66 v8::Persistent<v8::Object> persistent = v8::Persistent<v8::Object>::New( isolate, wrapper); 71 v8::Persistent<v8::Object> persistent = v8::Persistent<v8::Object>::New( isolate, wrapper);
67 configuration.configureWrapper(persistent, isolate); 72 configuration.configureWrapper(persistent, isolate);
68 WeakHandleListener<ScriptWrappable>::makeWeak(isolate, persistent, this) ; 73 WeakHandleListener<ScriptWrappable>::makeWeak(isolate, persistent, this) ;
69 m_maskedWrapper = maskOrUnmaskPointer(*persistent); 74 m_maskedStorage = maskOrUnmaskValue(reinterpret_cast<uintptr_t>(*persist ent));
75 ASSERT(containsWrapper());
76 }
77
78 const WrapperTypeInfo* typeInfo()
79 {
80 if (containsTypeInfo())
81 return reinterpret_cast<const WrapperTypeInfo*>(m_maskedStorage);
82
83 if (containsWrapper())
84 return toWrapperTypeInfo(wrapper());
85
86 return 0;
87 }
88
89 void setTypeInfo(const WrapperTypeInfo* info)
90 {
91 m_maskedStorage = reinterpret_cast<uintptr_t>(info);
92 ASSERT(containsTypeInfo());
70 } 93 }
71 94
72 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const 95 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
73 { 96 {
74 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); 97 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
75 info.ignoreMember(m_maskedWrapper); 98 info.ignoreMember(m_maskedStorage);
99 }
100
101 static bool wrapperCanBeStoredInObject(const void*) { return false; }
102 static bool wrapperCanBeStoredInObject(const ScriptWrappable*) { return true ; }
103
104 static v8::Handle<v8::Object> getWrapperFromObject(void*)
105 {
106 ASSERT_NOT_REACHED();
107 return v8::Handle<v8::Object>();
108 }
109
110 static v8::Handle<v8::Object> getWrapperFromObject(ScriptWrappable* object)
111 {
112 return object->wrapper();
113 }
114
115 static void setWrapperInObject(void*, v8::Handle<v8::Object>, v8::Isolate*, const WrapperConfiguration&)
116 {
117 ASSERT_NOT_REACHED();
118 }
119
120 static void setWrapperInObject(ScriptWrappable* object, v8::Handle<v8::Objec t> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
121 {
122 object->setWrapper(wrapper, isolate, configuration);
123 }
124
125 static const WrapperTypeInfo* getTypeInfoFromObject(void* object)
126 {
127 ASSERT_NOT_REACHED();
128 return 0;
129 }
130
131 static const WrapperTypeInfo* getTypeInfoFromObject(ScriptWrappable* object)
132 {
133 return object->typeInfo();
134 }
135
136 static void setTypeInfoInObject(void* object, const WrapperTypeInfo* info)
137 {
138 ASSERT_NOT_REACHED();
139 }
140
141 static void setTypeInfoInObject(ScriptWrappable* object, const WrapperTypeIn fo* info)
142 {
143 object->setTypeInfo(info);
76 } 144 }
77 145
78 protected: 146 protected:
79 ~ScriptWrappable() 147 ~ScriptWrappable()
80 { 148 {
81 #ifndef NDEBUG 149 ASSERT(m_maskedStorage); // Assert initialization via init() even if no t subsequently wrapped.
82 ASSERT(m_init); 150 m_maskedStorage = 0; // Break UAF attempts to wrap.
83 #endif
84 } 151 }
85 152
86 private: 153 private:
87 inline void disposeWrapper(v8::Persistent<v8::Value> value, v8::Isolate* iso late) 154 inline bool containsWrapper() const { return (m_maskedStorage & 1) == 1; }
155 inline bool containsTypeInfo() const { return m_maskedStorage && ((m_maskedS torage & 1) == 0); }
156
157 static inline uintptr_t maskOrUnmaskValue(uintptr_t value)
88 { 158 {
89 ASSERT(!m_maskedWrapper.IsEmpty()); 159 // Entropy via ASLR, bottom bit set to always toggle the bottom bit in t he result. Since masking is only
90 ASSERT(*value == maskOrUnmaskPointer(*m_maskedWrapper)); 160 // applied to wrappers, not wrapper type infos, and these are aligned po itners with zeros in the bottom
91 value.Dispose(isolate); 161 // bit(s), this automatically set the wrapper flag in the bottom bit upo n encoding. Simiarlry,this
92 m_maskedWrapper.Clear(); 162 // automatically zeros out the bit upon decoding. Additionally, since se tWrapper() now performs an explicit
163 // null test, and wrapper() requires the bottom bit to be set, there is no need to preserve null here.
164 const uintptr_t randomMask = ~((reinterpret_cast<uintptr_t>(&WebCoreMemo ryTypes::DOM) >> 13)) | 1;
165 return value ^ randomMask;
93 } 166 }
94 167
95 static inline v8::Object* maskOrUnmaskPointer(const v8::Object* object) 168 inline void disposeWrapper(v8::Persistent<v8::Value> value, v8::Isolate* iso late, const WrapperTypeInfo* info)
96 { 169 {
97 const uintptr_t objectPointer = reinterpret_cast<uintptr_t>(object); 170 ASSERT(containsWrapper());
98 const uintptr_t randomMask = ~(reinterpret_cast<uintptr_t>(&WebCoreMemor yTypes::DOM) >> 13); // Entropy via ASLR. 171 ASSERT(reinterpret_cast<uintptr_t>(*value) == maskOrUnmaskValue(m_masked Storage));
99 return reinterpret_cast<v8::Object*>((objectPointer ^ randomMask) & (!ob jectPointer - 1)); // Preserve null without branching. 172 value.Dispose(isolate);
173 setTypeInfo(info);
100 } 174 }
101 175
102 // Stores a masked wrapper to prevent attackers from overwriting this field 176 // If zero, then this contains nothing, otherwise:
103 // with a phony wrapper. 177 // If the bottom bit it set, then this contains a masked pointer to a wrap per object in the remainging bits.
104 v8::Persistent<v8::Object> m_maskedWrapper; 178 // If the bottom bit is clear, then this contains a pointer to the wrapper type info in the remaining bits.
105 179 // Masking wrappers prevents attackers from overwriting this field with poin ters to sprayed data.
106 #ifndef NDEBUG 180 // Pointers to (and inside) WrapperTypeInfo are already protected by ASLR.
107 bool m_init; 181 uintptr_t m_maskedStorage;
108 #endif
109
110 }; 182 };
111 183
112 template<> 184 template<>
113 inline void WeakHandleListener<ScriptWrappable>::callback(v8::Isolate* isolate, v8::Persistent<v8::Value> value, ScriptWrappable* key) 185 inline void WeakHandleListener<ScriptWrappable>::callback(v8::Isolate* isolate, v8::Persistent<v8::Value> value, ScriptWrappable* key)
114 { 186 {
115 ASSERT(value->IsObject()); 187 ASSERT(value->IsObject());
116 v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value) ; 188 v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value) ;
117 ASSERT(key->wrapper() == wrapper); 189 ASSERT(key->wrapper() == wrapper);
118 190
119 // Note: |object| might not be equal to |key|, e.g., if ScriptWrappable isn' t a left-most base class. 191 // Note: |object| might not be equal to |key|, e.g., if ScriptWrappable isn' t a left-most base class.
120 void* object = toNative(wrapper); 192 void* object = toNative(wrapper);
121 WrapperTypeInfo* info = toWrapperTypeInfo(wrapper); 193 WrapperTypeInfo* info = toWrapperTypeInfo(wrapper);
122 ASSERT(info->derefObjectFunction); 194 ASSERT(info->derefObjectFunction);
123 195
124 key->disposeWrapper(value, isolate); 196 key->disposeWrapper(value, isolate, info);
125 // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed 197 // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed
126 // inside key->deref(), which causes Node destructions. We should 198 // inside key->deref(), which causes Node destructions. We should
127 // make Node destructions incremental. 199 // make Node destructions incremental.
128 info->derefObject(object); 200 info->derefObject(object);
129 } 201 }
130 202
131 } // namespace WebCore 203 } // namespace WebCore
132 204
133 #endif // ScriptWrappable_h 205 #endif // ScriptWrappable_h
OLDNEW
« no previous file with comments | « Source/bindings/v8/DOMDataStore.h ('k') | Source/bindings/v8/WorkerScriptController.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698