[tor-commits] [tor-browser/tor-browser-38.1.0esr-5.x-1] Bug 16300: Isolate Broadcast Channels to first party.

mikeperry at torproject.org mikeperry at torproject.org
Thu Jun 25 22:30:37 UTC 2015


commit 8a7950b34812259d857f65daaae766174dc48ce5
Author: Kathy Brade <brade at pearlcrescent.com>
Date:   Fri Jun 19 10:53:28 2015 -0400

    Bug 16300: Isolate Broadcast Channels to first party.
    
    Note that when the privacy.thirdparty.isolate pref. is set to 1 or 2,
    we disable use of Broadcast Channels by SharedWorkers since we cannot
    obtain the isolation host.
---
 dom/broadcastchannel/BroadcastChannel.cpp        |   77 ++++++++++++++++++++--
 dom/broadcastchannel/BroadcastChannel.h          |    2 +
 dom/broadcastchannel/BroadcastChannelParent.cpp  |    7 +-
 dom/broadcastchannel/BroadcastChannelParent.h    |    3 +
 dom/broadcastchannel/BroadcastChannelService.cpp |   11 +++-
 dom/broadcastchannel/BroadcastChannelService.h   |    1 +
 ipc/glue/BackgroundChildImpl.cpp                 |    1 +
 ipc/glue/BackgroundChildImpl.h                   |    1 +
 ipc/glue/BackgroundParentImpl.cpp                |    5 +-
 ipc/glue/BackgroundParentImpl.h                  |    2 +
 ipc/glue/PBackground.ipdl                        |    3 +-
 11 files changed, 102 insertions(+), 11 deletions(-)

diff --git a/dom/broadcastchannel/BroadcastChannel.cpp b/dom/broadcastchannel/BroadcastChannel.cpp
index 6d16c2d..92ec729 100644
--- a/dom/broadcastchannel/BroadcastChannel.cpp
+++ b/dom/broadcastchannel/BroadcastChannel.cpp
@@ -20,6 +20,7 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsServiceManagerUtils.h"
 #include "nsISupportsPrimitives.h"
+#include "mozIThirdPartyUtil.h"
 
 #ifdef XP_WIN
 #undef PostMessage
@@ -105,6 +106,44 @@ GetOrigin(nsIPrincipal* aPrincipal, nsAString& aOrigin, ErrorResult& aRv)
   appsService->GetManifestURLByLocalId(appId, aOrigin);
 }
 
+bool
+IsFirstPartyIsolationEnabled()
+{
+  return 0 != mozilla::Preferences::GetInt("privacy.thirdparty.isolate");
+}
+
+void
+GetFirstPartyHost(nsIDocument* aDoc, nsAString& aFirstPartyHost,
+                  ErrorResult& aRv)
+{
+  if (!aDoc) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc =
+    do_GetService(THIRDPARTYUTIL_CONTRACTID);
+  nsCOMPtr<nsIURI> firstPartyIsolationURI;
+  nsresult rv = thirdPartySvc->GetFirstPartyIsolationURI(nullptr, aDoc,
+                                    getter_AddRefs(firstPartyIsolationURI));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    aRv.Throw(rv);
+    return;
+  }
+
+  if (firstPartyIsolationURI) {
+    nsAutoCString hostCStr;
+    rv = thirdPartySvc->GetFirstPartyHostForIsolation(firstPartyIsolationURI,
+                                                      hostCStr);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      aRv.Throw(rv);
+      return;
+    }
+
+    aFirstPartyHost = NS_ConvertUTF8toUTF16(hostCStr);
+  }
+}
+
 nsIPrincipal*
 GetPrincipalFromWorkerPrivate(WorkerPrivate* aWorkerPrivate)
 {
@@ -126,11 +165,13 @@ class InitializeRunnable final : public WorkerMainThreadRunnable
 {
 public:
   InitializeRunnable(WorkerPrivate* aWorkerPrivate, nsAString& aOrigin,
+                     nsAString& aFirstPartyHost,
                      PrincipalInfo& aPrincipalInfo, bool& aPrivateBrowsing,
                      ErrorResult& aRv)
     : WorkerMainThreadRunnable(aWorkerPrivate)
     , mWorkerPrivate(GetCurrentThreadWorkerPrivate())
     , mOrigin(aOrigin)
+    , mFirstPartyHost(aFirstPartyHost)
     , mPrincipalInfo(aPrincipalInfo)
     , mPrivateBrowsing(aPrivateBrowsing)
     , mRv(aRv)
@@ -175,9 +216,16 @@ public:
       wp = wp->GetParent();
     }
 
+    bool isIsolationEnabled = IsFirstPartyIsolationEnabled();
+
     // Window doesn't exist for some kind of workers (eg: SharedWorkers)
     nsPIDOMWindow* window = wp->GetWindow();
     if (!window) {
+      // If we lack a window and first party isolation is enabled, disallow
+      // use of Broadcast Channels. This is the safe thing to do, e.g., if
+      // a SharedWorker is being used.
+      if (isIsolationEnabled)
+        mRv.Throw(NS_ERROR_FAILURE);
       return true;
     }
 
@@ -189,12 +237,20 @@ public:
       doc->DisallowBFCaching();
     }
 
+    if (isIsolationEnabled) {
+      GetFirstPartyHost(doc, mFirstPartyHost, mRv);
+      if (NS_WARN_IF(mRv.Failed())) {
+        return true;
+      }
+    }
+
     return true;
   }
 
 private:
   WorkerPrivate* mWorkerPrivate;
   nsAString& mOrigin;
+  nsAString& mFirstPartyHost;
   PrincipalInfo& mPrincipalInfo;
   bool& mPrivateBrowsing;
   ErrorResult& mRv;
@@ -401,12 +457,14 @@ BroadcastChannel::IsEnabled(JSContext* aCx, JSObject* aGlobal)
 BroadcastChannel::BroadcastChannel(nsPIDOMWindow* aWindow,
                                    const PrincipalInfo& aPrincipalInfo,
                                    const nsAString& aOrigin,
+                                   const nsAString& aFirstPartyHost,
                                    const nsAString& aChannel,
                                    bool aPrivateBrowsing)
   : DOMEventTargetHelper(aWindow)
   , mWorkerFeature(nullptr)
   , mPrincipalInfo(new PrincipalInfo(aPrincipalInfo))
   , mOrigin(aOrigin)
+  , mFirstPartyHost(aFirstPartyHost)
   , mChannel(aChannel)
   , mPrivateBrowsing(aPrivateBrowsing)
   , mIsKeptAlive(false)
@@ -437,6 +495,7 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
   // Window is null in workers.
 
   nsAutoString origin;
+  nsAutoString firstPartyHost;
   PrincipalInfo principalInfo;
   bool privateBrowsing = false;
   WorkerPrivate* workerPrivate = nullptr;
@@ -483,14 +542,21 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
       // No bfcache when BroadcastChannel is used.
       doc->DisallowBFCaching();
     }
+
+    if (IsFirstPartyIsolationEnabled()) {
+      GetFirstPartyHost(doc, firstPartyHost, aRv);
+      if (NS_WARN_IF(aRv.Failed())) {
+        return nullptr;
+      }
+    }
   } else {
     JSContext* cx = aGlobal.Context();
     workerPrivate = GetWorkerPrivateFromContext(cx);
     MOZ_ASSERT(workerPrivate);
 
     nsRefPtr<InitializeRunnable> runnable =
-      new InitializeRunnable(workerPrivate, origin, principalInfo,
-                             privateBrowsing, aRv);
+      new InitializeRunnable(workerPrivate, origin, firstPartyHost,
+                             principalInfo, privateBrowsing, aRv);
     runnable->Dispatch(cx);
   }
 
@@ -499,8 +565,8 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal,
   }
 
   nsRefPtr<BroadcastChannel> bc =
-    new BroadcastChannel(window, principalInfo, origin, aChannel,
-                         privateBrowsing);
+    new BroadcastChannel(window, principalInfo, origin, firstPartyHost,
+                         aChannel, privateBrowsing);
 
   // Register this component to PBackground.
   PBackgroundChild* actor = BackgroundChild::GetForCurrentThread();
@@ -626,7 +692,8 @@ BroadcastChannel::ActorCreated(PBackgroundChild* aActor)
   }
 
   PBroadcastChannelChild* actor =
-    aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin, mChannel,
+    aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin,
+                                             mFirstPartyHost, mChannel,
                                              mPrivateBrowsing);
 
   mActor = static_cast<BroadcastChannelChild*>(actor);
diff --git a/dom/broadcastchannel/BroadcastChannel.h b/dom/broadcastchannel/BroadcastChannel.h
index 9208114..eac335f 100644
--- a/dom/broadcastchannel/BroadcastChannel.h
+++ b/dom/broadcastchannel/BroadcastChannel.h
@@ -92,6 +92,7 @@ private:
   BroadcastChannel(nsPIDOMWindow* aWindow,
                    const PrincipalInfo& aPrincipalInfo,
                    const nsAString& aOrigin,
+                   const nsAString& aFirstPartyHost,
                    const nsAString& aChannel,
                    bool aPrivateBrowsing);
 
@@ -112,6 +113,7 @@ private:
   nsAutoPtr<PrincipalInfo> mPrincipalInfo;
 
   nsString mOrigin;
+  nsString mFirstPartyHost;
   nsString mChannel;
   bool mPrivateBrowsing;
 
diff --git a/dom/broadcastchannel/BroadcastChannelParent.cpp b/dom/broadcastchannel/BroadcastChannelParent.cpp
index 7a1740d..f5fd9f3 100644
--- a/dom/broadcastchannel/BroadcastChannelParent.cpp
+++ b/dom/broadcastchannel/BroadcastChannelParent.cpp
@@ -18,10 +18,12 @@ namespace dom {
 
 BroadcastChannelParent::BroadcastChannelParent(
                                             const nsAString& aOrigin,
+                                            const nsAString& aFirstPartyHost,
                                             const nsAString& aChannel,
                                             bool aPrivateBrowsing)
   : mService(BroadcastChannelService::GetOrCreate())
   , mOrigin(aOrigin)
+  , mFirstPartyHost(aFirstPartyHost)
   , mChannel(aChannel)
   , mPrivateBrowsing(aPrivateBrowsing)
 {
@@ -43,7 +45,8 @@ BroadcastChannelParent::RecvPostMessage(const ClonedMessageData& aData)
     return false;
   }
 
-  mService->PostMessage(this, aData, mOrigin, mChannel, mPrivateBrowsing);
+  mService->PostMessage(this, aData, mOrigin, mFirstPartyHost,
+                        mChannel, mPrivateBrowsing);
   return true;
 }
 
@@ -79,12 +82,14 @@ BroadcastChannelParent::ActorDestroy(ActorDestroyReason aWhy)
 void
 BroadcastChannelParent::CheckAndDeliver(const ClonedMessageData& aData,
                                         const nsString& aOrigin,
+                                        const nsString& aFirstPartyHost,
                                         const nsString& aChannel,
                                         bool aPrivateBrowsing)
 {
   AssertIsOnBackgroundThread();
 
   if (aOrigin == mOrigin &&
+      aFirstPartyHost == mFirstPartyHost &&
       aChannel == mChannel &&
       aPrivateBrowsing == mPrivateBrowsing) {
     // We need to duplicate data only if we have blobs or if the manager of
diff --git a/dom/broadcastchannel/BroadcastChannelParent.h b/dom/broadcastchannel/BroadcastChannelParent.h
index 6ab3bb9..fc2d9de 100644
--- a/dom/broadcastchannel/BroadcastChannelParent.h
+++ b/dom/broadcastchannel/BroadcastChannelParent.h
@@ -24,11 +24,13 @@ class BroadcastChannelParent final : public PBroadcastChannelParent
 public:
   void CheckAndDeliver(const ClonedMessageData& aData,
                        const nsString& aOrigin,
+                       const nsString& aFirstPartyHost,
                        const nsString& aChannel,
                        bool aPrivateBrowsing);
 
 private:
   BroadcastChannelParent(const nsAString& aOrigin,
+                         const nsAString& aFirstPartyHost,
                          const nsAString& aChannel,
                          bool aPrivateBrowsing);
   ~BroadcastChannelParent();
@@ -42,6 +44,7 @@ private:
 
   nsRefPtr<BroadcastChannelService> mService;
   nsString mOrigin;
+  nsString mFirstPartyHost;
   nsString mChannel;
   bool mPrivateBrowsing;
 };
diff --git a/dom/broadcastchannel/BroadcastChannelService.cpp b/dom/broadcastchannel/BroadcastChannelService.cpp
index 7b73c72..debc111 100644
--- a/dom/broadcastchannel/BroadcastChannelService.cpp
+++ b/dom/broadcastchannel/BroadcastChannelService.cpp
@@ -83,11 +83,13 @@ struct MOZ_STACK_CLASS PostMessageData final
   PostMessageData(BroadcastChannelParent* aParent,
                   const ClonedMessageData& aData,
                   const nsAString& aOrigin,
+                  const nsAString& aFirstPartyHost,
                   const nsAString& aChannel,
                   bool aPrivateBrowsing)
     : mParent(aParent)
     , mData(aData)
     , mOrigin(aOrigin)
+    , mFirstPartyHost(aFirstPartyHost)
     , mChannel(aChannel)
     , mPrivateBrowsing(aPrivateBrowsing)
   {
@@ -117,6 +119,7 @@ struct MOZ_STACK_CLASS PostMessageData final
   const ClonedMessageData& mData;
   nsTArray<nsRefPtr<FileImpl>> mFiles;
   const nsString mOrigin;
+  const nsString mFirstPartyHost;
   const nsString mChannel;
   bool mPrivateBrowsing;
 };
@@ -131,8 +134,8 @@ PostMessageEnumerator(nsPtrHashKey<BroadcastChannelParent>* aKey, void* aPtr)
   MOZ_ASSERT(parent);
 
   if (parent != data->mParent) {
-    parent->CheckAndDeliver(data->mData, data->mOrigin, data->mChannel,
-                            data->mPrivateBrowsing);
+    parent->CheckAndDeliver(data->mData, data->mOrigin, data->mFirstPartyHost,
+                            data->mChannel, data->mPrivateBrowsing);
   }
 
   return PL_DHASH_NEXT;
@@ -144,6 +147,7 @@ void
 BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent,
                                      const ClonedMessageData& aData,
                                      const nsAString& aOrigin,
+                                     const nsAString& aFirstPartyHost,
                                      const nsAString& aChannel,
                                      bool aPrivateBrowsing)
 {
@@ -151,7 +155,8 @@ BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent,
   MOZ_ASSERT(aParent);
   MOZ_ASSERT(mAgents.Contains(aParent));
 
-  PostMessageData data(aParent, aData, aOrigin, aChannel, aPrivateBrowsing);
+  PostMessageData data(aParent, aData, aOrigin, aFirstPartyHost,
+                       aChannel, aPrivateBrowsing);
   mAgents.EnumerateEntries(PostMessageEnumerator, &data);
 }
 
diff --git a/dom/broadcastchannel/BroadcastChannelService.h b/dom/broadcastchannel/BroadcastChannelService.h
index 3864e78..30345c5 100644
--- a/dom/broadcastchannel/BroadcastChannelService.h
+++ b/dom/broadcastchannel/BroadcastChannelService.h
@@ -32,6 +32,7 @@ public:
   void PostMessage(BroadcastChannelParent* aParent,
                    const ClonedMessageData& aData,
                    const nsAString& aOrigin,
+                   const nsAString& aFirstPartyHost,
                    const nsAString& aChannel,
                    bool aPrivateBrowsing);
 
diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp
index c29f9b7..4c6e7e5 100644
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -214,6 +214,7 @@ BackgroundChildImpl::DeallocPVsyncChild(PVsyncChild* aActor)
 dom::PBroadcastChannelChild*
 BackgroundChildImpl::AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo,
                                                  const nsString& aOrigin,
+                                                 const nsString& aFirstPartyHost,
                                                  const nsString& aChannel,
                                                  const bool& aPrivateBrowsing)
 {
diff --git a/ipc/glue/BackgroundChildImpl.h b/ipc/glue/BackgroundChildImpl.h
index 267fb3c..27f78ba 100644
--- a/ipc/glue/BackgroundChildImpl.h
+++ b/ipc/glue/BackgroundChildImpl.h
@@ -80,6 +80,7 @@ protected:
   virtual PBroadcastChannelChild*
   AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo,
                               const nsString& aOrigin,
+                              const nsString& aFirstPartyHost,
                               const nsString& aChannel,
                               const bool& aPrivateBrowsing) override;
 
diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp
index 54a0afe..3bf16f0 100644
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -250,13 +250,15 @@ mozilla::dom::PBroadcastChannelParent*
 BackgroundParentImpl::AllocPBroadcastChannelParent(
                                             const PrincipalInfo& aPrincipalInfo,
                                             const nsString& aOrigin,
+                                            const nsString& aFirstPartyHost,
                                             const nsString& aChannel,
                                             const bool& aPrivateBrowsing)
 {
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
 
-  return new BroadcastChannelParent(aOrigin, aChannel, aPrivateBrowsing);
+  return new BroadcastChannelParent(aOrigin, aFirstPartyHost,
+                                    aChannel, aPrivateBrowsing);
 }
 
 namespace {
@@ -324,6 +326,7 @@ BackgroundParentImpl::RecvPBroadcastChannelConstructor(
                                             PBroadcastChannelParent* actor,
                                             const PrincipalInfo& aPrincipalInfo,
                                             const nsString& aOrigin,
+                                            const nsString& aFirstPartyHost,
                                             const nsString& aChannel,
                                             const bool& aPrivateBrowsing)
 {
diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h
index 1b58cf0..aeccd53 100644
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -73,6 +73,7 @@ protected:
   virtual PBroadcastChannelParent*
   AllocPBroadcastChannelParent(const PrincipalInfo& aPrincipalInfo,
                                const nsString& aOrigin,
+                               const nsString& aFirstPartyHost,
                                const nsString& aChannel,
                                const bool& aPrivateBrowsing) override;
 
@@ -80,6 +81,7 @@ protected:
   RecvPBroadcastChannelConstructor(PBroadcastChannelParent* actor,
                                    const PrincipalInfo& aPrincipalInfo,
                                    const nsString& origin,
+                                   const nsString& firstPartyHost,
                                    const nsString& channel,
                                    const bool& aPrivateBrowsing) override;
 
diff --git a/ipc/glue/PBackground.ipdl b/ipc/glue/PBackground.ipdl
index 6533290..dd5fdea 100644
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -34,7 +34,8 @@ parent:
 
   PVsync();
 
-  PBroadcastChannel(PrincipalInfo pInfo, nsString origin, nsString channel,
+  PBroadcastChannel(PrincipalInfo pInfo, nsString origin,
+                    nsString firstPartyHost, nsString channel,
                     bool privateBrowsing);
 
   RegisterServiceWorker(ServiceWorkerRegistrationData data);



More information about the tor-commits mailing list