Bug 834707 - Disable SOWs for remote XUL domains. r=bz
authorBobby Holley <bobbyholley@gmail.com>
Mon, 06 May 2013 19:38:22 -0700
changeset 131041 f6f8e02a9ab01720038bfb9a4ce4996ca8cbc819
parent 131040 b5e04d0c4a37d41a3bee6e5d624189317c7af4d4
child 131042 a28afac94104dd7713950647c3e5d84adc61357d
push id27660
push userbobbyholley@gmail.com
push dateTue, 07 May 2013 02:38:39 +0000
treeherdermozilla-inbound@a28afac94104 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs834707
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 834707 - Disable SOWs for remote XUL domains. r=bz We have to do this if we want to proceed with eliminating SOWs entirely. Given the other restrictions around remote XUL, I don't think this is a problem. Note that we shouldn't need any special handling in the wrapper reparenting paths, because those all depend on whether a SOW was there already. So that would only be an issue if it were possible to adoptNode from a non-remote-XUL domain into a remote-XUL domain, which thankfully can't happen.
content/base/src/nsINode.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/wrappers/WrapperFactory.cpp
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -2391,17 +2391,18 @@ nsINode::WrapObject(JSContext *aCx, JS::
       !hasHadScriptHandlingObject &&
       !nsContentUtils::IsCallerChrome()) {
     Throw<true>(aCx, NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   JSObject* obj = WrapNode(aCx, aScope);
   if (obj && ChromeOnlyAccess() &&
-      !nsContentUtils::IsSystemPrincipal(NodePrincipal()))
+      !nsContentUtils::IsSystemPrincipal(NodePrincipal()) &&
+      xpc::AllowXBLScope(js::GetContextCompartment(aCx)))
   {
     // Create a new wrapper and cache it.
     JSAutoCompartment ac(aCx, obj);
     JSObject* wrapper = xpc::WrapperFactory::WrapSOWObject(aCx, obj);
     if (!wrapper) {
       ClearWrapper();
       return nullptr;
     }
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -2070,17 +2070,20 @@ XPCWrappedNative::GetSameCompartmentSecu
     if (xpc::AccessCheck::isChrome(cxCompartment)) {
         MOZ_ASSERT(wrapper == NULL);
         return flat;
     }
 
     // Check the possibilities. Note that we need to check for null in each
     // case in order to distinguish between the 'no need for wrapper' and
     // 'wrapping failed' cases.
-    if (NeedsSOW()) {
+    //
+    // NB: We don't make SOWs for remote XUL domains where XBL scopes are
+    // disallowed.
+    if (NeedsSOW() && xpc::AllowXBLScope(js::GetContextCompartment(cx))) {
         wrapper = xpc::WrapperFactory::WrapSOWObject(cx, flat);
         if (!wrapper)
             return NULL;
     } else if (xpc::WrapperFactory::IsComponentsObject(flat)) {
         wrapper = xpc::WrapperFactory::WrapComponentsObject(cx, flat);
         if (!wrapper)
             return NULL;
     }
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -387,21 +387,23 @@ WrapperFactory::Rewrap(JSContext *cx, Ha
         wrapper = &CrossCompartmentWrapper::singleton;
 
     // If this is a chrome object being exposed to content without Xrays, use
     // a COW.
     } else if (originIsChrome && !targetIsChrome && xrayType == NotXray) {
         wrapper = &ChromeObjectWrapper::singleton;
 
     // If content is accessing a Components object or NAC, we need a special filter,
-    // even if the object is same origin.
+    // even if the object is same origin. Note that we allow access to NAC for
+    // remote-XUL whitelisted domains, since they don't have XBL scopes.
     } else if (IsComponentsObject(obj) && !AccessCheck::isChrome(target)) {
         wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
                                     ComponentsObjectPolicy>::singleton;
     } else if (AccessCheck::needsSystemOnlyWrapper(obj) &&
+               xpc::AllowXBLScope(target) &&
                !(targetIsChrome || (targetSubsumesOrigin && nsContentUtils::IsCallerXBL())))
     {
         wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
                                     OnlyIfSubjectIsSystem>::singleton;
     }
 
     // Normally, a non-xrayable non-waived content object that finds itself in
     // a privileged scope is wrapped with a CrossCompartmentWrapper, even though
@@ -558,16 +560,21 @@ WrapperFactory::WaiveXrayAndWrap(JSConte
     return JS_WrapValue(cx, vp);
 }
 
 JSObject *
 WrapperFactory::WrapSOWObject(JSContext *cx, JSObject *objArg)
 {
     RootedObject obj(cx, objArg);
     RootedObject proto(cx);
+
+    // If we're not allowing XBL scopes, that means we're running as a remote
+    // XUL domain, in which we can't have SOWs. We should never be called in
+    // that case.
+    MOZ_ASSERT(xpc::AllowXBLScope(js::GetContextCompartment(cx)));
     if (!JS_GetPrototype(cx, obj, proto.address()))
         return NULL;
     JSObject *wrapperObj =
         Wrapper::New(cx, obj, proto, JS_GetGlobalForObject(cx, obj),
                      &FilteringWrapper<SameCompartmentSecurityWrapper,
                      OnlyIfSubjectIsSystem>::singleton);
     return wrapperObj;
 }