From: uazo Date: Wed, 13 Jul 2022 14:51:09 +0000 Subject: Partition Blink memory cache Blink's in-memory cache is not partitioned (see also: http://crbug.com/1127971) This patch partitions it by the top-level site. This mitigation is effective in case the rendering process is re-used, because on such case the cache would be re-used as well and transfer information between different contexts. See also: * https://github.com/bromite/bromite/pull/2173 Original License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- .../core/html/parser/html_srcset_parser.cc | 2 +- .../core/inspector/inspector_network_agent.cc | 2 +- .../core/inspector/inspector_page_agent.cc | 4 +-- .../renderer/core/loader/image_loader.cc | 3 ++- .../platform/loader/fetch/memory_cache.cc | 8 ++---- .../platform/loader/fetch/memory_cache.h | 5 ++-- .../platform/loader/fetch/resource_fetcher.cc | 27 ++++++++++++++----- .../platform/loader/fetch/resource_fetcher.h | 5 +++- 8 files changed, 35 insertions(+), 21 deletions(-) diff --git a/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc b/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc --- a/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc +++ b/third_party/blink/renderer/core/html/parser/html_srcset_parser.cc @@ -418,7 +418,7 @@ static unsigned AvoidDownloadIfHigherDensityResourceIsInCache( KURL url = document->CompleteURL( StripLeadingAndTrailingHTMLSpaces(image_candidates[i]->Url())); auto* resource = MemoryCache::Get()->ResourceForURL( - url, document->Fetcher()->GetCacheIdentifier(url)); + url, document->Fetcher()->GetCacheIdentifier(url, document->TopFrameOrigin())); if ((resource && resource->IsLoaded()) || url.ProtocolIsData()) { return i; } diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc --- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc @@ -2436,7 +2436,7 @@ bool InspectorNetworkAgent::FetchResourceContent(Document* document, Resource* cached_resource = document->Fetcher()->CachedResource(url); if (!cached_resource) { cached_resource = MemoryCache::Get()->ResourceForURL( - url, document->Fetcher()->GetCacheIdentifier(url)); + url, document->Fetcher()->GetCacheIdentifier(url, document->TopFrameOrigin())); } if (cached_resource && InspectorPageAgent::CachedResourceContent( cached_resource, content, base64_encoded)) { diff --git a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc --- a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc @@ -176,9 +176,9 @@ Resource* CachedResource(LocalFrame* frame, if (!document) return nullptr; Resource* cached_resource = document->Fetcher()->CachedResource(url); - if (!cached_resource) { + if (!cached_resource && document->TopFrameOrigin()) { cached_resource = MemoryCache::Get()->ResourceForURL( - url, document->Fetcher()->GetCacheIdentifier(url)); + url, document->Fetcher()->GetCacheIdentifier(url, document->TopFrameOrigin())); } if (!cached_resource) cached_resource = loader->ResourceForURL(url); diff --git a/third_party/blink/renderer/core/loader/image_loader.cc b/third_party/blink/renderer/core/loader/image_loader.cc --- a/third_party/blink/renderer/core/loader/image_loader.cc +++ b/third_party/blink/renderer/core/loader/image_loader.cc @@ -709,7 +709,8 @@ bool ImageLoader::ShouldLoadImmediately(const KURL& url) const { // content when style recalc is over and DOM mutation is allowed again. if (!url.IsNull()) { Resource* resource = MemoryCache::Get()->ResourceForURL( - url, element_->GetDocument().Fetcher()->GetCacheIdentifier(url)); + url, element_->GetDocument().Fetcher()->GetCacheIdentifier(url, + element_->GetDocument().TopFrameOrigin())); if (resource && !resource->ErrorOccurred() && CanReuseFromListOfAvailableImages( diff --git a/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc b/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc --- a/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc +++ b/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc @@ -197,7 +197,7 @@ void MemoryCache::RemoveInternal(ResourceMap* resource_map, } bool MemoryCache::Contains(const Resource* resource) const { - if (!resource || resource->Url().IsEmpty()) + if (!resource || resource->Url().IsEmpty() || resource->CacheIdentifier().empty()) return false; const auto resource_maps_it = @@ -213,13 +213,9 @@ bool MemoryCache::Contains(const Resource* resource) const { return resource == resources_it->value->GetResource(); } -Resource* MemoryCache::ResourceForURLForTesting( - const KURL& resource_url) const { - return ResourceForURL(resource_url, DefaultCacheIdentifier()); -} - Resource* MemoryCache::ResourceForURL(const KURL& resource_url, const String& cache_identifier) const { + if (cache_identifier.empty()) return nullptr; DCHECK(WTF::IsMainThread()); if (!resource_url.IsValid() || resource_url.IsNull()) return nullptr; diff --git a/third_party/blink/renderer/platform/loader/fetch/memory_cache.h b/third_party/blink/renderer/platform/loader/fetch/memory_cache.h --- a/third_party/blink/renderer/platform/loader/fetch/memory_cache.h +++ b/third_party/blink/renderer/platform/loader/fetch/memory_cache.h @@ -122,10 +122,7 @@ class PLATFORM_EXPORT MemoryCache final : public GarbageCollected, // Do not use this method outside test purposes. // A resourfe URL is not enough to do a correct MemoryCache lookup, and // relying on the method would likely yield wrong results. - Resource* ResourceForURLForTesting(const KURL&) const; - Resource* ResourceForURL(const KURL&, const String& cache_identifier) const; - HeapVector> ResourcesForURL(const KURL&) const; void Add(Resource*); void Remove(Resource*); @@ -168,6 +165,8 @@ class PLATFORM_EXPORT MemoryCache final : public GarbageCollected, base::MemoryPressureListener::MemoryPressureLevel) override; private: + HeapVector> ResourcesForURL(const KURL&) const; + // A URL-based map of all resources that are in the cache (including the // freshest version of objects that are currently being referenced by a Web // page). removeFragmentIdentifierIfNeeded() should be called for the url diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc @@ -992,7 +992,7 @@ Resource* ResourceFetcher::CreateResourceForStaticData( if (!archive_ && factory.GetType() == ResourceType::kRaw) return nullptr; - const String cache_identifier = GetCacheIdentifier(url); + const String cache_identifier = GetCacheIdentifier(url, params.GetResourceRequest()); // Most off-main-thread resource fetches use Resource::kRaw and don't reach // this point, but off-main-thread module fetches might. if (IsMainThread()) { @@ -1408,7 +1408,8 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params, MakePreloadedResourceBlockOnloadIfNeeded(resource, params); } else if (IsMainThread()) { resource = MemoryCache::Get()->ResourceForURL( - params.Url(), GetCacheIdentifier(params.Url())); + params.Url(), + GetCacheIdentifier(params.Url(), params.GetResourceRequest())); if (resource) { policy = DetermineRevalidationPolicy(resource_type, params, *resource, is_static_data); @@ -1719,7 +1720,8 @@ Resource* ResourceFetcher::CreateResourceForLoading( const FetchParameters& params, const ResourceFactory& factory) { const String cache_identifier = - GetCacheIdentifier(params.GetResourceRequest().Url()); + GetCacheIdentifier(params.GetResourceRequest().Url(), + params.GetResourceRequest()); DCHECK(!IsMainThread() || params.IsStaleRevalidation() || !MemoryCache::Get()->ResourceForURL(params.GetResourceRequest().Url(), cache_identifier)); @@ -2788,10 +2790,23 @@ void ResourceFetcher::UpdateAllImageResourcePriorities() { to_be_removed.clear(); } -String ResourceFetcher::GetCacheIdentifier(const KURL& url) const { +String ResourceFetcher::GetCacheIdentifier(const KURL& url, + const ResourceRequest& resource_request) const { + if (const scoped_refptr top_origin = resource_request.TopFrameOrigin()) { + return ResourceFetcher::GetCacheIdentifier(url, top_origin); + } else if (const scoped_refptr requestor_origin = resource_request.RequestorOrigin()) { + return ResourceFetcher::GetCacheIdentifier(url, requestor_origin); + } + NOTREACHED(); +} + +String ResourceFetcher::GetCacheIdentifier(const KURL& url, + scoped_refptr origin) const { + String origin_url = origin ? origin->ToRawString() : ""; + if (properties_->GetControllerServiceWorkerMode() != mojom::ControllerServiceWorkerMode::kNoController) { - return String::Number(properties_->ServiceWorkerId()); + return origin_url + " " + String::Number(properties_->ServiceWorkerId()); } // Requests that can be satisfied via `archive_` (i.e. MHTML) or @@ -2804,7 +2819,7 @@ String ResourceFetcher::GetCacheIdentifier(const KURL& url) const { if (bundle) return bundle->GetCacheIdentifier(); - return MemoryCache::DefaultCacheIdentifier(); + return origin_url; } std::optional diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h @@ -278,7 +278,10 @@ class PLATFORM_EXPORT ResourceFetcher uint32_t inflight_keepalive_bytes); blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() const; - String GetCacheIdentifier(const KURL& url) const; + String GetCacheIdentifier(const KURL& url, + const ResourceRequest& resource_request) const; + String GetCacheIdentifier(const KURL& url, + scoped_refptr origin) const; // If `url` exists as a resource in a subresource bundle in this frame, // returns its UnguessableToken; otherwise, returns std::nullopt. --