From 1910dad0496fe3556dac4b2a0e34d6651b7ddea2 Mon Sep 17 00:00:00 2001 From: uazo <29201891+uazo@users.noreply.github.com> Date: Tue, 27 Sep 2022 23:38:13 +0200 Subject: [PATCH] Partition blobs by top frame url (#2338) Co-authored-by: Carmelo Messina --- .../Partition-blobs-by-top-frame-url.patch | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 build/patches/Partition-blobs-by-top-frame-url.patch diff --git a/build/patches/Partition-blobs-by-top-frame-url.patch b/build/patches/Partition-blobs-by-top-frame-url.patch new file mode 100644 index 00000000..3c809a6d --- /dev/null +++ b/build/patches/Partition-blobs-by-top-frame-url.patch @@ -0,0 +1,214 @@ +From: uazo +Date: Tue, 20 Sep 2022 07:20:01 +0000 +Subject: Partition blobs by top frame url + +Verifies that the blob was created with the same top frame url +or, if not defined, by the same agent cluster. +--- + storage/browser/blob/blob_url_store_impl.cc | 37 ++++++++++++++++++- + storage/browser/blob/blob_url_store_impl.h | 14 ++++++- + .../public/mojom/blob/blob_url_store.mojom | 12 ++++-- + .../core/fileapi/public_url_manager.cc | 17 +++++++++ + 4 files changed, 75 insertions(+), 5 deletions(-) + +diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/blob_url_store_impl.cc +--- a/storage/browser/blob/blob_url_store_impl.cc ++++ b/storage/browser/blob/blob_url_store_impl.cc +@@ -72,6 +72,20 @@ BlobURLStoreImpl::~BlobURLStoreImpl() { + } + } + ++bool BlobURLStoreImpl::IsSamePartition( ++ const GURL& blob_url, ++ const base::UnguessableToken& unsafe_agent_cluster_id, ++ const absl::optional& unsafe_top_level_site) { ++ const absl::optional& top_level_site = ++ registry_->GetUnsafeTopLevelSite(blob_url); ++ if (top_level_site.has_value()) ++ return top_level_site == unsafe_top_level_site; ++ ++ absl::optional agent_cluster_id = ++ registry_->GetUnsafeAgentClusterID(blob_url); ++ return agent_cluster_id == unsafe_agent_cluster_id; ++} ++ + void BlobURLStoreImpl::Register( + mojo::PendingRemote blob, + const GURL& url, +@@ -102,11 +116,18 @@ void BlobURLStoreImpl::Revoke(const GURL& url) { + urls_.erase(url); + } + +-void BlobURLStoreImpl::Resolve(const GURL& url, ResolveCallback callback) { ++void BlobURLStoreImpl::Resolve(const GURL& url, ++ const base::UnguessableToken& unsafe_agent_cluster_id, ++ const absl::optional& unsafe_top_level_site, ++ ResolveCallback callback) { + if (!registry_) { + std::move(callback).Run(mojo::NullRemote(), absl::nullopt); + return; + } ++ if (!IsSamePartition(url, unsafe_agent_cluster_id, unsafe_top_level_site)) { ++ std::move(callback).Run(mojo::NullRemote(), absl::nullopt); ++ return; ++ } + mojo::PendingRemote blob = registry_->GetBlobFromUrl(url); + std::move(callback).Run(std::move(blob), + registry_->GetUnsafeAgentClusterID(url)); +@@ -115,6 +136,8 @@ void BlobURLStoreImpl::Resolve(const GURL& url, ResolveCallback callback) { + void BlobURLStoreImpl::ResolveAsURLLoaderFactory( + const GURL& url, + mojo::PendingReceiver receiver, ++ const base::UnguessableToken& unsafe_agent_cluster_id, ++ const absl::optional& unsafe_top_level_site, + ResolveAsURLLoaderFactoryCallback callback) { + if (!registry_) { + BlobURLLoaderFactory::Create(mojo::NullRemote(), url, std::move(receiver)); +@@ -122,6 +145,12 @@ void BlobURLStoreImpl::ResolveAsURLLoaderFactory( + return; + } + ++ if (!IsSamePartition(url, unsafe_agent_cluster_id, unsafe_top_level_site)) { ++ BlobURLLoaderFactory::Create(mojo::NullRemote(), url, std::move(receiver)); ++ std::move(callback).Run(absl::nullopt, absl::nullopt); ++ return; ++ } ++ + BlobURLLoaderFactory::Create(registry_->GetBlobFromUrl(url), url, + std::move(receiver)); + std::move(callback).Run(registry_->GetUnsafeAgentClusterID(url), +@@ -131,11 +160,17 @@ void BlobURLStoreImpl::ResolveAsURLLoaderFactory( + void BlobURLStoreImpl::ResolveForNavigation( + const GURL& url, + mojo::PendingReceiver token, ++ const base::UnguessableToken& unsafe_agent_cluster_id, ++ const absl::optional& unsafe_top_level_site, + ResolveForNavigationCallback callback) { + if (!registry_) { + std::move(callback).Run(absl::nullopt); + return; + } ++ if (!IsSamePartition(url, unsafe_agent_cluster_id, unsafe_top_level_site)) { ++ std::move(callback).Run(absl::nullopt); ++ return; ++ } + mojo::PendingRemote blob = registry_->GetBlobFromUrl(url); + if (!blob) { + std::move(callback).Run(absl::nullopt); +diff --git a/storage/browser/blob/blob_url_store_impl.h b/storage/browser/blob/blob_url_store_impl.h +--- a/storage/browser/blob/blob_url_store_impl.h ++++ b/storage/browser/blob/blob_url_store_impl.h +@@ -39,14 +39,21 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl + const absl::optional& unsafe_top_level_site, + RegisterCallback callback) override; + void Revoke(const GURL& url) override; +- void Resolve(const GURL& url, ResolveCallback callback) override; ++ void Resolve(const GURL& url, ++ const base::UnguessableToken& unsafe_agent_cluster_id, ++ const absl::optional& unsafe_top_level_site, ++ ResolveCallback callback) override; + void ResolveAsURLLoaderFactory( + const GURL& url, + mojo::PendingReceiver receiver, ++ const base::UnguessableToken& unsafe_agent_cluster_id, ++ const absl::optional& unsafe_top_level_site, + ResolveAsURLLoaderFactoryCallback callback) override; + void ResolveForNavigation( + const GURL& url, + mojo::PendingReceiver token, ++ const base::UnguessableToken& unsafe_agent_cluster_id, ++ const absl::optional& unsafe_top_level_site, + ResolveForNavigationCallback callback) override; + + private: +@@ -54,6 +61,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl + // Returns false and reports a bad mojo message if not. + bool BlobUrlIsValid(const GURL& url, const char* method) const; + ++ bool IsSamePartition( ++ const GURL& blob_url, ++ const base::UnguessableToken& unsafe_agent_cluster_id, ++ const absl::optional& unsafe_top_level_site); ++ + const url::Origin origin_; + base::WeakPtr registry_; + +diff --git a/third_party/blink/public/mojom/blob/blob_url_store.mojom b/third_party/blink/public/mojom/blob/blob_url_store.mojom +--- a/third_party/blink/public/mojom/blob/blob_url_store.mojom ++++ b/third_party/blink/public/mojom/blob/blob_url_store.mojom +@@ -28,7 +28,9 @@ interface BlobURLStore { + Revoke(url.mojom.Url url); + + // Resolves a public Blob URL. +- Resolve(url.mojom.Url url) => ( ++ Resolve(url.mojom.Url url, ++ mojo_base.mojom.UnguessableToken unsafe_agent_cluster_id, ++ network.mojom.SchemefulSite? unsafe_top_level_site) => ( + pending_remote? blob, + // TODO(https://crbug.com/1224926): Remove this once experiment is over. + mojo_base.mojom.UnguessableToken? unsafe_agent_cluster_id); +@@ -42,7 +44,9 @@ interface BlobURLStore { + // both the blob URL and all other references to the blob have been dropped. + ResolveAsURLLoaderFactory( + url.mojom.Url url, +- pending_receiver factory) => ( ++ pending_receiver factory, ++ mojo_base.mojom.UnguessableToken unsafe_agent_cluster_id, ++ network.mojom.SchemefulSite? unsafe_top_level_site) => ( + // TODO(https://crbug.com/1224926): Remove these once experiment is over. + mojo_base.mojom.UnguessableToken? unsafe_agent_cluster_id, + network.mojom.SchemefulSite? unsafe_top_level_site); +@@ -52,7 +56,9 @@ interface BlobURLStore { + // refer to, even after the URL is revoked. + // As long as the token is alive, the resolved blob will also be kept alive. + ResolveForNavigation(url.mojom.Url url, +- pending_receiver token) => ( ++ pending_receiver token, ++ mojo_base.mojom.UnguessableToken unsafe_agent_cluster_id, ++ network.mojom.SchemefulSite? unsafe_top_level_site) => ( + // TODO(https://crbug.com/1224926): Remove this once experiment is over. + mojo_base.mojom.UnguessableToken? unsafe_agent_cluster_id); + }; +diff --git a/third_party/blink/renderer/core/fileapi/public_url_manager.cc b/third_party/blink/renderer/core/fileapi/public_url_manager.cc +--- a/third_party/blink/renderer/core/fileapi/public_url_manager.cc ++++ b/third_party/blink/renderer/core/fileapi/public_url_manager.cc +@@ -56,6 +56,21 @@ static void RemoveFromNullOriginMapIfNecessary(const KURL& blob_url) { + BlobURLNullOriginMap::GetInstance()->Remove(blob_url); + } + ++static absl::optional GetInsecureTopLevelSite( ++ ExecutionContext* execution_context) { ++ absl::optional top_level_site; ++ if (execution_context->IsWindow()) { ++ auto* window = To(execution_context); ++ if (window->top() && window->top()->GetFrame()) { ++ top_level_site = BlinkSchemefulSite(window->top() ++ ->GetFrame() ++ ->GetSecurityContext() ++ ->GetSecurityOrigin()); ++ } ++ } ++ return top_level_site; ++} ++ + } // namespace + + PublicURLManager::PublicURLManager(ExecutionContext* context) +@@ -176,6 +191,7 @@ void PublicURLManager::Resolve( + + url_store_->ResolveAsURLLoaderFactory( + url, std::move(factory_receiver), ++ GetExecutionContext()->GetAgentClusterID(), GetInsecureTopLevelSite(GetExecutionContext()), + WTF::Bind( + [](ExecutionContext* execution_context, + const absl::optional& +@@ -249,6 +265,7 @@ void PublicURLManager::Resolve( + + url_store_->ResolveForNavigation( + url, std::move(token_receiver), ++ GetExecutionContext()->GetAgentClusterID(), GetInsecureTopLevelSite(GetExecutionContext()), + WTF::Bind( + [](ExecutionContext* execution_context, + const absl::optional& +-- +2.25.1