Bug 1512029 part 4 - Use the privileged junk scope's compartment for sandboxes created with the system principal. r=bzbarsky
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 03 Jan 2019 10:02:31 +0000
changeset 509486 9ba6855363340fcf0a510c5bf4554adae4f1519e
parent 509485 ea7f319717df7ae012cb57b70859fa5531ef5a0b
child 509487 ba3a14b06003a7b437160c217bf732f27df2edab
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1512029
milestone66.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 1512029 part 4 - Use the privileged junk scope's compartment for sandboxes created with the system principal. r=bzbarsky Differential Revision: https://phabricator.services.mozilla.com/D14255
js/xpconnect/src/Sandbox.cpp
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1040,26 +1040,33 @@ nsresult xpc::CreateSandboxObject(JSCont
   JS::RealmOptions realmOptions;
 
   auto& creationOptions = realmOptions.creationOptions();
 
   // XXXjwatt: Consider whether/when sandboxes should be able to see
   // [SecureContext] API (bug 1273687).  In that case we'd call
   // creationOptions.setSecureContext(true).
 
-  if (principal == nsXPConnect::SystemPrincipal()) {
+  bool isSystemPrincipal = principal == nsXPConnect::SystemPrincipal();
+  if (isSystemPrincipal) {
     creationOptions.setClampAndJitterTime(false);
   }
 
   xpc::SetPrefableRealmOptions(realmOptions);
   if (options.sameZoneAs) {
     creationOptions.setNewCompartmentInExistingZone(
         js::UncheckedUnwrap(options.sameZoneAs));
   } else if (options.freshZone) {
     creationOptions.setNewCompartmentAndZone();
+  } else if (isSystemPrincipal && !options.invisibleToDebugger &&
+             !options.freshCompartment) {
+    // Use a shared system compartment for system-principal sandboxes that don't
+    // require invisibleToDebugger (this is a compartment property, see bug
+    // 1482215).
+    creationOptions.setExistingCompartment(xpc::PrivilegedJunkScope());
   } else {
     creationOptions.setNewCompartmentInSystemZone();
   }
 
   creationOptions.setInvisibleToDebugger(options.invisibleToDebugger)
       .setTrace(TraceXPCGlobal);
 
   realmOptions.behaviors().setDiscardSource(options.discardSource);
@@ -1067,37 +1074,52 @@ nsresult xpc::CreateSandboxObject(JSCont
   const js::Class* clasp = &SandboxClass;
 
   RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, js::Jsvalify(clasp),
                                                    principal, realmOptions));
   if (!sandbox) {
     return NS_ERROR_FAILURE;
   }
 
-  CompartmentPrivate* priv = CompartmentPrivate::Get(sandbox);
-  priv->allowWaivers = options.allowWaivers;
-  priv->isWebExtensionContentScript = options.isWebExtensionContentScript;
-  priv->isContentXBLCompartment = options.isContentXBLScope;
-  priv->isUAWidgetCompartment = options.isUAWidgetScope;
-
   // Use exclusive expandos for non-system-principal sandboxes.
-  if (principal != nsXPConnect::SystemPrincipal()) {
-    priv->hasExclusiveExpandos = true;
-  }
+  bool hasExclusiveExpandos = !isSystemPrincipal;
 
   // Set up the wantXrays flag, which indicates whether xrays are desired even
   // for same-origin access.
   //
   // This flag has historically been ignored for chrome sandboxes due to
   // quirks in the wrapping implementation that have now been removed. Indeed,
   // same-origin Xrays for chrome->chrome access seems a bit superfluous.
   // Arguably we should just flip the default for chrome and still honor the
   // flag, but such a change would break code in subtle ways for minimal
   // benefit. So we just switch it off here.
-  priv->wantXrays = AccessCheck::isChrome(sandbox) ? false : options.wantXrays;
+  bool wantXrays = AccessCheck::isChrome(sandbox) ? false : options.wantXrays;
+
+  if (creationOptions.compartmentSpecifier() ==
+      JS::CompartmentSpecifier::ExistingCompartment) {
+    // Make sure the compartment we're reusing has flags that match what we
+    // would set on a new compartment.
+    CompartmentPrivate* priv = CompartmentPrivate::Get(sandbox);
+    MOZ_RELEASE_ASSERT(priv->allowWaivers == options.allowWaivers);
+    MOZ_RELEASE_ASSERT(priv->isWebExtensionContentScript ==
+                       options.isWebExtensionContentScript);
+    MOZ_RELEASE_ASSERT(priv->isContentXBLCompartment ==
+                       options.isContentXBLScope);
+    MOZ_RELEASE_ASSERT(priv->isUAWidgetCompartment == options.isUAWidgetScope);
+    MOZ_RELEASE_ASSERT(priv->hasExclusiveExpandos == hasExclusiveExpandos);
+    MOZ_RELEASE_ASSERT(priv->wantXrays == wantXrays);
+  } else {
+    CompartmentPrivate* priv = CompartmentPrivate::Get(sandbox);
+    priv->allowWaivers = options.allowWaivers;
+    priv->isWebExtensionContentScript = options.isWebExtensionContentScript;
+    priv->isContentXBLCompartment = options.isContentXBLScope;
+    priv->isUAWidgetCompartment = options.isUAWidgetScope;
+    priv->hasExclusiveExpandos = hasExclusiveExpandos;
+    priv->wantXrays = wantXrays;
+  }
 
   {
     JSAutoRealm ar(cx, sandbox);
 
     // This creates a SandboxPrivate and passes ownership of it to |sandbox|.
     SandboxPrivate::Create(principal, sandbox);
 
     // Ensure |Object.prototype| is instantiated before prototype-