Bug 1319773 - Part 3: Making the WrapperFactory ignores the First Party Domain of the originAttributes when rewrapping the wrapper. r?mrbkap
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -54,21 +54,32 @@ AccessCheck::subsumes(JSObject* a, JSObj
{
return subsumes(js::GetObjectCompartment(a), js::GetObjectCompartment(b));
}
// Same as above, but considering document.domain.
bool
AccessCheck::subsumesConsideringDomain(JSCompartment* a, JSCompartment* b)
{
+ MOZ_ASSERT(OriginAttributes::IsRestrictOpenerAccessForFPI());
nsIPrincipal* aprin = GetCompartmentPrincipal(a);
nsIPrincipal* bprin = GetCompartmentPrincipal(b);
return aprin->SubsumesConsideringDomain(bprin);
}
+bool
+AccessCheck::subsumesConsideringDomainIgnoringFPD(JSCompartment* a,
+ JSCompartment* b)
+{
+ MOZ_ASSERT(!OriginAttributes::IsRestrictOpenerAccessForFPI());
+ nsIPrincipal* aprin = GetCompartmentPrincipal(a);
+ nsIPrincipal* bprin = GetCompartmentPrincipal(b);
+ return aprin->SubsumesConsideringDomainIgnoringFPD(bprin);
+}
+
// Does the compartment of the wrapper subsumes the compartment of the wrappee?
bool
AccessCheck::wrapperSubsumes(JSObject* wrapper)
{
MOZ_ASSERT(js::IsWrapper(wrapper));
JSObject* wrapped = js::UncheckedUnwrap(wrapper);
return AccessCheck::subsumes(js::GetObjectCompartment(wrapper),
js::GetObjectCompartment(wrapped));
--- a/js/xpconnect/wrappers/AccessCheck.h
+++ b/js/xpconnect/wrappers/AccessCheck.h
@@ -15,16 +15,18 @@ class nsIPrincipal;
namespace xpc {
class AccessCheck {
public:
static bool subsumes(JSCompartment* a, JSCompartment* b);
static bool subsumes(JSObject* a, JSObject* b);
static bool wrapperSubsumes(JSObject* wrapper);
static bool subsumesConsideringDomain(JSCompartment* a, JSCompartment* b);
+ static bool subsumesConsideringDomainIgnoringFPD(JSCompartment* a,
+ JSCompartment* b);
static bool isChrome(JSCompartment* compartment);
static bool isChrome(JSObject* obj);
static nsIPrincipal* getPrincipal(JSCompartment* compartment);
static bool isCrossOriginAccessPermitted(JSContext* cx, JS::HandleObject obj,
JS::HandleId id, js::Wrapper::Action act);
static bool checkPassToPrivilegedCode(JSContext* cx, JS::HandleObject wrapper,
JS::HandleValue value);
static bool checkPassToPrivilegedCode(JSContext* cx, JS::HandleObject wrapper,
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -135,19 +135,26 @@ ShouldWaiveXray(JSContext* cx, JSObject*
if (!(flags & Wrapper::CROSS_COMPARTMENT))
return true;
// Otherwise, this is a case of explicitly passing a wrapper across a
// compartment boundary. In that case, we only want to preserve waivers
// in transactions between same-origin compartments.
JSCompartment* oldCompartment = js::GetObjectCompartment(originalObj);
JSCompartment* newCompartment = js::GetContextCompartment(cx);
- bool sameOrigin =
- AccessCheck::subsumesConsideringDomain(oldCompartment, newCompartment) &&
- AccessCheck::subsumesConsideringDomain(newCompartment, oldCompartment);
+ bool sameOrigin = false;
+ if (OriginAttributes::IsRestrictOpenerAccessForFPI()) {
+ sameOrigin =
+ AccessCheck::subsumesConsideringDomain(oldCompartment, newCompartment) &&
+ AccessCheck::subsumesConsideringDomain(newCompartment, oldCompartment);
+ } else {
+ sameOrigin =
+ AccessCheck::subsumesConsideringDomainIgnoringFPD(oldCompartment, newCompartment) &&
+ AccessCheck::subsumesConsideringDomainIgnoringFPD(newCompartment, oldCompartment);
+ }
return sameOrigin;
}
void
WrapperFactory::PrepareForWrapping(JSContext* cx, HandleObject scope,
HandleObject objArg, HandleObject objectPassedToWrap,
MutableHandleObject retObj)
{
@@ -332,17 +339,19 @@ DEBUG_CheckUnwrapSafety(HandleObject obj
MOZ_ASSERT(!handler->hasSecurityPolicy());
} else if (CompartmentPrivate::Get(origin)->forcePermissiveCOWs) {
// Similarly, if this is a privileged scope that has opted to make itself
// accessible to the world (allowed only during automation), unwrap should
// be allowed.
MOZ_ASSERT(!handler->hasSecurityPolicy());
} else {
// Otherwise, it should depend on whether the target subsumes the origin.
- MOZ_ASSERT(handler->hasSecurityPolicy() == !AccessCheck::subsumesConsideringDomain(target, origin));
+ MOZ_ASSERT(handler->hasSecurityPolicy() == !(OriginAttributes::IsRestrictOpenerAccessForFPI() ?
+ AccessCheck::subsumesConsideringDomain(target, origin) :
+ AccessCheck::subsumesConsideringDomainIgnoringFPD(target, origin)));
}
}
#else
#define DEBUG_CheckUnwrapSafety(obj, handler, origin, target) {}
#endif
static const Wrapper*
SelectWrapper(bool securityWrapper, bool wantXrays, XrayType xrayType,
@@ -430,18 +439,22 @@ WrapperFactory::Rewrap(JSContext* cx, Ha
MOZ_ASSERT(!js::IsWindow(obj));
MOZ_ASSERT(dom::IsJSAPIActive());
// Compute the information we need to select the right wrapper.
JSCompartment* origin = js::GetObjectCompartment(obj);
JSCompartment* target = js::GetContextCompartment(cx);
bool originIsChrome = AccessCheck::isChrome(origin);
bool targetIsChrome = AccessCheck::isChrome(target);
- bool originSubsumesTarget = AccessCheck::subsumesConsideringDomain(origin, target);
- bool targetSubsumesOrigin = AccessCheck::subsumesConsideringDomain(target, origin);
+ bool originSubsumesTarget = OriginAttributes::IsRestrictOpenerAccessForFPI() ?
+ AccessCheck::subsumesConsideringDomain(origin, target) :
+ AccessCheck::subsumesConsideringDomainIgnoringFPD(origin, target);
+ bool targetSubsumesOrigin = OriginAttributes::IsRestrictOpenerAccessForFPI() ?
+ AccessCheck::subsumesConsideringDomain(target, origin) :
+ AccessCheck::subsumesConsideringDomainIgnoringFPD(target, origin);
bool sameOrigin = targetSubsumesOrigin && originSubsumesTarget;
XrayType xrayType = GetXrayType(obj);
const Wrapper* wrapper;
//
// First, handle the special cases.
//