[Webkit-unassigned] [Bug 160337] New: Crash in JavaScriptCore GC when using JSC on dispatch queues

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Fri Jul 29 04:46:23 PDT 2016


https://bugs.webkit.org/show_bug.cgi?id=160337

            Bug ID: 160337
           Summary: Crash in JavaScriptCore GC when using JSC on dispatch
                    queues
    Classification: Unclassified
           Product: WebKit
           Version: Other
          Hardware: iOS
                OS: iOS 9.3
            Status: NEW
          Severity: Normal
          Priority: P2
         Component: JavaScriptCore
          Assignee: webkit-unassigned at lists.webkit.org
          Reporter: nham at fb.com

We recently enabled the use of JSC APIs in our app from dispatch queues. This lead to a number of crashes in the JSC GC timer so we had to remove this feature from our app. This implies that it's not safe to use JSC on a dispatch queue.

The crashing stack looks like this on iOS 8 (EXC_BAD_ADDRESS at 0x0):

  Thread #15 Crashed:
  0 JavaScriptCore JSC::ConservativeRoots::add(void*, void*, JSC::JITStubRoutineSet&, JSC::CodeBlockSet&) + 88
  1 JavaScriptCore JSC::MachineThreads::gatherFromOtherThread(JSC::ConservativeRoots&, JSC::MachineThreads::Thread*, JSC::JITStubRoutineSet&, JSC::CodeBlockSet&) + 132
  2 JavaScriptCore JSC::MachineThreads::gatherFromOtherThread(JSC::ConservativeRoots&, JSC::MachineThreads::Thread*, JSC::JITStubRoutineSet&, JSC::CodeBlockSet&) + 132
  3 JavaScriptCore JSC::MachineThreads::gatherConservativeRoots(JSC::ConservativeRoots&, JSC::JITStubRoutineSet&, JSC::CodeBlockSet&, void*, int (&) [48]) + 384
  4 JavaScriptCore JSC::Heap::markRoots(double) + 432
  5 JavaScriptCore JSC::Heap::collect(JSC::HeapOperation) + 376
  6 JavaScriptCore JSC::GCActivityCallback::doWork() + 144
  7 JavaScriptCore JSC::HeapTimer::timerDidFire(__CFRunLoopTimer*, void*) + 196
  8 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 24
  9 CoreFoundation __CFRunLoopDoTimer + 884
  10 CoreFoundation __CFRunLoopRun + 1368
  11 CoreFoundation CFRunLoopRunSpecific + 392
  12 Facebook +[RCTJSCExecutor runRunLoopThread] (RCTJSCExecutor.mm:280)
  13 Foundation __NSThread__main__ + 1068
  14 libsystem_pthread.dylib _pthread_body + 160
  15 libsystem_pthread.dylib _pthread_start + 156
  16 libsystem_pthread.dylib thread_start + 0

Basically, this is the marker segfaulting on trying to dereference a stack pointer of 0x0 for the target thread. (For this crash, we actually have a dump of the entire state of the stack in this crash, and were able to walk up the stack and find the Thread::Registers instance right on the stack clearly showing a SP of 0x0.)

The crashing stack looks like this on iOS 9 (EXC_BAD_ACCESS at 0xbbadbeef):

  Thread #11 Crashed:
  0 JavaScriptCore bmalloc::Heap::allocateXLarge(std::__1::lock_guard<bmalloc::StaticMutex>&, unsigned long) + 36
  1 JavaScriptCore bmalloc::Heap::allocateXLarge(std::__1::lock_guard<bmalloc::StaticMutex>&, unsigned long) + 20
  2 JavaScriptCore bmalloc::Allocator::allocateXLarge(unsigned long) + 92
  3 JavaScriptCore JSC::MachineThreads::gatherConservativeRoots(JSC::ConservativeRoots&, JSC::JITStubRoutineSet&, JSC::CodeBlockSet&, void*, void*, int (&) [48]) + 176
  4 JavaScriptCore JSC::Heap::markRoots(double, void*, void*, int (&) [48]) + 384
  5 JavaScriptCore JSC::Heap::collectImpl(JSC::HeapOperation, void*, void*, int (&) [48]) + 612
  6 JavaScriptCore JSC::Heap::collect(JSC::HeapOperation) + 92
  7 JavaScriptCore JSC::GCActivityCallback::doWork() + 88
  8 JavaScriptCore JSC::HeapTimer::timerDidFire(__CFRunLoopTimer*, void*) + 216
  9 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 24
  10 CoreFoundation __CFRunLoopDoTimer + 880
  11 CoreFoundation __CFRunLoopRun + 1516
  12 CoreFoundation CFRunLoopRunSpecific + 380
  13 Facebook +[RCTJSCExecutor runRunLoopThread] (RCTJSCExecutor.mm:280)
  14 Foundation __NSThread__start__ + 996
  15 libsystem_pthread.dylib _pthread_body + 152
  16 libsystem_pthread.dylib _pthread_start + 152
  17 libsystem_pthread.dylib thread_start + 0

Basically, this is bmalloc crashing on purpose because vm_allocate can't allocate a large enough contiguous region to hold the target thread's stack, presumably because JSC thinks the stack is ginormous due to it having a SP of 0x0.

It looks like the basic issue here is that JSC uses thread_get_state to the the stack pointer of the target thread. Unfortunately, thread_get_state sometimes returns a SP of 0x0 for a thread. See <rdar://27607384> and https://openradar.appspot.com/27607384 for more details. Basically, when the target thread is a dispatch queue thread that's just about to run with this call stack:

  Thread #32:
  0 libsystem_pthread.dylib start_wqthread + 0

then thread_get_state may return 0x0 for the SP, causing the crashes in JSC GC outlined above.

It's unclear to me whether this is actually a kernel bug or a JSC bug, but it seems like it might be a good idea for JSC to be defensive against a SP of 0x0 and have it abort marking if a thread is in this state. Additionally, it seems like MachineStackMarker.cpp should do some sort of sanity check on the size of the stack and not try to allocate a ginormous buffer to hold a thread's stack. For instance, on iOS I believe the maximum size of a stack is 1 MB, so JSC should never be allocating more than that amount of space to hold a single thread's stack.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.webkit.org/pipermail/webkit-unassigned/attachments/20160729/8852f2bb/attachment.html>


More information about the webkit-unassigned mailing list