Closed Bug 803228 Opened 7 years ago Closed 7 years ago

Assertion failure: cx->compartment->principals == options.principals


(Core :: Plug-ins, defect, critical)

18 Branch
Windows XP
Not set



Tracking Status
firefox18 --- wontfix
firefox19 --- wontfix
firefox20 --- wontfix
firefox21 --- fixed
firefox-esr17 --- wontfix
b2g18 --- wontfix


(Reporter: bc, Assigned: benjamin)


(Blocks 1 open bug, )


(Keywords: assertion, regression, sec-audit, Whiteboard: [fixed by bug 824864][adv-main21+])

2. Assertion failure: cx->compartment->principals == options.principals, at c:/work/mozilla/builds/nightly/mozilla/js/src/jsapi.cpp:5689

s-s 'cause compartments are scary, mkay?

Windows XP Nightly so far. Doesn't appear to crash opt build.
really a plugin issue I think. s-s 'cause principals are scary, mkay?

Thread 0 (crashed)
 0  mozjs.dll!JS::Evaluate(JSContext *,JS::Handle<JSObject *>,JS::CompileOptions,wchar_t const *,unsigned int,JS::Value *) [jsapi.cpp : 5689 + 0x2b]
    eip = 0x00b2b08e   esp = 0x0012b4f4   ebp = 0x0012b540   ebx = 0x00000000
    esi = 0x0012b610   edi = 0x0012b570   eax = 0x00000000   ecx = 0xd11e63cc
    edx = 0x10362ee8   efl = 0x00000212
    Found by: given as instruction pointer in context
 1  xul.dll!nsJSContext::EvaluateStringWithValue(nsAString_internal const &,JSObject *,nsIPrincipal *,char const *,unsigned int,unsigned int,JS::Value *,bool *) [nsJSEnvironment.cpp : 1313 + 0x54]
    eip = 0x02a8eab3   esp = 0x0012b548   ebp = 0x0012b64c
    Found by: call frame info
 2  xul.dll!mozilla::plugins::parent::_evaluate(_NPP *,NPObject *,_NPString *,_NPVariant *) [nsNPAPIPlugin.cpp : 1557 + 0x4c]
    eip = 0x0333bc8e   esp = 0x0012b654   ebp = 0x0012b808
    Found by: call frame info
 3  xul.dll!mozilla::plugins::PluginScriptableObjectParent::AnswerNPN_Evaluate(nsCString const &,mozilla::plugins::Variant *,bool *) [PluginScriptableObjectParent.cpp : 1196 + 0x22]
    eip = 0x0360df8a   esp = 0x0012b810   ebp = 0x0012b868
    Found by: call frame info
 4  xul.dll!mozilla::plugins::PPluginScriptableObjectParent::OnCallReceived(IPC::Message const &,IPC::Message * &) [PPluginScriptableObjectParent.cpp : 776 + 0x27]
    eip = 0x036795b9   esp = 0x0012b870   ebp = 0x0012bd04
    Found by: call frame info
 5  xul.dll!mozilla::plugins::PPluginModuleParent::OnCallReceived(IPC::Message const &,IPC::Message * &) [PPluginModuleParent.cpp : 1288 + 0x1a]
    eip = 0x03655c95   esp = 0x0012bd0c   ebp = 0x0012be48
    Found by: call frame info
 6  xul.dll!mozilla::ipc::RPCChannel::DispatchIncall(IPC::Message const &) [RPCChannel.cpp : 486 + 0x1f]
    eip = 0x0361db44   esp = 0x0012be50   ebp = 0x0012be80
    Found by: call frame info
 7  xul.dll!mozilla::ipc::RPCChannel::Incall(IPC::Message const &,unsigned int) [RPCChannel.cpp : 472 + 0xb]
    eip = 0x0361da91   esp = 0x0012be88   ebp = 0x0012becc
    Found by: call frame info
 8  xul.dll!mozilla::ipc::RPCChannel::Call(IPC::Message *,IPC::Message *) [RPCChannel.cpp : 279 + 0x15]
    eip = 0x0361ced2   esp = 0x0012bed4   ebp = 0x0012c020
    Found by: call frame info
 9  xul.dll!mozilla::plugins::PPluginScriptableObjectParent::CallHasProperty(mozilla::plugins::PPluginIdentifierParent *,bool *) [PPluginScriptableObjectParent.cpp : 288 + 0x18]
    eip = 0x03677229   esp = 0x0012c028   ebp = 0x0012c0e8
    Found by: call frame info
10  xul.dll!mozilla::plugins::PluginScriptableObjectParent::ScriptableHasProperty(NPObject *,void *) [PluginScriptableObjectParent.cpp : 259 + 0x1b]
    eip = 0x0360b1e6   esp = 0x0012c0f0   ebp = 0x0012c10c
    Found by: call frame info
11  xul.dll!NPObjWrapper_NewResolve [nsJSNPRuntime.cpp : 1624 + 0x11]
    eip = 0x0335fbfb   esp = 0x0012c114   ebp = 0x0012c174
    Found by: call frame info
Assignee: general → nobody
Component: JavaScript Engine → Plug-ins
My totally wild guess at what's happening:

- There is JS running higher up the stack (frame 12+) because NPObjWrapper_NewResolve is a JSAPI hook.
- That JS is running on the JSContext* we have in frame 0.
- That JS is running in a compartment that is not the normal compartment of the JSContext (due to a CCW or something).
 	mozjs.dll!JS::Evaluate(cx=0x1239fdf0, obj={...}, options={...}, chars=0x12ffb970, length=0x0000064b, rval=0x0022b4f8)  Line 5670	C++
 	xul.dll!nsJSContext::EvaluateStringWithValue(aScript={...}, aScopeObject=0x14bf5d30, aPrincipal=0x1626a518, aURL=0x0dfe45a8, aLineNo=0x00000000, aVersion=0x00000000, aRetValue=0x0022b6cc, aIsUndefined=0x00000000)  Line 1313	C++
 	xul.dll!mozilla::plugins::parent::_evaluate(npp=0x16b996c4, npobj=0x0e5938e8, script=0x0022b724, result=0x0022b6fc)  Line 1558	C++
 	xul.dll!mozilla::plugins::PluginScriptableObjectParent::AnswerNPN_Evaluate(aScript={...}, aResult=0x0022b934, aSuccess=0x0022b933)  Line 1196	C++
 	xul.dll!mozilla::plugins::PPluginScriptableObjectParent::OnCallReceived(__msg={...}, __reply=0x00000000)  Line 776	C++
>	xul.dll!mozilla::plugins::PPluginModuleParent::OnCallReceived(__msg={...}, __reply=0x00000000)  Line 1288	C++
 	xul.dll!mozilla::ipc::RPCChannel::DispatchIncall(call={...})  Line 486	C++
 	xul.dll!mozilla::ipc::RPCChannel::Incall(call={...}, stackDepth=0x00000001)  Line 473	C++
 	xul.dll!mozilla::ipc::RPCChannel::Call(_msg=0x180e76e8, reply=0x0022bf14)  Line 281	C++
 	xul.dll!mozilla::plugins::PPluginScriptableObjectParent::CallHasMethod(aId=0x17ff5928, aHasMethod=0x0022bfcf)  Line 153	C++
 	xul.dll!mozilla::plugins::PluginScriptableObjectParent::ScriptableHasMethod(aObject=0x1249a1e0, aName=0x0caebb90)  Line 117	C++
 	xul.dll!NPObjWrapper_NewResolve(cx=0x1239fdf0, obj={...}, id={...}, flags=0x00000001, objp={...})  Line 1645	C++
 	mozjs.dll!CallResolveOp(cx=0x1239fdf0, obj={...}, id={...}, flags=0x00000001, objp={...}, propp={...}, recursedp=0x0022c10f)  Line 4048	C++
 	mozjs.dll!LookupPropertyWithFlagsInline(cx=0x1239fdf0, obj={...}, id={...}, flags=0x0000ffff, objp={...}, propp={...})  Line 4100	C++
 	mozjs.dll!js_GetPropertyHelperInline(cx=0x1239fdf0, obj={...}, receiver={...}, id_={...}, getHow=0x00000000, vp={...})  Line 4303	C++
 	mozjs.dll!js::baseops::GetProperty(cx=0x1239fdf0, obj={...}, receiver={...}, id={...}, vp={...})  Line 4398	C++
 	mozjs.dll!JSObject::getGeneric(cx=0x1239fdf0, obj={...}, receiver={...}, id={...}, vp={...})  Line 171	C++
 	mozjs.dll!js::DirectProxyHandler::get(cx=0x1239fdf0, proxy=0x098ca5b0, receiver_=0x17005cc0, id_={...}, vp=0x0022cdb8)  Line 586	C++
 	mozjs.dll!js::DirectWrapper::get(cx=0x1239fdf0, wrapper=0x098ca5b0, receiver=0x17005cc0, id={...}, vp=0x0022cdb8)  Line 358	C++
 	mozjs.dll!js::CrossCompartmentWrapper::get(cx=0x1239fdf0, wrapperArg=0x098ca5b0, receiverArg=0x098ca5b0, idArg={...}, vp=0x0022cdb8)  Line 592	C++
 	mozjs.dll!js::Proxy::get(cx=0x1239fdf0, proxy_={...}, receiver={...}, id={...}, vp={...})  Line 2377	C++
 	mozjs.dll!proxy_GetGeneric(cx=0x1239fdf0, obj={...}, receiver={...}, id={...}, vp={...})  Line 2646	C++
 	mozjs.dll!JSObject::getGeneric(cx=0x1239fdf0, obj={...}, receiver={...}, id={...}, vp={...})  Line 168	C++
 	mozjs.dll!js::GetPropertyGenericMaybeCallXML(cx=0x1239fdf0, op=JSOP_GETPROP, obj={...}, id={...}, vp={...})  Line 205	C++
 	mozjs.dll!js::GetPropertyOperation(cx=0x1239fdf0, script=0x170d6300, pc=0x081999be, lval={...}, vp={...})  Line 277	C++
 	mozjs.dll!js::Interpret(cx=0x1239fdf0, entryFrame=0x08350020, interpMode=JSINTERP_NORMAL)  Line 2340	C++
 	mozjs.dll!js::RunScript(cx=0x1239fdf0, script={...}, fp=0x08350020)  Line 324	C++
 	mozjs.dll!js::InvokeKernel(cx=0x1239fdf0, args={...}, construct=NO_CONSTRUCT)  Line 378	C++
 	mozjs.dll!js::Invoke(cx=0x1239fdf0, args={...}, construct=NO_CONSTRUCT)  Line 109	C++
 	mozjs.dll!js::Invoke(cx=0x1239fdf0, thisv={...}, fval={...}, argc=0x00000000, argv=0x00000000, rval=0x0022d41c)  Line 411	C++
 	mozjs.dll!JS_CallFunctionValue(cx=0x1239fdf0, objArg=0x098c2040, fval={...}, argc=0x00000000, argv=0x00000000, rval=0x0022d41c)  Line 5863	C++
 	xul.dll!nsJSContext::CallEventHandler(aTarget=0x0bdacfe8, aScope=0x098c2040, aHandler=0x17310aa0, aargv=0x0e7dbc70, arv=0x0022d484)  Line 1921	C++
 	xul.dll!nsGlobalWindow::RunTimeoutHandler(aTimeout=0x0e648c48, aScx=0x09f64328)  Line 9678	C++
 	xul.dll!nsGlobalWindow::RunTimeout(aTimeout=0x0e648c48)  Line 9927	C++
 	xul.dll!nsGlobalWindow::TimerCallback(aTimer=0x0e64bc90, aClosure=0x0e648c48)  Line 10195	C++
 	xul.dll!nsTimerImpl::Fire()  Line 473	C++
 	xul.dll!nsTimerEvent::Run()  Line 558	C++
 	xul.dll!nsThread::ProcessNextEvent(mayWait=false, result=0x0022d717)  Line 612	C++
 	xul.dll!NS_ProcessNextEvent_P(thread=0x00906e30, mayWait=false)  Line 220	C++
 	xul.dll!mozilla::ipc::MessagePump::Run(aDelegate=0x00905c70)  Line 82	C++
 	xul.dll!MessageLoop::RunInternal()  Line 209	C++
 	xul.dll!MessageLoop::RunHandler()  Line 202	C++
 	xul.dll!MessageLoop::Run()  Line 176	C++
 	xul.dll!nsBaseAppShell::Run()  Line 165	C++
 	xul.dll!nsAppShell::Run()  Line 232	C++
 	xul.dll!nsAppStartup::Run()  Line 290	C++
 	xul.dll!XREMain::XRE_mainRun()  Line 3782	C++
 	xul.dll!XREMain::XRE_main(argc=0x00000004, argv=0x008e7ab0, aAppData=0x01108864)  Line 3848	C++
 	xul.dll!XRE_main(argc=0x00000004, argv=0x008e7ab0, aAppData=0x01108864, aFlags=0x00000000)  Line 3923	C++
 	firefox.exe!do_main(argc=0x00000004, argv=0x008e7ab0)  Line 174	C++
 	firefox.exe!NS_internal_main(argc=0x00000004, argv=0x008e7ab0)  Line 279	C++
 	firefox.exe!wmain(argc=0x00000004, argv=0x00409d20)  Line 105	C++
 	firefox.exe!__tmainCRTStartup()  Line 552	C
 	firefox.exe!wmainCRTStartup()  Line 371	C

aPrincipal is a codebase principal for ""
options.principals = 0x1626a51c which dumps as the same thing

cx->compartment->principals = 0x0eb8eaf4 which dumps as "" (it's a domain principal)
Version: Trunk → 18 Branch
We have principals that are equivalent to Gecko (which uses nsIPrincipal::Equals to determine that) but that are not equivalent to the JS engine (which does a pointer comparison).  It seems like a footgun that the two sides are using different equivalence relations.
(In reply to Kyle Huey [:khuey] ( from comment #5)
> We have principals that are equivalent to Gecko (which uses
> nsIPrincipal::Equals to determine that) but that are not equivalent to the
> JS engine (which does a pointer comparison).  It seems like a footgun that
> the two sides are using different equivalence relations.

We've been moving away from direct principal comparisons in the engine (with the exception of assertion) in part for this reason. Given the assertion that already happens in nsJSContext::EvaluateStringWithValue, it seems like we can just use the other principal to fix this?
In this case the two principals /should/ have compared equal--failing when it should have passed--which is a bug but not a security problem. From the description in comment 5 it doesn't sound like we'd get into a security vulnerability case where they compare equal while actually being different. Is that right, or have I misunderstood the scenario?
Kyle thoughts on comment 7? (Or can you pass over to someone else for a look?)
Assignee: nobody → khuey
Bobby added this assertion, he should comment on the consequences of its failure.
Assignee: khuey → nobody
Flags: needinfo?(bobbyholley+bmo)
I added this assertion when I removed the code that handled options.principals. Since the argument was effectively unused, I wanted to make sure that it would match the principal that would actually be used (the scope object's principal). If they don't, then the caller is executing the code with the wrong principal. If that can be made to happen with cross-origin principals, that's bad. The same-origin-ness of the two principals in the testcase here seems likely to be incidental. I think we should assume that such a testcase could be constructed here unless proven otherwise.

Looking at the implementation of _evaluate in nsNPAPIPlugin.cpp, the issue appears to be that the results of GetDocumentFromNPP(npp) and nsNPObjWrapper::GetNewOrUsed(npp, cx, npobj) are not same-compartment. This could be the result of two possible causes:

(1) - The cx we pull off the document is in a different compartment from the document itself (which can happen if the page has navigated away from the document, since nsIScriptContext is per-outer-window).

(2) - The hashtable already contained an nsNPObjWrapper for npobj, and that object was in a different compartment (so we wrapped it).

Benjamin, any idea which case it is?
Flags: needinfo?(bobbyholley+bmo)
#2 is much more likely in this case. From the stack it looks like we are scripting some iframe from the main aol page, and so the first wrapper for a plugin object may well be the wrapper for, not its native document. currently doesn't exhibit this issue, but I can look at creating a testcase based on this hunch.
Is the hashmap specific to an NPP object? If so, maybe we should make sure that all objects in the hash are created in that document's compartment, and hand out wrappers as appropriate?
We couldn't maintain the invariant, though, because plugins can be adopted into other documents.
->me for a testcase for now
Assignee: nobody → benjamin
I'll assume wanting a testcase in this instance is akin to "sec-audit", but if it finds something we'll want to upgrade the severity.
Keywords: sec-audit
Does this still happen, I think it may have been fixed by bug 824864.
Bobby, that looks about right. This has been 'fairly' common but disappears on Nightly after 2013-01-17 but still appears on Aurora, Beta. I've resubmitted the urls for retesting and I'll report back in a bit.
Reproduced Beta, Aurora primarily Windows and 32bit Linux but not 64bit Linux with one url reproducing on 64bit OSX Beta, Aurora. Nightly does crash with the bogus Flash shutdown crash but not with this assertion.
Closed: 7 years ago
Resolution: --- → FIXED
Whiteboard: [fixed by bug 824864]
Seems unlikely we'd ever try to backport bug 824864.
Whiteboard: [fixed by bug 824864] → [fixed by bug 824864][adv-main21+]
Group: core-security
You need to log in before you can comment on or make changes to this bug.