Assertion failure: IsInt21(imm21), at jit/arm64/vixl/Assembler-vixl.h:4283
Categories
(Core :: JavaScript: WebAssembly, defect, P1)
Tracking
()
People
(Reporter: gkw, Assigned: rhunt, NeedInfo)
References
(Blocks 1 open bug)
Details
(4 keywords, Whiteboard: [adv-main141+][adv-ESR140.1+][adv-ESR128.13+][adv-ESR115.26+])
Attachments
(9 files, 3 obsolete files)
|
2.38 MB,
application/x-javascript
|
Details | |
|
7.53 KB,
text/plain
|
Details | |
|
48 bytes,
text/x-phabricator-request
|
tjr
:
sec-approval+
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
phab-bot
:
approval-mozilla-beta+
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
phab-bot
:
approval-mozilla-esr128+
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
phab-bot
:
approval-mozilla-esr140+
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
phab-bot
:
approval-mozilla-esr115+
|
Details | Review |
|
267 bytes,
text/plain
|
Details |
See attachment.
(gdb) bt
#0 0x0000555558285a7d in MOZ_CrashSequence (aAddress=0x0, aLine=4283)
at /home/msf1/shell-cache/js-dbg-64-armsim64-linux-x86_64-761c3d69bb90/objdir-js/dist/include/mozilla/Assertions.h:248
#1 vixl::Assembler::ImmPCRelAddress (imm21=-1048584) at /home/msf1/trees/mozilla-central/js/src/jit/arm64/vixl/Assembler-vixl.h:4283
#2 vixl::Assembler::adr (this=this@entry=0x7fffffff8948, rd=..., imm21=-1048584, doc=...)
at /home/msf1/trees/mozilla-central/js/src/jit/arm64/vixl/MozAssembler-vixl.cpp:336
#3 0x0000555558285c3f in vixl::Assembler::adr (this=0x7fffffff8948, rd=..., label=0x7fffffff78f4)
at /home/msf1/trees/mozilla-central/js/src/jit/arm64/vixl/MozAssembler-vixl.cpp:349
#4 0x0000555558229ada in vixl::MacroAssembler::Adr (this=0x7fffffff8948, rd=..., label=0x7fffffff78f4)
at /home/msf1/trees/mozilla-central/js/src/jit/arm64/vixl/MacroAssembler-vixl.h:518
#5 0x00005555586dc710 in js::wasm::BaseCompiler::tableSwitch (this=this@entry=0x7fffffff7bd0, theTable=theTable@entry=0x7fffffff78f4,
switchValue=switchValue@entry=..., dispatchCode=dispatchCode@entry=0x7fffffff78dc)
at /home/msf1/trees/mozilla-central/js/src/wasm/WasmBaselineCompile.cpp:382
/snip
This seems to have occurred since m-c rev c1acdcb0c63c, gh rev 564a36e5a3aebd0c0d0645744cdc8d074c82b1c0 (late-Feb 2024, Firefox 125-approx).
Run with --fuzzing-safe --ion-offthread-compile=off --ion-eager, compile with AR=ar sh ../configure --enable-simulator=arm64 --enable-debug --enable-debug-symbols --with-ccache --enable-nspr-build --enable-ctypes --enable-gczeal --enable-rust-simd --disable-tests, tested on m-c rev 761c3d69bb90.
Setting needinfo? from our wasm gurus, Ryan and Yury, as a start.
| Reporter | ||
Comment 1•6 months ago
|
||
| Reporter | ||
Comment 2•6 months ago
|
||
Actually cc'ing our JIT folks as well in case it's not a wasm-only thing. Note that this seems ARM64-only - frame 5 of the backtrace seems to occur through this region of code:
#elif defined(JS_CODEGEN_ARM64)
AutoForbidPoolsAndNops afp(&masm,
/* number of instructions in scope = */ 4);
ScratchI32 scratch(*this);
ARMRegister s(scratch, 64);
ARMRegister v(switchValue, 64);
masm.Adr(s, theTable); // <-- here
masm.Add(s, s, Operand(v, vixl::LSL, 3));
masm.Ldr(s, MemOperand(s, 0));
masm.Br(s);
#else
MOZ_CRASH("BaseCompiler platform hook: tableSwitch");
#endif
Updated•6 months ago
|
| Assignee | ||
Comment 3•6 months ago
|
||
This test case has 131073 labels in the br_table. This appears to lead to the label theTable being too far away for the Adr instruction. This triggers the assertion the test case runs into (too large of an immediate to encode in the instruction). It's just a debug assertion though, so in release we'll continue on. We truncate the too large of immediate to fit in 21-bits [1].
So in effect we have:
theTable:
codePointerToTableEntry
codePointerToTableEntry
codePointerToTableEntry
...
codePointerToTableEntry
;; should be: adr entry, theTable
;; but actually is:
mov entry, pc - truncateInt21(offsetToTheTable)
add entry, tableIndex << 3
ldr entry, entry
br entry
So we get a pointer into JIT code that should be pointing at the beginning of the jump table, but actually points somewhere in the middle thanks to the truncate operation. Then we index into it and perform an indirect jump from the table.
If the attacker can control the JIT code well enough, they might be able to index into a constant pool and use that to get RCE.
| Assignee | ||
Comment 4•6 months ago
|
||
This only affects ARM64, and from looking at the users of Adr, only wasm baseline seems vulnerable. All other uses don't have a user controlled amount of space between the Adr and the label.
We have an implementation limit for number of br_table entries, but it's set way too high (1 million). Lowering it would be the easiest fix here.
| Assignee | ||
Comment 5•6 months ago
|
||
This seems like it would go all the way back to our first ARM64 build that supported wasm baseline. I can't find exactly which release that was, but I'm pretty sure it effects all releases.
| Assignee | ||
Comment 6•6 months ago
|
||
Running in release, I can get the test case to crash by jumping to 'null' but nothing more interesting than that.
| Assignee | ||
Comment 7•6 months ago
|
||
Here's the disassembly for the important part of the testcase:
jump table entries ...
0xab1475280d0 107fffcf adr x15, #+0xffff8 (addr 0xab1476280c8)
0xab1475280d4 8b000def add x15, x15, x0, lsl #3
0xab1475280d8 f94001ef ldr x15, [x15]
0xab1475280dc d61f01e0 br x15
The truncate is turning the effective address of the adr to actually be forwards instead of backwards, which is normally where the jump table is. That explains why I was always jumping into zero. There's no other code memory in use, so it's all zero.
| Assignee | ||
Comment 8•6 months ago
|
||
I've been able to tweak the example to generate a bunch of other functions in the module so that we start jumping to non-null addresses.
So I think an attacker probably could place specially crafted wasm code in other functions in the module to generate the constants they want in JIT code, then choose the right br_table size and label index to trigger a load of that constant and jump to it. Unless I'm missing some mitigating factor.
| Assignee | ||
Comment 9•6 months ago
|
||
Chrome has a limit on br_table sizes of 65_520 as opposed to our limit of 1 million (!) [1]. We should just adopt that to fix this bug. I don't know of a better way to obfuscate the fix then that. It would point to there being an issue with large br_table sizes, but nothing beyond that.
The alternative would be to update the VIXL assembler to emit a adrp + add immediate when the range is too large. However that's a difficult change to make, and I'd be more hesitant to uplift that widely. But at least it wouldn't point immediately at the br_table instruction.
| Assignee | ||
Comment 10•6 months ago
|
||
| Assignee | ||
Comment 11•6 months ago
|
||
| Assignee | ||
Comment 12•6 months ago
|
||
Comment on attachment 9494641 [details]
Bug 1971581 - wasm: Align br_table limits with V8. r?yury
Security Approval Request
- How easily could an exploit be constructed based on the patch?: Moderately difficult for a knowledgeable attacker? The patch points to a potential issue with very large br_table instructions. Constructing one is not too difficult, and if you do it with a debug build (for the assertion) on ARM64 you'll find that
adrinstruction is not being encoded with the right pc-relative offset. From there the attacker would need to find a way to embed their desired code pointer in a different wasm function and figure out the right combination of labels and jump index to jump to that code pointer. I don't know if another exploit is needed to leak an address of a code pointer to embed in the JIT code.
(test will land as a followup)
- 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 branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?: All branches, flags are correct
- If not all supported branches, which bug introduced the flaw?: None
- Do you have backports for the affected branches?: Yes
- If not, how different, hard to create, and risky will they be?: N/A
- How likely is this patch to cause regressions; how much testing does it need?: Very low risk, the fix just changes the limit on br_table size to match Chrome. I don't expect web compat issues for this reason.
- Is the patch ready to land after security approval is given?: Yes
- Is Android affected?: Yes
| Assignee | ||
Comment 13•6 months ago
|
||
I have tested on the JS shell from 115 and can trigger the issue. So confirmed that all branches are vulnerable.
Comment 14•6 months ago
|
||
Comment on attachment 9494641 [details]
Bug 1971581 - wasm: Align br_table limits with V8. r?yury
Approved to request uplift and land
Updated•6 months ago
|
Comment 15•6 months ago
|
||
Comment 16•5 months ago
|
||
| Assignee | ||
Comment 17•5 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D253675
Updated•5 months ago
|
Comment 18•5 months ago
|
||
firefox-beta Uplift Approval Request
- User impact if declined: Possible RCE in content process.
- Code covered by automated testing: no
- Fix verified in Nightly: yes
- Needs manual QE test: no
- Steps to reproduce for manual QE testing: N/A
- Risk associated with taking this patch: Low
- Explanation of risk level: It doesn't change any codegen, it just lowers a validation limit.
- String changes made/needed: N/A
- Is Android affected?: yes
Comment 19•5 months ago
|
||
Ryan, could you request uplift to all the branches affected? Thanks
| Assignee | ||
Comment 20•5 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D253675
Updated•5 months ago
|
Comment 21•5 months ago
|
||
firefox-release Uplift Approval Request
- User impact if declined: Possible RCE in content process
- Code covered by automated testing: no
- Fix verified in Nightly: yes
- Needs manual QE test: no
- Steps to reproduce for manual QE testing: N/A
- Risk associated with taking this patch: Low
- Explanation of risk level: It doesn't change any codegen, it just lowers a validation limit.
- String changes made/needed: N/A
- Is Android affected?: yes
| Assignee | ||
Comment 22•5 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D253675
Updated•5 months ago
|
Comment 23•5 months ago
|
||
firefox-esr128 Uplift Approval Request
- User impact if declined: Possible RCE in content process.
- Code covered by automated testing: no
- Fix verified in Nightly: yes
- Needs manual QE test: no
- Steps to reproduce for manual QE testing: N/A
- Risk associated with taking this patch: Low
- Explanation of risk level: It doesn't change any codegen, it just lowers a validation limit.
- String changes made/needed: N/A
- Is Android affected?: yes
| Assignee | ||
Comment 24•5 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D253675
Updated•5 months ago
|
| Assignee | ||
Comment 25•5 months ago
|
||
I've requested uplift for beta, release, esr 128, and esr 140. I didn't request one for esr 115 because my understanding is that's no longer active. If that's not the case I can request an uplift for that too.
Comment 26•5 months ago
|
||
firefox-esr140 Uplift Approval Request
- User impact if declined: Possible RCE in content process
- Code covered by automated testing: no
- Fix verified in Nightly: yes
- Needs manual QE test: no
- Steps to reproduce for manual QE testing: N/A
- Risk associated with taking this patch: Low
- Explanation of risk level: It doesn't change any codegen, it just lowers a validation limit
- String changes made/needed: N/A
- Is Android affected?: yes
Comment 27•5 months ago
|
||
(In reply to Ryan Hunt [:rhunt] from comment #25)
I've requested uplift for beta, release, esr 128, and esr 140. I didn't request one for esr 115 because my understanding is that's no longer active. If that's not the case I can request an uplift for that too.
esr 115 is still active, we ship it for Windows 7-8.1 and macOS 10.12-10.14 until at least September (potentially longer)
| Assignee | ||
Comment 28•5 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D253675
Updated•5 months ago
|
Comment 29•5 months ago
|
||
firefox-esr115 Uplift Approval Request
- User impact if declined: Possible RCE in content process
- Code covered by automated testing: no
- Fix verified in Nightly: yes
- Needs manual QE test: no
- Steps to reproduce for manual QE testing: N/A
- Risk associated with taking this patch: Low
- Explanation of risk level: It doesn't change any codegen, it just lowers a validation limit
- String changes made/needed: N/A
- Is Android affected?: yes
Comment 30•5 months ago
|
||
This is not a suitable uplift for a dot release since ESRs are affected.
Updated•5 months ago
|
Updated•5 months ago
|
Updated•5 months ago
|
Comment 31•5 months ago
|
||
| uplift | ||
Updated•5 months ago
|
Updated•5 months ago
|
Updated•5 months ago
|
Updated•5 months ago
|
Comment 32•5 months ago
|
||
| uplift | ||
Comment 33•5 months ago
|
||
Ryan, could you rebase your patch for ESR and request uplift again? It failed to apply cleanly to the branch, thanks
https://lando.moz.tools/D255160/
Updated•5 months ago
|
Comment 35•5 months ago
|
||
| uplift | ||
Updated•5 months ago
|
Updated•5 months ago
|
Comment 36•5 months ago
|
||
| uplift | ||
Updated•5 months ago
|
Updated•5 months ago
|
Updated•5 months ago
|
Updated•5 months ago
|
Updated•5 months ago
|
Updated•5 months ago
|
Comment 37•5 months ago
|
||
Comment 38•5 months ago
|
||
Comment 39•5 months ago
|
||
Updated•5 months ago
|
Comment 40•3 months ago
|
||
2 months ago, tjr placed a reminder on the bug using the whiteboard tag [reminder-test 2025-09-02] .
rhunt, please refer to the original comment to better understand the reason for the reminder.
Updated•3 months ago
|
Comment 41•3 months ago
|
||
Comment 42•3 months ago
|
||
Updated•2 months ago
|
Updated•4 days ago
|
Description
•