Closed Bug 1992902 (CVE-2025-13024) Opened 1 year ago Closed 11 months ago

SEGV on IsWriteableAddress

Categories

(Core :: JavaScript Engine: JIT, defect, P1)

Firefox 130
defect

Tracking

()

RESOLVED FIXED
146 Branch
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
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 #

Group: core-security → javascript-core-security

Moving toS:GC as this looks more like GC related bug.

Component: JavaScript Engine → JavaScript: GC

:jonco, how severe of a problem does this look?

Blocks: GC.stability
Flags: needinfo?(jcoppeard)

This looks like a problem updating the Ion activations so moving to the JIT component for a first look.

Component: JavaScript: GC → JavaScript Engine: JIT
Flags: needinfo?(jcoppeard)

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?

Flags: needinfo?(andrebargull)
Attached file (secure) (obsolete) —
Assignee: nobody → andrebargull
Status: NEW → ASSIGNED
Attached file (secure) —
Flags: needinfo?(andrebargull)

Is this a security problem? The actual crash looks like a null deref inside an assertion but the patch is quite large. Thanks.

Flags: needinfo?(andrebargull)

(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.)

Flags: needinfo?(andrebargull)
Blocks: sm-security
Severity: -- → S2
Priority: -- → P1
Attached file (secure) (obsolete) —
Attached file (secure) —

:anba, I noticed all your patches have now been reviewed. Are these patches ready to land and for sec-approval now?

Flags: needinfo?(andrebargull)
Attachment #9519176 - Attachment is obsolete: true
Attachment #9518973 - Attachment is obsolete: true

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
Flags: needinfo?(andrebargull)
Attachment #9519447 - Flags: sec-approval?

Comment on attachment 9519447 [details]
(secure)

sec-approval+ = dveditz
please wait until after December 15 to land the tests

Attachment #9519447 - Flags: sec-approval? → sec-approval+
Whiteboard: [reminder-test 2025-12-15]

Can these patches be landed now?

Flags: needinfo?(andrebargull)

Do we also want to backport to Beta? (This requires a separate Beta uplift request, right?)

Flags: needinfo?(andrebargull)

Yes, please also request a Beta uplift.

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 MTypedArraySubarray were treated as being side-effect free, but now only scalar replaced instructions have AliasSet::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
Attachment #9523440 - Flags: approval-mozilla-beta?
Attached file (secure) —

Will this land today?

Flags: needinfo?(andrebargull)
Group: javascript-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 11 months ago
Flags: needinfo?(andrebargull)
Resolution: --- → FIXED
Target Milestone: --- → 146 Branch
Attachment #9523440 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
QA Whiteboard: [sec] [uplift] [qa-triage-done-c146/b145]
Whiteboard: [reminder-test 2025-12-15] → [reminder-test 2025-12-15][adv-main145+]
Attached file advisory.txt —

Comment on attachment 9525026 [details]
advisory.txt

Please credit as : Project KillFuzz of Qrious Secure

Alias: CVE-2025-13024

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.

Flags: needinfo?(andrebargull)
Whiteboard: [reminder-test 2025-12-15][adv-main145+] → [adv-main145+]
Flags: sec-bounty?
Flags: sec-bounty? → sec-bounty+
Flags: needinfo?(andrebargull)
Group: core-security-release
Duplicate of this bug: 2051441
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: