Bug 808608 - Remove specialized Location security wrappers. r=mrbkap

This commit is contained in:
Bobby Holley 2012-11-21 13:20:05 -08:00
Родитель 660ca5d5cf
Коммит 11d6106099
6 изменённых файлов: 10 добавлений и 135 удалений

Просмотреть файл

@ -1592,18 +1592,10 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
JSObject *ww = wrapper->GetWrapper(); JSObject *ww = wrapper->GetWrapper();
if (ww) { if (ww) {
JSObject *newwrapper; JSObject *newwrapper;
MOZ_ASSERT(!xpc::WrapperFactory::IsComponentsObject(flat), MOZ_ASSERT(wrapper->NeedsSOW(), "weird wrapper wrapper");
"Components object should never get here"); newwrapper = xpc::WrapperFactory::WrapSOWObject(ccx, newobj);
if (xpc::WrapperFactory::IsLocationObject(flat)) { if (!newwrapper)
newwrapper = xpc::WrapperFactory::WrapLocationObject(ccx, newobj); MOZ_CRASH();
if (!newwrapper)
MOZ_CRASH();
} else {
NS_ASSERTION(wrapper->NeedsSOW(), "weird wrapper wrapper");
newwrapper = xpc::WrapperFactory::WrapSOWObject(ccx, newobj);
if (!newwrapper)
MOZ_CRASH();
}
// Ok, now we do the special object-plus-wrapper transplant. // Ok, now we do the special object-plus-wrapper transplant.
ww = xpc::TransplantObjectWithWrapper(ccx, flat, ww, newobj, ww = xpc::TransplantObjectWithWrapper(ccx, flat, ww, newobj,
@ -2213,11 +2205,7 @@ XPCWrappedNative::GetSameCompartmentSecurityWrapper(JSContext *cx)
// Check the possibilities. Note that we need to check for null in each // Check the possibilities. Note that we need to check for null in each
// case in order to distinguish between the 'no need for wrapper' and // case in order to distinguish between the 'no need for wrapper' and
// 'wrapping failed' cases. // 'wrapping failed' cases.
if (xpc::WrapperFactory::IsLocationObject(flat)) { if (NeedsSOW()) {
wrapper = xpc::WrapperFactory::WrapLocationObject(cx, flat);
if (!wrapper)
return NULL;
} else if (NeedsSOW()) {
wrapper = xpc::WrapperFactory::WrapSOWObject(cx, flat); wrapper = xpc::WrapperFactory::WrapSOWObject(cx, flat);
if (!wrapper) if (!wrapper)
return NULL; return NULL;

Просмотреть файл

@ -79,32 +79,6 @@ AccessCheck::wrapperSubsumes(JSObject *wrapper)
js::GetObjectCompartment(wrapped)); js::GetObjectCompartment(wrapped));
} }
bool
AccessCheck::isLocationObjectSameOrigin(JSContext *cx, JSObject *wrapper)
{
// The caller must ensure that the given wrapper wraps a Location object.
MOZ_ASSERT(WrapperFactory::IsLocationObject(js::UnwrapObject(wrapper)));
// Location objects are parented to the outer window for which they
// were created. This gives us an easy way to determine whether our
// object is same origin with the current inner window:
// Grab the outer window...
JSObject *obj = js::GetObjectParent(js::UnwrapObject(wrapper));
if (!js::GetObjectClass(obj)->ext.innerObject) {
// ...which might be wrapped in a security wrapper.
obj = js::UnwrapObject(obj);
MOZ_ASSERT(js::GetObjectClass(obj)->ext.innerObject);
}
// Now innerize it to find the *current* inner window for our outer.
obj = JS_ObjectToInnerObject(cx, obj);
// Which lets us compare the current compartment against the old one.
return obj && subsumes(js::GetObjectCompartment(wrapper),
js::GetObjectCompartment(obj));
}
bool bool
AccessCheck::isChrome(JSCompartment *compartment) AccessCheck::isChrome(JSCompartment *compartment)
{ {
@ -299,9 +273,7 @@ AccessCheck::isScriptAccessOnly(JSContext *cx, JSObject *wrapper)
return true; // script-only return true; // script-only
} }
// Allow non-script access to same-origin location objects and any other return false;
// objects.
return WrapperFactory::IsLocationObject(obj) && !isLocationObjectSameOrigin(cx, wrapper);
} }
void void

Просмотреть файл

@ -29,7 +29,6 @@ class AccessCheck {
js::Wrapper::Action act); js::Wrapper::Action act);
static bool callerIsXBL(JSContext *cx); static bool callerIsXBL(JSContext *cx);
static bool isSystemOnlyAccessPermitted(JSContext *cx); static bool isSystemOnlyAccessPermitted(JSContext *cx);
static bool isLocationObjectSameOrigin(JSContext *cx, JSObject *wrapper);
static bool needsSystemOnlyWrapper(JSObject *obj); static bool needsSystemOnlyWrapper(JSObject *obj);
@ -58,8 +57,6 @@ struct OnlyIfSubjectIsSystem : public Policy {
// across origins. // across origins.
struct CrossOriginAccessiblePropertiesOnly : public Policy { struct CrossOriginAccessiblePropertiesOnly : public Policy {
static bool check(JSContext *cx, JSObject *wrapper, jsid id, js::Wrapper::Action act) { static bool check(JSContext *cx, JSObject *wrapper, jsid id, js::Wrapper::Action act) {
// Location objects should always use LocationPolicy.
MOZ_ASSERT(!WrapperFactory::IsLocationObject(js::UnwrapObject(wrapper)));
return AccessCheck::isCrossOriginAccessPermitted(cx, wrapper, id, act); return AccessCheck::isCrossOriginAccessPermitted(cx, wrapper, id, act);
} }
static bool deny(JSContext *cx, jsid id, js::Wrapper::Action act) { static bool deny(JSContext *cx, jsid id, js::Wrapper::Action act) {
@ -68,46 +65,6 @@ struct CrossOriginAccessiblePropertiesOnly : public Policy {
} }
}; };
// We need a special security policy for Location objects.
//
// Location objects are special because their effective principal is that of
// the outer window, not the inner window. So while the security characteristics
// of most objects can be inferred from their compartments, those of the Location
// object cannot. This has two implications:
//
// 1 - Same-compartment access of Location objects is not necessarily allowed.
// This means that objects must see a security wrapper around Location objects
// in their own compartment.
// 2 - Cross-origin access of Location objects is not necessarily forbidden.
// Since the security decision depends on the current state of the outer window,
// we can't make it at wrap time. Instead, we need to make it at the time of
// access.
//
// So for any Location object access, be it same-compartment or cross-compartment,
// we need to do a dynamic security check to determine whether the outer window is
// same-origin with the caller.
//
// So this policy first checks whether the access is something that any code,
// same-origin or not, is allowed to make. If it isn't, it _also_ checks the
// state of the outer window to determine whether we happen to be same-origin
// at the moment.
struct LocationPolicy : public Policy {
static bool check(JSContext *cx, JSObject *wrapper, jsid id, js::Wrapper::Action act) {
// We should only be dealing with Location objects here.
MOZ_ASSERT(WrapperFactory::IsLocationObject(js::UnwrapObject(wrapper)));
if ((AccessCheck::isCrossOriginAccessPermitted(cx, wrapper, id, act) ||
AccessCheck::isLocationObjectSameOrigin(cx, wrapper))) {
return true;
}
return false;
}
static bool deny(JSContext *cx, jsid id, js::Wrapper::Action act) {
AccessCheck::deny(cx, id);
return false;
}
};
// This policy only permits access to properties if they appear in the // This policy only permits access to properties if they appear in the
// objects exposed properties list. // objects exposed properties list.
struct ExposedPropertiesOnly : public Policy { struct ExposedPropertiesOnly : public Policy {

Просмотреть файл

@ -136,8 +136,6 @@ FilteringWrapper<Base, Policy>::enter(JSContext *cx, JSObject *wrapper, jsid id,
#define XOW FilteringWrapper<SecurityXrayXPCWN, CrossOriginAccessiblePropertiesOnly> #define XOW FilteringWrapper<SecurityXrayXPCWN, CrossOriginAccessiblePropertiesOnly>
#define DXOW FilteringWrapper<SecurityXrayDOM, CrossOriginAccessiblePropertiesOnly> #define DXOW FilteringWrapper<SecurityXrayDOM, CrossOriginAccessiblePropertiesOnly>
#define NNXOW FilteringWrapper<CrossCompartmentSecurityWrapper, CrossOriginAccessiblePropertiesOnly> #define NNXOW FilteringWrapper<CrossCompartmentSecurityWrapper, CrossOriginAccessiblePropertiesOnly>
#define LW FilteringWrapper<SCSecurityXrayXPCWN, LocationPolicy>
#define XLW FilteringWrapper<SecurityXrayXPCWN, LocationPolicy>
#define CW FilteringWrapper<SameCompartmentSecurityWrapper, ComponentsObjectPolicy> #define CW FilteringWrapper<SameCompartmentSecurityWrapper, ComponentsObjectPolicy>
#define XCW FilteringWrapper<CrossCompartmentSecurityWrapper, ComponentsObjectPolicy> #define XCW FilteringWrapper<CrossCompartmentSecurityWrapper, ComponentsObjectPolicy>
template<> SOW SOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG | template<> SOW SOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
@ -147,8 +145,6 @@ template<> SCSOW SCSOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
template<> XOW XOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG); template<> XOW XOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG);
template<> DXOW DXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG); template<> DXOW DXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG);
template<> NNXOW NNXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG); template<> NNXOW NNXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG);
template<> LW LW::singleton(WrapperFactory::SHADOWING_FORBIDDEN);
template<> XLW XLW::singleton(WrapperFactory::SHADOWING_FORBIDDEN);
template<> CW CW::singleton(0); template<> CW CW::singleton(0);
template<> XCW XCW::singleton(0); template<> XCW XCW::singleton(0);
@ -157,7 +153,5 @@ template class SOW;
template class XOW; template class XOW;
template class DXOW; template class DXOW;
template class NNXOW; template class NNXOW;
template class LW;
template class XLW;
template class ChromeObjectWrapperBase; template class ChromeObjectWrapperBase;
} }

Просмотреть файл

@ -301,8 +301,7 @@ DEBUG_CheckUnwrapSafety(JSObject *obj, js::Wrapper *handler,
if (AccessCheck::isChrome(target) || xpc::IsUniversalXPConnectEnabled(target)) { if (AccessCheck::isChrome(target) || xpc::IsUniversalXPConnectEnabled(target)) {
// If the caller is chrome (or effectively so), unwrap should always be allowed. // If the caller is chrome (or effectively so), unwrap should always be allowed.
MOZ_ASSERT(handler->isSafeToUnwrap()); MOZ_ASSERT(handler->isSafeToUnwrap());
} else if (WrapperFactory::IsLocationObject(obj) || } else if (WrapperFactory::IsComponentsObject(obj) ||
WrapperFactory::IsComponentsObject(obj) ||
handler == &XSOW::singleton) handler == &XSOW::singleton)
{ {
// This is an object that is restricted regardless of origin. // This is an object that is restricted regardless of origin.
@ -371,10 +370,7 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
if (targetdata && if (targetdata &&
(wn = GetWrappedNative(cx, obj)) && (wn = GetWrappedNative(cx, obj)) &&
wn->HasProto() && wn->GetProto()->ClassIsDOMObject()) { wn->HasProto() && wn->GetProto()->ClassIsDOMObject()) {
if (IsLocationObject(obj)) wrapper = &FilteringWrapper<SecurityXrayXPCWN, CrossOriginAccessiblePropertiesOnly>::singleton;
wrapper = &FilteringWrapper<SecurityXrayXPCWN, LocationPolicy>::singleton;
else
wrapper = &FilteringWrapper<SecurityXrayXPCWN, CrossOriginAccessiblePropertiesOnly>::singleton;
} else if (mozilla::dom::UseDOMXray(obj)) { } else if (mozilla::dom::UseDOMXray(obj)) {
wrapper = &FilteringWrapper<SecurityXrayDOM, CrossOriginAccessiblePropertiesOnly>::singleton; wrapper = &FilteringWrapper<SecurityXrayDOM, CrossOriginAccessiblePropertiesOnly>::singleton;
} else if (IsComponentsObject(obj)) { } else if (IsComponentsObject(obj)) {
@ -419,7 +415,6 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
// For the same-origin case we use a transparent wrapper, unless one // For the same-origin case we use a transparent wrapper, unless one
// of the following is true: // of the following is true:
// * The object is flagged as needing a SOW. // * The object is flagged as needing a SOW.
// * The object is a Location object.
// * The object is a Components object. // * The object is a Components object.
// * The context compartment specifically requested Xray vision into // * The context compartment specifically requested Xray vision into
// same-origin compartments. // same-origin compartments.
@ -430,8 +425,6 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
if (AccessCheck::needsSystemOnlyWrapper(obj)) { if (AccessCheck::needsSystemOnlyWrapper(obj)) {
wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper, wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
OnlyIfSubjectIsSystem>::singleton; OnlyIfSubjectIsSystem>::singleton;
} else if (IsLocationObject(obj)) {
wrapper = &FilteringWrapper<SecurityXrayXPCWN, LocationPolicy>::singleton;
} else if (IsComponentsObject(obj)) { } else if (IsComponentsObject(obj)) {
wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper, wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
ComponentsObjectPolicy>::singleton; ComponentsObjectPolicy>::singleton;
@ -457,14 +450,8 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
wrapper = &FilteringWrapper<SecurityXrayDOM, wrapper = &FilteringWrapper<SecurityXrayDOM,
CrossOriginAccessiblePropertiesOnly>::singleton; CrossOriginAccessiblePropertiesOnly>::singleton;
} else { } else {
// Location objects can become same origin after navigation, so we might wrapper = &FilteringWrapper<SecurityXrayXPCWN,
// have to grant transparent access later on. CrossOriginAccessiblePropertiesOnly>::singleton;
if (IsLocationObject(obj)) {
wrapper = &FilteringWrapper<SecurityXrayXPCWN, LocationPolicy>::singleton;
} else {
wrapper = &FilteringWrapper<SecurityXrayXPCWN,
CrossOriginAccessiblePropertiesOnly>::singleton;
}
} }
} }
@ -497,23 +484,6 @@ WrapperFactory::WrapForSameCompartment(JSContext *cx, JSObject *obj)
return wrapper; return wrapper;
} }
bool
WrapperFactory::IsLocationObject(JSObject *obj)
{
const char *name = js::GetObjectClass(obj)->name;
return name[0] == 'L' && !strcmp(name, "Location");
}
JSObject *
WrapperFactory::WrapLocationObject(JSContext *cx, JSObject *obj)
{
JSObject *proto;
if (!js::GetObjectProto(cx, obj, &proto))
return nullptr;
return Wrapper::New(cx, obj, proto, js::GetObjectParent(obj),
&FilteringWrapper<SCSecurityXrayXPCWN, LocationPolicy>::singleton);
}
// Call WaiveXrayAndWrap when you have a JS object that you don't want to be // Call WaiveXrayAndWrap when you have a JS object that you don't want to be
// wrapped in an Xray wrapper. cx->compartment is the compartment that will be // wrapped in an Xray wrapper. cx->compartment is the compartment that will be
// using the returned object. If the object to be wrapped is already in the // using the returned object. If the object to be wrapped is already in the

Просмотреть файл

@ -69,12 +69,6 @@ class WrapperFactory {
static JSObject *WrapForSameCompartment(JSContext *cx, static JSObject *WrapForSameCompartment(JSContext *cx,
JSObject *obj); JSObject *obj);
// Return true if this is a location object.
static bool IsLocationObject(JSObject *obj);
// Wrap a location object.
static JSObject *WrapLocationObject(JSContext *cx, JSObject *obj);
// Wrap wrapped object into a waiver wrapper and then re-wrap it. // Wrap wrapped object into a waiver wrapper and then re-wrap it.
static bool WaiveXrayAndWrap(JSContext *cx, jsval *vp); static bool WaiveXrayAndWrap(JSContext *cx, jsval *vp);