crash in [@ mozilla::dom::FlipYDataSourceSurface]
Categories
(Core :: Graphics: Canvas2D, defect, P3)
Tracking
()
People
(Reporter: tsmith, Assigned: lsalzman)
References
(Blocks 1 open bug)
Details
(Keywords: crash, pernosco, testcase, Whiteboard: [bugmon:bisected,confirmed])
Crash Data
Attachments
(2 files)
Found while fuzzing m-c 20240209-b17a56f7d0a8 (--enable-address-sanitizer --enable-fuzzing)
To reproduce via Grizzly Replay:
$ pip install fuzzfetch grizzly-framework
$ python -m fuzzfetch -a --fuzzing -n firefox
$ python -m grizzly.replay.bugzilla ./firefox/firefox <bugid>
==240681==ERROR: AddressSanitizer: SEGV on unknown address 0x7fd27783f000 (pc 0x7fd2941a30ab bp 0x7ffc1a738c30 sp 0x7ffc1a738a80 T0)
==240681==The signal is caused by a WRITE memory access.
#0 0x7fd2941a30ab in swap<unsigned char> /builds/worker/fetches/sysroot-x86_64-linux-gnu/usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/move.h:194:11
#1 0x7fd2941a30ab in iter_swap<unsigned char *, unsigned char *> /builds/worker/fetches/sysroot-x86_64-linux-gnu/usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_algobase.h:148:7
#2 0x7fd2941a30ab in swap_ranges<unsigned char *, unsigned char *> /builds/worker/fetches/sysroot-x86_64-linux-gnu/usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_algobase.h:177:2
#3 0x7fd2941a30ab in mozilla::dom::FlipYDataSourceSurface(mozilla::gfx::DataSourceSurface*) /builds/worker/checkouts/gecko/dom/canvas/ImageBitmap.cpp:375:5
#4 0x7fd29419fad6 in mozilla::dom::ImageBitmap::CreateImageBitmapInternal(nsIGlobalObject*, mozilla::gfx::SourceSurface*, mozilla::Maybe<mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits>> const&, mozilla::dom::ImageBitmapOptions const&, bool, bool, bool, gfxAlphaType, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/canvas/ImageBitmap.cpp:1073:15
#5 0x7fd2941aa45d in mozilla::dom::ImageBitmap::CreateInternal(nsIGlobalObject*, mozilla::dom::CanvasRenderingContext2D&, mozilla::Maybe<mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits>> const&, mozilla::dom::ImageBitmapOptions const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/canvas/ImageBitmap.cpp:1435:10
#6 0x7fd2941adaff in mozilla::dom::ImageBitmap::Create(nsIGlobalObject*, mozilla::dom::HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrOffscreenCanvasOrImageBitmapOrVideoFrameOrBlobOrCanvasRenderingContext2DOrImageData const&, mozilla::Maybe<mozilla::gfx::IntRectTyped<mozilla::gfx::UnknownUnits>> const&, mozilla::dom::ImageBitmapOptions const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/canvas/ImageBitmap.cpp:1832:19
#7 0x7fd2913e5acb in nsGlobalWindowInner::CreateImageBitmap(mozilla::dom::HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrOffscreenCanvasOrImageBitmapOrVideoFrameOrBlobOrCanvasRenderingContext2DOrImageData const&, mozilla::dom::ImageBitmapOptions const&, mozilla::ErrorResult&) /builds/worker/checkouts/gecko/dom/base/nsGlobalWindowInner.cpp:7368:10
#8 0x7fd29339af7e in createImageBitmap /builds/worker/workspace/obj-build/dom/bindings/./WindowBinding.cpp:19051:64
#9 0x7fd29339af7e in mozilla::dom::Window_Binding::createImageBitmap_promiseWrapper(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) /builds/worker/workspace/obj-build/dom/bindings/./WindowBinding.cpp:19117:13
#10 0x7fd293e3e3e5 in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::MaybeCrossOriginObjectThisPolicy, mozilla::dom::binding_detail::ConvertExceptionsToPromises>(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/dom/bindings/BindingUtils.cpp:3258:13
#11 0x7fd29e089c95 in CallJSNative /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:480:13
#12 0x7fd29e089c95 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:574:12
#13 0x7fd29e0af095 in InternalCall /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:641:10
#14 0x7fd29e0af095 in CallFromStack /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:646:10
#15 0x7fd29e0af095 in js::Interpret(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:3061:16
#16 0x7fd29e088a17 in MaybeEnterInterpreterTrampoline /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:394:10
#17 0x7fd29e088a17 in js::RunScript(JSContext*, js::RunState&) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:452:13
#18 0x7fd29e089dfe in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:606:13
#19 0x7fd29e08bd86 in InternalCall /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:641:10
#20 0x7fd29e08bd86 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:673:8
#21 0x7fd29e67b213 in js::CallSelfHostedFunction(JSContext*, JS::Handle<js::PropertyName*>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /builds/worker/checkouts/gecko/js/src/vm/SelfHosting.cpp:1585:10
#22 0x7fd29e1ed8bf in AsyncFunctionResume(JSContext*, JS::Handle<js::AsyncFunctionGeneratorObject*>, ResumeKind, JS::Handle<JS::Value>) /builds/worker/checkouts/gecko/js/src/vm/AsyncFunction.cpp:151:8
#23 0x7fd29e55ba3f in AsyncFunctionPromiseReactionJob /builds/worker/checkouts/gecko/js/src/builtin/Promise.cpp:2127:12
#24 0x7fd29e55ba3f in PromiseReactionJob(JSContext*, unsigned int, JS::Value*) /builds/worker/checkouts/gecko/js/src/builtin/Promise.cpp:2190:12
#25 0x7fd29e089c95 in CallJSNative /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:480:13
#26 0x7fd29e089c95 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:574:12
#27 0x7fd29e08bd86 in InternalCall /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:641:10
#28 0x7fd29e08bd86 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>, js::CallReason) /builds/worker/checkouts/gecko/js/src/vm/Interpreter.cpp:673:8
#29 0x7fd29e249f8b in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/checkouts/gecko/js/src/vm/CallAndConstruct.cpp:119:10
#30 0x7fd292635cd5 in mozilla::dom::PromiseJobCallback::Call(mozilla::dom::BindingCallContext&, JS::Handle<JS::Value>, mozilla::ErrorResult&) /builds/worker/workspace/obj-build/dom/bindings/./PromiseBinding.cpp:83:8
#31 0x7fd28d55c83a in Call /builds/worker/workspace/obj-build/dist/include/mozilla/dom/PromiseBinding.h:198:12
#32 0x7fd28d55c83a in Call /builds/worker/workspace/obj-build/dist/include/mozilla/dom/PromiseBinding.h:211:12
#33 0x7fd28d55c83a in mozilla::PromiseJobRunnable::Run(mozilla::AutoSlowOperation&) /builds/worker/checkouts/gecko/xpcom/base/CycleCollectedJSContext.cpp:210:18
#34 0x7fd28d5332de in mozilla::CycleCollectedJSContext::PerformMicroTaskCheckPoint(bool) /builds/worker/checkouts/gecko/xpcom/base/CycleCollectedJSContext.cpp:712:17
#35 0x7fd28d5345af in mozilla::CycleCollectedJSContext::AfterProcessTask(unsigned int) /builds/worker/checkouts/gecko/xpcom/base/CycleCollectedJSContext.cpp:499:3
#36 0x7fd28f806bac in XPCJSContext::AfterProcessTask(unsigned int) /builds/worker/checkouts/gecko/js/xpconnect/src/XPCJSContext.cpp:1444:28
#37 0x7fd28d7dbbd9 in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:1237:24
#38 0x7fd28d7e8d8a in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:480:10
#39 0x7fd28f48c2c3 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/checkouts/gecko/ipc/glue/MessagePump.cpp:107:5
#40 0x7fd28f2b4a4a in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:370:10
#41 0x7fd28f2b4a4a in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:363:3
#42 0x7fd28f2b4a4a in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:345:3
#43 0x7fd298c5d7e9 in nsBaseAppShell::Run() /builds/worker/checkouts/gecko/widget/nsBaseAppShell.cpp:148:27
#44 0x7fd298e63ff2 in nsAppShell::Run() /builds/worker/checkouts/gecko/widget/gtk/nsAppShell.cpp:470:33
#45 0x7fd29dc37b3e in XRE_RunAppShell() /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:721:20
#46 0x7fd28f2b4a4a in RunInternal /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:370:10
#47 0x7fd28f2b4a4a in RunHandler /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:363:3
#48 0x7fd28f2b4a4a in MessageLoop::Run() /builds/worker/checkouts/gecko/ipc/chromium/src/base/message_loop.cc:345:3
#49 0x7fd29dc370e3 in XRE_InitChildProcess(int, char**, XREChildData const*) /builds/worker/checkouts/gecko/toolkit/xre/nsEmbedFunctions.cpp:656:34
#50 0x55640b24a53c in content_process_main /builds/worker/checkouts/gecko/browser/app/../../ipc/contentproc/plugin-container.cpp:57:28
#51 0x55640b24a53c in main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:375:18
#52 0x7fd2b5e29d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#53 0x7fd2b5e29e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#54 0x55640b16e848 in _start (/home/user/workspace/browsers/m-c-20240209114116-fuzzing-asan-opt/firefox+0xdc848) (BuildId: d7e2b3c0365615acb02f090fdc8c595f41e0ee44)
Comment 1•9 months ago
|
||
Testcase crashes using the initial build (mozilla-central 20240209093717-b17a56f7d0a8) but not with tip (mozilla-central 20240209214145-9c7562b79131.)
Unable to bisect testcase (Start build didn't crash!):
Start: b17a56f7d0a828b62b52f572c8237345bf64786f (20240209093717)
End: 9c7562b7913101280cd24aef6e3839c02f297816 (20240209214145)
BuildFlags: BuildFlags(asan=True, tsan=False, debug=False, fuzzing=True, coverage=False, valgrind=False, no_opt=False, fuzzilli=False, nyx=False)
Removing bugmon keyword as no further action possible. Please review the bug and re-add the keyword for further analysis.
Comment 2•9 months ago
|
||
I wasn't able to get this to crash in a debug build. Perhaps there are some relevants prefs flipped?
Also bugmon seems a little confused?
Reporter | ||
Comment 3•9 months ago
|
||
A Pernosco session is available here: https://pernos.co/debug/f8vtIYpoc3rKW9Ve9BnDWQ/index.html
Hmm I guess that test is a bit flaky with some builds.
Comment 4•9 months ago
|
||
The code in FlipYDataSourceSurface seems reasonable, maybe some mixup handling the snapshot from the canvas?
Updated•9 months ago
|
Updated•9 months ago
|
Updated•9 months ago
|
Comment 5•9 months ago
|
||
I can reproduce this.
Comment 6•9 months ago
|
||
When the crash does occur, the memory at srcBufferPtr
is readable, but not writable. I added the following code:
fprintf(stderr, "JIMB: FlipYDataSourceSurface: %d\n", srcSize.height);
fprintf(stderr, "first byte: %p last byte: %p\n",
srcBufferPtr,
(srcBufferPtr + stride * srcSize.height - 1));
fprintf(stderr, "JIMB: read first byte: %d\n", *srcBufferPtr);
fprintf(stderr, "JIMB: read last byte: %d\n", *(srcBufferPtr + stride * srcSize.height - 1));
fprintf(stderr, "JIMB: write first byte:\n");
(*srcBufferPtr)++;
fprintf(stderr, "JIMB: write last byte:\n");
(*(srcBufferPtr + stride * srcSize.height - 1))++;
and got the following output:
JIMB: FlipYDataSourceSurface: 150
first byte: 0x7f7af0b10000 last byte: 0x7f7af0b3bf1f
JIMB: read first byte: 0
JIMB: read last byte: 0
JIMB: write first byte:
Program /home/jimb/moz/central/obj-release-debug/dist/bin/firefox (pid = 2378076) received signal 11.
Comment 7•9 months ago
|
||
The problem does not reproduce consistently. It crashes in about one run out of three.
Comment 8•9 months ago
•
|
||
[Edit: the below makes it sound as if the DataSourceSurface
is created first, and then the page protections get changed. I now believe the order is the opposite: the pages are mapped read-only in response to the SnapshotShmem
message, and then the DataSourceSurface
is created to point to them. The DataSourceSurface
's buffer never dangles: it was read-only from its creation.]
In the Pernosco recording, the data of the DataSourceSurface
passed to FlipYDataSourceSurface
starts at 0x7f062b9fb000.
This address was previously made read-only by a PCanvas::SnapshotShmem
IPDL message, when it calls mmap
to map in the shmem handle it received. It passes that mmap
call an address of 0, meaning that the kernel may choose any address it likes; it chooses the exact same address the DataSourceSurface
was using, 0x7f062b9fb000. It should only do this if that address is unmapped, meaning that the DataSourceSurface
's buffer had previously been freed, leaving it dangling.
Comment 9•9 months ago
|
||
Tentatively, it seems like, when CanvasChild::GetDataSurface
is able to find aTextureId
in mTextureInfo
, it tries to create a SourceSurfaceRawData
that points into that TextureInfo
's mSnapshotShmem
, which maps its contents read-only. This then runs afoul of ImageBitmap::CreateImageBitmapInternal
's expectation that it can call FlipYDataSourceSurface
on its contents.
Comment 10•8 months ago
•
|
||
:lsalzman confirms that the memory FlipYDataSourceSurface
is trying to write to in the crashes is deliberately mapped read-only, but that that's probably a bug and it needs to be mapped read-write anyway. This means the crash does not indicate a dangling pointer, so this is probably not security-sensitive. Tyler, do you want to re-flag this?
Reporter | ||
Updated•8 months ago
|
Comment 11•8 months ago
|
||
Severity and priority were set based on sec high. Adjusting.
Assignee | ||
Comment 12•8 months ago
|
||
Comment 13•8 months ago
|
||
Assignee | ||
Updated•8 months ago
|
Comment 14•8 months ago
|
||
bugherder |
Updated•8 months ago
|
Updated•8 months ago
|
Updated•8 months ago
|
Comment 15•8 months ago
|
||
The patch landed in nightly and beta is affected.
:lsalzman, is this bug important enough to require an uplift?
- If yes, please nominate the patch for beta approval.
- If no, please set
status-firefox124
towontfix
.
For more information, please visit BugBot documentation.
Assignee | ||
Updated•8 months ago
|
Description
•