Bug 968460 - Use the incumbent global for nsGlobalWindow::GetCallerGlobal and remove JS_GetScriptedGlobal. r=bz

This commit is contained in:
Bobby Holley 2014-02-14 22:39:33 -08:00
parent 263626e418
commit c163a63a57
4 changed files with 27 additions and 35 deletions

View File

@ -57,6 +57,14 @@ nsIGlobalObject* GetIncumbentGlobal();
// Components.utils.
nsIPrincipal* GetWebIDLCallerPrincipal();
// This may be used by callers that know that their incumbent global is non-
// null (i.e. they know there have been no System Caller pushes since the
// inner-most script execution).
inline JSObject& IncumbentJSGlobal()
{
return *GetIncumbentGlobal()->GetGlobalJSObject();
}
class ScriptSettingsStack;
struct ScriptSettingsStackEntry {
nsCOMPtr<nsIGlobalObject> mGlobalObject;

View File

@ -7431,20 +7431,25 @@ JSObject* nsGlobalWindow::CallerGlobal()
// If somebody does sameOriginIframeWindow.postMessage(...), they probably
// expect the .source attribute of the resulting message event to be |window|
// rather than |sameOriginIframeWindow|, even though the transparent wrapper
// semantics of same-origin access will cause us to be in the iframe's cx at
// the time of the call. So we do some nasty poking in the JS engine and
// retrieve the global corresponding to the innermost scripted frame. Then,
// we verify that its principal is subsumed by the subject principal. If it
// isn't, something is screwy, and we want to clamp to the cx global.
JS::Rooted<JSObject*> scriptedGlobal(cx, JS_GetScriptedGlobal(cx));
JS::Rooted<JSObject*> cxGlobal(cx, JS::CurrentGlobalOrNull(cx));
nsIPrincipal* scriptedPrin = nsContentUtils::GetObjectPrincipal(scriptedGlobal);
nsIPrincipal* cxPrin = nsContentUtils::GetObjectPrincipal(cxGlobal);
if (!cxPrin->SubsumesConsideringDomain(scriptedPrin)) {
NS_WARNING("Something nasty is happening! Applying countermeasures...");
return cxGlobal;
}
return scriptedGlobal;
// semantics of same-origin access will cause us to be in the iframe's
// compartment at the time of the call. This means that we want the incumbent
// global here, rather than the global of the current compartment.
//
// There are various edge cases in which the incumbent global and the current
// global would not be same-origin. They include:
// * A privileged caller (System Principal or Expanded Principal) manipulating
// less-privileged content via Xray Waivers.
// * An unprivileged caller invoking a cross-origin function that was exposed
// to it by privileged code (i.e. Sandbox.importFunction).
//
// In these cases, we probably don't want the privileged global appearing in the
// .source attribute. So we fall back to the compartment global there.
JS::Rooted<JSObject*> incumbentGlobal(cx, &IncumbentJSGlobal());
JS::Rooted<JSObject*> compartmentGlobal(cx, JS::CurrentGlobalOrNull(cx));
nsIPrincipal* incumbentPrin = nsContentUtils::GetObjectPrincipal(incumbentGlobal);
nsIPrincipal* compartmentPrin = nsContentUtils::GetObjectPrincipal(compartmentGlobal);
return incumbentPrin->EqualsConsideringDomain(compartmentPrin) ? incumbentGlobal
: compartmentGlobal;
}

View File

@ -6265,15 +6265,6 @@ JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
return funobj;
}
JS_PUBLIC_API(JSObject *)
JS_GetScriptedGlobal(JSContext *cx)
{
ScriptFrameIter i(cx);
if (i.done())
return cx->global();
return &i.scopeChain()->global();
}
JS_PUBLIC_API(bool)
JS_PreventExtensions(JSContext *cx, JS::HandleObject obj)
{

View File

@ -1815,18 +1815,6 @@ CurrentGlobalOrNull(JSContext *cx);
}
/*
* This method returns the global corresponding to the most recent scripted
* frame, which may not match the cx's current compartment. This is extremely
* dangerous, because it can bypass compartment security invariants in subtle
* ways. To use it safely, the caller must perform a subsequent security
* check. There is currently only one consumer of this function in Gecko, and
* it should probably stay that way. If you'd like to use it, please consult
* the XPConnect module owner first.
*/
extern JS_PUBLIC_API(JSObject *)
JS_GetScriptedGlobal(JSContext *cx);
/*
* Initialize the 'Reflect' object on a global object.
*/