зеркало из https://github.com/mozilla/pjs.git
Fixing bug 351370. Make javascript: URLs evaluate in a sandbox when principals don't match. r=mrbkap@gmail.com, sr=bzbarsky@mit.edu.
This commit is contained in:
Родитель
03427afba9
Коммит
3961fcdb53
|
@ -62,6 +62,8 @@ REQUIRES = xpcom \
|
|||
jsconsole \
|
||||
uconv \
|
||||
docshell \
|
||||
content \
|
||||
pref \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
|
@ -72,6 +74,10 @@ CPPSRCS = nsJSProtocolHandler.cpp
|
|||
|
||||
EXPORTS = $(srcdir)/nsJSProtocolHandler.h
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/../base \
|
||||
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
$(MOZ_COMPONENT_LIBS) \
|
||||
$(MOZ_JS_LIBS) \
|
||||
|
|
|
@ -69,6 +69,9 @@
|
|||
#include "nsIWebNavigation.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsJSUtils.h"
|
||||
|
||||
|
||||
class nsJSThunk : public nsIInputStream
|
||||
|
@ -194,6 +197,8 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel)
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
PRBool useSandbox = PR_TRUE;
|
||||
|
||||
if (owner) {
|
||||
principal = do_QueryInterface(owner, &rv);
|
||||
NS_ASSERTION(principal, "Channel's owner is not a principal");
|
||||
|
@ -215,49 +220,84 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel)
|
|||
if (principal != systemPrincipal) {
|
||||
rv = securityManager->CheckSameOriginPrincipal(principal,
|
||||
objectPrincipal);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsCOMPtr<nsIConsoleService> console =
|
||||
do_GetService("@mozilla.org/consoleservice;1");
|
||||
if (console) {
|
||||
// XXX Localize me!
|
||||
console->LogStringMessage(
|
||||
NS_LITERAL_STRING("Attempt to load a javascript: URL from one host\nin a window displaying content from another host\nwas blocked by the security manager.").get());
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_RETVAL_UNDEFINED;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
useSandbox = PR_FALSE;
|
||||
}
|
||||
} else {
|
||||
useSandbox = PR_FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No owner from channel, use the null principal for lack of anything
|
||||
// better. Note that we do not use the object principal here because
|
||||
// that would give the javascript: URL the principals of whatever page
|
||||
// we might be remotely associated with, which is a good recipe for XSS
|
||||
// issues.
|
||||
principal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||
|
||||
if (NS_FAILED(rv) || !principal) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
nsString result;
|
||||
PRBool isUndefined;
|
||||
|
||||
// Finally, we have everything needed to evaluate the expression.
|
||||
nsString result;
|
||||
PRBool bIsUndefined;
|
||||
|
||||
rv = scriptContext->EvaluateString(NS_ConvertUTF8toUTF16(script),
|
||||
globalJSObject, // obj
|
||||
principal,
|
||||
url.get(), // url
|
||||
1, // line no
|
||||
nsnull,
|
||||
&result,
|
||||
&bIsUndefined);
|
||||
if (useSandbox) {
|
||||
// No owner from channel, or we have a principal
|
||||
// mismatch. Evaluate the javascript URL in a sandbox to
|
||||
// prevent it from accessing data it doesn't have permissions
|
||||
// to access.
|
||||
|
||||
nsIXPConnect *xpc = nsContentUtils::XPConnect();
|
||||
|
||||
JSContext *cx = (JSContext*)scriptContext->GetNativeContext();
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> sandbox;
|
||||
rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(sandbox));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
jsval rval = JSVAL_VOID;
|
||||
nsAutoGCRoot root(&rval, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = xpc->EvalInSandboxObject(NS_ConvertUTF8toUTF16(script), cx,
|
||||
sandbox, &rval);
|
||||
|
||||
// Propagate and report exceptions that happened in the
|
||||
// sandbox.
|
||||
if (JS_IsExceptionPending(cx)) {
|
||||
JS_ReportPendingException(cx);
|
||||
}
|
||||
|
||||
isUndefined = rval == JSVAL_VOID;
|
||||
|
||||
if (!isUndefined && NS_SUCCEEDED(rv)) {
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSString *str = JS_ValueToString(cx, rval);
|
||||
if (!str) {
|
||||
// Report any pending exceptions.
|
||||
if (JS_IsExceptionPending(cx)) {
|
||||
JS_ReportPendingException(cx);
|
||||
}
|
||||
|
||||
// We don't know why this failed, so just use a
|
||||
// generic error code. It'll be translated to a
|
||||
// different one below anyways.
|
||||
rv = NS_ERROR_FAILURE;
|
||||
} else {
|
||||
result = nsDependentJSString(str);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No need to use the sandbox, evaluate the script directly in
|
||||
// the given scope.
|
||||
rv = scriptContext->EvaluateString(NS_ConvertUTF8toUTF16(script),
|
||||
globalJSObject, // obj
|
||||
principal,
|
||||
url.get(), // url
|
||||
1, // line no
|
||||
nsnull,
|
||||
&result,
|
||||
&isUndefined);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = NS_ERROR_MALFORMED_URI;
|
||||
}
|
||||
else if (bIsUndefined) {
|
||||
else if (isUndefined) {
|
||||
rv = NS_ERROR_DOM_RETVAL_UNDEFINED;
|
||||
}
|
||||
else {
|
||||
|
@ -270,6 +310,7 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel)
|
|||
else
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -147,12 +147,7 @@ interface nsIXPConnect;
|
|||
interface nsIXPConnectWrappedNative;
|
||||
interface nsIInterfaceInfo;
|
||||
interface nsIXPCSecurityManager;
|
||||
|
||||
%{C++
|
||||
#ifndef XPCONNECT_STANDALONE
|
||||
class nsIPrincipal;
|
||||
#endif
|
||||
%}
|
||||
interface nsIPrincipal;
|
||||
|
||||
/***************************************************************************/
|
||||
[uuid(8916a320-d118-11d3-8f3a-0010a4e73d9a)]
|
||||
|
@ -464,7 +459,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
|
|||
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
|
||||
%}
|
||||
|
||||
[uuid(038ce87f-c178-4d3a-9824-f71effc63aef)]
|
||||
[uuid(0f2f96c2-0a66-4677-a3d8-ebb907e9b780)]
|
||||
interface nsIXPConnect : nsISupports
|
||||
{
|
||||
%{ C++
|
||||
|
@ -705,4 +700,32 @@ interface nsIXPConnect : nsISupports
|
|||
in JSObjectPtr aScope,
|
||||
in nsIClassInfo aClassInfo,
|
||||
in nsIXPConnectJSObjectHolder aPrototype);
|
||||
|
||||
/**
|
||||
* Create a sandbox for evaluating code in isolation using
|
||||
* evalInSandboxObject().
|
||||
*
|
||||
* @param cx A context to use when creating the sandbox object.
|
||||
* @param principal The principal (or NULL to use the null principal)
|
||||
* to use when evaluating code in this sandbox.
|
||||
*/
|
||||
[noscript] nsIXPConnectJSObjectHolder createSandbox(in JSContextPtr cx,
|
||||
in nsIPrincipal principal);
|
||||
|
||||
/**
|
||||
* Evaluate script in a sandbox, completely isolated from all
|
||||
* other running scripts.
|
||||
*
|
||||
* @param source The source of the script to evaluate.
|
||||
* @param cx The context to use when setting up the evaluation of
|
||||
* the script. The actual evaluation will happen on a new
|
||||
* temporary context.
|
||||
* @param sandbox The sandbox object to evaluate the script in.
|
||||
* @return The result of the evaluation as a jsval. If the caller
|
||||
* intends to use the return value from this call the caller
|
||||
* is responsible for rooting the jsval before making a call
|
||||
* to this method.
|
||||
*/
|
||||
[noscript] JSVal evalInSandboxObject(in AString source, in JSContextPtr cx,
|
||||
in nsIXPConnectJSObjectHolder sandbox);
|
||||
};
|
||||
|
|
|
@ -1182,6 +1182,57 @@ nsXPConnect::RestoreWrappedNativePrototype(JSContext * aJSContext,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::CreateSandbox(JSContext *cx, nsIPrincipal *principal,
|
||||
nsIXPConnectJSObjectHolder **_retval)
|
||||
{
|
||||
#ifdef XPCONNECT_STANDALONE
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
#else /* XPCONNECT_STANDALONE */
|
||||
XPCCallContext ccx(NATIVE_CALLER, cx);
|
||||
if(!ccx.IsValid())
|
||||
return UnexpectedFailure(NS_ERROR_FAILURE);
|
||||
|
||||
*_retval = nsnull;
|
||||
|
||||
jsval rval = JSVAL_VOID;
|
||||
AUTO_MARK_JSVAL(ccx, &rval);
|
||||
|
||||
nsresult rv = xpc_CreateSandboxObject(cx, &rval, principal);
|
||||
NS_ASSERTION(NS_FAILED(rv) || !JSVAL_IS_PRIMITIVE(rval),
|
||||
"Bad return value from xpc_CreateSandboxObject()!");
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(rval)) {
|
||||
*_retval = XPCJSObjectHolder::newHolder(cx, JSVAL_TO_OBJECT(rval));
|
||||
NS_ENSURE_TRUE(*_retval, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ADDREF(*_retval);
|
||||
}
|
||||
|
||||
return rv;
|
||||
#endif /* XPCONNECT_STANDALONE */
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::EvalInSandboxObject(const nsAString& source, JSContext *cx,
|
||||
nsIXPConnectJSObjectHolder *sandbox,
|
||||
jsval *rval)
|
||||
{
|
||||
#ifdef XPCONNECT_STANDALONE
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
#else /* XPCONNECT_STANDALONE */
|
||||
if (!sandbox)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
JSObject *obj;
|
||||
nsresult rv = sandbox->GetJSObject(&obj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return xpc_EvalInSandbox(cx, obj, source,
|
||||
NS_ConvertUTF16toUTF8(source).get(), 1, rval);
|
||||
#endif /* XPCONNECT_STANDALONE */
|
||||
}
|
||||
|
||||
/* nsIXPConnectJSObjectHolder getWrappedNativePrototype (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsIClassInfo aClassInfo); */
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::GetWrappedNativePrototype(JSContext * aJSContext,
|
||||
|
|
|
@ -2666,6 +2666,9 @@ public:
|
|||
virtual ~nsXPCComponents_utils_Sandbox();
|
||||
|
||||
private:
|
||||
// XXXjst: This method (and other CallOrConstruct()'s in this
|
||||
// file) doesn't need to be virtual, could even be a static
|
||||
// method!
|
||||
NS_METHOD CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext * cx, JSObject * obj,
|
||||
PRUint32 argc, jsval * argv,
|
||||
|
@ -3145,6 +3148,77 @@ NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_utils_Sandbox)
|
|||
#define XPC_MAP_FLAGS 0
|
||||
#include "xpc_map_end.h" /* This #undef's the above. */
|
||||
|
||||
#ifndef XPCONNECT_STANDALONE
|
||||
nsresult
|
||||
xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop)
|
||||
{
|
||||
// Create the sandbox global object
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
|
||||
XPCAutoJSContext tempcx(JS_NewContext(JS_GetRuntime(cx), 1024), PR_FALSE);
|
||||
if (!tempcx)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
AutoJSRequestWithNoCallContext req(tempcx);
|
||||
JSObject *sandbox = JS_NewObject(tempcx, &SandboxClass, nsnull, nsnull);
|
||||
if (!sandbox)
|
||||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
|
||||
JS_SetGlobalObject(tempcx, sandbox);
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(prinOrSop));
|
||||
|
||||
if (!sop) {
|
||||
nsCOMPtr<nsIPrincipal> principal(do_QueryInterface(prinOrSop));
|
||||
|
||||
if (!principal) {
|
||||
principal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||
NS_ASSERTION(NS_FAILED(rv) || principal,
|
||||
"Bad return from do_CreateInstance");
|
||||
|
||||
if (!principal || NS_FAILED(rv)) {
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
sop = new PrincipalHolder(principal);
|
||||
if (!sop)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// Pass on ownership of sop to |sandbox|.
|
||||
|
||||
{
|
||||
nsIScriptObjectPrincipal *tmp = sop;
|
||||
|
||||
if (!JS_SetPrivate(cx, sandbox, tmp)) {
|
||||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_ADDREF(tmp);
|
||||
}
|
||||
|
||||
rv = xpc->InitClasses(cx, sandbox);
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
!JS_DefineFunctions(cx, sandbox, SandboxFunctions)) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
|
||||
if (vp)
|
||||
*vp = OBJECT_TO_JSVAL(sandbox);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif /* !XPCONNECT_STANDALONE */
|
||||
|
||||
/* PRBool call(in nsIXPConnectWrappedNative wrapper,
|
||||
in JSContextPtr cx,
|
||||
in JSObjectPtr obj,
|
||||
|
@ -3191,29 +3265,16 @@ nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrappe
|
|||
{
|
||||
#ifdef XPCONNECT_STANDALONE
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
#else
|
||||
#else /* XPCONNECT_STANDALONE */
|
||||
if (argc < 1)
|
||||
return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
|
||||
|
||||
// Create the sandbox global object
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
|
||||
if(NS_FAILED(rv))
|
||||
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
|
||||
|
||||
XPCAutoJSContext tempcx(JS_NewContext(JS_GetRuntime(cx), 1024), PR_FALSE);
|
||||
if (!tempcx)
|
||||
return ThrowAndFail(NS_ERROR_OUT_OF_MEMORY, cx, _retval);
|
||||
|
||||
AutoJSRequestWithNoCallContext req(tempcx);
|
||||
JSObject *sandbox = JS_NewObject(tempcx, &SandboxClass, nsnull, nsnull);
|
||||
if (!sandbox)
|
||||
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
|
||||
|
||||
JS_SetGlobalObject(tempcx, sandbox);
|
||||
|
||||
// Make sure to set up principals on the sandbox before initing classes
|
||||
nsIScriptObjectPrincipal *sop = nsnull;
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> sop;
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsISupports *prinOrSop = nsnull;
|
||||
if (JSVAL_IS_STRING(argv[0])) {
|
||||
JSString *codebasestr = JSVAL_TO_STRING(argv[0]);
|
||||
nsCAutoString codebase(JS_GetStringBytes(codebasestr),
|
||||
|
@ -3224,13 +3285,12 @@ nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrappe
|
|||
if (!stdUrl ||
|
||||
NS_FAILED(rv = stdUrl->Init(nsIStandardURL::URLTYPE_STANDARD, 80,
|
||||
codebase, nsnull, nsnull)) ||
|
||||
!(iURL = do_QueryInterface(stdUrl, &rv))) {
|
||||
!(iURL = do_QueryInterface(stdUrl, &rv))) {
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = NS_ERROR_FAILURE;
|
||||
return ThrowAndFail(rv, cx, _retval);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> secman =
|
||||
do_GetService(kScriptSecurityManagerContractID);
|
||||
if (!secman ||
|
||||
|
@ -3241,52 +3301,37 @@ nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrappe
|
|||
return ThrowAndFail(rv, cx, _retval);
|
||||
}
|
||||
|
||||
sop = new PrincipalHolder(principal);
|
||||
if (!sop)
|
||||
return ThrowAndFail(NS_ERROR_OUT_OF_MEMORY, cx, _retval);
|
||||
|
||||
NS_ADDREF(sop);
|
||||
prinOrSop = principal;
|
||||
} else {
|
||||
if (!JSVAL_IS_PRIMITIVE(argv[0])) {
|
||||
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
|
||||
if(!xpc)
|
||||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
||||
xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(argv[0]),
|
||||
getter_AddRefs(wrapper));
|
||||
|
||||
if (wrapper) {
|
||||
nsCOMPtr<nsIDOMWindow> win = do_QueryWrappedNative(wrapper);
|
||||
if (win)
|
||||
CallQueryInterface(win, &sop);
|
||||
sop = do_QueryWrappedNative(wrapper);
|
||||
|
||||
prinOrSop = sop;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sop)
|
||||
if (!prinOrSop)
|
||||
return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
|
||||
|
||||
// Note: if we're here, then sop has been AddRef'd by CallQueryInterface
|
||||
}
|
||||
|
||||
if (!JS_SetPrivate(cx, sandbox, sop)) {
|
||||
NS_RELEASE(sop);
|
||||
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
|
||||
rv = xpc_CreateSandboxObject(cx, vp, prinOrSop);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return ThrowAndFail(rv, cx, _retval);
|
||||
}
|
||||
|
||||
// After this point |sop| will be released when |sandbox| is
|
||||
// finalized, so no need to worry about it from now on.
|
||||
*_retval = PR_TRUE;
|
||||
|
||||
rv = xpc->InitClasses(cx, sandbox);
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
!JS_DefineFunctions(cx, sandbox, SandboxFunctions)) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
|
||||
|
||||
if (vp)
|
||||
*vp = OBJECT_TO_JSVAL(sandbox);
|
||||
|
||||
*_retval = JS_TRUE;
|
||||
return NS_OK;
|
||||
#endif
|
||||
return rv;
|
||||
#endif /* XPCONNECT_STANDALONE */
|
||||
}
|
||||
|
||||
class ContextHolder : public nsISupports
|
||||
|
@ -3327,7 +3372,7 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source)
|
|||
{
|
||||
#ifdef XPCONNECT_STANDALONE
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
#else
|
||||
#else /* XPCONNECT_STANDALONE */
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
|
||||
|
@ -3369,6 +3414,38 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source)
|
|||
if (JSVAL_IS_PRIMITIVE(argv[1]))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
JSObject *sandbox = JSVAL_TO_OBJECT(argv[1]);
|
||||
|
||||
// Get the current source info from xpc.
|
||||
nsXPIDLCString filename;
|
||||
PRInt32 lineNo = 0;
|
||||
{
|
||||
nsCOMPtr<nsIStackFrame> frame;
|
||||
xpc->GetCurrentJSStack(getter_AddRefs(frame));
|
||||
if (frame) {
|
||||
frame->GetFilename(getter_Copies(filename));
|
||||
frame->GetLineNumber(&lineNo);
|
||||
}
|
||||
}
|
||||
|
||||
rv = xpc_EvalInSandbox(cx, sandbox, source, filename.get(), lineNo, rval);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (JS_IsExceptionPending(cx)) {
|
||||
cc->SetExceptionWasThrown(PR_TRUE);
|
||||
} else {
|
||||
cc->SetReturnValueWasSet(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
#endif /* XPCONNECT_STANDALONE */
|
||||
}
|
||||
|
||||
#ifndef XPCONNECT_STANDALONE
|
||||
nsresult
|
||||
xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
|
||||
const char *filename, PRInt32 lineNo, jsval *rval)
|
||||
{
|
||||
if (JS_GetClass(cx, sandbox) != &SandboxClass)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
|
@ -3393,8 +3470,7 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source)
|
|||
}
|
||||
|
||||
XPCPerThreadData *data = XPCPerThreadData::GetData();
|
||||
XPCJSContextStack *stack;
|
||||
PRBool popContext = PR_FALSE;
|
||||
XPCJSContextStack *stack = nsnull;
|
||||
if (data && (stack = data->GetJSContextStack())) {
|
||||
if (NS_FAILED(stack->Push(sandcx->GetJSContext()))) {
|
||||
JS_ReportError(cx,
|
||||
|
@ -3402,55 +3478,44 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source)
|
|||
JSPRINCIPALS_DROP(cx, jsPrincipals);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
popContext = PR_TRUE;
|
||||
}
|
||||
|
||||
// Get the current source info from xpc. Use the codebase as a fallback,
|
||||
// though.
|
||||
nsXPIDLCString filename;
|
||||
PRInt32 lineNo = 0;
|
||||
{
|
||||
nsCOMPtr<nsIStackFrame> frame;
|
||||
xpc->GetCurrentJSStack(getter_AddRefs(frame));
|
||||
if (frame) {
|
||||
frame->GetFilename(getter_Copies(filename));
|
||||
frame->GetLineNumber(&lineNo);
|
||||
} else {
|
||||
filename.Assign(jsPrincipals->codebase);
|
||||
lineNo = 1;
|
||||
}
|
||||
if (!filename) {
|
||||
// Default the filename to the codebase.
|
||||
filename = jsPrincipals->codebase;
|
||||
lineNo = 1;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
AutoJSRequestWithNoCallContext req(sandcx->GetJSContext());
|
||||
if (!JS_EvaluateUCScriptForPrincipals(sandcx->GetJSContext(), sandbox,
|
||||
jsPrincipals,
|
||||
NS_REINTERPRET_CAST(const jschar *,
|
||||
PromiseFlatString(source).get()),
|
||||
source.Length(), filename.get(),
|
||||
lineNo, rval)) {
|
||||
source.Length(), filename, lineNo,
|
||||
rval)) {
|
||||
jsval exn;
|
||||
if (JS_GetPendingException(sandcx->GetJSContext(), &exn)) {
|
||||
AutoJSSuspendRequestWithNoCallContext sus(sandcx->GetJSContext());
|
||||
AutoJSRequestWithNoCallContext cxreq(cx);
|
||||
|
||||
JS_SetPendingException(cx, exn);
|
||||
cc->SetExceptionWasThrown(PR_TRUE);
|
||||
} else {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
} else {
|
||||
cc->SetReturnValueWasSet(PR_TRUE);
|
||||
}
|
||||
|
||||
if (popContext) {
|
||||
if (stack) {
|
||||
stack->Pop(nsnull);
|
||||
}
|
||||
|
||||
JSPRINCIPALS_DROP(cx, jsPrincipals);
|
||||
|
||||
return rv;
|
||||
#endif /* !XPCONNECT_STANDALONE */
|
||||
}
|
||||
#endif /* !XPCONNECT_STANDALONE */
|
||||
|
||||
|
||||
#ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
|
||||
/* string canCreateWrapper (in nsIIDPtr iid); */
|
||||
|
|
|
@ -3615,6 +3615,31 @@ JSBool xpc_IsReportableErrorCode(nsresult code);
|
|||
JSObject* xpc_CloneJSFunction(XPCCallContext &ccx, JSObject *funobj,
|
||||
JSObject *parent);
|
||||
|
||||
#ifndef XPCONNECT_STANDALONE
|
||||
|
||||
// Helper for creating a sandbox object to use for evaluating
|
||||
// untrusted code completely separated from all other code in the
|
||||
// system using xpc_EvalInSandbox(). Takes the JSContext on which to
|
||||
// do setup etc on, puts the sandbox object in *vp (which must be
|
||||
// rooted by the caller), and uses the principal that's either
|
||||
// directly passed in prinOrSop or indirectly as an
|
||||
// nsIScriptObjectPrincipal holding the principal. If no principal is
|
||||
// reachable through prinOrSop, a new null principal will be created
|
||||
// and used.
|
||||
nsresult
|
||||
xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop);
|
||||
|
||||
// Helper for evaluating scripts in a sandbox object created with
|
||||
// xpc_CreateSandboxObject(). The caller is responsible of ensuring
|
||||
// that *rval doesn't get collected during the call or usage after the
|
||||
// call. This helper will use filename and lineNo for error reporting,
|
||||
// and if no filename is provided it will use the codebase from the
|
||||
// principal and line number 1 as a fallback.
|
||||
nsresult
|
||||
xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
|
||||
const char *filename, PRInt32 lineNo, jsval *rval);
|
||||
#endif /* !XPCONNECT_STANDALONE */
|
||||
|
||||
/***************************************************************************/
|
||||
// Inlined utilities.
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче