mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 840488 - Compute immunity from caps checks exactly once, and kill nsScriptSecurityManager::CanExecuteScripts. r=bz
This commit is contained in:
parent
15add0796f
commit
a80315ff5c
@ -201,6 +201,13 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
||||
* script to check whether a given principal is system.
|
||||
*/
|
||||
boolean isSystemPrincipal(in nsIPrincipal aPrincipal);
|
||||
%{C++
|
||||
bool IsSystemPrincipal(nsIPrincipal* aPrincipal) {
|
||||
bool isSystem = false;
|
||||
IsSystemPrincipal(aPrincipal, &isSystem);
|
||||
return isSystem;
|
||||
}
|
||||
%}
|
||||
|
||||
/**
|
||||
* Same as getSubjectPrincipal(), only faster. cx must *never* be
|
||||
|
@ -381,7 +381,7 @@ private:
|
||||
|
||||
// Returns null if a principal cannot be found; generally callers
|
||||
// should error out at that point.
|
||||
static nsIPrincipal* doGetObjectPrincipal(JS::Handle<JSObject*> obj);
|
||||
static nsIPrincipal* doGetObjectPrincipal(JSObject* obj);
|
||||
|
||||
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
||||
// when this happens -- this means that there was no JS running.
|
||||
@ -462,9 +462,6 @@ private:
|
||||
nsIPrincipal* aSubjectPrincipal,
|
||||
const char* aObjectSecurityLevel);
|
||||
|
||||
nsresult
|
||||
CanExecuteScripts(JSContext* cx, nsIPrincipal *aPrincipal, bool *result);
|
||||
|
||||
nsresult
|
||||
Init();
|
||||
|
||||
|
@ -1596,97 +1596,43 @@ nsScriptSecurityManager::CheckLoadURIStrWithPrincipal(nsIPrincipal* aPrincipal,
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptSecurityManager::CanExecuteScripts(JSContext* cx,
|
||||
nsIPrincipal *aPrincipal,
|
||||
bool *result)
|
||||
{
|
||||
*result = false;
|
||||
|
||||
if (aPrincipal == mSystemPrincipal)
|
||||
{
|
||||
// Even if JavaScript is disabled, we must still execute system scripts
|
||||
*result = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Same thing for nsExpandedPrincipal, which is pseudo-privileged.
|
||||
nsCOMPtr<nsIExpandedPrincipal> ep = do_QueryInterface(aPrincipal);
|
||||
if (ep)
|
||||
{
|
||||
*result = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check whether our URI is an "about:" URI that allows scripts. If it is,
|
||||
// we need to allow JS to run. In this case, don't apply the JS enabled
|
||||
// pref or policies. On failures, just press on and don't do this special
|
||||
// case.
|
||||
nsCOMPtr<nsIURI> principalURI;
|
||||
aPrincipal->GetURI(getter_AddRefs(principalURI));
|
||||
if (!principalURI) {
|
||||
// Broken principal of some sort. Disallow.
|
||||
*result = false;
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
bool isAbout;
|
||||
nsresult rv = principalURI->SchemeIs("about", &isAbout);
|
||||
if (NS_SUCCEEDED(rv) && isAbout) {
|
||||
nsCOMPtr<nsIAboutModule> module;
|
||||
rv = NS_GetAboutModule(principalURI, getter_AddRefs(module));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
uint32_t flags;
|
||||
rv = module->GetURIFlags(principalURI, &flags);
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
(flags & nsIAboutModule::ALLOW_SCRIPT)) {
|
||||
*result = true;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*result = mIsJavaScriptEnabled;
|
||||
if (!*result)
|
||||
return NS_OK; // Do not run scripts
|
||||
|
||||
//-- Check for a per-site policy
|
||||
static const char jsPrefGroupName[] = "javascript";
|
||||
ClassInfoData nameData(nullptr, jsPrefGroupName);
|
||||
|
||||
SecurityLevel secLevel;
|
||||
rv = LookupPolicy(aPrincipal, nameData, EnabledID(),
|
||||
nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
|
||||
nullptr, &secLevel);
|
||||
if (NS_FAILED(rv) || secLevel.level == SCRIPT_SECURITY_NO_ACCESS)
|
||||
{
|
||||
*result = false;
|
||||
return rv;
|
||||
}
|
||||
|
||||
//-- Nobody vetoed, so allow the JS to run.
|
||||
*result = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
bool
|
||||
nsScriptSecurityManager::ScriptAllowed(JSObject *aGlobal)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT(JS_IsGlobalObject(aGlobal) || js::IsOuterObject(aGlobal));
|
||||
AutoJSContext cx_;
|
||||
JS::RootedObject global(cx_, js::UncheckedUnwrap(aGlobal, /* stopAtOuter = */ false));
|
||||
AutoJSContext cx;
|
||||
JS::RootedObject global(cx, js::UncheckedUnwrap(aGlobal, /* stopAtOuter = */ false));
|
||||
|
||||
// Check the bits on the compartment private.
|
||||
if (!xpc::Scriptability::Get(global).Allowed()) {
|
||||
xpc::Scriptability& scriptability = xpc::Scriptability::Get(aGlobal);
|
||||
if (!scriptability.Allowed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptContext> scx = nsJSUtils::GetStaticScriptContext(global);
|
||||
AutoPushJSContext cx(scx ? scx->GetNativeContext() : GetSafeJSContext());
|
||||
bool result = false;
|
||||
nsresult rv = CanExecuteScripts(cx, doGetObjectPrincipal(global), &result);
|
||||
return NS_SUCCEEDED(rv) && result;
|
||||
// If the compartment is immune to script policy, we're done.
|
||||
if (scriptability.IsImmuneToScriptPolicy()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If JS is disabled system-wide, we disallow.
|
||||
if (!mIsJavaScriptEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for a per-site policy.
|
||||
static const char jsPrefGroupName[] = "javascript";
|
||||
ClassInfoData nameData(nullptr, jsPrefGroupName);
|
||||
SecurityLevel secLevel;
|
||||
nsresult rv = LookupPolicy(doGetObjectPrincipal(global), nameData,
|
||||
EnabledID(),
|
||||
nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
|
||||
nullptr, &secLevel);
|
||||
if (NS_FAILED(rv) || secLevel.level == SCRIPT_SECURITY_NO_ACCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////// Principals ///////////////////////
|
||||
@ -1883,7 +1829,7 @@ nsScriptSecurityManager::GetObjectPrincipal(JSContext *aCx, JSObject *aObj,
|
||||
|
||||
// static
|
||||
nsIPrincipal*
|
||||
nsScriptSecurityManager::doGetObjectPrincipal(JS::Handle<JSObject*> aObj)
|
||||
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
|
||||
{
|
||||
JSCompartment *compartment = js::GetObjectCompartment(aObj);
|
||||
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "AccessCheck.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsAboutProtocolUtils.h"
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
@ -405,14 +406,52 @@ EnsureCompartmentPrivate(JSCompartment *c)
|
||||
CompartmentPrivate *priv = GetCompartmentPrivate(c);
|
||||
if (priv)
|
||||
return priv;
|
||||
priv = new CompartmentPrivate();
|
||||
priv = new CompartmentPrivate(c);
|
||||
JS_SetCompartmentPrivate(c, priv);
|
||||
return priv;
|
||||
}
|
||||
|
||||
Scriptability::Scriptability() : mScriptBlocks(0)
|
||||
, mDocShellAllowsScript(true)
|
||||
{}
|
||||
static bool
|
||||
PrincipalImmuneToScriptPolicy(nsIPrincipal* aPrincipal)
|
||||
{
|
||||
// System principal gets a free pass.
|
||||
if (XPCWrapper::GetSecurityManager()->IsSystemPrincipal(aPrincipal))
|
||||
return true;
|
||||
|
||||
// nsExpandedPrincipal gets a free pass.
|
||||
nsCOMPtr<nsIExpandedPrincipal> ep = do_QueryInterface(aPrincipal);
|
||||
if (ep)
|
||||
return true;
|
||||
|
||||
// Check whether our URI is an "about:" URI that allows scripts. If it is,
|
||||
// we need to allow JS to run.
|
||||
nsCOMPtr<nsIURI> principalURI;
|
||||
aPrincipal->GetURI(getter_AddRefs(principalURI));
|
||||
MOZ_ASSERT(principalURI);
|
||||
bool isAbout;
|
||||
nsresult rv = principalURI->SchemeIs("about", &isAbout);
|
||||
if (NS_SUCCEEDED(rv) && isAbout) {
|
||||
nsCOMPtr<nsIAboutModule> module;
|
||||
rv = NS_GetAboutModule(principalURI, getter_AddRefs(module));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
uint32_t flags;
|
||||
rv = module->GetURIFlags(principalURI, &flags);
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
(flags & nsIAboutModule::ALLOW_SCRIPT)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Scriptability::Scriptability(JSCompartment *c) : mScriptBlocks(0)
|
||||
, mDocShellAllowsScript(true)
|
||||
{
|
||||
nsIPrincipal *prin = nsJSPrincipals::get(JS_GetCompartmentPrincipals(c));
|
||||
mImmuneToScriptPolicy = PrincipalImmuneToScriptPolicy(prin);
|
||||
}
|
||||
|
||||
bool
|
||||
Scriptability::Allowed()
|
||||
@ -420,6 +459,12 @@ Scriptability::Allowed()
|
||||
return mDocShellAllowsScript && mScriptBlocks == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Scriptability::IsImmuneToScriptPolicy()
|
||||
{
|
||||
return mImmuneToScriptPolicy;
|
||||
}
|
||||
|
||||
void
|
||||
Scriptability::Block()
|
||||
{
|
||||
|
@ -3758,11 +3758,12 @@ public:
|
||||
LocationHintAddon
|
||||
};
|
||||
|
||||
CompartmentPrivate()
|
||||
CompartmentPrivate(JSCompartment *c)
|
||||
: wantXrays(false)
|
||||
, universalXPConnectEnabled(false)
|
||||
, adoptedNode(false)
|
||||
, donatedNode(false)
|
||||
, scriptability(c)
|
||||
, scope(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(xpc::CompartmentPrivate);
|
||||
|
@ -37,8 +37,9 @@ namespace xpc {
|
||||
|
||||
class Scriptability {
|
||||
public:
|
||||
Scriptability();
|
||||
Scriptability(JSCompartment *c);
|
||||
bool Allowed();
|
||||
bool IsImmuneToScriptPolicy();
|
||||
|
||||
void Block();
|
||||
void Unblock();
|
||||
@ -56,6 +57,10 @@ private:
|
||||
// Whether the docshell allows javascript in this scope. If this scope
|
||||
// doesn't have a docshell, this value is always true.
|
||||
bool mDocShellAllowsScript;
|
||||
|
||||
// Whether this scope is immune to user-defined or addon-defined script
|
||||
// policy.
|
||||
bool mImmuneToScriptPolicy;
|
||||
};
|
||||
|
||||
JSObject *
|
||||
|
Loading…
Reference in New Issue
Block a user