зеркало из https://github.com/mozilla/gecko-dev.git
Bug 304048 - "xpconnect getters/setters don't have principals until after they pass or fail their security check." Patch by jst, sr=bzbarsky, a=jst.
This commit is contained in:
Родитель
7a36d83fa1
Коммит
5f9effcd34
|
@ -493,6 +493,12 @@ nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSObject *obj,
|
||||||
if (!ssm)
|
if (!ssm)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
|
nsCOMPtr<nsISupports> native;
|
||||||
|
nsresult rv =
|
||||||
|
sXPConnect->GetNativeOfJSObject(cx, obj,
|
||||||
|
NS_GET_IID(nsISupports),
|
||||||
|
getter_AddRefs(native));
|
||||||
|
|
||||||
// Get the object being accessed. We protect these cases:
|
// Get the object being accessed. We protect these cases:
|
||||||
// 1. The Function.prototype.caller property's value, which might lead
|
// 1. The Function.prototype.caller property's value, which might lead
|
||||||
// an attacker up a call-stack to a function or another object from
|
// an attacker up a call-stack to a function or another object from
|
||||||
|
@ -505,11 +511,13 @@ nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSObject *obj,
|
||||||
|
|
||||||
// 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 parent object's class name, as we have no class-info for it.
|
// Pass the parent object's class name, as we have no class-info for it.
|
||||||
nsresult rv =
|
rv = ssm->CheckPropertyAccessImpl(( (mode & JSACC_WRITE) ?
|
||||||
ssm->CheckPropertyAccess(cx, target, JS_GetClass(cx, obj)->name, id,
|
|
||||||
(mode & JSACC_WRITE) ?
|
|
||||||
nsIXPCSecurityManager::ACCESS_SET_PROPERTY :
|
nsIXPCSecurityManager::ACCESS_SET_PROPERTY :
|
||||||
nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
|
nsIXPCSecurityManager::ACCESS_GET_PROPERTY ),
|
||||||
|
nsnull, cx, target, native, nsnull,
|
||||||
|
nsnull, JS_GET_CLASS(cx, obj)->name, id,
|
||||||
|
nsnull);
|
||||||
|
|
||||||
|
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return JS_FALSE; // Security check failed (XXX was an error reported?)
|
return JS_FALSE; // Security check failed (XXX was an error reported?)
|
||||||
|
@ -771,14 +779,24 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
|
||||||
nsXPIDLCString objectSecurityLevel;
|
nsXPIDLCString objectSecurityLevel;
|
||||||
if (checkedComponent)
|
if (checkedComponent)
|
||||||
{
|
{
|
||||||
|
const nsIID* objIID = nsnull;
|
||||||
|
if (aCallContext) {
|
||||||
|
// If we have a call context, find the wrapper and the IID
|
||||||
|
// with the member in question to pass to
|
||||||
|
// nsISecurityCheckedComponent, if not, pass a null IID
|
||||||
|
// and it's up to the implementation to decide whether or
|
||||||
|
// not it wants to permit access.
|
||||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
||||||
nsCOMPtr<nsIInterfaceInfo> interfaceInfo;
|
nsCOMPtr<nsIInterfaceInfo> interfaceInfo;
|
||||||
const nsIID* objIID;
|
|
||||||
rv = aCallContext->GetCalleeWrapper(getter_AddRefs(wrapper));
|
rv = aCallContext->GetCalleeWrapper(getter_AddRefs(wrapper));
|
||||||
if (NS_SUCCEEDED(rv))
|
if (NS_SUCCEEDED(rv))
|
||||||
rv = wrapper->FindInterfaceWithMember(aProperty, getter_AddRefs(interfaceInfo));
|
rv = wrapper->FindInterfaceWithMember(aProperty, getter_AddRefs(interfaceInfo));
|
||||||
if (NS_SUCCEEDED(rv))
|
if (NS_SUCCEEDED(rv))
|
||||||
rv = interfaceInfo->GetIIDShared(&objIID);
|
rv = interfaceInfo->GetIIDShared(&objIID);
|
||||||
|
} else {
|
||||||
|
rv = NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv))
|
if (NS_SUCCEEDED(rv))
|
||||||
{
|
{
|
||||||
switch (aAction)
|
switch (aAction)
|
||||||
|
|
|
@ -674,6 +674,17 @@ interface nsIXPConnect : nsISupports
|
||||||
*/
|
*/
|
||||||
void flagSystemFilenamePrefix(in string aFilenamePrefix);
|
void flagSystemFilenamePrefix(in string aFilenamePrefix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a native pointer of type aIID from aJSObject if the object
|
||||||
|
* is a wrapped native or a wrapped JS object, but never create a
|
||||||
|
* new wrapper, only use existing ones.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
getNativeOfJSObject(in JSContextPtr aJSContext,
|
||||||
|
in JSObjectPtr aJSObj,
|
||||||
|
in nsIIDRef aIID,
|
||||||
|
[iid_is(aIID),retval] out nsQIResult result);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore an old prototype for wrapped natives of type
|
* Restore an old prototype for wrapped natives of type
|
||||||
* aClassInfo. This should be used only when restoring an old
|
* aClassInfo. This should be used only when restoring an old
|
||||||
|
|
|
@ -331,6 +331,7 @@ JSBool XPCDispConvert::JSToCOM(XPCCallContext& ccx,
|
||||||
obj,
|
obj,
|
||||||
&NSID_IDISPATCH,
|
&NSID_IDISPATCH,
|
||||||
nsnull,
|
nsnull,
|
||||||
|
PR_TRUE,
|
||||||
&err))
|
&err))
|
||||||
{
|
{
|
||||||
// Avoid cleaning up garbage
|
// Avoid cleaning up garbage
|
||||||
|
|
|
@ -1112,7 +1112,7 @@ nsXPConnect::WrapJS(JSContext * aJSContext,
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
if(!XPCConvert::JSObject2NativeInterface(ccx, result, aJSObj,
|
if(!XPCConvert::JSObject2NativeInterface(ccx, result, aJSObj,
|
||||||
&aIID, nsnull, &rv))
|
&aIID, nsnull, PR_TRUE, &rv))
|
||||||
return rv;
|
return rv;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -1138,7 +1138,7 @@ nsXPConnect::WrapJSAggregatedToNative(nsISupports *aOuter,
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
if(!XPCConvert::JSObject2NativeInterface(ccx, result, aJSObj,
|
if(!XPCConvert::JSObject2NativeInterface(ccx, result, aJSObj,
|
||||||
&aIID, aOuter, &rv))
|
&aIID, aOuter, PR_TRUE, &rv))
|
||||||
return rv;
|
return rv;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -2097,6 +2097,30 @@ nsXPConnect::OnDispatchedEvent(nsIThreadInternal* aThread)
|
||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* void getNativeOfJSObject(in JSContextPtr aJSContext, in JSObjectPtr aJSObj, in nsIIDRef aIID, [iid_is(aIID),retval] out nsQIResult result); */
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXPConnect::GetNativeOfJSObject(JSContext * aJSContext,
|
||||||
|
JSObject * aJSObj,
|
||||||
|
const nsIID & aIID,
|
||||||
|
void * *result)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aJSContext, "bad param");
|
||||||
|
NS_ASSERTION(aJSObj, "bad param");
|
||||||
|
NS_ASSERTION(result, "bad param");
|
||||||
|
|
||||||
|
*result = nsnull;
|
||||||
|
|
||||||
|
XPCCallContext ccx(NATIVE_CALLER, aJSContext);
|
||||||
|
if(!ccx.IsValid())
|
||||||
|
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
if(!XPCConvert::JSObject2NativeInterface(ccx, result, aJSObj,
|
||||||
|
&aIID, nsnull, PR_FALSE, &rv))
|
||||||
|
return rv;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/* These are here to be callable from a debugger */
|
/* These are here to be callable from a debugger */
|
||||||
JS_BEGIN_EXTERN_C
|
JS_BEGIN_EXTERN_C
|
||||||
|
|
|
@ -1030,7 +1030,7 @@ XPCConvert::JSData2Native(XPCCallContext& ccx, void* d, jsval s,
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSObject2NativeInterface(ccx, (void**)d, obj, iid,
|
return JSObject2NativeInterface(ccx, (void**)d, obj, iid,
|
||||||
nsnull, pErr);
|
nsnull, PR_TRUE, pErr);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
NS_ASSERTION(0, "bad type");
|
NS_ASSERTION(0, "bad type");
|
||||||
|
@ -1230,6 +1230,7 @@ XPCConvert::JSObject2NativeInterface(XPCCallContext& ccx,
|
||||||
void** dest, JSObject* src,
|
void** dest, JSObject* src,
|
||||||
const nsID* iid,
|
const nsID* iid,
|
||||||
nsISupports* aOuter,
|
nsISupports* aOuter,
|
||||||
|
PRBool allowCreateNew,
|
||||||
nsresult* pErr)
|
nsresult* pErr)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(dest, "bad param");
|
NS_ASSERTION(dest, "bad param");
|
||||||
|
@ -1288,8 +1289,15 @@ XPCConvert::JSObject2NativeInterface(XPCCallContext& ccx,
|
||||||
|
|
||||||
// else...
|
// else...
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
nsXPCWrappedJS* wrapper;
|
nsXPCWrappedJS* wrapper;
|
||||||
nsresult rv = nsXPCWrappedJS::GetNewOrUsed(ccx, src, *iid, aOuter, &wrapper);
|
if (allowCreateNew) {
|
||||||
|
rv = nsXPCWrappedJS::GetNewOrUsed(ccx, src, *iid, aOuter, &wrapper);
|
||||||
|
} else {
|
||||||
|
rv = nsXPCWrappedJS::GetUsedOnly(ccx, src, *iid, aOuter, &wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
if(pErr)
|
if(pErr)
|
||||||
*pErr = rv;
|
*pErr = rv;
|
||||||
if(NS_SUCCEEDED(rv) && wrapper)
|
if(NS_SUCCEEDED(rv) && wrapper)
|
||||||
|
|
|
@ -2356,6 +2356,12 @@ public:
|
||||||
REFNSIID aIID,
|
REFNSIID aIID,
|
||||||
nsISupports* aOuter,
|
nsISupports* aOuter,
|
||||||
nsXPCWrappedJS** wrapper);
|
nsXPCWrappedJS** wrapper);
|
||||||
|
static nsresult
|
||||||
|
GetUsedOnly(XPCCallContext& ccx,
|
||||||
|
JSObject* aJSObj,
|
||||||
|
REFNSIID aIID,
|
||||||
|
nsISupports* aOuter,
|
||||||
|
nsXPCWrappedJS** wrapperResult);
|
||||||
|
|
||||||
nsISomeInterface* GetXPTCStub() { return mXPTCStub; }
|
nsISomeInterface* GetXPTCStub() { return mXPTCStub; }
|
||||||
JSObject* GetJSObject() const {return mJSObj;}
|
JSObject* GetJSObject() const {return mJSObj;}
|
||||||
|
@ -2531,6 +2537,7 @@ public:
|
||||||
void** dest, JSObject* src,
|
void** dest, JSObject* src,
|
||||||
const nsID* iid,
|
const nsID* iid,
|
||||||
nsISupports* aOuter,
|
nsISupports* aOuter,
|
||||||
|
PRBool allowCreateNew,
|
||||||
nsresult* pErr);
|
nsresult* pErr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -417,6 +417,68 @@ return_wrapper:
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
nsresult
|
||||||
|
nsXPCWrappedJS::GetUsedOnly(XPCCallContext& ccx,
|
||||||
|
JSObject* aJSObj,
|
||||||
|
REFNSIID aIID,
|
||||||
|
nsISupports* aOuter,
|
||||||
|
nsXPCWrappedJS** wrapperResult)
|
||||||
|
{
|
||||||
|
JSObject2WrappedJSMap* map;
|
||||||
|
JSBool hasProp;
|
||||||
|
JSObject* rootJSObj;
|
||||||
|
nsXPCWrappedJS* root;
|
||||||
|
nsXPCWrappedJS* wrapper = nsnull;
|
||||||
|
nsXPCWrappedJSClass *clazz = nsnull;
|
||||||
|
XPCJSRuntime* rt = ccx.GetRuntime();
|
||||||
|
|
||||||
|
map = rt->GetWrappedJSMap();
|
||||||
|
if(!map)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(map,"bad map");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXPCWrappedJSClass::GetNewOrUsed(ccx, aIID, &clazz);
|
||||||
|
if(!clazz)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
// GetRootJSObject will attempt to call a QueryInterface function on
|
||||||
|
// aJSObj. If QueryInterface doesn't exist on the object then a strict
|
||||||
|
// warning will be emitted, so check to make sure that the QueryInterface
|
||||||
|
// function exists before proceeding.
|
||||||
|
if(JS_HasProperty(ccx.GetJSContext(), aJSObj,
|
||||||
|
rt->GetStringName(XPCJSRuntime::IDX_QUERY_INTERFACE),
|
||||||
|
&hasProp) && hasProp)
|
||||||
|
rootJSObj = clazz->GetRootJSObject(ccx, aJSObj);
|
||||||
|
else
|
||||||
|
rootJSObj = aJSObj;
|
||||||
|
|
||||||
|
NS_RELEASE(clazz);
|
||||||
|
|
||||||
|
if(!rootJSObj)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
// look for the root wrapper
|
||||||
|
{ // scoped lock
|
||||||
|
XPCAutoLock lock(rt->GetMapLock());
|
||||||
|
root = map->Find(rootJSObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(root)
|
||||||
|
{
|
||||||
|
if((nsnull != (wrapper = root->Find(aIID))) ||
|
||||||
|
(nsnull != (wrapper = root->FindInherited(aIID))))
|
||||||
|
{
|
||||||
|
NS_ADDREF(wrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*wrapperResult = wrapper;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsXPCWrappedJS::nsXPCWrappedJS(XPCCallContext& ccx,
|
nsXPCWrappedJS::nsXPCWrappedJS(XPCCallContext& ccx,
|
||||||
JSObject* aJSObj,
|
JSObject* aJSObj,
|
||||||
nsXPCWrappedJSClass* aClass,
|
nsXPCWrappedJSClass* aClass,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче