SEGV on IsWriteableAddress
Categories
(Core :: JavaScript Engine: JIT, defect, P1)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox-esr115 | --- | unaffected |
| firefox-esr140 | --- | unaffected |
| firefox144 | --- | wontfix |
| firefox145 | + | fixed |
| firefox146 | + | fixed |
People
(Reporter: phambao1340, Assigned: anba)
References
(Blocks 2 open bugs, Regression)
Details
(4 keywords, Whiteboard: [adv-main145+])
Attachments
(4 files, 2 obsolete files)
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
dveditz
:
sec-approval+
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
phab-bot
:
approval-mozilla-beta+
|
Details | Review |
|
53 bytes,
text/plain
|
Details |
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
Steps to reproduce:
Run following javascript
var s = "";
function func_1() {
for (var i = 16; i < 10000; i++) {
const arr = new Int32Array(Int32Array);
arr[i] = 0;
var sub_1 = arr.subarray(1);
arr[0] = 1;
}
switch (sub_1 % 2) {
case 0:
}
}
for (var i =0;i<1000;i++){
func_1();
}
Actual results:
/home/zx/firefox/obj-fuzzbuild/dist/bin/js --ion-warmup-threshold=100 --ion-check-range-analysis --ion-extra-checks --disable-oom-functions --fuzzing-safe crash.js
[COV] no shared memory bitmap available, skipping
[COV] edge counters initialized. Shared memory: (null) with 415985 edges
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==507059==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x59a46f513715 bp 0x7ffc9ead50d0 sp 0x7ffc9ead50b0 T507059)
==507059==The signal is caused by a READ memory access.
==507059==Hint: address points to the zero page.
/home/zx/firefox/obj-fuzzbuild/dist/bin/llvm-symbolizer: error: '[anon:js-executable-memory]': No such file or directory
#0 0x59a46f513715 in IsWriteableAddress(void*) /home/zx/firefox/js/src/gc/Nursery.cpp:993:11
#1 0x59a46f513715 in js::Nursery::forwardBufferPointer(unsigned long*) /home/zx/firefox/js/src/gc/Nursery.cpp:1022:5
#2 0x59a46fe6dd30 in js::jit::UpdateIonJSFrameForMinorGC(JSRuntime*, js::jit::JSJitFrameIter const&) /home/zx/firefox/js/src/jit/JitFrames.cpp:1171:13
#3 0x59a46fe6dd30 in js::jit::UpdateJitActivationsForMinorGC(JSRuntime*) /home/zx/firefox/js/src/jit/JitFrames.cpp:1528:11
#4 0x59a46f51600f in js::Nursery::doCollection(js::gc::AutoGCSession&, JS::GCOptions, JS::GCReason) /home/zx/firefox/js/src/gc/Nursery.cpp:1725:3
#5 0x59a46f5151b5 in js::Nursery::collect(JS::GCOptions, JS::GCReason) /home/zx/firefox/js/src/gc/Nursery.cpp:1442:31
#6 0x59a46f4a76fc in js::gc::GCRuntime::collectNursery(JS::GCOptions, JS::GCReason, js::gcstats::PhaseKind) /home/zx/firefox/js/src/gc/GC.cpp:5055:13
#7 0x59a46f48f52d in js::gc::GCRuntime::minorGC(JS::GCReason, js::gcstats::PhaseKind) /home/zx/firefox/js/src/gc/GC.cpp:5026:3
#8 0x59a46f46f68f in void* js::gc::CellAllocator::RetryNurseryAlloc<(js::AllowGC)1>(JSContext*, JS::TraceKind, js::gc::AllocKind, unsigned long, js::gc::AllocSite*) /home/zx/firefox/js/src/gc/Allocator.cpp:107:23
#9 0x59a46e749f71 in js::NativeObject* js::gc::CellAllocator::NewObject<js::NativeObject, (js::AllowGC)1>(JSContext*, js::gc::AllocKind, js::gc::Heap, JSClass const*, js::gc::AllocSite*) /home/zx/firefox/js/src/gc/Allocator-inl.h:112:16
#10 0x59a46e748a5f in js::NativeObject* js::gc::CellAllocator::NewCell<js::NativeObject, (js::AllowGC)1, js::gc::AllocKind&, js::gc::Heap&, JSClass const*&, js::gc::AllocSite*&>(JSContext*, js::gc::AllocKind&, js::gc::Heap&, JSClass const*&, js::gc::AllocSite*&) /home/zx/firefox/js/src/gc/Allocator-inl.h:35:12
#11 0x59a46e748a5f in js::NativeObject* JSContext::newCell<js::NativeObject, (js::AllowGC)1, js::gc::AllocKind&, js::gc::Heap&, JSClass const*&, js::gc::AllocSite*&>(js::gc::AllocKind&, js::gc::Heap&, JSClass const*&, js::gc::AllocSite*&) /home/zx/firefox/js/src/vm/JSContext-inl.h:359:10
#12 0x59a46e748a5f in js::NativeObject::create(JSContext*, js::gc::AllocKind, js::gc::Heap, JS::Handle<js::SharedShape*>, js::gc::AllocSite*) /home/zx/firefox/js/src/vm/NativeObject-inl.h:482:28
#13 0x59a46ee6d40c in js::FixedLengthTypedArrayObject* js::NativeObject::create<js::FixedLengthTypedArrayObject>(JSContext*, js::gc::AllocKind, js::gc::Heap, JS::Handle<js::SharedShape*>, js::gc::AllocSite*) /home/zx/firefox/js/src/vm/NativeObject.h:745:26
#14 0x59a46ee6d40c in js::FixedLengthTypedArrayObject* (anonymous namespace)::NewTypedArrayObject<js::FixedLengthTypedArrayObject>(JSContext*, JSClass const*, JS::Handle<JSObject*>, js::gc::AllocKind, js::gc::Heap) /home/zx/firefox/js/src/vm/TypedArrayObject.cpp:395:10
#15 0x59a46ee73b85 in (anonymous namespace)::FixedLengthTypedArrayObjectTemplate<int>::newBuiltinClassInstance(JSContext*, js::gc::AllocKind, js::gc::Heap) /home/zx/firefox/js/src/vm/TypedArrayObject.cpp:917:12
#16 0x59a46ee732ef in (anonymous namespace)::FixedLengthTypedArrayObjectTemplate<int>::makeInstance(JSContext*, JS::Handle<js::ArrayBufferObjectMaybeShared*>, unsigned long, unsigned long, JS::Handle<JSObject*>, js::gc::Heap) /home/zx/firefox/js/src/vm/TypedArrayObject.cpp:943:13
#17 0x59a46eddc1bd in js::TypedArraySubarrayWithLength(JSContext*, JS::Handle<js::TypedArrayObject*>, long, long) /home/zx/firefox/js/src/vm/TypedArrayObject.cpp:4275:7
#18 0x2b5764cc36bd ([anon:js-executable-memory]+0x1f6bd)
==507059==Register values:
rax = 0x0000000000000000 rbx = 0x00007ffc9ead5820 rcx = 0x00002c853d37ffd8 rdx = 0x000073fcff545068
rdi = 0x000073fcff534b10 rsi = 0x00007ffc9ead57c0 rbp = 0x00007ffc9ead50d0 rsp = 0x00007ffc9ead50b0
r8 = 0x0000000000000000 r9 = 0x000000000007ffd8 r10 = 0x0000000000000000 r11 = 0x0000000000000000
r12 = 0x00007ffc9ead50f8 r13 = 0x000073fcff534b10 r14 = 0x0000000000000040 r15 = 0x00007ffc9ead5168
UndefinedBehaviorSanitizer can not provide additional info.
SUMMARY: UndefinedBehaviorSanitizer: SEGV /home/zx/firefox/js/src/gc/Nursery.cpp:993:11 in IsWriteableAddress(void*)
==507059==ABORTING
[00:19:30] [gecko]/home/zx #
Updated•1 year ago
|
Comment 1•1 year ago
|
||
Moving toS:GC as this looks more like GC related bug.
Comment 2•1 year ago
|
||
:jonco, how severe of a problem does this look?
Comment 3•1 year ago
|
||
This looks like a problem updating the Ion activations so moving to the JIT component for a first look.
Comment 4•1 year ago
|
||
This looks like it's probably related to bug 1980613, although I can trigger it without actually triggering scalar replacement. Here's a reduced testcase:
function foo() {
var subarray;
for (var i = 0; i < 10000; i++) {
const arr = new Int32Array(2);
arr[0] = 1;
subarray = arr.subarray(1);
arr[1] = 1;
}
return subarray;
}
foo();
It looks like what's happening is that we trigger a gc while allocating the subarray. We have an ArrayBufferViewElements shared between the two stores. It was spilled to the stack before allocating the subarray. For reasons I haven't yet worked through, we expect it to contain a forwarding pointer, but it doesn't.
Anba, can you take a look?
| Assignee | ||
Comment 5•1 year ago
|
||
Updated•1 year ago
|
| Assignee | ||
Comment 6•1 year ago
|
||
| Assignee | ||
Updated•1 year ago
|
Comment 7•1 year ago
|
||
Is this a security problem? The actual crash looks like a null deref inside an assertion but the patch is quite large. Thanks.
| Assignee | ||
Comment 8•1 year ago
|
||
(In reply to Andrew McCreight [:mccr8] from comment #7)
Is this a security problem? The actual crash looks like a null deref inside an assertion but the patch is quite large. Thanks.
Yes, it's a security issue. The address is modifiable through the test case, for example using arr[0] = 0xaabb_ccdd will crash with IsWriteableAddress (ptr=0xaabbccdd). (It's also easily possible to use 64-bit addresses. Either by writing to arr[0] and arr[1] or by switching Int32Array with BigInt64Array.)
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
| Assignee | ||
Comment 9•1 year ago
|
||
| Assignee | ||
Comment 10•1 year ago
|
||
Comment 11•11 months ago
|
||
:anba, I noticed all your patches have now been reviewed. Are these patches ready to land and for sec-approval now?
Updated•11 months ago
|
Updated•11 months ago
|
| Assignee | ||
Comment 12•11 months ago
|
||
Comment on attachment 9519447 [details]
(secure)
Security Approval Request
- How easily could an exploit be constructed based on the patch?: It shouldn't be directly obvious that the patch fixes a bug around GC behaviour. That being said the affected MIR instruction is only used for
TypedArray.prototype.subarray, so an attacker will know where to focus their attention. It also helps a bit that the patch replaces some auto-generated MIR/LIR definitions with hand-written code, which makes the patch appear larger than it actually is and may help to distract from the actual bug fix. - 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?: Release (Firefox 143)
- If not all supported branches, which bug introduced the flaw?: Bug 1980613
- Do you have backports for the affected branches?: No
- If not, how different, hard to create, and risky will they be?: Patch should apply to Beta/Release without any merge conflicts.
- How likely is this patch to cause regressions; how much testing does it need?: Unlikely to cause regressions. The code paths are covered by existing tests.
- Is the patch ready to land after security approval is given?: Yes
- Is Android affected?: Yes
Updated•11 months ago
|
Comment 13•11 months ago
|
||
Comment on attachment 9519447 [details]
(secure)
sec-approval+ = dveditz
please wait until after December 15 to land the tests
Updated•11 months ago
|
| Assignee | ||
Comment 15•11 months ago
|
||
Do we also want to backport to Beta? (This requires a separate Beta uplift request, right?)
Comment 16•11 months ago
|
||
Yes, please also request a Beta uplift.
Comment 17•11 months ago
|
||
firefox-beta Uplift Approval Request
- User impact if declined: Security bug allowing writes to arbitrary memory.
- Code covered by automated testing: yes
- 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: Before this change all
MTypedArraySubarraywere treated as being side-effect free, but now only scalar replaced instructions haveAliasSet::None()and are allowed to be recovered after bailout. That means we're now applying fewer JIT optimisations which can lead to problems. - String changes made/needed: None
- Is Android affected?: yes
| Assignee | ||
Comment 18•11 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D268254
Comment 20•11 months ago
|
||
Comment 21•11 months ago
|
||
Updated•11 months ago
|
Updated•11 months ago
|
Comment 22•11 months ago
|
||
| uplift | ||
Updated•11 months ago
|
Updated•11 months ago
|
Comment 23•11 months ago
|
||
| Reporter | ||
Comment 24•11 months ago
|
||
Comment on attachment 9525026 [details]
advisory.txt
Please credit as : Project KillFuzz of Qrious Secure
Updated•11 months ago
|
Comment 25•10 months ago
|
||
a month ago, dveditz placed a reminder on the bug using the whiteboard tag [reminder-test 2025-12-15] .
anba, please refer to the original comment to better understand the reason for the reminder.
Updated•10 months ago
|
Updated•9 months ago
|
| Assignee | ||
Updated•9 months ago
|
Comment 26•9 months ago
|
||
Comment 27•9 months ago
|
||
Updated•4 months ago
|
Description
•