Bug 1337543 P0 Sanitize the nsIPrincipal used to register a service worker to ensure CSP is not persisted. r=baku
authorBen Kelly <ben@wanderview.com>
Tue, 14 Feb 2017 10:06:38 -0500
changeset 342803 f2d6e4198d851a595746ca1deb222b8f441edcf6
parent 342802 45b99d7a75826ad0e7906a4215b926032d76ff9e
child 342804 786d2c5cba9c17f47b3c306233914fe4b905e0f4
push id31363
push userkwierso@gmail.com
push dateTue, 14 Feb 2017 21:12:30 +0000
treeherdermozilla-central@1060668405a9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1337543
milestone54.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 1337543 P0 Sanitize the nsIPrincipal used to register a service worker to ensure CSP is not persisted. r=baku
dom/workers/ServiceWorkerManager.cpp
dom/workers/ServiceWorkerRegisterJob.cpp
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -3201,29 +3201,58 @@ ServiceWorkerManager::GetRegistration(co
   return reg.forget();
 }
 
 already_AddRefed<ServiceWorkerRegistrationInfo>
 ServiceWorkerManager::CreateNewRegistration(const nsCString& aScope,
                                             nsIPrincipal* aPrincipal,
                                             nsLoadFlags aLoadFlags)
 {
+  nsresult rv;
+
 #ifdef DEBUG
   AssertIsOnMainThread();
   nsCOMPtr<nsIURI> scopeURI;
-  nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), aScope, nullptr, nullptr);
+  rv = NS_NewURI(getter_AddRefs(scopeURI), aScope, nullptr, nullptr);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 
   RefPtr<ServiceWorkerRegistrationInfo> tmp =
     GetRegistration(aPrincipal, aScope);
   MOZ_ASSERT(!tmp);
 #endif
 
+  // The environment that registers the document may have some CSP applied
+  // to its principal.  This should not be inherited by the registration
+  // itself or the worker it creates.  To avoid confusion in callsites
+  // downstream we strip the CSP from the principal now.
+  //
+  // Unfortunately there is no API to clone a principal without its CSP.  To
+  // achieve the same thing we serialize to the IPC PrincipalInfo type and
+  // back to an nsIPrincipal.
+  PrincipalInfo principalInfo;
+  rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIPrincipal> cleanPrincipal =
+    PrincipalInfoToPrincipal(principalInfo, &rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return nullptr;
+  }
+
+  // Verify that we do not have any CSP set on our principal "clone".
+#if defined(DEBUG) || !defined(RELEASE_OR_BETA)
+  nsCOMPtr<nsIContentSecurityPolicy> csp;
+  MOZ_ALWAYS_SUCCEEDS(cleanPrincipal->GetCsp(getter_AddRefs(csp)));
+  MOZ_DIAGNOSTIC_ASSERT(!csp);
+#endif
+
   RefPtr<ServiceWorkerRegistrationInfo> registration =
-    new ServiceWorkerRegistrationInfo(aScope, aPrincipal, aLoadFlags);
+    new ServiceWorkerRegistrationInfo(aScope, cleanPrincipal, aLoadFlags);
   // From now on ownership of registration is with
   // mServiceWorkerRegistrationInfos.
   AddScopeAndRegistration(aScope, registration);
   return registration.forget();
 }
 
 void
 ServiceWorkerManager::MaybeRemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration)
--- a/dom/workers/ServiceWorkerRegisterJob.cpp
+++ b/dom/workers/ServiceWorkerRegisterJob.cpp
@@ -52,16 +52,20 @@ ServiceWorkerRegisterJob::AsyncExecute()
     if (newest && mScriptSpec.Equals(newest->ScriptSpec()) && isSameLoadFlags) {
       SetRegistration(registration);
       Finish(NS_OK);
       return;
     }
   } else {
     registration = swm->CreateNewRegistration(mScope, mPrincipal,
                                               GetLoadFlags());
+    if (!registration) {
+      FailUpdateJob(NS_ERROR_DOM_ABORT_ERR);
+      return;
+    }
   }
 
   SetRegistration(registration);
   Update();
 }
 
 ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob()
 {