Bug 667388 - Introduce the PUNCTURE wrapper action. r=mrbkap

This commit is contained in:
Bobby Holley 2012-03-23 14:59:27 -07:00
parent 563b97de8f
commit f8fe97314f
3 changed files with 49 additions and 3 deletions

View File

@ -100,8 +100,35 @@ class JS_FRIEND_API(Wrapper) : public ProxyHandler
virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE;
/* Policy enforcement traps. */
enum Action { GET, SET, CALL };
/* Policy enforcement traps.
*
* enter() allows the policy to specify whether the caller may perform |act|
* on the underlying object's |id| property. In the case when |act| is CALL,
* |id| is generally JSID_VOID.
*
* leave() allows the policy to undo various scoped state changes taken in
* enter(). If enter() succeeds, leave() must be called upon completion of
* the approved action.
*
* The |act| parameter to enter() specifies the action being performed. GET,
* SET, and CALL are self-explanatory, but PUNCTURE requires more explanation:
*
* GET and SET allow for a very fine-grained security membrane, through
* which access can be granted or denied on a per-property, per-object, and
* per-action basis. Sometimes though, we just want to asks if we can access
* _everything_ behind the wrapper barrier. For example, when the structured
* clone algorithm runs up against a cross-compartment wrapper, it needs to
* know whether it can enter the compartment and keep cloning, or whether it
* should throw. This is the role of PUNCTURE.
*
* PUNCTURE allows the policy to specify whether the wrapper barrier may
* be lifted - that is to say, whether the caller is allowed to access
* anything that the wrapped object could access. This is a very powerful
* permission, and thus should generally be denied for security wrappers
* except under very special circumstances. When |act| is PUNCTURE, |id|
* should be JSID_VOID.
* */
enum Action { GET, SET, CALL, PUNCTURE };
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp);
virtual void leave(JSContext *cx, JSObject *wrapper);

View File

@ -306,6 +306,15 @@ AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, JSObject *wrapper, jsid
JSObject *obj = Wrapper::wrappedObject(wrapper);
// LocationPolicy checks PUNCTURE first, so we should never get here for
// Location wrappers. For all other wrappers interested in cross-origin
// semantics, we want to allow puncturing only for the same-origin
// document.domain case.
if (act == Wrapper::PUNCTURE) {
MOZ_ASSERT(!WrapperFactory::IsLocationObject(obj));
return documentDomainMakesSameOrigin(cx, obj);
}
const char *name;
js::Class *clasp = js::GetObjectClass(obj);
NS_ASSERTION(Jsvalify(clasp) != &XrayUtils::HolderClass, "shouldn't have a holder here");
@ -498,6 +507,10 @@ ExposedPropertiesOnly::check(JSContext *cx, JSObject *wrapper, jsid id, Wrapper:
perm = PermitObjectAccess;
return true;
}
if (act == Wrapper::PUNCTURE) {
perm = DenyAccess;
return false;
}
perm = DenyAccess;

View File

@ -151,12 +151,18 @@ struct LocationPolicy : public Policy {
// We should only be dealing with Location objects here.
MOZ_ASSERT(WrapperFactory::IsLocationObject(js::UnwrapObject(wrapper)));
// Default to deny.
perm = DenyAccess;
// Location object security is complicated enough. Don't allow punctures.
if (act == js::Wrapper::PUNCTURE)
return false;
if (AccessCheck::isCrossOriginAccessPermitted(cx, wrapper, id, act) ||
AccessCheck::isLocationObjectSameOrigin(cx, wrapper)) {
perm = PermitPropertyAccess;
return true;
}
perm = DenyAccess;
JSAutoEnterCompartment ac;
if (!ac.enter(cx, wrapper))
return false;