зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
6a1371e983
Коммит
3065c84571
|
@ -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++
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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, ¤tfp),
|
||||
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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче