Closed Bug 1770006 Opened 2 years ago Closed 2 years ago

heap-use-after-free in [@ gfxFontGroup::FindFontForChar]

Categories

(Core :: Graphics: Text, defect, P3)

defect

Tracking

()

RESOLVED FIXED
102 Branch
Tracking Status
firefox-esr91 --- unaffected
firefox100 --- unaffected
firefox101 --- unaffected
firefox102 --- fixed

People

(Reporter: tsmith, Assigned: jfkthame)

References

(Blocks 1 open bug, Regression)

Details

(Keywords: csectype-uaf, csectype-uninitialized, sec-low)

Attachments

(2 files, 2 obsolete files)

Found while fuzzing m-c 20220517-383c699ac203 (--enable-address-sanitizer --enable-fuzzing)

The test case is currently being reduced and will be attached shortly.

==26651==ERROR: AddressSanitizer: heap-use-after-free on address 0x616000092fe5 at pc 0x7f925c8e29be bp 0x7ffec61b4ba0 sp 0x7ffec61b4b98
READ of size 1 at 0x616000092fe5 thread T0 (Isolated Web Co)
    #0 0x7f925c8e29bd in nsPresContext::GetFontVisibility() const /builds/worker/workspace/obj-build/dist/include/nsPresContext.h:166:53
    #1 0x7f925c912497 in gfxFontGroup::FindFontForChar(unsigned int, unsigned int, unsigned int, mozilla::intl::Script, gfxFont*, FontMatchType*) /gecko/gfx/thebes/gfxTextRun.cpp:3352:36
    #2 0x7f925c94e434 in void gfxFontGroup::ComputeRanges<char16_t>(nsTArray<gfxFontGroup::TextRange>&, char16_t const*, unsigned int, mozilla::intl::Script, mozilla::gfx::ShapedTextFlags) /gecko/gfx/thebes/gfxTextRun.cpp:3495:11
    #3 0x7f925c94b07e in void gfxFontGroup::InitScriptRun<char16_t>(mozilla::gfx::DrawTarget*, gfxTextRun*, char16_t const*, unsigned int, unsigned int, mozilla::intl::Script, gfxMissingFontRecorder*) /gecko/gfx/thebes/gfxTextRun.cpp:2729:3
    #4 0x7f925c91676a in void gfxFontGroup::InitTextRun<char16_t>(mozilla::gfx::DrawTarget*, gfxTextRun*, char16_t const*, unsigned int, gfxMissingFontRecorder*) /gecko/gfx/thebes/gfxTextRun.cpp:2651:9
    #5 0x7f925c915c63 in gfxFontGroup::MakeTextRun(char16_t const*, unsigned int, gfxTextRunFactory::Parameters const*, mozilla::gfx::ShapedTextFlags, nsTextFrameUtils::Flags, gfxMissingFontRecorder*) /gecko/gfx/thebes/gfxTextRun.cpp:2525:3
    #6 0x7f925f2d45f8 in MakeTextRun<char16_t> /builds/worker/workspace/obj-build/dist/include/gfxTextRun.h:989:12
    #7 0x7f925f2d45f8 in mozilla::dom::CanvasBidiProcessor::SetText(char16_t const*, int, mozilla::intl::BidiDirection) /gecko/dom/canvas/CanvasRenderingContext2D.cpp:3730:26
    #8 0x7f9262b94a47 in nsBidiPresUtils::ProcessText(char16_t const*, unsigned long, mozilla::intl::BidiEmbeddingLevel, nsPresContext*, nsBidiPresUtils::BidiProcessor&, nsBidiPresUtils::Mode, nsBidiPositionResolve*, int, int*, mozilla::intl::Bidi*) /gecko/layout/base/nsBidiPresUtils.cpp:2234:18
    #9 0x7f925f1e09ce in mozilla::dom::CanvasRenderingContext2D::DrawOrMeasureText(nsTSubstring<char16_t> const&, float, float, mozilla::dom::Optional<double> const&, mozilla::dom::CanvasRenderingContext2D::TextDrawOperation, mozilla::ErrorResult&) /gecko/dom/canvas/CanvasRenderingContext2D.cpp:4101:12
    #10 0x7f925e1c5377 in mozilla::dom::CanvasRenderingContext2D_Binding::fillText(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) /builds/worker/workspace/obj-build/dom/bindings/CanvasRenderingContext2DBinding.cpp:6432:24
    #11 0x7f925f02aced in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) /gecko/dom/bindings/BindingUtils.cpp:3271:13
    #12 0x7f9269125a14 in CallJSNative /gecko/js/src/vm/Interpreter.cpp:420:13
    #13 0x7f9269125a14 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:507:12
    #14 0x7f9269112cfe in InternalCall /gecko/js/src/vm/Interpreter.cpp:574:10
    #15 0x7f9269112cfe in CallFromStack /gecko/js/src/vm/Interpreter.cpp:578:10
    #16 0x7f9269112cfe in Interpret(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:3314:16
    #17 0x7f92690f7881 in js::RunScript(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:389:13
    #18 0x7f9269125b4f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:539:13
    #19 0x7f92691276da in InternalCall /gecko/js/src/vm/Interpreter.cpp:574:10
    #20 0x7f92691276da in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:605:8
    #21 0x7f9267bea50c in js::CallSelfHostedFunction(JSContext*, JS::Handle<js::PropertyName*>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /gecko/js/src/vm/SelfHosting.cpp:1590:10
    #22 0x7f9267822da9 in AsyncFunctionResume(JSContext*, JS::Handle<js::AsyncFunctionGeneratorObject*>, ResumeKind, JS::Handle<JS::Value>) /gecko/js/src/vm/AsyncFunction.cpp:152:8
    #23 0x7f9267af5e6a in AsyncFunctionPromiseReactionJob /gecko/js/src/builtin/Promise.cpp:2113:12
    #24 0x7f9267af5e6a in PromiseReactionJob(JSContext*, unsigned int, JS::Value*) /gecko/js/src/builtin/Promise.cpp:2176:12
    #25 0x7f9269125a14 in CallJSNative /gecko/js/src/vm/Interpreter.cpp:420:13
    #26 0x7f9269125a14 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:507:12
    #27 0x7f92691276da in InternalCall /gecko/js/src/vm/Interpreter.cpp:574:10
    #28 0x7f92691276da in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:605:8
    #29 0x7f926785af7d in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /gecko/js/src/vm/CallAndConstruct.cpp:117:10
    #30 0x7f925de31acc in mozilla::dom::PromiseJobCallback::Call(mozilla::dom::BindingCallContext&, JS::Handle<JS::Value>, mozilla::ErrorResult&) /builds/worker/workspace/obj-build/dom/bindings/PromiseBinding.cpp:35:8
    #31 0x7f9259e5c1f7 in Call /builds/worker/workspace/obj-build/dist/include/mozilla/dom/PromiseBinding.h:89:12
    #32 0x7f9259e5c1f7 in Call /builds/worker/workspace/obj-build/dist/include/mozilla/dom/PromiseBinding.h:102:12
    #33 0x7f9259e5c1f7 in mozilla::PromiseJobRunnable::Run(mozilla::AutoSlowOperation&) /gecko/xpcom/base/CycleCollectedJSContext.cpp:213:18
    #34 0x7f9259e3bc47 in mozilla::CycleCollectedJSContext::PerformMicroTaskCheckPoint(bool) /gecko/xpcom/base/CycleCollectedJSContext.cpp:674:17
    #35 0x7f9259e3cc8f in mozilla::CycleCollectedJSContext::AfterProcessTask(unsigned int) /gecko/xpcom/base/CycleCollectedJSContext.cpp:463:3
    #36 0x7f925ba525a0 in XPCJSContext::AfterProcessTask(unsigned int) /gecko/js/xpconnect/src/XPCJSContext.cpp:1481:28
    #37 0x7f925a068cf8 in nsThread::ProcessNextEvent(bool, bool*) /gecko/xpcom/threads/nsThread.cpp:1217:24
    #38 0x7f925a07290c in NS_ProcessNextEvent(nsIThread*, bool) /gecko/xpcom/threads/nsThreadUtils.cpp:465:10
    #39 0x7f925b78652f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /gecko/ipc/glue/MessagePump.cpp:85:21
    #40 0x7f925b60ce91 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:380:10
    #41 0x7f925b60ce91 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:373:3
    #42 0x7f925b60ce91 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:355:3
    #43 0x7f926252e6a7 in nsBaseAppShell::Run() /gecko/widget/nsBaseAppShell.cpp:137:27
    #44 0x7f9267407caf in XRE_RunAppShell() /gecko/toolkit/xre/nsEmbedFunctions.cpp:874:20
    #45 0x7f925b60ce91 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:380:10
    #46 0x7f925b60ce91 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:373:3
    #47 0x7f925b60ce91 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:355:3
    #48 0x7f9267406e5b in XRE_InitChildProcess(int, char**, XREChildData const*) /gecko/toolkit/xre/nsEmbedFunctions.cpp:733:34
    #49 0x559073dc3c1d in content_process_main(mozilla::Bootstrap*, int, char**) /gecko/browser/app/../../ipc/contentproc/plugin-container.cpp:57:28
    #50 0x559073dc4050 in main /gecko/browser/app/nsBrowserApp.cpp:329:18
    #51 0x7f927fce0082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
    #52 0x559073d04069 in _start (/home/worker/builds/m-c-20220518031437-fuzzing-asan-opt/firefox+0x5f069) (BuildId: 02119ab8eeba1c89f47f2513042feffac2a82f48)

0x616000092fe5 is located 613 bytes inside of 632-byte region [0x616000092d80,0x616000092ff8)
freed by thread T0 (Isolated Web Co) here:
    #0 0x559073d862e2 in __interceptor_free /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3
    #1 0x7f9259e8c592 in SnowWhiteKiller::~SnowWhiteKiller() /gecko/xpcom/base/nsCycleCollector.cpp:2406:7
    #2 0x7f9259e8bb2e in nsCycleCollector::FreeSnowWhite(bool) /gecko/xpcom/base/nsCycleCollector.cpp:2596:3
    #3 0x7f9259e93c17 in nsCycleCollector::BeginCollection(mozilla::CCReason, ccIsManual, nsICycleCollectorListener*) /gecko/xpcom/base/nsCycleCollector.cpp:3585:3
    #4 0x7f9259e9325c in nsCycleCollector::Collect(mozilla::CCReason, ccIsManual, js::SliceBudget&, nsICycleCollectorListener*, bool) /gecko/xpcom/base/nsCycleCollector.cpp:3412:9
    #5 0x7f9259e968f2 in nsCycleCollector_collect(mozilla::CCReason, nsICycleCollectorListener*) /gecko/xpcom/base/nsCycleCollector.cpp:3911:28
    #6 0x7f925d4a04e6 in nsJSContext::CycleCollectNow(mozilla::CCReason, nsICycleCollectorListener*) /gecko/dom/base/nsJSEnvironment.cpp:1413:3
    #7 0x7f925ed9d632 in mozilla::dom::FuzzingFunctions_Binding::cycleCollect(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/obj-build/dom/bindings/FuzzingFunctionsBinding.cpp:132:3
    #8 0x7f9269125a14 in CallJSNative /gecko/js/src/vm/Interpreter.cpp:420:13
    #9 0x7f9269125a14 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:507:12
    #10 0x7f9269112cfe in InternalCall /gecko/js/src/vm/Interpreter.cpp:574:10
    #11 0x7f9269112cfe in CallFromStack /gecko/js/src/vm/Interpreter.cpp:578:10
    #12 0x7f9269112cfe in Interpret(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:3314:16
    #13 0x7f92690f7881 in js::RunScript(JSContext*, js::RunState&) /gecko/js/src/vm/Interpreter.cpp:389:13
    #14 0x7f9269125b4f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:539:13
    #15 0x7f92691276da in InternalCall /gecko/js/src/vm/Interpreter.cpp:574:10
    #16 0x7f92691276da in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:605:8
    #17 0x7f9267bea50c in js::CallSelfHostedFunction(JSContext*, JS::Handle<js::PropertyName*>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /gecko/js/src/vm/SelfHosting.cpp:1590:10
    #18 0x7f9267822da9 in AsyncFunctionResume(JSContext*, JS::Handle<js::AsyncFunctionGeneratorObject*>, ResumeKind, JS::Handle<JS::Value>) /gecko/js/src/vm/AsyncFunction.cpp:152:8
    #19 0x7f9267af5e6a in AsyncFunctionPromiseReactionJob /gecko/js/src/builtin/Promise.cpp:2113:12
    #20 0x7f9267af5e6a in PromiseReactionJob(JSContext*, unsigned int, JS::Value*) /gecko/js/src/builtin/Promise.cpp:2176:12
    #21 0x7f9269125a14 in CallJSNative /gecko/js/src/vm/Interpreter.cpp:420:13
    #22 0x7f9269125a14 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:507:12
    #23 0x7f92691276da in InternalCall /gecko/js/src/vm/Interpreter.cpp:574:10
    #24 0x7f92691276da in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /gecko/js/src/vm/Interpreter.cpp:605:8
    #25 0x7f926785af7d in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /gecko/js/src/vm/CallAndConstruct.cpp:117:10
    #26 0x7f925de31acc in mozilla::dom::PromiseJobCallback::Call(mozilla::dom::BindingCallContext&, JS::Handle<JS::Value>, mozilla::ErrorResult&) /builds/worker/workspace/obj-build/dom/bindings/PromiseBinding.cpp:35:8
    #27 0x7f9259e5c1f7 in Call /builds/worker/workspace/obj-build/dist/include/mozilla/dom/PromiseBinding.h:89:12
    #28 0x7f9259e5c1f7 in Call /builds/worker/workspace/obj-build/dist/include/mozilla/dom/PromiseBinding.h:102:12
    #29 0x7f9259e5c1f7 in mozilla::PromiseJobRunnable::Run(mozilla::AutoSlowOperation&) /gecko/xpcom/base/CycleCollectedJSContext.cpp:213:18
    #30 0x7f9259e3bc47 in mozilla::CycleCollectedJSContext::PerformMicroTaskCheckPoint(bool) /gecko/xpcom/base/CycleCollectedJSContext.cpp:674:17
    #31 0x7f9259e3cc8f in mozilla::CycleCollectedJSContext::AfterProcessTask(unsigned int) /gecko/xpcom/base/CycleCollectedJSContext.cpp:463:3
    #32 0x7f925ba525a0 in XPCJSContext::AfterProcessTask(unsigned int) /gecko/js/xpconnect/src/XPCJSContext.cpp:1481:28
    #33 0x7f925a068cf8 in nsThread::ProcessNextEvent(bool, bool*) /gecko/xpcom/threads/nsThread.cpp:1217:24
    #34 0x7f925a07290c in NS_ProcessNextEvent(nsIThread*, bool) /gecko/xpcom/threads/nsThreadUtils.cpp:465:10
    #35 0x7f925b78652f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /gecko/ipc/glue/MessagePump.cpp:85:21
    #36 0x7f925b60ce91 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:380:10
    #37 0x7f925b60ce91 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:373:3
    #38 0x7f925b60ce91 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:355:3
    #39 0x7f926252e6a7 in nsBaseAppShell::Run() /gecko/widget/nsBaseAppShell.cpp:137:27
    #40 0x7f9267407caf in XRE_RunAppShell() /gecko/toolkit/xre/nsEmbedFunctions.cpp:874:20

previously allocated by thread T0 (Isolated Web Co) here:
    #0 0x559073d8658e in __interceptor_malloc /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3
    #1 0x559073dca30d in moz_xmalloc /gecko/memory/mozalloc/mozalloc.cpp:52:15
    #2 0x7f9262bdffa6 in operator new /builds/worker/workspace/obj-build/dist/include/mozilla/cxxalloc.h:33:10
    #3 0x7f9262bdffa6 in CreatePresContext /gecko/layout/base/nsDocumentViewer.cpp:787:10
    #4 0x7f9262bdffa6 in nsDocumentViewer::InitInternal(nsIWidget*, nsISupports*, mozilla::dom::WindowGlobalChild*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, bool, bool, bool) /gecko/layout/base/nsDocumentViewer.cpp:829:24
    #5 0x7f9262bdfcc7 in nsDocumentViewer::Init(nsIWidget*, mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits> const&, mozilla::dom::WindowGlobalChild*) /gecko/layout/base/nsDocumentViewer.cpp:679:10
    #6 0x7f92665de35b in nsDocShell::SetupNewViewer(nsIContentViewer*, mozilla::dom::WindowGlobalChild*) /gecko/docshell/base/nsDocShell.cpp:8253:7
    #7 0x7f92665dcdbe in nsDocShell::Embed(nsIContentViewer*, mozilla::dom::WindowGlobalChild*, bool, bool, nsIRequest*) /gecko/docshell/base/nsDocShell.cpp:5695:17
    #8 0x7f92665a56f1 in nsDocShell::CreateContentViewer(nsTSubstring<char> const&, nsIRequest*, nsIStreamListener**) /gecko/docshell/base/nsDocShell.cpp:8065:3
    #9 0x7f92665a3920 in nsDSURIContentListener::DoContent(nsTSubstring<char> const&, bool, nsIRequest*, nsIStreamListener**, bool*) /gecko/docshell/base/nsDSURIContentListener.cpp:168:20
    #10 0x7f925bcc9b19 in nsDocumentOpenInfo::TryContentListener(nsIURIContentListener*, nsIChannel*) /gecko/uriloader/base/nsURILoader.cpp:625:18
    #11 0x7f925bcc7374 in nsDocumentOpenInfo::DispatchContent(nsIRequest*) /gecko/uriloader/base/nsURILoader.cpp:304:9
    #12 0x7f925bcc5cb4 in nsDocumentOpenInfo::OnStartRequest(nsIRequest*) /gecko/uriloader/base/nsURILoader.cpp:155:8
    #13 0x7f925aec218b in mozilla::net::HttpChannelChild::DoOnStartRequest(nsIRequest*) /gecko/netwerk/protocol/http/HttpChannelChild.cpp:567:20
    #14 0x7f925aec113f in mozilla::net::HttpChannelChild::OnStartRequest(mozilla::net::nsHttpResponseHead const&, bool const&, mozilla::net::nsHttpHeaderArray const&, mozilla::net::HttpChannelOnStartRequestArgs const&) /gecko/netwerk/protocol/http/HttpChannelChild.cpp:499:3
    #15 0x7f925b271f0e in mozilla::net::ChannelEventQueue::FlushQueue() /gecko/netwerk/ipc/ChannelEventQueue.cpp:94:12
    #16 0x7f925b2bebe7 in mozilla::net::ChannelEventQueue::ResumeInternal()::CompleteResumeRunnable::Run() /gecko/netwerk/ipc/ChannelEventQueue.cpp:152:17
    #17 0x7f925a081de2 in mozilla::RunnableTask::Run() /gecko/xpcom/threads/TaskController.cpp:475:16
    #18 0x7f925a047e45 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /gecko/xpcom/threads/TaskController.cpp:788:26
    #19 0x7f925a044ff8 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /gecko/xpcom/threads/TaskController.cpp:620:15
    #20 0x7f925a045720 in mozilla::TaskController::ProcessPendingMTTask(bool) /gecko/xpcom/threads/TaskController.cpp:398:36
    #21 0x7f925a08a931 in operator() /gecko/xpcom/threads/TaskController.cpp:124:37
    #22 0x7f925a08a931 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_0>::Run() /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:531:5
    #23 0x7f925a0687a7 in nsThread::ProcessNextEvent(bool, bool*) /gecko/xpcom/threads/nsThread.cpp:1180:16
    #24 0x7f925a07290c in NS_ProcessNextEvent(nsIThread*, bool) /gecko/xpcom/threads/nsThreadUtils.cpp:465:10
    #25 0x7f925b78652f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /gecko/ipc/glue/MessagePump.cpp:85:21
    #26 0x7f925b60ce91 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:380:10
    #27 0x7f925b60ce91 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:373:3
    #28 0x7f925b60ce91 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:355:3
    #29 0x7f926252e6a7 in nsBaseAppShell::Run() /gecko/widget/nsBaseAppShell.cpp:137:27
    #30 0x7f9267407caf in XRE_RunAppShell() /gecko/toolkit/xre/nsEmbedFunctions.cpp:874:20
    #31 0x7f925b60ce91 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:380:10
    #32 0x7f925b60ce91 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:373:3
    #33 0x7f925b60ce91 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:355:3
    #34 0x7f9267406e5b in XRE_InitChildProcess(int, char**, XREChildData const*) /gecko/toolkit/xre/nsEmbedFunctions.cpp:733:34
    #35 0x559073dc3c1d in content_process_main(mozilla::Bootstrap*, int, char**) /gecko/browser/app/../../ipc/contentproc/plugin-container.cpp:57:28
    #36 0x559073dc4050 in main /gecko/browser/app/nsBrowserApp.cpp:329:18

Looks like the UAF is a read on gfxFontGroup::mPresContext, which is a raw pointer.

I bet this was regressed by the first patch in bug 1759686, which removed the apparently-unused mPresContext member from CanvasBidiProcessor; this would have been fortuitously ensuring the presContext was kept alive.

Rather than reverting that (given that it was not at all obvious!), I think we should instead hold a strong reference directly in CanvasRenderingContext2D::DrawOrMeasureText, which currently only has a raw pointer.

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

Tyson, if you have a chance to verify that the above patch fixes the issue here, that'd be awesome - thanks. Or if there's a reduced testcase that reliably reproduces it, that'd also be great.

Flags: needinfo?(twsmith)
Flags: needinfo?(twsmith)

I am able to reproduce the issue with the patch applied.

A Pernosco session is available here (with patch): https://pernos.co/debug/W2T-EjlAjU1mU3LUr_QhSA/index.html

Jason will attach the test case once reduction is complete.

Flags: needinfo?(jfkthame)

Thanks - sounds like my guess in comment 2 wasn't right, and we'll need to dig further.

Flags: needinfo?(jfkthame)

OK, I don't think this is a particularly recent regression, then. Looks like the flaw here was introduced in bug 1715501.

I think what's happening is that the testcase is doing a text operation on a canvas, such that the CanvasRenderingContext2D's "current font style" gets set up based on the current document and presShell. Then the canvas element is removed from its document and the original document/presShell/presContext is destroyed. But the canvas rendering context is kept alive by script, and another text-drawing operation is done on it. It tries to re-use its current font style, which has a dangling reference to the now-destroyed document's presentation.

So CanvasRenderingContext2D::GetCurrentFontStyle() needs to check for a change in presContext and force re-creation of the fontGroup.

Fortunately, the use-after-free here is relatively benign, in that the gfxFontGroup just looks at its mPresContext to read the mFontVisibility field; getting a garbage value here means we might expose a font to be used in the canvas text rendering that was supposed to be blocked, or conversely, we might block a font that was supposed to be usable. So in principle this could be a weakness in the font-fingerprinting mitigation work, but it doesn't look to me like it's otherwise exploitable.

Dan, given the limited nature of the UAF here, should the rating be reduced from sec-high? It's still a bug, but doesn't seem to meet the sec-high bar AFAICS.

Flags: needinfo?(dveditz)
Attachment #9277161 - Attachment is obsolete: true

Jason, if you have a chance to re-test with the new patch (comment 8) and confirm whether it fixes the problem, that'd be awesome - thanks!

Flags: needinfo?(jkratzer)
Attached file testcase.html (obsolete) —
Flags: needinfo?(jkratzer)
Keywords: bugmon

Bugmon Analysis
Unable to reproduce bug 1770006 using build mozilla-central 20220517212638-383c699ac203. Without a baseline, bugmon is unable to analyze this bug.
Removing bugmon keyword as no further action possible. Please review the bug and re-add the keyword for further analysis.

Keywords: bugmon

Hrmm, I was really hoping bugmon could handle this testcase. I'll give it a go manually and see if I can come up with a bisection range. Also awaiting my try builds with your patch :jfkthame.

Thanks; I don't want to try landing the patch until we can confirm it works as expected, but currently my local asan/fuzzing build seems to be broken... :-\

Attached file testcase.html
Attachment #9277303 - Attachment is obsolete: true

:jfkthame, I can confirm that with your patch, I can no longer trigger the issue using the attached testcase. I'm still waiting on that bisection.

Thanks. I'm setting flags based on the assumption this was regressed by bug 1715501, as I'm reasonably confident of this, but it'd be great if your bisection is able to verify that.

Marking this as an S3 given that it's not a very recent regression, and despite it being a UAF, the actual impact is relatively minor (see comment 7).

Severity: -- → S3
Priority: -- → P3
Regressed by: 1715501

Comment on attachment 9277266 [details]
Bug 1770006 - Ensure the fontGroup is recreated if necessary in CanvasRenderingContext2D::GetCurrentFontStyle. r=lsalzman

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: The patch implies that it's possible to have a stale fontGroup associated with canvas, though not how to achieve that (the fuzzer case relies on forcing GC/CC); but even with that realization, the exploitable impact is very limited (comment 7).
  • 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?: Only Nightly (102) 94 and later
  • If not all supported branches, which bug introduced the flaw?: Bug 1759686 1715501
  • Do you have backports for the affected branches?: No
  • If not, how different, hard to create, and risky will they be?: n/a Expected to transplant cleanly
  • How likely is this patch to cause regressions; how much testing does it need?: Minimal risk
  • Is Android affected?: Yes
Attachment #9277266 - Flags: sec-approval?

The bug appears to have been introduced in the following build range:

Start: 6caa30153d0b6e71f31316ca071c3173dc10c89c (20220504210204)
End: d71652d1278bbf55b8079fcd77fc68c3920d954d (20220504224543)
Pushlog: https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=6caa30153d0b6e71f31316ca071c3173dc10c89c&tochange=d71652d1278bbf55b8079fcd77fc68c3920d954d

Ah, that's interesting. Yeah, makes sense on looking again: before bug 1759686 patch 5 landed, some of the other checks for a "detached" canvas would have caused us to bail out earlier, so the problem code wasn't reached.

So that means we can update the "affected" flags as it doesn't reach all the way back to bug 1715501 after all. Although the "flaw" was arguably introduced there, it wasn't actually reachable at that point.

Has Regression Range: --- → yes

The severity field for this bug is set to S3. However, the bug is flagged with the sec-high keyword.
:jfkthame, could you consider increasing the severity of this security bug?

For more information, please visit auto_nag documentation.

Flags: needinfo?(jfkthame)
Flags: needinfo?(jfkthame)

(In reply to Release mgmt bot [:suhaib / :marco/ :calixte] from comment #20)

The severity field for this bug is set to S3. However, the bug is flagged with the sec-high keyword.
:jfkthame, could you consider increasing the severity of this security bug?

As per comment 7, I think the sec-* rating could be reduced, but wanted to get a second opinion rather than just changing it myself.

Based on the description in comment 7, although this is technically a UAF it's impact is more like an "uninitialized variable".

Flags: needinfo?(dveditz)

Comment on attachment 9277266 [details]
Bug 1770006 - Ensure the fontGroup is recreated if necessary in CanvasRenderingContext2D::GetCurrentFontStyle. r=lsalzman

Cancelling approval request as this is now sec-low and can go ahead and land.

Attachment #9277266 - Flags: sec-approval?

Ensure the fontGroup is recreated if necessary in CanvasRenderingContext2D::GetCurrentFontStyle. r=lsalzman
https://hg.mozilla.org/integration/autoland/rev/aa1694798075ca236e66e70aa2f451c21bf4bfbf
https://hg.mozilla.org/mozilla-central/rev/aa1694798075

Group: gfx-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → 102 Branch
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: