Bug 823348 - Replace security wrapper enumeration with a more rule-based approach. r=mrbkap

This commit is contained in:
Bobby Holley 2013-01-23 06:04:39 +01:00
parent 4b3c0f19a3
commit c82ae67593

View File

@ -307,6 +307,41 @@ DEBUG_CheckUnwrapSafety(JSObject *obj, js::Wrapper *handler,
#define DEBUG_CheckUnwrapSafety(obj, handler, origin, target) {}
#endif
static Wrapper *
SelectWrapper(bool securityWrapper, bool wantXrays, XrayType xrayType,
bool waiveXrays)
{
// Waived Xray uses a modified CCW that has transparent behavior but
// transitively waives Xrays on arguments.
if (waiveXrays) {
MOZ_ASSERT(!securityWrapper);
return &WaiveXrayWrapper::singleton;
}
// If we don't want or can't use Xrays, select a wrapper that's either
// entirely transparent or entirely opaque.
if (!wantXrays || xrayType == NotXray) {
if (!securityWrapper)
return &CrossCompartmentWrapper::singleton;
return &FilteringWrapper<CrossCompartmentSecurityWrapper, Opaque>::singleton;
}
// Ok, we're using Xray. If this isn't a security wrapper, use the permissive
// version and skip the filter.
if (!securityWrapper) {
if (xrayType == XrayForWrappedNative)
return &PermissiveXrayXPCWN::singleton;
return &PermissiveXrayDOM::singleton;
}
// This is a security wrapper. Use the security versions and filter.
if (xrayType == XrayForWrappedNative)
return &FilteringWrapper<SecurityXrayXPCWN,
CrossOriginAccessiblePropertiesOnly>::singleton;
return &FilteringWrapper<SecurityXrayDOM,
CrossOriginAccessiblePropertiesOnly>::singleton;
}
JSObject *
WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
JSObject *wrappedProto, JSObject *parent,
@ -367,66 +402,33 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
//
// Now, handle the regular cases.
//
// These are wrappers we can compute using a rule-based approach. In order
// to do so, we need to compute some parameters.
//
else {
else if (targetIsChrome) {
if (originIsChrome) {
wrapper = &CrossCompartmentWrapper::singleton;
} else {
if (flags & WAIVE_XRAY_WRAPPER_FLAG) {
// If we waived the X-ray wrapper for this object, wrap it into a
// special wrapper to transitively maintain the X-ray waiver.
wrapper = &WaiveXrayWrapper::singleton;
} else {
// Native objects must be wrapped into an X-ray wrapper.
if (xrayType == XrayForDOMObject) {
wrapper = &PermissiveXrayDOM::singleton;
} else if (xrayType == XrayForWrappedNative) {
wrapper = &PermissiveXrayXPCWN::singleton;
} else {
wrapper = &CrossCompartmentWrapper::singleton;
}
}
}
} else if (originIsChrome) {
// The wrapper is a security wrapper (protecting the wrappee) if and
// only if the target does not subsume the origin.
bool securityWrapper = !targetSubsumesOrigin;
if (xrayType == XrayForWrappedNative) {
wrapper = &FilteringWrapper<SecurityXrayXPCWN, CrossOriginAccessiblePropertiesOnly>::singleton;
} else if (xrayType == XrayForDOMObject) {
wrapper = &FilteringWrapper<SecurityXrayDOM, CrossOriginAccessiblePropertiesOnly>::singleton;
} else {
MOZ_NOT_REACHED();
}
} else if (targetSubsumesOrigin) {
// For the same-origin case we use a transparent wrapper, unless one
// of the following is true:
// * The object is flagged as needing a SOW.
// * The object is a Components object.
// * The context compartment specifically requested Xray vision into
// same-origin compartments.
// Xrays are warranted if either the target or the origin don't trust
// each other. This is generally the case, unless the two are same-origin
// and the caller has not requested same-origin Xrays.
//
// The first two cases always require a security wrapper for non-chrome
// access, regardless of the origin of the object.
if (!targetdata->wantXrays || xrayType == NotXray) {
wrapper = &CrossCompartmentWrapper::singleton;
} else if (xrayType == XrayForDOMObject) {
wrapper = &PermissiveXrayDOM::singleton;
} else {
wrapper = &PermissiveXrayXPCWN::singleton;
}
} else {
// Cross origin we want to disallow scripting and limit access to
// a predefined set of properties.
if (xrayType == NotXray) {
wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper, Opaque>::singleton;
} else if (xrayType == XrayForDOMObject) {
wrapper = &FilteringWrapper<SecurityXrayDOM,
CrossOriginAccessiblePropertiesOnly>::singleton;
} else {
wrapper = &FilteringWrapper<SecurityXrayXPCWN,
CrossOriginAccessiblePropertiesOnly>::singleton;
}
// Xrays are a bidirectional protection, since it affords clarity to the
// caller and privacy to the callee.
bool wantXrays = !(sameOrigin && !targetdata->wantXrays);
// If Xrays are warranted, the caller may waive them for non-security
// wrappers.
bool waiveXrays = wantXrays && !securityWrapper &&
(flags & WAIVE_XRAY_WRAPPER_FLAG);
wrapper = SelectWrapper(securityWrapper, wantXrays, xrayType, waiveXrays);
}
// If the prototype of a chrome object being wrapped in content is a prototype
// for a standard class, use the one from the content compartment so
// that we can safely take advantage of things like .forEach().