Wild deref in js::CheckTracedThing<js::Shape>
Categories
(Core :: JavaScript Engine: JIT, defect, P1)
Tracking
()
People
(Reporter: lukas.bernhard, Assigned: jandem)
References
(Blocks 2 open bugs, Regression)
Details
(5 keywords, Whiteboard: [adv-main125+])
Attachments
(3 files)
48 bytes,
text/x-phabricator-request
|
RyanVM
:
approval-mozilla-beta+
tjr
:
sec-approval+
|
Details | Review |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
173 bytes,
text/plain
|
Details |
Steps to reproduce:
On git commit 28cc363411d2029aed04c969c8f98785cae110db the attached sample crashes the js-shell when invoked as obj-x86_64-pc-linux-gnu/dist/bin/js --fuzzing-safe --gc-zeal=10 crash.js
Bisecting the issue points to commit 0f80a6542954802e72888f3a2e43136a9a56eb65 related to bug 1863939.
function probe(value) {
let originalPrototype, newPrototype;
let handler = {
get(target, key, receiver) {
return Reflect.get(target, key, receiver);
},
};
try {
originalPrototype = Object.getPrototypeOf(value);
newPrototype = new Proxy(originalPrototype, handler);
Object.setPrototypeOf(value, newPrototype);
} catch (e) {}
}
const v0 = [];
function f1() {
Object.defineProperty(v0, 5, { configurable: true, get: f1 });
try { v0.toReversed(); } catch (e) {}
probe([].__proto__);
}
f1();
#0 js::CheckTracedThing<js::Shape> (trc=trc@entry=0x7fffffe35a10, thing=0x2726717dab80) at js/src/gc/Marking.cpp:136
#1 0x0000555557f2621c in js::gc::TraceEdgeInternal (trc=0x7fffffe35a10, thingp=0x7ffff54f90e8, Shape=0x555555a43546 "cacheir-weak-shape")
at js/src/gc/Tracer.h:109
#2 js::TraceSameZoneCrossCompartmentEdge<js::Shape*> (trc=trc@entry=0x7fffffe35a10, dst=dst@entry=0x7ffff54f90e8, name=0x555555a43546 "cacheir-weak-shape")
at js/src/gc/Marking.cpp:529
#3 0x0000555558534288 in js::jit::TraceCacheIRStub<js::jit::ICCacheIRStub> (trc=trc@entry=0x7fffffe35a10, stub=stub@entry=0x7ffff54f90a8,
stubInfo=0x7ffff55c6c00) at js/src/jit/CacheIRCompiler.cpp:1289
#4 0x00005555580c26d4 in js::jit::ICCacheIRStub::trace (this=0x7ffff54f90a8, trc=0x7fffffe35a10) at js/src/jit/BaselineIC.cpp:458
#5 0x00005555587a4968 in js::jit::TraceBaselineStubFrame (trc=0x7fffffe35a10, frame=...) at js/src/jit/JitFrames.cpp:1172
#6 js::jit::TraceJitActivation (trc=0x7fffffe35a10, activation=<optimised out>) at js/src/jit/JitFrames.cpp:1472
#7 js::jit::TraceJitActivations (cx=cx@entry=0x7ffff743ec00, trc=trc@entry=0x7fffffe35a10) at js/src/jit/JitFrames.cpp:1517
#8 0x0000555557f6f092 in js::gc::GCRuntime::traceRuntimeCommon (this=this@entry=0x7ffff742f798, trc=trc@entry=0x7fffffe35a10,
traceOrMark=traceOrMark@entry=js::gc::GCRuntime::TraceRuntime) at js/src/gc/RootMarking.cpp:303
#9 0x0000555557f61c66 in js::gc::GCRuntime::traceRuntimeForMinorGC (this=0x7ffff742f798, trc=0x7fffffe35a10, session=...)
at js/src/gc/RootMarking.cpp:258
#10 js::Nursery::traceRoots (this=this@entry=0x7ffff7431860, session=..., mover=...) at js/src/gc/Nursery.cpp:1634
#11 0x0000555557f5ee2f in js::Nursery::doCollection (this=this@entry=0x7ffff7431860, session=..., options=options@entry=JS::GCOptions::Shrink,
reason=reason@entry=JS::GCReason::EVICT_NURSERY) at js/src/gc/Nursery.cpp:1494
#12 0x0000555557f5e302 in js::Nursery::collect (this=0x7ffff7431860, options=JS::GCOptions::Shrink, reason=JS::GCReason::EVICT_NURSERY)
at js/src/gc/Nursery.cpp:1264
#13 0x0000555557ed5b7d in js::gc::GCRuntime::collectNursery (this=this@entry=0x7ffff742f798, options=JS::GCOptions::Shrink,
reason=reason@entry=JS::GCReason::EVICT_NURSERY, phase=phase@entry=js::gcstats::PhaseKind::EVICT_NURSERY_FOR_MAJOR_GC)
at js/src/gc/GC.cpp:4750
#14 0x0000555557eceac2 in js::gc::GCRuntime::collectNurseryFromMajorGC (this=this@entry=0x7ffff742f798, reason=<optimised out>)
at js/src/gc/GC.cpp:3893
#15 0x0000555557ece17c in js::gc::GCRuntime::endPreparePhase (this=this@entry=0x7ffff742f798, reason=reason@entry=JS::GCReason::DEBUG_GC)
at js/src/gc/GC.cpp:2830
#16 0x0000555557ed4c25 in js::gc::GCRuntime::incrementalSlice (this=this@entry=0x7ffff742f798, budget=..., reason=reason@entry=JS::GCReason::DEBUG_GC,
budgetWasIncreased=false) at js/src/gc/GC.cpp:3733
#17 0x0000555557ed81fe in js::gc::GCRuntime::gcCycle (this=this@entry=0x7ffff742f798, nonincrementalByAPI=false, budgetArg=...,
reason=reason@entry=JS::GCReason::DEBUG_GC) at js/src/gc/GC.cpp:4322
#18 0x0000555557ed9b44 in js::gc::GCRuntime::collect (this=this@entry=0x7ffff742f798, nonincrementalByAPI=false, budget=...,
reason=reason@entry=JS::GCReason::DEBUG_GC) at js/src/gc/GC.cpp:4513
#19 0x0000555557ea60d7 in js::gc::GCRuntime::runDebugGC (this=this@entry=0x7ffff742f798) at js/src/gc/GC.cpp:4976
#20 0x0000555557eddba0 in js::gc::CellAllocator::PreAllocChecks<(js::AllowGC)1> (cx=0x7ffff743ec00, kind=<optimised out>)
at js/src/gc/Allocator.cpp:257
#21 0x00005555572513b4 in js::gc::CellAllocator::AllocNurseryOrTenuredCell<(JS::TraceKind)0, (js::AllowGC)1> (cx=cx@entry=0x7ffff743ec00,
allocKind=js::gc::AllocKind::OBJECT2_BACKGROUND, thingSize=40, heap=js::gc::Heap::Default, site=site@entry=0x7ffff559b978)
at js/src/gc/Allocator-inl.h:114
#22 0x0000555557251238 in js::gc::CellAllocator::NewObject<js::NativeObject, (js::AllowGC)1> (cx=cx@entry=0x7ffff743ec00,
kind=kind@entry=js::gc::AllocKind::OBJECT2_BACKGROUND, heap=heap@entry=js::gc::Heap::Default, clasp=clasp@entry=0x55555905cca0 <js::PlainObject::class_>,
site=site@entry=0x7ffff559b978) at js/src/gc/Allocator-inl.h:94
#23 0x000055555724fee5 in js::gc::CellAllocator::NewCell<js::NativeObject, (js::AllowGC)1, js::gc::AllocKind&, js::gc::Heap&, JSClass const*&, js::gc::AllocSite*&> (cx=0x7ffff743ec00, args=<optimised out>, args=<optimised out>, args=<optimised out>, args=<optimised out>)
at js/src/gc/Allocator-inl.h:35
#24 JSContext::newCell<js::NativeObject, (js::AllowGC)1, js::gc::AllocKind&, js::gc::Heap&, JSClass const*&, js::gc::AllocSite*&> (this=0x7ffff743ec00,
args=<optimised out>, args=<optimised out>, args=<optimised out>, args=<optimised out>) at js/src/vm/JSContext-inl.h:359
#25 js::NativeObject::create (cx=0x7ffff743ec00, kind=js::gc::AllocKind::OBJECT2_BACKGROUND, heap=js::gc::Heap::Default, shape=..., site=0x7ffff559b978)
at js/src/vm/NativeObject-inl.h:495
#26 0x000055555729ef8c in js::NativeObject::create<js::PlainObject> (cx=0x7ffff743ec00, kind=js::gc::AllocKind::OBJECT2_BACKGROUND, shape=...,
site=0x7ffff559b978, heap=<optimised out>) at js/src/vm/NativeObject.h:762
#27 js::NewPlainObjectBaselineFallback (cx=0x7ffff743ec00, shape=..., allocKind=js::gc::AllocKind::OBJECT2_BACKGROUND, site=0x7ffff559b978)
at js/src/vm/Interpreter.cpp:5101
#28 0x00002af92f171aee in ?? ()
#29 0x00000000000000cf in ?? ()
#30 0x00007fffffe36200 in ?? ()
Reporter | ||
Updated•1 year ago
|
Reporter | ||
Comment 1•1 year ago
|
||
js::CheckTracedThing<js::Shape> (trc=trc@entry=0x7fffffdfcf00, thing=0x1e8675ddab80)
at js/src/gc/Marking.cpp:136
136 if (IsForwarded(thing)) {
(gdb) x/i $rip
=> 0x555557f22ea6 <_ZN2js16CheckTracedThingINS_5ShapeEEEvP8JSTracerPT_+38>: mov (%rbx),%rax
(gdb) i r rbx
rbx 0x1e8675ddab80 33562851912576
Updated•1 year ago
|
Updated•1 year ago
|
Comment 2•1 year ago
|
||
Set release status flags based on info from the regressing bug 1863939
:jandem, since you are the author of the regressor, bug 1863939, could you take a look? Also, could you set the severity field?
For more information, please visit BugBot documentation.
Updated•1 year ago
|
Comment 3•1 year ago
|
||
Haven't confirmed, but giving an initial sec-rating based on Lukas' description
Assignee | ||
Comment 4•1 year ago
|
||
I'm looking into this.
More reduced test:
function f() {
var v0 = [];
Object.defineProperty(v0, 0, {get: f});
try { v0.toReversed(); } catch {}
var handler = {
get(target, key, receiver) {
return Reflect.get(target, key, receiver);
}
};
var proxy = new Proxy(Object.prototype, handler);
Object.setPrototypeOf(Array.prototype, proxy);
}
gczeal(10);
f();
Updated•1 year ago
|
Assignee | ||
Comment 5•1 year ago
•
|
||
What's happening is:
- We have an active Baseline stub on the stack, a Sparse GetElement stub.
- This stub ends up calling function
f
recursively due to the0
element getter. f
also changesArray.prototype
's proto to a new (proxy) object, so the originalArray.prototype
shape is now dead.- The Baseline CacheIR stub from (1) is still active on the stack. We trace it in
TraceWeakBaselineStubFrame => TraceCacheIRStub
wheretrc->traceWeakEdges()
is false, so we don't trace the now dead shape. - We later call
TraceWeakCacheIRStub
where we returnfalse
when we notice the dead shape, butTraceWeakBaselineStubFrame
ignores this return value. - Next time we trace the BaselineStub frame, we find the same stub but a shape field is now garbage and we crash.
Potential fix is to always trace weak edges in TraceCacheIRStub
when called for Baseline stub frames. That fixes the test locally.
Bug 1863939 may have exposed this, but I think this goes back to bug 1837620.
More reduced test:
function f() {
try { arr.toReversed(); } catch {}
var handler = {get() { return arr[0]; }};
var proxy = new Proxy(Object.prototype, handler);
Object.setPrototypeOf(Array.prototype, proxy);
}
var arr = [];
Object.defineProperty(arr, 0, {get: f});
gczeal(10);
f();
Updated•1 year ago
|
Updated•1 year ago
|
Assignee | ||
Comment 6•1 year ago
|
||
Assignee | ||
Comment 7•1 year ago
|
||
Assignee | ||
Updated•1 year ago
|
Assignee | ||
Comment 8•1 year ago
|
||
Comment on attachment 9394738 [details]
Bug 1888892 - Trace all fields in TraceWeakCacheIRStub. r?jonco!
Security Approval Request
- How easily could an exploit be constructed based on the patch?: Not easily. It's hard to trigger this.
- 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 and beta
- If not all supported branches, which bug introduced the flaw?: Bug 1837620
- Do you have backports for the affected branches?: Yes
- If not, how different, hard to create, and risky will they be?: Should apply or be easy to backport.
- How likely is this patch to cause regressions; how much testing does it need?: Unlikely to cause regressions.
- Is the patch ready to land after security approval is given?: Yes
- Is Android affected?: Yes
Comment 9•1 year ago
|
||
Comment on attachment 9394738 [details]
Bug 1888892 - Trace all fields in TraceWeakCacheIRStub. r?jonco!
If you can get this uplifted before the deadline (tomorrow) then approved, otherwise let's hold it until next release
Comment 10•1 year ago
|
||
Comment on attachment 9394739 [details]
Bug 1888892 - Add test and comment. r?jonco!
I'm going to flag the test so i remember to come back here and add a reminder flag for when the test should land.
Reporter | ||
Updated•1 year ago
|
Assignee | ||
Comment 11•1 year ago
|
||
Comment on attachment 9394738 [details]
Bug 1888892 - Trace all fields in TraceWeakCacheIRStub. r?jonco!
Beta/Release Uplift Approval Request
- User impact if declined: Security bug, 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): The patch is pretty simple. Instead of returning immediately after seeing a dead field it returns after processing all fields.
- String changes made/needed:
- Is Android affected?: Yes
Comment 12•1 year ago
|
||
![]() |
||
Comment 13•1 year ago
|
||
Comment 14•1 year ago
|
||
Comment on attachment 9394738 [details]
Bug 1888892 - Trace all fields in TraceWeakCacheIRStub. r?jonco!
Approved for 125.0b9.
Updated•1 year ago
|
Comment 15•1 year ago
|
||
uplift |
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Comment 16•1 year ago
|
||
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
Comment 17•1 year ago
|
||
a month ago, dveditz placed a reminder on the bug using the whiteboard tag [reminder-test 2024-05-28]
.
jandem, please refer to the original comment to better understand the reason for the reminder.
Comment 18•1 year ago
|
||
![]() |
||
Updated•1 year ago
|
Updated•1 year ago
|
Updated•11 months ago
|
Description
•