Closed Bug 1849704 (CVE-2023-5175) Opened 10 months ago Closed 10 months ago

heap-use-after-free xpcom/ds/PLDHashTable.cpp:546 in PLDHashTable::Remove with ImageBitmapShutdownObserver

Categories

(Core :: Graphics: Canvas2D, defect)

defect

Tracking

()

RESOLVED FIXED
118 Branch
Tracking Status
firefox-esr102 --- unaffected
firefox-esr115 --- unaffected
firefox116 --- unaffected
firefox117 --- wontfix
firefox118 --- fixed

People

(Reporter: m.cooolie, Assigned: tnikkel)

References

(Regression)

Details

(4 keywords, Whiteboard: [reporter-external] [client-bounty-form] [verif?][adv-main118+])

Attachments

(4 files)

Attached file poc.html

#Summary
heap-use-after-free xpcom/ds/PLDHashTable.cpp:546 in PLDHashTable::Remove

#Reproduce
OS:Win10 X64
118.0a1 (2023-08-21) (64-bit)

step:

  1. install node & puppeteer-core (for easy reproduce)
  2. python -m http.server 1337
  3. node ff.test2.js test http://localhost:1337/poc.html 30 firefox.exe_path

#Type of crash
Tab process

#Analysis
coming soon

#ASAN

==14772==ERROR: AddressSanitizer: heap-use-after-free on address 0x119d234cc1d8 at pc 0x7ffafd5d922e bp 0x008a8fdfe1d0 sp 0x008a8fdfe218
READ of size 4 at 0x119d234cc1d8 thread T0
#0 0x7ffafd5d922d in PLDHashTable::Remove /builds/worker/checkouts/gecko/xpcom/ds/PLDHashTable.cpp:546
#1 0x7ffb034f2b86 in mozilla::dom::ImageBitmap::~ImageBitmap /builds/worker/checkouts/gecko/dom/canvas/ImageBitmap.cpp:665
#2 0x7ffb0353152f in mozilla::dom::ImageBitmap::cycleCollection::DeleteCycleCollectable /builds/worker/workspace/obj-build/dist/include/mozilla/dom/ImageBitmap.h:85
#3 0x7ffafd552f86 in SnowWhiteKiller::~SnowWhiteKiller /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:2473
#4 0x7ffafd55185e in nsCycleCollector::FreeSnowWhite /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:2663
#5 0x7ffafd55d195 in nsCycleCollector::BeginCollection /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:3660
#6 0x7ffafd55c16f in nsCycleCollector::Collect /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:3484
#7 0x7ffafd55b9e0 in nsCycleCollector::ShutdownCollect /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:3418
#8 0x7ffafd561ffc in nsCycleCollector_shutdown /builds/worker/checkouts/gecko/xpcom/base/nsCycleCollector.cpp:4046
#9 0x7ffafd82f6d0 in mozilla::ShutdownXPCOM /builds/worker/checkouts/gecko/xpcom/build/XPCOMInit.cpp:693
#10 0x7ffb0c0cf54a in XRE_InitChildProcess /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:661
#11 0x7ff6e0c92953 in NS_internal_main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:375
#12 0x7ff6e0c9169b in wmain /builds/worker/checkouts/gecko/toolkit/xre/nsWindowsWMain.cpp:167
#13 0x7ff6e0d734e7 in __scrt_common_main_seh D:\a_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#14 0x7ffbb0d17613 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180017613)
#15 0x7ffbb0fe26b0 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x1800526b0)

0x119d234cc1d8 is located 56 bytes inside of 64-byte region [0x119d234cc1a0,0x119d234cc1e0)
freed by thread T0 here:
#0 0x7ffb5fd4f28d in free /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_malloc_win.cpp:82
#1 0x7ffb034f3042 in mozilla::dom::ImageBitmapShutdownObserver::Release /builds/worker/checkouts/gecko/dom/canvas/ImageBitmap.cpp:137
#2 0x7ffafd629fe5 in nsTHashtable<nsObserverList>::s_ClearEntry /builds/worker/workspace/obj-build/dist/include/nsTHashtable.h:720
#3 0x7ffafd5d600c in PLDHashTable::~PLDHashTable /builds/worker/checkouts/gecko/xpcom/ds/PLDHashTable.cpp:293
#4 0x7ffafd5d6290 in PLDHashTable::Clear /builds/worker/checkouts/gecko/xpcom/ds/PLDHashTable.cpp:312
#5 0x7ffafd82f49a in mozilla::ShutdownXPCOM /builds/worker/checkouts/gecko/xpcom/build/XPCOMInit.cpp:633
#6 0x7ffb0c0cf54a in XRE_InitChildProcess /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:661
#7 0x7ff6e0c92953 in NS_internal_main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:375
#8 0x7ff6e0c9169b in wmain /builds/worker/checkouts/gecko/toolkit/xre/nsWindowsWMain.cpp:167
#9 0x7ff6e0d734e7 in __scrt_common_main_seh D:\a_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#10 0x7ffbb0d17613 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180017613)
#11 0x7ffbb0fe26b0 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x1800526b0)

previously allocated by thread T22 here:
#0 0x7ffb5fd4f39d in malloc /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_malloc_win.cpp:98
#1 0x7ffb6dfa11ad in moz_xmalloc /builds/worker/checkouts/gecko/memory/mozalloc/mozalloc.cpp:52
#2 0x7ffb034f3a45 in mozilla::dom::ImageBitmap::ImageBitmap /builds/worker/checkouts/gecko/dom/canvas/ImageBitmap.cpp:651
#3 0x7ffb034f6d57 in mozilla::dom::ImageBitmap::CreateFromOffscreenCanvas /builds/worker/checkouts/gecko/dom/canvas/ImageBitmap.cpp:949
#4 0x7ffb03517068 in mozilla::dom::OffscreenCanvas::TransferToImageBitmap /builds/worker/checkouts/gecko/dom/canvas/OffscreenCanvas.cpp:346
#5 0x7ffb0174bf77 in mozilla::dom::OffscreenCanvas_Binding::transferToImageBitmap /builds/worker/workspace/obj-build/dom/bindings/OffscreenCanvasBinding.cpp:1171
#6 0x7ffb03208582 in mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy,mozilla::dom::binding_detail::ThrowExceptions> /builds/worker/checkouts/gecko/dom/bindings/BindingUtils.cpp:3327
#7 0x2fffc814c4 (<unknown module>)

Thread T22 created by T0 here:
#0 0x7ffb5fd5ce72 in __asan_wrap_CreateThread /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_win.cpp:146
#1 0x7ffbae991896 in beginthreadex+0x56 (C:\WINDOWS\System32\ucrtbase.dll+0x180021896)
#2 0x7ffb5d4092f2 in _PR_MD_CREATE_THREAD /builds/worker/checkouts/gecko/nsprpub/pr/src/md/windows/w95thred.c:153
#3 0x7ffb5d43173e in _PR_NativeCreateThread /builds/worker/checkouts/gecko/nsprpub/pr/src/threads/combined/pruthr.c:1058
#4 0x7ffb5d431f42 in _PR_CreateThread /builds/worker/checkouts/gecko/nsprpub/pr/src/threads/combined/pruthr.c:1184
#5 0x7ffb5d427e2f in PR_CreateThread /builds/worker/checkouts/gecko/nsprpub/pr/src/threads/combined/pruthr.c:1404
#6 0x7ffafd78ff5f in nsThread::Init /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:634
#7 0x7ffb06a27026 in mozilla::dom::WorkerThread::Create /builds/worker/checkouts/gecko/dom/workers/WorkerThread.cpp:101
#8 0x7ffb06990c43 in mozilla::dom::workerinternals::RuntimeService::ScheduleWorker /builds/worker/checkouts/gecko/dom/workers/RuntimeService.cpp:1313
#9 0x7ffb0698eb31 in mozilla::dom::workerinternals::RuntimeService::RegisterWorker /builds/worker/checkouts/gecko/dom/workers/RuntimeService.cpp:1195
#10 0x7ffb069e9d84 in mozilla::dom::WorkerPrivate::Constructor /builds/worker/checkouts/gecko/dom/workers/WorkerPrivate.cpp:2684
#11 0x7ffb069ad485 in mozilla::dom::Worker::Constructor /builds/worker/checkouts/gecko/dom/workers/Worker.cpp:50
#12 0x7ffb0273b1d9 in mozilla::dom::Worker_Binding::_constructor /builds/worker/workspace/obj-build/dom/bindings/WorkerBinding.cpp:1158
#13 0x7ffb0dfadb87 in InternalConstruct /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:727
#14 0x7ffb0dfc89ee in js::Interpret /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:3380
#15 0x7ffb0dfa9803 in js::RunScript /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:458
#16 0x7ffb0dfaf1b5 in js::ExecuteKernel /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:845
#17 0x7ffb0dfaf611 in js::Execute /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:877
#18 0x7ffb0c53a5bd in ExecuteScript /builds/worker/checkouts/gecko/js/src/vm/CompilationAndEvaluation.cpp:494
#19 0x7ffb0c53a94f in JS_ExecuteScript /builds/worker/checkouts/gecko/js/src/vm/CompilationAndEvaluation.cpp:518
#20 0x7ffb00c821a7 in mozilla::dom::JSExecutionContext::ExecScript /builds/worker/checkouts/gecko/dom/base/JSExecutionContext.cpp:241
#21 0x7ffb07027306 in mozilla::dom::ScriptLoader::EvaluateScript /builds/worker/checkouts/gecko/dom/script/ScriptLoader.cpp:2440
#22 0x7ffb07025653 in mozilla::dom::ScriptLoader::EvaluateScriptElement /builds/worker/checkouts/gecko/dom/script/ScriptLoader.cpp:2244
#23 0x7ffb0701bc8c in mozilla::dom::ScriptLoader::ProcessRequest /builds/worker/checkouts/gecko/dom/script/ScriptLoader.cpp:1884
#24 0x7ffb07016a1a in mozilla::dom::ScriptLoader::ProcessInlineScript /builds/worker/checkouts/gecko/dom/script/ScriptLoader.cpp:1318
#25 0x7ffb07000f02 in mozilla::dom::ScriptLoader::ProcessScriptElement /builds/worker/checkouts/gecko/dom/script/ScriptLoader.cpp:908
#26 0x7ffb06fffcb3 in mozilla::dom::ScriptElement::MaybeProcessScript /builds/worker/checkouts/gecko/dom/script/ScriptElement.cpp:182
#27 0x7ffaff71b7aa in nsHtml5TreeOpExecutor::RunScript /builds/worker/checkouts/gecko/parser/html/nsHtml5TreeOpExecutor.cpp:950
#28 0x7ffaff715c5e in nsHtml5TreeOpExecutor::RunFlushLoop /builds/worker/checkouts/gecko/parser/html/nsHtml5TreeOpExecutor.cpp:741
#29 0x7ffaff7239d4 in nsHtml5ExecutorFlusher::Run /builds/worker/checkouts/gecko/parser/html/nsHtml5StreamParser.cpp:174
#30 0x7ffafd76219e in mozilla::RunnableTask::Run /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:559
#31 0x7ffafd743e51 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:886
#32 0x7ffafd73f595 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:709
#33 0x7ffafd7401e4 in mozilla::TaskController::ProcessPendingMTTask /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:495
#34 0x7ffafd765ae1 in mozilla::detail::RunnableFunction<`lambda at /builds/worker/checkouts/gecko/xpcom/threads/TaskController.cpp:218:7'>::Run /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.h:548
#35 0x7ffafd795a8e in nsThread::ProcessNextEvent /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1199
#36 0x7ffafd7a62f1 in NS_ProcessNextEvent /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:480
#37 0x7ffafee92007 in mozilla::ipc::MessagePump::Run /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:85
#38 0x7ffafedae5f3 in MessageLoop::RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:363
#39 0x7ffafedae3ba in MessageLoop::Run /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:345
#40 0x7ffb07579b5c in nsBaseAppShell::Run /builds/worker/checkouts/gecko/widget/nsBaseAppShell.cpp:148
#41 0x7ffb07798227 in nsAppShell::Run /builds/worker/checkouts/gecko/widget/windows/nsAppShell.cpp:466
#42 0x7ffb0c0cff5e in XRE_RunAppShell /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:722
#43 0x7ffafedae5f3 in MessageLoop::RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:363
#44 0x7ffafedae3ba in MessageLoop::Run /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:345
#45 0x7ffb0c0cf518 in XRE_InitChildProcess /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:657
#46 0x7ff6e0c92953 in NS_internal_main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:375
#47 0x7ff6e0c9169b in wmain /builds/worker/checkouts/gecko/toolkit/xre/nsWindowsWMain.cpp:167
#48 0x7ff6e0d734e7 in __scrt_common_main_seh D:\a_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#49 0x7ffbb0d17613 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180017613)
#50 0x7ffbb0fe26b0 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x1800526b0)

SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/checkouts/gecko/xpcom/ds/PLDHashTable.cpp:546 in PLDHashTable::Remove
Shadow bytes around the buggy address:
0x119d234cbf00: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
0x119d234cbf80: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
0x119d234cc000: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
0x119d234cc080: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
0x119d234cc100: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
=>0x119d234cc180: fa fa fa fa fd fd fd fd fd fd fd[fd]fa fa fa fa
0x119d234cc200: fd fd fd fd fd fd fd fa fa fa fa fa fd fd fd fd
0x119d234cc280: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
0x119d234cc300: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
0x119d234cc380: fd fd fd fd fd fd fd fa fa fa fa fa fd fd fd fd
0x119d234cc400: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
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
==14772==ABORTING

Flags: sec-bounty?
Attached file ff.test2.js
Group: firefox-core-security → gfx-core-security
Component: Security → Graphics: Canvas2D
Keywords: csectype-uaf
Product: Firefox → Core

This looks like a child process shutdown issue, so I'm not sure it is actually exploitable. This looks like it could be a regression from bug 1839286, which changed ImageBitmapShutdownObserver recently.

Regressed by: 1839286
Summary: heap-use-after-free xpcom/ds/PLDHashTable.cpp:546 in PLDHashTable::Remove → heap-use-after-free xpcom/ds/PLDHashTable.cpp:546 in PLDHashTable::Remove with ImageBitmapShutdownObserver

(by not really exploitable, I mean that we don't run this code in the child process in release builds, only in ASan and debug builds...)

Hmm, I haven't reproduced yet, but I think this is the same as bug 1845372 except we're creating another image bitmap shutdown observer in the XPCOMShutdown phase (instead of after that phase). So the AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdownThreads) just needs to be changed to AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdown). I'll work on reproducing to confirm that.

Set release status flags based on info from the regressing bug 1839286

Assignee: nobody → tnikkel

(In reply to Andrew McCreight [:mccr8] from comment #3)

(by not really exploitable, I mean that we don't run this code in the child process in release builds, only in ASan and debug builds...)

Is that because we do a quick exit call without running any of the shutdown phases?

(In reply to Timothy Nikkel (:tnikkel) from comment #6)

Is that because we do a quick exit call without running any of the shutdown phases?

Yes, it is the call to ProcessChild::QuickExit() in ContentChild::ActorDestroy() under #ifndef NS_FREE_PERMANENT_DATA. Maybe we should enable that somehow in fuzzing builds where we don't care about leak checking. I'm not sure.

Keywords: sec-moderatesec-low

I wasn't able to reproduce, but I made builds with the proposed patch on try here

https://treeherder.mozilla.org/jobs?repo=try&revision=7d6c85198e29ce72c5e327b837e08ead39d57ced

Is it possible for you to download a build from that try link and see if it reproduces for you? If you haven't done that before you just click on the B of the type of build that you want, then "Artifacts and Debugging Tools" and then download target.zip from there. There are asan, fuzzing, debug, and regular opt builds there.

Flags: needinfo?(m.cooolie)

(In reply to Timothy Nikkel (:tnikkel) from comment #8)

I wasn't able to reproduce, but I made builds with the proposed patch on try here

https://treeherder.mozilla.org/jobs?repo=try&revision=7d6c85198e29ce72c5e327b837e08ead39d57ced

Is it possible for you to download a build from that try link and see if it reproduces for you? If you haven't done that before you just click on the B of the type of build that you want, then "Artifacts and Debugging Tools" and then download target.zip from there. There are asan, fuzzing, debug, and regular opt builds there.

no longer reproduce.

Flags: needinfo?(m.cooolie)

:tnikkel, I'd like to understand a bit more about what configuration might be required to trigger this issue. I've been unable to reproduce it locally. Could it be related to a hardware specific configuration?

(In reply to Jason Kratzer [:jkratzer] from comment #10)

:tnikkel, I'd like to understand a bit more about what configuration might be required to trigger this issue. I've been unable to reproduce it locally. Could it be related to a hardware specific configuration?

Not as far as I know. I suspect it's just very timing sensitive: we have to create an ImageBitmap in exactly the right shutdown phase, and normally we would try to avoid creating any new unnecessary objects in shutdown at all. So different os/cpu/environment can lead to differences in thread dispatching and what runs when. I only have access to macos this week and the reporter seems to be on Windows. Have you tried to reproduce anywhere?

It's also possible that this bug is the same as your bug 1846528, but we didn't have any reproduction or pernosco there so we weren't able to go any further.

PCOMShutdownThreads is the phase just after XPCOMShutdown and XPCOMShutdown is when we destory the ImageBitmapShutdownObserver, so we need to not create a new ImageBitmapShutdownObserver if we are in XPCOMShutdown or later.

Pushed by tnikkel@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/8bec97042dc0
Don't create a new ImageBitmapShutdownObserver if we are in XPCOMShutdown or later. r=gfx-reviewers,aosmond
Group: gfx-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 10 months ago
Resolution: --- → FIXED
Target Milestone: --- → 118 Branch

(In reply to Andrew McCreight [:mccr8] from comment #7)

(In reply to Timothy Nikkel (:tnikkel) from comment #6)

Is that because we do a quick exit call without running any of the shutdown phases?

Yes, it is the call to ProcessChild::QuickExit() in ContentChild::ActorDestroy() under #ifndef NS_FREE_PERMANENT_DATA. Maybe we should enable that somehow in fuzzing builds where we don't care about leak checking. I'm not sure.

Can someone provide an authoritative answer?
Should we adjust how this is fuzzed?

Flags: needinfo?(tnikkel)
Flags: sec-bounty? → sec-bounty+

(In reply to Frederik Braun [:freddy] from comment #15)

Can someone provide an authoritative answer?
Should we adjust how this is fuzzed?

I filed bug 1850021 on this.

I think Andrew answered this needinfo.

Flags: needinfo?(tnikkel)
Flags: qe-verify+
QA Whiteboard: [post-critsmash-triage]

I've followed the STR from comment 0 in order to reproduce the bug, but unfortunately it does not crash on my end. I'm using an affected asan Nightly build (20230822040001) on Win 11 x64.

After talking with Timothy on slack, it seems that the crash is not an easy one to reproduce, and we have to rely on the verification made in comment 9.

I'm removing the qe+ flag since there's nothing for QA to be done here.

Flags: qe-verify+
Whiteboard: [reporter-external] [client-bounty-form] [verif?] → [reporter-external] [client-bounty-form] [verif?][adv-main118+]
Group: core-security-release
Alias: CVE-2023-5175
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: