mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 739825 - Push principals when entering compartments in structured clone. r=mrbkap
This commit is contained in:
parent
4036c3cfb5
commit
403f8c3812
@ -198,6 +198,44 @@ GetScriptContext(JSContext *cx)
|
||||
return GetScriptContextFromJSContext(cx);
|
||||
}
|
||||
|
||||
// Callbacks for the JS engine to use to push/pop context principals.
|
||||
static JSBool
|
||||
PushPrincipalCallback(JSContext *cx, JSPrincipals *principals)
|
||||
{
|
||||
// We should already be in the compartment of the given principal.
|
||||
MOZ_ASSERT(principals ==
|
||||
JS_GetCompartmentPrincipals((js::GetContextCompartment(cx))));
|
||||
|
||||
// Get the security manager.
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
if (!ssm) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Push the principal.
|
||||
JSStackFrame *fp = NULL;
|
||||
nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp),
|
||||
nsJSPrincipals::get(principals));
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
PopPrincipalCallback(JSContext *cx)
|
||||
{
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
if (ssm) {
|
||||
ssm->PopContextPrincipal(cx);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline void SetPendingException(JSContext *cx, const char *aMsg)
|
||||
{
|
||||
JSAutoRequest ar(cx);
|
||||
@ -3391,7 +3429,9 @@ nsresult nsScriptSecurityManager::Init()
|
||||
CheckObjectAccess,
|
||||
nsJSPrincipals::Subsume,
|
||||
ObjectPrincipalFinder,
|
||||
ContentSecurityPolicyPermitsJSAction
|
||||
ContentSecurityPolicyPermitsJSAction,
|
||||
PushPrincipalCallback,
|
||||
PopPrincipalCallback
|
||||
};
|
||||
|
||||
MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime));
|
||||
|
@ -1437,7 +1437,7 @@ JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext *cx, JSObject *target)
|
||||
JSAutoEnterCompartment::~JSAutoEnterCompartment()
|
||||
{
|
||||
if (state == STATE_OTHER_COMPARTMENT) {
|
||||
AutoCompartment* ac = reinterpret_cast<AutoCompartment*>(bytes);
|
||||
AutoCompartment* ac = getAutoCompartment();
|
||||
CHECK_REQUEST(ac->context);
|
||||
ac->~AutoCompartment();
|
||||
}
|
||||
|
@ -1580,6 +1580,16 @@ typedef JSPrincipals *
|
||||
typedef JSBool
|
||||
(* JSCSPEvalChecker)(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Security callbacks for pushing and popping context principals. These are only
|
||||
* temporarily necessary and will hopefully be gone again in a matter of weeks.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSPushContextPrincipalOp)(JSContext *cx, JSPrincipals *principals);
|
||||
|
||||
typedef JSBool
|
||||
(* JSPopContextPrincipalOp)(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Callback used to ask the embedding for the cross compartment wrapper handler
|
||||
* that implements the desired prolicy for this kind of object in the
|
||||
@ -2723,6 +2733,10 @@ js_TransplantObjectWithWrapper(JSContext *cx,
|
||||
#ifdef __cplusplus
|
||||
JS_END_EXTERN_C
|
||||
|
||||
namespace js {
|
||||
struct AutoCompartment;
|
||||
}
|
||||
|
||||
class JS_PUBLIC_API(JSAutoEnterCompartment)
|
||||
{
|
||||
/*
|
||||
@ -2735,6 +2749,12 @@ class JS_PUBLIC_API(JSAutoEnterCompartment)
|
||||
*/
|
||||
void* bytes[sizeof(void*) == 4 && MOZ_ALIGNOF(uint64_t) == 8 ? 16 : 13];
|
||||
|
||||
protected:
|
||||
js::AutoCompartment *getAutoCompartment() {
|
||||
JS_ASSERT(state == STATE_OTHER_COMPARTMENT);
|
||||
return reinterpret_cast<js::AutoCompartment*>(bytes);
|
||||
}
|
||||
|
||||
/*
|
||||
* This object may be in one of three states. If enter() or
|
||||
* enterAndIgnoreErrors() hasn't been called, it's in STATE_UNENTERED.
|
||||
@ -4234,6 +4254,8 @@ struct JSSecurityCallbacks {
|
||||
JSSubsumePrincipalsOp subsumePrincipals;
|
||||
JSObjectPrincipalsFinder findObjectPrincipals;
|
||||
JSCSPEvalChecker contentSecurityPolicyAllows;
|
||||
JSPushContextPrincipalOp pushContextPrincipal;
|
||||
JSPopContextPrincipalOp popContextPrincipal;
|
||||
};
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
|
@ -510,6 +510,34 @@ JSStructuredCloneWriter::startObject(JSObject *obj)
|
||||
return out.writePair(obj->isArray() ? SCTAG_ARRAY_OBJECT : SCTAG_OBJECT_OBJECT, 0);
|
||||
}
|
||||
|
||||
class AutoEnterCompartmentAndPushPrincipal : public JSAutoEnterCompartment
|
||||
{
|
||||
public:
|
||||
bool enter(JSContext *cx, JSObject *target) {
|
||||
// First, enter the compartment.
|
||||
if (!JSAutoEnterCompartment::enter(cx, target))
|
||||
return false;
|
||||
|
||||
// We only need to push a principal if we changed compartments.
|
||||
if (state != STATE_OTHER_COMPARTMENT)
|
||||
return true;
|
||||
|
||||
// Push.
|
||||
const JSSecurityCallbacks *cb = cx->runtime->securityCallbacks;
|
||||
return cb->pushContextPrincipal(cx, target->principals(cx));
|
||||
};
|
||||
|
||||
~AutoEnterCompartmentAndPushPrincipal() {
|
||||
// Pop the principal if necessary.
|
||||
if (state == STATE_OTHER_COMPARTMENT) {
|
||||
AutoCompartment *ac = getAutoCompartment();
|
||||
const JSSecurityCallbacks *cb = ac->context->runtime->securityCallbacks;
|
||||
cb->popContextPrincipal(ac->context);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
bool
|
||||
JSStructuredCloneWriter::startWrite(const js::Value &v)
|
||||
{
|
||||
@ -536,7 +564,7 @@ JSStructuredCloneWriter::startWrite(const js::Value &v)
|
||||
|
||||
// If we unwrapped above, we'll need to enter the underlying compartment.
|
||||
// Let the AutoEnterCompartment do the right thing for us.
|
||||
JSAutoEnterCompartment ac;
|
||||
AutoEnterCompartmentAndPushPrincipal ac;
|
||||
if (!ac.enter(context(), obj))
|
||||
return false;
|
||||
|
||||
@ -581,7 +609,7 @@ JSStructuredCloneWriter::write(const Value &v)
|
||||
JSObject *obj = &objs.back().toObject();
|
||||
|
||||
// The objects in |obj| can live in other compartments.
|
||||
JSAutoEnterCompartment ac;
|
||||
AutoEnterCompartmentAndPushPrincipal ac;
|
||||
if (!ac.enter(context(), obj))
|
||||
return false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user