Minimal fix for bug 504021. r=jst a=dveditz

git-svn-id: svn://10.0.0.236/trunk@259482 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
mrbkap%gmail.com 2010-01-27 01:21:43 +00:00
parent 4c16d780b7
commit dbea1036d8
7 changed files with 165 additions and 20 deletions

View File

@ -335,6 +335,33 @@ interface nsIScriptSecurityManager_1_9_0_BRANCH : nsIScriptSecurityManager
out JSStackFramePtr fp);
};
[scriptable, uuid(83db3256-5ff6-4703-a21d-8a5f7c8af4b0)]
interface nsIScriptSecurityManager_1_9_2 : nsIScriptSecurityManager_1_9_0_BRANCH
{
/**
* 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 supercedes 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++
#define NS_SCRIPTSECURITYMANAGER_CONTRACTID "@mozilla.org/scriptsecuritymanager;1"
#define NS_SCRIPTSECURITYMANAGER_CLASSNAME "scriptsecuritymanager"

View File

@ -368,7 +368,7 @@ MoveClassPolicyEntry(PLDHashTable *table,
{ 0x7ee2a4c0, 0x4b93, 0x17d3, \
{ 0xba, 0x18, 0x00, 0x60, 0xb0, 0xf1, 0x99, 0xa2 }}
class nsScriptSecurityManager : public nsIScriptSecurityManager_1_9_0_BRANCH,
class nsScriptSecurityManager : public nsIScriptSecurityManager_1_9_2,
public nsIPrefSecurityCheck,
public nsIChannelEventSink,
public nsIObserver
@ -381,6 +381,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSISCRIPTSECURITYMANAGER
NS_DECL_NSISCRIPTSECURITYMANAGER_1_9_0_BRANCH
NS_DECL_NSISCRIPTSECURITYMANAGER_1_9_2
NS_DECL_NSIXPCSECURITYMANAGER
NS_DECL_NSIPREFSECURITYCHECK
NS_DECL_NSICHANNELEVENTSINK
@ -483,13 +484,13 @@ private:
// Returns null if a principal cannot be found. Note that rv can be NS_OK
// when this happens -- this means that there was no script for the
// context. Callers MUST pass in a non-null rv here.
static nsIPrincipal*
nsIPrincipal*
GetSubjectPrincipal(JSContext* cx, nsresult* rv);
// Returns null if a principal cannot be found. Note that rv can be NS_OK
// when this happens -- this means that there was no script for the frame.
// Callers MUST pass in a non-null rv here.
static nsIPrincipal*
nsIPrincipal*
GetFramePrincipal(JSContext* cx, JSStackFrame* fp, nsresult* rv);
// Returns null if a principal cannot be found. Note that rv can be NS_OK
@ -511,7 +512,7 @@ private:
// Returns null if a principal cannot be found. Note that rv can be NS_OK
// when this happens -- this means that there was no script
// running. Callers MUST pass in a non-null rv here.
static nsIPrincipal*
nsIPrincipal*
GetPrincipalAndFrame(JSContext *cx,
JSStackFrame** frameResult,
nsresult* rv);
@ -565,6 +566,17 @@ private:
PrintPolicyDB();
#endif
struct ContextPrincipal {
ContextPrincipal(ContextPrincipal *next, JSContext *cx,
JSStackFrame *fp, nsIPrincipal *principal)
: mNext(next), mCx(cx), mFp(fp), mPrincipal(principal) {}
ContextPrincipal *mNext;
JSContext *mCx;
JSStackFrame *mFp;
nsCOMPtr<nsIPrincipal> mPrincipal;
};
// JS strings we need to clean up on shutdown
static jsval sEnabledID;
@ -585,6 +597,7 @@ private:
nsCOMPtr<nsIPrincipal> mSystemCertificate;
nsInterfaceHashtable<PrincipalKey, nsIPrincipal> mPrincipals;
nsCOMPtr<nsIThreadJSContextStack> mJSContextStack;
ContextPrincipal *mContextPrincipals;
PRPackedBool mIsJavaScriptEnabled;
PRPackedBool mIsMailJavaScriptEnabled;
PRPackedBool mIsWritingPrefs;

View File

@ -454,6 +454,32 @@ nsScriptSecurityManager::GetCxSubjectPrincipalAndFrame(JSContext *cx, JSStackFra
return principal;
}
NS_IMETHODIMP
nsScriptSecurityManager::PushContextPrincipal(JSContext *cx,
JSStackFrame *fp,
nsIPrincipal *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 //
////////////////////
@ -529,13 +555,14 @@ DeleteDomainEntry(nsHashKey *aKey, void *aData, void* closure)
////////////////////////////////////
// Methods implementing ISupports //
////////////////////////////////////
NS_IMPL_ISUPPORTS6(nsScriptSecurityManager,
NS_IMPL_ISUPPORTS7(nsScriptSecurityManager,
nsIScriptSecurityManager,
nsIXPCSecurityManager,
nsIPrefSecurityCheck,
nsIChannelEventSink,
nsIObserver,
nsIScriptSecurityManager_1_9_0_BRANCH)
nsIScriptSecurityManager_1_9_0_BRANCH,
nsIScriptSecurityManager_1_9_2)
///////////////////////////////////////////////////
// Methods implementing nsIScriptSecurityManager //
@ -2249,7 +2276,6 @@ nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
return GetScriptPrincipal(cx, script, rv);
}
// static
nsIPrincipal*
nsScriptSecurityManager::GetFramePrincipal(JSContext *cx,
JSStackFrame *fp,
@ -2279,7 +2305,6 @@ nsScriptSecurityManager::GetFramePrincipal(JSContext *cx,
return result;
}
// static
nsIPrincipal*
nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
JSStackFrame **frameResult,
@ -2289,12 +2314,27 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
//-- If there's no principal on the stack, look at the global object
// and return the innermost frame for annotations.
*rv = NS_OK;
if (cx)
{
// Get principals from innermost frame of JavaScript or Java.
JSStackFrame *target = nsnull;
nsIPrincipal *targetPrincipal = nsnull;
for (ContextPrincipal *cp = mContextPrincipals; cp; cp = cp->mNext)
{
if (cp->mCx == cx)
{
target = cp->mFp;
targetPrincipal = cp->mPrincipal;
break;
}
}
// Get principals from innermost JavaScript frame.
JSStackFrame *fp = nsnull; // tell JS_FrameIterator to start at innermost
for (fp = JS_FrameIterator(cx, &fp); fp; fp = JS_FrameIterator(cx, &fp))
{
if (fp == target)
break;
nsIPrincipal* result = GetFramePrincipal(cx, fp, rv);
if (result)
{
@ -2304,6 +2344,25 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
}
}
// If targetPrincipal is non-null, then it means that someone wants to
// clamp the principals on this context to this principal. Note that
// fp might not equal target here (fp might be null) because someone
// could have set aside the frame chain in the meantime.
if (targetPrincipal)
{
if (fp && fp == target)
{
*frameResult = fp;
}
else
{
JSStackFrame *inner = nsnull;
*frameResult = JS_FrameIterator(cx, &inner);
}
return targetPrincipal;
}
nsIScriptContext *scriptContext = GetScriptContext(cx);
if (scriptContext)
{
@ -2330,7 +2389,6 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
return nsnull;
}
// static
nsIPrincipal*
nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
nsresult* rv)
@ -3293,6 +3351,7 @@ nsScriptSecurityManager::nsScriptSecurityManager(void)
: mOriginToPolicyMap(nsnull),
mDefaultPolicy(nsnull),
mCapabilities(nsnull),
mContextPrincipals(nsnull),
mIsJavaScriptEnabled(PR_FALSE),
mIsMailJavaScriptEnabled(PR_FALSE),
mIsWritingPrefs(PR_FALSE),
@ -3369,6 +3428,7 @@ jsval nsScriptSecurityManager::sEnabledID = JSVAL_VOID;
nsScriptSecurityManager::~nsScriptSecurityManager(void)
{
NS_ASSERTION(!mContextPrincipals, "Leaking mContextPrincipals");
delete mOriginToPolicyMap;
if(mDefaultPolicy)
mDefaultPolicy->Drop();

View File

@ -916,7 +916,7 @@ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
class FullTrustSecMan
#ifndef XPCONNECT_STANDALONE
: public nsIScriptSecurityManager_1_9_0_BRANCH
: public nsIScriptSecurityManager_1_9_2
#else
: public nsIXPCSecurityManager
#endif
@ -927,6 +927,7 @@ public:
#ifndef XPCONNECT_STANDALONE
NS_DECL_NSISCRIPTSECURITYMANAGER
NS_DECL_NSISCRIPTSECURITYMANAGER_1_9_0_BRANCH
NS_DECL_NSISCRIPTSECURITYMANAGER_1_9_2
#endif
FullTrustSecMan();
@ -946,6 +947,7 @@ NS_INTERFACE_MAP_BEGIN(FullTrustSecMan)
NS_INTERFACE_MAP_ENTRY(nsIXPCSecurityManager)
#ifndef XPCONNECT_STANDALONE
NS_INTERFACE_MAP_ENTRY(nsIScriptSecurityManager)
NS_INTERFACE_MAP_ENTRY(nsIScriptSecurityManager_1_9_2)
#endif
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCSecurityManager)
NS_INTERFACE_MAP_END
@ -1078,6 +1080,20 @@ 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

@ -169,8 +169,8 @@ public:
/**
* Returns the script security manager used by XPConnect.
*/
static nsIScriptSecurityManager_1_9_0_BRANCH *GetSecurityManager() {
extern nsIScriptSecurityManager_1_9_0_BRANCH *gScriptSecurityManager;
static nsIScriptSecurityManager_1_9_2 *GetSecurityManager() {
extern nsIScriptSecurityManager_1_9_2 *gScriptSecurityManager;
return gScriptSecurityManager;
}

View File

@ -65,7 +65,7 @@ PRUint32 nsXPConnect::gReportAllJSExceptions = 0;
// Global cache of the default script security manager (QI'd to
// nsIScriptSecurityManager)
nsIScriptSecurityManager_1_9_0_BRANCH *gScriptSecurityManager = nsnull;
nsIScriptSecurityManager_1_9_2 *gScriptSecurityManager = nsnull;
const char XPC_CONTEXT_STACK_CONTRACTID[] = "@mozilla.org/js/xpc/ContextStack;1";
const char XPC_RUNTIME_CONTRACTID[] = "@mozilla.org/js/xpc/RuntimeService;1";
@ -1685,7 +1685,7 @@ nsXPConnect::SetDefaultSecurityManager(nsIXPCSecurityManager *aManager,
mDefaultSecurityManager = aManager;
mDefaultSecurityManagerFlags = flags;
nsCOMPtr<nsIScriptSecurityManager_1_9_0_BRANCH> ssm =
nsCOMPtr<nsIScriptSecurityManager_1_9_2> ssm =
do_QueryInterface(mDefaultSecurityManager);
// Remember the result of the above QI for fast access to the

View File

@ -42,6 +42,7 @@
/* Sharable code and data for wrapper around JSObjects. */
#include "xpcprivate.h"
#include "XPCWrapper.h"
NS_IMPL_THREADSAFE_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass)
@ -1122,6 +1123,8 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
XPCContext* xpcc;
JSContext* cx;
JSObject* thisObj;
JSBool popPrincipal = JS_FALSE;
nsIScriptSecurityManager_1_9_2* ssm = nsnull;
// Make sure not to set the callee on ccx until after we've gone through
// the whole nsIXPCFunctionThisTranslator bit. That code uses ccx to
@ -1449,8 +1452,6 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
*sp++ = val;
}
readyToDoTheCall = JS_TRUE;
pre_call_clean_up:
@ -1512,6 +1513,31 @@ pre_call_clean_up:
JS_ClearPendingException(cx);
if(XPCPerThreadData::IsMainThread(ccx))
{
ssm = XPCWrapper::GetSecurityManager();
if(ssm)
{
nsCOMPtr<nsIPrincipal> objPrincipal;
ssm->GetObjectPrincipal(ccx, obj, getter_AddRefs(objPrincipal));
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 done;
}
popPrincipal = JS_TRUE;
}
}
}
if(XPT_MD_IS_GETTER(info->flags))
success = JS_GetProperty(cx, obj, name, &result);
else if(XPT_MD_IS_SETTER(info->flags))
@ -1548,7 +1574,10 @@ pre_call_clean_up:
}
}
if (!success)
if(popPrincipal)
ssm->PopContextPrincipal(ccx);
if(!success)
{
PRBool forceReport;
if(NS_FAILED(mInfo->IsFunction(&forceReport)))