Ensure that accesses to implicit XPCNativeWrappers are actually legal. bug 384750, r+sr=jst

This commit is contained in:
mrbkap%gmail.com 2007-07-05 20:01:12 +00:00
Родитель 8e09a05e8f
Коммит 0609e26629
2 изменённых файлов: 71 добавлений и 2 удалений

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

@ -216,6 +216,32 @@ ThrowException(nsresult ex, JSContext *cx)
return JS_FALSE; return JS_FALSE;
} }
static inline
JSBool
EnsureLegalActivity(JSContext *cx, JSObject *obj)
{
jsval flags;
::JS_GetReservedSlot(cx, obj, 0, &flags);
if (HAS_FLAGS(flags, FLAG_EXPLICIT)) {
// Can't make any assertions about the owner of this wrapper.
return JS_TRUE;
}
JSStackFrame *frame = nsnull;
uint32 fileFlags = JS_GetTopScriptFilenameFlags(cx, NULL);
if (!JS_FrameIterator(cx, &frame) ||
fileFlags == JSFILENAME_NULL ||
(fileFlags & JSFILENAME_SYSTEM)) {
// We expect implicit native wrappers in system files.
return JS_TRUE;
}
// Otherwise, we're looking at a non-system file with a handle on an
// implcit wrapper. This is a bug! Deny access.
return ThrowException(NS_ERROR_XPC_SECURITY_MANAGER_VETO, cx);
}
static JSBool static JSBool
WrapFunction(JSContext* cx, JSObject* funobj, jsval *rval) WrapFunction(JSContext* cx, JSObject* funobj, jsval *rval)
{ {
@ -265,12 +291,17 @@ XPC_NW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
// Note: no need to protect *vp from GC here, since it's already in the slot // Note: no need to protect *vp from GC here, since it's already in the slot
// on |obj|. // on |obj|.
return RewrapIfDeepWrapper(cx, obj, *vp, vp); return EnsureLegalActivity(cx, obj) &&
RewrapIfDeepWrapper(cx, obj, *vp, vp);
} }
JS_STATIC_DLL_CALLBACK(JSBool) JS_STATIC_DLL_CALLBACK(JSBool)
XPC_NW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) XPC_NW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{ {
if (!EnsureLegalActivity(cx, obj)) {
return JS_FALSE;
}
XPC_NW_BYPASS_BASE(cx, obj, XPC_NW_BYPASS_BASE(cx, obj,
// We're being notified of a delete operation on id in this // We're being notified of a delete operation on id in this
// XPCNativeWrapper, so forward to the right high-level hook, // XPCNativeWrapper, so forward to the right high-level hook,
@ -414,6 +445,10 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
} }
} }
if (!EnsureLegalActivity(cx, obj)) {
return JS_FALSE;
}
XPCWrappedNative *wrappedNative = XPCWrappedNative *wrappedNative =
XPCNativeWrapper::GetWrappedNative(cx, obj); XPCNativeWrapper::GetWrappedNative(cx, obj);
@ -623,6 +658,10 @@ XPC_NW_Enumerate(JSContext *cx, JSObject *obj)
// JS_Enumerate API. Then reflect properties named by the enumerated // JS_Enumerate API. Then reflect properties named by the enumerated
// identifiers from the wrapped native to the native wrapper. // identifiers from the wrapped native to the native wrapper.
if (!EnsureLegalActivity(cx, obj)) {
return JS_FALSE;
}
XPCWrappedNative *wn = XPCNativeWrapper::GetWrappedNative(cx, obj); XPCWrappedNative *wn = XPCNativeWrapper::GetWrappedNative(cx, obj);
if (!wn) { if (!wn) {
return JS_TRUE; return JS_TRUE;
@ -682,6 +721,10 @@ XPC_NW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
return JS_TRUE; return JS_TRUE;
} }
if (!EnsureLegalActivity(cx, obj)) {
return JS_FALSE;
}
// We can't use XPC_NW_BYPASS here, because we need to do a full // We can't use XPC_NW_BYPASS here, because we need to do a full
// OBJ_LOOKUP_PROPERTY on the wrapped native's object, in order to // OBJ_LOOKUP_PROPERTY on the wrapped native's object, in order to
// trigger reflection along the wrapped native prototype chain. // trigger reflection along the wrapped native prototype chain.
@ -893,8 +936,11 @@ XPC_NW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
JS_STATIC_DLL_CALLBACK(JSBool) JS_STATIC_DLL_CALLBACK(JSBool)
XPC_NW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) XPC_NW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
{ {
XPC_NW_BYPASS(cx, obj, convert, (cx, obj, type, vp)); if (!EnsureLegalActivity(cx, obj)) {
return JS_FALSE;
}
XPC_NW_BYPASS(cx, obj, convert, (cx, obj, type, vp));
return JS_TRUE; return JS_TRUE;
} }
@ -1256,6 +1302,10 @@ XPC_NW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
} }
} }
if (!EnsureLegalActivity(cx, obj)) {
return JS_FALSE;
}
// Check whether toString was overridden in any object along // Check whether toString was overridden in any object along
// the wrapped native's object's prototype chain. // the wrapped native's object's prototype chain.
XPCJSRuntime *rt = nsXPConnect::GetRuntime(); XPCJSRuntime *rt = nsXPConnect::GetRuntime();

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

@ -836,6 +836,23 @@ inline nsresult UnexpectedFailure(nsresult rv)
return rv; return rv;
} }
class SaveFrame
{
public:
SaveFrame(JSContext *cx)
: mJSContext(cx) {
mFrame = JS_SaveFrameChain(mJSContext);
}
~SaveFrame() {
JS_RestoreFrameChain(mJSContext, mFrame);
}
private:
JSContext *mJSContext;
JSStackFrame *mFrame;
};
/* void initClasses (in JSContextPtr aJSContext, in JSObjectPtr aGlobalJSObj); */ /* void initClasses (in JSContextPtr aJSContext, in JSObjectPtr aGlobalJSObj); */
NS_IMETHODIMP NS_IMETHODIMP
nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj) nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj)
@ -843,6 +860,7 @@ nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj)
NS_ASSERTION(aJSContext, "bad param"); NS_ASSERTION(aJSContext, "bad param");
NS_ASSERTION(aGlobalJSObj, "bad param"); NS_ASSERTION(aGlobalJSObj, "bad param");
SaveFrame sf(aJSContext);
XPCCallContext ccx(NATIVE_CALLER, aJSContext); XPCCallContext ccx(NATIVE_CALLER, aJSContext);
if(!ccx.IsValid()) if(!ccx.IsValid())
return UnexpectedFailure(NS_ERROR_FAILURE); return UnexpectedFailure(NS_ERROR_FAILURE);
@ -980,6 +998,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
JS_SetPrototype(aJSContext, protoJSObject, scope->GetPrototypeJSObject()); JS_SetPrototype(aJSContext, protoJSObject, scope->GetPrototypeJSObject());
} }
SaveFrame sf(ccx);
if(!nsXPCComponents::AttachNewComponentsObject(ccx, scope, globalJSObj)) if(!nsXPCComponents::AttachNewComponentsObject(ccx, scope, globalJSObj))
return UnexpectedFailure(NS_ERROR_FAILURE); return UnexpectedFailure(NS_ERROR_FAILURE);