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

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: rebase 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
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 scriptwrappable_init() functions are
49 // implemented by the generated V8 bindings code.
50 template <class C> static void init(C* object)
45 { 51 {
46 #ifndef NDEBUG 52 extern void scriptwrappable_init(C*); // Workaround for lack of extern t emplate prior to C++11.
abarth-chromium 2013/04/11 22:59:33 Why do we need to extern for this function? I gue
47 m_init = false; 53 scriptwrappable_init(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 } 54 }
57 55
58 v8::Handle<v8::Object> wrapper() const 56 v8::Handle<v8::Object> wrapper() const
59 { 57 {
60 return v8::Handle<v8::Object>(maskOrUnmaskPointer(*m_maskedWrapper)); 58 v8::Object* object = containsWrapper() ? reinterpret_cast<v8::Object*>(m askOrUnmaskValue(m_maskedStorage)) : 0;
59 return v8::Handle<v8::Object>(object);
61 } 60 }
62 61
63 void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration) 62 void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
64 { 63 {
65 ASSERT(m_maskedWrapper.IsEmpty()); 64 ASSERT(!containsWrapper());
66 v8::Persistent<v8::Object> persistent = v8::Persistent<v8::Object>::New( isolate, wrapper); 65 v8::Persistent<v8::Object> persistent = v8::Persistent<v8::Object>::New( isolate, wrapper);
67 configuration.configureWrapper(persistent, isolate); 66 configuration.configureWrapper(persistent, isolate);
68 WeakHandleListener<ScriptWrappable>::makeWeak(isolate, persistent, this) ; 67 WeakHandleListener<ScriptWrappable>::makeWeak(isolate, persistent, this) ;
69 m_maskedWrapper = maskOrUnmaskPointer(*persistent); 68 m_maskedStorage = maskOrUnmaskValue(reinterpret_cast<uintptr_t>(*persist ent));
69 }
70
71 const WrapperTypeInfo* typeInfo()
72 {
73 if (containsTypeInfo())
74 return reinterpret_cast<const WrapperTypeInfo*>(m_maskedStorage & ~1 );
75
76 if (containsWrapper())
77 return toWrapperTypeInfo(wrapper());
78
79 return 0;
80 }
81
82 void setTypeInfo(const WrapperTypeInfo* info)
83 {
84 m_maskedStorage = (reinterpret_cast<uintptr_t>(info) | 1);
70 } 85 }
71 86
72 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const 87 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
73 { 88 {
74 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); 89 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
75 info.ignoreMember(m_maskedWrapper); 90 info.ignoreMember(m_maskedStorage);
91 }
92
93 static bool wrapperCanBeStoredInObject(const void*) { return false; }
94 static bool wrapperCanBeStoredInObject(const ScriptWrappable*) { return true ; }
95
96 static v8::Handle<v8::Object> getWrapperFromObject(void*)
97 {
98 ASSERT_NOT_REACHED();
99 return v8::Handle<v8::Object>();
100 }
101
102 static v8::Handle<v8::Object> getWrapperFromObject(ScriptWrappable* object)
103 {
104 return object->wrapper();
105 }
106
107 static void setWrapperInObject(void*, v8::Handle<v8::Object>, v8::Isolate*, const WrapperConfiguration&)
108 {
109 ASSERT_NOT_REACHED();
110 }
111
112 static void setWrapperInObject(ScriptWrappable* object, v8::Handle<v8::Objec t> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration)
113 {
114 object->setWrapper(wrapper, isolate, configuration);
115 }
116
117 static const WrapperTypeInfo* getTypeInfoFromObject(void* object)
118 {
119 ASSERT_NOT_REACHED();
120 return 0;
121 }
122
123 static const WrapperTypeInfo* getTypeInfoFromObject(ScriptWrappable* object)
124 {
125 return object->typeInfo();
126 }
127
128 static void setTypeInfoInObject(void* object, const WrapperTypeInfo* info)
129 {
130 ASSERT_NOT_REACHED();
131 }
132
133 static void setTypeInfoInObject(ScriptWrappable* object, const WrapperTypeIn fo* info)
134 {
135 object->setTypeInfo(info);
76 } 136 }
77 137
78 protected: 138 protected:
79 ~ScriptWrappable() 139 ~ScriptWrappable()
80 { 140 {
81 #ifndef NDEBUG 141 ASSERT(m_maskedStorage); // Assert initialization via init() even if no t subsequently wrapped.
82 ASSERT(m_init); 142 m_maskedStorage = 0; // Break UAF attempts to wrap.
83 #endif
84 } 143 }
85 144
86 private: 145 private:
87 inline void disposeWrapper(v8::Persistent<v8::Value> value, v8::Isolate* iso late) 146 inline bool containsTypeInfo() const { return (m_maskedStorage & 1) == 1; }
147 inline bool containsWrapper() const { return m_maskedStorage && ((m_maskedSt orage & 1) == 0); }
148
149 static inline uintptr_t maskOrUnmaskValue(uintptr_t value)
88 { 150 {
89 ASSERT(!m_maskedWrapper.IsEmpty()); 151 const uintptr_t randomMask = ~((reinterpret_cast<uintptr_t>(&WebCoreMemo ryTypes::DOM) >> 13) | 1); // Entropy via ASLR, bottom bit clear.
90 ASSERT(*value == maskOrUnmaskPointer(*m_maskedWrapper)); 152 return (value ^ randomMask) & (!value - 1); // Preserve null without bra nching.
91 value.Dispose(isolate);
92 m_maskedWrapper.Clear();
93 } 153 }
94 154
95 static inline v8::Object* maskOrUnmaskPointer(const v8::Object* object) 155 inline void disposeWrapper(v8::Persistent<v8::Value> value, v8::Isolate* iso late, const WrapperTypeInfo* info)
96 { 156 {
97 const uintptr_t objectPointer = reinterpret_cast<uintptr_t>(object); 157 ASSERT(containsWrapper());
98 const uintptr_t randomMask = ~(reinterpret_cast<uintptr_t>(&WebCoreMemor yTypes::DOM) >> 13); // Entropy via ASLR. 158 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. 159 value.Dispose(isolate);
160 setTypeInfo(info);
100 } 161 }
101 162
102 // Stores a masked wrapper to prevent attackers from overwriting this field 163 // If zero, then this contains nothing, otherwise:
103 // with a phony wrapper. 164 // If the bottom bit it clear, then this contains a masked pointer to a wr apper object.
104 v8::Persistent<v8::Object> m_maskedWrapper; 165 // If the bottom bit is set, then this contains a pointer to the wrapper t ype info in the remaining bits.
105 166 // Masking wrappers prevents attackers from overwriting this field with poin ters to sprayed data.
106 #ifndef NDEBUG 167 // Pointers to (and inside) WrapperTypeInfo are already protected by ASLR.
107 bool m_init; 168 uintptr_t m_maskedStorage;
108 #endif
109
110 }; 169 };
111 170
112 template<> 171 template<>
113 inline void WeakHandleListener<ScriptWrappable>::callback(v8::Isolate* isolate, v8::Persistent<v8::Value> value, ScriptWrappable* key) 172 inline void WeakHandleListener<ScriptWrappable>::callback(v8::Isolate* isolate, v8::Persistent<v8::Value> value, ScriptWrappable* key)
114 { 173 {
115 ASSERT(value->IsObject()); 174 ASSERT(value->IsObject());
116 v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value) ; 175 v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::Cast(value) ;
117 ASSERT(key->wrapper() == wrapper); 176 ASSERT(key->wrapper() == wrapper);
118 177
119 // Note: |object| might not be equal to |key|, e.g., if ScriptWrappable isn' t a left-most base class. 178 // Note: |object| might not be equal to |key|, e.g., if ScriptWrappable isn' t a left-most base class.
120 void* object = toNative(wrapper); 179 void* object = toNative(wrapper);
121 WrapperTypeInfo* info = toWrapperTypeInfo(wrapper); 180 WrapperTypeInfo* info = toWrapperTypeInfo(wrapper);
122 ASSERT(info->derefObjectFunction); 181 ASSERT(info->derefObjectFunction);
123 182
124 key->disposeWrapper(value, isolate); 183 key->disposeWrapper(value, isolate, info);
125 // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed 184 // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed
126 // inside key->deref(), which causes Node destructions. We should 185 // inside key->deref(), which causes Node destructions. We should
127 // make Node destructions incremental. 186 // make Node destructions incremental.
128 info->derefObject(object); 187 info->derefObject(object);
129 } 188 }
130 189
131 } // namespace WebCore 190 } // namespace WebCore
132 191
133 #endif // ScriptWrappable_h 192 #endif // ScriptWrappable_h
OLDNEW
« Source/bindings/scripts/CodeGeneratorV8.pm ('K') | « Source/bindings/v8/DOMDataStore.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698