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

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: Fix comments. 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. C++11's extern template feature may provide
52 // a cleaner solution someday.
53 template <class C> static void init(C* object)
45 { 54 {
46 #ifndef NDEBUG 55 void initializeScriptWrappableForInterface(C*);
47 m_init = false; 56 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 } 57 }
57 58
58 v8::Handle<v8::Object> wrapper() const 59 v8::Handle<v8::Object> wrapper() const
59 { 60 {
60 return v8::Handle<v8::Object>(maskOrUnmaskPointer(*m_maskedWrapper)); 61 v8::Object* object = containsWrapper() ? reinterpret_cast<v8::Object*>(m askOrUnmaskValue(m_maskedStorage)) : 0;
62 return v8::Handle<v8::Object>(object);
61 } 63 }
62 64
63 void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration) 65 void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
64 { 66 {
65 ASSERT(m_maskedWrapper.IsEmpty()); 67 ASSERT(!containsWrapper());
68 if (!*wrapper) {
69 m_maskedStorage = 0;
70 return;
71 }
66 v8::Persistent<v8::Object> persistent = v8::Persistent<v8::Object>::New( isolate, wrapper); 72 v8::Persistent<v8::Object> persistent = v8::Persistent<v8::Object>::New( isolate, wrapper);
67 configuration.configureWrapper(persistent, isolate); 73 configuration.configureWrapper(persistent, isolate);
68 WeakHandleListener<ScriptWrappable>::makeWeak(isolate, persistent, this) ; 74 WeakHandleListener<ScriptWrappable>::makeWeak(isolate, persistent, this) ;
69 m_maskedWrapper = maskOrUnmaskPointer(*persistent); 75 m_maskedStorage = maskOrUnmaskValue(reinterpret_cast<uintptr_t>(*persist ent));
76 ASSERT(containsWrapper());
77 }
78
79 const WrapperTypeInfo* typeInfo()
80 {
81 if (containsTypeInfo())
82 return reinterpret_cast<const WrapperTypeInfo*>(m_maskedStorage);
83
84 if (containsWrapper())
85 return toWrapperTypeInfo(wrapper());
86
87 return 0;
88 }
89
90 void setTypeInfo(const WrapperTypeInfo* info)
91 {
92 m_maskedStorage = reinterpret_cast<uintptr_t>(info);
93 ASSERT(containsTypeInfo());
70 } 94 }
71 95
72 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const 96 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
73 { 97 {
74 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); 98 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
75 info.ignoreMember(m_maskedWrapper); 99 info.ignoreMember(m_maskedStorage);
100 }
101
102 static bool wrapperCanBeStoredInObject(const void*) { return false; }
103 static bool wrapperCanBeStoredInObject(const ScriptWrappable*) { return true ; }
104
105 static v8::Handle<v8::Object> getWrapperFromObject(void*)
106 {
107 ASSERT_NOT_REACHED();
108 return v8::Handle<v8::Object>();
109 }
110
111 static v8::Handle<v8::Object> getWrapperFromObject(ScriptWrappable* object)
112 {
113 return object->wrapper();
114 }
115
116 static void setWrapperInObject(void*, v8::Handle<v8::Object>, v8::Isolate*, const WrapperConfiguration&)
117 {
118 ASSERT_NOT_REACHED();
119 }
120
121 static void setWrapperInObject(ScriptWrappable* object, v8::Handle<v8::Objec t> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
122 {
123 object->setWrapper(wrapper, isolate, configuration);
124 }
125
126 static const WrapperTypeInfo* getTypeInfoFromObject(void* object)
127 {
128 ASSERT_NOT_REACHED();
129 return 0;
130 }
131
132 static const WrapperTypeInfo* getTypeInfoFromObject(ScriptWrappable* object)
133 {
134 return object->typeInfo();
135 }
136
137 static void setTypeInfoInObject(void* object, const WrapperTypeInfo* info)
138 {
139 ASSERT_NOT_REACHED();
140 }
141
142 static void setTypeInfoInObject(ScriptWrappable* object, const WrapperTypeIn fo* info)
143 {
144 object->setTypeInfo(info);
76 } 145 }
77 146
78 protected: 147 protected:
79 ~ScriptWrappable() 148 ~ScriptWrappable()
80 { 149 {
81 #ifndef NDEBUG 150 ASSERT(m_maskedStorage); // Assert initialization via init() even if no t subsequently wrapped.
82 ASSERT(m_init); 151 m_maskedStorage = 0; // Break UAF attempts to wrap.
83 #endif
84 } 152 }
85 153
86 private: 154 private:
87 inline void disposeWrapper(v8::Persistent<v8::Value> value, v8::Isolate* iso late) 155 inline bool containsWrapper() const { return (m_maskedStorage & 1) == 1; }
156 inline bool containsTypeInfo() const { return m_maskedStorage && ((m_maskedS torage & 1) == 0); }
157
158 static inline uintptr_t maskOrUnmaskValue(uintptr_t value)
88 { 159 {
89 ASSERT(!m_maskedWrapper.IsEmpty()); 160 // 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)); 161 // applied to wrappers, not wrapper type infos, and these are aligned po itners with zeros in the bottom
91 value.Dispose(isolate); 162 // bit(s), this automatically set the wrapper flag in the bottom bit upo n encoding. Simiarlry,this
92 m_maskedWrapper.Clear(); 163 // automatically zeros out the bit upon decoding. Additionally, since se tWrapper() now performs an explicit
164 // null test, and wrapper() requires the bottom bit to be set, there is no need to preserve null here.
165 const uintptr_t randomMask = ~((reinterpret_cast<uintptr_t>(&WebCoreMemo ryTypes::DOM) >> 13)) | 1;
166 return value ^ randomMask;
93 } 167 }
94 168
95 static inline v8::Object* maskOrUnmaskPointer(const v8::Object* object) 169 inline void disposeWrapper(v8::Persistent<v8::Value> value, v8::Isolate* iso late, const WrapperTypeInfo* info)
96 { 170 {
97 const uintptr_t objectPointer = reinterpret_cast<uintptr_t>(object); 171 ASSERT(containsWrapper());
98 const uintptr_t randomMask = ~(reinterpret_cast<uintptr_t>(&WebCoreMemor yTypes::DOM) >> 13); // Entropy via ASLR. 172 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. 173 value.Dispose(isolate);
174 setTypeInfo(info);
100 } 175 }
101 176
102 // Stores a masked wrapper to prevent attackers from overwriting this field 177 // If zero, then this contains nothing, otherwise:
103 // with a phony wrapper. 178 // 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; 179 // If the bottom bit is clear, then this contains a pointer to the wrapper type info in the remaining bits.
105 180 // Masking wrappers prevents attackers from overwriting this field with poin ters to sprayed data.
106 #ifndef NDEBUG 181 // Pointers to (and inside) WrapperTypeInfo are already protected by ASLR.
107 bool m_init; 182 uintptr_t m_maskedStorage;
108 #endif
109
110 }; 183 };
111 184
112 template<> 185 template<>
113 inline void WeakHandleListener<ScriptWrappable>::callback(v8::Isolate* isolate, v8::Persistent<v8::Value> value, ScriptWrappable* key) 186 inline void WeakHandleListener<ScriptWrappable>::callback(v8::Isolate* isolate, v8::Persistent<v8::Value> value, ScriptWrappable* key)
114 { 187 {
115 ASSERT(value->IsObject()); 188 ASSERT(value->IsObject());
116 v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value) ; 189 v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value) ;
117 ASSERT(key->wrapper() == wrapper); 190 ASSERT(key->wrapper() == wrapper);
118 191
119 // Note: |object| might not be equal to |key|, e.g., if ScriptWrappable isn' t a left-most base class. 192 // Note: |object| might not be equal to |key|, e.g., if ScriptWrappable isn' t a left-most base class.
120 void* object = toNative(wrapper); 193 void* object = toNative(wrapper);
121 WrapperTypeInfo* info = toWrapperTypeInfo(wrapper); 194 WrapperTypeInfo* info = toWrapperTypeInfo(wrapper);
122 ASSERT(info->derefObjectFunction); 195 ASSERT(info->derefObjectFunction);
123 196
124 key->disposeWrapper(value, isolate); 197 key->disposeWrapper(value, isolate, info);
125 // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed 198 // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed
126 // inside key->deref(), which causes Node destructions. We should 199 // inside key->deref(), which causes Node destructions. We should
127 // make Node destructions incremental. 200 // make Node destructions incremental.
128 info->derefObject(object); 201 info->derefObject(object);
129 } 202 }
130 203
131 } // namespace WebCore 204 } // namespace WebCore
132 205
133 #endif // ScriptWrappable_h 206 #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