Closed Bug 1656957 (CVE-2020-15669) Opened 4 years ago Closed 4 years ago

AddressSanitizer: heap-use-after-free /builds/worker/workspace/obj-build/dist/include/nsTArray.h:413:37 in Length

Categories

(Core :: DOM: Core & HTML, defect)

defect
Not set
normal

Tracking

()

VERIFIED FIXED
81 Branch
Tracking Status
firefox-esr68 80+ verified
firefox-esr78 80+ verified
firefox79 --- wontfix
firefox80 + verified
firefox81 --- verified

People

(Reporter: jkratzer, Assigned: sg)

References

(Blocks 1 open bug)

Details

(4 keywords, Whiteboard: [bugmon:],bisected,confirmed,[adv-main80+r][adv-esr68.12+r][adv-esr78.2+r][sec-survey])

Attachments

(2 files)

Attached file testcase.html

Testcase found while fuzzing mozilla-central rev 84b257d07031 (built with --enable-fuzzing). Testcase must be served over HTTP in order to reproduce.

==26094==ERROR: AddressSanitizer: heap-use-after-free on address 0x60f0000617f0 at pc 0x7f82d6863c37 bp 0x7ffd199d96b0 sp 0x7ffd199d96a8
READ of size 8 at 0x60f0000617f0 thread T0 (file:// Content)
    #0 0x7f82d6863c36 in Length /builds/worker/workspace/obj-build/dist/include/nsTArray.h:413:37
    #1 0x7f82d6863c36 in Length /builds/worker/workspace/obj-build/dist/include/nsTObserverArray.h:88:44
    #2 0x7f82d6863c36 in HasMore /builds/worker/workspace/obj-build/dist/include/nsTObserverArray.h:326:55
    #3 0x7f82d6863c36 in nsAutoTObserverArray<mozilla::dom::AbortFollower*, 0ul>::STLIterator<nsAutoTObserverArray<mozilla::dom::AbortFollower*, 0ul>::ForwardIterator, mozilla::dom::AbortFollower*>::operator++() /builds/worker/workspace/obj-build/dist/include/nsTObserverArray.h:435:28
    #4 0x7f82d6863a34 in mozilla::dom::AbortSignalImpl::Abort() /builds/worker/checkouts/gecko/dom/abort/AbortSignal.cpp:30:32
    #5 0x7f82d68634d8 in mozilla::dom::AbortSignal::Abort() /builds/worker/checkouts/gecko/dom/abort/AbortSignal.cpp:77:20
    #6 0x7f82d6863a2c in mozilla::dom::AbortSignalImpl::Abort() /builds/worker/checkouts/gecko/dom/abort/AbortSignal.cpp:31:15
    #7 0x7f82d68634d8 in mozilla::dom::AbortSignal::Abort() /builds/worker/checkouts/gecko/dom/abort/AbortSignal.cpp:77:20
    #8 0x7f82d6f82b74 in mozilla::dom::AbortController_Binding::abort(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) /builds/worker/workspace/obj-build/dom/bindings/AbortControllerBinding.cpp:72:24
    #9 0x7f82d89638b8 in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/dom/bindings/BindingUtils.cpp:3221:13
    #10 0x7f82df0e4f0b in CallJSNative /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:487:13
    #11 0x7f82df0e4f0b in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:579:12
    #12 0x7f82df0e71a8 in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:642:10
    #13 0x7f82df0cd77f in CallFromStack /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:646:10
    #14 0x7f82df0cd77f in Interpret(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:3314:16
    #15 0x7f82df0b0761 in js::RunScript(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:459:10
    #16 0x7f82df0e4fed in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:614:13
    #17 0x7f82df0e71a8 in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:642:10
    #18 0x7f82df0e7486 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:659:8
    #19 0x7f82df45fe30 in js::PromiseObject::create(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSObject*>, bool) /builds/worker/checkouts/gecko/js/src/builtin/Promise.cpp:2444:15
    #20 0x7f82df4a6b4f in PromiseConstructor(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/js/src/builtin/Promise.cpp:2365:7
    #21 0x7f82df0e7dc0 in CallJSNative /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:487:13
    #22 0x7f82df0e7dc0 in CallJSNativeConstructor /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:503:8
    #23 0x7f82df0e7dc0 in InternalConstruct(JSContext*, js::AnyConstructArgs const&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:686:14
    #24 0x7f82df0e7714 in js::ConstructFromStack(JSContext*, JS::CallArgs const&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:732:10
    #25 0x7f82df0bacf2 in Interpret(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:3304:16
    #26 0x7f82df0b0761 in js::RunScript(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:459:10
    #27 0x7f82df0e4fed in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:614:13
    #28 0x7f82df0e71a8 in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:642:10
    #29 0x7f82df0e7486 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:659:8
    #30 0x7f82df286be0 in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/checkouts/gecko/js/src/jsapi.cpp:2831:10
    #31 0x7f82d86153bf in mozilla::dom::Function::Call(mozilla::dom::BindingCallContext&, JS::Handle<JS::Value>, nsTArray<JS::Value> const&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&) /builds/worker/workspace/obj-build/dom/bindings/FunctionBinding.cpp:43:8
    #32 0x7f82d6d7f887 in void mozilla::dom::Function::Call<nsCOMPtr<nsIGlobalObject> >(nsCOMPtr<nsIGlobalObject> const&, nsTArray<JS::Value> const&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&, char const*, mozilla::dom::CallbackObject::ExceptionHandling, JS::Realm*) /builds/worker/workspace/obj-build/dist/include/mozilla/dom/FunctionBinding.h:73:12
    #33 0x7f82d6d7f4e8 in mozilla::dom::CallbackTimeoutHandler::Call(char const*) /builds/worker/checkouts/gecko/dom/base/TimeoutHandler.cpp:167:29
    #34 0x7f82d69b9f1f in nsGlobalWindowInner::RunTimeoutHandler(mozilla::dom::Timeout*, nsIScriptContext*) /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowInner.cpp:6024:38
    #35 0x7f82d6d7abbe in mozilla::dom::TimeoutManager::RunTimeout(mozilla::TimeStamp const&, mozilla::TimeStamp const&, bool) /builds/worker/checkouts/gecko/dom/base/TimeoutManager.cpp:911:44
    #36 0x7f82d6d7950f in mozilla::dom::TimeoutExecutor::MaybeExecute() /builds/worker/checkouts/gecko/dom/base/TimeoutExecutor.cpp:179:11
    #37 0x7f82d6d7d0eb in mozilla::dom::TimeoutExecutor::Run() /builds/worker/checkouts/gecko/dom/base/TimeoutExecutor.cpp:234:5
    #38 0x7f82d2ca828e in mozilla::ThrottledEventQueue::Inner::ExecuteRunnable() /builds/worker/checkouts/gecko/xpcom/threads/ThrottledEventQueue.cpp:254:22
    #39 0x7f82d2c9c48f in mozilla::ThrottledEventQueue::Inner::Executor::Run() /builds/worker/checkouts/gecko/xpcom/threads/ThrottledEventQueue.cpp:81:15
    #40 0x7f82d2c4e0b9 in mozilla::RunnableTask::Run() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:242:16
    #41 0x7f82d2c4a5a5 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:512:26
    #42 0x7f82d2c48462 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:371:15
    #43 0x7f82d2c4889f in mozilla::TaskController::ProcessPendingMTTask(bool) /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:168:36
    #44 0x7f82d2c59ec1 in operator() /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:83:37
    #45 0x7f82d2c59ec1 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_4>::Run() /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:577:5
    #46 0x7f82d2c7ef7c in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1234:14
    #47 0x7f82d2c89e6c in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:513:10
    #48 0x7f82d404a63f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:87:21
    #49 0x7f82d3f2b0e7 in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:334:10
    #50 0x7f82d3f2b0e7 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:327:3
    #51 0x7f82d3f2b0e7 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:309:3
    #52 0x7f82db288c48 in nsBaseAppShell::Run() /builds/worker/checkouts/gecko/widget/nsBaseAppShell.cpp:137:27
    #53 0x7f82dee72516 in XRE_RunAppShell() /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:913:20
    #54 0x7f82d3f2b0e7 in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:334:10
    #55 0x7f82d3f2b0e7 in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:327:3
    #56 0x7f82d3f2b0e7 in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:309:3
    #57 0x7f82dee71aff in XRE_InitChildProcess(int, char**, XREChildData const*) /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:744:34
    #58 0x5587981768b3 in content_process_main /builds/worker/checkouts/gecko/browser/app/../../ipc/contentproc/plugin-container.cpp:56:28
    #59 0x5587981768b3 in main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:303:18
    #60 0x7f82f6d61b96 in __libc_start_main /build/glibc-2ORdQG/glibc-2.27/csu/../csu/libc-start.c:310

0x60f0000617f0 is located 160 bytes inside of 176-byte region [0x60f000061750,0x60f000061800)
freed by thread T0 (file:// Content) here:
    #0 0x55879814394d in free /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:123:3
    #1 0x7f82d2abec82 in SnowWhiteKiller::~SnowWhiteKiller() /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:2419:7
    #2 0x7f82d2abe0d8 in nsCycleCollector::FreeSnowWhite(bool) /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:2607:3
    #3 0x7f82d2ac59bd in nsCycleCollector::BeginCollection(ccType, nsICycleCollectorListener*) /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:3580:3
    #4 0x7f82d2ac51cc in nsCycleCollector::Collect(ccType, js::SliceBudget&, nsICycleCollectorListener*, bool) /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:3409:9
    #5 0x7f82d2ac859e in nsCycleCollector_collect(nsICycleCollectorListener*) /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:3907:28
    #6 0x7f82d6ea4474 in nsJSContext::CycleCollectNow(nsICycleCollectorListener*) /builds/worker/checkouts/gecko/dom/base/nsJSEnvironment.cpp:1533:3
    #7 0x7f82d866dd71 in mozilla::dom::FuzzingFunctions_Binding::cycleCollect(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/obj-build/dom/bindings/FuzzingFunctionsBinding.cpp:68:3
    #8 0x7f82df0e4f0b in CallJSNative /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:487:13
    #9 0x7f82df0e4f0b in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:579:12
    #10 0x7f82df0e71a8 in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:642:10
    #11 0x7f82df0cd77f in CallFromStack /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:646:10
    #12 0x7f82df0cd77f in Interpret(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:3314:16
    #13 0x7f82df0b0761 in js::RunScript(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:459:10
    #14 0x7f82df0e4fed in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:614:13
    #15 0x7f82df0e71a8 in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:642:10
    #16 0x7f82df0e7486 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:659:8
    #17 0x7f82df45fe30 in js::PromiseObject::create(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSObject*>, bool) /builds/worker/checkouts/gecko/js/src/builtin/Promise.cpp:2444:15
    #18 0x7f82df4a6b4f in PromiseConstructor(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/js/src/builtin/Promise.cpp:2365:7
    #19 0x7f82df0e7dc0 in CallJSNative /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:487:13
    #20 0x7f82df0e7dc0 in CallJSNativeConstructor /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:503:8
    #21 0x7f82df0e7dc0 in InternalConstruct(JSContext*, js::AnyConstructArgs const&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:686:14
    #22 0x7f82df0e7714 in js::ConstructFromStack(JSContext*, JS::CallArgs const&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:732:10
    #23 0x7f82df0bacf2 in Interpret(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:3304:16

previously allocated by thread T0 (file:// Content) here:
    #0 0x558798143bcd in malloc /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:145:3
    #1 0x558798179cbd in moz_xmalloc /builds/worker/checkouts/gecko/memory/mozalloc/mozalloc.cpp:52:15
    #2 0x7f82d916ab89 in operator new /builds/worker/workspace/obj-build/dist/include/mozilla/cxxalloc.h:33:10
    #3 0x7f82d916ab89 in mozilla::dom::Request::Request(nsIGlobalObject*, mozilla::SafeRefPtr<mozilla::dom::InternalRequest>, mozilla::dom::AbortSignal*) /builds/worker/checkouts/gecko/dom/fetch/Request.cpp:67:15
    #4 0x7f82d91724d6 in mozilla::SafeRefPtr<mozilla::dom::Request> mozilla::MakeSafeRefPtr<mozilla::dom::Request, nsIGlobalObject*&, mozilla::SafeRefPtr<mozilla::dom::InternalRequest>, RefPtr<mozilla::dom::AbortSignal>&>(nsIGlobalObject*&, mozilla::SafeRefPtr<mozilla::dom::InternalRequest>&&, RefPtr<mozilla::dom::AbortSignal>&) /builds/worker/workspace/obj-build/dist/include/mozilla/dom/SafeRefPtr.h:382:25
    #5 0x7f82d916f30d in mozilla::dom::Request::Constructor(nsIGlobalObject*, JSContext*, mozilla::dom::RequestOrUSVString const&, mozilla::dom::RequestInit const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/fetch/Request.cpp:609:7
    #6 0x7f82d913d412 in mozilla::dom::Request::Constructor(mozilla::dom::GlobalObject const&, mozilla::dom::RequestOrUSVString const&, mozilla::dom::RequestInit const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/fetch/Request.cpp:268:10
    #7 0x7f82d913b73d in mozilla::dom::FetchRequest(nsIGlobalObject*, mozilla::dom::RequestOrUSVString const&, mozilla::dom::RequestInit const&, mozilla::dom::CallerType, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/fetch/Fetch.cpp:454:7
    #8 0x7f82d8143ffd in fetch /builds/worker/workspace/obj-build/dom/bindings/WindowBinding.cpp:19041:60
    #9 0x7f82d8143ffd in mozilla::dom::Window_Binding::fetch_promiseWrapper(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) /builds/worker/workspace/obj-build/dom/bindings/WindowBinding.cpp:19057:13
    #10 0x7f82d8967b82 in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::MaybeCrossOriginObjectThisPolicy, mozilla::dom::binding_detail::ConvertExceptionsToPromises>(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/dom/bindings/BindingUtils.cpp:3221:13
    #11 0x7f82df0e4f0b in CallJSNative /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:487:13
    #12 0x7f82df0e4f0b in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:579:12
    #13 0x7f82df0e71a8 in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:642:10
    #14 0x7f82df0cd77f in CallFromStack /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:646:10
    #15 0x7f82df0cd77f in Interpret(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:3314:16
    #16 0x7f82df0b0761 in js::RunScript(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:459:10
    #17 0x7f82df0e4fed in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:614:13
    #18 0x7f82df0e71a8 in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:642:10
    #19 0x7f82df0e7486 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:659:8
    #20 0x7f82df742e30 in js::CallSelfHostedFunction(JSContext*, JS::Handle<js::PropertyName*>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /builds/worker/checkouts/gecko/js/src/vm/SelfHosting.cpp:1719:10
    #21 0x7f82df36779c in AsyncFunctionResume(JSContext*, JS::Handle<js::AsyncFunctionGeneratorObject*>, ResumeKind, JS::Handle<JS::Value>) /builds/worker/checkouts/gecko/js/src/vm/AsyncFunction.cpp:128:8
    #22 0x7f82df4b0d61 in AsyncFunctionPromiseReactionJob /builds/worker/checkouts/gecko/js/src/builtin/Promise.cpp:1700:10
    #23 0x7f82df4b0d61 in PromiseReactionJob(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/js/src/builtin/Promise.cpp:1852:12
    #24 0x7f82df0e4f0b in CallJSNative /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:487:13
    #25 0x7f82df0e4f0b in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:579:12

SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/workspace/obj-build/dist/include/nsTArray.h:413:37 in Length
Shadow bytes around the buggy address:
  0x0c1e800042a0: fd fd fd fd fd fd fa fa fa fa fa fa fa fa 00 00
  0x0c1e800042b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c1e800042c0: 00 00 00 00 fa fa fa fa fa fa fa fa fd fd fd fd
  0x0c1e800042d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c1e800042e0: fd fa fa fa fa fa fa fa fa fa fd fd fd fd fd fd
=>0x0c1e800042f0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd
  0x0c1e80004300: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x0c1e80004310: fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa
  0x0c1e80004320: fa fa fa fa fa fa 00 00 00 00 00 00 00 00 00 00
  0x0c1e80004330: 00 00 00 00 00 00 00 00 00 00 04 fa fa fa fa fa
  0x0c1e80004340: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
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
  Shadow gap:              cc
==26094==ABORTING
Flags: in-testsuite?

(Assuming this was meant to be filed as security)

Group: core-security
Group: core-security → dom-core-security

I see that something changed recently around ForwardIterator, maybe related?

Flags: needinfo?(sgiesecke)

There was a change in the implementation of AbortSignalImpl::Abort regarding the iteration, but AFAIU this is not related to this issue. The UAF does not happen when accessing an array element, but the array (length) itself. It seems that the AbortSignalImpl is being destroyed (and deallocated) during the iteration, which destroys the whole mFollowers array.

Maybe we need to add RefPtr pinThis = this; in the AbortSignalImpl::Abort?

Jason, can we get a regression window?

Flags: needinfo?(sgiesecke) → needinfo?(jkratzer)
Keywords: bugmon
Whiteboard: [bugmon:confirm] → [bugmon:confirmed]
Bugmon Analysis:
Unable to reproduce bug using the following builds:
> mozilla-central 20200804091327-7cb90fa4f485
> mozilla-central 20200803033015-f6a3b097f8af
Removing bugmon keyword as no further action possible.
Please review the bug and re-add the keyword for further analysis.

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

Bugmon Analysis:
Unable to reproduce bug using the following builds:

mozilla-central 20200804091327-7cb90fa4f485
mozilla-central 20200803033015-f6a3b097f8af
Removing bugmon keyword as no further action possible.
Please review the bug and re-add the keyword for further analysis.

Hm, it's not clear to me what this means. Does it mean that the bug has been fixed in the meantime already?

No, it still reproduces. Looks like Bugmon is confused here. I'm working on figuring out why. I'll have a bisection here shortly.

Flags: needinfo?(jkratzer)
Whiteboard: [bugmon:confirmed] → [bugmon:],bisected,confirmed
Apologies for the delay.  Looks like bugmon was using outdated prefs.  The attached testcase requires the `dom.fetchObserver.enabled` pref enabled.
Bugmon Analysis:
Verified bug as reproducible on mozilla-central 20200804091327-7cb90fa4f485.
Failed to bisect testcase (Start build crashes!):
> Start: e8b7c48d4e7ed1b63aeedff379b51e566ea499d9 (20191107015224)
> End: f6a3b097f8af440a142b02450a2cdaa978fdde9f (20200803033015)
> BuildFlags: BuildFlags(asan=True, tsan=False, debug=False, fuzzing=True, coverage=False, valgrind=False)

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

Apologies for the delay. Looks like bugmon was using outdated prefs. The
attached testcase requires the dom.fetchObserver.enabled pref enabled.

Ah, that's good to know, I wasn't able to reproduce this locally without the pref.

With the pref set, I can reproduce the crash. If I add the line as suggested in comment 3, it does no longer crash, but it doesn't seem to terminate. There are several JavaScript error: http://localhost:8000/1656957.html, line 32: TypeError: e2.waitUntil is not a function outputs.

Assignee: nobody → sgiesecke
Status: NEW → ASSIGNED
Keywords: sec-high

Comment on attachment 9168158 [details]
Bug 1656957 - Pin AbortSignalImpl instance while signaling followers. r=baku

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: Unsure, OTOH it is obvious that an abort follower that removes the signal itself could cause a UAF, and I don't see any way to hide this, but I am not sure how easy it is to construct an exploit based on that.
  • Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: Yes
  • Which older supported branches are affected by this flaw?: all
  • If not all supported branches, which bug introduced the flaw?: None
  • Do you have backports for the affected branches?: Yes
  • If not, how different, hard to create, and risky will they be?:
  • How likely is this patch to cause regressions; how much testing does it need?: Unlikely, it only adds a temporary strong reference to the AbortSignalImpl instance.
Attachment #9168158 - Flags: sec-approval?

Comment on attachment 9168158 [details]
Bug 1656957 - Pin AbortSignalImpl instance while signaling followers. r=baku

Approved to land 8/18 and to request uplift to other branches.

Attachment #9168158 - Flags: sec-approval?
Attachment #9168158 - Flags: sec-approval+
Attachment #9168158 - Flags: approval-mozilla-esr78?
Attachment #9168158 - Flags: approval-mozilla-esr68?
Attachment #9168158 - Flags: approval-mozilla-beta?

8/18 is the day after we build the release candidate for 80, what's the reasoning for that date?

Flags: needinfo?(tom)

I was picking a date two days before the soft freeze as I thought that would be a good timeframe for "Close to release but with a little bit of time to handle unexpected problems". So I guess a better date would be today or tomorrow.

If the RC build date is the marker for "Get everything in befoe this date" it would be helpful to have that on the Release Calendar =)

Flags: needinfo?(tom)

Comment on attachment 9168158 [details]
Bug 1656957 - Pin AbortSignalImpl instance while signaling followers. r=baku

https://hg.mozilla.org/integration/autoland/rev/c9db7aaa4eda8702b4bf9708a14dc971eb7138c3

Approved for 80.8b8, 78.2esr, and 68.12esr also.

Attachment #9168158 - Flags: approval-mozilla-esr78?
Attachment #9168158 - Flags: approval-mozilla-esr78+
Attachment #9168158 - Flags: approval-mozilla-esr68?
Attachment #9168158 - Flags: approval-mozilla-esr68+
Attachment #9168158 - Flags: approval-mozilla-beta?
Attachment #9168158 - Flags: approval-mozilla-beta+

(In reply to Tom Ritter [:tjr] (ni? for response to sec-[advisories/bounties/ratings/cves]) from comment #14)

If the RC build date is the marker for "Get everything in befoe this date" it would be helpful to have that on the Release Calendar =)

By definition, an RC build is something we create with the intent to release it. I think it's reasonable to assume that changes aren't likely to be taken after that point.

Group: dom-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Target Milestone: --- → 81 Branch
QA Whiteboard: [post-critsmash-triage]
Flags: qe-verify+

Reproduced the crash with fuzzing mozilla-central rev 84b257d07031 and the attached test case served with HTTP and dom.fetchObserver.enabled pref enabled on Ubuntu 18.04.
There are no crashes with 81.0a1(20200813213942), 80.0b8 (20200813191622), 68.12esr (20200813214232) and 78.2.0esr (20200813212801) on Ubuntu 18.04.

Unfortunately, I still see multiple JavaScript error: http://127.0.0.1/, line 33: TypeError: e2.waitUntil is not a function/JavaScript error: http://127.0.0.1/, line 31: ReferenceError: FuzzingFunctions is not defined errors output when loading the test case. I see that is mentioned in comment 9 too but I just want to make sure that this is expected. Thank you!

Flags: needinfo?(sgiesecke)
QA Whiteboard: [post-critsmash-triage] → [post-critsmash-triage] [qa-triaged]

(In reply to Alexandru Trif, QA [:atrif] from comment #21)

Reproduced the crash with fuzzing mozilla-central rev 84b257d07031 and the attached test case served with HTTP and dom.fetchObserver.enabled pref enabled on Ubuntu 18.04.
There are no crashes with 81.0a1(20200813213942), 80.0b8 (20200813191622), 68.12esr (20200813214232) and 78.2.0esr (20200813212801) on Ubuntu 18.04.

Unfortunately, I still see multiple JavaScript error: http://127.0.0.1/, line 33: TypeError: e2.waitUntil is not a function/JavaScript error: http://127.0.0.1/, line 31: ReferenceError: FuzzingFunctions is not defined errors output when loading the test case. I see that is mentioned in comment 9 too but I just want to make sure that this is expected. Thank you!

JavaScript error: http://127.0.0.1/, line 31: ReferenceError: FuzzingFunctions is not defined probably means that fuzzing.enabled is not set to true.

I'm not sure what causes: JavaScript error: http://127.0.0.1/, line 33: TypeError: e2.waitUntil is not a function, but that was already happening in the original execution, so that's expected.

Flags: needinfo?(sgiesecke)

(In reply to Simon Giesecke [:sg] [he/him] from comment #22)

JavaScript error: http://127.0.0.1/, line 31: ReferenceError: FuzzingFunctions is not defined probably means that fuzzing.enabled is not set to true.

I'm not sure what causes: JavaScript error: http://127.0.0.1/, line 33: TypeError: e2.waitUntil is not a function, but that was already happening in the original execution, so that's expected.

Thank you, Simon!
Verified again with 81.0a1(20200813213942), 80.0b8 (20200813191622), 68.12esr (20200813214232) and 78.2.0esr (20200813212801) on Ubuntu 18.04 and there are no tab crashes while loading the test case with dom.fetchObserver.enabled and fuzzing.enabled prefs set on true.

Ok, great!

It's still interesting that the crash was reproducible with the test case even with fuzzing.enabled not being true. I still need to add a test case after a while, and will check then again if this can be reproduced even with a non-fuzzing build deterministically.

Whiteboard: [bugmon:],bisected,confirmed → [bugmon:],bisected,confirmed,[adv-main80+r]
Whiteboard: [bugmon:],bisected,confirmed,[adv-main80+r] → [bugmon:],bisected,confirmed,[adv-main80+r][adv-esr68.12+r]
Whiteboard: [bugmon:],bisected,confirmed,[adv-main80+r][adv-esr68.12+r] → [bugmon:],bisected,confirmed,[adv-main80+r][adv-esr68.12+r][adv-esr78.2+r]

As part of a security bug pattern analysis, we are requesting your help with a high level analysis of this bug. It is our hope to develop static analysis (or potentially runtime/dynamic analysis) in the future to identify classes of bugs.

Please visit this google form to reply.

Flags: needinfo?(sgiesecke)
Whiteboard: [bugmon:],bisected,confirmed,[adv-main80+r][adv-esr68.12+r][adv-esr78.2+r] → [bugmon:],bisected,confirmed,[adv-main80+r][adv-esr68.12+r][adv-esr78.2+r][sec-survey]
Alias: CVE-2020-15669
Blocks: 1660954

Hm, I'm having trouble reproducing this.

Given c9db7aaa4eda is the fix and 45e64fba31ca96328a058409a98a6f492fca50fa is its parent, updating to 45e64fba31ca96328a058409a98a6f492fca50fa, doing ./mach build with a debug-oriented mozconfig, then downloading testcase.html into a directory as abortsignal-testcase.html then serving its containing directory as localhost:8080 and then loading the file using ./mach run --setpref dom.fetchObserver.enabled=true --setpref fuzzing.enabled=true http://localhost:8080/abortsignal-testcase.html doesn't work. What am I missing?

Is my doing a debug build throwing off everything? I also see subresource integrity mismatch warnings in the console -- is something wrong with that? Or something else entirely? (I'm trying to verify the patch for bug 1660954 doesn't break this, by reproducing the crash with one rev, then backporting that patch to verify it too makes the crash go away.)

I also see a bunch of errors about FuzzingFunctions is not defined, but about:config definitely says the two set prefs, are set.

Oh bah, I need to tack on --enable-fuzzing when building, judging from Searchfox. Will comment here if that's not adequate to repro.

Yeah, never mind, with that in place the one rev crashes, the rev with the patch here and my followup patch in place passes. I'm good now!

Group: core-security-release
Flags: needinfo?(simon.giesecke)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: