From 3c0c23b8603f460ea52c6c0673af8fc59657b419 Mon Sep 17 00:00:00 2001 From: "brendan%mozilla.org" Date: Thu, 6 Mar 2003 19:40:14 +0000 Subject: [PATCH] Generalize the JS_SetCheckObjectAccessCallback hook implemented here to deal with user-defined getters and setters (92773, r=mstoltz, sr=jst). --- caps/include/nsScriptSecurityManager.h | 7 ++-- caps/src/nsScriptSecurityManager.cpp | 47 +++++++++++++------------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/caps/include/nsScriptSecurityManager.h b/caps/include/nsScriptSecurityManager.h index 03a76182b807..1c7237124a64 100644 --- a/caps/include/nsScriptSecurityManager.h +++ b/caps/include/nsScriptSecurityManager.h @@ -294,9 +294,9 @@ private: virtual ~nsScriptSecurityManager(); static JSBool JS_DLL_CALLBACK - CheckJSFunctionCallerAccess(JSContext *cx, JSObject *obj, - jsval id, JSAccessMode mode, - jsval *vp); + CheckObjectAccess(JSContext *cx, JSObject *obj, + jsval id, JSAccessMode mode, + jsval *vp); static nsresult doGetObjectPrincipal(JSContext *cx, JSObject *obj, nsIPrincipal **result); @@ -396,7 +396,6 @@ private: #endif // JS strings we need to clean up on shutdown - static jsval sCallerID; static jsval sEnabledID; inline void diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index 5f22cc981e3b..dfb14c85f9b5 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -431,38 +431,39 @@ NS_IMPL_ISUPPORTS3(nsScriptSecurityManager, ///////////////// Security Checks ///////////////// JSBool JS_DLL_CALLBACK -nsScriptSecurityManager::CheckJSFunctionCallerAccess(JSContext *cx, JSObject *obj, - jsval id, JSAccessMode mode, - jsval *vp) +nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSObject *obj, + jsval id, JSAccessMode mode, + jsval *vp) { - // Currently, this function will be called only when function.caller - // is accessed. If that changes, we will need to change this function. - NS_ASSERTION(nsCRT::strcmp(NS_REINTERPRET_CAST(PRUnichar*, - JS_GetStringChars(JSVAL_TO_STRING(id))), - NS_LITERAL_STRING("caller").get()) == 0, - "CheckJSFunctionCallerAccess called for a property other than \'caller\'"); // Get the security manager - nsScriptSecurityManager *ssm = nsScriptSecurityManager::GetScriptSecurityManager(); + NS_ASSERTION(ssm, "Failed to get security manager service"); if (!ssm) - { - NS_ERROR("Failed to get security manager service"); return JS_FALSE; - } - // Get the caller function object - NS_ASSERTION(JSVAL_IS_OBJECT(*vp), "*vp is not an object"); - JSObject* target = JSVAL_TO_OBJECT(*vp); + // Get the object being accessed. We protect these cases: + // 1. The Function.prototype.caller property's value, which might lead + // an attacker up a call-stack to a function or another object from + // a different trust domain. + // 2. A user-defined getter or setter function accessible on another + // trust domain's window or document object. + // If *vp is not a primitive, some new JS engine call to this hook was + // added, but we can handle that case too -- if a primitive value in a + // property of obj is being accessed, we should use obj as the target + // object. + NS_ASSERTION(!JSVAL_IS_PRIMITIVE(*vp), "unexpected target property value"); + JSObject* target = JSVAL_IS_PRIMITIVE(*vp) ? obj : JSVAL_TO_OBJECT(*vp); - // Do the same-origin check - this sets a JS exception if the check fails + // Do the same-origin check -- this sets a JS exception if the check fails. + // Pass the target object's class name, as we have no class-info for it. nsresult rv = - ssm->CheckPropertyAccess(cx, target, "Function", sCallerID, + ssm->CheckPropertyAccess(cx, target, JS_GetClass(cx, target)->name, id, nsIXPCSecurityManager::ACCESS_GET_PROPERTY); if (NS_FAILED(rv)) - return JS_FALSE; // Security check failed + return JS_FALSE; // Security check failed (XXX was an error reported?) return JS_TRUE; } @@ -2538,10 +2539,10 @@ nsresult nsScriptSecurityManager::Init() JSContext* cx = GetSafeJSContext(); if (!cx) return NS_ERROR_FAILURE; // this can happen of xpt loading fails - if (sCallerID == JSVAL_VOID) - sCallerID = STRING_TO_JSVAL(::JS_InternString(cx, "caller")); + ::JS_BeginRequest(cx); if (sEnabledID == JSVAL_VOID) sEnabledID = STRING_TO_JSVAL(::JS_InternString(cx, "enabled")); + ::JS_EndRequest(cx); nsresult rv = InitPrefs(); NS_ENSURE_SUCCESS(rv, rv); @@ -2559,7 +2560,7 @@ nsresult nsScriptSecurityManager::Init() #ifdef DEBUG JSCheckAccessOp oldCallback = #endif - JS_SetCheckObjectAccessCallback(rt, CheckJSFunctionCallerAccess); + JS_SetCheckObjectAccessCallback(rt, CheckObjectAccess); // For now, assert that no callback was set previously NS_ASSERTION(!oldCallback, "Someone already set a JS CheckObjectAccess callback"); @@ -2568,7 +2569,6 @@ nsresult nsScriptSecurityManager::Init() static nsScriptSecurityManager *gScriptSecMan = nsnull; -jsval nsScriptSecurityManager::sCallerID = JSVAL_VOID; jsval nsScriptSecurityManager::sEnabledID = JSVAL_VOID; nsScriptSecurityManager::~nsScriptSecurityManager(void) @@ -2584,7 +2584,6 @@ nsScriptSecurityManager::~nsScriptSecurityManager(void) void nsScriptSecurityManager::Shutdown() { - sCallerID = JSVAL_VOID; sEnabledID = JSVAL_VOID; }