Closed Bug 1748401 Opened 2 years ago Closed 2 years ago

AddressSanitizer: heap-use-after-free [@ load] with READ of size 8 - harden WorkerGlobalScopeBase.mWorkerPrivate access during cycle collection traverse

Categories

(Core :: DOM: Workers, defect, P1)

x86_64
Linux
defect

Tracking

()

RESOLVED WORKSFORME
Tracking Status
firefox97 --- affected

People

(Reporter: jstutte, Assigned: edenchuang)

References

(Blocks 1 open bug)

Details

(Keywords: csectype-uaf, sec-high, testcase-wanted, Whiteboard: [bugmon:confirm])

+++ This bug was initially created as a clone of Bug #1741869 +++

Found while fuzzing mozilla-central rev 818c851d0aeb (20211224) (built with: --enable-address-sanitizer --enable-fuzzing). We do not currently have a reliable testcase for this issue.

==6911==ERROR: AddressSanitizer: heap-use-after-free on address 0x61b000222ce8 at pc 0x7f59b0a0d9a0 bp 0x7f591345d160 sp 0x7f591345d158
READ of size 8 at 0x61b000222ce8 thread T107 (DOM Worker)
    #0 0x7f59b0a0d99f in load /builds/worker/fetches/sysroot-x86_64-linux-gnu/usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/bits/atomic_base.h:713:9
    #1 0x7f59b0a0d99f in load /builds/worker/fetches/sysroot-x86_64-linux-gnu/usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/atomic:452:21
    #2 0x7f59b0a0d99f in load /builds/worker/workspace/obj-build/dist/include/mozilla/Atomics.h:195:17
    #3 0x7f59b0a0d99f in operator const PRThread * /builds/worker/workspace/obj-build/dist/include/mozilla/Atomics.h:340:31
    #4 0x7f59b0a0d99f in IsCorrectThread /builds/worker/workspace/obj-build/dist/include/mozilla/ThreadBound.h:128:41
    #5 0x7f59b0a0d99f in AssertIsCorrectThread /builds/worker/workspace/obj-build/dist/include/mozilla/ThreadBound.h:135:3
    #6 0x7f59b0a0d99f in mozilla::ThreadBound<mozilla::dom::WorkerPrivate::WorkerThreadAccessible>::Accessor<false>::Accessor(mozilla::ThreadBound<mozilla::dom::WorkerPrivate::WorkerThreadAccessible>&) /builds/worker/workspace/obj-build/dist/include/mozilla/ThreadBound.h:100:20
    #7 0x7f59b09eb15e in Access /builds/worker/workspace/obj-build/dist/include/mozilla/ThreadBound.h:123:26
    #8 0x7f59b09eb15e in mozilla::dom::WorkerPrivate::TraverseTimeouts(nsCycleCollectionTraversalCallback&) /gecko/dom/workers/WorkerPrivate.cpp:3795:39
    #9 0x7f59b0a0038e in mozilla::dom::WorkerGlobalScopeBase::cycleCollection::TraverseNative(void*, nsCycleCollectionTraversalCallback&) /gecko/dom/workers/WorkerScope.cpp:195:24
    #10 0x7f59b0a01798 in mozilla::dom::WorkerGlobalScope::cycleCollection::TraverseNative(void*, nsCycleCollectionTraversalCallback&) /gecko/dom/workers/WorkerScope.cpp:358:1
    #11 0x7f59b0a04ee1 in mozilla::dom::DedicatedWorkerGlobalScope::cycleCollection::TraverseNative(void*, nsCycleCollectionTraversalCallback&) /gecko/dom/workers/WorkerScope.cpp:772:1
    #12 0x7f59a8c6cb95 in TraverseNativeAndJS /gecko/xpcom/base/nsCycleCollectionParticipant.h:223:19
    #13 0x7f59a8c6cb95 in CCGraphBuilder::BuildGraph(js::SliceBudget&) /gecko/xpcom/base/nsCycleCollector.cpp:2051:39
    #14 0x7f59a8c723f1 in nsCycleCollector::MarkRoots(js::SliceBudget&) /gecko/xpcom/base/nsCycleCollector.cpp:2656:33
    #15 0x7f59a8c7856b in nsCycleCollector::Collect(mozilla::CCReason, ccIsManual, js::SliceBudget&, nsICycleCollectorListener*, bool) /gecko/xpcom/base/nsCycleCollector.cpp:3406:9
    #16 0x7f59a8c7bc58 in nsCycleCollector_collect(mozilla::CCReason, nsICycleCollectorListener*) /gecko/xpcom/base/nsCycleCollector.cpp:3907:28
    #17 0x7f59b09ac7cd in mozilla::dom::workerinternals::(anonymous namespace)::WorkerJSRuntime::CustomGCCallback(JSGCStatus) /gecko/dom/workers/RuntimeService.cpp:834:11
    #18 0x7f59a8c25f30 in mozilla::CycleCollectedJSRuntime::OnGC(JSContext*, JSGCStatus, JS::GCReason) /gecko/xpcom/base/CycleCollectedJSRuntime.cpp:1877:3
    #19 0x7f59b6d50f1a in js::gc::GCRuntime::maybeCallGCCallback(JSGCStatus, JS::GCReason) /gecko/js/src/gc/GC.cpp:3595:3
    #20 0x7f59b6d51ebc in ~AutoCallGCCallbacks /gecko/js/src/gc/GC.cpp:3574:32
    #21 0x7f59b6d51ebc in js::gc::GCRuntime::gcCycle(bool, js::SliceBudget const&, mozilla::Maybe<JS::GCOptions> const&, JS::GCReason) /gecko/js/src/gc/GC.cpp:3672:1
    #22 0x7f59b6d53475 in js::gc::GCRuntime::collect(bool, js::SliceBudget const&, mozilla::Maybe<JS::GCOptions> const&, JS::GCReason) /gecko/js/src/gc/GC.cpp:3855:9
    #23 0x7f59b6d1c616 in js::gc::GCRuntime::gc(JS::GCOptions, JS::GCReason) /gecko/js/src/gc/GC.cpp:3938:3
    #24 0x7f59b09ab4ea in mozilla::dom::workerinternals::(anonymous namespace)::WorkerThreadPrimaryRunnable::Run() /gecko/dom/workers/RuntimeService.cpp:2231:7
    #25 0x7f59a8e5650b in nsThread::ProcessNextEvent(bool, bool*) /gecko/xpcom/threads/nsThread.cpp:1177:16
    #26 0x7f59a8e6133c in NS_ProcessNextEvent(nsIThread*, bool) /gecko/xpcom/threads/nsThreadUtils.cpp:467:10
    #27 0x7f59aa3762c1 in mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate*) /gecko/ipc/glue/MessagePump.cpp:330:5
    #28 0x7f59aa1f3ec1 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:331:10
    #29 0x7f59aa1f3ec1 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:324:3
    #30 0x7f59aa1f3ec1 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:306:3
    #31 0x7f59a8e4ea0f in nsThread::ThreadFunc(void*) /gecko/xpcom/threads/nsThread.cpp:391:10
    #32 0x7f59cb61202e in _pt_root /gecko/nsprpub/pr/src/pthreads/ptthread.c:201:5
    #33 0x7f59cd734608 in start_thread /build/glibc-eX1tMB/glibc-2.31/nptl/pthread_create.c:477:8
    #34 0x7f59cd2fc292 in __clone /build/glibc-eX1tMB/glibc-2.31/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95

0x61b000222ce8 is located 1384 bytes inside of 1472-byte region [0x61b000222780,0x61b000222d40)
freed by thread T0 (Isolated Web Co) here:
    #0 0x55d8f67984c2 in __interceptor_free /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:111:3
    #1 0x7f59b09c8849 in operator delete /builds/worker/workspace/obj-build/dist/include/mozilla/cxxalloc.h:51:10
    #2 0x7f59b09c8849 in mozilla::dom::WorkerPrivate::Release() /builds/worker/workspace/obj-build/dist/include/mozilla/dom/WorkerPrivate.h:124:3
    #3 0x7f59b0a10820 in mozilla::dom::(anonymous namespace)::TopLevelWorkerFinishedRunnable::Run() /gecko/dom/workers/WorkerPrivate.cpp:309:22
    #4 0x7f59a8e766f2 in mozilla::ThrottledEventQueue::Inner::ExecuteRunnable() /gecko/xpcom/threads/ThrottledEventQueue.cpp:254:22
    #5 0x7f59a8e6e6cf in mozilla::ThrottledEventQueue::Inner::Executor::Run() /gecko/xpcom/threads/ThrottledEventQueue.cpp:81:15
    #6 0x7f59a8e766f2 in mozilla::ThrottledEventQueue::Inner::ExecuteRunnable() /gecko/xpcom/threads/ThrottledEventQueue.cpp:254:22
    #7 0x7f59a8e6e6cf in mozilla::ThrottledEventQueue::Inner::Executor::Run() /gecko/xpcom/threads/ThrottledEventQueue.cpp:81:15
    #8 0x7f59a8e70562 in mozilla::RunnableTask::Run() /gecko/xpcom/threads/TaskController.cpp:468:16
    #9 0x7f59a8e357ad in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /gecko/xpcom/threads/TaskController.cpp:771:26
    #10 0x7f59a8e32d08 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /gecko/xpcom/threads/TaskController.cpp:607:15
    #11 0x7f59a8e33419 in mozilla::TaskController::ProcessPendingMTTask(bool) /gecko/xpcom/threads/TaskController.cpp:391:36
    #12 0x7f59a8e79f24 in operator() /gecko/xpcom/threads/TaskController.cpp:127:37
    #13 0x7f59a8e79f24 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_1>::Run() /gecko/xpcom/threads/nsThreadUtils.h:531:5
    #14 0x7f59a8e55cd7 in nsThread::ProcessNextEvent(bool, bool*) /gecko/xpcom/threads/nsThread.cpp:1183:16
    #15 0x7f59a8e6133c in NS_ProcessNextEvent(nsIThread*, bool) /gecko/xpcom/threads/nsThreadUtils.cpp:467:10
    #16 0x7f59b0d1d9fa in bool mozilla::SpinEventLoopUntil<(mozilla::ProcessFailureBehavior)1, mozilla::dom::XMLHttpRequestMainThread::SendInternal(mozilla::dom::BodyExtractorBase const*, bool, mozilla::ErrorResult&)::$_1>(nsTSubstring<char> const&, mozilla::dom::XMLHttpRequestMainThread::SendInternal(mozilla::dom::BodyExtractorBase const*, bool, mozilla::ErrorResult&)::$_1&&, nsIThread*) /builds/worker/workspace/obj-build/dist/include/mozilla/SpinEventLoopUntil.h:176:25
    #17 0x7f59b0d1ac08 in mozilla::dom::XMLHttpRequestMainThread::SendInternal(mozilla::dom::BodyExtractorBase const*, bool, mozilla::ErrorResult&) /gecko/dom/xhr/XMLHttpRequestMainThread.cpp:3063:10
    #18 0x7f59b0d1932b in mozilla::dom::XMLHttpRequestMainThread::Send(mozilla::dom::Nullable<mozilla::dom::DocumentOrBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString> const&, mozilla::ErrorResult&) /gecko/dom/xhr/XMLHttpRequestMainThread.cpp:2817:5
    #19 0x7f59ade0cf24 in mozilla::dom::XMLHttpRequest_Binding::send(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) /builds/worker/workspace/obj-build/dom/bindings/XMLHttpRequestBinding.cpp:1374:24
    #20 0x7f59ae522cfd in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) /gecko/dom/bindings/BindingUtils.cpp:3306:13
    #21 0x7f59b6059404 in CallJSNative /gecko/js/src/vm/Interpreter.cpp:425:13
    #22 0x7f59b6059404 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:512:12
    #23 0x7f59b60458ce in CallFromStack /gecko/js/src/vm/Interpreter.cpp:576:10
    #24 0x7f59b60458ce in Interpret(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:3309:16
    #25 0x7f59b602a6d1 in js::RunScript(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:394:13
    #26 0x7f59b605953f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:544:13
    #27 0x7f59b605b68b in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:589:8
    #28 0x7f59b65f4ba7 in js::CallSelfHostedFunction(JSContext*, JS::Handle<js::PropertyName*>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /gecko/js/src/vm/SelfHosting.cpp:1539:10
    #29 0x7f59b62a2d89 in AsyncFunctionResume(JSContext*, JS::Handle<js::AsyncFunctionGeneratorObject*>, ResumeKind, JS::Handle<JS::Value>) /gecko/js/src/vm/AsyncFunction.cpp:152:8
    #30 0x7f59b645374d in AsyncFunctionPromiseReactionJob /gecko/js/src/builtin/Promise.cpp:1954:10
    #31 0x7f59b645374d in PromiseReactionJob(JSContext*, unsigned int, JS::Value*) /gecko/js/src/builtin/Promise.cpp:2012:12
    #32 0x7f59b6059404 in CallJSNative /gecko/js/src/vm/Interpreter.cpp:425:13
    #33 0x7f59b6059404 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:512:12
    #34 0x7f59b605b68b in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:589:8
    #35 0x7f59b62d9a1d in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /gecko/js/src/vm/CallAndConstruct.cpp:117:10

previously allocated by thread T0 (Isolated Web Co) here:
    #0 0x55d8f679872d in __interceptor_malloc /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:129:3
    #1 0x55d8f67d33bd in moz_xmalloc /gecko/memory/mozalloc/mozalloc.cpp:52:15
    #2 0x7f59b09dfd47 in operator new /builds/worker/workspace/obj-build/dist/include/mozilla/cxxalloc.h:33:10
    #3 0x7f59b09dfd47 in mozilla::dom::WorkerPrivate::Constructor(JSContext*, nsTSubstring<char16_t> const&, bool, mozilla::dom::WorkerKind, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, mozilla::dom::WorkerLoadInfo*, mozilla::ErrorResult&, nsTString<char16_t>) /gecko/dom/workers/WorkerPrivate.cpp:2502:7
    #4 0x7f59b0995e4d in mozilla::dom::Worker::Constructor(mozilla::dom::GlobalObject const&, nsTSubstring<char16_t> const&, mozilla::dom::WorkerOptions const&, mozilla::ErrorResult&) /gecko/dom/workers/Worker.cpp:44:41
    #5 0x7f59adde522c in mozilla::dom::Worker_Binding::_constructor(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/obj-build/dom/bindings/WorkerBinding.cpp:1107:52
    #6 0x7f59b605c235 in CallJSNative /gecko/js/src/vm/Interpreter.cpp:425:13
    #7 0x7f59b605c235 in CallJSNativeConstructor /gecko/js/src/vm/Interpreter.cpp:441:8
    #8 0x7f59b605c235 in InternalConstruct(JSContext*, js::AnyConstructArgs const&) /gecko/js/src/vm/Interpreter.cpp:636:10
    #9 0x7f59b604587f in Interpret(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:3299:16
    #10 0x7f59b602a6d1 in js::RunScript(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:394:13
    #11 0x7f59b605953f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:544:13
    #12 0x7f59b605b68b in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:589:8
    #13 0x7f59b62d9a1d in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /gecko/js/src/vm/CallAndConstruct.cpp:117:10
    #14 0x7f59ae141b79 in mozilla::dom::EventListener::HandleEvent(mozilla::dom::BindingCallContext&, JS::Handle<JS::Value>, mozilla::dom::Event&, mozilla::ErrorResult&) /builds/worker/workspace/obj-build/dom/bindings/EventListenerBinding.cpp:62:8
    #15 0x7f59aedf5894 in void mozilla::dom::EventListener::HandleEvent<mozilla::dom::EventTarget*>(mozilla::dom::EventTarget* const&, mozilla::dom::Event&, mozilla::ErrorResult&, char const*, mozilla::dom::CallbackObject::ExceptionHandling, JS::Realm*) /builds/worker/workspace/obj-build/dist/include/mozilla/dom/EventListenerBinding.h:65:12
    #16 0x7f59aedf5350 in mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener*, mozilla::dom::Event*, mozilla::dom::EventTarget*) /gecko/dom/events/EventListenerManager.cpp:1303:43
    #17 0x7f59aedf69fc in mozilla::EventListenerManager::HandleEventInternal(nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event**, mozilla::dom::EventTarget*, nsEventStatus*, bool) /gecko/dom/events/EventListenerManager.cpp:1500:17
    #18 0x7f59aede4ace in mozilla::EventTargetChainItem::HandleEvent(mozilla::EventChainPostVisitor&, mozilla::ELMCreationDetector&) /gecko/dom/events/EventDispatcher.cpp:348:17
    #19 0x7f59aede32dd in mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem>&, mozilla::EventChainPostVisitor&, mozilla::EventDispatchingCallback*, mozilla::ELMCreationDetector&) /gecko/dom/events/EventDispatcher.cpp:550:16
    #20 0x7f59aede7555 in mozilla::EventDispatcher::Dispatch(nsISupports*, nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event*, nsEventStatus*, mozilla::EventDispatchingCallback*, nsTArray<mozilla::dom::EventTarget*>*) /gecko/dom/events/EventDispatcher.cpp:1085:11
    #21 0x7f59b178d5c7 in nsDocumentViewer::LoadComplete(nsresult) /gecko/layout/base/nsDocumentViewer.cpp:1086:7
    #22 0x7f59b5118033 in nsDocShell::EndPageLoad(nsIWebProgress*, nsIChannel*, nsresult) /gecko/docshell/base/nsDocShell.cpp:6309:20
    #23 0x7f59b511732b in nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /gecko/docshell/base/nsDocShell.cpp:5698:7
    #24 0x7f59b51192ff in non-virtual thunk to nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /gecko/docshell/base/nsDocShell.cpp
    #25 0x7f59ab492ac0 in nsDocLoader::DoFireOnStateChange(nsIWebProgress*, nsIRequest*, int&, nsresult) /gecko/uriloader/base/nsDocLoader.cpp:1377:3
    #26 0x7f59ab4916d4 in nsDocLoader::doStopDocumentLoad(nsIRequest*, nsresult) /gecko/uriloader/base/nsDocLoader.cpp:975:14
    #27 0x7f59ab48df02 in nsDocLoader::DocLoaderIsEmpty(bool, mozilla::Maybe<nsresult> const&) /gecko/uriloader/base/nsDocLoader.cpp:794:9
    #28 0x7f59ab4900c5 in nsDocLoader::OnStopRequest(nsIRequest*, nsresult) /gecko/uriloader/base/nsDocLoader.cpp:677:5
    #29 0x7f59b515187b in nsDocShell::OnStopRequest(nsIRequest*, nsresult) /gecko/docshell/base/nsDocShell.cpp:13571:23
    #30 0x7f59a91bca8e in mozilla::net::nsLoadGroup::NotifyRemovalObservers(nsIRequest*, nsresult) /gecko/netwerk/base/nsLoadGroup.cpp:614:22
    #31 0x7f59a91bf4d3 in mozilla::net::nsLoadGroup::RemoveRequest(nsIRequest*, nsISupports*, nsresult) /gecko/netwerk/base/nsLoadGroup.cpp:518:10
    #32 0x7f59ac6ca2a2 in mozilla::dom::Document::DoUnblockOnload() /gecko/dom/base/Document.cpp:11556:18

Thread T107 (DOM Worker) created by T0 (Isolated Web Co) here:
    #0 0x55d8f6782e2c in __interceptor_pthread_create /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_interceptors.cpp:207:3
    #1 0x7f59cb6020b4 in _PR_CreateThread /gecko/nsprpub/pr/src/pthreads/ptthread.c:458:14
    #2 0x7f59cb5f335e in PR_CreateThread /gecko/nsprpub/pr/src/pthreads/ptthread.c:533:12
    #3 0x7f59a8e51d65 in nsThread::Init(nsTSubstring<char> const&) /gecko/xpcom/threads/nsThread.cpp:615:18
    #4 0x7f59b0a0b792 in mozilla::dom::WorkerThread::Create(mozilla::dom::WorkerThreadFriendKey const&) /gecko/dom/workers/WorkerThread.cpp:102:7
    #5 0x7f59b098b7b8 in mozilla::dom::workerinternals::RuntimeService::ScheduleWorker(mozilla::dom::WorkerPrivate&) /gecko/dom/workers/RuntimeService.cpp:1360:14
    #6 0x7f59b098a6d4 in mozilla::dom::workerinternals::RuntimeService::RegisterWorker(mozilla::dom::WorkerPrivate&) /gecko/dom/workers/RuntimeService.cpp:1227:19
    #7 0x7f59b09dfe64 in mozilla::dom::WorkerPrivate::Constructor(JSContext*, nsTSubstring<char16_t> const&, bool, mozilla::dom::WorkerKind, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, mozilla::dom::WorkerLoadInfo*, mozilla::ErrorResult&, nsTString<char16_t>) /gecko/dom/workers/WorkerPrivate.cpp:2518:24
    #8 0x7f59b0995e4d in mozilla::dom::Worker::Constructor(mozilla::dom::GlobalObject const&, nsTSubstring<char16_t> const&, mozilla::dom::WorkerOptions const&, mozilla::ErrorResult&) /gecko/dom/workers/Worker.cpp:44:41
    #9 0x7f59adde522c in mozilla::dom::Worker_Binding::_constructor(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/obj-build/dom/bindings/WorkerBinding.cpp:1107:52
    #10 0x7f59b605c235 in CallJSNative /gecko/js/src/vm/Interpreter.cpp:425:13
    #11 0x7f59b605c235 in CallJSNativeConstructor /gecko/js/src/vm/Interpreter.cpp:441:8
    #12 0x7f59b605c235 in InternalConstruct(JSContext*, js::AnyConstructArgs const&) /gecko/js/src/vm/Interpreter.cpp:636:10
    #13 0x7f59b604587f in Interpret(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:3299:16
    #14 0x7f59b602a6d1 in js::RunScript(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:394:13
    #15 0x7f59b605953f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:544:13
    #16 0x7f59b605b68b in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:589:8
    #17 0x7f59b62d9a1d in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /gecko/js/src/vm/CallAndConstruct.cpp:117:10
    #18 0x7f59ae141b79 in mozilla::dom::EventListener::HandleEvent(mozilla::dom::BindingCallContext&, JS::Handle<JS::Value>, mozilla::dom::Event&, mozilla::ErrorResult&) /builds/worker/workspace/obj-build/dom/bindings/EventListenerBinding.cpp:62:8
    #19 0x7f59aedf5894 in void mozilla::dom::EventListener::HandleEvent<mozilla::dom::EventTarget*>(mozilla::dom::EventTarget* const&, mozilla::dom::Event&, mozilla::ErrorResult&, char const*, mozilla::dom::CallbackObject::ExceptionHandling, JS::Realm*) /builds/worker/workspace/obj-build/dist/include/mozilla/dom/EventListenerBinding.h:65:12
    #20 0x7f59aedf5350 in mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener*, mozilla::dom::Event*, mozilla::dom::EventTarget*) /gecko/dom/events/EventListenerManager.cpp:1303:43
    #21 0x7f59aedf69fc in mozilla::EventListenerManager::HandleEventInternal(nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event**, mozilla::dom::EventTarget*, nsEventStatus*, bool) /gecko/dom/events/EventListenerManager.cpp:1500:17
    #22 0x7f59aede4ace in mozilla::EventTargetChainItem::HandleEvent(mozilla::EventChainPostVisitor&, mozilla::ELMCreationDetector&) /gecko/dom/events/EventDispatcher.cpp:348:17
    #23 0x7f59aede32dd in mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem>&, mozilla::EventChainPostVisitor&, mozilla::EventDispatchingCallback*, mozilla::ELMCreationDetector&) /gecko/dom/events/EventDispatcher.cpp:550:16
    #24 0x7f59aede7555 in mozilla::EventDispatcher::Dispatch(nsISupports*, nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event*, nsEventStatus*, mozilla::EventDispatchingCallback*, nsTArray<mozilla::dom::EventTarget*>*) /gecko/dom/events/EventDispatcher.cpp:1085:11
    #25 0x7f59b178d5c7 in nsDocumentViewer::LoadComplete(nsresult) /gecko/layout/base/nsDocumentViewer.cpp:1086:7
    #26 0x7f59b5118033 in nsDocShell::EndPageLoad(nsIWebProgress*, nsIChannel*, nsresult) /gecko/docshell/base/nsDocShell.cpp:6309:20
    #27 0x7f59b511732b in nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /gecko/docshell/base/nsDocShell.cpp:5698:7
    #28 0x7f59b51192ff in non-virtual thunk to nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /gecko/docshell/base/nsDocShell.cpp
    #29 0x7f59ab492ac0 in nsDocLoader::DoFireOnStateChange(nsIWebProgress*, nsIRequest*, int&, nsresult) /gecko/uriloader/base/nsDocLoader.cpp:1377:3
    #30 0x7f59ab4916d4 in nsDocLoader::doStopDocumentLoad(nsIRequest*, nsresult) /gecko/uriloader/base/nsDocLoader.cpp:975:14
    #31 0x7f59ab48df02 in nsDocLoader::DocLoaderIsEmpty(bool, mozilla::Maybe<nsresult> const&) /gecko/uriloader/base/nsDocLoader.cpp:794:9
    #32 0x7f59ab4900c5 in nsDocLoader::OnStopRequest(nsIRequest*, nsresult) /gecko/uriloader/base/nsDocLoader.cpp:677:5
    #33 0x7f59b515187b in nsDocShell::OnStopRequest(nsIRequest*, nsresult) /gecko/docshell/base/nsDocShell.cpp:13571:23
    #34 0x7f59a91bca8e in mozilla::net::nsLoadGroup::NotifyRemovalObservers(nsIRequest*, nsresult) /gecko/netwerk/base/nsLoadGroup.cpp:614:22
    #35 0x7f59a91bf4d3 in mozilla::net::nsLoadGroup::RemoveRequest(nsIRequest*, nsISupports*, nsresult) /gecko/netwerk/base/nsLoadGroup.cpp:518:10
    #36 0x7f59ac6ca2a2 in mozilla::dom::Document::DoUnblockOnload() /gecko/dom/base/Document.cpp:11556:18
    #37 0x7f59ac6772f7 in mozilla::dom::Document::UnblockOnload(bool) /gecko/dom/base/Document.cpp:11486:9
    #38 0x7f59ac6a1fb1 in mozilla::dom::Document::DispatchContentLoadedEvents() /gecko/dom/base/Document.cpp:8001:3
    #39 0x7f59ac79171d in applyImpl<mozilla::dom::Document, void (mozilla::dom::Document::*)()> /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1147:12
    #40 0x7f59ac79171d in apply<mozilla::dom::Document, void (mozilla::dom::Document::*)()> /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1153:12
    #41 0x7f59ac79171d in mozilla::detail::RunnableMethodImpl<mozilla::dom::Document*, void (mozilla::dom::Document::*)(), true, (mozilla::RunnableKind)0>::Run() /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:1200:13
    #42 0x7f59a8e2391f in mozilla::SchedulerGroup::Runnable::Run() /gecko/xpcom/threads/SchedulerGroup.cpp:144:20
    #43 0x7f59a8e70562 in mozilla::RunnableTask::Run() /gecko/xpcom/threads/TaskController.cpp:468:16
    #44 0x7f59a8e357ad in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /gecko/xpcom/threads/TaskController.cpp:771:26
    #45 0x7f59a8e32d08 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /gecko/xpcom/threads/TaskController.cpp:607:15
    #46 0x7f59a8e33419 in mozilla::TaskController::ProcessPendingMTTask(bool) /gecko/xpcom/threads/TaskController.cpp:391:36
    #47 0x7f59a8e79ef1 in operator() /gecko/xpcom/threads/TaskController.cpp:124:37
    #48 0x7f59a8e79ef1 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_0>::Run() /gecko/xpcom/threads/nsThreadUtils.h:531:5
    #49 0x7f59a8e55cd7 in nsThread::ProcessNextEvent(bool, bool*) /gecko/xpcom/threads/nsThread.cpp:1183:16
    #50 0x7f59a8e6133c in NS_ProcessNextEvent(nsIThread*, bool) /gecko/xpcom/threads/nsThreadUtils.cpp:467:10
    #51 0x7f59aa3749cf in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /gecko/ipc/glue/MessagePump.cpp:85:21
    #52 0x7f59aa1f3ec1 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:331:10
    #53 0x7f59aa1f3ec1 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:324:3
    #54 0x7f59aa1f3ec1 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:306:3
    #55 0x7f59b1105fa7 in nsBaseAppShell::Run() /gecko/widget/nsBaseAppShell.cpp:137:27
    #56 0x7f59b5d76f7f in XRE_RunAppShell() /gecko/toolkit/xre/nsEmbedFunctions.cpp:864:20
    #57 0x7f59aa1f3ec1 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:331:10
    #58 0x7f59aa1f3ec1 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:324:3
    #59 0x7f59aa1f3ec1 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:306:3
    #60 0x7f59b5d761b2 in XRE_InitChildProcess(int, char**, XREChildData const*) /gecko/toolkit/xre/nsEmbedFunctions.cpp:701:34
    #61 0x55d8f67cd08d in content_process_main(mozilla::Bootstrap*, int, char**) /gecko/browser/app/../../ipc/contentproc/plugin-container.cpp:57:28
    #62 0x55d8f67cd4b8 in main /gecko/browser/app/nsBrowserApp.cpp:327:18
    #63 0x7f59cd2010b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/fetches/sysroot-x86_64-linux-gnu/usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/bits/atomic_base.h:713:9 in load
Shadow bytes around the buggy address:
  0x0c368003c540: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c368003c550: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c368003c560: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c368003c570: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c368003c580: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c368003c590: fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd
  0x0c368003c5a0: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
  0x0c368003c5b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c368003c5c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c368003c5d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c368003c5e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==6911==ABORTING
Summary: AddressSanitizer: heap-use-after-free [@ load] with READ of size 8 → AddressSanitizer: heap-use-after-free [@ load] with READ of size 8 - harden WorkerGlobalScopeBase.mWorkerPrivate access during cycle collection traverse

From bug 1741869 comment 2:

TopLevelWorkerFinishedRunnable clears the WorkerPrivate self reference which makes it go away.

But we have WorkerGlobalScopeBase.mWorkerPrivate and for reasons I ignore the ServiceWorkerGlobalScope this is part of is cycle collected only later and there we have a custom traverse function that triggers WorkerPrivate::TraverseTimeouts on the already freed WorkerPrivate memory.

A naive approach could be to make WorkerGlobalScopeBase.mWorkerPrivate become a RefPtr, but WorkerPrivate is not thread safe for refcounting. I assume the solution might be part of a more general overhaul of WorkerPrivate?

From bug 1741869 comment 24:

I suspect there to be a different root cause. And on that new bug we might want to discuss also if we can find some hardening/mitigation that does not require us to fix all ordering problems. I assume from comment 2 that WorkerGlobalScopeBase.mWorkerPrivate could become a RefPtr<StrongWorkerRef> or even RefPtr<ThreadSafeWorkerRef>.

Blocks: 1741869
No longer depends on: 1741869

Jason, if you happen to find a reliable testcase and/or a pernosco session for this that would be great. But I really think we should harden WorkerGlobalScopeBase.mWorkerPrivate against bad event ordering somehow.

Flags: needinfo?(jkratzer)

Eden, can you take a look here? Thanks!

Flags: needinfo?(echuang)

BTW: This somehow relates to the investigations we started in bug 1744025, specifically D132709. CheckedUnsafePtr would maybe have helped to find it earlier, but is obviously not a solution to heal this.

I think the first part of my comment from https://bugzilla.mozilla.org/show_bug.cgi?id=1741869#c14 is probably still relevant here, quoting here:

The comment 0 stack is somewhat confusing. Frame 24 of the UAF on the worker is at the call to JS_GC(cx, JS::GCReason::WORKER_SHUTDOWN);
which strictly happens before ScheduleDeletion is called which would create the TopLevelWorkerFinishedRunnable. For this stack to occur, it would tend to imply that we ended up in the notify/cancel edge case that calls ScheduleDeletion or that the run loop's failureCleanup case got invoked which calls RunLoopNeverRan which calls ScheduleDeletion.

Group: core-security → dom-core-security
No longer blocks: 1741869

(In reply to Jens Stutte [:jstutte] from comment #1)

I suspect there to be a different root cause. And on that new bug we might want to discuss also if we can find some hardening/mitigation that does not require us to fix all ordering problems. I assume from comment 2 that WorkerGlobalScopeBase.mWorkerPrivate could become a RefPtr<StrongWorkerRef> or even RefPtr<ThreadSafeWorkerRef>.

Talking with Eden we think that actually this might be more a case for a WeakWorkerRef.

The WeakWorkerRef could be a good change there and maybe mitigate this exact crash stack, but I do want to reiterate that the TopLevelWorkerFinishedRunnable being dispatched before it should be dispatched is a serious invariant violation and seems likely to still manifest in other serious ways. (Although it would be very nice if none of those are UAFs! :)

(In reply to Andrew Sutherland [:asuth] (he/him) from comment #7)

The WeakWorkerRef could be a good change there and maybe mitigate this exact crash stack, but I do want to reiterate that the TopLevelWorkerFinishedRunnable being dispatched before it should be dispatched is a serious invariant violation and seems likely to still manifest in other serious ways. (Although it would be very nice if none of those are UAFs! :)

Just to recap and precise from our direct conversations - we definitely want both: Reduce the direct harm this can cause by using a WeakWorkerRef and improve our checks for the lifecycle invariants.

Assignee: nobody → echuang
Flags: needinfo?(echuang)

:jens, just wanted to let you know that I have not seen another instance of this crash since I initially reported it.

Flags: needinfo?(jkratzer)

(In reply to Jason Kratzer [:jkratzer] from comment #9)

:jens, just wanted to let you know that I have not seen another instance of this crash since I initially reported it.

Thanks, we'll continue work on bug 1744025 but until we have other occurrences I'd consider this one stalled.

Keywords: stalled

(In reply to Andrew Sutherland [:asuth] (he/him) from comment #5)

I think the first part of my comment from https://bugzilla.mozilla.org/show_bug.cgi?id=1741869#c14 is probably still relevant here, quoting here:

The comment 0 stack is somewhat confusing. Frame 24 of the UAF on the worker is at the call to JS_GC(cx, JS::GCReason::WORKER_SHUTDOWN);
which strictly happens before ScheduleDeletion is called which would create the TopLevelWorkerFinishedRunnable. For this stack to occur, it would tend to imply that we ended up in the notify/cancel edge case that calls ScheduleDeletion or that the run loop's failureCleanup case got invoked which calls RunLoopNeverRan which calls ScheduleDeletion.

The interesting is that if we are in JS_GC(cx, JS::GCReason::WORKER_SHUTDOWN), it seems to be impossible calling ScheduleDeletion from WorkerPrivate::Notify or failureCleanup.

Considering that we have already been in WorkerThreadPrimaryRunnable::Run(), that means the worker thread is created and ScheduleWorker() must be called. Under this situation, the WorkerPrivate::mParentStatus should not be "Pending". Therefore, it should have no chance to call ScheduleDeletion from WorkerPrivate::Notify().

Since we have already at the line JS_GC(cx, JS::GCReason::WORKER_SHUTDOWN), failureCleanup has already released here. It also means ScheduleDeletion would not be called by failureCleanup.

See Also: → 1752120

(In reply to Jason Kratzer [:jkratzer] from comment #9)

:jens, just wanted to let you know that I have not seen another instance of this crash since I initially reported it.

Hi Jason, is this still true?

Flags: needinfo?(jkratzer)

(In reply to Jens Stutte [:jstutte] from comment #12)

(In reply to Jason Kratzer [:jkratzer] from comment #9)

:jens, just wanted to let you know that I have not seen another instance of this crash since I initially reported it.

Hi Jason, is this still true?

Yes. Only one instance of this bug was ever identified back on 2021/12/24.

Flags: needinfo?(jkratzer)

Marking this WORKSFORME as:

  • Our reading of the issue I raised in comment 5 and Eden also analyzed in comment 11 is that the stacks/ordering implied by this bug are impossible, and...
    • It's possible (as it's always possible, especially if things have already gone wrong in a bunch of ways) that the stack backtrace can be incorrect due to compiler optimization or a corrupted stack, especially if the backtrace falls back to stack scanning. (I don't know enough about ASAN's behavior here, though.)
    • Since this only happened the once, we can't get a pernosco reproduction, or really any reproduction.
  • We fixed some very important shutdown related logic for workers related to when GC happens, etc.
    • It's possible this might have fixed whatever complex thing was going on here, especially if the stack was wrong/misleading.
    • We expect these fixes to broadly eliminate an entire class of bugs related to worker shutdown, which means that fuzzing is more likely to reproduce this problem in the future if it actually is a problem (since it's not crashing on the cases we fixed).

It's possible some keywords or the RESOLVED state should be different; please correct if so.

Status: NEW → RESOLVED
Closed: 2 years ago
Resolution: --- → WORKSFORME

Since the bug is closed, the stalled keyword is now meaningless.
For more information, please visit auto_nag documentation.

Keywords: stalled
See Also: → 1741869
Group: dom-core-security
You need to log in before you can comment on or make changes to this bug.