mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 840488 - Introduce a mechanism to temporarily or permanently block script for a given scope, and use it for unsafe channels. r=bz
This commit is contained in:
parent
589ed842af
commit
260c41dfe4
@ -1714,6 +1714,11 @@ nsScriptSecurityManager::ScriptAllowed(JSObject *aGlobal)
|
||||
AutoJSContext cx_;
|
||||
JS::RootedObject global(cx_, js::UncheckedUnwrap(aGlobal, /* stopAtOuter = */ false));
|
||||
|
||||
// Check the bits on the compartment private.
|
||||
if (!xpc::Scriptability::Get(global).Allowed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptContext> scx = nsJSUtils::GetStaticScriptContext(global);
|
||||
AutoPushJSContext cx(scx ? scx->GetNativeContext() : GetSafeJSContext());
|
||||
bool result = false;
|
||||
|
@ -2077,12 +2077,6 @@ nsDocShell::GetAllowJavascript(bool * aAllowJavascript)
|
||||
NS_ENSURE_ARG_POINTER(aAllowJavascript);
|
||||
|
||||
*aAllowJavascript = mAllowJavascript;
|
||||
if (!mAllowJavascript) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool unsafe;
|
||||
*aAllowJavascript = NS_SUCCEEDED(GetChannelIsUnsafe(&unsafe)) && !unsafe;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -139,6 +139,7 @@
|
||||
#endif
|
||||
#include "nsIDOMCustomEvent.h"
|
||||
#include "nsIFrameRequestCallback.h"
|
||||
#include "nsIJARChannel.h"
|
||||
|
||||
#include "xpcprivate.h"
|
||||
|
||||
@ -2541,6 +2542,14 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// If the document comes from a JAR, check if the channel was determined
|
||||
// to be unsafe. If so, permanently disable script on the compartment by
|
||||
// calling Block() and throwing away the key.
|
||||
nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(aDocument->GetChannel());
|
||||
if (jarChannel && jarChannel->GetIsUnsafe()) {
|
||||
xpc::Scriptability::Get(newInnerWindow->mJSObject).Block();
|
||||
}
|
||||
|
||||
if (mArguments) {
|
||||
newInnerWindow->DefineArgumentsProperty(mArguments);
|
||||
mArguments = nullptr;
|
||||
|
@ -120,7 +120,7 @@ interface ScheduledGCCallback : nsISupports
|
||||
/**
|
||||
* interface of Components.utils
|
||||
*/
|
||||
[scriptable, uuid(90019271-a0d1-439f-911c-967f8e85cd5b)]
|
||||
[scriptable, uuid(12368474-b448-4ac6-ba2c-db1966a7a697)]
|
||||
interface nsIXPCComponents_Utils : nsISupports
|
||||
{
|
||||
|
||||
@ -448,6 +448,23 @@ interface nsIXPCComponents_Utils : nsISupports
|
||||
[implicit_jscontext]
|
||||
void nukeSandbox(in jsval obj);
|
||||
|
||||
/*
|
||||
* API to dynamically block script for a given global. This takes effect
|
||||
* immediately, unlike other APIs that only affect newly-created globals.
|
||||
*
|
||||
* The machinery here maintains a counter, and allows script only if each
|
||||
* call to blockScriptForGlobal() has been matched with a call to
|
||||
* unblockScriptForGlobal(). The caller _must_ make sure never to call
|
||||
* unblock() more times than it calls block(), since that could potentially
|
||||
* interfere with another consumer's script blocking.
|
||||
*/
|
||||
|
||||
[implicit_jscontext]
|
||||
void blockScriptForGlobal(in jsval global);
|
||||
|
||||
[implicit_jscontext]
|
||||
void unblockScriptForGlobal(in jsval global);
|
||||
|
||||
/**
|
||||
* Check whether the given object is an XrayWrapper.
|
||||
*/
|
||||
|
@ -3374,6 +3374,38 @@ nsXPCComponents_Utils::NukeSandbox(const Value &obj, JSContext *cx)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::BlockScriptForGlobal(const JS::Value &globalArg,
|
||||
JSContext *cx)
|
||||
{
|
||||
NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
|
||||
JSObject *global = UncheckedUnwrap(&globalArg.toObject(),
|
||||
/* stopAtOuter = */ false);
|
||||
NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
|
||||
if (nsContentUtils::IsSystemPrincipal(GetObjectPrincipal(global))) {
|
||||
JS_ReportError(cx, "Script may not be disabled for system globals");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
Scriptability::Get(global).Block();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::UnblockScriptForGlobal(const JS::Value &globalArg,
|
||||
JSContext *cx)
|
||||
{
|
||||
NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
|
||||
JSObject *global = UncheckedUnwrap(&globalArg.toObject(),
|
||||
/* stopAtOuter = */ false);
|
||||
NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
|
||||
if (nsContentUtils::IsSystemPrincipal(GetObjectPrincipal(global))) {
|
||||
JS_ReportError(cx, "Script may not be disabled for system globals");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
Scriptability::Get(global).Unblock();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::IsXrayWrapper(const Value &obj, bool* aRetval)
|
||||
{
|
||||
|
@ -410,6 +410,34 @@ EnsureCompartmentPrivate(JSCompartment *c)
|
||||
return priv;
|
||||
}
|
||||
|
||||
Scriptability::Scriptability() : mScriptBlocks(0) {}
|
||||
|
||||
bool
|
||||
Scriptability::Allowed()
|
||||
{
|
||||
return mScriptBlocks == 0;
|
||||
}
|
||||
|
||||
void
|
||||
Scriptability::Block()
|
||||
{
|
||||
++mScriptBlocks;
|
||||
}
|
||||
|
||||
void
|
||||
Scriptability::Unblock()
|
||||
{
|
||||
MOZ_ASSERT(mScriptBlocks > 0);
|
||||
--mScriptBlocks;
|
||||
}
|
||||
|
||||
/* static */
|
||||
Scriptability&
|
||||
Scriptability::Get(JSObject *aScope)
|
||||
{
|
||||
return EnsureCompartmentPrivate(aScope)->scriptability;
|
||||
}
|
||||
|
||||
bool
|
||||
IsXBLScope(JSCompartment *compartment)
|
||||
{
|
||||
|
@ -3782,6 +3782,9 @@ public:
|
||||
bool adoptedNode;
|
||||
bool donatedNode;
|
||||
|
||||
// The scriptability of this compartment.
|
||||
Scriptability scriptability;
|
||||
|
||||
// Our XPCWrappedNativeScope. This is non-null if and only if this is an
|
||||
// XPConnect compartment.
|
||||
XPCWrappedNativeScope *scope;
|
||||
|
@ -34,6 +34,25 @@ class nsIMemoryReporterCallback;
|
||||
#endif
|
||||
|
||||
namespace xpc {
|
||||
|
||||
class Scriptability {
|
||||
public:
|
||||
Scriptability();
|
||||
bool Allowed();
|
||||
|
||||
void Block();
|
||||
void Unblock();
|
||||
|
||||
static Scriptability& Get(JSObject *aScope);
|
||||
|
||||
private:
|
||||
// Whenever a consumer wishes to prevent script from running on a global,
|
||||
// it increments this value with a call to Block(). When it wishes to
|
||||
// re-enable it (if ever), it decrements this value with a call to Unblock().
|
||||
// Script may not run if this value is non-zero.
|
||||
uint32_t mScriptBlocks;
|
||||
};
|
||||
|
||||
JSObject *
|
||||
TransplantObject(JSContext *cx, JS::HandleObject origobj, JS::HandleObject target);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "nsIChannel.idl"
|
||||
|
||||
[scriptable, uuid(6e6cc56d-51eb-4299-a795-dcfd1229ab3d)]
|
||||
[scriptable, builtinclass, uuid(6e6cc56d-51eb-4299-a795-dcfd1229ab3d)]
|
||||
interface nsIJARChannel : nsIChannel
|
||||
{
|
||||
/**
|
||||
@ -14,7 +14,7 @@ interface nsIJARChannel : nsIChannel
|
||||
* redirects, and plugins should be disabled when loading from this
|
||||
* channel.
|
||||
*/
|
||||
readonly attribute boolean isUnsafe;
|
||||
[infallible] readonly attribute boolean isUnsafe;
|
||||
|
||||
/**
|
||||
* Forces the uri to be a app:// uri.
|
||||
|
Loading…
Reference in New Issue
Block a user