Changeset 180602 in webkit
- Timestamp:
- Feb 24, 2015 6:28:23 PM (9 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r180599 r180602 1 2015-02-24 Mark Lam <mark.lam@apple.com> 2 3 MachineThreads::Thread clean up has a use after free race condition. 4 <https://webkit.org/b/141990> 5 6 Reviewed by Michael Saboff. 7 8 MachineThreads::Thread clean up relies on the clean up mechanism 9 implemented in _pthread_tsd_cleanup_key(), which looks like this: 10 11 void _pthread_tsd_cleanup_key(pthread_t self, pthread_key_t key) 12 { 13 void (*destructor)(void *); 14 if (_pthread_key_get_destructor(key, &destructor)) { 15 void **ptr = &self->tsd[key]; 16 void *value = *ptr; 17 18 // At this point, this thread has cached "destructor" and "value" 19 // (which is a MachineThreads*). If the VM gets destructed (along 20 // with its MachineThreads registry) by another thread, then this 21 // thread will have no way of knowing that the MachineThreads* is 22 // now pointing to freed memory. Calling the destructor below will 23 // therefore result in a use after free scenario when it tries to 24 // access the MachineThreads' data members. 25 26 if (value) { 27 *ptr = NULL; 28 if (destructor) { 29 destructor(value); 30 } 31 } 32 } 33 } 34 35 The solution is simply to change MachineThreads from a per VM thread 36 registry to a process global singleton thread registry i.e. the 37 MachineThreads registry is now immortal and we cannot have a use after 38 free scenario since we never free it. 39 40 The cost of this change is that all VM instances will have to scan 41 stacks of all threads ever touched by a VM, and not just those that 42 touched a specific VM. However, stacks tend to be shallow. Hence, 43 those additional scans will tend to be cheap. 44 45 Secondly, it is not common for there to be multiple JSC VMs in use 46 concurrently on multiple threads. Hence, this cost should rarely 47 manifest in real world applications. 48 49 * heap/Heap.cpp: 50 (JSC::Heap::Heap): 51 (JSC::Heap::machineThreads): 52 (JSC::Heap::gatherStackRoots): 53 * heap/Heap.h: 54 (JSC::Heap::machineThreads): Deleted. 55 * heap/MachineStackMarker.cpp: 56 (JSC::MachineThreads::MachineThreads): 57 (JSC::MachineThreads::~MachineThreads): 58 (JSC::MachineThreads::addCurrentThread): 59 * heap/MachineStackMarker.h: 60 * runtime/JSLock.cpp: 61 (JSC::JSLock::didAcquireLock): 62 1 63 2015-02-24 Myles C. Maxfield <mmaxfield@apple.com> 2 64 -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r180591 r180602 312 312 , m_storageSpace(this) 313 313 , m_extraMemoryUsage(0) 314 , m_machineThreads(this)315 314 , m_sharedData(vm) 316 315 , m_slotVisitor(m_sharedData) … … 350 349 } 351 350 351 MachineThreads& Heap::machineThreads() 352 { 353 static std::once_flag initializeMachineThreadsOnceFlag; 354 static MachineThreads* machineThreads = nullptr; 355 356 std::call_once(initializeMachineThreadsOnceFlag, [] { 357 machineThreads = new MachineThreads(); 358 }); 359 360 return *machineThreads; 361 } 362 352 363 bool Heap::isPagedOut(double deadline) 353 364 { … … 588 599 GCPHASE(GatherStackRoots); 589 600 m_jitStubRoutines.clearMarks(); 590 m _machineThreads.gatherConservativeRoots(roots, m_jitStubRoutines, m_codeBlocks, dummy, registers);601 machineThreads().gatherConservativeRoots(roots, m_jitStubRoutines, m_codeBlocks, dummy, registers); 591 602 } 592 603 -
trunk/Source/JavaScriptCore/heap/Heap.h
r180591 r180602 120 120 VM* vm() const { return m_vm; } 121 121 MarkedSpace& objectSpace() { return m_objectSpace; } 122 MachineThreads& machineThreads() { return m_machineThreads; }122 static MachineThreads& machineThreads(); 123 123 124 124 const SlotVisitor& slotVisitor() const { return m_slotVisitor; } … … 356 356 std::unique_ptr<HashSet<MarkedArgumentBuffer*>> m_markListSet; 357 357 358 MachineThreads m_machineThreads;359 360 358 GCThreadSharedData m_sharedData; 361 359 SlotVisitor m_slotVisitor; -
trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp
r180591 r180602 116 116 }; 117 117 118 MachineThreads::MachineThreads( Heap* heap)118 MachineThreads::MachineThreads() 119 119 : m_registeredThreads(0) 120 120 , m_threadSpecific(0) 121 #if !ASSERT_DISABLED 122 , m_heap(heap) 123 #endif 124 { 125 UNUSED_PARAM(heap); 121 { 126 122 threadSpecificKeyCreate(&m_threadSpecific, removeThread); 127 123 } 128 124 129 MachineThreads::~MachineThreads() 130 { 131 threadSpecificKeyDelete(m_threadSpecific); 132 133 MutexLocker registeredThreadsLock(m_registeredThreadsMutex); 134 for (Thread* t = m_registeredThreads; t;) { 135 Thread* next = t->next; 136 delete t; 137 t = next; 138 } 125 NO_RETURN_DUE_TO_CRASH MachineThreads::~MachineThreads() 126 { 127 RELEASE_ASSERT_NOT_REACHED(); 139 128 } 140 129 … … 161 150 } 162 151 163 void MachineThreads::addCurrentThread( )164 { 165 ASSERT (!m_heap->vm()->hasExclusiveThread() || m_heap->vm()->exclusiveThread() == std::this_thread::get_id());152 void MachineThreads::addCurrentThread(VM* vm) 153 { 154 ASSERT_UNUSED(vm, !vm->hasExclusiveThread() || vm->exclusiveThread() == std::this_thread::get_id()); 166 155 167 156 if (threadSpecificGet(m_threadSpecific)) { -
trunk/Source/JavaScriptCore/heap/MachineStackMarker.h
r180591 r180602 34 34 class Heap; 35 35 class JITStubRoutineSet; 36 class VM; 36 37 37 38 class MachineThreads { … … 40 41 typedef jmp_buf RegisterState; 41 42 42 MachineThreads( Heap*);43 MachineThreads(); 43 44 ~MachineThreads(); 44 45 45 46 void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&, void* stackCurrent, RegisterState& registers); 46 47 47 JS_EXPORT_PRIVATE void addCurrentThread( ); // Only needs to be called by clients that can use the same heap from multiple threads.48 JS_EXPORT_PRIVATE void addCurrentThread(VM*); // Only needs to be called by clients that can use the same heap from multiple threads. 48 49 49 50 private: … … 61 62 Thread* m_registeredThreads; 62 63 WTF::ThreadSpecificKey m_threadSpecific; 63 #if !ASSERT_DISABLED64 Heap* m_heap;65 #endif66 64 }; 67 65 -
trunk/Source/JavaScriptCore/runtime/JSLock.cpp
r179728 r180602 145 145 ASSERT(m_entryAtomicStringTable); 146 146 147 m_vm->heap.machineThreads().addCurrentThread( );147 m_vm->heap.machineThreads().addCurrentThread(m_vm); 148 148 } 149 149
Note: See TracChangeset
for help on using the changeset viewer.