Closed Bug 1298135 Opened 8 years ago Closed 8 years ago

Crash [@ js::GCMarker::eagerlyMarkChildren] or Crash [@ JSString::isPermanentAtom] with use-after-free

Categories

(Core :: JavaScript Engine, defect)

x86_64
Linux
defect
Not set
critical

Tracking

()

RESOLVED DUPLICATE of bug 1301343
Tracking Status
firefox49 --- unaffected
firefox-esr45 --- unaffected

People

(Reporter: decoder, Unassigned)

References

Details

(5 keywords, Whiteboard: [jsbugmon:ignore])

Crash Data

Attachments

(3 files)

The following testcase crashes on mozilla-central revision 01748a2b1a46 (build with --enable-posix-nspr-emulation --enable-valgrind --enable-gczeal --disable-tests --disable-debug --enable-optimize, run with --fuzzing-safe --thread-count=2 --disable-oom-functions --ion-eager): See attachment. Backtrace: received signal SIGSEGV, Segmentation fault. js::GCMarker::eagerlyMarkChildren (this=<optimized out>, linearStr=<optimized out>) at js/src/gc/Marking.cpp:1107 #0 js::GCMarker::eagerlyMarkChildren (this=<optimized out>, linearStr=<optimized out>) at js/src/gc/Marking.cpp:1107 #1 js::GCMarker::eagerlyMarkChildren (str=0x7ffff0ec3058, this=0x7ffff6961550) at js/src/gc/Marking.cpp:1085 #2 js::GCMarker::markAndScan<JSString> (this=this@entry=0x7ffff6961550, thing=0x7ffff0ec3058) at js/src/gc/Marking.cpp:884 #3 0x0000000000a73240 in js::GCMarker::traverse<JSString*> (thing=<optimized out>, this=0x7ffff6961550) at js/src/gc/Marking.cpp:887 #4 js::GCMarker::traverseEdge<js::ObjectGroup*, JSString> (source=0x7ffff366dac0, target=<optimized out>, this=0x7ffff6961550) at js/src/gc/Marking.cpp:946 #5 TraverseEdgeFunctor<jsid, js::ObjectGroup*>::operator()<JSString*> (this=<synthetic pointer>, s=0x7ffff366dac0, gcmarker=0x7ffff6961550, t=<optimized out>) at js/src/gc/Marking.cpp:951 #6 js::DispatchTyped<TraverseEdgeFunctor<jsid, js::ObjectGroup*>, js::GCMarker*, js::ObjectGroup*&>(TraverseEdgeFunctor<jsid, js::ObjectGroup*>, jsid&, js::GCMarker*&&, js::ObjectGroup*&) (iden=<synthetic pointer>, f=...) at /srv/jenkins/jobs/mozilla-central-build-jsshell/workspace/arch/64/compiler/gcc/sanitizer/none/type/opt/dist/include/js/Id.h:210 #7 js::GCMarker::traverseEdge<js::ObjectGroup*, jsid> (thing=..., source=0x7ffff366dac0, this=0x7ffff6961550) at js/src/gc/Marking.cpp:959 #8 js::GCMarker::lazilyMarkChildren (this=0x7ffff6961550, group=group@entry=0x7ffff366dac0) at js/src/gc/Marking.cpp:1244 #9 0x0000000000a86100 in js::GCMarker::processMarkStackTop (this=this@entry=0x7ffff6961550, budget=...) at js/src/gc/Marking.cpp:1470 #10 0x0000000000a78107 in js::GCMarker::drainMarkStack (this=this@entry=0x7ffff6961550, budget=...) at js/src/gc/Marking.cpp:1372 #11 0x0000000000783600 in js::gc::GCRuntime::drainMarkStack (this=0x7ffff695f448, sliceBudget=..., phase=<optimized out>) at js/src/jsgc.cpp:5190 #12 0x00000000007a0414 in js::gc::GCRuntime::incrementalCollectSlice (this=this@entry=0x7ffff695f448, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC, lock=...) at js/src/jsgc.cpp:5831 #13 0x00000000007a15b0 in js::gc::GCRuntime::gcCycle (this=this@entry=0x7ffff695f448, nonincrementalByAPI=nonincrementalByAPI@entry=false, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC) at js/src/jsgc.cpp:6109 #14 0x00000000007a1a1e in js::gc::GCRuntime::collect (this=this@entry=0x7ffff695f448, nonincrementalByAPI=nonincrementalByAPI@entry=false, budget=..., reason=reason@entry=JS::gcreason::DEBUG_GC) at js/src/jsgc.cpp:6212 #15 0x00000000007a228c in js::gc::GCRuntime::runDebugGC (this=this@entry=0x7ffff695f448) at js/src/jsgc.cpp:6717 #16 0x0000000000a62120 in js::gc::GCRuntime::gcIfNeededPerAllocation (this=0x7ffff695f448, cx=0x7ffff695f000) at js/src/gc/Allocator.cpp:224 #17 0x0000000000a6d5fd in js::gc::GCRuntime::checkAllocatorState<(js::AllowGC)1> (kind=js::gc::AllocKind::LAZY_SCRIPT, cx=<optimized out>, this=0x7ffff695f448) at js/src/gc/Allocator.cpp:189 #18 js::Allocate<js::LazyScript, (js::AllowGC)1> (cx=cx@entry=0x7ffff695f000) at js/src/gc/Allocator.cpp:139 #19 0x00000000007fee3a in js::LazyScript::CreateRaw (cx=0x7ffff695f000, fun=..., packedFields=<optimized out>, begin=492, end=611, lineno=lineno@entry=17, column=29) at js/src/jsscript.cpp:4274 #20 0x00000000007fefcf in js::LazyScript::CreateRaw (cx=<optimized out>, fun=..., fun@entry=..., numFreeVariables=<optimized out>, numInnerFunctions=numInnerFunctions@entry=0, version=<optimized out>, begin=<optimized out>, end=<optimized out>, lineno=17, column=29) at js/src/jsscript.cpp:4305 #21 0x0000000000487063 in js::frontend::Parser<js::frontend::SyntaxParseHandler>::finishFunctionDefinition (this=this@entry=0x7fffffffb888, funbox=funbox@entry=0x7ffff698b370, body=<optimized out>, pn=js::frontend::SyntaxParseHandler::NodeGeneric) at js/src/frontend/Parser.cpp:2900 #22 0x000000000049f34f in js::frontend::Parser<js::frontend::SyntaxParseHandler>::finishFunctionDefinition (body=<optimized out>, funbox=0x7ffff698b370, pn=js::frontend::SyntaxParseHandler::NodeGeneric, this=0x7fffffffb888) at /srv/jenkins/jobs/mozilla-central-build-jsshell/workspace/arch/64/compiler/gcc/sanitizer/none/type/opt/dist/include/js/RootingAPI.h:693 #23 js::frontend::Parser<js::frontend::SyntaxParseHandler>::functionArgsAndBodyGeneric (this=this@entry=0x7fffffffb888, inHandling=inHandling@entry=js::frontend::InAllowed, yieldHandling=yieldHandling@entry=js::frontend::YieldIsName, pn=pn@entry=js::frontend::SyntaxParseHandler::NodeGeneric, fun=fun@entry=..., kind=kind@entry=js::frontend::Statement) at js/src/frontend/Parser.cpp:3246 #24 0x000000000048e27f in js::frontend::Parser<js::frontend::FullParseHandler>::functionArgsAndBody (this=this@entry=0x7fffffffbd78, inHandling=inHandling@entry=js::frontend::InAllowed, pn=0x7ffff698b338, fun=..., fun@entry=..., kind=kind@entry=js::frontend::Statement, generatorKind=generatorKind@entry=js::NotGenerator, inheritedDirectives=..., newDirectives=0x7fffffffaf50) at js/src/frontend/Parser.cpp:2981 #25 0x00000000004a8b73 in js::frontend::Parser<js::frontend::FullParseHandler>::functionDef (this=this@entry=0x7fffffffbd78, inHandling=inHandling@entry=js::frontend::InAllowed, yieldHandling=yieldHandling@entry=js::frontend::YieldIsName, funName=..., funName@entry=..., kind=kind@entry=js::frontend::Statement, generatorKind=<optimized out>, invoked=js::frontend::Parser<js::frontend::FullParseHandler>::PredictUninvoked, assignmentForAnnexBOut=0x7fffffffb0a8) at js/src/frontend/Parser.cpp:2846 #26 0x00000000004a8f76 in js::frontend::Parser<js::frontend::FullParseHandler>::functionStmt (this=this@entry=0x7fffffffbd78, yieldHandling=yieldHandling@entry=js::frontend::YieldIsName, defaultHandling=defaultHandling@entry=js::frontend::NameRequired) at js/src/frontend/Parser.cpp:3315 #27 0x00000000004b232c in js::frontend::Parser<js::frontend::FullParseHandler>::statement (this=this@entry=0x7fffffffbd78, yieldHandling=yieldHandling@entry=js::frontend::YieldIsName, canHaveDirectives=<optimized out>) at js/src/frontend/Parser.cpp:7567 #28 0x00000000004b27f8 in js::frontend::Parser<js::frontend::FullParseHandler>::statements (this=this@entry=0x7fffffffbd78, yieldHandling=yieldHandling@entry=js::frontend::YieldIsName) at js/src/frontend/Parser.cpp:3564 #29 0x000000000048cde5 in js::frontend::Parser<js::frontend::FullParseHandler>::evalBody (this=0x7fffffffbd78) at js/src/frontend/Parser.cpp:1095 #30 0x0000000000a4e305 in BytecodeCompiler::compileScript (this=this@entry=0x7fffffffb780, scopeChain=..., scopeChain@entry=..., evalCaller=..., evalCaller@entry=...) at js/src/frontend/BytecodeCompiler.cpp:529 #31 0x0000000000a4e5f6 in js::frontend::CompileScript (cx=cx@entry=0x7ffff695f000, alloc=alloc@entry=0x7ffff695f360, scopeChain=scopeChain@entry=..., enclosingStaticScope=..., enclosingStaticScope@entry=..., evalCaller=evalCaller@entry=..., options=..., srcBuf=..., source_=0x7ffff20a01c0, extraSct=0x0, sourceObjectOut=0x0) at js/src/frontend/BytecodeCompiler.cpp:742 #32 0x000000000082c87b in EvalKernel (cx=cx@entry=0x7ffff695f000, v=..., v@entry=..., evalType=evalType@entry=DIRECT_EVAL, caller=..., scopeobj=scopeobj@entry=..., pc=0x7ffff693a187 "{", vp=...) at js/src/builtin/Eval.cpp:327 #33 0x000000000082cc7b in js::DirectEval (cx=cx@entry=0x7ffff695f000, v=..., vp=vp@entry=...) at js/src/builtin/Eval.cpp:457 #34 0x0000000000b819ac in js::jit::DoCallFallback (cx=0x7ffff695f000, frame=0x7fffffffd128, stub_=0x7ffff2759618, argc=1, vp=0x7fffffffd0d8, res=...) at js/src/jit/BaselineIC.cpp:5974 #35 0x00007ffff7e3ca5f in ?? () [...] #71 0x0000000000000000 in ?? () rax 0x4b4b4b4b4b4b4b4b 5425512962855750475 rbx 0x7ffff366dac0 140737276992192 rcx 0x7ffff0eff160 140737235644768 rdx 0x4020000000000800 4620693217682130944 rsi 0x7ffff0ec3058 140737235398744 rdi 0x1 1 rbp 0xff8 4088 rsp 0x7fffffffa4d8 140737488331992 r8 0x7ffff36fdca0 140737277582496 r9 0x1000 4096 r10 0x0 0 r11 0x246 582 r12 0x7ffff6961550 140737330419024 r13 0x450 1104 r14 0x7ffff366d000 140737276989440 r15 0x7fffffffa840 140737488332864 rip 0xa79bd5 <js::GCMarker::markAndScan<JSString>(JSString*)+837> => 0xa79bd5 <js::GCMarker::markAndScan<JSString>(JSString*)+837>: mov (%rax),%edx 0xa79bd7 <js::GCMarker::markAndScan<JSString>(JSString*)+839>: and $0x28,%edx The crash is intermittent (should crash within a minute and require maybe 10 runs) and reducing the test case further makes it almost impossible to reproduce. Marking s-s and sec-critical because the crash address indicates use-after-free. Might be a dup to one of the previous GC issues filed, but I can't really tell without a reduced test and we can't afford missing one of these.
Attached file Testcase (deleted) —
Attached file another testcase (deleted) —
(also fairly intermittent, crashing at js::GCMarker::eagerlyMarkChildren) Run with --fuzzing-safe --thread-count=2 --ion-eager and tested with m-c rev bd7645928990. CC="clang -Qunused-arguments" CXX="clang++ -Qunused-arguments" AR=ar AUTOCONF=/usr/local/Cellar/autoconf213/2.13/bin/autoconf213 sh /Users/skywalker/trees/mozilla-central/js/src/configure --target=x86_64-apple-darwin14.5.0 --disable-jemalloc --enable-debug --enable-more-deterministic --with-ccache --enable-gczeal --enable-debug-symbols --disable-tests Managed to squeeze out a possible regression window: autoBisect shows this is probably related to the following changeset: The first bad revision is: changeset: https://hg.mozilla.org/mozilla-central/rev/815c7d8dfebe user: Michael Smith date: Mon Jul 18 19:00:26 2016 -0700 summary: Bug 1282944 - Link excess lazy builders immediately, instead of throwing them away. (r=h4writer,efaust) Michael, is bug 1282944 a likely regressor?
Flags: needinfo?(michael+bmo)
Digging into this now... It shouldn't be, but it's not impossible. Previously we threw away pending IonBuilders once our queue exceeded a certain threshold; that patch makes us excess builders immediately instead. But if the builders are in the pending link queue then linking them in should be safe...
Perhaps the removal of |AutoEnterAnalysis enterTypes(cx);| is related? AutoEnterAnalysis disables GC.
After completion, the IonBuilder and its LifoAlloc are deleted in FinishOffThreadBuilder: https://dxr.mozilla.org/mozilla-central/source/js/src/jit/Ion.cpp#505-510 It seems plausible that this could lead to a use-after-free through some confluence of circumstances. Can I ping h4writer on this?
Alternatively, it could just be that linking in a particular IonBuilder / IonScript allows this test to reach a code path that it wouldn't otherwise, as the Ion code would have been thrown away and not used.
Flags: needinfo?(michael+bmo) → needinfo?(gary)
(In reply to Michael Smith [:mismith] from comment #6) > Can I ping h4writer on this? Sure, setting needinfo? for you. Also adding :jonco to cc list.
Flags: needinfo?(gary) → needinfo?(hv1989)
Jan can you take a look?
Flags: needinfo?(jdemooij)
Hannes will look at this today.
Flags: needinfo?(jdemooij)
(In reply to Gary Kwong [:gkw] [:nth10sd] from comment #2) > Created attachment 8784950 [details] > another testcase Thanks for the second testcase. That was reproducible for me. Cannot get the first one to work. > Michael, is bug 1282944 a likely regressor? I'm still investigating, but from what I see, I don't think it is introduced by that bug. There is some logs pointing to sharedStubs. Though from what I currently understand I think sharedStubs is not the reason. Investigating further to find the issue.
Maybe it's another bug that will be fixed by bug 1301343? You could try the patch there.
(In reply to Jan de Mooij [:jandem] from comment #13) > Maybe it's another bug that will be fixed by bug 1301343? You could try the > patch there. That sounds very much like what I was experiencing. I looked a bit deeper to confirm that patch fix it. (It is intermittent and quite fragile. Therefore I couldn't confirm by applying the patch) I'm seeing the following: The suspects are an ObjectGroup (lets call it group1) and a Atom/String (lets call it string1) 1) group1 is alive and well 2) We start IonBuilder compiling, which freezes a HeapTypeSetKey (with string1 as jsid) 3) ObjectGroup is getting marked 4) We free everything that isn't marked. We free jsid! 5) We link, where the freeze causes us to add the property to the Objectgroup 6) We start marking, which sees the jsid (which is already freed)
Flags: needinfo?(hv1989)
Status: NEW → RESOLVED
Closed: 8 years ago
Resolution: --- → DUPLICATE
Group: javascript-core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: