Bug 823348 - Flip off the wantXrays for chrome sandboxes. r=mrbkap

wantXrays means that the sandbox wants Xray wrappers even when accessing same-
origin content. The default is true, which Blake says has something to do with
GreaseMonkey and days of old.

This flag never had an effect for chrome, because the chrome->chrome case always
short-circuited to &CrossCompartmentWrapper::singleton. But once we start
respecting the flag as a general-purpose indicator that Xrays should be applied
same-origin, we need to either add a special case in Rewrap or make the flag reflect
reality. The latter seems cleaner and more sane.

However, things are complicated by the fact that there's also a completely different,
orthogonal usage, whereby setting wantXrays to false implicitly waives Xray on the
returned sandbox _and_ on any results returned from evalInSandbox. This is just nuts.
The former can be accomplished by callers manually using .wrappedJSObject, and the
latter by having EvalInSandbox transitively apply waivers from their sandbox arguments.

I've updated the documentation on the MDN page so that it only describes the
reasonable usage. The next step is to get rid of the crazy behavior. I think the
best path of migration is to have wantXrays: false keep implicitly waiving, but
waive return values from EvalInSandbox based on whether the argument was waived. This
patch does that.
This commit is contained in:
Bobby Holley 2013-01-23 06:04:39 +01:00
parent 44a21fc15a
commit c3882ecf88

View File

@ -3044,14 +3044,6 @@ NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_utils_Sandbox)
#define XPC_MAP_FLAGS 0
#include "xpc_map_end.h" /* This #undef's the above. */
static bool
WrapForSandbox(JSContext *cx, bool wantXrays, jsval *vp)
{
return wantXrays
? JS_WrapValue(cx, vp)
: xpc::WrapperFactory::WaiveXrayAndWrap(cx, vp);
}
xpc::SandboxProxyHandler xpc::sandboxProxyHandler;
bool
@ -3290,7 +3282,18 @@ xpc_CreateSandboxObject(JSContext *cx, jsval *vp, nsISupports *prinOrSop, Sandbo
sandbox = xpc::CreateGlobalObject(cx, &SandboxClass, principal);
if (!sandbox)
return NS_ERROR_FAILURE;
xpc::GetCompartmentPrivate(sandbox)->wantXrays = options.wantXrays;
// Set up the wantXrays flag, which indicates whether xrays are desired even
// for same-origin access.
//
// This flag has historically been ignored for chrome sandboxes due to
// quirks in the wrapping implementation that have now been removed. Indeed,
// same-origin Xrays for chrome->chrome access seems a bit superfluous.
// Arguably we should just flip the default for chrome and still honor the
// flag, but such a change would break code in subtle ways for minimal
// benefit. So we just switch it off here.
xpc::GetCompartmentPrivate(sandbox)->wantXrays =
AccessCheck::isChrome(sandbox) ? false : options.wantXrays;
JS::AutoObjectRooter tvr(cx, sandbox);
@ -3354,10 +3357,14 @@ xpc_CreateSandboxObject(JSContext *cx, jsval *vp, nsISupports *prinOrSop, Sandbo
}
if (vp) {
// We have this crazy behavior where wantXrays=false also implies that the
// returned sandbox is implicitly waived. We've stopped advertising it, but
// keep supporting it for now.
*vp = OBJECT_TO_JSVAL(sandbox);
if (!WrapForSandbox(cx, options.wantXrays, vp)) {
if (options.wantXrays && !JS_WrapValue(cx, vp))
return NS_ERROR_UNEXPECTED;
if (!options.wantXrays && !xpc::WrapperFactory::WaiveXrayAndWrap(cx, vp))
return NS_ERROR_UNEXPECTED;
}
}
// Set the location information for the new global, so that tools like
@ -3862,6 +3869,7 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
{
JS_AbortIfWrongThread(JS_GetRuntime(cx));
bool waiveXray = xpc::WrapperFactory::HasWaiveXrayFlag(sandbox);
sandbox = js::UnwrapObjectChecked(sandbox);
if (!sandbox || js::GetObjectJSClass(sandbox) != &SandboxClass) {
return NS_ERROR_INVALID_ARG;
@ -3976,10 +3984,11 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
v = STRING_TO_JSVAL(str);
}
CompartmentPrivate *sandboxdata = GetCompartmentPrivate(sandbox);
if (!WrapForSandbox(cx, sandboxdata->wantXrays, &v)) {
// Transitively apply Xray waivers if |sb| was waived.
if (waiveXray && !xpc::WrapperFactory::WaiveXrayAndWrap(cx, &v))
rv = NS_ERROR_FAILURE;
if (!waiveXray && !JS_WrapValue(cx, &v))
rv = NS_ERROR_FAILURE;
}
if (NS_SUCCEEDED(rv)) {
*rval = v;