Bug 1560178 - disallow unsafe loads in the parent, r=bzbarsky a=RyanVM
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Fri, 12 Jul 2019 16:29:01 +0000
changeset 544674 d5c1f040691a4b986aa7fa03d9127c34b72c57d9
parent 544673 a188fb7e00d9d6d25b08d93bfece15498ed1bef8
child 544675 cbf0daa7f713e2d86bb0bb8ea823dbc396bb8aba
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky, RyanVM
bugs1560178
milestone69.0
Bug 1560178 - disallow unsafe loads in the parent, r=bzbarsky a=RyanVM Differential Revision: https://phabricator.services.mozilla.com/D36312
docshell/base/nsDocShell.cpp
modules/libpref/init/StaticPrefList.h
modules/libpref/init/all.js
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1566,18 +1566,18 @@ nsDocShell::GetUseRemoteSubframes(bool* 
 }
 
 NS_IMETHODIMP
 nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) {
   static bool annotated = false;
 
   if (aUseRemoteSubframes && !annotated) {
     annotated = true;
-    CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::DOMFissionEnabled,
-                                       true);
+    CrashReporter::AnnotateCrashReport(
+        CrashReporter::Annotation::DOMFissionEnabled, true);
   }
 
   // Don't allow non-remote tabs with remote subframes.
   if (NS_WARN_IF(aUseRemoteSubframes && !mUseRemoteTabs)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   mUseRemoteSubframes = aUseRemoteSubframes;
@@ -9542,16 +9542,96 @@ nsresult nsDocShell::InternalLoad(nsDocS
     rv = browserChrome3->ShouldLoadURI(
         this, aLoadState->URI(), referrer, !!aLoadState->PostDataStream(),
         aLoadState->TriggeringPrincipal(), aLoadState->Csp(), &shouldLoad);
     if (NS_SUCCEEDED(rv) && !shouldLoad) {
       return NS_OK;
     }
   }
 
+  // In e10s, in the parent process, we refuse to load anything other than
+  // "safe" resources that we ship or trust enough to give "special" URLs.
+  if (XRE_IsE10sParentProcess()) {
+    nsCOMPtr<nsIURI> uri = aLoadState->URI();
+    do {
+      bool canLoadInParent = false;
+      if (NS_SUCCEEDED(NS_URIChainHasFlags(
+              uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent)) &&
+          canLoadInParent) {
+        // We allow UI resources.
+        break;
+      }
+      // For about: and extension-based URIs, which don't get
+      // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present.
+      while (uri && uri->SchemeIs("view-source")) {
+        nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri);
+        if (nested) {
+          nested->GetInnerURI(getter_AddRefs(uri));
+        } else {
+          break;
+        }
+      }
+      // Allow about: URIs, and allow moz-extension ones if we're running
+      // extension content in the parent process.
+      if (!uri || uri->SchemeIs("about") ||
+          (!StaticPrefs::extensions_webextensions_remote() &&
+           uri->SchemeIs("moz-extension"))) {
+        break;
+      }
+      nsAutoCString scheme;
+      uri->GetScheme(scheme);
+      // Allow ext+foo URIs (extension-registered custom protocols). See
+      // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers
+      if (StringBeginsWith(scheme, NS_LITERAL_CSTRING("ext+")) &&
+          !StaticPrefs::extensions_webextensions_remote()) {
+        break;
+      }
+      // This next bit is... awful. Basically, about:addons used to load the
+      // discovery pane remotely. Allow for that, if that's actually the state
+      // we're in (which is no longer the default at time of writing, but still
+      // tested). https://bugzilla.mozilla.org/show_bug.cgi?id=1565606 covers
+      // removing this atrocity.
+      nsCOMPtr<nsIWebNavigation> parent(do_QueryInterface(mParent));
+      if (parent) {
+        nsCOMPtr<nsIURI> parentURL;
+        parent->GetCurrentURI(getter_AddRefs(parentURL));
+        if (parentURL &&
+            parentURL->GetSpecOrDefault().EqualsLiteral("about:addons") &&
+            (!Preferences::GetBool("extensions.htmlaboutaddons.enabled",
+                                   true) ||
+             !Preferences::GetBool(
+                 "extensions.htmlaboutaddons.discover.enabled", true))) {
+          nsCString discoveryURLString;
+          Preferences::GetCString("extensions.webservice.discoverURL",
+                                  discoveryURLString);
+          nsCOMPtr<nsIURI> discoveryURL;
+          NS_NewURI(getter_AddRefs(discoveryURL), discoveryURLString);
+
+          nsAutoCString discoveryPrePath;
+          if (discoveryURL) {
+            discoveryURL->GetPrePath(discoveryPrePath);
+          }
+
+          nsAutoCString requestedPrePath;
+          uri->GetPrePath(requestedPrePath);
+          // So allow the discovery path to load inside about:addons.
+          if (discoveryPrePath.Equals(requestedPrePath)) {
+            break;
+          }
+        }
+      }
+      // Final exception for some legacy automated tests:
+      if (xpc::IsInAutomation() &&
+          Preferences::GetBool("security.allow_unsafe_parent_loads", false)) {
+        break;
+      }
+      return NS_ERROR_FAILURE;
+    } while (0);
+  }
+
   // Whenever a top-level browsing context is navigated, the user agent MUST
   // lock the orientation of the document to the document's default
   // orientation. We don't explicitly check for a top-level browsing context
   // here because orientation is only set on top-level browsing contexts.
   if (OrientationLock() != hal::eScreenOrientation_None) {
 #ifdef DEBUG
     nsCOMPtr<nsIDocShellTreeItem> parent;
     GetSameTypeParent(getter_AddRefs(parent));
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -2644,16 +2644,25 @@ VARCACHE_PREF(
 // changes applied in Bug 152591 (to be removed as part of Bug 1537753).
 VARCACHE_PREF(
   Live,
   "extensions.cookiesBehavior.overrideOnTopLevel",
   extensions_cookiesBehavior_overrideOnTopLevel,
   bool, false
 )
 
+// This pref governs whether we run webextensions in a separate process (true)
+// or the parent/main process (false)
+VARCACHE_PREF(
+  Live,
+  "extensions.webextensions.remote",
+  extensions_webextensions_remote,
+  bool, false
+)
+
 //---------------------------------------------------------------------------
 // Prefs starting with "fission."
 //---------------------------------------------------------------------------
 
 // This pref has no effect within fission windows, it only controls the
 // behaviour within non-fission windows.
 VARCACHE_PREF(
   Live,
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4847,17 +4847,16 @@ pref("extensions.legacy.enabled", true);
 
 // Other webextensions prefs
 pref("extensions.webextensions.keepStorageOnUninstall", false);
 pref("extensions.webextensions.keepUuidOnUninstall", false);
 // Redirect basedomain used by identity api
 pref("extensions.webextensions.identity.redirectDomain", "extensions.allizom.org");
 pref("extensions.webextensions.restrictedDomains", "accounts-static.cdn.mozilla.net,accounts.firefox.com,addons.cdn.mozilla.net,addons.mozilla.org,api.accounts.firefox.com,content.cdn.mozilla.net,discovery.addons.mozilla.org,install.mozilla.org,oauth.accounts.firefox.com,profile.accounts.firefox.com,support.mozilla.org,sync.services.mozilla.com");
 
-pref("extensions.webextensions.remote", false);
 // Whether or not the moz-extension resource loads are remoted. For debugging
 // purposes only. Setting this to false will break moz-extension URI loading
 // unless other process sandboxing and extension remoting prefs are changed.
 pref("extensions.webextensions.protocol.remote", true);
 
 // Enable tab hiding API by default.
 pref("extensions.webextensions.tabhide.enabled", true);