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:
jst%netscape.com 2003-04-17 20:21:00 +00:00
Родитель 1bdbf1e104
Коммит 981b45ec02
3 изменённых файлов: 77 добавлений и 36 удалений

Просмотреть файл

@ -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;