Bug 1233497 - Fix infrastructure for disallowing unsafe CPOWs in browser code. r=mrbkap

This commit is contained in:
Bill McCloskey
2016-01-05 19:28:27 -05:00
parent d1bb08fb15
commit 0fbb50f168
7 changed files with 44 additions and 4 deletions

View File

@@ -16,6 +16,12 @@
SimpleTest.waitForExplicitFinish();
const PREF_UNSAFE_FORBIDDEN = "dom.ipc.cpows.forbid-unsafe-from-browser";
SpecialPowers.setBoolPref(PREF_UNSAFE_FORBIDDEN, false);
SimpleTest.registerCleanupFunction(() => {
SpecialPowers.clearUserPref(PREF_UNSAFE_FORBIDDEN);
});
function done() {
SimpleTest.finish();
}

View File

@@ -7,6 +7,7 @@
#include "JavaScriptParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsJSUtils.h"
#include "jsfriendapi.h"
#include "jswrapper.h"
@@ -68,8 +69,11 @@ JavaScriptParent::allowMessage(JSContext* cx)
return true;
if (ForbidUnsafeBrowserCPOWs()) {
if (JSObject* global = JS::CurrentGlobalOrNull(cx)) {
if (!JS::AddonIdOfObject(global)) {
nsIGlobalObject* global = dom::GetIncumbentGlobal();
JSObject* jsGlobal = global ? global->GetGlobalJSObject() : nullptr;
if (jsGlobal) {
JSAutoCompartment ac(cx, jsGlobal);
if (!JS::AddonIdOfObject(jsGlobal) && !xpc::CompartmentPrivate::Get(jsGlobal)->allowCPOWs) {
JS_ReportError(cx, "unsafe CPOW usage forbidden");
return false;
}

View File

@@ -123,7 +123,7 @@ interface ScheduledGCCallback : nsISupports
/**
* interface of Components.utils
*/
[scriptable, uuid(3ce3a6f8-2b59-439c-a57e-74e7b122fb3c)]
[scriptable, uuid(86003fe3-ee9a-4620-91dc-eef8b1e58815)]
interface nsIXPCComponents_Utils : nsISupports
{
@@ -444,6 +444,15 @@ interface nsIXPCComponents_Utils : nsISupports
*/
ACString getCrossProcessWrapperTag(in jsval obj);
/**
* If CPOWs are disabled for browser code via the
* dom.ipc.cpows.forbid-unsafe-from-browser preferences, then only
* add-ons can use CPOWs. This function allows a non-addon scope
* to opt into CPOWs. It's necessary for the implementation of
* RemoteAddonsParent.jsm.
*/
void permitCPOWsInScope(in jsval obj);
/*
* To be called from JS only. This is for Gecko internal use only, and may
* disappear at any moment.

View File

@@ -2860,6 +2860,17 @@ nsXPCComponents_Utils::GetCrossProcessWrapperTag(HandleValue obj, nsACString& ou
return NS_OK;
}
NS_IMETHODIMP
nsXPCComponents_Utils::PermitCPOWsInScope(HandleValue obj)
{
if (!obj.isObject())
return NS_ERROR_INVALID_ARG;
JSObject* scopeObj = js::UncheckedUnwrap(&obj.toObject());
CompartmentPrivate::Get(scopeObj)->allowCPOWs = true;
return NS_OK;
}
NS_IMETHODIMP
nsXPCComponents_Utils::RecomputeWrappers(HandleValue vobj, JSContext* cx)
{

View File

@@ -202,6 +202,7 @@ CompartmentPrivate::CompartmentPrivate(JSCompartment* c)
, skipWriteToGlobalPrototype(false)
, isWebExtensionContentScript(false)
, waiveInterposition(false)
, allowCPOWs(false)
, universalXPConnectEnabled(false)
, forcePermissiveCOWs(false)
, scriptability(c)

View File

@@ -3730,6 +3730,13 @@ public:
// scope.
bool waiveInterposition;
// If CPOWs are disabled for browser code via the
// dom.ipc.cpows.forbid-unsafe-from-browser preferences, then only
// add-ons can use CPOWs. This flag allows a non-addon scope
// to opt into CPOWs. It's necessary for the implementation of
// RemoteAddonsParent.jsm.
bool allowCPOWs;
// This is only ever set during mochitest runs when enablePrivilege is called.
// It's intended as a temporary stopgap measure until we can finish ripping out
// enablePrivilege. Once set, this value is never unset (i.e., it doesn't follow

View File

@@ -22,6 +22,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "Prefetcher",
XPCOMUtils.defineLazyModuleGetter(this, "CompatWarning",
"resource://gre/modules/CompatWarning.jsm");
Cu.permitCPOWsInScope(this);
// Similar to Python. Returns dict[key] if it exists. Otherwise,
// sets dict[key] to default_ and returns default_.
function setDefault(dict, key, default_)
@@ -851,7 +853,7 @@ function getContentDocument(addon, browser)
return doc;
}
return browser.contentDocumentAsCPOW;
return browser.contentWindowAsCPOW.document;
}
function getSessionHistory(browser) {