Bug 871262 - Fix rooting hazards in the CAPS code; r=till

This commit is contained in:
Ehsan Akhgari 2013-05-12 15:52:21 -04:00
parent c2468980c6
commit b4be6ea2b3
2 changed files with 49 additions and 40 deletions

View File

@ -409,7 +409,8 @@ private:
uint32_t aAction);
nsresult
LookupPolicy(nsIPrincipal* principal,
LookupPolicy(JSContext* cx,
nsIPrincipal* principal,
ClassInfoData& aClassData, jsid aProperty,
uint32_t aAction,
ClassPolicy** aCachedClassPolicy,

View File

@ -91,8 +91,9 @@ nsScriptSecurityManager::SubjectIsPrivileged()
///////////////////////////
// Result of this function should not be freed.
static inline const PRUnichar *
IDToString(JSContext *cx, jsid id)
IDToString(JSContext *cx, jsid id_)
{
JS::RootedId id(cx, id_);
if (JSID_IS_STRING(id))
return JS_GetInternedStringChars(JSID_TO_STRING(id));
@ -610,6 +611,8 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(uint32_t aAction,
void** aCachedClassPolicy)
{
nsresult rv;
JS::RootedObject jsObject(cx, aJSObject);
JS::RootedId property(cx, aProperty);
nsIPrincipal* subjectPrincipal = GetSubjectPrincipal(cx, &rv);
if (NS_FAILED(rv))
return rv;
@ -626,13 +629,13 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(uint32_t aAction,
//-- Look up the security policy for this class and subject domain
SecurityLevel securityLevel;
rv = LookupPolicy(subjectPrincipal, classInfoData, aProperty, aAction,
rv = LookupPolicy(cx, subjectPrincipal, classInfoData, property, aAction,
(ClassPolicy**)aCachedClassPolicy, &securityLevel);
if (NS_FAILED(rv))
return rv;
if (securityLevel.level == SCRIPT_SECURITY_UNDEFINED_ACCESS)
{
{
// No policy found for this property so use the default of last resort.
// If we were called from somewhere other than XPConnect
// (no XPC call context), assume this is a DOM class. Otherwise,
@ -659,9 +662,9 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(uint32_t aAction,
case SCRIPT_SECURITY_SAME_ORIGIN_ACCESS:
{
nsCOMPtr<nsIPrincipal> principalHolder;
if(aJSObject)
if (jsObject)
{
objectPrincipal = doGetObjectPrincipal(aJSObject);
objectPrincipal = doGetObjectPrincipal(jsObject);
if (!objectPrincipal)
rv = NS_ERROR_DOM_SECURITY_ERR;
}
@ -703,7 +706,7 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(uint32_t aAction,
const nsIID* objIID = nullptr;
rv = aCallContext->GetCalleeWrapper(getter_AddRefs(wrapper));
if (NS_SUCCEEDED(rv) && wrapper)
rv = wrapper->FindInterfaceWithMember(aProperty, getter_AddRefs(interfaceInfo));
rv = wrapper->FindInterfaceWithMember(property, getter_AddRefs(interfaceInfo));
if (NS_SUCCEEDED(rv) && interfaceInfo)
rv = interfaceInfo->GetIIDShared(&objIID);
if (NS_SUCCEEDED(rv) && objIID)
@ -712,22 +715,22 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(uint32_t aAction,
{
case nsIXPCSecurityManager::ACCESS_GET_PROPERTY:
checkedComponent->CanGetProperty(objIID,
IDToString(cx, aProperty),
IDToString(cx, property),
getter_Copies(objectSecurityLevel));
break;
case nsIXPCSecurityManager::ACCESS_SET_PROPERTY:
checkedComponent->CanSetProperty(objIID,
IDToString(cx, aProperty),
IDToString(cx, property),
getter_Copies(objectSecurityLevel));
break;
case nsIXPCSecurityManager::ACCESS_CALL_METHOD:
checkedComponent->CanCallMethod(objIID,
IDToString(cx, aProperty),
IDToString(cx, property),
getter_Copies(objectSecurityLevel));
}
}
}
rv = CheckXPCPermissions(cx, aObj, aJSObject, subjectPrincipal,
rv = CheckXPCPermissions(cx, aObj, jsObject, subjectPrincipal,
objectSecurityLevel);
if (NS_FAILED(rv)) //-- Security tests failed, access is denied, report error
@ -791,7 +794,7 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(uint32_t aAction,
{
subjectOriginUnicode.get(),
className.get(),
IDToString(cx, aProperty),
IDToString(cx, property),
objectOriginUnicode.get(),
subjectDomainUnicode.get(),
objectDomainUnicode.get()
@ -969,7 +972,8 @@ nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal* aSubject,
}
nsresult
nsScriptSecurityManager::LookupPolicy(nsIPrincipal* aPrincipal,
nsScriptSecurityManager::LookupPolicy(JSContext* cx,
nsIPrincipal* aPrincipal,
ClassInfoData& aClassData,
jsid aProperty,
uint32_t aAction,
@ -977,6 +981,7 @@ nsScriptSecurityManager::LookupPolicy(nsIPrincipal* aPrincipal,
SecurityLevel* result)
{
nsresult rv;
JS::RootedId property(cx, aProperty);
result->level = SCRIPT_SECURITY_UNDEFINED_ACCESS;
DomainPolicy* dpolicy = nullptr;
@ -1083,14 +1088,14 @@ nsScriptSecurityManager::LookupPolicy(nsIPrincipal* aPrincipal,
*aCachedClassPolicy = cpolicy;
}
NS_ASSERTION(JSID_IS_INT(aProperty) || JSID_IS_OBJECT(aProperty) ||
JSID_IS_STRING(aProperty), "Property must be a valid id");
NS_ASSERTION(JSID_IS_INT(property) || JSID_IS_OBJECT(property) ||
JSID_IS_STRING(property), "Property must be a valid id");
// Only atomized strings are stored in the policies' hash tables.
if (!JSID_IS_STRING(aProperty))
if (!JSID_IS_STRING(property))
return NS_OK;
JSString *propertyKey = JSID_TO_STRING(aProperty);
JS::RootedString propertyKey(cx, JSID_TO_STRING(property));
// We look for a PropertyPolicy in the following places:
// 1) The ClassPolicy for our class we got from our DomainPolicy
@ -1443,8 +1448,9 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
ClassInfoData nameData(nullptr, loadURIPrefGroup);
SecurityLevel secLevel;
rv = LookupPolicy(aPrincipal, nameData, sEnabledID,
nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
rv = LookupPolicy(GetCurrentJSContext(),
aPrincipal, nameData, sEnabledID,
nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
nullptr, &secLevel);
if (NS_SUCCEEDED(rv) && secLevel.level == SCRIPT_SECURITY_ALL_ACCESS)
{
@ -1748,8 +1754,8 @@ nsScriptSecurityManager::CanExecuteScripts(JSContext* cx,
ClassInfoData nameData(nullptr, jsPrefGroupName);
SecurityLevel secLevel;
rv = LookupPolicy(aPrincipal, nameData, sEnabledID,
nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
rv = LookupPolicy(cx, aPrincipal, nameData, sEnabledID,
nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
nullptr, &secLevel);
if (NS_FAILED(rv) || secLevel.level == SCRIPT_SECURITY_NO_ACCESS)
{
@ -2052,31 +2058,32 @@ nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
NS_ASSERTION(aObj, "Bad call to doGetObjectPrincipal()!");
nsIPrincipal* result = nullptr;
JSObject* origObj = aObj;
js::Class *jsClass = js::GetObjectClass(aObj);
JS::RootedObject obj(sXPConnect->GetCurrentJSContext(), aObj);
JSObject* origObj = obj;
js::Class *jsClass = js::GetObjectClass(obj);
// A common case seen in this code is that we enter this function
// with aObj being a Function object, whose parent is a Call
// with obj being a Function object, whose parent is a Call
// object. Neither of those have object principals, so we can skip
// those objects here before we enter the below loop. That way we
// avoid wasting time checking properties of their classes etc in
// the loop.
if (jsClass == &js::FunctionClass) {
aObj = js::GetObjectParent(aObj);
obj = js::GetObjectParent(obj);
if (!aObj)
if (!obj)
return nullptr;
jsClass = js::GetObjectClass(aObj);
jsClass = js::GetObjectClass(obj);
if (jsClass == &js::CallClass) {
aObj = js::GetObjectParentMaybeScope(aObj);
obj = js::GetObjectParentMaybeScope(obj);
if (!aObj)
if (!obj)
return nullptr;
jsClass = js::GetObjectClass(aObj);
jsClass = js::GetObjectClass(obj);
}
}
@ -2085,7 +2092,7 @@ nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
// *end* of this loop.
if (IS_WRAPPER_CLASS(jsClass)) {
result = sXPConnect->GetPrincipal(aObj,
result = sXPConnect->GetPrincipal(obj,
aAllowShortCircuit);
if (result) {
break;
@ -2094,8 +2101,8 @@ nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
nsISupports *priv;
if (!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
priv = (nsISupports *) js::GetObjectPrivate(aObj);
} else if (!UnwrapDOMObjectToISupports(aObj, priv)) {
priv = (nsISupports *) js::GetObjectPrivate(obj);
} else if (!UnwrapDOMObjectToISupports(obj, priv)) {
priv = nullptr;
}
@ -2121,12 +2128,12 @@ nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
}
}
aObj = js::GetObjectParentMaybeScope(aObj);
obj = js::GetObjectParentMaybeScope(obj);
if (!aObj)
if (!obj)
break;
jsClass = js::GetObjectClass(aObj);
jsClass = js::GetObjectClass(obj);
} while (1);
if (aAllowShortCircuit) {
@ -2266,6 +2273,7 @@ nsScriptSecurityManager::CheckXPCPermissions(JSContext* cx,
nsIPrincipal* aSubjectPrincipal,
const char* aObjectSecurityLevel)
{
JS::RootedObject jsObject(cx, aJSObject);
// Check if the subject is privileged.
if (SubjectIsPrivileged())
return NS_OK;
@ -2278,13 +2286,13 @@ nsScriptSecurityManager::CheckXPCPermissions(JSContext* cx,
if (cx && PL_strcasecmp(aObjectSecurityLevel, "sameOrigin") == 0)
{
nsresult rv;
if (!aJSObject)
if (!jsObject)
{
nsCOMPtr<nsIXPConnectWrappedJS> xpcwrappedjs =
do_QueryInterface(aObj);
if (xpcwrappedjs)
{
rv = xpcwrappedjs->GetJSObject(&aJSObject);
rv = xpcwrappedjs->GetJSObject(jsObject.address());
NS_ENSURE_SUCCESS(rv, rv);
}
}
@ -2295,9 +2303,9 @@ nsScriptSecurityManager::CheckXPCPermissions(JSContext* cx,
aSubjectPrincipal = GetSubjectPrincipal(cx, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
if (aSubjectPrincipal && aJSObject)
if (aSubjectPrincipal && jsObject)
{
nsIPrincipal* objectPrincipal = doGetObjectPrincipal(aJSObject);
nsIPrincipal* objectPrincipal = doGetObjectPrincipal(jsObject);
// Only do anything if we have both a subject and object
// principal.