Bug 1333573 P5 Validate that final channel load principal does not change. r=baku
authorBen Kelly <ben@wanderview.com>
Tue, 07 Feb 2017 10:28:39 -0500
changeset 387839 fad843873cf7f84dc678a3eb8d3042f6c16792b7
parent 387838 db60240c86478ab329048be0c124d00e8dbf8796
child 387840 d60942e5c631de61156ad115b40563846b396fd8
push id7198
push userjlorenzo@mozilla.com
push dateTue, 18 Apr 2017 12:07:49 +0000
treeherdermozilla-beta@d57aa49c3948 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1333573
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 1333573 P5 Validate that final channel load principal does not change. r=baku
dom/workers/ScriptLoader.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
dom/workers/Workers.h
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -1124,16 +1124,18 @@ private:
     // worker's primary script.
     if (IsMainWorkerScript()) {
       // Take care of the base URI first.
       mWorkerPrivate->SetBaseURI(finalURI);
 
       // Store the channel info if needed.
       mWorkerPrivate->InitChannelInfo(channel);
 
+      MOZ_DIAGNOSTIC_ASSERT(mWorkerPrivate->FinalChannelPrincipalIsValid(channel));
+
       // We did inherit CSP in bug 1223647. If we do not already have a CSP, we
       // should get it from the HTTP headers on the worker script.
       if (!mWorkerPrivate->GetCSP() && CSPService::sCSPEnabled) {
         NS_ConvertASCIItoUTF16 cspHeaderValue(tCspHeaderValue);
         NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue);
 
         nsIPrincipal* principal = mWorkerPrivate->GetPrincipal();
         MOZ_ASSERT(principal, "Should not be null");
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1886,20 +1886,24 @@ WorkerLoadInfo::SetPrincipalOnMainThread
   mPrincipalInfo = new PrincipalInfo();
   mOriginAttributes = nsContentUtils::GetOriginAttributes(aLoadGroup);
 
   MOZ_ALWAYS_SUCCEEDS(
     PrincipalToPrincipalInfo(aPrincipal, mPrincipalInfo));
 }
 
 nsresult
-WorkerLoadInfo::SetPrincipalFromChannel(nsIChannel* aChannel)
+WorkerLoadInfo::GetPrincipalAndLoadGroupFromChannel(nsIChannel* aChannel,
+                                                    nsIPrincipal** aPrincipalOut,
+                                                    nsILoadGroup** aLoadGroupOut)
 {
   AssertIsOnMainThread();
   MOZ_DIAGNOSTIC_ASSERT(aChannel);
+  MOZ_DIAGNOSTIC_ASSERT(aPrincipalOut);
+  MOZ_DIAGNOSTIC_ASSERT(aLoadGroupOut);
 
   // Initial triggering principal should be set
   MOZ_DIAGNOSTIC_ASSERT(mPrincipal);
 
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   MOZ_DIAGNOSTIC_ASSERT(ssm);
 
   nsCOMPtr<nsIPrincipal> channelPrincipal;
@@ -1942,20 +1946,69 @@ WorkerLoadInfo::SetPrincipalFromChannel(
       }
     }
   }
 
   // The principal can change, but it should still match the original
   // load group's appId and browser element flag.
   MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(channelLoadGroup, channelPrincipal));
 
-  SetPrincipalOnMainThread(channelPrincipal, channelLoadGroup);
+  channelPrincipal.forget(aPrincipalOut);
+  channelLoadGroup.forget(aLoadGroupOut);
+
+  return NS_OK;
+}
+
+nsresult
+WorkerLoadInfo::SetPrincipalFromChannel(nsIChannel* aChannel)
+{
+  AssertIsOnMainThread();
+
+  nsCOMPtr<nsIPrincipal> principal;
+  nsCOMPtr<nsILoadGroup> loadGroup;
+  nsresult rv = GetPrincipalAndLoadGroupFromChannel(aChannel,
+                                                    getter_AddRefs(principal),
+                                                    getter_AddRefs(loadGroup));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  SetPrincipalOnMainThread(principal, loadGroup);
   return NS_OK;
 }
 
+#if defined(DEBUG) || !defined(RELEASE_OR_BETA)
+bool
+WorkerLoadInfo::FinalChannelPrincipalIsValid(nsIChannel* aChannel)
+{
+  AssertIsOnMainThread();
+
+  nsCOMPtr<nsIPrincipal> principal;
+  nsCOMPtr<nsILoadGroup> loadGroup;
+  nsresult rv = GetPrincipalAndLoadGroupFromChannel(aChannel,
+                                                    getter_AddRefs(principal),
+                                                    getter_AddRefs(loadGroup));
+  NS_ENSURE_SUCCESS(rv, false);
+
+
+  // Verify that the channel is still a null principal.  We don't care
+  // if these are the exact same null principal object, though.  From
+  // the worker's perspective its the same effect.
+  if (principal->GetIsNullPrincipal() && mPrincipal->GetIsNullPrincipal()) {
+    return true;
+  }
+
+  // Otherwise we require exact equality.  Redirects can happen, but they
+  // are not allowed to change our principal.
+  if (principal->Equals(mPrincipal)) {
+    return true;
+  }
+
+  return false;
+}
+#endif // defined(DEBUG) || !defined(RELEASE_OR_BETA)
+
 template <class Derived>
 class WorkerPrivateParent<Derived>::EventTarget final
   : public nsIEventTarget
 {
   // This mutex protects mWorkerPrivate and must be acquired *before* the
   // WorkerPrivate's mutex whenever they must both be held.
   mozilla::Mutex mMutex;
   WorkerPrivate* mWorkerPrivate;
@@ -3764,16 +3817,25 @@ WorkerPrivateParent<Derived>::SetPrincip
 
 template <class Derived>
 nsresult
 WorkerPrivateParent<Derived>::SetPrincipalFromChannel(nsIChannel* aChannel)
 {
   return mLoadInfo.SetPrincipalFromChannel(aChannel);
 }
 
+#if defined(DEBUG) || !defined(RELEASE_OR_BETA)
+template <class Derived>
+bool
+WorkerPrivateParent<Derived>::FinalChannelPrincipalIsValid(nsIChannel* aChannel)
+{
+  return mLoadInfo.FinalChannelPrincipalIsValid(aChannel);
+}
+#endif
+
 template <class Derived>
 void
 WorkerPrivateParent<Derived>::UpdateOverridenLoadGroup(nsILoadGroup* aBaseLoadGroup)
 {
   AssertIsOnMainThread();
 
   // The load group should have been overriden at init time.
   mLoadInfo.mInterfaceRequestor->MaybeAddTabChild(aBaseLoadGroup);
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -611,16 +611,21 @@ public:
   }
 
   void
   SetPrincipalOnMainThread(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
 
   nsresult
   SetPrincipalFromChannel(nsIChannel* aChannel);
 
+#if defined(DEBUG) || !defined(RELEASE_OR_BETA)
+  bool
+  FinalChannelPrincipalIsValid(nsIChannel* aChannel);
+#endif
+
   bool
   UsesSystemPrincipal() const
   {
     return mLoadInfo.mPrincipalIsSystem;
   }
 
   const PrincipalInfo&
   GetPrincipalInfo() const
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -277,17 +277,27 @@ struct WorkerLoadInfo
   ~WorkerLoadInfo();
 
   void StealFrom(WorkerLoadInfo& aOther);
 
   void
   SetPrincipalOnMainThread(nsIPrincipal* aPrincipal, nsILoadGroup* aLoadGroup);
 
   nsresult
+  GetPrincipalAndLoadGroupFromChannel(nsIChannel* aChannel,
+                                      nsIPrincipal** aPrincipalOut,
+                                      nsILoadGroup** aLoadGroupOut);
+
+  nsresult
   SetPrincipalFromChannel(nsIChannel* aChannel);
+
+#if defined(DEBUG) || !defined(RELEASE_OR_BETA)
+  bool
+  FinalChannelPrincipalIsValid(nsIChannel* aChannel);
+#endif
 };
 
 // All of these are implemented in RuntimeService.cpp
 
 void
 CancelWorkersForWindow(nsPIDOMWindowInner* aWindow);
 
 void