Closed Bug 1495573 Opened 6 years ago Closed 6 years ago

Crash [@ js::SharedArrayRawBuffer::dropReference]

Categories

(Core :: JavaScript: WebAssembly, defect)

x86_64
Linux
defect
Not set
critical

Tracking

()

RESOLVED FIXED
mozilla64
Tracking Status
firefox-esr60 --- unaffected
firefox62 --- unaffected
firefox63 --- wontfix
firefox64 --- fixed

People

(Reporter: decoder, Assigned: lth)

References

Details

(4 keywords, Whiteboard: [jsbugmon:])

Crash Data

Attachments

(1 file)

The following testcase crashes on mozilla-central revision ba2b3ed1eb96 (build with --enable-posix-nspr-emulation --enable-valgrind --enable-gczeal --disable-tests --disable-profiling --enable-debug --enable-optimize, run with --fuzzing-safe --cpu-count=2):

var mem = new WebAssembly.Memory({initial: 1, maximum: 1, shared: true});
setSharedObject(mem);
evalInWorker(`
  try { evaluate(\`
    var N = 100;
    function test(out) {
      var arrs = out.arrs = [];
      for (var i = 0; i < N; bailAfter(100))
        arrs.push([0, 1, 2, 3]);
    }
    var obj = {};
    test(obj);
  \`); } catch(exc) {}
  getSharedObject()
`);


Backtrace:

received signal SIGSEGV, Segmentation fault.
#0  js::SharedArrayRawBuffer::dropReference (this=0x7ffe753effa0) at js/src/vm/SharedArrayObject.cpp:166
#1  0x0000555555f45bf9 in js::SharedArrayBufferObject::Finalize (fop=<optimized out>, obj=0x7ffff598a160) at js/src/vm/SharedArrayObject.cpp:306
#2  0x00005555561de9bb in js::Class::doFinalize (this=<optimized out>, obj=0x7ffff598a160, fop=0x7fffffffcce0) at dist/include/js/Class.h:896
#3  JSObject::finalize (this=this@entry=0x7ffff598a160, fop=fop@entry=0x7fffffffcce0) at js/src/vm/JSObject-inl.h:91
#4  0x00005555561fb00f in js::gc::Arena::finalize<JSObject> (this=0x7ffff598a000, fop=0x7fffffffcce0, thingKind=<optimized out>, thingSize=48) at js/src/gc/GC.cpp:618
#5  0x00005555561bf058 in FinalizeTypedArenas<JSObject> (fop=fop@entry=0x7fffffffcce0, src=0x7fffffffbbb8, dest=..., thingKind=thingKind@entry=js::gc::AllocKind::OBJECT2_BACKGROUND, budget=..., keepArenas=js::gc::ArenaLists::KEEP_ARENAS) at js/src/gc/GC.cpp:677
#6  0x00005555561c1615 in FinalizeArenas (keepArenas=js::gc::ArenaLists::KEEP_ARENAS, budget=..., thingKind=js::gc::AllocKind::OBJECT2_BACKGROUND, dest=..., src=0x7fffffffbbb8, fop=0x7fffffffcce0) at js/src/gc/GC.cpp:713
#7  js::gc::ArenaLists::backgroundFinalize (fop=fop@entry=0x7fffffffcce0, listHead=<optimized out>, empty=empty@entry=0x7fffffffcc98) at js/src/gc/GC.cpp:3333
#8  0x00005555561c18e6 in js::gc::GCRuntime::sweepBackgroundThings (this=this@entry=0x7ffff5f1c678, zones=..., freeBlocks=...) at js/src/gc/GC.cpp:3782
#9  0x00005555561c1d63 in js::gc::GCRuntime::sweepBackgroundThings (freeBlocks=..., zones=..., this=0x7ffff5f1c678) at js/src/threading/ProtectedData.h:107
#10 js::gc::GCRuntime::sweepFromBackgroundThread (this=0x7ffff5f1c678, lock=...) at js/src/gc/GC.cpp:3942
#11 0x00005555561c1ec2 in js::gc::BackgroundSweepTask::run (this=0x7ffff5f1df78) at js/src/gc/GC.cpp:3925
#12 0x0000555555dd7dd5 in js::GCParallelTask::runTask (this=0x7ffff5f1df78) at js/src/gc/GCParallelTask.h:130
#13 js::GCParallelTask::runFromMainThread (this=this@entry=0x7ffff5f1df78, rt=rt@entry=0x7ffff5f1c000) at js/src/vm/HelperThreads.cpp:1677
#14 0x0000555556193366 in js::gc::BackgroundSweepTask::runFromMainThread (this=0x7ffff5f1df78, rt=0x7ffff5f1c000) at js/src/gc/GC.cpp:3912
#15 0x000055555619f225 in js::gc::GCRuntime::endSweepingSweepGroup (this=0x7ffff5f1c678, fop=<optimized out>, budget=...) at js/src/gc/GC.cpp:6182
#16 0x00005555561fdb00 in sweepaction::SweepActionSequence<js::gc::GCRuntime*, js::FreeOp*, js::SliceBudget&>::run (this=0x7ffff5f17380, args#0=0x7ffff5f1c678, args#1=0x7fffffffd1e0, args#2=...) at js/src/gc/GC.cpp:6742
#17 0x00005555561ff85a in sweepaction::SweepActionRepeatFor<js::gc::SweepGroupsIter, JSRuntime*, js::gc::GCRuntime*, js::FreeOp*, js::SliceBudget&>::run (this=0x7ffff5f31040, args#0=0x7ffff5f1c678, args#1=0x7fffffffd1e0, args#2=...) at js/src/gc/GC.cpp:6806
#18 0x00005555561cf457 in js::gc::GCRuntime::performSweepActions (this=this@entry=0x7ffff5f1c678, budget=...) at js/src/gc/GC.cpp:6984
#19 0x00005555561d1f8f in js::gc::GCRuntime::incrementalCollectSlice (this=this@entry=0x7ffff5f1c678, budget=..., reason=reason@entry=JS::gcreason::DESTROY_RUNTIME, session=...) at js/src/gc/GC.cpp:7584
#20 0x00005555561d339e in js::gc::GCRuntime::gcCycle (this=this@entry=0x7ffff5f1c678, nonincrementalByAPI=nonincrementalByAPI@entry=true, budget=..., reason=reason@entry=JS::gcreason::DESTROY_RUNTIME) at js/src/gc/GC.cpp:7940
#21 0x00005555561d3b1d in js::gc::GCRuntime::collect (this=this@entry=0x7ffff5f1c678, nonincrementalByAPI=nonincrementalByAPI@entry=true, budget=..., reason=reason@entry=JS::gcreason::DESTROY_RUNTIME) at js/src/gc/GC.cpp:8121
#22 0x00005555561d3ee9 in js::gc::GCRuntime::gc (this=this@entry=0x7ffff5f1c678, gckind=gckind@entry=GC_NORMAL, reason=reason@entry=JS::gcreason::DESTROY_RUNTIME) at js/src/gc/GC.cpp:8204
#23 0x0000555555ed90cc in JSRuntime::destroyRuntime (this=0x7ffff5f1c000) at js/src/vm/Runtime.cpp:299
#24 0x0000555555e36ec9 in js::DestroyContext (cx=0x7ffff5f18000) at js/src/vm/JSContext.cpp:217
#25 0x00005555556536e0 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at js/src/shell/js.cpp:10998
rax	0x7ffe753effa0	140730865483680
rbx	0x7ffff598a160	140737313808736
rcx	0xfff80000ffffffff	-2251795518717953
rdx	0x80003fff3a9f7fd0	-9223301671422033968
rsi	0x0	0
rdi	0x7ffe753effa0	140730865483680
rbp	0x7fffffffb990	140737488337296
rsp	0x7fffffffb970	140737488337264
r8	0x0	0
r9	0x7ffff598a160	140737313808736
r10	0x6	6
r11	0x0	0
r12	0xfff9800000000000	-1829587348619264
r13	0x7fffffffcce0	140737488342240
r14	0x55555733f7c0	93825023604672
r15	0x40	64
rip	0x555555f224fb <js::SharedArrayRawBuffer::dropReference()+11>
=> 0x555555f224fb <js::SharedArrayRawBuffer::dropReference()+11>:	mov    (%rdi),%eax
   0x555555f224fd <js::SharedArrayRawBuffer::dropReference()+13>:	test   %eax,%eax
Whiteboard: [jsbugmon:update,bisect] → [jsbugmon:bisect]
JSBugMon: Cannot process bug: Unable to automatically reproduce, please track manually.
Whiteboard: [jsbugmon:bisect] → [jsbugmon:]
NI lth because SAB.
Flags: needinfo?(lhansen)
Hm, some refcounting problem with WebAssembly.Memory.  DestroyContext runs after destructing the shared memory mailbox, looks like the latter operation took the last reference to the buffer, which is wrong.  I will investigate.
This problem resulted from an extra reference count decrement along a failure path following an OOM; an orphaned object that held onto the underlying buffer would then perform a decref on a dead buffer if it were GC'd late enough, as here.

The problem is shell-only, it does not need to be flagged as security-sensitive.
Flags: needinfo?(lhansen)
Assignee: nobody → lhansen
Status: NEW → ASSIGNED
Attachment #9013580 - Flags: review?(luke)
Group: javascript-core-security
Comment on attachment 9013580 [details] [diff] [review]
bug1495573-sab-refcount-again.patch

Review of attachment 9013580 [details] [diff] [review]:
-----------------------------------------------------------------

Makes sense.
Attachment #9013580 - Flags: review?(luke) → review+
Pushed by lhansen@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/9d0ccdab956d
avoid double refcount decrement along failure path.  r=luke
https://hg.mozilla.org/mozilla-central/rev/9d0ccdab956d
Status: ASSIGNED → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla64
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: