зеркало из https://github.com/mozilla/gecko-dev.git
Bug 800915 - Add infrastructure to flag security wrappers as unsafe to unwrap. r=mrbkap
This commit is contained in:
Родитель
b892d5b7f5
Коммит
118da73481
|
@ -519,7 +519,7 @@ nsPIDOMWindow::~nsPIDOMWindow() {}
|
|||
class nsOuterWindowProxy : public js::Wrapper
|
||||
{
|
||||
public:
|
||||
nsOuterWindowProxy() : js::Wrapper(0) {}
|
||||
nsOuterWindowProxy() : js::Wrapper(0) { setSafeToUnwrap(false); }
|
||||
|
||||
virtual bool isOuterWindow() {
|
||||
return true;
|
||||
|
|
|
@ -160,6 +160,7 @@ js::IsCrossCompartmentWrapper(RawObject wrapper)
|
|||
|
||||
Wrapper::Wrapper(unsigned flags, bool hasPrototype) : DirectProxyHandler(&sWrapperFamily)
|
||||
, mFlags(flags)
|
||||
, mSafeToUnwrap(true)
|
||||
{
|
||||
setHasPrototype(hasPrototype);
|
||||
}
|
||||
|
@ -796,7 +797,9 @@ CrossCompartmentWrapper CrossCompartmentWrapper::singleton(0u);
|
|||
template <class Base>
|
||||
SecurityWrapper<Base>::SecurityWrapper(unsigned flags)
|
||||
: Base(flags)
|
||||
{}
|
||||
{
|
||||
Base::setSafeToUnwrap(false);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
bool
|
||||
|
|
|
@ -29,6 +29,7 @@ class DummyFrameGuard;
|
|||
class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
|
||||
{
|
||||
unsigned mFlags;
|
||||
bool mSafeToUnwrap;
|
||||
|
||||
public:
|
||||
enum Action {
|
||||
|
@ -43,6 +44,15 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
|
|||
LAST_USED_FLAG = CROSS_COMPARTMENT
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrappers can explicitly specify that they are unsafe to unwrap from a
|
||||
* security perspective (as is the case for SecurityWrappers). If a wrapper
|
||||
* is not safe to unwrap, operations requiring full access to the underlying
|
||||
* object (via UnwrapObjectChecked) will throw. Otherwise, they will succeed.
|
||||
*/
|
||||
void setSafeToUnwrap(bool safe) { mSafeToUnwrap = safe; };
|
||||
bool isSafeToUnwrap() { return mSafeToUnwrap; };
|
||||
|
||||
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto,
|
||||
JSObject *parent, Wrapper *handler);
|
||||
|
||||
|
|
|
@ -291,6 +291,31 @@ GetWrappedNative(JSContext *cx, JSObject *obj)
|
|||
: nullptr;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
DEBUG_CheckUnwrapSafety(JSObject *obj, js::Wrapper *handler,
|
||||
JSCompartment *origin, JSCompartment *target)
|
||||
{
|
||||
typedef FilteringWrapper<CrossCompartmentSecurityWrapper, OnlyIfSubjectIsSystem> XSOW;
|
||||
|
||||
if (AccessCheck::isChrome(target) || xpc::IsUniversalXPConnectEnabled(target)) {
|
||||
// If the caller is chrome (or effectively so), unwrap should always be allowed.
|
||||
MOZ_ASSERT(handler->isSafeToUnwrap());
|
||||
} else if (WrapperFactory::IsLocationObject(obj) ||
|
||||
WrapperFactory::IsComponentsObject(obj) ||
|
||||
handler == &XSOW::singleton)
|
||||
{
|
||||
// This is an object that is restricted regardless of origin.
|
||||
MOZ_ASSERT(!handler->isSafeToUnwrap());
|
||||
} else {
|
||||
// Otherwise, it should depend on whether the target subsumes the origin.
|
||||
MOZ_ASSERT(handler->isSafeToUnwrap() == AccessCheck::subsumes(target, origin));
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define DEBUG_CheckUnwrapSafety(obj, handler, origin, target) {}
|
||||
#endif
|
||||
|
||||
JSObject *
|
||||
WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
|
||||
JSObject *wrappedProto, JSObject *parent,
|
||||
|
@ -443,6 +468,8 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj,
|
|||
}
|
||||
}
|
||||
|
||||
DEBUG_CheckUnwrapSafety(obj, wrapper, origin, target);
|
||||
|
||||
if (existing && proxyProto == wrappedProto)
|
||||
return Wrapper::Renew(cx, existing, obj, wrapper);
|
||||
|
||||
|
@ -465,7 +492,9 @@ WrapperFactory::WrapForSameCompartment(JSContext *cx, JSObject *obj)
|
|||
MOZ_ASSERT(wn, "Trying to wrap a dead WN!");
|
||||
|
||||
// The WN knows what to do.
|
||||
return wn->GetSameCompartmentSecurityWrapper(cx);
|
||||
JSObject *wrapper = wn->GetSameCompartmentSecurityWrapper(cx);
|
||||
MOZ_ASSERT_IF(wrapper != obj, !Wrapper::wrapperHandler(wrapper)->isSafeToUnwrap());
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
Загрузка…
Ссылка в новой задаче