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 275373 dc78e255ac9b2557121382afee8d1591f483e4c5
parent 275372 75e056cdd421db46c419d59a2b73af3eb2876fce
child 275374 177144e23d022a2ec3ccba07ce99c2690dea1ecd
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley, lmandel
bugs1174950
milestone40.0
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
@@ -8976,16 +8976,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);
@@ -9021,17 +9033,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;
   }