[WASM] JIT Optimization Triggered TRAP on unknown address 0x000000000000
Categories
(Core :: JavaScript: WebAssembly, defect, P1)
Tracking
()
People
(Reporter: xiangwei1895, Assigned: jandem)
References
(Blocks 1 open bug)
Details
(Keywords: csectype-jit, reporter-external, sec-high, Whiteboard: [adv-main136+][adv-esr128.8+][adv-esr115.21+])
Attachments
(4 files)
|
75.60 KB,
text/javascript
|
Details | |
|
48 bytes,
text/x-phabricator-request
|
dmeehan
:
approval-mozilla-beta+
dmeehan
:
approval-mozilla-esr115+
dmeehan
:
approval-mozilla-esr128+
tjr
:
sec-approval+
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
290 bytes,
text/plain
|
Details |
Steps to reproduce:
My env:
Ubuntu 22.04 TLS
gecko-dev e85232b4b28ecc970240d39203e417d1c320623c
Build args:
../configure --disable-jemalloc --enable-fuzzing --enable-gczeal --enable-debug --enable-optimize --disable-shared-js --enable-address-sanitizer
Execution:
./dist/bin/js poc.js
Actual results:
AddressSanitizer:DEADLYSIGNAL
==2407027==ERROR: AddressSanitizer: TRAP on unknown address 0x000000000000 (pc 0x10c1009be66a bp 0x7fffe45805a0 sp 0x7fffe4580580 T0)
#0 0x10c1009be66a (<unknown module>)
#1 0x10c100971be7 (<unknown module>)
#2 0x10c1009eace9 (<unknown module>)
#3 0x10c1008ced80 (<unknown module>)
#4 0x55b8d3651cf2 in EnterBaseline(JSContext*, EnterJitData&) /data/workspace/gecko-dev/js/src/jit/BaselineJIT.cpp:143:5
#5 0x55b8d3651cf2 in js::jit::EnterBaselineInterpreterAtBranch(JSContext*, js::InterpreterFrame*, unsigned char*) /data/workspace/gecko-dev/js/src/jit/BaselineJIT.cpp:199:26
#6 0x55b8d1002b9e in js::Interpret(JSContext*, js::RunState&) /data/workspace/gecko-dev/js/src/vm/Interpreter.cpp:2107:17
#7 0x55b8d0fc8763 in MaybeEnterInterpreterTrampoline(JSContext*, js::RunState&) /data/workspace/gecko-dev/js/src/vm/Interpreter.cpp:433:10
#8 0x55b8d0fc781c in js::RunScript(JSContext*, js::RunState&) /data/workspace/gecko-dev/js/src/vm/Interpreter.cpp:502:13
#9 0x55b8d0fcf251 in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, js::AbstractFramePtr, JS::MutableHandle<JS::Value>) /data/workspace/gecko-dev/js/src/vm/Interpreter.cpp:893:13
#10 0x55b8d0fcfdba in js::Execute(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, JS::MutableHandle<JS::Value>) /data/workspace/gecko-dev/js/src/vm/Interpreter.cpp:926:10
#11 0x55b8d13bf4d2 in ExecuteScript(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSScript*>, JS::MutableHandle<JS::Value>) /data/workspace/gecko-dev/js/src/vm/CompilationAndEvaluation.cpp:601:10
#12 0x55b8d13bfae8 in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>) /data/workspace/gecko-dev/js/src/vm/CompilationAndEvaluation.cpp:625:10
#13 0x55b8d0e2677a in RunFile(JSContext*, char const*, _IO_FILE*, CompileUtf8, bool, bool) /data/workspace/gecko-dev/js/src/shell/js.cpp:1311:10
#14 0x55b8d0e2523a in Process(JSContext*, char const*, bool, FileKind) /data/workspace/gecko-dev/js/src/shell/js.cpp
#15 0x55b8d0d83a04 in ProcessArgs(JSContext*, js::cli::OptionParser*) /data/workspace/gecko-dev/js/src/shell/js.cpp:11752:10
#16 0x55b8d0d83a04 in Shell(JSContext*, js::cli::OptionParser*) /data/workspace/gecko-dev/js/src/shell/js.cpp:12006:12
#17 0x55b8d0d6f43d in main /data/workspace/gecko-dev/js/src/shell/js.cpp:12421:12
#18 0x7f925de79d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: TRAP (<unknown module>)
==2407027==ABORTING
Expected results:
exit normally.
Updated•8 months ago
|
Updated•8 months ago
|
| Assignee | ||
Comment 1•8 months ago
•
|
||
I can reproduce this. It looks like we fail the check in this code in boxValue while boxing an int32 value.
This means we're creating an Int32Value but the payload doesn't fit in 32 bits. This is dangerous because it'd create an invalid JS::Value and if the payload is sufficiently large it could corrupt the tag bits.
Updated•8 months ago
|
Updated•8 months ago
|
| Assignee | ||
Comment 2•8 months ago
|
||
Here's a reduced test case that fails intermittently with rr record -h about 1 in every 10-20 runs with a Linux x64 debug build:
let buf = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 18, 3, 94, 120, 0, 96, 3, 127, 127, 127, 1, 127, 96, 2, 127, 127, 2, 127, 127, 3, 3, 2, 1, 2, 4, 1, 0, 7, 8, 1, 4, 109, 97, 105, 110, 0, 0, 10, 77, 2, 10, 0, 65, 0, 65, 0, 16, 1, 33, 0, 11, 64, 1, 4, 127, 3, 127, 65, 3, 11, 3, 127, 3, 127, 65, 3, 33, 3, 3, 127, 3, 127, 65, 3, 33, 5, 3, 127, 32, 5, 65, 1, 107, 34, 5, 4, 64, 12, 1, 11, 65, 5, 11, 4, 64, 11, 65, 0, 11, 26, 32, 3, 4, 64, 11, 65, 34, 11, 4, 64, 11, 65, 2, 11, 11, 11]);
let module = new WebAssembly.Module(buf);
let instance = new WebAssembly.Instance(module);
for (var i = 0; i < 10000; i++) {
instance.exports.main(0, 0, 0);
}
What happens is this:
- A Wasm-Ion function stores a stack result value of 3 (
LInteger,LWasmStoreSlot) and then returns.
0x5574bbc1052: mov $0x3,%eax
0x5574bbc1057: mov %eax,(%rdx)
0x5574bbc1059: mov $0x2,%eax
0x5574bbc105e: pop %rbp
0x5574bbc105f: ret
- This returns to a Wasm-Baseline function where we
popthis value intorax(IIRC this happens inpopBlockResultsunderdoReturn). The value that's popped is0x7ffd00000003: the low bits are what we expect (3) but the high bits are garbage because the callee stored an int32.
0x5574bb9106a: lea -0x28(%rbp),%rsp
0x5574bb9106e: mov %eax,%eax
0x5574bb91070: mov %eax,0x24(%rsp)
0x5574bb91074: pop %rax
0x5574bb91075: jmp 0x5574bb9107b
0x5574bb9107a: int3
0x5574bb9107b: add $0x20,%rsp
0x5574bb9107f: pop %rbp
0x5574bb91080: ret
- We return to the JIT entry stub and do this:
// No widening is required, as the value is boxed.
masm.boxNonDouble(JSVAL_TYPE_INT32, ReturnReg, JSReturnOperand);
This comment (added in bug 1736531) seems wrong because boxNonDouble does expect a widened (= upper bits zero) value; that's what's causing the assertion failure.
| Assignee | ||
Comment 3•8 months ago
|
||
In GenerateDirectCallFromJit we already widen i32 return values so I think we just need to follow that for the JitEntry stub.
| Assignee | ||
Comment 4•8 months ago
|
||
| Assignee | ||
Comment 5•8 months ago
|
||
| Assignee | ||
Comment 6•8 months ago
|
||
I think sec-high is accurate: because the value in the register is OR-ed into the Int32Value bits, it's possible to construct an arbitrary SymbolValue or BigIntValue as these have similar type tags but with some additional bits set. Pulling this off also requires controlling the 'garbage' value that's stored in the stack slot, but that's likely not too difficult with stack spraying.
Updated•8 months ago
|
| Assignee | ||
Comment 7•8 months ago
|
||
Comment on attachment 9465096 [details]
Bug 1946004 - Widen i32 return values in GenerateJitEntry. r?rhunt!
Security Approval Request
- How easily could an exploit be constructed based on the patch?: Not very easy.
- 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
- 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?: This patch should apply or it will be easy to backport.
- How likely is this patch to cause regressions; how much testing does it need?: It's a small and simple patch and very unlikely to cause regressions.
- Is the patch ready to land after security approval is given?: Yes
- Is Android affected?: Yes
Comment 8•8 months ago
|
||
Comment on attachment 9465096 [details]
Bug 1946004 - Widen i32 return values in GenerateJitEntry. r?rhunt!
Approved to land and request uplift
Updated•8 months ago
|
| Assignee | ||
Comment 10•8 months ago
|
||
Comment on attachment 9465096 [details]
Bug 1946004 - Widen i32 return values in GenerateJitEntry. r?rhunt!
Beta/Release Uplift Approval Request
- User impact if declined/Reason for urgency: Security bugs or crashes.
- Is this code covered by automated tests?: Yes
- Has the fix been verified in Nightly?: No
- Needs manual test from QE?: No
- If yes, steps to reproduce:
- List of other uplifts needed: None
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): It's a small patch that matches code elsewhere (ensures the upper bits of an int32 register are zero).
- String changes made/needed: N/A
- Is Android affected?: Yes
Comment 11•8 months ago
|
||
| Reporter | ||
Updated•8 months ago
|
Comment 13•8 months ago
|
||
Comment on attachment 9465096 [details]
Bug 1946004 - Widen i32 return values in GenerateJitEntry. r?rhunt!
Approved for 136.0b7
Comment 14•8 months ago
|
||
| uplift | ||
Updated•8 months ago
|
Updated•8 months ago
|
Comment 15•8 months ago
|
||
Comment on attachment 9465096 [details]
Bug 1946004 - Widen i32 return values in GenerateJitEntry. r?rhunt!
Approved for 128.8esr
Comment 16•8 months ago
|
||
| uplift | ||
Updated•8 months ago
|
Comment 17•8 months ago
|
||
Comment on attachment 9465096 [details]
Bug 1946004 - Widen i32 return values in GenerateJitEntry. r?rhunt!
Approved for 115.21esr
Comment 18•8 months ago
|
||
| uplift | ||
Updated•8 months ago
|
Updated•8 months ago
|
Updated•8 months ago
|
Comment 19•7 months ago
|
||
Updated•7 months ago
|
Comment 20•6 months ago
|
||
2 months ago, tjr placed a reminder on the bug using the whiteboard tag [reminder-test 2025-04-15] .
jandem, please refer to the original comment to better understand the reason for the reminder.
| Assignee | ||
Updated•6 months ago
|
Comment 21•6 months ago
|
||
Comment 22•6 months ago
|
||
Updated•3 months ago
|
Description
•