Closed Bug 1175278 Opened 9 years ago Closed 9 years ago

ZDI-CAN-2938: Mozilla Firefox nsIPresShell Use-After-Free Remote Code Execution Vulnerability

Categories

(Core :: Graphics: Canvas2D, defect)

38 Branch
defect
Not set
normal

Tracking

()

VERIFIED DUPLICATE of bug 1164766
Tracking Status
firefox38 --- wontfix
firefox38.0.5 --- wontfix
firefox39 --- wontfix
firefox40 + verified
firefox41 + fixed
firefox42 + fixed
firefox-esr31 --- wontfix
firefox-esr38 40+ verified
b2g-v2.0 --- affected
b2g-v2.0M --- affected
b2g-v2.1 --- affected
b2g-v2.1S --- affected
b2g-v2.2 --- affected
b2g-master --- affected

People

(Reporter: abillings, Unassigned)

References

Details

(Keywords: crash, regression, sec-critical, Whiteboard: working on fix in bug 1164766. ZDI will disclose October 2015 (Firefox 41))

Attachments

(6 files)

The following bug report was received from ZDI and Ucha Gobejishvili. 


ZDI-CAN-2938: Mozilla Firefox nsIPresShell Use-After-Free Remote Code Execution Vulnerability


-- CVSS -----------------------------------------

7.5, AV:N/AC:L/Au:N/C:P/I:P/A:P


-- ABSTRACT -------------------------------------

HP's Zero Day Initiative has identified a vulnerability affecting the following products:

  Mozilla Firefox


-- VULNERABILITY DETAILS ------------------------

```
Tested on: source build of mozilla-release (current 38.0.5)
Platform tested: ubuntu linux 14.04 LTS

This is a gdb session with address sanitizer output to demonstrate the use-after-free vulnerability.

=================================================================
==5279==ERROR: AddressSanitizer: heap-use-after-free on address 0x6170003e5c18 at pc 0x7fffe90defd9 bp 0x7fffffff6030 sp 0x7fffffff6028
READ of size 8 at 0x6170003e5c18 thread T0
    #0 0x7fffe90defd8 in nsIPresShell::StyleSet() const /home/researcher/source/firefox/objdir-ff-asan/dom/canvas/../../dist/include/nsIPresShell.h:319
    #1 0x7fffe90defd8 in mozilla::dom::GetFontStyleContext(mozilla::dom::Element*, nsAString_internal const&, nsIPresShell*, nsAString_internal&, mozilla::ErrorResult&) /home/researcher/source/firefox/dom/canvas/CanvasRenderingContext2D.cpp:2174
    #2 0x7fffe90e9435 in mozilla::dom::CanvasRenderingContext2D::SetFont(nsAString_internal const&, mozilla::ErrorResult&) /home/researcher/source/firefox/dom/canvas/CanvasRenderingContext2D.cpp:2994
    #3 0x7fffe90edb6a in mozilla::dom::CanvasRenderingContext2D::GetCurrentFontStyle() /home/researcher/source/firefox/dom/canvas/CanvasRenderingContext2D.cpp:3808
    #4 0x7fffe871782d in mozilla::dom::CanvasRenderingContext2D::GetFont() /home/researcher/source/firefox/objdir-ff-asan/dom/bindings/../../dist/include/mozilla/dom/CanvasRenderingContext2D.h:737
    #5 0x7fffe871782d in mozilla::dom::CanvasRenderingContext2D::GetFont(nsAString_internal&) /home/researcher/source/firefox/objdir-ff-asan/dom/bindings/../../dist/include/mozilla/dom/CanvasRenderingContext2D.h:340
    #6 0x7fffe86b35e9 in mozilla::dom::DOMString::operator nsString&() /home/researcher/source/firefox/objdir-ff-asan/dom/bindings/../../dist/include/mozilla/dom/CanvasRenderingContext2D.h:443
    #7 0x7fffe86b35e9 in mozilla::dom::CanvasRenderingContext2DBinding::get_mozTextStyle(JSContext*, JS::Handle<JSObject*>, mozilla::dom::CanvasRenderingContext2D*, JSJitGetterCallArgs) /home/researcher/source/firefox/objdir-ff-asan/dom/bindings/./CanvasRenderingContext2DBinding.cpp:4924
    #8 0x7fffe90ac7a2 in mozilla::dom::GenericBindingGetter(JSContext*, unsigned int, JS::Value*) /home/researcher/source/firefox/dom/bindings/BindingUtils.cpp:2467
    #9 0x7fffed703d3e in js::CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), JS::CallArgs const&) /home/researcher/source/firefox/js/src/jscntxtinlines.h:226
    #10 0x7fffed703d3e in js::Invoke(JSContext*, JS::CallArgs, js::MaybeConstruct) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:498
    #11 0x7fffed6b8bd8 in js::Invoke(JSContext*, JS::Value const&, JS::Value const&, unsigned int, JS::Value const*, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:554
    #12 0x7fffed7af8df in js::InvokeGetterOrSetter(JSContext*, JSObject*, JS::Value, unsigned int, JS::Value*, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:624
    #13 0x7fffed7af8df in CallGetter(JSContext*, JS::Handle<JSObject*>, JS::Handle<js::Shape*>, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/NativeObject.cpp:1626
    #14 0x7fffed7af8df in _ZL19GetExistingPropertyILN2js7AllowGCE1EEbP9JSContextNS0_11MaybeRootedIP8JSObjectXT_EE10HandleTypeENS4_IPNS0_12NativeObjectEXT_EE10HandleTypeENS4_IPNS0_5ShapeEXT_EE10HandleTypeENS4_IN2JS5ValueEXT_EE17MutableHandleTypeE /home/researcher/source/firefox/js/src/vm/NativeObject.cpp:1673
    #15 0x7fffed7b108a in _ZL23NativeGetPropertyInlineILN2js7AllowGCE1EEbP9JSContextNS0_11MaybeRootedIPNS0_12NativeObjectEXT_EE10HandleTypeENS4_IP8JSObjectXT_EE10HandleTypeENS4_I4jsidXT_EE10HandleTypeE12IsNameLookupNS4_IN2JS5ValueEXT_EE17MutableHandleTypeE /home/researcher/source/firefox/js/src/vm/NativeObject.cpp:1875:20
    #16 0x7fffed756ffd in js::NativeGetProperty(JSContext*, JS::Handle<js::NativeObject*>, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/NativeObject.cpp:1909:12
    #17 0x7fffed756ffd in js::GetProperty(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/NativeObject.h:1407
    #18 0x7fffed756ffd in GetPropertyOperation(JSContext*, js::InterpreterFrame*, JS::Handle<JSScript*>, unsigned char*, JS::MutableHandle<JS::Value>, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:256
    #19 0x7fffed756ffd in Interpret(JSContext*, js::RunState&) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:2419
    #20 0x7fffed736f20 in js::RunScript(JSContext*, js::RunState&) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:448
    #21 0x7fffed772e98 in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JSObject&, JS::Value const&, js::ExecuteType, js::AbstractFramePtr, JS::Value*) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:654
    #22 0x7fffed7738e7 in js::Execute(JSContext*, JS::Handle<JSScript*>, JSObject&, JS::Value*) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:690
    #23 0x7fffee75142c in Evaluate(JSContext*, JS::Handle<JSObject*>, JS::ReadOnlyCompileOptions const&, JS::SourceBufferHolder&, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/jsapi.cpp:4072
    #24 0x7fffee751e6a in Evaluate(JSContext*, JS::AutoObjectVector&, JS::ReadOnlyCompileOptions const&, JS::SourceBufferHolder&, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/jsapi.cpp:4099
    #25 0x7fffee751e6a in JS::Evaluate(JSContext*, JS::AutoObjectVector&, JS::ReadOnlyCompileOptions const&, JS::SourceBufferHolder&, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/jsapi.cpp:4154
    #26 0x7fffe798d1b6 in nsJSUtils::EvaluateString(JSContext*, JS::SourceBufferHolder&, JS::Handle<JSObject*>, JS::CompileOptions&, nsJSUtils::EvaluateOptions const&, JS::MutableHandle<JS::Value>, void**) /home/researcher/source/firefox/dom/base/nsJSUtils.cpp:265
    #27 0x7fffe798c6d6 in nsJSUtils::EvaluateString(JSContext*, nsAString_internal const&, JS::Handle<JSObject*>, JS::CompileOptions&, nsJSUtils::EvaluateOptions const&, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/dom/base/nsJSUtils.cpp:186
    #28 0x7fffe798e55e in nsJSUtils::EvaluateString(JSContext*, nsAString_internal const&, JS::Handle<JSObject*>, JS::CompileOptions&) /home/researcher/source/firefox/dom/base/nsJSUtils.cpp:323
    #29 0x7fffe75af033 in nsGlobalWindow::RunTimeoutHandler(nsTimeout*, nsIScriptContext*) /home/researcher/source/firefox/dom/base/nsGlobalWindow.cpp:12303
    #30 0x7fffe7590f1c in nsGlobalWindow::RunTimeout(nsTimeout*) /home/researcher/source/firefox/dom/base/nsGlobalWindow.cpp:12534
    #31 0x7fffe75ae21b in nsGlobalWindow::TimerCallback(nsITimer*, void*) /home/researcher/source/firefox/dom/base/nsGlobalWindow.cpp:12781
    #32 0x7fffe545348f in nsTimerImpl::Fire() /home/researcher/source/firefox/xpcom/threads/nsTimerImpl.cpp:631
    #33 0x7fffe5453f14 in nsTimerEvent::Run() /home/researcher/source/firefox/xpcom/threads/nsTimerImpl.cpp:724
    #34 0x7fffe54489e1 in nsThread::ProcessNextEvent(bool, bool*) /home/researcher/source/firefox/xpcom/threads/nsThread.cpp:855
    #35 0x7fffe54b8f80 in NS_ProcessNextEvent(nsIThread*, bool) /home/researcher/source/firefox/xpcom/glue/nsThreadUtils.cpp:265
    #36 0x7fffe5e160a9 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /home/researcher/source/firefox/ipc/glue/MessagePump.cpp:140
    #37 0x7fffe5d99476 in MessageLoop::RunInternal() /home/researcher/source/firefox/ipc/chromium/src/base/message_loop.cc:233
    #38 0x7fffe5d98f1b in MessageLoop::RunHandler() /home/researcher/source/firefox/ipc/chromium/src/base/message_loop.cc:226
    #39 0x7fffe5d98f1b in MessageLoop::Run() /home/researcher/source/firefox/ipc/chromium/src/base/message_loop.cc:200
    #40 0x7fffea597b1a in nsBaseAppShell::Run() /home/researcher/source/firefox/widget/nsBaseAppShell.cpp:164
    #41 0x7fffebf144e9 in nsAppStartup::Run() /home/researcher/source/firefox/toolkit/components/startup/nsAppStartup.cpp:281
    #42 0x7fffec0050ef in XREMain::XRE_mainRun() /home/researcher/source/firefox/toolkit/xre/nsAppRunner.cpp:4228
    #43 0x7fffec005e3a in XREMain::XRE_main(int, char**, nsXREAppData const*) /home/researcher/source/firefox/toolkit/xre/nsAppRunner.cpp:4308
    #44 0x7fffec006ada in XRE_main /home/researcher/source/firefox/toolkit/xre/nsAppRunner.cpp:4527
    #45 0x47adab in do_main(int, char**, nsIFile*) /home/researcher/source/firefox/browser/app/nsBrowserApp.cpp:294
    #46 0x47adab in main /home/researcher/source/firefox/browser/app/nsBrowserApp.cpp:667
    #47 0x7ffff6bebec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)
    #48 0x47a11a in _start (/home/researcher/source/firefox/objdir-ff-asan/dist/bin/firefox+0x47a11a)

0x6170003e5c18 is located 24 bytes inside of 696-byte region [0x6170003e5c00,0x6170003e5eb8)
freed by thread T0 here:
    #0 0x4607cf in __interceptor_free /home/researcher/source/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:64
    #1 0x7fffead812bd in PresShell::Release() /home/researcher/source/firefox/layout/base/nsPresShell.cpp:807
    #2 0x7fffea9c6c15 in nsComputedDOMStyle::GetStyleContextForElement(mozilla::dom::Element*, nsIAtom*, nsIPresShell*, nsComputedDOMStyle::StyleType) /home/researcher/source/firefox/layout/style/nsComputedDOMStyle.cpp:413
    #3 0x7fffe90dea29 in mozilla::dom::GetFontParentStyleContext(mozilla::dom::Element*, nsIPresShell*, mozilla::ErrorResult&) /home/researcher/source/firefox/dom/canvas/CanvasRenderingContext2D.cpp:2099
    #4 0x7fffe90dea29 in mozilla::dom::GetFontStyleContext(mozilla::dom::Element*, nsAString_internal const&, nsIPresShell*, nsAString_internal&, mozilla::ErrorResult&) /home/researcher/source/firefox/dom/canvas/CanvasRenderingContext2D.cpp:2162
    #5 0x7fffe90e9435 in mozilla::dom::CanvasRenderingContext2D::SetFont(nsAString_internal const&, mozilla::ErrorResult&) /home/researcher/source/firefox/dom/canvas/CanvasRenderingContext2D.cpp:2994
    #6 0x7fffe90edb6a in mozilla::dom::CanvasRenderingContext2D::GetCurrentFontStyle() /home/researcher/source/firefox/dom/canvas/CanvasRenderingContext2D.cpp:3808
    #7 0x7fffe871782d in mozilla::dom::CanvasRenderingContext2D::GetFont() /home/researcher/source/firefox/objdir-ff-asan/dom/bindings/../../dist/include/mozilla/dom/CanvasRenderingContext2D.h:737
    #8 0x7fffe871782d in mozilla::dom::CanvasRenderingContext2D::GetFont(nsAString_internal&) /home/researcher/source/firefox/objdir-ff-asan/dom/bindings/../../dist/include/mozilla/dom/CanvasRenderingContext2D.h:340
    #9 0x7fffe86b35e9 in mozilla::dom::DOMString::operator nsString&() /home/researcher/source/firefox/objdir-ff-asan/dom/bindings/../../dist/include/mozilla/dom/CanvasRenderingContext2D.h:443
    #10 0x7fffe86b35e9 in mozilla::dom::CanvasRenderingContext2DBinding::get_mozTextStyle(JSContext*, JS::Handle<JSObject*>, mozilla::dom::CanvasRenderingContext2D*, JSJitGetterCallArgs) /home/researcher/source/firefox/objdir-ff-asan/dom/bindings/./CanvasRenderingContext2DBinding.cpp:4924
    #11 0x7fffe90ac7a2 in mozilla::dom::GenericBindingGetter(JSContext*, unsigned int, JS::Value*) /home/researcher/source/firefox/dom/bindings/BindingUtils.cpp:2467
    #12 0x7fffed703d3e in js::CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), JS::CallArgs const&) /home/researcher/source/firefox/js/src/jscntxtinlines.h:226
    #13 0x7fffed703d3e in js::Invoke(JSContext*, JS::CallArgs, js::MaybeConstruct) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:498
    #14 0x7fffed6b8bd8 in js::Invoke(JSContext*, JS::Value const&, JS::Value const&, unsigned int, JS::Value const*, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:554
    #15 0x7fffed7af8df in js::InvokeGetterOrSetter(JSContext*, JSObject*, JS::Value, unsigned int, JS::Value*, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:624
    #16 0x7fffed7af8df in CallGetter(JSContext*, JS::Handle<JSObject*>, JS::Handle<js::Shape*>, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/NativeObject.cpp:1626
    #17 0x7fffed7af8df in _ZL19GetExistingPropertyILN2js7AllowGCE1EEbP9JSContextNS0_11MaybeRootedIP8JSObjectXT_EE10HandleTypeENS4_IPNS0_12NativeObjectEXT_EE10HandleTypeENS4_IPNS0_5ShapeEXT_EE10HandleTypeENS4_IN2JS5ValueEXT_EE17MutableHandleTypeE /home/researcher/source/firefox/js/src/vm/NativeObject.cpp:1673
    #18 0x7fffed7b108a in _ZL23NativeGetPropertyInlineILN2js7AllowGCE1EEbP9JSContextNS0_11MaybeRootedIPNS0_12NativeObjectEXT_EE10HandleTypeENS4_IP8JSObjectXT_EE10HandleTypeENS4_I4jsidXT_EE10HandleTypeE12IsNameLookupNS4_IN2JS5ValueEXT_EE17MutableHandleTypeE /home/researcher/source/firefox/js/src/vm/NativeObject.cpp:1875:20
    #19 0x7fffed756ffd in js::NativeGetProperty(JSContext*, JS::Handle<js::NativeObject*>, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/NativeObject.cpp:1909:12
    #20 0x7fffed756ffd in js::GetProperty(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/NativeObject.h:1407
    #21 0x7fffed756ffd in GetPropertyOperation(JSContext*, js::InterpreterFrame*, JS::Handle<JSScript*>, unsigned char*, JS::MutableHandle<JS::Value>, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:256
    #22 0x7fffed756ffd in Interpret(JSContext*, js::RunState&) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:2419
    #23 0x7fffed736f20 in js::RunScript(JSContext*, js::RunState&) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:448
    #24 0x7fffed772e98 in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JSObject&, JS::Value const&, js::ExecuteType, js::AbstractFramePtr, JS::Value*) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:654
    #25 0x7fffed7738e7 in js::Execute(JSContext*, JS::Handle<JSScript*>, JSObject&, JS::Value*) /home/researcher/source/firefox/js/src/vm/Interpreter.cpp:690
    #26 0x7fffee75142c in Evaluate(JSContext*, JS::Handle<JSObject*>, JS::ReadOnlyCompileOptions const&, JS::SourceBufferHolder&, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/jsapi.cpp:4072
    #27 0x7fffee751e6a in Evaluate(JSContext*, JS::AutoObjectVector&, JS::ReadOnlyCompileOptions const&, JS::SourceBufferHolder&, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/jsapi.cpp:4099
    #28 0x7fffee751e6a in JS::Evaluate(JSContext*, JS::AutoObjectVector&, JS::ReadOnlyCompileOptions const&, JS::SourceBufferHolder&, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/js/src/jsapi.cpp:4154
    #29 0x7fffe798d1b6 in nsJSUtils::EvaluateString(JSContext*, JS::SourceBufferHolder&, JS::Handle<JSObject*>, JS::CompileOptions&, nsJSUtils::EvaluateOptions const&, JS::MutableHandle<JS::Value>, void**) /home/researcher/source/firefox/dom/base/nsJSUtils.cpp:265
    #30 0x7fffe798c6d6 in nsJSUtils::EvaluateString(JSContext*, nsAString_internal const&, JS::Handle<JSObject*>, JS::CompileOptions&, nsJSUtils::EvaluateOptions const&, JS::MutableHandle<JS::Value>) /home/researcher/source/firefox/dom/base/nsJSUtils.cpp:186
    #31 0x7fffe798e55e in nsJSUtils::EvaluateString(JSContext*, nsAString_internal const&, JS::Handle<JSObject*>, JS::CompileOptions&) /home/researcher/source/firefox/dom/base/nsJSUtils.cpp:323
    #32 0x7fffe75af033 in nsGlobalWindow::RunTimeoutHandler(nsTimeout*, nsIScriptContext*) /home/researcher/source/firefox/dom/base/nsGlobalWindow.cpp:12303
    #33 0x7fffe7590f1c in nsGlobalWindow::RunTimeout(nsTimeout*) /home/researcher/source/firefox/dom/base/nsGlobalWindow.cpp:12534
    #34 0x7fffe75ae21b in nsGlobalWindow::TimerCallback(nsITimer*, void*) /home/researcher/source/firefox/dom/base/nsGlobalWindow.cpp:12781
    #35 0x7fffe545348f in nsTimerImpl::Fire() /home/researcher/source/firefox/xpcom/threads/nsTimerImpl.cpp:631
    #36 0x7fffe5453f14 in nsTimerEvent::Run() /home/researcher/source/firefox/xpcom/threads/nsTimerImpl.cpp:724
    #37 0x7fffe54489e1 in nsThread::ProcessNextEvent(bool, bool*) /home/researcher/source/firefox/xpcom/threads/nsThread.cpp:855
    #38 0x7fffe54b8f80 in NS_ProcessNextEvent(nsIThread*, bool) /home/researcher/source/firefox/xpcom/glue/nsThreadUtils.cpp:265
    #39 0x7fffe5e160a9 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /home/researcher/source/firefox/ipc/glue/MessagePump.cpp:140

previously allocated by thread T0 here:
    #0 0x4609e7 in __interceptor_malloc /home/researcher/source/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74
    #1 0x7ffff7f95852 in moz_xmalloc /home/researcher/source/firefox/memory/mozalloc/mozalloc.cpp:52
    #2 0x7fffe785118a in operator new(unsigned long) /home/researcher/source/firefox/objdir-ff-asan/dom/base/../../dist/include/mozilla/mozalloc.h:209
    #3 0x7fffe785118a in PresShell::operator new(unsigned long) /home/researcher/source/firefox/layout/base/nsPresShell.h:68
    #4 0x7fffe785118a in nsDocument::doCreateShell(nsPresContext*, nsViewManager*, nsStyleSet*, nsCompatibility) /home/researcher/source/firefox/dom/base/nsDocument.cpp:3880
    #5 0x7fffe96741e1 in nsHTMLDocument::CreateShell(nsPresContext*, nsViewManager*, nsStyleSet*) /home/researcher/source/firefox/dom/html/nsHTMLDocument.cpp:288
    #6 0x7fffeace2f53 in nsDocumentViewer::InitPresentationStuff(bool) /home/researcher/source/firefox/layout/base/nsDocumentViewer.cpp:643
    #7 0x7fffeace26d2 in nsDocumentViewer::InitInternal(nsIWidget*, nsISupports*, nsIntRect const&, bool, bool, bool) /home/researcher/source/firefox/layout/base/nsDocumentViewer.cpp:899
    #8 0x7fffeace168d in nsDocumentViewer::Init(nsIWidget*, nsIntRect const&) /home/researcher/source/firefox/layout/base/nsDocumentViewer.cpp:625
    #9 0x7fffeb8cab8e in nsDocShell::SetupNewViewer(nsIContentViewer*) /home/researcher/source/firefox/docshell/base/nsDocShell.cpp:9261
    #10 0x7fffeb8c99af in nsDocShell::Embed(nsIContentViewer*, char const*, nsISupports*) /home/researcher/source/firefox/docshell/base/nsDocShell.cpp:7168
    #11 0x7fffeb8759d0 in nsDocShell::CreateContentViewer(char const*, nsIRequest*, nsIStreamListener**) /home/researcher/source/firefox/docshell/base/nsDocShell.cpp:9069
    #12 0x7fffeb873002 in nsDSURIContentListener::DoContent(char const*, bool, nsIRequest*, nsIStreamListener**, bool*) /home/researcher/source/firefox/docshell/base/nsDSURIContentListener.cpp:141
    #13 0x7fffe6c8fb86 in nsDocumentOpenInfo::TryContentListener(nsIURIContentListener*, nsIChannel*) /home/researcher/source/firefox/uriloader/base/nsURILoader.cpp:726
    #14 0x7fffe6c8ce92 in nsDocumentOpenInfo::DispatchContent(nsIRequest*, nsISupports*) /home/researcher/source/firefox/uriloader/base/nsURILoader.cpp:401
    #15 0x7fffe6c8c129 in nsDocumentOpenInfo::OnStartRequest(nsIRequest*, nsISupports*) /home/researcher/source/firefox/uriloader/base/nsURILoader.cpp:262
    #16 0x7fffe55d0d6e in nsBaseChannel::OnStartRequest(nsIRequest*, nsISupports*) /home/researcher/source/firefox/netwerk/base/nsBaseChannel.cpp:754
    #17 0x7fffe56014bc in nsInputStreamPump::OnStateStart() /home/researcher/source/firefox/netwerk/base/nsInputStreamPump.cpp:531
    #18 0x7fffe5600a5b in nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream*) /home/researcher/source/firefox/netwerk/base/nsInputStreamPump.cpp:433
    #19 0x7fffe54085fb in nsInputStreamReadyEvent::Run() /home/researcher/source/firefox/xpcom/io/nsStreamUtils.cpp:90
    #20 0x7fffe54489e1 in nsThread::ProcessNextEvent(bool, bool*) /home/researcher/source/firefox/xpcom/threads/nsThread.cpp:855
    #21 0x7fffe54b8f80 in NS_ProcessNextEvent(nsIThread*, bool) /home/researcher/source/firefox/xpcom/glue/nsThreadUtils.cpp:265
    #22 0x7fffe5e160ca in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /home/researcher/source/firefox/ipc/glue/MessagePump.cpp:99
    #23 0x7fffe5d99476 in MessageLoop::RunInternal() /home/researcher/source/firefox/ipc/chromium/src/base/message_loop.cc:233
    #24 0x7fffe5d98f1b in MessageLoop::RunHandler() /home/researcher/source/firefox/ipc/chromium/src/base/message_loop.cc:226
    #25 0x7fffe5d98f1b in MessageLoop::Run() /home/researcher/source/firefox/ipc/chromium/src/base/message_loop.cc:200
    #26 0x7fffea597b1a in nsBaseAppShell::Run() /home/researcher/source/firefox/widget/nsBaseAppShell.cpp:164
    #27 0x7fffebf144e9 in nsAppStartup::Run() /home/researcher/source/firefox/toolkit/components/startup/nsAppStartup.cpp:281
    #28 0x7fffec0050ef in XREMain::XRE_mainRun() /home/researcher/source/firefox/toolkit/xre/nsAppRunner.cpp:4228
    #29 0x7fffec005e3a in XREMain::XRE_main(int, char**, nsXREAppData const*) /home/researcher/source/firefox/toolkit/xre/nsAppRunner.cpp:4308
    #30 0x7fffec006ada in XRE_main /home/researcher/source/firefox/toolkit/xre/nsAppRunner.cpp:4527
    #31 0x47adab in do_main(int, char**, nsIFile*) /home/researcher/source/firefox/browser/app/nsBrowserApp.cpp:294
    #32 0x47adab in main /home/researcher/source/firefox/browser/app/nsBrowserApp.cpp:667
    #33 0x7ffff6bebec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)

SUMMARY: AddressSanitizer: heap-use-after-free /home/researcher/source/firefox/objdir-ff-asan/dom/canvas/../../dist/include/nsIPresShell.h:319 nsIPresShell::StyleSet() const
Shadow bytes around the buggy address:
  0x0c2e80074b30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80074b40: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80074b50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80074b60: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80074b70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2e80074b80: fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80074b90: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80074ba0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80074bb0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80074bc0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80074bd0: fd fd fd fd fd fd fd 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
  Heap right redzon==5279==ABORTING

```

-- CREDIT ---------------------------------------

This vulnerability was discovered by:

   Ucha Gobejishvili working with HP's Zero Day Initiative

-- FURTHER DETAILS ------------------------------

If supporting files were contained with this report they are provided within a password protected ZIP file. The password is the ZDI candidate number in the form: ZDI-CAN-XXXX where XXXX is the ID number.

Please confirm receipt of this report. We expect all vendors to remediate ZDI vulnerabilities within 120 days of the reported date. If you are ready to release a patch at any point leading up the the deadline please coordinate with us so that we may release our advisory detailing the issue. If the 120 day deadline is reached and no patch has been made available we will release a limited public advisory with our own mitigations so that the public can protect themselves in the absence of a patch. Please keep us updated regarding the status of this issue and feel free to contact us at any time:

Zero Day Initiative
zdi-disclosures@hp.com

The PGP key used for all ZDI vendor communications is available from:

     http://www.zerodayinitiative.com/documents/zdi-pgp-key.asc

-- INFORMATION ABOUT THE ZDI ---------------------

Established by TippingPoint and acquired by Hewlett-Packard, The Zero Day Initiative (ZDI) represents a best-of-breed model for rewarding security researchers for responsibly disclosing discovered vulnerabilities.

The ZDI is unique in how the acquired vulnerability information is used. The ZDI does not re-sell the vulnerability details or any exploit code. Instead, upon notifying the affected product vendor, the ZDI provides its HP TippingPoint customers with zero day protection through its intrusion prevention technology. Explicit details regarding the specifics of the vulnerability are not exposed to any parties until an official vendor patch is publicly available.

    http://www.zerodayinitiative.com

-- DISCLOSURE POLICY ----------------------------

Our vulnerability disclosure policy is available online at:

    http://www.zerodayinitiative.com/advisories/disclosure_policy/
Looks like the testcase has a dangling pointer to the result of canvas.getContext('2d'), from a subdocument which has been torn down and recreated (via its parent having been removed & reappended to the document).

The specific thing being used-after-free seems to be something in the presShell's styleset, obtained here:

> 2128 static already_AddRefed<nsStyleContext>
> 2129 GetFontStyleContext(Element* aElement, const nsAString& aFont,
> 2130                     nsIPresShell* presShell,
> 2131                     nsAString& aOutUsedFont,
> 2132                     ErrorResult& error)
> 2133 {
[...]
> 2171   nsStyleSet* styleSet = presShell->StyleSet();
> 2172   nsRefPtr<nsStyleContext> sc =
> 2173     styleSet->ResolveStyleForRules(parentContext, rules);
http://mxr.mozilla.org/mozilla-central/source/dom/canvas/CanvasRenderingContext2D.cpp?rev=536bd9910bc2#2171
I think use-after-free bugs are generally sec-critical; classifying as such.
Keywords: sec-critical
(In reply to Daniel Holbert [:dholbert] from comment #2)
> I think use-after-free bugs are generally sec-critical; classifying as such.

Yes, if they are trigerable by web content. I should have marked it. Thanks.
OK, so here's what happens:
 (1) The resize operation (and the resize-handler) gets queued up to be performed later on.
 (2) The "mozTextStyle" access makes us call CanvasRenderingContext2D::SetFont() (shown in the backtrace in comment 0)
 (3) SetFont() does the following:
   a) Grabs the presShell and stores it in a *raw pointer*
   b) Calls GetFontStyleContext
   c) ...which down a few levels makes us call PresShell::FlushPendingNotifications
   d) ...which ends up triggering the resize and its handler, which removes the iframe's old document, including its PresShell.
 (4) Then we try to call functions on the presShell raw pointer that we stored earlier, and we find it's been destroyed.


The last thing that holds a reference to the presShell is a local variable in nsComputedDOMStyle::GetStyleContextForElement (which we call from GetFontParentStyleContext.)  So when that variable goes out of scope, the presShell dies.

I think we just need to make SetFont() use a refcounted pointer (not a raw pointer) for its local presShell variable. Then it won't be left dangling after we flush notifications.
Assignee: nobody → dholbert
Attached patch fix v1Splinter Review
This is effectively a kung-fu deathgrip, to make sure this presShell is alive for as long as we're still using it (and doesn't die during a flush).  See previous comment for details.
Attachment #8623423 - Flags: review?(mats)
Attached file testcase 2 (simpler)
Here's a simpler version of the original testcase, with more understandable naming and a few parts removed.

This testcase & the original testcase each crash my local debug build (from dereferencing a bogus 0x5a5a..5a pointer on the deleted PresShell).  No ASAN needed.

With my patch applied, both testcases load just fine.
I can reproduce the crashes on a b2g37 win32 Fx build, but not off b2g34. Dan says that the raw pointer goes back to the Gecko 7 timeframe, so I guess there's something more at play?
Comment on attachment 8623423 [details] [diff] [review]
fix v1

Actually, this fix isn't complete. Looks like we have the same pattern (presShell looked up & stored in raw pointer, followed by style resolution) other places:
 CanvasRenderingContext2D::ParseColor
 CanvasRenderingContext2D::ParseFilter
and possibly:
 CanvasRenderingContext2D::GetCurrentFontStyle
though that last one's probably safe. (the presShell is only used once, and not after any obvious style resolution)

Canceling review request for the moment.
Attachment #8623423 - Flags: review?(mats)
So the regression range (comment 8) points to bug 927892, which exposed a bunch of new canvas APIs.

The actual raw presShell-pointer-followed-by-style-flush goes back much much further, though...
http://hg.mozilla.org/mozilla-central/rev/a8171812fe05#l5.3163
...so it's possible there are other ways to trigger this in older builds.

(the main question being, do we need to patch this in ESR31, I guess. Might be best to just assume that we should.)
[ni=me to post a more comprehensive patch per comment 9]
Flags: needinfo?(dholbert)
This is the same underlying issue as bug 1164766 but let's deal with it here instead,
since we have a start of a fix here.  Bug 1164766 is flagged esr31:affected so it
goes back to that version at least.
(In reply to Daniel Holbert [:dholbert] from comment #9)
> Comment on attachment 8623423 [details] [diff] [review]
> fix v1
> 
> Actually, this fix isn't complete. Looks like we have the same pattern
> (presShell looked up & stored in raw pointer, followed by style resolution)
> other places

Yeah, I think we need to audit all callers that can reach
GetFontStyleContext, recursively.

The owner of the CanvasRenderingContext2D seems to be the HTMLCanvasElement
so if that is removed from the document we also need to deal with having
a dangling 'this' pointer in the affected methods.
(In reply to Daniel Holbert [:dholbert] from comment #9)
> Actually, this fix isn't complete. Looks like we have the same pattern
> (presShell looked up & stored in raw pointer, followed by style resolution)
> other places:
>  CanvasRenderingContext2D::ParseColor

Attaching two testcases that target this other chunk of code with the same issue. (& crash)
Attachment #8623781 - Attachment description: testcase 3 (targeting SetColor via shadowColor) → testcase 3 (targeting ParseColor via shadowColor)
Attachment #8623782 - Attachment description: testcase 4 (targeting SetColor via fillStyle) → testcase 4 (targeting ParseColor via fillStyle)
(In reply to Mats Palmgren (:mats) from comment #13)
> The owner of the CanvasRenderingContext2D seems to be the HTMLCanvasElement
> so if that is removed from the document we also need to deal with having
> a dangling 'this' pointer in the affected methods.

I'm not sure how CanvasRenderingContext2D lifetimes are managed, but I suspect we're OK, because:
 (1) The JS object is likely holding a reference to the CanvasRenderingContext2D object.
 (2) I placed a breakpoint in CanvasRenderingContext2D::Release, and I got no hits during the run of the setter functions that trigger this bug. (Though I did hit PresShell::Destroy and HTMLCanvasElement::Release when the newly-safe nsCOMPtr<nsIPresShell> goes out of scope.
 (3) At some point *after the JS has finished*, I see a cycle-collection-triggered call to HTMLCanvasElement::Release and CanvasRenderingContext2D::Release.
Flags: needinfo?(dholbert)
(In reply to Mats Palmgren (:mats) from comment #12)
> This is the same underlying issue as bug 1164766 but let's deal with it here
> instead, since we have a start of a fix here.

Spoke with mstange -- he's gonnna finish it off over on bug 1164766, actually. (though we should be sure to test the fix against my various testcases posted here).

Duping this bug there.
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → DUPLICATE
> (1) The JS object is likely holding a reference to the CanvasRenderingContext2D object.

If the call was made via the JS API, then it is.  Not only that, but the JS object is being kept alive by the SpiderMonkey stack.  So your "this" can't go away until you return back into JS.
Assignee: dholbert → nobody
For external reporter purposes, etc., is this a true duplicate of 1164766 or is that bug and its fix larger scope and includes work that addresses this issue as well? It sounds like the same issue based on comments but I want to be 100% clear since ZDI will be asking.
Flags: needinfo?(dholbert)
(In reply to Al Billings [:abillings] from comment #20)
> For external reporter purposes, etc., is this a true duplicate of 1164766

Yes. The testcases on the two bugs are pretty much the same. (This bug's testcase uses ctx.mozTextStyle while the other bug uses ctx.font, but both of those are just ways of triggering CanvasRenderingContext2D::SetFont, which blows up per comment 4.)
Flags: needinfo?(dholbert)
Making this bug a dupe seems to have reduced the urgency on bug 1164766 -- no substantive comments since two days after this was duped. This is an external report from ZDI that comes with a disclosure deadline, we can't afford to miss another release.
No longer blocks: CVE-2015-4497
Status: RESOLVED → REOPENED
Depends on: CVE-2015-4497
Resolution: DUPLICATE → ---
Whiteboard: working on fix in bug 1164766. ZDI will disclose October 2015 (Firefox 41)
Nonetheless, this is indeed a dupe of bug 1164766; un-duping won't help here. (Re-duping after discussing w/ dveditz.)

And yes, we should absolutely fix this (in bug 1164766) ASAP. I'll tag mstange over there.
Status: REOPENED → RESOLVED
Closed: 9 years ago9 years ago
Resolution: --- → DUPLICATE
The dupe bug has been fixed, we can test this one now.
Verification on Firefox 40.0.3 and ESR 38.2.1 was done in bug 1164766, and covered the 5 testcases in this bug as well.
Group: core-security → core-security-release
In addition to comment 26, I just verified that the attached testcases all load without any crashes or assertions in a mozilla-inbound debug build from today.

--> Marking VERIFIED
Status: RESOLVED → VERIFIED
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: