Bug 658909 - Make isSafeToUnwrap pseudo-dynamic for SOWs. r=mrbkap

This can go away as soon as XBL scopes are no longer behind a pref.
This commit is contained in:
Bobby Holley 2013-03-21 08:20:41 -07:00
parent 8be761a0f4
commit 821b04d2d6
6 changed files with 45 additions and 4 deletions

View File

@ -46,7 +46,7 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
* object (via UnwrapObjectChecked) will throw. Otherwise, they will succeed. * object (via UnwrapObjectChecked) will throw. Otherwise, they will succeed.
*/ */
void setSafeToUnwrap(bool safe) { mSafeToUnwrap = safe; } void setSafeToUnwrap(bool safe) { mSafeToUnwrap = safe; }
bool isSafeToUnwrap() { return mSafeToUnwrap; } virtual bool isSafeToUnwrap() { return mSafeToUnwrap; }
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto, static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto,
JSObject *parent, Wrapper *handler); JSObject *parent, Wrapper *handler);

View File

@ -269,6 +269,19 @@ AccessCheck::isScriptAccessOnly(JSContext *cx, JSObject *wrapper)
return false; return false;
} }
bool
OnlyIfSubjectIsSystem::isSafeToUnwrap()
{
if (XPCJSRuntime::Get()->XBLScopesEnabled())
return false;
// It's nasty to use the context stack here, but the alternative is passing cx all
// the way down through UnwrapObjectChecked, which we just undid in a 100k patch. :-(
JSContext *cx = nsContentUtils::GetCurrentJSContext();
if (!cx)
return true;
return AccessCheck::isSystemOnlyAccessPermitted(cx);
}
enum Access { READ = (1<<0), WRITE = (1<<1), NO_ACCESS = 0 }; enum Access { READ = (1<<0), WRITE = (1<<1), NO_ACCESS = 0 };
static bool static bool

View File

@ -50,6 +50,9 @@ struct Opaque : public Policy {
{ {
return false; return false;
} }
static bool isSafeToUnwrap() {
return false;
}
}; };
// This policy only permits access to the object if the subject can touch // This policy only permits access to the object if the subject can touch
@ -67,6 +70,8 @@ struct OnlyIfSubjectIsSystem : public Policy {
{ {
return AccessCheck::isSystemOnlyAccessPermitted(cx); return AccessCheck::isSystemOnlyAccessPermitted(cx);
} }
static bool isSafeToUnwrap();
}; };
// This policy only permits access to properties that are safe to be used // This policy only permits access to properties that are safe to be used
@ -82,6 +87,10 @@ struct CrossOriginAccessiblePropertiesOnly : public Policy {
{ {
return false; return false;
} }
static bool isSafeToUnwrap() {
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
@ -94,6 +103,10 @@ struct ExposedPropertiesOnly : public Policy {
return act == js::Wrapper::GET; return act == js::Wrapper::GET;
} }
static bool allowNativeCall(JSContext *cx, JS::IsAcceptableThis test, JS::NativeImpl impl); static bool allowNativeCall(JSContext *cx, JS::IsAcceptableThis test, JS::NativeImpl impl);
static bool isSafeToUnwrap() {
return false;
}
}; };
// Components specific policy // Components specific policy
@ -106,6 +119,10 @@ struct ComponentsObjectPolicy : public Policy {
static bool allowNativeCall(JSContext *cx, JS::IsAcceptableThis test, JS::NativeImpl impl) { static bool allowNativeCall(JSContext *cx, JS::IsAcceptableThis test, JS::NativeImpl impl) {
return false; return false;
} }
static bool isSafeToUnwrap() {
return false;
}
}; };
} }

View File

@ -29,6 +29,13 @@ FilteringWrapper<Base, Policy>::~FilteringWrapper()
{ {
} }
template <typename Base, typename Policy>
bool
FilteringWrapper<Base, Policy>::isSafeToUnwrap()
{
return Policy::isSafeToUnwrap();
}
template <typename Policy> template <typename Policy>
static bool static bool
Filter(JSContext *cx, JSObject *wrapper, AutoIdVector &props) Filter(JSContext *cx, JSObject *wrapper, AutoIdVector &props)

View File

@ -19,6 +19,9 @@ class FilteringWrapper : public Base {
FilteringWrapper(unsigned flags); FilteringWrapper(unsigned flags);
virtual ~FilteringWrapper(); virtual ~FilteringWrapper();
// This is potentially dynamic until XBL scopes are no longer behind a pref.
virtual bool isSafeToUnwrap();
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, js::PropertyDescriptor *desc, unsigned flags) MOZ_OVERRIDE; virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, js::PropertyDescriptor *desc, unsigned flags) MOZ_OVERRIDE;
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, js::PropertyDescriptor *desc, unsigned flags) MOZ_OVERRIDE; virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, js::PropertyDescriptor *desc, unsigned flags) MOZ_OVERRIDE;
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props) MOZ_OVERRIDE; virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props) MOZ_OVERRIDE;

View File

@ -284,8 +284,8 @@ DEBUG_CheckUnwrapSafety(JSObject *obj, js::Wrapper *handler,
// The Components object that is restricted regardless of origin. // The Components object that is restricted regardless of origin.
MOZ_ASSERT(!handler->isSafeToUnwrap()); MOZ_ASSERT(!handler->isSafeToUnwrap());
} else if (AccessCheck::needsSystemOnlyWrapper(obj)) { } else if (AccessCheck::needsSystemOnlyWrapper(obj)) {
// SOWs are opaque to everyone but Chrome and XBL scopes. // SOWs have a dynamic unwrap check, so we can't really say anything useful
MOZ_ASSERT(handler->isSafeToUnwrap() == nsContentUtils::CanAccessNativeAnon()); // about them here :-(
} else { } else {
// Otherwise, it should depend on whether the target subsumes the origin. // Otherwise, it should depend on whether the target subsumes the origin.
MOZ_ASSERT(handler->isSafeToUnwrap() == AccessCheck::subsumes(target, origin)); MOZ_ASSERT(handler->isSafeToUnwrap() == AccessCheck::subsumes(target, origin));
@ -499,7 +499,8 @@ WrapperFactory::WrapForSameCompartment(JSContext *cx, JSObject *obj)
// The WN knows what to do. // The WN knows what to do.
JSObject *wrapper = wn->GetSameCompartmentSecurityWrapper(cx); JSObject *wrapper = wn->GetSameCompartmentSecurityWrapper(cx);
MOZ_ASSERT_IF(wrapper != obj, !Wrapper::wrapperHandler(wrapper)->isSafeToUnwrap()); MOZ_ASSERT_IF(wrapper != obj && IsComponentsObject(js::UnwrapObject(obj)),
!Wrapper::wrapperHandler(wrapper)->isSafeToUnwrap());
return wrapper; return wrapper;
} }