Intermittent segfault in JITed code by PreBarrierFastPath for MIRType::Value on riscv64-simulator
Categories
(Core :: JavaScript Engine: JIT, defect, P5)
Tracking
()
People
(Reporter: csmantle, Assigned: csmantle)
References
(Blocks 1 open bug, Regression)
Details
(4 keywords, Whiteboard: [tier 3 platform only][adv-main146+][adv-esr140.6+])
Attachments
(4 files, 1 obsolete file)
Running program.js in a js shell on riscv64-simulator produces intermittent (4 in 15 consecutive runs) SIGSEGV:
$ ~/workspace/mozilla-firefox-dev/obj-x86_64-pc-linux-gnu/dist/bin/js ./program.js
AddressSanitizer:DEADLYSIGNAL
=================================================================
==3910502==ERROR: AddressSanitizer: SEGV on unknown address 0x3f529bb00000 (pc 0x55f64f314997 bp 0x7fff7ed850b0 sp 0x7fff7ed84c20 T0)
==3910502==The signal is caused by a READ memory access.
#0 0x55f64f314997 in long js::jit::Simulator::ReadMem<long>(long, js::jit::Instruction*) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:1482:13
#1 0x55f64f314997 in js::jit::Simulator::DecodeRVIType() /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:3463:21
#2 0x55f64f303e79 in js::jit::Simulator::InstructionDecode(js::jit::Instruction*) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:1831:7
#3 0x55f64f3347aa in void js::jit::Simulator::execute<false>() /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:1941:5
#4 0x55f64f3347aa in js::jit::Simulator::callInternal(unsigned char*) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:4060:5
#5 0x55f64f335115 in js::jit::Simulator::call(unsigned char*, int, ...) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:4125:3
#6 0x55f64f952430 in EnterJit(JSContext*, js::RunState&, unsigned char*) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/Jit.cpp:107:5
#7 0x55f64f952430 in js::jit::MaybeEnterJit(JSContext*, js::RunState&) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/Jit.cpp:255:10
#8 0x55f64d3152c5 in js::RunScript(JSContext*, js::RunState&) /home/mantle/workspace/mozilla-firefox-dev/js/src/vm/Interpreter.cpp:450:32
#9 0x55f64d3169d5 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) /home/mantle/workspace/mozilla-firefox-dev/js/src/vm/Interpreter.cpp:618:13
#10 0x55f64ee4962e in js::jit::DoCallFallback(JSContext*, js::jit::BaselineFrame*, js::jit::ICFallbackStub*, unsigned int, JS::Value*, JS::MutableHandle<JS::Value>) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/BaselineIC.cpp:1697:10
#11 0x55f64f309316 in js::jit::Simulator::SoftwareInterrupt() /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:1629:7
#12 0x55f64f3121e4 in js::jit::Simulator::DecodeRVIType() /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp
#13 0x55f64f303e79 in js::jit::Simulator::InstructionDecode(js::jit::Instruction*) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:1831:7
#14 0x55f64f3347aa in void js::jit::Simulator::execute<false>() /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:1941:5
#15 0x55f64f3347aa in js::jit::Simulator::callInternal(unsigned char*) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:4060:5
#16 0x55f64f335115 in js::jit::Simulator::call(unsigned char*, int, ...) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:4125:3
#17 0x55f64f952430 in EnterJit(JSContext*, js::RunState&, unsigned char*) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/Jit.cpp:107:5
#18 0x55f64f952430 in js::jit::MaybeEnterJit(JSContext*, js::RunState&) /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/Jit.cpp:255:10
#19 0x55f64d335518 in js::Interpret(JSContext*, js::RunState&) /home/mantle/workspace/mozilla-firefox-dev/js/src/vm/Interpreter.cpp:3315:40
#20 0x55f64d3152de in js::RunScript(JSContext*, js::RunState&) /home/mantle/workspace/mozilla-firefox-dev/js/src/vm/Interpreter.cpp:460:13
#21 0x55f64d31b5ea in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, js::AbstractFramePtr, JS::MutableHandle<JS::Value>) /home/mantle/workspace/mozilla-firefox-dev/js/src/vm/Interpreter.cpp:851:13
#22 0x55f64d31be99 in js::Execute(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, JS::MutableHandle<JS::Value>) /home/mantle/workspace/mozilla-firefox-dev/js/src/vm/Interpreter.cpp:884:10
#23 0x55f64d5bd92a in ExecuteScript(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSScript*>, JS::MutableHandle<JS::Value>) /home/mantle/workspace/mozilla-firefox-dev/js/src/vm/CompilationAndEvaluation.cpp:548:10
#24 0x55f64d5bdccc in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>) /home/mantle/workspace/mozilla-firefox-dev/js/src/vm/CompilationAndEvaluation.cpp:572:10
#25 0x55f64d1de88b in RunFile(JSContext*, char const*, _IO_FILE*, CompileUtf8, bool, bool) /home/mantle/workspace/mozilla-firefox-dev/js/src/shell/js.cpp:1315:10
#26 0x55f64d1dd57b in Process(JSContext*, char const*, bool, FileKind) /home/mantle/workspace/mozilla-firefox-dev/js/src/shell/js.cpp
#27 0x55f64d160a3b in ProcessArgs(JSContext*, js::cli::OptionParser*) /home/mantle/workspace/mozilla-firefox-dev/js/src/shell/js.cpp:12060:10
#28 0x55f64d160a3b in Shell(JSContext*, js::cli::OptionParser*) /home/mantle/workspace/mozilla-firefox-dev/js/src/shell/js.cpp:12313:12
#29 0x55f64d14fe5f in main /home/mantle/workspace/mozilla-firefox-dev/js/src/shell/js.cpp:12716:12
#30 0x7f529c627674 (/usr/lib/libc.so.6+0x27674) (BuildId: 4fe011c94a88e8aeb6f2201b9eb369f42b4a1e9e)
#31 0x7f529c627728 in __libc_start_main (/usr/lib/libc.so.6+0x27728) (BuildId: 4fe011c94a88e8aeb6f2201b9eb369f42b4a1e9e)
#32 0x55f64d058d08 in _start (/home/mantle/workspace/mozilla-firefox-dev/obj-x86_64-pc-linux-gnu/dist/bin/js+0x2a42d08) (BuildId: 1cca63e781db4dbd800668e9b1706abc)
==3910502==Register values:
rax = 0x000007ea53760000 rbx = 0x0000522000001900 rcx = 0x000055f651d39c03 rdx = 0x00002fd4a325a0a0
rdi = 0x0000522000001908 rsi = 0xf2f2f2f2f2f8f8f8 rbp = 0x00007fff7ed850b0 rsp = 0x00007fff7ed84c20
r8 = 0xf2f8f2f2f2f2f2f8 r9 = 0xf2f8f8f8f8f8f2f2 r10 = 0xffffffffffffffff r11 = 0x0000000000000000
r12 = 0x00003f529bb00000 r13 = 0x00003f529bb00000 r14 = 0x000010006fda8988 r15 = 0x00000a4400000322
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/mantle/workspace/mozilla-firefox-dev/js/src/jit/riscv64/Simulator-riscv64.cpp:1482:13 in long js::jit::Simulator::ReadMem<long>(long, js::jit::Instruction*)
==3910502==ABORTING
Aborted (core dumped) ~/workspace/mozilla-firefox-dev/obj-x86_64-pc-linux-gnu/dist/bin/js ./program.js
To know the exact location in JITed code, I applied the following patch:
diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
index a9bb7ad2e3..33e26559f1 100644
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -7970,6 +7970,8 @@
MOZ_ASSERT(temp2 != PreBarrierReg);
MOZ_ASSERT(temp3 != PreBarrierReg);
+ AutoCreatedBy acb(*this, __FUNCTION__);
+
// Load the GC thing in temp1.
if (type == MIRType::Value) {
unboxGCThingForGCBarrier(Address(PreBarrierReg, 0), temp1);
@@ -7990,6 +7992,9 @@
#endif
// Load the chunk address in temp2.
+ for (auto i = 0; i < static_cast<int>(type); i++) {
+ nop();
+ }
andPtr(Imm32(int32_t(~gc::ChunkMask)), temp1, temp2);
// If the GC thing is in the nursery, we don't need to barrier it.
Then loaded the coredump in GDB and examined the number of nops around pc. Turns out that the crash happened in riscv64 code generated by MacroAssembler::emitPreBarrierFastPath, at https://searchfox.org/firefox-main/rev/a7d872e9d28072c2dd6d688d1b6c0493fcf7e94c/js/src/jit/MacroAssembler.cpp#7998-7999.
| Assignee | ||
Comment 1•10 months ago
|
||
| Assignee | ||
Updated•10 months ago
|
| Assignee | ||
Comment 2•10 months ago
|
||
Commit:
○ poumyyrz rmalicdem@mozilla.com 2025-10-31 03:05:43 main 908469b7
│ Bug 1997370 - Enable toolbar customization in Nightly r=android-reviewers,Roger
Updated•10 months ago
|
Comment 3•10 months ago
|
||
I would be worried if fuzzers did not caught this issue in Tier-1 platforms. I CC'ed a few persons in case you have questions.
If you are using the simulator on Linux x64, you might be able to use rr to record executions, and rewind the execution to find what part of the program generated the memory.
Comment 4•10 months ago
•
|
||
I'd suggest stepping through the code emitted by emitPreBarrierFastPath to see if the instructions do what you'd expect.
Skimming the code quickly, I noticed that unboxGCThingForGCBarrier for riscv calls ExtractBits with JSVAL_TAG_SHIFT - 1. Is that right or should it be just JSVAL_TAG_SHIFT?
Updated•10 months ago
|
| Assignee | ||
Comment 5•10 months ago
|
||
(In reply to Jan de Mooij [:jandem] from comment #4)
I'd suggest stepping through the code emitted by
emitPreBarrierFastPathto see if the instructions do what you'd expect.
Yes, I'm trying to understand the nature of this bug by replaying a crashing case recorded by rr record --chaos.
Skimming the code quickly, I noticed that
unboxGCThingForGCBarrierfor riscv callsExtractBitswithJSVAL_TAG_SHIFT - 1. Is that right or should it be justJSVAL_TAG_SHIFT?
It should be JSVAL_TAG_SHIFT since the parameter is size; See (^1). The crash disappears after fixing this (0 out of 35 consecutive runs).
| Assignee | ||
Comment 6•10 months ago
|
||
Updated•10 months ago
|
| Assignee | ||
Comment 7•10 months ago
|
||
Jan, I wonder if I should request sec-approval to land this?
Comment 8•10 months ago
|
||
(In reply to Rong Bao [:csmantle] from comment #7)
Jan, I wonder if I should request sec-approval to land this?
Oh I already queued the patch for landing. RISC-V is a tier 3 platform so I think it's fine to just land it.
| Assignee | ||
Comment 10•10 months ago
|
||
(In reply to Jan de Mooij [:jandem] from comment #8)
Oh I already queued the patch for landing. RISC-V is a tier 3 platform so I think it's fine to just land it.\
Sure. Just for completeness (wrt. sec-approval questionnaire), this bug originates directly from Bug 1800431, so maybe backporting it to branches supporting riscv64 JIT would be nice.
Updated•10 months ago
|
Comment 11•10 months ago
|
||
firefox-beta Uplift Approval Request
- User impact if declined: Fixes potential crashes with Firefox builds for RISC-V.
- Code covered by automated testing: no
- Fix verified in Nightly: no
- Needs manual QE test: no
- Steps to reproduce for manual QE testing:
- Risk associated with taking this patch: low
- Explanation of risk level: Code is only used on RISC-V (tier 3 platform)
- String changes made/needed: N/A
- Is Android affected?: no
Comment 12•10 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D271395
Comment 13•10 months ago
|
||
firefox-esr140 Uplift Approval Request
- User impact if declined: Fixes crashes with Firefox builds for RISC-V (tier 3 platform)
- Code covered by automated testing: no
- Fix verified in Nightly: no
- Needs manual QE test: no
- Steps to reproduce for manual QE testing:
- Risk associated with taking this patch: low
- Explanation of risk level: Code is only used on RISC-V (tier 3 platform)
- String changes made/needed: N/A
- Is Android affected?: no
Comment 14•10 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D271395
Comment 15•10 months ago
|
||
Set release status flags based on info from the regressing bug 1800431
Comment 16•10 months ago
|
||
Updated•10 months ago
|
| Assignee | ||
Comment 17•10 months ago
•
|
||
I wonder should this bug be tagged with one of those sec-* severity tags?
(needinfo-ing Nicolas for the initial flags setup in comment 3.)
Comment 18•10 months ago
|
||
(In reply to Rong Bao [:csmantle] from comment #17)
I wonder should this bug be tagged with one of those sec-* severity tags?
Probably yes, especially since we are backtracking patches.
Updated•10 months ago
|
Updated•10 months ago
|
Updated•10 months ago
|
Comment 20•10 months ago
|
||
Rong Bao: Unfortunately this bug does not qualify for our bounty program because we only cover the platforms that are in versions of Firefox shipped by Mozilla. In addition this would be disqualified because you appear to be the maintainer or contributor to this part of the code.
| Assignee | ||
Comment 21•10 months ago
•
|
||
(In reply to Daniel Veditz [:dveditz] from comment #20)
Rong Bao: Unfortunately this bug does not qualify for our bounty program because we only cover the platforms that are in versions of Firefox shipped by Mozilla.
Thanks for clarification. However, I do notice that https://launchpad.net/~mozillateam/+archive/ubuntu/ppa/+packages ships various beta and esr versions targeting riscv64. Should this be considered as "shipped by Mozilla"? Or are there any official documents explicitly stating that scope of bounty program excludes Tier-3 platforms or said PPA?
In addition this would be disqualified because you appear to be the maintainer or contributor to this part of the code.
I beg to differ on this point. As per https://www.mozilla.org/en-US/security/bug-bounty/, the only rule that could justify this decision is:
- You must not have written the buggy code or otherwise been involved in contributing the buggy code to the Mozilla project.
I'd like to point out that I am not the contributor of the buggy code -- it's proposed by Yahan Lu (<yahan@iscas.ac.cn>) in 2023 with no further modifications since then; Xref https://searchfox.org/firefox-main/rev/80de3bfc92ff505f458fe9a03a74f09ae0733d8c/js/src/jit/riscv64/MacroAssembler-riscv64.h#847. Thus, I am neither the author nor the regressor. My contribution started in July, 2025 as both part of my tutor's assignment and personal interest. I am not, in any way, affiliated with Yahan or their organization. So, I am not convinced that the bullet point mentioned is a valid blocker.
Comment 22•10 months ago
|
||
I'd like to point out that I am not the contributor of the buggy code
I apologize for not checking deeper. someone said you were the module owner for that port, which generally confers responsibility for the code whether you wrote that specific bit or not. But it's a murky area for ports. In any case that was a secondary thing.
I do notice that https://launchpad.net/~mozillateam/+archive/ubuntu/ppa/+packages ships various beta and esr versions targeting riscv64. Should this be considered as "shipped by Mozilla"?
That launchpad "MozillaTeam" is not us. "Shipped by Mozilla" means the binaries available from https://www.firefox.com/en-US/download/all/.
| Assignee | ||
Comment 23•10 months ago
|
||
(In reply to Daniel Veditz [:dveditz] from comment #22)
someone said you were the module owner for that port, which generally confers responsibility for the code whether you wrote that specific bit or not.
I'm flattered to know that my contributions are recognized, but I'd have to say that I'm not the module owner either. But yes, it's a minor point and I'm glad that we can reach consensus here.
That launchpad "MozillaTeam" is not us. "Shipped by Mozilla" means the binaries available from https://www.firefox.com/en-US/download/all/.
Thanks, after following this link I see that "MozillaTeam" at Launchpad is indeed a third-party vendor. I'll check more carefully next time.
Updated•10 months ago
|
Updated•10 months ago
|
Comment 24•10 months ago
|
||
| uplift | ||
Updated•10 months ago
|
Updated•10 months ago
|
Updated•10 months ago
|
Updated•9 months ago
|
Updated•9 months ago
|
Updated•9 months ago
|
Updated•9 months ago
|
Updated•9 months ago
|
Updated•7 months ago
|
Updated•3 months ago
|
Description
•