Fixing bug 201132. Always use the JSPrincipals from the target object when compiling event handlers, never use the principals of the global object in which the event handler is compiled. Also make sure we never use the principals that are precompiled into cloned Functions, always get the principal from the Function's scope in such cases. r=mstoltz@netscape.com (and heikki@netscape.com), sr=brendan@mozilla.org
This commit is contained in:
Родитель
1bdbf1e104
Коммит
981b45ec02
|
@ -1386,8 +1386,20 @@ nsScriptSecurityManager::CheckFunctionAccess(JSContext *aCx, void *aFunObj,
|
|||
getter_AddRefs(subject));
|
||||
//-- If subject is null, get a principal from the function object's scope.
|
||||
if (NS_SUCCEEDED(rv) && !subject)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
{
|
||||
JSFunction *fun =
|
||||
(JSFunction *)JS_GetPrivate(aCx, (JSObject *)aFunObj);
|
||||
JSScript *script = JS_GetFunctionScript(aCx, fun);
|
||||
|
||||
NS_ASSERTION(!script, "Null principal for non-native function!");
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = doGetObjectPrincipal(aCx, (JSObject*)aFunObj,
|
||||
getter_AddRefs(subject));
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!subject) return NS_ERROR_FAILURE;
|
||||
|
@ -1811,16 +1823,20 @@ nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
|
|||
|
||||
nsCOMPtr<nsIPrincipal> scriptPrincipal;
|
||||
if (script)
|
||||
if (NS_FAILED(GetScriptPrincipal(cx, script, getter_AddRefs(scriptPrincipal))))
|
||||
{
|
||||
if (JS_GetFunctionObject(fun) != obj)
|
||||
{
|
||||
// Function is a clone, its prototype was precompiled from
|
||||
// brutally shared chrome. For this case only, get the
|
||||
// principals from the clone's scope since there's no
|
||||
// reliable principals compiled into the function.
|
||||
return doGetObjectPrincipal(cx, obj, result);
|
||||
}
|
||||
|
||||
if (NS_FAILED(GetScriptPrincipal(cx, script,
|
||||
getter_AddRefs(scriptPrincipal))))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (script && (JS_GetFunctionObject(fun) != obj) &&
|
||||
(scriptPrincipal.get() == mSystemPrincipal))
|
||||
{
|
||||
// Function is brutally-shared chrome. For this case only,
|
||||
// get a principal from the object's scope instead of the
|
||||
// principal compiled into the function.
|
||||
return doGetObjectPrincipal(cx, obj, result);
|
||||
}
|
||||
|
||||
*result = scriptPrincipal.get();
|
||||
|
@ -1840,7 +1856,20 @@ nsScriptSecurityManager::GetFramePrincipal(JSContext *cx,
|
|||
JSScript *script = JS_GetFrameScript(cx, fp);
|
||||
return GetScriptPrincipal(cx, script, result);
|
||||
}
|
||||
return GetFunctionObjectPrincipal(cx, obj, result);
|
||||
|
||||
nsresult rv = GetFunctionObjectPrincipal(cx, obj, result);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (NS_SUCCEEDED(rv) && !*result)
|
||||
{
|
||||
JSFunction *fun = (JSFunction *)JS_GetPrivate(cx, obj);
|
||||
JSScript *script = JS_GetFunctionScript(cx, fun);
|
||||
|
||||
NS_ASSERTION(!script, "Null principal for non-native function!");
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -120,6 +120,7 @@ static PRBool sDidShutdown = PR_FALSE;
|
|||
|
||||
static PRInt32 sContextCount = 0;
|
||||
|
||||
static nsIScriptSecurityManager *sSecurityManager = nsnull;
|
||||
|
||||
void JS_DLL_CALLBACK
|
||||
NS_ScriptErrorReporter(JSContext *cx,
|
||||
|
@ -436,8 +437,6 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime) : mGCOnDestruction(PR_TRUE)
|
|||
|
||||
nsJSContext::~nsJSContext()
|
||||
{
|
||||
mSecurityManager = nsnull; // Force release
|
||||
|
||||
// Cope with JS_NewContext failure in ctor (XXXbe move NewContext to Init?)
|
||||
if (!mContext)
|
||||
return;
|
||||
|
@ -469,9 +468,12 @@ nsJSContext::~nsJSContext()
|
|||
|
||||
if (!sContextCount && sDidShutdown) {
|
||||
// The last context is being deleted, and we're already in the
|
||||
// process of shutting down, release the JS runtime service.
|
||||
// process of shutting down, release the JS runtime service, and
|
||||
// the security manager.
|
||||
|
||||
NS_IF_RELEASE(sRuntimeService);
|
||||
|
||||
NS_IF_RELEASE(sSecurityManager);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -930,25 +932,35 @@ nsJSContext::CompileEventHandler(void *aTarget, nsIAtom *aName,
|
|||
const nsAString& aBody,
|
||||
PRBool aShared, void** aHandler)
|
||||
{
|
||||
if (!sSecurityManager) {
|
||||
NS_ERROR("Huh, we need a script security manager to compile "
|
||||
"an event handler!");
|
||||
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
JSObject *target = (JSObject*)aTarget;
|
||||
|
||||
JSPrincipals *jsprin = nsnull;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
GetGlobalObject(getter_AddRefs(global));
|
||||
if (global) {
|
||||
// XXXbe why the two-step QI? speed up via a new GetGlobalObjectData func?
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> globalData = do_QueryInterface(global);
|
||||
if (globalData) {
|
||||
nsCOMPtr<nsIPrincipal> prin;
|
||||
if (NS_FAILED(globalData->GetPrincipal(getter_AddRefs(prin))))
|
||||
return NS_ERROR_FAILURE;
|
||||
prin->GetJSPrincipals(&jsprin);
|
||||
}
|
||||
if (target) {
|
||||
// Get the principal of the event target (the object principal),
|
||||
// don't get the principal of the global object in this context
|
||||
// since that opens up security exploits with delayed event
|
||||
// handler compilation on stale DOM objects (objects that live in
|
||||
// a document that has already been unloaded).
|
||||
nsCOMPtr<nsIPrincipal> prin;
|
||||
nsresult rv = sSecurityManager->GetObjectPrincipal(mContext, target,
|
||||
getter_AddRefs(prin));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
prin->GetJSPrincipals(&jsprin);
|
||||
NS_ENSURE_TRUE(jsprin, NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
char charName[64];
|
||||
AtomToEventHandlerName(aName, charName, sizeof charName);
|
||||
|
||||
JSObject *target = (JSObject*)aTarget;
|
||||
JSFunction* fun =
|
||||
::JS_CompileUCFunctionForPrincipals(mContext, target, jsprin,
|
||||
charName, 1, gEventArgv,
|
||||
|
@ -957,10 +969,12 @@ nsJSContext::CompileEventHandler(void *aTarget, nsIAtom *aName,
|
|||
//XXXbe filename, lineno:
|
||||
nsnull, 0);
|
||||
|
||||
if (jsprin)
|
||||
if (jsprin) {
|
||||
JSPRINCIPALS_DROP(mContext, jsprin);
|
||||
if (!fun)
|
||||
}
|
||||
if (!fun) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JSObject *handler = ::JS_GetFunctionObject(fun);
|
||||
if (aHandler)
|
||||
|
@ -1522,14 +1536,12 @@ nsJSContext::ScriptEvaluated(PRBool aTerminated)
|
|||
NS_IMETHODIMP
|
||||
nsJSContext::GetSecurityManager(nsIScriptSecurityManager **aInstancePtr)
|
||||
{
|
||||
if (!mSecurityManager) {
|
||||
nsresult rv = NS_OK;
|
||||
*aInstancePtr = sSecurityManager;
|
||||
|
||||
mSecurityManager = do_GetService(kScriptSecurityManagerContractID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!sSecurityManager) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
*aInstancePtr = mSecurityManager;
|
||||
NS_ADDREF(*aInstancePtr);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1679,9 +1691,7 @@ nsresult nsJSEnvironment::Init()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = nsServiceManager::GetService(kJSRuntimeServiceContractID,
|
||||
NS_GET_IID(nsIJSRuntimeService),
|
||||
(nsISupports**)&sRuntimeService);
|
||||
nsresult rv = CallGetService(kJSRuntimeServiceContractID, &sRuntimeService);
|
||||
// get the JSRuntime from the runtime svc, if possible
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -1732,6 +1742,8 @@ nsresult nsJSEnvironment::Init()
|
|||
}
|
||||
#endif /* OJI */
|
||||
|
||||
rv = CallGetService(kScriptSecurityManagerContractID, &sSecurityManager);
|
||||
|
||||
isInitialized = NS_SUCCEEDED(rv);
|
||||
|
||||
return rv;
|
||||
|
@ -1754,9 +1766,10 @@ void nsJSEnvironment::ShutDown()
|
|||
|
||||
if (!sContextCount) {
|
||||
// We're being shutdown, and there are no more contexts
|
||||
// alive, release the JS runtime service.
|
||||
// alive, release the JS runtime service and the security manager.
|
||||
|
||||
NS_IF_RELEASE(sRuntimeService);
|
||||
NS_IF_RELEASE(sSecurityManager);
|
||||
}
|
||||
|
||||
sDidShutdown = PR_TRUE;
|
||||
|
|
|
@ -144,7 +144,6 @@ private:
|
|||
JSContext *mContext;
|
||||
PRUint32 mNumEvaluations;
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> mSecurityManager; // [OWNER]
|
||||
nsIScriptContextOwner* mOwner; /* NB: weak reference, not ADDREF'd */
|
||||
nsScriptTerminationFunc mTerminationFunc;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче