Bug 754202 - Remove context pushing/popping API. r=mrbkap

Each one of these uses grabs the principal off of an object for pushing, but also enters the compartment of that object. So we shouldn't need this anymore.

Can I get a 'hell yeah'?
This commit is contained in:
Bobby Holley 2012-06-07 14:28:21 +02:00
parent 22f683d552
commit a2ec0f4f20
10 changed files with 5 additions and 273 deletions

View File

@ -9,7 +9,7 @@
interface nsIURI;
interface nsIChannel;
[scriptable, uuid(3708aa92-e2d9-4fd1-9e46-edfa3eb5ebf5)]
[scriptable, uuid(cdb27711-492b-4973-938b-de81ac124658)]
interface nsIScriptSecurityManager : nsIXPCSecurityManager
{
///////////////// Security Checks //////////////////
@ -260,29 +260,6 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
[noscript,notxpcom] nsIPrincipal getCxSubjectPrincipal(in JSContextPtr cx);
[noscript,notxpcom] nsIPrincipal getCxSubjectPrincipalAndFrame(in JSContextPtr cx,
out JSStackFramePtr fp);
/**
* If no scripted code is running "above" (or called from) fp, then
* instead of looking at cx->globalObject, we will return |principal|.
* This function only affects |cx|. If someone pushes another context onto
* the context stack, then it supersedes this call.
* NOTE: If |fp| is non-null popContextPrincipal must be called before fp
* has finished executing.
*
* @param cx The context to clamp.
* @param fp The frame pointer to clamp at. May be 'null'.
* @param principal The principal to clamp to.
*/
[noscript] void pushContextPrincipal(in JSContextPtr cx,
in JSStackFramePtr fp,
in nsIPrincipal principal);
/**
* Removes a clamp set by pushContextPrincipal from cx. This must be
* called in a stack-like fashion (e.g., given two contexts |a| and |b|,
* it is not legal to do: push(a) push(b) pop(a)).
*/
[noscript] void popContextPrincipal(in JSContextPtr cx);
};
%{C++

View File

@ -162,44 +162,6 @@ 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);
@ -404,34 +366,6 @@ nsScriptSecurityManager::GetCxSubjectPrincipalAndFrame(JSContext *cx, JSStackFra
return principal;
}
NS_IMETHODIMP
nsScriptSecurityManager::PushContextPrincipal(JSContext *cx,
JSStackFrame *fp,
nsIPrincipal *principal)
{
NS_ASSERTION(principal, "Must pass a non-null principal");
ContextPrincipal *cp = new ContextPrincipal(mContextPrincipals, cx, fp,
principal);
if (!cp)
return NS_ERROR_OUT_OF_MEMORY;
mContextPrincipals = cp;
return NS_OK;
}
NS_IMETHODIMP
nsScriptSecurityManager::PopContextPrincipal(JSContext *cx)
{
NS_ASSERTION(mContextPrincipals->mCx == cx, "Mismatched push/pop");
ContextPrincipal *next = mContextPrincipals->mNext;
delete mContextPrincipals;
mContextPrincipals = next;
return NS_OK;
}
////////////////////
// Policy Storage //
////////////////////
@ -3127,9 +3061,7 @@ nsresult nsScriptSecurityManager::Init()
CheckObjectAccess,
nsJSPrincipals::Subsume,
ObjectPrincipalFinder,
ContentSecurityPolicyPermitsJSAction,
PushPrincipalCallback,
PopPrincipalCallback
ContentSecurityPolicyPermitsJSAction
};
MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime));

View File

@ -1237,9 +1237,6 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
jsval val;
rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
NS_ENSURE_SUCCESS(rv, rv);
nsJSContext::TerminationFuncHolder holder(this);
// SecurityManager said "ok", but don't compile if aVersion is unknown.
@ -1295,8 +1292,6 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
}
}
sSecurityManager->PopContextPrincipal(mContext);
// Pop here, after JS_ValueToString and any other possible evaluation.
if (NS_FAILED(stack->Pop(nsnull)))
rv = NS_ERROR_FAILURE;
@ -1445,9 +1440,6 @@ nsJSContext::EvaluateString(const nsAString& aScript,
jsval val = JSVAL_VOID;
jsval* vp = aRetValue ? &val : NULL;
rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
NS_ENSURE_SUCCESS(rv, rv);
nsJSContext::TerminationFuncHolder holder(this);
++mExecuteDepth;
@ -1499,8 +1491,6 @@ nsJSContext::EvaluateString(const nsAString& aScript,
--mExecuteDepth;
sSecurityManager->PopContextPrincipal(mContext);
// Pop here, after JS_ValueToString and any other possible evaluation.
if (NS_FAILED(stack->Pop(nsnull)))
rv = NS_ERROR_FAILURE;
@ -1598,15 +1588,6 @@ nsJSContext::ExecuteScript(JSScript* aScriptObject,
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPrincipal> principal;
rv = sSecurityManager->GetObjectPrincipal(mContext,
JS_GetGlobalFromScript(aScriptObject),
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
NS_ENSURE_SUCCESS(rv, rv);
nsJSContext::TerminationFuncHolder holder(this);
XPCAutoRequest ar(mContext);
++mExecuteDepth;
@ -1633,8 +1614,6 @@ nsJSContext::ExecuteScript(JSScript* aScriptObject,
--mExecuteDepth;
sSecurityManager->PopContextPrincipal(mContext);
// Pop here, after JS_ValueToString and any other possible evaluation.
if (NS_FAILED(stack->Pop(nsnull)))
rv = NS_ERROR_FAILURE;
@ -1875,24 +1854,12 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
jsval *argv = nsnull;
JSObject *funobj = aHandler;
nsCOMPtr<nsIPrincipal> principal;
rv = sSecurityManager->GetObjectPrincipal(mContext, funobj,
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
JSStackFrame *currentfp = nsnull;
rv = sSecurityManager->PushContextPrincipal(mContext,
JS_FrameIterator(mContext, &currentfp),
principal);
NS_ENSURE_SUCCESS(rv, rv);
jsval funval = OBJECT_TO_JSVAL(funobj);
JSAutoEnterCompartment ac;
js::ForceFrame ff(mContext, funobj);
if (!ac.enter(mContext, funobj) || !ff.enter() ||
!JS_WrapObject(mContext, &target)) {
ReportPendingException();
sSecurityManager->PopContextPrincipal(mContext);
return NS_ERROR_FAILURE;
}
@ -1935,8 +1902,6 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
// nested calls through XPConnect.
if (NS_FAILED(rv))
ReportPendingException();
sSecurityManager->PopContextPrincipal(mContext);
}
pusher.Pop();

View File

@ -177,32 +177,15 @@ nsJSON::EncodeFromJSVal(JS::Value *value, JSContext *cx, nsAString &result)
JSAutoRequest ar(cx);
JSAutoEnterCompartment ac;
nsIScriptSecurityManager *ssm = nsnull;
if (value->isObject()) {
JSObject *obj = &value->toObject();
if (!ac.enter(cx, obj)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPrincipal> principal;
ssm = nsContentUtils::GetSecurityManager();
nsresult rv = ssm->GetObjectPrincipal(cx, obj, getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
JSStackFrame *fp = nsnull;
rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp), principal);
NS_ENSURE_SUCCESS(rv, rv);
}
nsJSONWriter writer;
JSBool ok = JS_Stringify(cx, value, NULL, JSVAL_NULL,
WriteCallback, &writer);
if (ssm) {
ssm->PopContextPrincipal(cx);
}
if (!ok) {
if (!JS_Stringify(cx, value, NULL, JSVAL_NULL, WriteCallback, &writer)) {
return NS_ERROR_XPC_BAD_CONVERT_JS;
}

View File

@ -880,20 +880,6 @@ FullTrustSecMan::GetCxSubjectPrincipalAndFrame(JSContext *cx,
return mSystemPrincipal;
}
NS_IMETHODIMP
FullTrustSecMan::PushContextPrincipal(JSContext *cx,
JSStackFrame *fp,
nsIPrincipal *principal)
{
return NS_OK;
}
NS_IMETHODIMP
FullTrustSecMan::PopContextPrincipal(JSContext *cx)
{
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
XPCShellDirProvider::AddRef()
{

View File

@ -1671,16 +1671,6 @@ 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
@ -4349,8 +4339,6 @@ struct JSSecurityCallbacks {
JSSubsumePrincipalsOp subsumePrincipals;
JSObjectPrincipalsFinder findObjectPrincipals;
JSCSPEvalChecker contentSecurityPolicyAllows;
JSPushContextPrincipalOp pushContextPrincipal;
JSPopContextPrincipalOp popContextPrincipal;
};
extern JS_PUBLIC_API(void)

View File

@ -472,37 +472,6 @@ 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;
if (cb->pushContextPrincipal)
return cb->pushContextPrincipal(cx, target->principals(cx));
return true;
};
~AutoEnterCompartmentAndPushPrincipal() {
// Pop the principal if necessary.
if (state == STATE_OTHER_COMPARTMENT) {
AutoCompartment *ac = getAutoCompartment();
const JSSecurityCallbacks *cb = ac->context->runtime->securityCallbacks;
if (cb->popContextPrincipal)
cb->popContextPrincipal(ac->context);
}
};
};
bool
JSStructuredCloneWriter::startWrite(const Value &v)
{
@ -529,7 +498,7 @@ JSStructuredCloneWriter::startWrite(const Value &v)
// If we unwrapped above, we'll need to enter the underlying compartment.
// Let the AutoEnterCompartment do the right thing for us.
AutoEnterCompartmentAndPushPrincipal ac;
JSAutoEnterCompartment ac;
if (!ac.enter(context(), obj))
return false;
@ -574,7 +543,7 @@ JSStructuredCloneWriter::write(const Value &v)
RootedObject obj(context(), &objs.back().toObject());
// The objects in |obj| can live in other compartments.
AutoEnterCompartmentAndPushPrincipal ac;
JSAutoEnterCompartment ac;
if (!ac.enter(context(), obj))
return false;

View File

@ -1395,20 +1395,6 @@ FullTrustSecMan::GetSubjectPrincipal(nsIPrincipal **_retval)
return *_retval ? NS_OK : NS_ERROR_FAILURE;
}
/* [noscript] void pushContextPrincipal (in JSContextPtr cx, in JSStackFramePtr fp, in nsIPrincipal principal); */
NS_IMETHODIMP
FullTrustSecMan::PushContextPrincipal(JSContext * cx, JSStackFrame * fp, nsIPrincipal *principal)
{
return NS_OK;
}
/* [noscript] void popContextPrincipal (in JSContextPtr cx); */
NS_IMETHODIMP
FullTrustSecMan::PopContextPrincipal(JSContext * cx)
{
return NS_OK;
}
/* [noscript] nsIPrincipal getSystemPrincipal (); */
NS_IMETHODIMP
FullTrustSecMan::GetSystemPrincipal(nsIPrincipal **_retval)

View File

@ -1116,17 +1116,6 @@ nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
return NS_ERROR_FAILURE;
}
class ContextPrincipalGuard
{
nsIScriptSecurityManager *ssm;
XPCCallContext &ccx;
public:
ContextPrincipalGuard(XPCCallContext &ccx)
: ssm(nsnull), ccx(ccx) {}
void principalPushed(nsIScriptSecurityManager *ssm) { this->ssm = ssm; }
~ContextPrincipalGuard() { if (ssm) ssm->PopContextPrincipal(ccx); }
};
NS_IMETHODIMP
nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
const XPTMethodDescriptor* info,
@ -1170,7 +1159,6 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
JS::AutoValueVector args(cx);
AutoScriptEvaluate scriptEval(cx);
ContextPrincipalGuard principalGuard(ccx);
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
uint8_t paramCount = info->num_args;
@ -1184,28 +1172,6 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
xpcc->SetException(nsnull);
ccx.GetThreadData()->SetException(nsnull);
if (XPCPerThreadData::IsMainThread(ccx)) {
// TODO Remove me in favor of security wrappers.
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (ssm) {
nsIPrincipal *objPrincipal =
xpc::AccessCheck::getPrincipal(js::GetObjectCompartment(obj));
if (objPrincipal) {
JSStackFrame* fp = nsnull;
nsresult rv =
ssm->PushContextPrincipal(ccx, JS_FrameIterator(ccx, &fp),
objPrincipal);
if (NS_FAILED(rv)) {
JS_ReportOutOfMemory(ccx);
retval = NS_ERROR_OUT_OF_MEMORY;
goto pre_call_clean_up;
}
principalGuard.principalPushed(ssm);
}
}
}
// We use js_Invoke so that the gcthings we use as args will be rooted by
// the engine as we do conversions and prepare to do the function call.

View File

@ -74,32 +74,12 @@ bool
NoWaiverWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp)
{
*bp = true; // always allowed
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (!ssm) {
return true;
}
// Note: By the time enter is called here, CrossCompartmentWrapper has
// already pushed the fake stack frame onto cx. Because of this, the frame
// that we're clamping is the one that we want (the one in our compartment).
JSStackFrame *fp = NULL;
nsIPrincipal *principal = GetCompartmentPrincipal(js::GetObjectCompartment(wrappedObject(wrapper)));
nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp), principal);
if (NS_FAILED(rv)) {
NS_WARNING("Not allowing call because we're out of memory");
JS_ReportOutOfMemory(cx);
return false;
}
return true;
}
void
NoWaiverWrapper::leave(JSContext *cx, JSObject *wrapper)
{
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (ssm) {
ssm->PopContextPrincipal(cx);
}
}
}