Bug 1174950 - Nuke wrappers from compartments with expanded principals to non-system windows. r=bholley, a=lmandel
authorAndrew McCreight <continuation@gmail.com>
Mon, 13 Jul 2015 12:59:00 +0200
changeset 268902 365181b8498590a7d141b8cfe45c199f1c4b4ad3
parent 268901 3b0c7e2563c124693f39eacb5d7df9e0bd7b2737
child 268903 63e39f82b3169a3e2d8f0464d8e16367fc932c8f
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-esr52@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley, lmandel
bugs1174950
milestone41.0a2
Bug 1174950 - Nuke wrappers from compartments with expanded principals to non-system windows. r=bholley, a=lmandel This extends the hueyfix to the case where a sandbox with expanded principals is leaked, for instance by an addon, and ends up entraining a content window. This fix prevents the leak of the content window, but not the sandbox.
dom/base/nsGlobalWindow.cpp
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -8643,16 +8643,28 @@ nsGlobalWindow::NotifyDOMWindowDestroyed
     services::GetObserverService();
   if (observerService) {
     observerService->
       NotifyObservers(ToSupports(aWindow),
                       DOM_WINDOW_DESTROYED_TOPIC, nullptr);
   }
 }
 
+// Try to match compartments that are not web content by matching compartments
+// with principals that are either the system principal or an expanded principal.
+// This may not return true for all non-web-content compartments.
+struct BrowserCompartmentMatcher : public js::CompartmentFilter {
+  virtual bool match(JSCompartment* c) const override
+  {
+    nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(c));
+    return nsContentUtils::IsSystemOrExpandedPrincipal(pc);
+  }
+};
+
+
 class WindowDestroyedEvent : public nsRunnable
 {
 public:
   WindowDestroyedEvent(nsPIDOMWindow* aWindow, uint64_t aID,
                        const char* aTopic) :
     mID(aID), mTopic(aTopic)
   {
     mWindow = do_GetWeakReference(aWindow);
@@ -8688,17 +8700,17 @@ public:
                                   static_cast<nsGlobalWindow*>(window->GetCurrentInnerWindow());
       NS_ENSURE_TRUE(currentInner, NS_OK);
 
       AutoSafeJSContext cx;
       JS::Rooted<JSObject*> obj(cx, currentInner->FastGetGlobalJSObject());
       // We only want to nuke wrappers for the chrome->content case
       if (obj && !js::IsSystemCompartment(js::GetObjectCompartment(obj))) {
         js::NukeCrossCompartmentWrappers(cx,
-                                         js::ChromeCompartmentsOnly(),
+                                         BrowserCompartmentMatcher(),
                                          js::SingleCompartment(js::GetObjectCompartment(obj)),
                                          window->IsInnerWindow() ? js::DontNukeWindowReferences :
                                                                    js::NukeWindowReferences);
       }
     }
 
     return NS_OK;
   }